Функция обхода документов-ответов, ответов на ответы и т.д.

Тема в разделе "Lotus - Программирование", создана пользователем FixeR, 14 дек 2009.

  1. FixeR

    FixeR Гость

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

    Сам писал такую два года назад как-то с двумя циклами, без рекурсии, а щас третий день не могу вспомнить...
     
  2. hosm

    hosm * so what *

    Регистрация:
    18 май 2009
    Сообщения:
    2.450
    Симпатии:
    7
    в КБ есть обработка ответов: http://codeby.net/forum/threads/17552.html
    там сбор юнидов, в принципе, на коллекцию переписать не сложно, имхо.
    Единственное - код я не проверяла.


    Добавлено: там рекурсия

    Добавлено: тут вот по вьюхе брали:
    Код (Text):
    Sub getAllChildren(view As NotesView, doc As NotesDocument, coll As NotesDocumentCollection)
    ' рекурсия
    Dim childs As NotesDocumentCollection, child As NotesDocument

    Set childs = view.GetAllDocumentsByKey(doc.UniversalID, True)
    If childs.Count = 0 Then Exit Sub

    Set child = childs.GetFirstDocument
    While Not child Is Nothing
    Call coll.AddDocument( child )
    Call getAllChildren(view, child, coll)

    Set child = childs.GetNextDocument( child )
    Wend   
    End Sub
     
  3. lmike

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

    Регистрация:
    27 авг 2008
    Сообщения:
    6.075
    Симпатии:
    300
    можно через нафигатор
     
  4. VladSh

    VladSh начинающий
    Lotus team

    Регистрация:
    11 дек 2009
    Сообщения:
    1.251
    Симпатии:
    2
    Мой старый код:

    Код (Text):
    %REM
    Sub TreeRDownC
    Description: Возвращает дерево ответов переданного документа
    %END REM
    Sub TreeRDownC(ND_Source As NotesDocument, NDC_Rez As NotesDocumentCollection)
    If ND_Source Is Nothing Then Exit Sub
    Dim NDС As NotesDocumentCollection
    Dim ND As NotesDocument
    Set NDC = ND_Source.Responses
    If NDC.Count = 0 Then Exit Sub

    On Error 4469 Resume Next

    Set ND = NDC.GetFirstDocument
    Do
    If IsDocAccessed(ND, false) Then    'Обнаружил баг с параметром TIA
    Call NDC_Rez.AddDocument(ND)
    Call TreeRDownC(ND, NDC_Rez)
    End If

    Set ND = NDC.GetNextDocument(ND)
    If ND Is Nothing Then Exit Do
    Loop
    End Sub
    Код (Text):
    %REM
    Sub IsDocAccessed
    Description: Определяет, доступен ли документ
    %END REM
    Function IsDocAccessed(ND As NotesDocument, SetNothing As Boolean) As Boolean
    If Not ND Is Nothing Then
    If ND.IsValid And Not IsEmpty(ND.Items) And Not ND.IsDeleted Then   'Добавил проверку на Items, т.к. действительно бывают траблы; спасибо сообществу!
    IsDocAccessed = True
    Exit Function
    End If
    End If
    If SetNothing Then Set ND = Nothing
    End Function
    Если надо получить полное дерево от верхнего документа, то вызываем сначала:
    Код (Text):
    %REM
    Sub GetTopDoc
    Description: Возвращает самый верхний документ коллекции
    Если у документа нет ответа, то ND_Parent будет равно Nothing.
    %END REM
    Sub GetTopDoc(ND_Source As NotesDocument, ND_Parent As NotesDocument)
    Dim NDB As NotesDatabase
    Dim ND As NotesDocument
    Set NDB = ND_Source.ParentDatabase

    On Error 4091 Goto Err4091
    Set ND_Parent = ND_Source
    Set ND = ND_Source
    Do
    If Cstr(ND.ParentDocumentUNID) = "" Then Exit Sub
    Set ND = NDB.GetDocumentByUNID(ND.ParentDocumentUNID)
    If Not ND Is Nothing Then
    If Not ND_Parent Is ND Then
    Call IsDocAccessed(ND, True)
    Set ND_Parent = ND
    Else
    If ND_Parent Is ND_Source Then Set ND_Parent = Nothing
    Exit Sub
    End If
    Else
    On Error Goto 0
    Exit Sub
    End If
    Loop
    Exit Sub

    Err4091:
    Resume Next
    End Sub
    а потом для полученного ND_Parent вызываем TreeRDownC.
     
  5. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    пару вопросов-предположений :O_0:

    почему не обрабатываем вариант наличия документа в коллекции проверкой наличия, а попускаем?
    Код (Text):
    Sub TreeRDownC...
    On Error 4469 Resume Next
    ...
    Call NDC_Rez.AddDocument(ND)
    Call TreeRDownC(ND, NDC_Rez)
    например так
    Код (Text):
    On Error 4469 Resume Next
    ...
    if NDC_Rez.GetDocument(ND) is nothing then
    Call NDC_Rez.AddDocument(ND)
    Call TreeRDownC(ND, NDC_Rez)
    end if
    вообще, я не вижу из приведенного кода, когда возможен вариант, что будет попытка добавить документ в коллекцию повторно (кроме как вызов извне на документе из дерева), но, логически будет верным вызывать TreeRDownC только для документов, которые в коллекцию добавлены в момент выполнения, иначе мы разрешаем ситуацию, когда дерево документов может быть обработато повторно, хотя изменений в коллекции произведено не будет. нет?


    достаточно ли проверок
    Код (Text):
    Function IsDocAccessed...

    ND.IsValid And Not ND.IsDeleted
    или может нужно еще и проверить доступность по доступу
    Код (Text):
    ND.IsValid And Not ND.IsDeleted And isArray(ND.Items)
    иначе можем получить в коллекции документ, с которым не получится работать.


    лишний On Error или фича?
    Код (Text):
    Sub GetTopDoc...
    ...
    Else
    On Error Goto 0
    Exit Sub
    End If
     
  6. TIA

    TIA :-)
    Lotus team

    Регистрация:
    15 май 2009
    Сообщения:
    790
    Симпатии:
    0
    Ещё косяк:

    Функция IsDocAccessed может устанавливать ND в Nothing. В этом случае не сработает NDC.GetNextDocument(ND).
     
  7. VladSh

    VladSh начинающий
    Lotus team

    Регистрация:
    11 дек 2009
    Сообщения:
    1.251
    Симпатии:
    2
    Потому что проверка - это действие, на которое тратится время, а вероятность ошибки мала..

    Всё правильно заметили; есть ещё одна функция, которая работает по выделенным докам в виде (в неё передаётся коллекция) и собирает все деревья ответов, потому именно так.

    Не можем, этих проверок достаточно. Проверки на массив айтемов - это наследие древних версий, когда нормально невозможно было проверить док. Массив полей появляется тогда, когда обе проверки проходят.

    Решил обнулить ошибку по человечески, т.к. Err=0 иногда всё равно выбивает, точно не помню, кажется в агентах на сервере.


    Это точно!
    Поставлю здесь параметр в False.
    EDITED: Посмотрел почему параметр в True - я сначала писал такие функции на массивы, так вот перебор доков там идёт по GetNthDocument, видимо код скопировал, а над параметром не задумался. И как оно уже столько лет работает?.. прикольно)))
    Спасибо! Вот вместе и довели до ума :O_0:
     
  8. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    что имеется в виду под древними версиями? т.к. моя практика основывается на версиях 5-6, в 7-8 честно не проверял :O_0: и в них, если я не имею доступа к документу по РА-полям, но док каким-то образом получаю, то имею ситуацию, когда док валиден, не удален, но и итемсов нет О.о я только не помню как мы такие доки получали...

    зы: буду рад переходу на "ты" :)
     
  9. VladSh

    VladSh начинающий
    Lotus team

    Регистрация:
    11 дек 2009
    Сообщения:
    1.251
    Симпатии:
    2
    Akupaka
    Ок, перейдём на "ты" :)
    Стартовал с 5.03.. Есть привычка разные спорные (для меня) моменты перепроверять с выходом новой версии (а вдруг поправили? :) ). В 6.5.1 уже хватало 2-х проверок. Функции написаны и работают - ни разу не удалось получить док, чтобы проверки прошли, но Items бы не было; хотя может быть просто потому, что не ТУДА ещё не вступал.. :O_0:
    Если вспомнится - напиши. Интересно, что это такое может быть..
     
  10. hosm

    hosm * so what *

    Регистрация:
    18 май 2009
    Сообщения:
    2.450
    Симпатии:
    7
    ND.IsValid And Not ND.IsDeleted
    Будете смеяться?
    Документ, к которому нет доступа:
    Клиент - 7.0.3:
    ND.IsValid = False IsEmpty(ND.Items) = True
    Клиент - 8.5:
    ND.IsValid = True IsEmpty(ND.Items) = True
    сервер 7.0.3 - возможно, в этом причина?

    Добавлено: документ берется по униду, код один и тот же, клиент и сервер - английские.
     
  11. VladSh

    VladSh начинающий
    Lotus team

    Регистрация:
    11 дек 2009
    Сообщения:
    1.251
    Симпатии:
    2
    OKEN, тут не до смеху...
    Документ один и тот же???
    Что говорит ND.IsDeleted?
     
  12. hosm

    hosm * so what *

    Регистрация:
    18 май 2009
    Сообщения:
    2.450
    Симпатии:
    7
    да не удален он, не удален. Админ (манагер) его получает без проблем. Валидным, неудаленным и с итемами.
     
  13. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    о! точно ))) надо док взять по униду! а я думаю, как же мы их получали? )))
    это были проблемы у пользователей при работе со связанными документами, но когда к одному из них доступа нет, по какой-то причине, но унид был известен.
     
  14. hosm

    hosm * so what *

    Регистрация:
    18 май 2009
    Сообщения:
    2.450
    Симпатии:
    7
    Простую сделали форму: вводишь унид дока, и кнопочку, по которой коллега мне эту красоту и продемонстировал (в 2 клиентах под 2-мя id).
    на досуге можешь глянуть корректность в 8.5.1. /*более "древняя" версия?*/ :)
    В общем, вставляйте все проверки "на вшивость"...
     
  15. VladSh

    VladSh начинающий
    Lotus team

    Регистрация:
    11 дек 2009
    Сообщения:
    1.251
    Симпатии:
    2
    Проверил лично, подтверждаю, всё что говорила выше OKEN! Раньше с этим не встречался, т.к. приложения были так спроектированы, что возникновение такой ситуации было исключено...
    Откорректировал проверку в своей функции IsDocAccessed.

    Т.к. обсуждение уже идёт по поводу какую проверку для этого лучше использовать :), то я предлагаю IsEmpty, т.к. проверка указанием на пустоту по аналогии с Object Is Nothing работает быстрее всего.
     
  16. nvyush

    nvyush Lotus team
    Lotus team

    Регистрация:
    22 апр 2009
    Сообщения:
    2.317
    Симпатии:
    0
    А чему равен ND.Size? В моих проверках при открытии недоступного документа по UNID doc.Size = 0, doc.GetItemValue("AnyItem") и doc.AnyItem ошибку не генерят, ND.IsValid = False, ND.IsDeleted = False. Клиент 8.0.2ru, сервер 8.0.2.
    Мне кажется, проверка на IsDeleted избыточна. В справке сказано, что она отражает текущее состояние объекта doc, а IsValid - при создании объекта. Таким образом, если мы делаем проверку сразу после set doc = db.GetDocumentByUnid, достаточно тестировать IsValid (если справка не врёт). Для дополнительной проверки ошибочно валидного документа в ситуации, приведённой OKEN, я предлагаю использовать проверку на doc.Size > 0, она будет быстрее IsEmpty(ND.Items). Если, конечно, в этой кривой ситуации и Size не "кривой". OKEN, есть возможность проверить?
     
  17. hosm

    hosm * so what *

    Регистрация:
    18 май 2009
    Сообщения:
    2.450
    Симпатии:
    7
    у меня ща нет времени - запарка жуткая, после 25го. и 8ки нет.
     
  18. Darker

    Darker Гость

    По обходу документов-ответов: вчера на одном доке моя рекрсивная функция зациклилась.
    Оказалось что-когда создается конфликт при галочке merge conflicts документ становится своим же потомком.
    После этого решил сравнивать REF c UniversalID текущего дока
     
  19. VladSh

    VladSh начинающий
    Lotus team

    Регистрация:
    11 дек 2009
    Сообщения:
    1.251
    Симпатии:
    2
    nvy
    Хорошее решение! Осталось только определить, сколько времени занимает отработка метода Size... :)

    Darker
    Если можно, поподробнее:
    - что за код зациклился?
    - где изменили проверку?
     
  20. ToxaRat

    ToxaRat Чёрный маг
    Lotus team

    Регистрация:
    6 ноя 2007
    Сообщения:
    3.046
    Симпатии:
    18
    есть более злое решение :)

    часто у меня возникает ситуация когда один документ становится респонсом на другой, который на деле является 20м потомком этого
    поэтому пришлось в рекурсию еще и статистический счеткик ввести, чтобы рекурсия далья 255 колена обрывалась ;)
     
Загрузка...

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