Как сравнить два ричтекстовых поля?

Gandliar

Lotus Team
16.02.2004
552
26
Здравствуйте!
Подскажите пожалуйста, как сравнить два ричтекстовых поля. лотус 8.5.3
Либо подсказать иной вариант решения для следующей задачи.

Есть сервер и клиенты.
Один и тот же документ может меняться на сервере и на клиенте (разные поля) напрямую на сервере или на клиенте через репликацию. То есть в стандартном случае может возникнуть ситуация при сохранении документа когда выдается системное сообщение - что ктото уже отредактировал документ, пока его редактировали вы.

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

Gandliar

Lotus Team
16.02.2004
552
26
Пока решил сделать следующим образом
на событие entering поля запоминаю текущее значение
на событие ончейндж поля записываю текущее поле в список изменившихся полей в памяти
в результате на событие onSave формы имею список изменившихся полей.

Кстати в отладчике почему то не всегда срабатывает событие entering. Без в ключенного отладчика работает отлично.

Может есть вариант лучше?
 
  • Нравится
Реакции: The Codeby
R

romych2004

Ну еще вариант попробовать с ValueLength и Text методами

Но вообще, работа с событием мне больше нравится
А зачем в этой цепочке entering?
 

Gandliar

Lotus Team
16.02.2004
552
26
Ну еще вариант попробовать с ValueLength и Text методами

Но вообще, работа с событием мне больше нравится
А зачем в этой цепочке entering?

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

garrick

Lotus Team
26.10.2009
1 306
147
А ончейндж сработает если сразу после редактирования поля нажать какую-нибудь кнопку типа "ОК", которая закрывает форму, без перехода в другое поле?
 

Gandliar

Lotus Team
16.02.2004
552
26
А ончейндж сработает если сразу после редактирования поля нажать какую-нибудь кнопку типа "ОК", которая закрывает форму, без перехода в другое поле?

Срабатывает на кнопку save и на комбинацию ctrl+s, если поле менялось, это я проверял :)
 

ToxaRat

Чёрный маг
Green Team
06.11.2007
3 332
42
через DXML выгружать док в стрим, дальше работать как со строкой
 

Gandliar

Lotus Team
16.02.2004
552
26
через DXML выгружать док в стрим, дальше работать как со строкой

Это имеется ввиду?

Call uidoc.refresh(True)
Dim sOutput As String
Dim exporter As NotesDXLExporter
Set exporter = session.CreateDXLExporter
sOutput = exporter.Export (doc)

а затем достать содержимое поля по тэгам для сравнения?
 

ToxaRat

Чёрный маг
Green Team
06.11.2007
3 332
42
да, только док нужно сохранить РТ поля не фиксируются пока они не сохранены

большую часть тегов можно вырезать - если не нужно отслеживать форматирование
и получите чистое содержимое

стринг до 2 гиг позволит вам фактически всё фиксировать

там же отдельными тегами и вложения найдёте
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 877
598
там же отдельными тегами и вложения найдёте
чтобы лишнее не гонять и не держать в памяти - можно использовать SAX
теги для файлов
XML:
<item name='$FILE' summary='true' sign='true' seal='true'><object><file hosttype='msdos'
compression='none' flags='sign storedindoc' encoding='none' name='catalogCIS.zip'>
<created><datetime dst='true'>20080731T010008,01+04</datetime></created>
<modified><datetime dst='true'>20080731T010008,03+04</datetime></modified>
на <filedata> - обрывать выгрузку
тогда и
стринг до 2 гиг позволит вам фактически всё фиксировать
не нужно
 

Gandliar

Lotus Team
16.02.2004
552
26
Что получилось в итоге:
Событие ончейндж использовать не удалось. Если не сохранять форму (на onsave continue = false) при нажатии на крестик или кнопки эскейп, это событие не срабатывает.

Написал класс, который если документ новый, просто сохраняет док на диск. Если документ не новый - документ по форме не сохраняет, находит документ на диске, проверяет список "проверяемых полей" с помощью дхл экспортера, и если они изменились по сравнению с открытым документом, сохраняет измененные поля в документ на диске.

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

Если кому такое надо - могу выложить скрипт.

Всем спасибо, кто давал советы.
 

Gandliar

Lotus Team
16.02.2004
552
26
Пожалуйста. Критикуйте :)

Код:
%REM
   Library documentManagerLib
   Created Dec 14, 2016 by Administrator/Gandliar
   Description: Comments for Library
%END REM
Option Public
Option Declare

Dim dm As DocumentManager

%REM
   Class DocumentManager
   Description: Класс сохранения измененных полей документа
   
   Необходимо в базу данных добавить вид "(all~unid)" с отсортированным первым столбцом с формулой @Text(@DocumentUniqueID)
   
   Необходимо для формы установить "Merge\NoConflict"
   
   Необходимо добавить на форму cfd поле saveOptions со значением ""
   
   Необходимо добавить в событие queryOpen:    
       Set dm = New DocumentManager(Source)
       Call dm.addField("a")
       Call dm.addField("b")
       Call dm.addField("c")
           
       где а,b,c имена проверяемых и сохраняемых полей.
   
   Необходимо добавить в событие querySave:
       Continue = False   
       Call dm.save()       
       
   Необходимо добавить в событие queryClose:
       Continue = dm.queryClose()
     
%END REM
Class DocumentManager
   Private uidoc As NotesUIDocument
   Private doc As NotesDocument   
   %REM
       Содержит список проверяемых полей
   %END REM
   Private   fieldNameList List As String
   %REM
       Содержит список изменившихся полей
   %END REM
   Private changeFieldNameList List As String
   
   %REM
       Sub New
       Description: Создание менеджера документа
   %END REM
   Sub New (source As NotesUIDocument)
       Set me.uidoc = source       
   End Sub
   
   %REM
       Sub addField
       Description: Добавление полей для проверки и сохранения
   %END REM
   Sub addField(fieldName As String)
       me.fieldNameList(fieldName) = fieldName
   End Sub   
   
   %REM
       Function checkField
       Description: Проверяет, изменилось ли конкретное поле
   %END REM
   Private Function checkField(fieldName As String, currentDocString As String, sourceDocString As String) As Boolean       
       Dim currentValue As String
       currentValue = StrRight$(currentDocString, {<item name='} + fieldName + {'>})
       currentValue = StrLeft$(currentValue,{</item>})
       currentValue = {<item name='} + fieldName + {'>}+currentValue + {</item>}
       If InStr(sourceDocString,currentValue)>1 Then checkField = True       
   End Function
   
   %REM
       Function checkFields
       Description: Проверяет, изменились ли поля
   %END REM
   Private Function checkFields(docSource As NotesDocument) As Boolean
       Dim session As New NotesSession       
       Dim exporter As NotesDXLExporter           
       Set exporter = session.CreateDXLExporter
       Dim currentDocString As String
       currentDocString = exporter.Export(me.doc)
       Dim sourceDocString As String
       sourceDocString = exporter.Export(docSource)
       Delete exporter       
       
       ForAll f In me.fieldNameList
           If Not me.checkField(f, currentDocString, sourceDocString) Then
               me.changeFieldNameList(f) = f               
               checkFields = true               
           End If                   
       End ForAll       
       
   End Function
   
   
   %REM
       Function save
       Description: Сохраняет документ
   %END REM
   Function save() As Boolean
       'Проверим на формулы полей и обновим значение ричтекстовых полей
       On Error 4412 GoTo errHandler
       Call me.uidoc.Refresh(true)
       Set me.doc = me.uidoc.Document
       'Проверка прошла успешно       
       If me.doc.Isnewnote Then
           Call doc.save(True, True)           
       Else
           'Найдем исходный документ на диске
           Dim view As NotesView
           Set view = me.doc.Parentdatabase.Getview("all~unid")
           Dim i As Integer
           For i = 0 To 10
               Call view.Refresh()
               Dim docSource As NotesDocument
               Set docSource = view.Getdocumentbykey(me.doc.Universalid, True)
               If me.checkFields(docSource) Then           
                   'Запишем в него содержание изменившихся полей
                   ForAll f In me.changeFieldNameList
                       Dim item As NotesItem
                       Set item = me.doc.Getfirstitem(f)
                       If docSource.Hasitem(f) Then Call docSource.Removeitem(f)   
                       Call item.Copyitemtodocument(docSource, f)
                   End ForAll
                   If docSource.save(false, false) Then
                       Dim flag As Boolean
                       flag = true
                       Exit For
                   Else
                       Delete docSource
                   End If
               Else
                   flag = True
                   Exit For   
               End If               
           Next i
           
           If Not flag Then
               MessageBox "Не удалось сохранить документ. Попробуйте еще раз позже.", 16, "Операция прервана!"
               Exit Function                                   
           End If                       
       End If
       'Очистим список изменившихся полей
       Erase me.changeFieldNameList
       save = True
ex:
       Exit function
errHandler:       
       Resume ex           
   End Function
   
   %REM
       Function queryClose
       Description: Обработка события queryClose
   %END REM
   Function queryClose() As Boolean
       If me.uidoc.Modifiedsincesaved Then
           Dim result As Integer
           result = MessageBox("Документ был изменен. Сохранить изменения?", 32+3, "Внимание!")
           Select Case result
           Case 6   'да
               queryClose = me.save()
           Case 7   'нет
               queryClose = true
           Case 2   'отмена
               queryClose = false   
       End Select   
       Else
           queryClose = True           
       End If       
   End Function   
End Class
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 877
598
Пожалуйста. Критикуйте
надеялся увидеть парсинг... ;)
хотя бы DOM (с аттачами будет память забивать), лучше - SAX
регистрируем появление атрибутов для item (там имя будет) и берем значения...
 

Gandliar

Lotus Team
16.02.2004
552
26
Мне почему то кажется, что разобрать стринг будет быстрее, чем использовать парсеры.
Из моих опытов, парсер выгодно использовать когда весь хмл файл надо считать и последовательно обновить инфу например.
Причем sax, особенно когда большой файл.
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 877
598
Мне почему то кажется, что разобрать стринг будет быстрее, чем использовать парсеры.
Из моих опытов, парсер выгодно использовать когда весь хмл файл надо считать и последовательно обновить инфу например.
Причем sax, особенно когда большой файл.
если у вас будут аттачи - ох и незавидная участь стринга ;)
 
30.05.2006
1 345
12
ЕСЛИ надо сравнивать только тексты и без учёта форматирования, то есть "собака" abstract
 
30.05.2006
1 345
12
ограничение на 64К у нее
Это размер результата, а не аргументов. Абстрагируемые поля м.б. и больше. Но не гиговые, это да
[doublepost=1486079776,1486060913][/doublepost]А как вам такая идейка: сосчитать хеш rtitem-а
Вот их и сравнивать (вспомнив предварительно, кто у нас хеши считать умеет, без ограничений 64к)
 
Последнее редактирование:
Мы в соцсетях:

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