Как выдрать картинку из RichText

Тема в разделе "Lotus - Программирование", создана пользователем CodeGuy, 24 авг 2008.

  1. CodeGuy

    CodeGuy Гость

    Здравствуйте!

    Понадобилось сформировать небольшой отчёт по базе Lotus, которая состоит из документов с набором полей, одним из которых является Foto (его тип Item.RICHTEXT). Если выделить мышкой и нажать "Копировать" (Ctrl + C), то картинка отлично копируется и вставляется в Word, например. Так как документов много, а руками делать операцию сотни раз не хочется, то было принято решение набросать небольшую программу на Java, которая это сделает.

    После нескольких мучений у меня получилось создать локальное приложение на Java (с помощью Notes.jar), которое соединяется с удалённым сервером, открывает нужную базу, осуществляет выборку документов и данных из них. Единственная проблема - в картинке, собственно, из-за неё всё и затевалось.
    Итак, есть Item, тип которого Item.RICHTEXT, количество {doc links, file attachments, OLE objects, sections, tables, table cells, text paragraphs, text runs} равно нулю. Item.GetValueLength() возвращает 39708, а родной клиент Lotus пишет следующее:
    Имя поля: Foto
    Тип данных: Форматируемый текст
    Размер данных: 39706 байт
    Порядковый номер: 1
    Код дубликата: 0
    Флаги поля:

    Помогите с советом, как выдрать картинку? Какой использовать метод? Как она там хранится?


    P.S. Сейчас умею использовать классы из Notes.jar с обычным javac, есть клиентский доступ к серверу и базе Lotus, дизайнера нет и запускать код в клиенте Lotus не могу.
     
  2. allex

    allex Гость

    Если я правильно понял суть твоей задачи, тебе нужно из RT поля взять картинку и поместить в Word - документ.

    Этот код делает как раз то что нужно
    <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">Разворачивающийся текст</div></div><div class="sp-body"><div class="sp-content">
    Код (LotusScript):
    Sub Click(Source As Button)
    Dim session As New notessession, db As notesdatabase, view As notesview
    Dim rtitem As NotesRichTextItem
    Dim rtitem2 As NotesRichTextItem
    Dim rtitem3 As NotesRichTextItem
    'Dim rtitem2 As NotesItem
    'Dim rtitem3 As NotesItem
    Dim object As NotesEmbeddedObject
    'Dim uidoc As NotesUIDocument

    'Dim ui_doc As String
    Dim n_kk As String
    Dim date_kk As String
    Dim postavleno_na_kontr As String
    Dim n_doc_kk As String
    Dim date_n_doc_kk As String

    Dim nazvanie_doc As String
    Dim soderjanie_poruch As String
    Dim nazvanie_doc_ As String
    Dim soderjanie_poruch_ As String

    Dim plane_date_isp As String
    Dim fakte_date_isp As String
    Dim vid_predost_inf As String
    Dim kurator_kk As String
    Dim phone_kurator_kk As String
    Dim otvet As String
    Dim data As String
    Dim doljnost_fio_telefon As String

    Dim word As Variant
    Dim worddoc As Variant

    Set w = New NotesUiWorkspace
    Set db = session.currentdatabase
    Set uidoc = w.CurrentDocument
    Set docA = uidoc.Document

    '******** присвоение переменным значение полей из "Информация о заявителе"
    n_kk = uidoc.FieldGetText("n_kk")  
    date_kk =
    postavleno_na_kontr =
    n_doc_kk =
    ..............

    '******* получение файла шаблона и сохранение его на диск 
    Set view = db.getview( "BDconf" )
    Set doc=view.GetFirstDocument
    Set rtitem = doc.GetFirstItem( "kk" )
    Forall o In rtitem.EmbeddedObjects
    If ( o.Type = EMBED_ATTACHMENT ) Then  
    Call o.ExtractFile( "c:\" & o.Source )
    FileName$ = o.Source
    End If
    End Forall
    '******* получение файла шаблона и сохранение его на диск

    '******* получение шаблона подписи и сохранение его на диск     
    Set view = db.getview("Pictures")
    Set doc = view.getdocumentbykey("test")

    '********сохранение картинки на диск
    Set rtitem = doc.GetFirstItem( "Body" )
    Forall o In rtitem.EmbeddedObjects
    If ( o.Type = EMBED_ATTACHMENT ) Then
    Call o.ExtractFile( "c:\" & o.Source )
    PictureName$ = o.Source
    End If
    End Forall 

    '******* Создание объекта Word:
    Set word = CreateObject("Word.Application") 'Create Word object
    Call word.documents.add("c:\" & FileName$) 'Create a new document based on the template
    word.visible = True
    Set worddoc = word.activedocument 'Get a handle for the active document


    '****** вставка пидписи
    Set myRange = word.ActiveDocument.Tables(3).Rows(1).cells(1).Range
    myRange.Select
    Call word.selection.InlineShapes.AddPicture ("c:\" & PictureName$, False, True)

    '********* Ответ в табличку
    Set myRange1 = word.ActiveDocument.Tables(2).Rows(1).cells(1).Range
    If worddoc.Bookmarks.Exists("otvet1") = False Then Exit Sub 'если закладки нет выходим
    Call word.Selection.GoTo(-1,,, "otvet1") ' переходим на указаную закладку
    Call Word.Selection.TypeText(otvet)


    '******** записывание в поле worda значения переменной
    worddoc.FormFields("n_kk").result = n_kk
    ....................

    name_file= "c:\" + " Контрольная карточка"+"№"+ n_kk +".rtf"
    worddoc.saveas( name_file ) 'сохранение документа Word на диск

    Call docA.save(True,True)

    End Sub
     
  3. CodeGuy

    CodeGuy Гость

    allex
    Спасибо за пример кода. Проверить смогу только вечером, но сомневаюсь, что заработает, так как у меня в поле Item ВООБЩЕ НЕТ EmbeddedObjects, а здесь они являются ключевыми. :)

    Собственно меня это и смущает, так как Ctrl+C работает, а как он сохранён - не ясно.

    Может быть есть метод, который содержимое RichText поля скопирует в буфер? С таким попробую справиться.
     
  4. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Если через буфер, то можно сделать uidoc.Goto + uidoc.Copy
    Но это только на форграунде и в едит моде.

    Ещё можно выкинуть док в DXL и оттуда декодировать картинку.
     
  5. CodeGuy

    CodeGuy Гость

    "На форграунде" - это мне нужно внедрять в базу Lotus мою программу, так? Если да, то не подходит.

    По поводу DXL ничего пока ничего не знаю, так как о программировании в Lotus узнал только вчера. Есть ли где-нибудь уже готовый пример подобной операции?
     
  6. Kee_Keekkenen

    Kee_Keekkenen Well-Known Member

    Регистрация:
    5 сен 2006
    Сообщения:
    616
    Симпатии:
    4
    поддерживаю, это кстати отлично работает..
     
  7. NetWood

    NetWood Lotus team
    Lotus team

    Регистрация:
    17 апр 2008
    Сообщения:
    308
    Симпатии:
    0
    Ха! Суть проблемы в том что картинка НЕ ЯВЛЯЕТСЯ НИ АТТАЧЕМ НИ ОБЬЕКТОМ. Увы. Были бы аттачи :)
     
  8. CodeGuy

    CodeGuy Гость

    А чем же является картинка??? Или этого никто вообще не знает? Неужели все работают лишь с plain text?
     
  9. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Тебе надо:
    1. Выгрузить документ в DXL (это простой текстовой XML файл)
    2. По тегам найти картинку
    3. Декодировать картинку (в DXL она хранится закодированая в base64)

    Ключевые слова:
    1. NotesDXLExporter
    2. NotesDOMParser, GetElementsByTagName
    3. NotesMIMEEntity или сторонними програмами.

    Если только вчера начал программит в лотус, можешь и не осилить :)
     
  10. Kee_Keekkenen

    Kee_Keekkenen Well-Known Member

    Регистрация:
    5 сен 2006
    Сообщения:
    616
    Симпатии:
    4
    сперва проверь, а после пиши.. если картинка вставлен как изображение, а не как файл, то в RTF поле нет никаких embeded объектов..
     
  11. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Kee_Keekkenen
    Кажись, CodeGuy и не утверждал, что у него embedded object'ы...
     
  12. CodeGuy

    CodeGuy Гость

    что проверить? у меня точно нет никаких вложений и embedded objects.

    сейчас открыт клиент Lotus, куда смотреть?
     
  13. CodeGuy

    CodeGuy Гость

    СПАСИБО!

    1. Экспорт отдельного документа прошёл на ура, только пришлось использовать DxlExporter, так как NotesDXLExporter оказался неизвестен. Фотографию ручками вытащил и декодировал - появился честный jpeg, поэтому метод через пятую точку будет работать (разобрать-то этот xml смогу как угодно).

    Заинтересовало, что при экспорте поле описывается следующим образом


    <item name='Foto'><richtext>
    <pardef id='1'/>
    <par def='1'>
    <picture width='118px' height='157px'><jpeg>
    /9j/4AAQSkZJRgABAgEAZABkAAD/4RPjRXhpZgAATU0
    ... очень много букв ...
    +9ybkiG2uMPxQ5Uc7Z1pwP/Z
    </jpeg></picture></par>
    <par def='1'/>
    </richtext></item>

    То есть на лицо пара параграфов (выделил цветом), однако элементов RichTextItem.RTELEM_TYPE_TEXTPARAGRAPH или RichTextItem.RTELEM_TYPE_TEXTRUN у меня вообще нет.

    Всё-таки хочу попробовать сделать прямым методом через голову, поэтому вопрос:
    Каким образом можно развернуть параграф, то есть получить доступ к содержимому первого параграфа элемента richtext? (здесь речь про стандартный интерфейс, а не XML)
     
  14. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Ты чем парсишь xml и вообще, зачнм "развернуть" параграф.
    Я слегка не понял вопроса...

    Только не забудь, что в DXL картинки погут лежать под тегами gif, jpeg и bmp.
     
  15. CodeGuy

    CodeGuy Гость

    Omh
    Я сейчас сделал полную выгрузку всей базы (здесь "плюс" ibm за применимость метода, хотя жаль, что к отдельному элементу не применим). Теперь могу хоть offline разбирать, хоть онлайн. К этому вопросу ещё вернусь.

    К сожалению, метод через XML немного коряв, так как похож на копирование файла с помощью печати и последующего распознавания. Мне сложно принять, что десяток лет картинки можно из richtext полей вытаскивать только с помощью XML-подобных операций. Пока нигде не встречал ответа, каким же образом картинка представлена в richtext, поэтому остаются лишь косвенные признаки. Здесь и наткнулся на "<pardef id='1'/> <par def='1'>" в DXL. Откуда они взялись? Это следствие упаковки изображения в поле или побочный эффект преобразования в DXL? Из каких же элементов состоит RichTextItem, если вообще ничего не возвращается?

    Даже получаемый GetInputStream() поток пуст. Почему в IBM просто не могут вернуть представление, совпадающее с возвращаемой длиной элемента?
     
  16. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Вообще pardef это элемент начала параграфа.
    В параграфе может быть текст, или, как например тут, картинка.
    Я думаю, при вставлении картинки автоматически делается параграф, который и виден в DXL-ке.

    С картинками, которые не embedded, а inline в лотусе действително беда.
    Особенно раньше была, ибо никаких методов, позволяющих получить картинку не было.
    С появлением 6-ки стало получше.
    Кстати говоря, получение картинки через DXL, на мой взгляд, на данный момент, один из самых прямых методов ;)

    Кстати, DXLExporter может выгружать и один элемент: там входным параметром может быть и объект класса NotesDocument.
     
  17. CodeGuy

    CodeGuy Гость

    Omh
    значит буду разбираться с DXL

    Под элементом я имел в виду те объекты, из которых состоят документы, входящие в базу. DXLExporter имеет следующие сигнатуры
    public String exportDxl(Database database) throws NotesException
    public String exportDxl(Document document) throws NotesException
    public String exportDxl(DocumentCollection documentcollection) throws NotesException
    public String exportDxl(NoteCollection notecollection) throws NotesException
    и применимость к Item у него отсутсвует. Не думаю, что пройдёт преобразование Item --> Document
     
  18. NetWood

    NetWood Lotus team
    Lotus team

    Регистрация:
    17 апр 2008
    Сообщения:
    308
    Симпатии:
    0
    Интересный путь намечается. Даже интересно ;) Далее задача сделать представление из найденных itemoв-картинок. Вот вопрос. Ну найде все что надо через DXL и ?
    Если только пошерстить все необходимые доки агентом и прописать имена картинок в доп поле и потом выводить. мб.
     
  19. CodeGuy

    CodeGuy Гость

    NetWood
    У меня есть подозрение, что под "представление" подразумеваете некоторый специальный объект Lotus, так? И насколько могу судить, то агент - это программа, выполняемая внутри базы?

    Так как у меня нет задачи замкнуть всё внутри Lotus, поэтому я спокойно пробегусь по базе и легко вставлю картинки и данные в таблицу Word-документа, а дальше выведу на печать.
     
  20. lmike

    lmike нет, пердело совершенство
    Команда форума Lotus team

    Регистрация:
    27 авг 2008
    Сообщения:
    6.079
    Симпатии:
    300
    всю ветку не прочел, может чё не видел...
    Файлы и, как подмножество, картинки НЕ ХРАНЯТСЯ В РТФ поле! Там только хинты и их замбнейлы

    ДХЛ самый гибкий и правильный путь, ИМХО

    дергалку аттачей и картинок (включая файловые пиктограммы) я выкладывал на интертрасте (вообще там есть много кода для этого) - LAX
    да и VTD очень даже (XPath поддерживает)
    http://web3.inttrust.ru/site/itforum.nsf/x...83?OpenDocument
    http://web3.inttrust.ru/site/itforum.nsf/f...33;OpenDocument (ссылка унутря)

    остальное...
    текст находится в тегах <par>, его атрибуты <pardef> ссылаюся по id

    тут гондыбал базку и сочинял способы конвертации MIME....
    родной java:
    String encoded=new sun.misc.BASE64Encoder().encode(URLDecoder.decode(xml,"UTF-8").getBytes());
    нативная java (код приложен в LAX):
    String encoded=Base64.encodeBytes(URLDecoder.decode(xml,"UTF-8").getBytes());

    Нотусёвая (через ж...):
    String encoded=encodeBASE64(URLDecoder.decode(xml,"UTF-8"));

    и сама
    <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">ф-ция</div></div><div class="sp-body"><div class="sp-content">
    Код (LotusScript):
        public String encodeBASE64(String s){
    String result="";
    try{
    Document doc=db.createDocument();
    MIMEEntity entity=doc.createMIMEEntity("temp");
    Stream tmp=session.createStream();

    tmp.writeText(URLDecoder.decode(s,"UTF-8"));
    entity.setContentFromText(tmp, "text/plain;charset=UTF-8", MIMEEntity.ENC_NONE);
    //          tmp.setPosition(0);
    //          tmp.truncate();
    entity.encodeContent(MIMEEntity.ENC_BASE64);
    result=entity.getContentAsText();
    tmp.recycle();
    doc.recycle();
    } catch(Exception e) {
    printStackTrace(e);
    }
    return result;
    }
    URLDecode там никчему :) - мне лень чистить было
    и это кодеры, декодеры аналогичны

    Можно применить чисто джавовское решение (без Нотусёвого клиента) - поднять на сервере IIOP (на клиенте проблематично и бессмысленно ИМХО)
    бился здесь: http://www.inttrust.ru/Site/itforum.nsf/al...DD?OpenDocument
    но там были "мои особенности"
    а просто - должно быть без траблов...

    Не понимаю также и зацикленность на МС продукты - там сплошные АктивХ прочая хрень - а оно вам надо.
    Опен Офис - куда как проще - это XML
    пример на том же ресурсе, очень показательный (я делал для ворда подбное, используя АктивХе - некрасивое решение, в сравнении с этим):
    http://www.inttrust.ru/site/itforum.nsf/f1...33;OpenDocument
    кстати там есть и парсинг SAX - что тоже дает возможность обработки файлов (выше в ссылках вариант, в т.ч. - LAX - ищите по ссылкам)
     
Загрузка...

Поделиться этой страницей