• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

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

    Запись на курс до 25 апреля. Получить промодоступ ...

Переоткрытие Родителя

  • Автор темы juk-777
  • Дата начала
J

juk-777

Доброго времени суток, уважаемые! Помогите пожалста разобраться...

Существует документ-родитель, к которому создается дочерний (документ правда не совсем "дочерний", а имеет поле UniRoditelya, в которое я заношу UniversalID родительского дока. Ну и потом по этому полю я строю необходимую мне иерархию во встроенных вьюхах).
Это была маленькая прелюдия, а проблема в следующем: в родительском доке имеется RT-поле History, в которое я хочу вносить каждое действие, которое совершает пользователь по редактированию/созданию новых дочерних документов.
Так вот, мне надо чтобы после сохранения дочки, которая открыта или создана из родителя, открытый родитель переоткрывался в режиме просмотра. Долго я бился над кодом, который сейчас выложу... Он работает, но как-то не стабильно. Не стабильность в том, что то нормально закрывает все открытые доки и открывает для чтения родителя, то отставляет "старого" родителя открытым и открывает "нового" для чтения. То дочку оставляет открытой для редактирования :)(
Прошу помочь в решении проблемы, может туплю по-страшному где-то).

В событии QuerySave дочки идет проверка: на заполнение необходимых полей на форме и запись в историю родителя:
Continue=ProverkaPeople(Source.Document)

Теперь приведу выборочный код самой проверки ProverkaPeople.
сразу чуть поясню по коду:
nd - это получаемый функцией дочерний документ
pardoc - это получаемый из дочки родительский документ

<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">Код проверки ProverkaPeople</div></div><div class="sp-body"><div class="sp-content">
Function ProverkaPeople (nd As NotesDocument) As Boolean
'здесь идет объявление переменных...

ProverkaPeople = True

On Error GoTo err1

'тут идет проверка на заполнение полей в форме...


'после проверки на заполнение полей оставляю код как в ориггинале, чтобы было легче понять что к чему

mes=nd.UniRoditelya(0)
Set pardoc = db.GetDocumentByUNID(mes)

If pardoc Is Nothing Then
ProverkaPeople = False
Exit Function
End If

Set NameItm=New NotesName(session.UserName)
formul$="" + Date$ + " " + Time() + " - " + CStr(NameItm.Abbreviated) +_
". " + nd.PeopleRol(0) +_
". ФИО: " + nd.PeopleFIO(0) +_
". Год рождения: " + nd.PeopleGodRozh(0) +_
". Место жительства: " + nd.PeopleMestoZhit(0) +_
". Место работы: " + nd.PeopleMestoRab(0) + "."

Set RTItm=pardoc.getFirstItem("HistoryUD")
Call RTItm.Appendtext(formul$)
Call RTItm.Addnewline(1,True)
Call pardoc.Save(1,0)
Call pardoc.ReplaceItemValue("SAVEOPTIONS","0")

If nd.Isnewnote Then
nd.Form="FormPeople"
Call nd.Save(1,0)
Call nd.ReplaceItemValue("SAVEOPTIONS","0")
End If


Set uidoc = ws.Currentdocument
Call uidoc.Close
Call ws.URLOpen(pardoc.NotesURL)
Set uidoc = ws.Currentdocument
Call uidoc.Close

Call ws.EditDocument(false, pardoc)

Exit Function


err1:

Print "Ошибка в функции ProverkaPeople. Err=" & Err & ", Error=" & Error & ", Line=" & Erl
ProverkaPeople = False
Exit Function
End Function
 

savl

Lotus Team
28.10.2011
2 597
310
BIT
180
"Зачем..." ну да ладно.
Можно немного поменять код (сделайте копию функции ProverkaPeople, назавите её ProverkaPeople2):
1. Если функция вызывается в QuerySave, то думаю лучше вызвать ProverkaPeople2(Source)
То есть поменять тип входящего значения и уже внутри функции получать документ.
Это может сократить количество вызовов ws.Currentdocument, который достаточно глючный.
2. Попробовать получить ui-объект родителя через ws.EditDocument, но метод глючит порой, в частности во фреймах, так что нужны тесты.

Итого примерно такие правки (код не проверял, решение на ходу):
Код:
Function ProverkaPeople (ndUI As NotesUIDocument) As Boolean
'.... Ваши другие Dim
Dim nd as Notesdocument
set Nd = ndUI.Document
'..... Ваш основной код
Call ndUI .Close
Set uidoc = ws.EditDocument(false, pardoc,,,,true,false)
Call uidoc.Close
Call ws.URLOpen(pardoc.NotesURL)
End Function

Добавлено: А как по мне, я бы при создании дочерки - закрывал родителя, затем при сохранении - закрывал дочерку, открывал родителя.
Или бы не открывал, а сделал кнопку "Открыть основной документ" и пусть нажимают.
 
J

juk-777

Огромное спасибо за ответ!

"Зачем..." ну да ладно.
Можно немного поменять код (сделайте копию функции ProverkaPeople, назавите её ProverkaPeople2):
1. Если функция вызывается в QuerySave, то думаю лучше вызвать ProverkaPeople2(Source)
То есть поменять тип входящего значения и уже внутри функции получать документ.
Это может сократить количество вызовов ws.Currentdocument, который достаточно глючный.
2. Попробовать получить ui-объект родителя через ws.EditDocument, но метод глючит порой, в частности во фреймах, так что нужны тесты.

Итого примерно такие правки (код не проверял, решение на ходу):
Код:
Function ProverkaPeople (ndUI As NotesUIDocument) As Boolean
'.... Ваши другие Dim
Dim nd as Notesdocument
set Nd = ndUI.Document
'..... Ваш основной код
Call ndUI .Close
Set uidoc = ws.EditDocument(false, pardoc,,,,true,false)
Call uidoc.Close
Call ws.URLOpen(pardoc.NotesURL)
End Function
сократив кол-во вызовов ws.Currentdocument получил вроде 100% результат по НЕГЛЮЧНОСТИ)) За время тестирования все срабатывало на УРА! Изменил чуток ваш код на следующий, так как с вашим кодом закрывались все документы и оставалась открыта только база.
Call ndui.Close
Call ws.URLOpen(pardoc.NotesURL)
Set uidoc = ws.Currentdocument
Call uidoc.Close
Call ws.EditDocument(False, pardoc)

Редактирую пост спустя некоторое время: погорячился я все-таки со ста процентами ... (( проглючивает все равно его .. оставляет иногда открытым старого родителя и открывает еще вдобавок нового. Вопрос про закрытие родителя при открытии и дальнейшем изменении дочки, а не при ее создании, остается открытым)
Добавлено: А как по мне, я бы при создании дочерки - закрывал родителя, затем при сохранении - закрывал дочерку, открывал родителя.
Или бы не открывал, а сделал кнопку "Открыть основной документ" и пусть нажимают.
Кнопку открыть родителя я смастерил тоже, но хотел, чтобы поменьше юзвери шелкали мышками) Посмотрю как покажет себя код в работе .. и если будя глючить - буду закрывать родителя при создании дочки.

Кстати .. вопрос походу возник (может глуповатый - но простите :) ):
А как закрыть родителя, если дочка не создается новая, а открывается существующая из внедренного представления?
 
A

alexas

Не надо, в Вашем случае, использовать ws.URLOpen() вообще!
Чтобы придти в UI дока используйте ws.EditDocument(false/true, pardoc,,,,,false), как правильно savl отметил, и всё будет нормально (если док открыт в отдельной вкладке, т.е. НЕ в фрэйме).
С фрэймами другой разговор, но тоже есть решение.
И старайтесь не прыгать туда-сюда из UI одного дока в другой (не любит нотус этого): сделайте всё в UI одного дока, перейдите в UI другого и завершите скрипт.
 
J

juk-777

Не надо, в Вашем случае, использовать ws.URLOpen() вообще!
Чтобы придти в UI дока используйте ws.EditDocument(false/true, pardoc,,,,,false), как правильно savl отметил, и всё будет нормально (если док открыт в отдельной вкладке, т.е. НЕ в фрэйме).
С фрэймами другой разговор, но тоже есть решение.
И старайтесь не прыгать туда-сюда из UI одного дока в другой (не любит нотус этого): сделайте всё в UI одного дока, перейдите в UI другого и завершите скрипт.
Спасибо за ответ!
Вчера еще немного поэкспериментировал с кодом и пришел к такому варианту, без ws.URLOpen().

<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">функция ProverkaPeople</div></div><div class="sp-body"><div class="sp-content">
Function ProverkaPeople (ndUI As NotesUIDocument) As Boolean

...основной код

Call ndui.Close 'закрывает дочку

Set uidoc = ws.EditDocument(False, pardoc,,,True,False) 'переходим в открытого родителя
Call uidoc.Close 'закрываем родителя

Call ws.EditDocument(False, pardoc) 'открываем родителя для чтения

End Function

Вчера и сегодня мучаю лотус в этом варианте - все пока отлично..
 

savl

Lotus Team
28.10.2011
2 597
310
BIT
180
так как с вашим кодом закрывались все документы и оставалась открыта только база.
о! Вспомнил, стоит добавить.
Когда закрывается вкладка документа, то лотус возвращает фокус на предыдущий UI объект.
Возможен такой случай:
0. Открываем родитель
1. Создаем/Открываем дочку
2. Переходим в Почту
3. Переходим в дочку
4. Сохраняем.

По логике после закрытии дочки фокус перемещается в Почту, следовательно скрипт может закрыть вкладку с Почтой.
Возврат UI-объекта родителя должен решить этот вопрос. Попробуйте повторить мои шаги.
 

alexas1

Green Team
10.04.2014
1 202
225
BIT
37
Ещё момент...
Вы храните "историю" в RTF (поэтому и требуется "переоткрытие"). Зачем?
У Вас ведь нет какого-то специфического форматирования инфы в "истории" или добавления в "историю" аттачей-ссылок-и т.д.?
Если это так, то лучше использовать обычное текстовое поле.
Тогда, после добавления "истории", просто сохраните parent и переведите его в чтение (и первое и второе - в UI, в который Вы пришли через ws.EditDocument...). Так будет лучше.

P.S.
Добавление к "истории": pardoc.HistoryUD = pardoc.HistoryUD(0) + Chr(13) + "NewInfo"

Добавлено:
Когда закрывается вкладка документа, то лотус возвращает фокус на предыдущий UI объект...
А если юзверь поработал с дочкой, открыл ещё чего-нибудь и опять вернулся в дочку?
Так нехорошо, надо целенаправленно приходить в открытый док.
 

savl

Lotus Team
28.10.2011
2 597
310
BIT
180
alexas1
32k problem...

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

alexas1

Green Team
10.04.2014
1 202
225
BIT
37
savl
32k - Да! Я лопух.
А в остальном - "Мы с тобой одной крови, ты и я."(с) :)
 

ToxaRat

Чёрный маг
Green Team
06.11.2007
3 332
42
BIT
0
RT-поле History
:lamer:

лучше бы для этого функционала налепил отдельную базу!
 
J

juk-777

alexas1
32k problem...


Так я и не говорю обратное, а даже наоборот. Такой глюк возможен, если не получать UI родителя принудительно.
Вот и советую проверить скрипт на такой случай, интересно как отработает.
С приведенным мною кодом выше все отлично работает, даже если открыто на редактирование множество документов и переключаешься с одного на другой. Код удачно закрывает дочку и родителя и снова открывает родителя для чтения. Остальные открытые документы остаются в том же состоянии.

To ToxaRat: отдельную базу я тож сделаю для накопления истории по всем документам, но хотелось сделать и историю внутри отдельного документа-родителя .. как мне показалось - так будет удобно:lamer: )

Спасибо огромное всем за ответы.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!