CodeGuy
24:08:2008, 14:32
Здравствуйте!
Понадобилось сформировать небольшой отчёт по базе 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
24:08:2008, 19:51
Imho обсуждали пару раз. Результат нулевой. Резюме - никак нельзя.
У самого были сходные задачи. Кроме как открывать под WEB и парсить методов нет. все это через заднее место...
CodeGuy
24:08:2008, 22:53
Цитата(NetWood @ 24:08:2008, 22:51 )

Imho обсуждали пару раз. Результат нулевой. Резюме - никак нельзя.
У самого были сходные задачи. Кроме как открывать под WEB и парсить методов нет. все это через заднее место...
Никак нельзя?!?

Я согласен на кривые методы, но без Web.
Если я правильно понял суть твоей задачи, тебе нужно из 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
25:08:2008, 08:24
allex Спасибо за пример кода. Проверить смогу только вечером, но сомневаюсь, что заработает, так как у меня в поле Item ВООБЩЕ НЕТ
EmbeddedObjects, а здесь они являются ключевыми.
Собственно меня это и смущает, так как Ctrl+C работает, а как он сохранён - не ясно.
Может быть есть метод, который содержимое RichText поля скопирует в буфер? С таким попробую справиться.
Если через буфер, то можно сделать uidoc.Goto + uidoc.Copy
Но это только на форграунде и в едит моде.
Ещё можно выкинуть док в DXL и оттуда декодировать картинку.
CodeGuy
25:08:2008, 10:44
Цитата(Omh @ 25:08:2008, 13:30 )

Если через буфер, то можно сделать uidoc.Goto + uidoc.Copy
Но это только на форграунде и в едит моде.
Ещё можно выкинуть док в DXL и оттуда декодировать картинку.
"На форграунде" - это мне нужно внедрять в базу Lotus мою программу, так? Если да, то не подходит.
По поводу DXL ничего пока ничего не знаю, так как о программировании в Lotus узнал только вчера. Есть ли где-нибудь уже готовый пример подобной операции?
Kee_Keekkenen
25:08:2008, 10:44
Цитата(Omh @ 25:08:2008, 13:30 )

Ещё можно выкинуть док в DXL и оттуда декодировать картинку.
поддерживаю, это кстати отлично работает..
NetWood
25:08:2008, 11:01
Цитата(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 )
Ха! Суть проблемы в том что картинка НЕ ЯВЛЯЕТСЯ НИ АТТАЧЕМ НИ ОБЬЕКТОМ. Увы. Были бы аттачи
CodeGuy
25:08:2008, 11:03
Цитата(NetWood @ 25:08:2008, 14:01 )

Ха! Суть проблемы в том что картинка НЕ ЯВЛЯЕТСЯ НИ АТТАЧЕМ НИ ОБЬЕКТОМ. Увы. Были бы аттачи

А чем же является картинка??? Или этого никто вообще не знает? Неужели все работают лишь с plain text?
Тебе надо:
1. Выгрузить документ в DXL (это простой текстовой XML файл)
2. По тегам найти картинку
3. Декодировать картинку (в DXL она хранится закодированая в base64)
Ключевые слова:
1. NotesDXLExporter
2. NotesDOMParser, GetElementsByTagName
3. NotesMIMEEntity или сторонними програмами.
Если только вчера начал программит в лотус, можешь и не осилить
Kee_Keekkenen
25:08:2008, 11:56
Цитата(CodeGuy @ 25:08:2008, 14:03 )

А чем же является картинка??? Или этого никто вообще не знает? Неужели все работают лишь с plain text?
сперва проверь, а после пиши.. если картинка вставлен как изображение, а не как файл, то в RTF поле нет никаких embeded объектов..
Kee_Keekkenen
Кажись, CodeGuy и не утверждал, что у него embedded object'ы...
CodeGuy
25:08:2008, 12:18
Цитата(Kee_Keekkenen @ 25:08:2008, 14:56 )

сперва проверь, а после пиши.. если картинка вставлен как изображение, а не как файл, то в RTF поле нет никаких embeded объектов..
что проверить? у меня точно нет никаких вложений и embedded objects.
сейчас открыт клиент Lotus, куда смотреть?
CodeGuy
25:08:2008, 17:36
Цитата(Omh @ 25:08:2008, 14:22 )

Тебе надо:
1. Выгрузить документ в DXL (это простой текстовой XML файл)
2. По тегам найти картинку
3. Декодировать картинку (в DXL она хранится закодированая в base64)
Ключевые слова:
1. NotesDXLExporter
2. NotesDOMParser, GetElementsByTagName
3. NotesMIMEEntity или сторонними програмами.
Если только вчера начал программит в лотус, можешь и не осилить

СПАСИБО!
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)
Ты чем парсишь xml и вообще, зачнм "развернуть" параграф.
Я слегка не понял вопроса...
Только не забудь, что в DXL картинки погут лежать под тегами gif, jpeg и bmp.
CodeGuy
25:08:2008, 19:32
Omh
Я сейчас сделал полную выгрузку всей базы (здесь "плюс" ibm за применимость метода, хотя жаль, что к отдельному элементу не применим). Теперь могу хоть offline разбирать, хоть онлайн. К этому вопросу ещё вернусь.
К сожалению, метод через XML немного коряв, так как похож на копирование файла с помощью печати и последующего распознавания. Мне сложно принять, что десяток лет картинки можно из richtext полей вытаскивать только с помощью XML-подобных операций. Пока нигде не встречал ответа, каким же образом картинка представлена в richtext, поэтому остаются лишь косвенные признаки. Здесь и наткнулся на "<pardef id='1'/> <par def='1'>" в DXL. Откуда они взялись? Это следствие упаковки изображения в поле или побочный эффект преобразования в DXL? Из каких же элементов состоит RichTextItem, если вообще ничего не возвращается?
Даже получаемый GetInputStream() поток пуст. Почему в IBM просто не могут вернуть представление, совпадающее с возвращаемой длиной элемента?
Вообще pardef это элемент начала параграфа.
В параграфе может быть текст, или, как например тут, картинка.
Я думаю, при вставлении картинки автоматически делается параграф, который и виден в DXL-ке.
С картинками, которые не embedded, а inline в лотусе действително беда.
Особенно раньше была, ибо никаких методов, позволяющих получить картинку не было.
С появлением 6-ки стало получше.
Кстати говоря, получение картинки через DXL, на мой взгляд, на данный момент, один из самых прямых методов

Кстати, DXLExporter может выгружать и один элемент: там входным параметром может быть и объект класса NotesDocument.
CodeGuy
25:08:2008, 20:20
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
25:08:2008, 21:38
Интересный путь намечается. Даже интересно

Далее задача сделать представление из найденных itemoв-картинок. Вот вопрос. Ну найде все что надо через DXL и ?
Если только пошерстить все необходимые доки агентом и прописать имена картинок в доп поле и потом выводить. мб.
CodeGuy
26:08:2008, 04:49
NetWood
У меня есть подозрение, что под "представление" подразумеваете некоторый специальный объект Lotus, так? И насколько могу судить, то агент - это программа, выполняемая внутри базы?
Так как у меня нет задачи замкнуть всё внутри Lotus, поэтому я спокойно пробегусь по базе и легко вставлю картинки и данные в таблицу Word-документа, а дальше выведу на печать.
всю ветку не прочел, может чё не видел...
Файлы и, как подмножество, картинки НЕ ХРАНЯТСЯ В РТФ поле! Там только хинты и их замбнейлы
ДХЛ самый гибкий и правильный путь, ИМХО
Есть много кода на 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 - ищите по ссылкам)
у меня возник вопрос
допустим инлайн картинку в ричтексте
экпортнули с помощью DXL инструментов
с новоиспеченного XML-а получили код картинки
а как этот полученный код превратить в JPEG файл?
Декодировать из Base64
Либо NotesMimeEntity, либо LS библиотека гуляющаая на просторах нета (мееедленно), либо сторонней прогой.
Цитата(yerke @ 28:08:2008, 10:19 )

у меня возник вопрос
допустим инлайн картинку в ричтексте
экпортнули с помощью DXL инструментов
с новоиспеченного XML-а получили код картинки
а как этот полученный код превратить в JPEG файл?
а код приложенный выше слабо псмотреть

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