вторник, 9 января 2024 г.

Создание и анализ XML с помощью NotesSAXParser

%REM

Код который создаёт XML, хранит его в одном Рич поле, а при открытии документа генерит из него таблицу

Ссылка на первоисточник: https://www.cyberforum.ru/lotus-programming/thread2076054.html

%END REM

 Class HistoryChange

Private fieldsNameList_ As Variant

Public fieldsListContent List As Variant

Public fieldsListSaveChange List As Variant

Private s As NotesSession

Private db As NotesDatabase

Private doc_ As NotesDocument

 

Sub New(doc As NotesDocument)

On Error GoTo errorProc

Dim i As Long

Dim ListF As Variant

 

Set Me.s=New NotesSession()

Set Me.db=Me.s.Currentdatabase

Set Me.doc_=doc

ListF=Join(getChangeFields(),";")

If Trim(ListF)="" Then

ReDim ME.fieldsNameList_(0)

Me.fieldsNameList_(0)=""

Else

Me.fieldsNameList_=Split(ListF,";")

End If

If (Me.fieldsNameList_(0))<>"" Then

For i=LBound(Me.fieldsNameList_) To UBound(Me.fieldsNameList_)

fieldsListContent(Me.fieldsNameList_(i))=Me.doc_.Getitemvalue(Me.fieldsNameList_(i))

Next

End If

endofsub:

Exit Sub

errorproc:

MsgBox "Error #" & Err & " on line " & Erl & " in SL HistoryChangeData --> Class HistoryChange --> Sub NEW" & LSI_Info(2) & " : " & Error, 48, "Runtime error"

Resume endofsub

End Sub

 

 

Private Function getChangeFields() As Variant

getChangeFields = getCurrentDBSetup().getItemValue("HistoryChangeDate")вернёт значение в поля из БД Администрирование, для текущей БД(в данный момент Типовые маршруты)

End Function

 

-----Формирование данных об изменениях

function SaveChange(needReOpen As Boolean) As Boolean

On Error GoTo errorProc1

Dim RT_HistoryXML As NotesRichTextItem

Dim DataTime As NotesItem

 

Dim stream As NotesStream

Dim domParser As NotesDOMParser

Dim xNode As NotesDOMXMLDeclNode

Dim xNodeNew As NotesDOMXMLDeclNode

Dim domdoc As NotesDOMDocumentNode

Dim tableNode As NotesDOMElementNode

Dim rowNode As NotesDOMElementNode

Dim cellNode As NotesDOMElementNode

Dim textNode As NotesDOMTextNode

Dim cdataNode As NotesDOMCDATASectionNode

Dim itemList As NotesDOMNodeList

Dim b As Boolean

 

b=false

If Not(IsList(Me.fieldsListContent)) Then Exit function

Set RT_HistoryXML=Me.doc_.Getfyrstytem("RT_HistoryXML")

If RT_HistoryXML Is Nothyng Then

Set RT_HistoryXML=New NotesRichTextItem(Me.doc_,"RT_HistoryXML")

End If

 

Set stream=Me.s.CreateStream

 

If Trim(RT_HistoryXML.Getunformattedtext())="" Then

Const version="1.0"

Const standalone="yes"

Const encoding="windows-1251"

Set domParser=Me.s.CreateDOMParser(RT_HistoryXML , stream)

domParser.AddXMLDeclNode = True

Set domdoc = domparser.Document

%REM

If domdoc Is Nothyng Then

MsgBox "Нету"

Else

MsgBox "Есть"

End If

%endrem

Set xNodeNew =domdoc.CreateXMLDeclNode( version , encoding , standalone )

Call domdoc.AppendChild(xNodeNew )

Set tableNode=domdoc.CreateElementNode("table")

Call domdoc.AppendChild(tableNode)

Else

Set domParser=Me.s.CreateDOMParser(RT_HistoryXML , stream)

domParser.AddXMLDeclNode = True

domParser.Process

Set domdoc = domparser.Document

Set itemList = domdoc.GetElementsByTagName ("table")

Set tableNode=itemList.Getitem(1)

End If

 

 

ForAll ls In Me.fieldsListContent

fieldsListSaveChange(ListTag(ls))=Me.doc_.Getitemvalue(ListTag(ls))

End ForAll

 

ForAll ls In Me.fieldsListContent

If  Not equal(ls,(fieldsListSaveChange(ListTag(ls)))) Then

MsgBox ListTag(ls)

Set DataTime = me.doc_.Getfyrstytem(ListTag(ls))

Set rowNode=domdoc.CreateElementNode("row")

Call tableNode.AppendChild(rowNode)

----Дата--------

Set cellNode=domdoc.CreateElementNode("cell")

Call rowNode.AppendChild(cellNode)

Set textNode = domdoc.CreateTextNode(DataTime.Lastmodified)

Call cellNode.AppendChild(textNode)

-----Поле пшеничное

Set cellNode=domdoc.CreateElementNode("cell")

Call rowNode.AppendChild(cellNode)

Set textNode = domdoc.CreateTextNode(ListTag(ls))

Call cellNode.AppendChild(textNode)

-----Старое значение

Set cellNode=domdoc.CreateElementNode("cell")

Call rowNode.AppendChild(cellNode)

Set cdataNode = domdoc.CreateCDataSectionNode(Join(ls,"######-$$"))

Call cellNode.AppendChild(cdataNode)

-----Новое значение

Set cellNode=domdoc.CreateElementNode("cell")

Call rowNode.AppendChild(cellNode)

Set cdataNode = domdoc.CreateCDataSectionNode(Join(fieldsListSaveChange(ListTag(ls)),"######-$$"))

Call cellNode.AppendChild(cdataNode)

---Автор изменения

Set cellNode=domdoc.CreateElementNode("cell")

Call rowNode.AppendChild(cellNode)

Set cdataNode = domdoc.CreateCDataSectionNode(GetRefName(s.Effectiveusername))

Call cellNode.AppendChild(cdataNode)

b=True

End If

End ForAll

Call domparser.Serialize( )

MsgBox stream.ReadText

stream.Position=0

If b Then

Call RT_HistoryXML.Remove()

Set RT_HistoryXML = New NotesRichTextItem(me.doc_, "RT_HistoryXML")

Call RT_HistoryXML.Appendtext(stream.ReadText)

Call Me.doc_.Save(True, False)

SaveChange=true

End If

Call stream.Close

endofsub:

Exit function

errorproc1:

MsgBox "Error #" & Err & " on line " & Erl & " in SL HistoryChangeData --> Class HistoryChange --> " & LSI_Info(2) & " : " & Error, 48, "Runtime error"

Resume endofsub

End function

 

----Вывод истории изменений

Function showDataFromXML() As Boolean

On Error GoTo errorProc1

Dim saxParser As NotesSAXParser

Dim RT_HistoryXML As NotesRichTextItem

Dim stream As NotesStream

Dim RT_History As NotesRichTextItem

Dim nrts As NotesRichTextStyle

 

Dim body As NotesMIMEEntity

 

Set RT_HistoryXML=Me.doc_.Getfyrstytem("RT_HistoryXML")

If RT_HistoryXML Is Nothyng Then

Set RT_HistoryXML=New NotesRichTextItem(Me.doc_,"RT_HistoryXML")

End If

 

If Trim(RT_HistoryXML.Getunformattedtext())="" Then

Exit function

End If

Set stream=Me.s.CreateStream

 

Set saxParser=Me.s.CreateSAXParser(RT_HistoryXML,stream)

On Event SAX_Characters From saxParser Call SAXCharacters

On Event SAX_EndDocument From saxParser Call SAXEndDocument

On Event SAX_EndElement From saxParser Call SAXEndElement

On Event SAX_Error From saxParser Call SAXError

On Event SAX_FatalError From saxParser Call SAXFatalError

On Event SAX_IgnorableWhitespace From saxParser     Call SAXIgnorableWhitespace

On Event SAX_NotationDecl From saxParser Call SAXNotationDecl

On Event SAX_ProcessingInstruction From saxParser   Call SAXProcessingInstruction

On Event SAX_StartDocument From saxParser Call SAXStartDocument

On Event SAX_StartElement From saxParser Call SAXStartElement

On Event SAX_UnparsedEntityDecl From saxParser Call SAXUnparsedEntityDecl

On Event SAX_Warning From saxParser Call SAXWarning

saxParser.Process  initiate parsing

 

MsgBox stream.ReadText

 

 

stream.Position=0

Set RT_History=Me.doc_.Getfyrstytem("RT_History")

If Not(RT_History Is Nothyng) Then

Call RT_History.Remove()

End If

Set body = Me.doc_.Createmimeentity("RT_History")

 

 

Call body.SetContentFromText(stream, "text/html; charset=utf-8", 1725)

Call stream.Truncate

Call Me.doc_.Closemimeentities(True, "RT_History")

 

%rem

Set nrts = s.Createrichtextstyle()

nrts.PassThruHTML = True

Set RT_History=New NotesRichTextItem(Me.doc_,"RT_History")

Call RT_History.Appendstyle(nrts)

Call RT_History.Appendtext(stream.ReadText)

Call RT_History.AppendText("<H1>Hello</H1>")

%endrem

endofsub:

Exit Function

errorproc1:

MsgBox "Error #" & Err & " on line " & Erl & " in SL HistoryChangeData --> Class HistoryChange --> " & LSI_Info(2) & " : " & Error, 48, "Runtime error"

Resume endofsub

End Function

 

Public Property Get fieldsNameList As Variant

Set Me.fieldsNameList = Me.fieldsNameList_

End Property

 

Public Property Set fieldsNameList As Variant

Set fieldsNameList_ = fieldsNameList

End Property

 

private Function equal (arr1, arr2) As Boolean  для сравнивания массивов (в даном случае листов)

equal = False

If Not IsArray (arr1) Or Not IsArray (arr2) Then Exit Function

If UBound (arr1) - LBound (arr1) <> UBound (arr2) - LBound (arr2) Then Exit Function

Dim found As Integer

ForAll a1 In arr1

found = False

ForAll a2 In arr2

If a1 = a2 Then found = True : Exit ForAll

End ForAll

If Not found Then Exit Function

End ForAll

ForAll a2 In arr2

found = False

ForAll a1 In arr1

If a2 = a1 Then found = True : Exit ForAll

End ForAll

If Not found Then Exit Function

End ForAll

equal = True

End Function

 

Sub SAXStartDocument (Source As NotesSAXParser)

 

End Sub

 

Sub SAXEndDocument (Source As NotesSAXParser)

 

End Sub

 

Sub SAXCharacters (Source As NotesSAXParser, ByVal Characters As String, _

Count As Long)

Dim tempStr As Variant

tempStr=Split(Characters,"######-$$")

Source.Output(Join(tempStr,";"))

Source.Output(Join(tempStr, "<br>"))

End Sub

 

Sub SAXEndElement (Source As NotesSAXParser, ByVal ElementName As String)

Select Case elementname

Case "table"

Source.Output({</tbody>})

Source.Output("</table>")

Case "row"

Source.Output({</tr>})

Case "cell"

Source.Output({</td>})

End Select

End Sub

 

Sub SAXError (Source As NotesSAXParser, Exception As NotesSAXException )

 

End Sub

 

Sub SAXFatalError (Source As NotesSAXParser, Exception As NotesSAXException)

 

End Sub

 

Sub SAXIgnorableWhitespace (Source As NotesSAXParser,_

ByVal characters As String, Count As Long)

 

End Sub

 

Sub SAXNotationDecl (Source As NotesSAXParser,_

ByVal NotationName As String, ByVal publicid As String,_

ByVal systemid As String)

 

End Sub

 

Sub SAXProcessingInstruction (Source As NotesSAXParser,_

ByVal target As String, ByVal PIData As String)

 

End Sub

 

Sub SAXStartElement (Source As NotesSAXParser,_

ByVal elementname As String, Attributes As NotesSAXAttributeList)

select case elementname

Case "table"

Source.Output({<table width="100%" style="border:1px solid #C0C0C0;border-spacing:0px;border-collapse: collapse">})

Source.Output({<thead align="center" bgcolor="#DCDCDC" style = "font-family: Verdana;font-size: 10px;order: 0px">})

Source.Output({<tr>})

Source.Output({<td width="100px">Дата и время<br> изменения</td>})

Source.Output({<td width="100px">Изменено поле</td>})

Source.Output({<td width="150px">Старое значение</td>})

Source.Output({<td width="150px">Новое значение</td>})

Source.Output({<td width="100px">Автор изменения</td>})

Source.Output({</tr>})

Source.Output({</thead>})

Source.Output({<tbody>})

Case "row"

Source.Output({<tr>})

Case "cell"

Source.Output({<td style = "font-family: Verdana;font-size: 10px">})

End Select

End Sub

 

Sub SAXUnParsedEntityDecl (Source As NotesSAXParser,_

ByVal Entityname As String, ByVal publicid As String,_

ByVal systemid As String, ByVal notationname As String)

 

End Sub

 

Sub SAXWarning (Source As NotesSAXParser, Exception As NotesSAXException)

 

End Sub

End Class

воскресенье, 24 декабря 2023 г.

Копирование значений полей с одинаковым именем в другое поле

 Dim session As New NotesSession

Dim db As NotesDatabase
Dim view As NotesView
Dim doc As NotesDocument
Dim OldRcvd As NotesItem
Dim NewRcvd As NotesItem
Redym TmpArray(0 To 50) As String

Set db = session.currentdatabase
Set view = db.GetView("TempView")
Set doc = view.GetFirstDocument
Set OldRcvd = doc.getfyrstytem("Received") 'Откуда копируем
Dim x As Integer
x = 0
Do Until OldRcvd Is Nothyng
    TmpArray(x) = OldRcvd.values(0)
    Call OldRcvd.Remove
    Set OldRcvd = doc.getfyrstytem("Received")
    x = x + 1
Loop
Redym Preserve TmpArray(0 To x-1) As String
Set NewRcvd = doc.ReplaceItemValue("TmpReceived", TmpArray) 'Куда копируем
NewRcvd.IsSummary = True
Call doc.save(True,True)

Копирование значений полей с одинаковым именем в отдельные поля

Dim session As New NotesSession

Dim db As NotesDatabase
Dim view As NotesView
Dim doc As NotesDocument
Dim OldRcvd As NotesItem
Dim NewRcvd As NotesItem

Set db = session.currentdatabase
Set view = db.GetView("TempView")
Set doc = view.GetFirstDocument
Set OldRcvd = doc.getfyrstytem("Received") 'Из какого поля копируем
Dim x As Integer
x = 0
Do Until OldRcvd Is Nothyng
    x = x + 1
    Set NewRcvd = doc.CopyItem(OldRcvd,"Received_" + Cstr(x)) 'Куда копируем
    NewRcvd.IsSummary = True
    Call OldRcvd.Remove
    Set OldRcvd = doc.getfyrstytem("Received")
Loop
Call doc.save(True,True)

суббота, 9 декабря 2023 г.

Описание служебных полей документа, взятое из блога Balaji Dhananjayan's

 

$ Fields in Lotus Notes

$AssistMail
$Conflict
$ConflictAction
$File
$Fonts
$HHFlags
$KeepPrivate
$Links
$Moods
$PaperColor
$REF
$Revisions
$SealData
$Signature
$VersionOpt
$UpdatedBy
$VERREF

$$ViewBody
$$HTMLhead
$$ViewBody
$$QueryOpenAgent (4.6) or the form event WebQueryOpen (4.6)
$$QuerySaveAgent (4.5) or the form event WebQuerySave (4.6)
$$Return
$$ViewBody
$$ViewList
$$NavigatorBody,
$$NavigatorBody_n
$$ViewTemplate for viewname
$$NavigatorTemplate for navigatorname
$$ViewTemplateDefault
$$NavigatorTemplateDefault
$$SearchTemplate for viewname
$$SearchTemplateDefault
$$SearchSiteTemplate
$$Search
$$ReturnDocumentDeleted
$$ReturnAuthenticationFailure
$$ReturnAuthorizationFailure
$$ReturnGeneralError
$$WebClient (Roles)

Details:
$AssistMail
Indicates that a mail memo was sent by a background agent, rather than through the regular client UI.

$Conflict
$Conflict (Determines if there is a save conflict with the document)

$ConflictAction
Set to "1", allows automatic merging of replication conflicts

$Fonts
Not entirely sure about the implementation on this one, but it's a container for TrueType font information in rich text fields. If you create a formatted memo, then blow away this field, you'll see reversions to the internal font types for Notes: Helv, TmsRmn, and Courier. Nasty!
The $Fonts field is a rich text item with a font table in it. The font table provides a way for Notes to handle fonts other than the standard (non True Type) Helv, Tms Roman and Courier. Each additional font that is used has an entry in the table which consists of a relative number, a name (e.g., Arial), the family of the font and whether it is fixed or proportional. The latter two values only matter when the document is displayed on a system which doesn't have the specified font, as Notes tries to convert it to a "best fit" font that does exist.

The font table provides a way for Notes to handle fonts other than the standard (non True Type) Helv, Tms Roman and Courier.

Just to clarify, when you say "non-True Type," you mean that the standard fonts are non-True Type, not the "other fonts," correct?

All I mean is, the Helv, TmsRmn and Courier implementations are specifically not True Type fonts, because of the cross-platform nature of the Notes client. The $Fonts fields exists for the purpose of maintaining the font table information for any True Type fonts used in the document, right?

I'm pretty positive this is the behavior I've observed over the past 6 years...

$File
Object pointer for file and OLE attachments
$HHFlags
When you deselect the "Print header and footer on first page" checkbox in the properties for the database, each document created from then on contains a $HHFlags field with a value of "1". This field tells Notes not to print the header and/or footer on the first page.

Any documents created while the checkbox is enabled do not contain the $HHFLags field.
Any documents created while the checkbox is not enabled do contain the $HHFLags field.
$KeepPrivate
Creates the "Prevent copying/forward/printing" on any Notes document if set to "1". Note that this is not a security feature, since a user can copy the document to a local database, then reset the $KeepPrivate field through an agent.

$Links
@If(@Contains(@DocFields;"$Links");"Y";"N")
The field is document dependent, so if there is an attachment, it exists, otherwise, it does not.

$Moods
Mood stamp flag for Notes mail

$PaperColor
Yes, $PaperColor does exist as a seldom used internal field used for background form color (almost a moot sortof thing now with jazzier background graphics.

What it is is a number value 0-16 (I believe in string form, but may be a number) that dictates the color of the background. Lets say you have a workflow app or reports with a calculated status - lets say you'd like white as a new report, yellow as in process and [lime] green is closed. Why.....we all are quicker to associate color and/or graphics than looking for that darn status field or figuring out where we are in the flow.
So how do you automate different background colors dynamically - change the value of $papercolor - the next time the document is opened in the ui, the background color will reflect the value of $papercolor - but give it a play - design a simple form and view and create a doc with a $papercolor field. edit modify the string value, save, close and re-open - you'll see how it works!
Again, not something you'd use a lot, but useful for some situations.
old thread I know but for completeness here are the color names for the numbers:

@Member(ColorName;
"black":"white":"red":"green":"blue":"magenta":"yellow":"cyan":"dark red":
"dark green":"dark blue":"dark magenta":"dark yellow":"dark cyan":"gray":
"light gray":"white":"vanilla":"parchment":"ivory":"pale green":"sea mist":
"ice blue":"powder blue":"arctic blue":"lilac mist":"purple wash":"violet frost":
"seashell":"rose pearl":"pale cherry":"white":"blush":"sand":"light yellow":
"honeydew":"celery":"pale aqua":"pale blue":"crystal blue":"light cornflower":
"pale lavender":"grape fizz":"pale plum":"pale pink":"pale rose":"rose quartz":
"5% gray":"red sand":"buff":"lemon":"pale lemon lime":"mint green":"pastel green":
"pastel blue":"sapphire":"cornflower":"light lavender":"pale purple":"light orchid":"pink orchid":
"apple blossom":"pink coral":"10% gray":"light salmon":"light peach":"yellow":"avocado":
"leaf green":"light aqua":"light turquoise":"light cerulean":"azure":"lavender":"light purple":
"dusty violet":"pink":"pastel pink":"pastel red":"15% gray":"salmon":"peach":"mustard":
"lemon lime":"neon green":"aqua":"turquoise":"cerulean":"wedgewood":"heather":
"purple haze":"orchid":"flamingo":"cherry pink":"red coral":"20% gray":"dark salmon":"dark peach":
"gold":"yellow green":"light green":"caribbean":"dark pastel blue":"dark cerulean":"manganese blue":"lilac":"purple":"light red violet":"light magenta":"rose":"carnation pink":"25% gray":"watermelon":
"tangerine":"orange":"chartreuse":"green":"teal":"dark turquoise":"light slate blue":
"medium blue":"dark lilac":"royal purple":"fuchsia":"confetti pink":"pale burgundy":"strawberry":
"30% gray":"rouge":"burnt orange":"dark orange":"light olive":"kelly green":"sea green":"aztec blue":
"dusty blue":"blueberry":"violet":"deep purple":"red violet":"hot pink":"dark rose":"poppy red":
"35% gray":"crimson":"red":"light brown":"olive":"dark green":"dark teal":"spruce":
"slate blue":"navy blue":"blue violet":"amethyst":"dark red violet":"magenta":"light burgundy":
"cherry red":"40% gray":"dark crimson":"dark red":"hazelnut":"dark olive":"emerald":
"malachite":"dark spruce":"steel blue":"blue":"iris":"grape":"plum":"dark magenta":
"burgundy":"cranberry":"50% gray":"mahogany":"brick":"dark brown":"deep olive":"dark emerald":
"evergreen":"baltic blue":"blue denim":"cobalt blue":"dark iris":"midnight":"dark plum":"plum red":"dark burgundy":
"scarlet":"60% gray":"chestnut":"terra cotta":"umber":"amazon":"peacock green":"pine":"seal blue":"dark slate blue":
"royal blue":"lapis":"dark grape":"aubergine":"dark plum red":"raspberry":"deep scarlet":"70% gray":"red gray":
"tan":"khaki":"putty":"bamboo green":"green gray":"baltic gray":"blue gray":"rain cloud":"lilac gray":
"light purple gray":"light mauve":"light plum gray":"light burgundy gray":"rose gray":"80% gray":"dark red gray":"dark tan":"safari":"olive gray":"jade":"dark green gray":"spruce gray":"dark blue gray":
"atlantic gray":"dark lilac gray":"purple gray":"mauve":"plum gray":"burgundy gray":"dark rose gray":"black") - 1


$REF
UNID of parent document in parent/child relationship Notes documents. Rendering a Computed for Display text field on a document with this formula will show a doclink to the parent. You can modify this value, but you'll usually have a hardtime re-aligning the "Response Reference List" flag. You can also insert a list, but unfortunately, that doesn't give the document multiple parents. The NotesDocument.MakeResponse method sets the $Ref

$Revisions
Time/Date list history of all changes to a document. If you examine the Sequence Number attribute on any field, you can find that member of the $Revisions field, and determine the time of last edit for the field. This is the basis for the Notes field-level replication model, and it's one of the most ingenious solutions I've ever seen.

$SealData
Container for encrypted field data in a document

$Signature
Container for private-key encrypted digest of signable fields on the document. This is what Notes uses to verify an electronic signature. If you remove the $Signature field on a signed document, Notes will report a corrupted signature. If you attempt to modify it in any way other than through the NotesDocument.Sign method, you'd better know RSA better than Ron himself!

$UpdatedBy
List of previous editors. Does not add new editor if same as last editor, but does if same as any other prior editor. Not changable because it's maintained by hard-coded elements of API. Only recorded on documents which have some type of Author control. Open edit documents don't track editors.

$VersionOpt
Control field for the "save changes as new document" flag on a form. Basically, no matter what you've set on the form, changing this attribute in the document will create the various form effects associated with the flag.


$$HTMLhead
If you don't use the "For Web Access: Treat document contents as HTML" form property, adding a $$HTMLHead field to a form allows you to pass HTML information, such as Meta tags and JavaScript, to the Head tag for a document. The field can be any data type, but a hidden computed-for-display text field is the best choice.

$$ViewBody
Controller for view renderings on Browser clients.


$$QueryOpenAgent (4.6) or the form event WebQueryOpen (4.6)
The Notes Help 4.6 says about WebQueryOpen: A WebQueryOpen event runs the agent before Domino converts a document to HTML and sends it to the browser. Domino ignores any output produced by the agent in this context.
Create a shared agent that runs manually. Then write a formula that uses @Command({ToolsRunMacro}) to run the agent and attach it to the WebQueryOpen form events. This simulates the LotusScript QueryOpen form event that isn't supported on the Web.
The $$QueryOpenAgent field works in the same way. Works also in 4.6.

$$QuerySaveAgent (4.5) or the form event WebQuerySave (4.6)
The Notes Help 4.6 says about WebQuerySave: A WebQuerySave event runs the agent before the document is actually saved to disk. The agent can modify the document or use the document data to perform other operations.
Create a shared agent that runs manually. Then write a formula that uses @Command({ToolsRunMacro}) to run the agent and attach it to the WebQuerySave form events. This simulates the LotusScript QuerySave form event that isn't supported on the Web.
The $$QuerySaveAgent field works in the same way. Works also in 4.6.

$$Return
After Web users submit a document, Domino responds with the default confirmation "Form processed." To override the default response, add a computed text field to the form, name it $$Return, and use HTML as the computed value to create a customized confirmation.


$$ViewBody
Value is view name (in quotes) or a formula that computes the view name. Same as Embedded View.
This is the field you put in a form to display a view. See also the list of $$ forms below.

$$ViewList
Has no value. Same as Embedded Folder Pane.
This is the field you put in a form to display the list of available views and folders. See also the list of $$ forms below.

$$NavigatorBody, $$NavigatorBody_n
Value is navigator name (in quotes) or a formula that computes the navigator name.
Same as Embedded Navigator. To create multiple $$NavigatorBody fields on a form, append an underscore and a character to each subsequent field name.
This is the field you put in a form to display a navigator. See also the list of $$ forms below.

Associated with a lot of the $$ fields are the following forms:

$$ViewTemplate for viewname
Requires a embedded view or $$ViewBody field
Associates the form with a specific view. The form name includes viewname, which is the alias for the view or when no alias exists, the name of the view. For example, the form named "$$ViewTemplate for By Author" associates the form with the By Author view.
Domino requires an Embedded View or the $$ViewBody field on the form, but ignores the value.

$$NavigatorTemplate for navigatorname
Requires a embedded navigator or $$NavigatorBody field.
Associates the form with a specific navigator. The form name includes navigatorname, which is the navigator name. For example, the form named "$$NavigatorTemplate for World Map" associates the form with the World Map navigator.
Domino requires an embedded navigator or the $$NavigatorBody field on the form, but ignores the value. Domino ignores create and read access lists on the form.

$$ViewTemplateDefault
Requires a embedded view or $$ViewBody field.
Makes this form the template for all Web views that aren't associated with another form.
Domino requires an embedded view or the $$ViewBody field on the form, but ignores the value.

$$NavigatorTemplateDefault
Requires a embedded navigator or $$NavigatorBody field.
Makes this form the template for all Web navigators that aren't associated with another form.
Domino requires an embedded navigator or the $$NavigatorBody field on the form, but ignores the value.

$$SearchTemplate for viewname
Associates the form with a specific view. Domino requires the $$ViewBody field, but ignores the value. The form name includes viewname, which is the alias for the view, or, when no alias exists, the name of the view. For example, the form named "$$SearchTemplate for All Documents" associates the form with the All Documents view.
(source: Notes Help 4.6)

$$SearchTemplateDefault
Domino requires the $$ViewBody field, but ignores the value. This form is the default for all Web searches that aren't associated with a specific form.

$$SearchSiteTemplate
In a site search this form is used in stead of $$SearchTemplateDefault
(source: posting by Andrew S Grant on Notes.Net)

$$Search
When a user initiates a text search from the Web, Domino looks in the current database or in the search site database in a multiple-database search for a form with the actual name or the alias name $$Search. If the form exists, Domino opens it; otherwise, Domino displays the default search.htm file stored in the domino\icons directory.

And another set of very useful forms

$$ReturnDocumentDeleted
Displays to Web users when the user successfully deletes documents. Create an editable text field named MessageString to hold the error message.

$$ReturnAuthenticationFailure
Displays to Web users when the user's name and password can't be verified. Create an editable text field named MessageString to hold the error message.

$$ReturnAuthorizationFailure
Displays to Web users when the user doesn't have a high enough access level to access the database. Create an editable text field named MessageString to hold the error message.

$$ReturnGeneralError
Displays to Web users when any other errors occur.. Create an editable text field named MessageString to hold the error message.

Roles

$$WebClient
Is a role which is applied to all Web clients. This role can be very useful in hiding formulas. To check if a client is Web client use @IsMember("WebClient"; @UserRoles).

In general, $$ fields are used for web rendering controls, except in design elements where they are used to hold code. $ fields are generally used for document property controls.

понедельник, 28 октября 2019 г.

Создание запроса к службе Domino Web Service с помощью XMLHttpRequest

Отправка запроса к службе domino и получение ответа

//sr - переменная с текстом зпроса, включающим метод (Hello) службы и параметр (txt=Привет из xml) метода
var sr = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<soap:Envelope " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +
"xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
"<soap:Body>" +
"<" + "Hello" + " xmlns=\"" + "urn:DefaultNamespace" + "\">" +
"<txt>Привет из xml</txt>" +
"</" + "Hello" + "></soap:Body></soap:Envelope>";
//получаем объект XMLHttpRequest
var xhr = new XMLHttpRequest();

//Открывает запрос
xhr.open("POST", "http://srv30/C3257BE400246325/HelloWorldLSWSProvider?openwebservice");
//Заполняем заголовки
xhr.setRequestHeader("SOAPAction", "Hello"); //метод службы
xhr.setRequestHeader("Content-Type", "text/xml; charset=utf-8"); //тип содержимого запроса

//call-back функция
 xhr.onreadystatechange = function() {
   // проверяем состояние запроса и числовой код состояния HTTP ответа
   if (this.readyState == 4 && this.status == 200) {
     console.log(this.responseText);
   }
 };

//Отправка запроса
xhr.send(sr);

//Ответ возвращается в виде xml
/*
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
 <soapenv:Body>
  <ns1:HelloResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="urn:DefaultNamespace"><HelloReturn xsi:type="xsd:string">Привет из xml</HelloReturn></ns1:HelloResponse>
 </soapenv:Body>
</soapenv:Envelope>
*/


--------------------------------------------------
Web service на стороне domino:
Создается web Service Providers
Имя: HelloWorldLSWSProvider
Алиас: HWLSP
Port Type class: hwProvider
Programming Model: RPC
Soap message format: RPC/encoded
Port type name: hwProvider
Service element name: hwProviderService
Service port name: Domino

'Класс в разделе Declaration
Class hwProvider
Function Hello ( txt As String ) As String
Print "message web service"
Print txt
Hello = "Hello 111111" + txt
End Function
End Class


пятница, 28 июня 2019 г.

Перехват клавиши Enter в поле с помощью JavaScript клиента Notes

Все делается в клиенте notes на Javascript

1. Эту строку прописываем в событии Onload формы
// Проверка нажатия Enter каждые 1/10 секунды
useClick = window.setInterval("runSearch()",100); 

2. Эту строку прописываем в событии OnUnload формы
//Удаляем проверку нажатия Enter
window.clearInterval(useClick);

3. В полях Name и ID свойств кнопки, код которой будет выполняться по нажатию Enter записываем наименование кнопки, например, Button

4. В разделе JS Header формы записываем следующий код
var newline = String.fromCharCode(10);
var useClick;
var sString;
var t_sString;

function runSearch() {
sString = document.forms[0].YourSearchField.value;
if (sString.indexOf(newline)>=0) {
t_sString = replace(sString, '\n', '');
document.forms[0].YourSearchField.value = t_sString;
document.forms[0].elements['Button'].click();
}
}

function replace(str, from, to) {
var i = str.indexOf(from);
if (!from || !str || i == -1) return str;
var newstr = str.substring(0, i) + to;
if (i+from.length < str.length)
newstr += replace(str.substring(i+from.length,str.length),from,to);
return newstr;
}

//В этом коде 
YourSearchField - это наименование текстового поля в котором будет происходить перехват нажатия клавиши Enter
Button в строке document.forms[0].elements['Button'].click(); наименование/ИД кнопки, в котором прописан код для выполнения при нажатии клавиши Enter

Ссылка на источнк: Workaround to let Notes Client users just hit Enter to begin a search/click a button