LINUX.ORG.RU
ФорумTalks

Экспорт CSV-файла в LDIF-файл для последующего импорта в ClawsMail

 , , , ,


1

1

В продолжение темы о Thunderbirdтемы об OperaMail)

Да, можно было написать на чём угодно другом, но

  • уже даже есть скрипт на perl на сайте clawsmail, но таскать perl везде не хочется - как он работает не проверял;
  • да, нужно, чтобы был установлен OpenOffice или LibreOffice (+ jre, jdk или openjdk), но предположу, что у пользователя ClawsMail что-нибудь из этого установлено;
  • всё равно csv предварительно удобнее править в табличном процессоре, а писать громоздкое GUI-приложение для такой мелкой задачи слишком долго (для меня);
  • мне нужно было, чтобы импортированные в clawsmail записи Ф.И.О. выглядели определённым образом;
  • раз уж установлен OpenOffice или LibreOffice (+ jre, jdk или openjdk), то макрос легко подправить под свой формат и порядок следования полей.

поэтому написано в OpenOffice BASIC.

Макрос экспортирует csv-файл (первая строка - названия полей):

Имя,Фамилия,"Отображаемое имя","Электронная почта",Телефон,Адрес,Должность,Отдел
"Иван Иванович",Иванов,"Иванов Иван Иванович",ivanov@ivan.iv,"223-322, 322-223","корпус 1, этаж 2, к. 3","Начальник отдела","Отдел 001"
"Пётр Петрович",Петров,"Петров Пётр Петрович",petrov@petr.pe,"322-223, 223-322","корпус 3, этаж 2, к. 1","Заместитель начальника отдела","Отдел 002"
в выходной файл формата LDIF:
cn: Иванов Иван Иванович
sn:  Иванович
givenName: Иванов Иван
displayName: Иванов Иван Иванович
mail: ivanov@ivan.iv
адрес: корпус 1, этаж 2, к. 3
телефон: 223-322, 322-223
отдел: Отдел 001
должность: Начальник отдела

cn: Петров Пётр Петрович
sn:  Петрович
givenName: Петров Пётр
displayName: Петров Пётр Петрович
mail: petrov@petr.pe
адрес: корпус 3, этаж 2, к. 1
телефон: 322-223, 223-322
отдел: Отдел 002
должность: Заместитель начальника отдела

Имя выходного файла выбирается пользователем в появляющемся при запуске макроса диалога «Save As». Названия полей LDIF должны начинаться со строчной буквы. Сохраняются только названия полей, которых достаточно для последующего импорта адресной книги в ClawsMail.

Сам макрос нужно запускать после открытия csv-файла в OpenOffice:

REM Экспорт Адрессной книги из открытого .CSV файла в файл в формате LDIF для последующего испорта в Адресную книгу ClawsMail
REM Export AddressBook from opened .CSV to LDIF formated file for import to ClawsMail AddressBook
Sub ClawsMail_LDIF_export

  oDoc=ThisComponent
  oSheet = oDoc.CurrentController.getActiveSheet()
  oCellCursor = oSheet.createCursor()
  oCellCursor.GotoEndOfUsedArea(True) ' Select Used Cells Range 
  End_Row = oCellCursor.getRangeAddress.EndRow
  End_Col = oCellCursor.getRangeAddress.EndColumn

  Dim AddrItem(End_Row - 1, End_Col) as String
  Dim AddrItemNew(End_Row - 1, End_Col + 1) as String
  
  REM Чтение AddrItem (Address Item) в формате:
  REM Имя,Фамилия,"Отображаемое имя","Электронная почта",Телефон,Адрес,Должность,Отдел
  REM Name (or "Name" + "Patronymic"),Surname,"Display Name","e-mail address",phone,address,position,department
  For i = 0 To End_Row - 1   ' AddrItem Row number
    For j = 0 To End_Col
      AddrItem(i, j) = oSheet.getCellByPosition(j, i + 1).Formula
    Next j	
  Next i
  
  For i = 0 To End_Row - 1
    SpacePos = InStr(AddrItem(i, 0), " ")
    If SpacePos > 0 Then
      AddrItemNew(i, 1) = " " + Mid(AddrItem(i, 0), SpacePos+1, Len(AddrItem(i, 0))-SpacePos+1)
    Else
      AddrItemNew(i, 1) = ""
    End If
    AddrItemNew(i, 2) = AddrItem(i, 1) + " " + Mid(AddrItem(i, 0), 1, InStr(AddrItem(i, 0), " ")-1)
    AddrItemNew(i, 0) = AddrItemNew(i, 2) + AddrItemNew(i, 1)
    AddrItemNew(i, 3) = AddrItem(i, 2)
    AddrItemNew(i, 4) = AddrItem(i, 3)
    AddrItemNew(i, 5) = AddrItem(i, 5)
    AddrItemNew(i, 6) = AddrItem(i, 4)
    AddrItemNew(i, 7) = AddrItem(i, 7)
    AddrItemNew(i, 8) = AddrItem(i, 6)
  Next i
  Dim LDIF_field_name(9) As String ' Поля адресной книги в формате LDIF
  LDIF_field_name = Array("cn: ", "sn: ", "givenName: ", "displayName: ", "mail: ", "адрес: ", _
                          "телефон: ", "отдел: ", "должность: ")
  REM LDIF_field_name = Array("cn: ", "sn: ", "givenName: ", "displayName: ", "mail: ", "address: ", _
  REM                        "phone: ", "department: ", "position: ")


  ' Open file to write
  sFileName = ""
  sFilename = FilePickSave
  
  If sFilename <> "" Then
  
    ' Opening file to write in UTF-8 as LDIF must use UTF-8 codepage
    encoding = "UTF-8"  ' set codepage
    ' names of codepage are described here:
    ' http://www.iana.org/assignments/character-sets/character-sets.xhtml
    
    fileaccess = createUnoService ("com.sun.star.ucb.SimpleFileAccess")
    
    REM удаление выходного файла если он существует
    REM if output file exists then delete it
    If fileaccess.exists(sFileName) Then
      fileaccess.kill(sFileName) 
    End If
    
    intextstream = createUnoService ("com.sun.star.io.TextOutputStream")
    intextstream.setEncoding( encoding )
    intext = fileaccess.openFileWrite( sFileName )
    intextstream.setOutputStream( intext )  
  
    For i = 0 to End_Row - 1
      For j = 0 To End_Col+1
        If AddrItemNew(i, j) <> "" Then
          intextstream.writeString( LDIF_field_name(j) &  AddrItemNew(i, j) & CHR$(13) & CHR$(10))
        End If
      Next j
      ' write empty string
      intextstream.writeString(CHR$(13) & CHR$(10))
    Next i
  
    ' closing file
    intextstream.closeOutput()
  End If ' sFilename <> ""
  
End Sub ' ClawsMail_LDIF_export 

REM *** Функция выбора файла для сохранения | Function: File to Save As
REM *** Взята здесь | From : https://forum.openoffice.org/en/forum/viewtopic.php?f=45&t=26774
' ******* FilePicker Save File ******************************************
Function FilePickSave As String
Dim FilePicker As Object
Dim FPtype(0) As Integer

FilePicker = CreateUnoService("com.sun.star.ui.dialogs.FilePicker")
FPtype(0)=com.sun.star.ui.dialogs.TemplateDescription.FILESAVE_SIMPLE
FilePicker.initialize(FPtype())

If FilePicker.execute() Then
   FilePickSave = ConvertToURL(FilePicker.Files(0))
EndIf

End Function
' ******* End FilePicker Save File ******************************************
★★★★★
Ответ на: комментарий от MKuznetsov

однострочники мне тяжело читать и править

grem ★★★★★
() автор топика

Вы только что прослушали лекцию о плачевном состоянии PIM в ОС линукс.

aidaho ★★★★★
()

таскать perl везде не хочется
нужно, чтобы был установлен OpenOffice или LibreOffice (+ jre, jdk или openjdk)

Сильно...

WindowsXP ★★
()

уже даже есть скрипт на perl на сайте clawsmail, но таскать perl везде не хочется - как он работает не проверял;

А что, есть уже GNU/Linux, на котором нет perl'а? О_О

Sectoid ★★★★★
()

Ну это как микроскопом гвозди забивать. Вроде и можно, но зачем? Можно на любом питоне, руби, перле или баше написать такое.

Hater ★★
()
Ответ на: комментарий от Hater

Можно, но clawsmail я, внезапно, использую не только в онтопике, как и openoffice/libreoffice. Python/perl/ruby в системе тоже далеко не всегда нужны на всех используемых платформах. Плюс кто-то может не использовать python2 или 3. Всего лишь одна из кроссплатформенных (надо бы дома проверить) реализаций для тех, у кого есть упомянутые офисные пакеты, которые по этой причине упомянуты в тэгах (а не что-то другое).

grem ★★★★★
() автор топика
Последнее исправление: grem (всего исправлений: 1)
Ответ на: комментарий от Hater

и самое главное! у данного кода есть огромное преимущество: он делает то, что мне нужно мгновенно по сравнению с ненаписанным кодом на других языках, который «исполняется» бесконечно долго ^_^

grem ★★★★★
() автор топика
Последнее исправление: grem (всего исправлений: 1)
Ответ на: комментарий от MKuznetsov

> однострочник awk

Интересно было бы на него посмотреть, в целях общего развития. Особенно интересуют обработки исключений для отдельных записей: случай отсутствия отчества (поле «sn: » должно отсутствовать в выходном файле); пропуск пустых полей (чтобы и в выходном файле отсутствовали, например, хранится телефон, но и-мейл отсутствует); перечисление данных внутри поля через запятую (несколько номеров телефона, адрес и т.д.).

grem ★★★★★
() автор топика
Ответ на: комментарий от grem

обработки исключений для отдельных записей

это не исключения. научитесь в конвееры - пустые записи можно удалять следующим шагом.

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

Да, исключения не в смысле «исключения», а в смысле исключения из общего правила.

научитесь в конвееры - пустые записи можно удалять следующим шагом.

Я даже эту короткую «хрень» не в состоянии вспомнить сейчас, не говоря о том, чтобы добавить в предлагаемую «однострочку» дополнительных 5-10 полей, допустим, через 2 недели.

grem ★★★★★
() автор топика

макрос нужно запускать после открытия csv-файла в OpenOffice

Прочитал тему и после этой строки не удержался и воскликнул:«Ужас!» Лет 5 назад конвертировал csv в виндовой кодировке в ldif в юникоде скриптом на bash.

foxy_ant ★★
()
Ответ на: комментарий от foxy_ant

лет 5 назад конвертировал csv

то есть у всех есть готовые решения с использованием awk, ruby, bash, даже perl (скрипт отличный от того, что предлагает clawsmail), но все их прячут? :(

Поделишься? Я его шапку темы помещу.

grem ★★★★★
() автор топика
Последнее исправление: grem (всего исправлений: 1)
Ответ на: комментарий от grem

по-быстрому, для примера:

awk -F "," '{gsub("\"",""); print "nc "$3"\n" "displayName "$3"\n" "mail "$4"\n"}' file.csv
foxy_ant ★★
()
Ответ на: комментарий от grem

решение «в лоб»:

awk -F "," '{gsub("\"",""); print "nc: "$3; split($3, fld, " "); print "sn: "fld[3]"\n" "givenName: "fld[1] " " fld[2]"\n" "displayName: "$3"\n" "mail: "$4"\n" "адрес: "$7","$8","$9"\n" "телефон: "$5","$6"\n" "отдел: "$11"\n" "должность: "$10"\n"}' file.csv

в шапку темы этот код помещать не нужно.

foxy_ant ★★
()
Ответ на: комментарий от foxy_ant

Нужно будет попробовать дописать макрос, чтобы работал не только для произвольного числа перечислений с запятой в поле как сейчас, но и для произвольного числа полей (с переводом их названий в нижний регистр), которые экспортируются из thunderbird.

Не подскажешь как с помощью sed удалить строку (что-то вроде sed /строка:/d), но по строгому соответствию, а не в случае если «строка:» просто содержится в обрабатываемой?

«sed /строка[:$]/d» - есть подозрение, что так, но не успел провкрить.

grem ★★★★★
() автор топика
Ответ на: комментарий от grem

«sed /строка[:$]/d» - есть подозрение

похоже, что так: sed /'строка[:]$'/d

grem ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.