Конвертер для переноса контактов из Outlook в Android, для параноиков (с открытым кодом, без использования синхронизации с гуглом и сторонних утилит)

в 5:05, , рубрики: android, csv, outlook, vcf, аутлук, контакты, перенос, метки: , , , , , ,

Вчера обратился один товарищ, столкнувшийся с проблемой переноса контактов из смартфона на WM6 под новый Андроидофон. После недели тщетных попыток он опустил руки и передал csv-файл, полученный из аутлука, к которому ему довольно просто удалось подключить записную книжку телефона.

Он перепробовал множество конвертеров и способов, но все они либо не давали нужного результата — быстрого и бесплатного конвертирования в два клика, либо искажали информацию из-за кучерявой реализации локализации его версии Аутлука. Использовать привязку контактов к аккаунту он отказался по религиозно-политическим соображениям, велению внутренней морали или уклада жизни, я не уточнял.

В результате слегка погуглив, но не найдя простого решения пришлось налабать скриптик на великом и могучем, который создает vcf-файл контактов, который в свою очередь легко импортируется в Андроид стандартными средствами телефона.

Исходные данные

Собственно то, с чем пришлось столкнуться.

CSV

CSV-файл — обычный текстовый файл в котором каждая строка представляет собой строку таблицы данных, а столбцы внутри строки разделяются символом-разделителем, который может выбираться пользователем и обычно представляет собой знак табуляции, точку с запятой, запятую и т.п. В первой строке зачастую присутствуют не значения данных, а имена полей.

При экспорте из Outlook необходимо выбрать все поля и разрешить помещать названия полей в первой строке (возможно это включено по умолчанию).

В результате получается текстовый файл подобного формата

Обращение; Имя; Отество; Фамилия; Суффикс; Организация; Отдел; Должность; Улицарабадрес; Улица2рабадрес; Улица3рабадрес; Городрабадрес; Областьрабадрес; Индексрабадрес; Странарабадрес; Улицадомадрес; Улица2домадрес; Улица3домадрес; Городдомадрес; Областьдомадрес; Потовыйкоддом; Странадомадрес; Улицадругойадрес; Улица2другойадрес; Улица3другойадрес; Городдругойадрес; Областьдругойадрес; Индексдругойадрес; Странадругойадрес; Телефонпомощника; Рабоийфакс; Рабоийтелефон; Телефонраб2; Обратныйвызов; Телефонвмашине; Основнойтелефонорганизации; Домашнийфакс; Домашнийтелефон; Телефондом2;ISDN; Телефонпереносной; Другойфакс; Другойтелефон; Пейджер; Основнойтелефон; Радиотелефон; Телетайптелефонститрами; Телекс; Важность; Вебстраница; Годовщина; Деньрождения; Дети; Имяпомощника; Инициалы; Категории; Клюевыеслова; Кодорганизации; Линыйкод; Отложено; Пол; Пользователь1; Пользователь2; Пользователь3; Пользователь4; Пометка; Потовыйящикдомадрес; Потовыйящикдругойадрес; Потовыйящикрабадрес; Профессия; Расположение; Расположениекомнаты; Расстояние; Руководитель; СведенияодоступностивИнтернете; Серверкаталогов; Супруга; Сет; Сета; Хобби;_астное; Адресэлпоты; Типэлпоты; Краткоеимяэлпоты; Адрес2элпоты; Тип2элпоты; Краткое2имяэлпоты; Адрес3элпоты; Тип3элпоты; Краткое3имяэлпоты; Язык[CRLF]

; Кредит;;Bee Line Счет;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;067404;;;067404;;;;;;;; Обычная;;;;;; К.B.L.С.; Служебные;;;;; Не определен;;;;; Обычная;;;;;;;;;;;;;;; ЛОЖЬ;;;;;;;;;;[CRLF]

Прочие записи

vCard

Это формат визитной карточки. В Андроидофонах это основной формат обмена контактами. Если вы пытаетесь отправить контакт по почте или SMS то телефон прицепит именно vcf-карточку. Прелесть формата, в том что в одной карточке (файле) можно объединять несколько контактов.

Преобразованная запись из примера выше выглядит так

BEGIN:VCARD
VERSION:3.0
CATEGORIES: Служебные
N:Bee Line Счет; Кредит
TEL;TYPE=cell:067404
TEL;TYPE=home:067404
END:VCARD

Скрипт-конвертер

Скрипт написан на удобном, простом, легковесном, кросс-платформенном, и еще куча разных эпитетов awk. В начале указывается разделитель полей внутри csv (мне попался csv с точкой-с-запятой). Далее задается карта отображения полей csv в поля vCard в виде массива KEYS. В общем-то это все настройки, которые должны работать по умолчанию.

outlook2vcard.awk

BEGIN {
	FS = ";"

	KEYS["Фамилия"] = "N.1";
	KEYS["Имя"] = "N.2"; 	
	KEYS["Отество"] = "N.3"; 	
	KEYS["Обращение"] = "N.4";
	KEYS["Суффикс"] = "N.5";
	
	KEYS["Организация"] = "ORG.1";
	KEYS["Отдел"] = "ORG.2";
	KEYS["Должность"] = "TITLE";
	
	KEYS["Улицарабадрес"] = "ADR;TYPE=work.2";
	KEYS["Улица2рабадрес"] = "ADR;TYPE=work.2";
	KEYS["Улица3рабадрес"] = "ADR;TYPE=work.2";
	KEYS["Городрабадрес"] = "ADR;TYPE=work.3";
	KEYS["Областьрабадрес"] = "ADR;TYPE=work.4";
	KEYS["Индексрабадрес"] = "ADR;TYPE=work.5";
	KEYS["Странарабадрес"] = "ADR;TYPE=work.6";

	KEYS["Потовыйкоддом"] = "ADR;TYPE=home.1";
	KEYS["Улицадомадрес"] = "ADR;TYPE=home.2";
	KEYS["Улица2домадрес"] = "ADR;TYPE=home.2";
	KEYS["Улица3домадрес"] = "ADR;TYPE=home.2";
	KEYS["Городдомадрес"] = "ADR;TYPE=home.3";
	KEYS["Областьдомадрес"] = "ADR;TYPE=home.4";
	KEYS["Индексдомадрес"] = "ADR;TYPE=home.5";
	KEYS["Странадомадрес"] = "ADR;TYPE=home.6";

	KEYS["Улицадругойадрес"] = "ADR;TYPE=postal.2";
	KEYS["Улица2другойадрес"] = "ADR;TYPE=postal.2";
	KEYS["Улица3другойадрес"] = "ADR;TYPE=postal.2";
	KEYS["Городдругойадрес"] = "ADR;TYPE=postal.3";
	KEYS["Областьдругойадрес"] = "ADR;TYPE=postal.4";
	KEYS["Индексдругойадрес"] = "ADR;TYPE=postal.5";
	KEYS["Странадругойадрес"] = "ADR;TYPE=postal.6";
	
	KEYS["Телефонпомощника"] = "TEL;TYPE=pager";
	KEYS["Рабоийфакс"] = "TEL;TYPE=work;TYPE=fax";
	KEYS["Рабоийтелефон"] = "TEL;TYPE=work";
	KEYS["Телефонраб2"] = "TEL;TYPE=work";
	KEYS["Обратныйвызов"] = "TEL;TYPE=X-EVOLUTION-CALLBACK";
	KEYS["Телефонвмашине"] = "TEL;TYPE=car";
	KEYS["Основнойтелефонорганизации"] = "TEL;TYPE=work";
	KEYS["Домашнийфакс"] = "TEL;TYPE=home;TYPE=fax";
	KEYS["Домашнийтелефон"] = "TEL;TYPE=home";
	KEYS["Телефондом2"] = "TEL;TYPE=home";
	KEYS["ISDN"] = "TEL;TYPE=isdn";
	KEYS["Телефонпереносной"] = "TEL;TYPE=cell";
	KEYS["Другойфакс"] = "TEL;TYPE=fax";
	KEYS["Другойтелефон"] = "TEL";
	KEYS["Пейджер"] = "TEL;TYPE=pager";
	KEYS["Основнойтелефон"] = "TEL";
	KEYS["Радиотелефон"] = "TEL;TYPE=pcs";
	KEYS["Телетайптелефонститрами"] = "TEL;TYPE=msg";
	KEYS["Телекс"] = "TEL;TYPE=msg";
	
	KEYS["Важность"] = "";
	KEYS["Вебстраница"] = "URL";
	KEYS["Годовщина"] = "X-ANNIVERSARY";
	KEYS["Деньрождения"] = "BDAY";
	KEYS["Дети"] = "";
	KEYS["Имяпомощника"] = "X-ASSISTANT";
	KEYS["Инициалы"] = "";
	KEYS["Категории"] = "CATEGORIES";
	KEYS["Клюевыеслова"] = "NOTE";
	KEYS["Кодорганизации"] = "";
	KEYS["Линыйкод"] = "";
	KEYS["Отложено"] = "";
	KEYS["Пол"] = "";

	KEYS["Пользователь1"] = "";
	KEYS["Пользователь2"] = "";
	KEYS["Пользователь3"] = "";
	KEYS["Пользователь4"] = "";
	KEYS["Пометка"] = "";
	KEYS["Потовыйящикдомадрес"] = "";
	KEYS["Потовыйящикдругойадрес"] = "";
	KEYS["Потовыйящикрабадрес"] = "";
	KEYS["Профессия"] = "";
	KEYS["Расположение"] = "";
	KEYS["Расположениекомнаты"] = "";
	KEYS["Расстояние"] = "";
	KEYS["Руководитель"] = "";
	KEYS["СведенияодоступностивИнтернете"] = "";
	KEYS["Серверкаталогов"] = "";
	KEYS["Супруга"] = "X-SPOUSE";
	KEYS["Сет"] = "";
	KEYS["Сета"] = "";
	KEYS["Хобби"] = "";
	KEYS["_астное"] = "";
	KEYS["Адресэлпоты"] = "EMAIL;TYPE=internet";
	KEYS["Типэлпоты"] = "";
	KEYS["Краткоеимяэлпоты"] = "";
	KEYS["Адрес2элпоты"] = "EMAIL;TYPE=internet";
	KEYS["Тип2элпоты"] = "";
	KEYS["Краткое2имяэлпоты"] = "";
	KEYS["Адрес3элпоты"] = "EMAIL;TYPE=internet";
	KEYS["Тип3элпоты"] = "";
	KEYS["Краткое3имяэлпоты"] = "";
	KEYS["Язык"] = "";
}

FNR == 1 {
	for (i = 1; i <= NF; i++) {
		k = KEYS[$i];
		if ("" != k) {
			MAPS[i] = k;
		}
	}
}

FNR != 1 {
	delete PROPS;
	for (i = 1; i <= NF; i++) {
		k = MAPS[i];
		if (("" != $i) && ("" != k)) {
			PROPS[k] = $i;
		}
	}
	
	n = asorti(PROPS, SKEYS);
	if (n > 0) {
		l = "";
		print("BEGIN:VCARD");
		printf("VERSION:3.0");
		for (i = 1; i <= n; i++) {
			k = SKEYS[i];
			v = PROPS[k];
			if (2 == split(k, a, ".")) {
				k = a[1];
				x = 0 + a[2];
			}
			else {
				x = 1;
			}
			if (l != k) {
				l = k;
				m = 1;
				printf("rn%s:", l);
			}
			while (m < x) {
				m++;
				printf(";");
			}
			printf("%s", v);
		}
		print("rnEND:VCARD");
	}
}

function die(str) {
	print "Error at " FILENAME ":" FNR " " str
	exit
}

function warn(str) {
	print "Warning at " FILENAME ":" FNR " " str
}

Как запускать

Запускать скрипт из под интерпретатора awk следующим образом:

gawk -f outlook2vcard.awk inputfile.csv >outputfile.vcf

В качестве входных файлов можно указать несколько файлов csv, тогда они будут объединены.

Ложка дегтя

Скрипт автоматически не преобразует кодировку кириллицы в UTF-8, который является родным для Андроида. Этот заключительный аккорд надо сделать вручную либо с помощью iconv для юниксоидов, она же кстати есть и под gnuwin32, либо обычным блокнотом (notepad.exe) для форточек, открыв файл, а затем сохранив с новым именем (Save As...) и выбрав кодировку UTF-8 под именем нового файла.

Импорт в телефон

Способ прост и описан в куче блогов и форумов, но не поленюсь и приведу еще раз. Полученный файл с расширением vcf необходимо положить на карту памяти Андроидофона. Затем войти в контакты, нажать кнопку меню и выбрать «Импорт/Экспорт — Импорт с карты памяти», вуаля.

Автор: ma5ter

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js