Войти
 
 
   
 
  
Новости Notes.ру Библиотека Биржа труда Вопрос - ответ Форум Регистрация Поиск О проекте
Разделы
О Notes
Советы
Шаблоны и примеры
Литература
Презентации
 
Всё о задаче AdminP. Часть вторая   Во второй части мы завершаем рассмотрение AdminP. В ней рассмотрены запросы междоменного администрирования и способы управления функциями AdminP с помощью настроек документа сервера, команд консоли сервера, файла Notes.ini и интервалов очистки базы данных. В этой статье предполагается, что вы опытный администратор Domino и прочитали первую часть
О Notes Читать статью
 
Всё о задаче AdminP. Proxy-действия в R5 и Domino 6   Приложение к статье об административном процессе
О Notes Читать статью
 
Всё о задаче AdminP. Часть первая   Перевод классической статьи 2003-его года о задаче административного процесса (AdminP). Очень полезна для понимания работы механизма этой задачи. В первой части статьи описаны компоненты задачи AdminP, как они работают, и как их использование помогает сделать работу администратора Domino проще. Задача AdminP (сакращённо от Administration Process, Административный процесс) работает с базой административных запросов (Administration Requests, admin4.nsf)
О Notes Читать статью
 


Советы

Главная   Библиотека   Советы

Внедрённые представления из других баз

Василий Соков, компания «Аплана Софтвер»
Vasiliy.Sokov@aplana.com

Всем нам хорошо известны такие элементы дизайна как формы и представления, а также приемы их совместного использования, которые способны сделать приложение по-настоящему удобным, функциональным и чутким к пользователю. Разрабатывая приложение, состоящее из одного самодостаточного модуля (базы) особых проблем с использованием такого функционала, как внедренное представление, не встречается. Но если речь заходит о более масштабном приложении, тогда уже на этапе проектирования разработчику приходится сталкиваться с довольно серьезными ограничениями, связанными с отображением информации, хранящейся вне текущей БД.
Чтобы до конца понять, о чем идет речь, рассмотрим следующий пример.
Представим себе менеджера с довольно объемной персональной адресной книгой (АК) и не менее объемным почтовым файлом. Менеджер, выступающий в роли бизнес-заказчика, требует от вас добавить в АК функционал, позволяющий отображать в карточке клиента (т.е. в форме Person) всю историю переписки с этим клиентом из почтовой базы. Решение, казалось бы, очевидное – добавить в форму Person внедренное представление из почтового файла пользователя (благо R6 позволяет это сделать) и с помощью SingleShowCategory показывать документы, у которых в полях SendTo, CopyTo, BlindCopyTo и From содержится адрес из поля MailAddress в карточке контакта. Ну и, естественно, само такое представление в почтовый файл добавить, настроить формулу отбора и группировку. Тратим 5 минут, обновляем дизайн баз у менеджера и… а внедренного представления-то и нет...
Если вы поняли о чем идет речь, вспомнили аналогичную сцену из собственной практики, то пришло время пролить свет на сложившуюся ситуацию.
Для начала, разберемся, в чем причина. А причина проста, как три рубля мелочью: в момент внедрения представления в форму, в форме намертво прописывается replica id базы, из которой Notes и пытается при открытии формы подгрузить данное представление. А так как внедряли представление, допустим, из почтового шаблона на машине разработчика, а использовать пытаемся на машине менеджера, то Notes не может найти базу по replica id и, соответственно, подгрузить представление тоже не может. Можно, конечно, сделать реплику почтового файла менеджера на машину разработчика, «перевнедрить» представление и реплицировать изменения обратно менеджеру. Но это не серьезно: менеджеров может быть много, у каждого свой почтовый файл, а если все почтовые файлы хранятся, допустим, на сервере, то у каждого будет разный replica id.
Таким образом, нужно найти решение, позволяющее настраивать этот параметр. Причем манипуляции с формулами для вычисления представления ни к чему не приведут – доказано на практике. По сему, предлагаю на рассмотрение следующий код. Это агент, запрашивающий путь к нужной базе и меняющий соответствующий параметр в элементе дизайна на replica id указанной базы.
Для начала, вынесем внедренное представление в подформу и назовем ее, к примеру, $$EmbView_forPerson, а потом эту подформу встроим в форму Person. Это нужно для ускорения процесса «переколачивания». Затем создадим агента на Lotus Script’е с типом запуска «При выборе из меню действий», чтобы иметь возможность взаимодействовать с UI-объектами.
Если кратко, то схема работы агента проста: в Initialize запрашивается база, из которой нужно отображать представление (в нашем примере это почтовый ящик пользователя), проводится проверка, и если база открыта, то устанавливается переменная REPLICAID$ и вызывается подпрограмма rebuildView, которая будет организовывать конвейер по обработке. В rebuildView сначала создается коллекция подформ, затем помощью NotesDXLExporter эта коллекция экспортируется в DXL и поступает по конвейеру на обработку NotesDOMParser’у, на событие PostDOMParse которого реагирует подпрограмма postParse, которая и производит поиск нужного атрибута и его замену. В этой же postParse вызывается метод Serialize класса NotesDOMParser, который выдает модифицированный DXL на вход для NotesDXLImporter’а, который в свою очередь импортирует DXL в текущую БД, заменяя подформы.

(Options)
Option Public
Option Declare

(Declarations)
Dim session As NotesSession
Dim db As NotesDatabase
Dim REPLICAID As String

Sub Initialize
On Error Goto errline

Dim target As NotesDatabase
Dim PATH as Variant

Dim ws As New NotesUIWorkSpace

' получаем путь к базе, из которой нужно брать внедренное представление
PATH=ws.Prompt(13,””,””)

' если нажата Отмена - выходим
If IsEmpty(PATH) then Exit Sub

Set session=New NotesSession
Set db = session.CurrentDatabase
Set target=New NotesDatabase("","")

' если указанная БД существует и есть к ней доступ – тогда приступаем к ее обработке
If target.Open(PATH(0),PATH(1)) Then
REPLICAID$=target.ReplicaID
Call rebuildView
End if

Exit Sub
errline:
Msgbox " Error " & Err & " in line " & Erl & " in function " & Lsi_info(2) & " : " & Error
End 1
End Sub

Sub rebuildView
On Error Goto errline

' с помощью этого класса получим коллекцию подформ в текущей БД
Dim subformCollection As NotesNoteCollection

' с помощью этих классов выполним конвейерную обработку DXL
Dim exporter As NotesDXLExporter
Dim xml As NotesDOMParser
Dim importer As NotesDXLImporter

' создаем экземпляр NotesNoteCollection в текущей базе
Set subformCollection=db.CreateNoteCollection(False)
' отбираем в коллекцию только подформы
subformCollection.SelectSubforms=True
' генерируем коллекцию
Call subformCollection.BuildCollection

' если вдруг подформ в БД не оказалось – выходим
If subformCollection.Count=0 Then Exit Sub

' сначала объявляем парсер, чтобы при объявлении экспортера сразу его указать в качестве
' приёмника
Set xml=session.CreateDOMParser
' после того, как DXL будет отпарсен, приступаем к поиску и замене нужного нам
' параметра
On Event PostDOMParse From xml Call postParse
' создаем экспортер, на входе – коллекция подформ, на выходе - парсер
Set exporter=session.CreateDXLExporter(subformCollection,xml)
' создаем импортер, на входе – парсер, на выходе – текущая база
Set importer=session.CreateDXLImporter(xml,db)
' при импорте элементов дизайна – заменять уже существующие, а если не существует –
' игнорировать
importer.DesignImportOption = DXLIMPORTOPTION_REPLACE_ELSE_IGNORE

' поехали!
Call exporter.Process

Exit Sub
errline:
Msgbox " Error " & Err & " in line " & Erl & " in function " & Lsi_info(2) & " : " & Error
End 1
End Sub

Sub postParse(xml As NotesDOMParser)
On Error Goto errline

' корень экспортированного DXL
Dim root As NotesDOMDocumentNode
' ориентироваться будем на несколько подформ
Dim subFormNodeList As NotesDOMNodeList
Dim subFormNode As NotesDOMElementNode
' этот элемент будет представлять внедренное представление
Dim embViewNode As NotesDOMElementNode

Dim SUBFORM_NAME As String
Dim i As Integer

' получаем корень
Set root=xml.Document
' и ищем все подформы
Set subFormNodeList=root.GetElementsByTagName("subform")

For i=1 To subFormNodeList.NumberOfEntries
' перебираем по очереди каждую
Set subFormNode=subFormNodeList.GetItem(i)
' выясням ее имя
SUBFORM_NAME$=subFormNode.GetAttribute("name")

' если имя подформы совпадает с шаблоном – обрабатываем ее
If Left(SUBFORM_NAME$,10)="$$EmbView_" Then
' берем первое внедренное представление (и единственное)
            Set embViewNode=subFormNode.getElementsByTagName("embeddedview").getItem(1)

' и устанавливаем нужное значение для аттрибута database
Call embViewNode.SetAttribute("database",REPLICAID$)
' при испытаниях выяснилось, что после обработки ширина внедренного
' представления
' становится зачем-то равной 5040%, чтобы вылечить этот глюк – проставляем
' ширину
' вручную.
Call embViewNode.SetAttribute("width","100%")

End If
Next

'парсер не умеет автоматически подавать на выход, поэтому нужно его об этом попросить
Call xml.Serialize

Exit Sub
errline:
Msgbox " Error " & Err & " in line " & Erl & " in function " & Lsi_info(2) & " : " & Error
End 1
End Sub

Чтобы проконтролировать результаты выполнения, можно воспользоваться встроенным средством просмотра DXL (в дизайнере открыть подформу Сервис – Программы DXL – Средство просмотра), чтобы сравнить результаты до и после.
Ну и как водится, в бочке меда есть ложка дегтя. Элемент embeddedview не имеет параметра server, поэтому реплика базы, содержащей внедренное представление, должна находиться на машине пользователя, чтобы Notes смог ее найти. Но и в ложке дегтя есть углеводы – вместо ID реплики базы параметр database принимает одно из зарезервированных значений: mailfile, addressbook, subscriptions, bookmarks, которые соответствуют почтовому ящику, АК, подпискам и закладкам. То есть, если установить в атрибут database значение, например, mailfile, тогда возможны различные комбинации с расположением баз друг относительно друга.



Программный код, приведенный в этом материале, был первоначально создан Василием Соковым, компания «Аплана Софтвер», 2006 г. Этот код может свободно распространяться, изменяться и использоваться только со ссылкой на автора.
Все предложения, замечания и исправления прошу присылать на адрес Vasiliy.Sokov@aplana.com.
 
  Опубликовано — 03/28/2006 |    

_Vovka_, 28.06.2012 17:24:51:
Чтобы всё-таки не оставлять тему открытой ... вариант решения без всяких dxl и правки дизайна:

1. на форму внедряется Embedded Editor с формой Х
2. на форме Х ставится AutoFrame в фреймсет Y
3. во фреймсете Y для единственного фрейма ставится NamedElement=Form и Content=Cumputed и указывается формула для определения базы и формы Z
4. в форме Z внедряется необходимая EmbeddedView (хоть по формуле, хоть так)

P.S. вариант рабочий и находится в промышленной эксплуатации много лет в самой лучшей лотусовой СЭД :-)

Максим, 24.10.2007:
Пробовал использовать приведенный в статье код... получил такую проблему: при работе агента возникает ошибка 4522 ошибка в работе ДХЛ импортера. кто-нибудь может посоветовать способ устранение? Кто-нибудь работал с версиями 7 и 8? Там проблема внедренных видов не решена?

Владимир, 16.08.2007:
>>модифицировать другие элементы дизайна этот код не может по определению Это почему же не может???? Вы же считываете ВЕСЬ дизайн, потом изменяете ЧАСТЬ, потом записываете ВЕСЬ дизан!!!! Вот соседнике куски дизайна и херятся. Это так лотус работает. Можете даже просто сделать ЧТЕНИЕ и ЗАПИСЬ - ваши виды и формы модифицируются!!!! Похерятся частично размеры

Василий, 04.10.2006:
2 сергей: совсем не обязательно, можно выполнять запуск обрабатывающего агента от имени привелигированного пользователя

Василий, 04.10.2006:
пример, приведенный для описания проблемы, на самом деле игрушечный. а вот пример кода очень даже рабочий и отлично справляется с поставленными задачами на базах с огромным количеством подформ в том числе и вложенных. модифицировать другие элементы дизайна этот код не может по определению, такшто ищите баги, батенька, там где они есть, а не там, где они могут быть...

сергей, 04.10.2006:
получается что пользователям БД надо давать доступ к изменениям элементов дизайна БД, я бы на такое не решился -))

Владимир, 04.10.2006:
Работать-то работает, что-то там модифицирует, но блин другие элементы дизайна портит. Создается впечатление, что этот пример носит игрушечный характер. От размещенной статьи хотелось бы действенного и применимого на практике способа решения проблемы. Видно, что автор не применял его на сколько-нибудь большой базе, изобилующей подформами, таблицами и т.д. Основной вывод: пример непригодный.

Максим, 26.10.2005:
Василий, в своих поисках решения я наткнулся на такой проект: http://www.openntf.org/Projects/pmt.nsf/ProjectLookup/Remote%20Embedded%20View%20Manager%20(REVM) Работа в нем также осуществляется через ДХЛ импорт\экспорт. Поставил эксперимент по его работоспособности. Выяснилось, что работая с 6 сервером и клиентом возникает такаяже ошибка, как в приведенном на этой странице коде. При работе с версией клиента и сервера 7.0.х все работает пока без ошибок...

Василий, 25.10.2005:
Максим, я тут по ходу применения этого куска наткнулся на довольно интересный глюк. В моем случае импортер валился если в имени базы встречался знак одинарной кавычки. Т.е. экспортер не умеет заменять подобные знаки на аналоги с амперсандом, чтобы избежать ошибок в дальнейшем, а импортер в свою очередь пытается импортнуть как есть. Например, в случае адресной книжки тайтл базы был Sokov's AddressBook. И внутри dxl для строк тоже использовалась одинарная кавычка. Попробуйте выгрузить dxl в файлик а в обработчике ошибки вывести подробное сообщение с помощью DXLImporter.Log. Думаю проблема из этого же разряда.



Добавить комментарий
Имя * :
e-mail
Комментарий * :
Код подтверждения * :


Мероприятия
Пресс-релизы
Биржа труда
Последнее на форуме
 
А так же:
Как удалить профиль?
16.04.2016 00:08:51
Скопировать в буфер поле документа
24.05.2015 08:55:52
Импорт DXL-описания документов в Lotus Domino. Одноимённые поля
16.04.2015 16:49:58
 
© LOGOSPHERE.RU