Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как выдрать картинку из Item.richtext?
Форум программистов > Базы данных и администрирование > Lotus > Lotus - Программирование
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 не могу.
NetWood
Imho обсуждали пару раз. Результат нулевой. Резюме - никак нельзя.
У самого были сходные задачи. Кроме как открывать под WEB и парсить методов нет. все это через заднее место...
CodeGuy
Цитата(NetWood @ 24:08:2008, 22:51 ) *
Imho обсуждали пару раз. Результат нулевой. Резюме - никак нельзя.
У самого были сходные задачи. Кроме как открывать под WEB и парсить методов нет. все это через заднее место...


Никак нельзя?!? unsure.gif ohmy.gif Я согласен на кривые методы, но без Web.
allex
Если я правильно понял суть твоей задачи, тебе нужно из RT поля взять картинку и поместить в Word - документ.

Этот код делает как раз то что нужно

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
CodeGuy
allex
Спасибо за пример кода. Проверить смогу только вечером, но сомневаюсь, что заработает, так как у меня в поле Item ВООБЩЕ НЕТ EmbeddedObjects, а здесь они являются ключевыми. sad.gif

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

Может быть есть метод, который содержимое RichText поля скопирует в буфер? С таким попробую справиться.
Omh
Если через буфер, то можно сделать uidoc.Goto + uidoc.Copy
Но это только на форграунде и в едит моде.

Ещё можно выкинуть док в DXL и оттуда декодировать картинку.
CodeGuy
Цитата(Omh @ 25:08:2008, 13:30 ) *
Если через буфер, то можно сделать uidoc.Goto + uidoc.Copy
Но это только на форграунде и в едит моде.

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


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

По поводу DXL ничего пока ничего не знаю, так как о программировании в Lotus узнал только вчера. Есть ли где-нибудь уже готовый пример подобной операции?
Kee_Keekkenen
Цитата(Omh @ 25:08:2008, 13:30 ) *
Ещё можно выкинуть док в DXL и оттуда декодировать картинку.

поддерживаю, это кстати отлично работает..
NetWood
Цитата(allex @ 25:08:2008, 05:44 ) *
'********сохранение картинки на диск
Set rtitem = doc.GetFirstItem( "Body" )
Forall o In rtitem.EmbeddedObjects
If ( o.Type = EMBED_ATTACHMENT ) Then
Call o.ExtractFile( "c:\" & o.Source )

Ха! Суть проблемы в том что картинка НЕ ЯВЛЯЕТСЯ НИ АТТАЧЕМ НИ ОБЬЕКТОМ. Увы. Были бы аттачи smile.gif
CodeGuy
Цитата(NetWood @ 25:08:2008, 14:01 ) *
Ха! Суть проблемы в том что картинка НЕ ЯВЛЯЕТСЯ НИ АТТАЧЕМ НИ ОБЬЕКТОМ. Увы. Были бы аттачи smile.gif


А чем же является картинка??? Или этого никто вообще не знает? Неужели все работают лишь с plain text?
Omh
Тебе надо:
1. Выгрузить документ в DXL (это простой текстовой XML файл)
2. По тегам найти картинку
3. Декодировать картинку (в DXL она хранится закодированая в base64)

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

Если только вчера начал программит в лотус, можешь и не осилить smile.gif
Kee_Keekkenen
Цитата(CodeGuy @ 25:08:2008, 14:03 ) *
А чем же является картинка??? Или этого никто вообще не знает? Неужели все работают лишь с plain text?

сперва проверь, а после пиши.. если картинка вставлен как изображение, а не как файл, то в RTF поле нет никаких embeded объектов..
Omh
Kee_Keekkenen
Кажись, CodeGuy и не утверждал, что у него embedded object'ы...
CodeGuy
Цитата(Kee_Keekkenen @ 25:08:2008, 14:56 ) *
сперва проверь, а после пиши.. если картинка вставлен как изображение, а не как файл, то в RTF поле нет никаких embeded объектов..


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

сейчас открыт клиент Lotus, куда смотреть?
CodeGuy
Цитата(Omh @ 25:08:2008, 14:22 ) *
Тебе надо:
1. Выгрузить документ в DXL (это простой текстовой XML файл)
2. По тегам найти картинку
3. Декодировать картинку (в DXL она хранится закодированая в base64)

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

Если только вчера начал программит в лотус, можешь и не осилить smile.gif


СПАСИБО!

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)
Omh
Ты чем парсишь xml и вообще, зачнм "развернуть" параграф.
Я слегка не понял вопроса...

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

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

Даже получаемый GetInputStream() поток пуст. Почему в IBM просто не могут вернуть представление, совпадающее с возвращаемой длиной элемента?
Omh
Вообще pardef это элемент начала параграфа.
В параграфе может быть текст, или, как например тут, картинка.
Я думаю, при вставлении картинки автоматически делается параграф, который и виден в DXL-ке.

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

Кстати, DXLExporter может выгружать и один элемент: там входным параметром может быть и объект класса NotesDocument.
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
NetWood
Интересный путь намечается. Даже интересно smile.gif Далее задача сделать представление из найденных itemoв-картинок. Вот вопрос. Ну найде все что надо через DXL и ?
Если только пошерстить все необходимые доки агентом и прописать имена картинок в доп поле и потом выводить. мб.
CodeGuy
NetWood
У меня есть подозрение, что под "представление" подразумеваете некоторый специальный объект Lotus, так? И насколько могу судить, то агент - это программа, выполняемая внутри базы?

Так как у меня нет задачи замкнуть всё внутри Lotus, поэтому я спокойно пробегусь по базе и легко вставлю картинки и данные в таблицу Word-документа, а дальше выведу на печать.
lmike
всю ветку не прочел, может чё не видел...
Файлы и, как подмножество, картинки НЕ ХРАНЯТСЯ В РТФ поле! Там только хинты и их замбнейлы

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

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

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

а как этот полученный код превратить в JPEG файл?
Omh
Декодировать из Base64
Либо NotesMimeEntity, либо LS библиотека гуляющаая на просторах нета (мееедленно), либо сторонней прогой.
lmike
Цитата(yerke @ 28:08:2008, 10:19 ) *
у меня возник вопрос
допустим инлайн картинку в ричтексте
экпортнули с помощью DXL инструментов
с новоиспеченного XML-а получили код картинки

а как этот полученный код превратить в JPEG файл?

а код приложенный выше слабо псмотреть wink.gif ? Там все уже сделано...
и Base64 библа, на джаве, приложена..., лень джаву "мучать", берите бридж LS2J и оборачивайте упомянутый класс
как высказался предыдущий коллега - чисто LS решение - медленное (LS "плохо" работает со стрингами)
Akupaka
если интересно как устроен dxl, то смотрите его dtd!
для каждой версии нотеса есть свой, все лежат в папке (по-умолчанию) notesdirectory\xmlschemas
например, D:\lotus\notes702\xmlschemas\domino_7_0_2.dtd

к стати, в каждой новой версии лежат все предыдущие. стоит обращать внимание на комменты! некоторые элементы устаревают, это описано в комментах.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2008 IPS, Inc.