LotusScript Create table in RichTextItem - lotus-notes

I'm new with Notes and LotusScript and I got a problem.
I need to create a table in a rich text item, I have used an "action partagée" (maybe "shared action" in English). My code runs without returning an error but my table is not visible.
Sub Click(Source As Button)
On Error Goto errorhandler
Dim workspace As New NotesUIWorkspace
Dim session As New NotesSession
Dim db As NotesDatabase
Dim uidoc As Notesuidocument
Dim doc_bdl As NotesDocument
Dim table As NotesRichTextItem
Dim rtnav As NotesRichTextNavigator
' création du document
Set uidoc = workspace.ComposeDocument("","","EXPEDITION")
Set doc_bdl = uidoc.Document
Set table = New NotesRichTextItem(doc_bdl,"rtTableau")
' création du tableau
Call table.AppendTable(4, 3)
Set rtnav = table.CreateNavigator
Call rtnav.FindFirstElement(RTELEM_TYPE_TABLECELL)
Dim iRow As Integer
Dim iColumn As Integer
For iRow = 1 To 4 Step 1
For iColumn = 1 To 3 Step 1
Call table.BeginInsert(rtnav)
Call table.AppendText("Ligne " & iRow & ", Colonne " & iColumn)
Call table.EndInsert
Call rtnav.FindNextElement(RTELEM_TYPE_TABLECELL)
Next
Next
Exit Sub
errorHandler:
Print Lsi_info(2) & " : " & Err & " (" & Error & ") ligne " & Erl
Exit Sub
End Sub
I have read that to see the content of rich text items it's necessary to refresh the document. So I used examples in the help.
I tried to add this :
Call doc_bdl.Save(True, False)
Dim ws As New NotesUIWorkspace
Call ws.ViewRefresh
I got no error but I still not see my table.
I tried this :
Call doc_bdl.Save(True, False)
Call doc_bdl.Refresh(True)
I got this error : "Illegal use of PROPERTY"
Can someone help me ? Thank you in advance
PS : English is not my language so please excuse my possible errors, I don't find french forums for help.

You need to do something like this:
' Save your backend document with the updated RichText field
Call doc_bdl.Save(True, False)
' Open saved backend document as a uidoc
ws.EditDocument(True, doc_bdl)
If you want to build a table with content, and you don't know how many rows there will be (and/or if you want more control ov the formatting of the table) you can use this technique:
http://blog.texasswede.com/dynamic-tables-in-classic-notes/

Related

Getting "The linked document (UNID... cannot be found in the view (UNID ...)" Error Message

I'm getting the error message below:
Upon clicking the doclink which was being attached in the e-mail which was generated by me through clicking the send to managers button. I also tried using NotesURL instead of doclink:
Call rtitem.appendtext(emaildoc.Notesurl)
but the generated URL is different from the doclink. Below is the generated from the doclink itself.
Generated NotesURL: notes://LNCDC#PHGDC/__48257E3E00234910.nsf/0/237B2549EEA393A948257E530042BA4A?OpenDocument
Doclink: Notes://LNCDC/48257E3E00234910/28BD6697AB48F55348257E2D0006CF60/C9B0266FDC0D929E48257E530041D6F9
Can you please help? Below is my agent code.
%REM
Agent Send Email to Managers
%END REM
Option Public
Option Declare
Dim s As NotesSession
Dim db As NotesDatabase
Dim emaildoc As NotesDocument
Dim paydoc As NotesDocument
Dim rtitem As NotesRichTextItem
Dim i As Integer
Dim view As NotesView
Sub Initialize
Set s = New NotesSession
Set db = s.CurrentDatabase
Set view = db.GetView("Pending Claims")
Dim addresses As NotesName
Dim arrpem As Variant
ReDim arrpem(0)
Set paydoc = view.GetFirstDocument
'// Store all PEM names in an array
While Not(paydoc Is Nothing)
ReDim Preserve arrpem(UBound(arrpem) + 1)
arrpem(UBound(arrpem)) = paydoc.PeopleManager(0)
Set paydoc = view.GetNextDocument(paydoc)
Wend
'// Remove all duplicate PEM names and empty entries in the array
arrpem = FullTrim(ArrayUnique (arrpem))
'// Loop the PEM names array
ForAll pem In arrpem
Set emaildoc = New NotesDocument(db)
Set addresses = New NotesName(pem)
If addresses.abbreviated <> "" Then
emaildoc.SendTo = addresses.abbreviated
emaildoc.Subject = "Leave Balances of your Direct Reports"
emaildoc.Form = "Memo"
Set rtitem = New NotesRichTextItem(emaildoc, "Body")
Call rtitem.AppendText("Dear " & addresses.common & ",")
Call rtitem.AddNewLine(2)
'// Remove paydoc value which was used in the PEM names array
Set paydoc = Nothing
'// Get all documents that has matching PEM name in the view
Dim dc As NotesDocumentCollection
Set dc = view.GetAllDocumentsByKey(addresses.Abbreviated, True)
Set paydoc = dc.GetFirstDocument
'// Append doc link of employee
While Not(paydoc Is Nothing)
Call rtitem.AppendText("Doc link of :" & paydoc.FMName(0) & " " & paydoc.LastName(0))
Call rtitem.appenddoclink(emaildoc, "Link to Leave Balance of " & paydoc.FMName(0) & " " & paydoc.LastName(0))
Call rtitem.AddNewLine(1)
Set paydoc = dc.GetNextDocument(paydoc)
Wend
'// Send email per PEM
Call emaildoc.Send(False)
End If
End ForAll
MsgBox "Emails successfully sent."
End Sub
The doclink is pointing back to the document you've created in memory for your email. When sent, that document no longer exists in the original database.
Change your code to be:
Call rtitem.appendtext(paydoc.Notesurl)

VBA to Lotus Notes - Variable body with formatting ( Colors )

I'm currently working in the automation of a process at work that used to require a lot of hand work and gathering data from several sources and ended in sending an email with:
Header ( fixed ) Regular
Description ( One line for each cell with data in a given range ) Bold
Footer ( fixed ) - Text Color: Red
Attachment
Well, we had a stationery to aid with the email, but as i can't guarantee that everybody will have the stationery properly set up i am looking for a more elegant way to do so ( basically the goal is to make it fool-proof ), so i started to work on a way to do it mixing VBA+Formulas in the cells.
So far my code creates the message on notes, inserts the adress list, title and attaches the file that it generates, but when it comes to inserting the body, fat chance! I can insert a single-lined message but without any formatting or styles, the ones described above in bold next to the elements of the body.
What i'm chasing is a way to paste the text in given cells from my spreadsheet to notes and apply formatting on them, so each cell value would be a line of text on notes, with different styling.
I've been reading questions and articles for about 3 days already without any success, and i decided to ask it myself cause it's a big step forward in my project, is there a way to do it? i believe i'm looking for something like
notesmagicproperty.boldthisrange("B3")
that translates to
"03 - Lorem ipsum dolor sit amet"
Thanks in advance, Stack Overflow has saved me a thousand times already!
Also, sorry for not posting the code, i'm writing this from home and it's 3am so i have no access to it at the moment.
0. NotesRichTextRange.SetStyle method
NotesRichTextRange.SetStyle method is what you are looking for. For this method you need to create NotesRichTextStyle object. Also you need to SetBegin end SetEnd of range by using NotesRichTextNavigator object.
Here is example:
Dim ses As New NotesSession
Dim doc As NotesDocument
Dim richText As NotesRichTextItem
Dim navigator As NotesRichTextNavigator
Dim range As NotesRichTextRange
Dim headerStyle As NotesRichTextStyle
Dim descriptionStyle As NotesRichTextStyle
Dim footerStyle As NotesRichTextStyle
'Create your doc.
'Generate rich text content:
Set richText = doc.CreateRichTextItem("Body")
Set navigator = richText.CreateNavigator
Set range = richText.CreateRange
richText.AppendText("Header")
richText.AddNewline(1)
Set headerStyle = ses.CreateRichTextStyle
headerStyle.Underline = True
Set descriptionStyle = ses.CreateRichTextStyle
descriptionStyle.Bold = True
Set footerStyle = ses.CreateRichTextStyle
footerStyle.NotesColor = COLOR_RED
navigator.FindFirstElement(RTELEM_TYPE_TEXTPARAGRAPH)
range.SetBegin(navigator)
range.SetEnd(navigator)
Call range.SetStyle(headerStyle)
For index% = 0 To 7
richText.AppendText("Description" & index%)
richText.AddNewline(1)
navigator.FindNextElement(RTELEM_TYPE_TEXTPARAGRAPH)
range.SetBegin(navigator)
range.SetEnd(navigator)
Call range.SetStyle(descriptionStyle)
Next
richText.AppendText("Footer")
richText.AddNewline(1)
navigator.FindNextElement(RTELEM_TYPE_TEXTPARAGRAPH)
range.SetBegin(navigator)
range.SetEnd(navigator)
Call range.SetStyle(footerStyle)
Call richText.EmbedObject(EMBED_ATTACHMENT, "", "SomeFile")
richText.Update
'Process your doc.
This example generates this rich text:
1. NotesDocument.RenderToRTItem method
The other way is to use NotesDocument.RenderToRTItem method. For this method you need to create a form and style it as you need. For example, create a form "Message" and add to this form four fields:
And use this form in your code:
Dim ses As New NotesSession
Dim db As NotesDatabase
Dim messageDoc As NotesDocument
Dim attachment As NotesRichTextItem
Dim description(7) As String
Dim doc As NotesDocument
Dim richText As NotesRichTextItem
Set db = ses.CurrentDatabase
Set messageDoc = db.CreateDocument
messageDoc.Form = "Message"
messageDoc.Header = "Header"
For index% = 0 To Ubound(description)
description(index%) = "Description" & index%
Next
messageDoc.Description = description
messageDoc.Footer = "Footer"
Set attachment = messageDoc.CreateRichTextItem("Attachment")
Call attachment.EmbedObject(EMBED_ATTACHMENT, "", "SomeFile")
'Create your doc.
'Generate rich text content:
Set richText = doc.CreateRichTextItem("Body")
Call messageDoc.RenderToRTItem(richText)
richText.Update
'Process your doc.
This example generates this rich text:
2. NotesUIDocument.Import method
You can genereate the rich text content somewhere else and import it to your document by using NotesUIDocument.Import method.
Here is example for importing html content:
Dim ses As New NotesSession
Dim db As NotesDatabase
Dim doc As NotesDocument
Dim richText As NotesRichTextItem
Dim ws As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
'Generate html file
tempdir$ = Environ("Temp")
file = Freefile
filename$ = tempdir$ & "\temp.html"
Open filename$ For Output As file
Print #file, "<u>Header</u><br>"
For index% = 0 To 7
Print #file, "<b>Description" & index% & "</b><br>"
Next
Print #file, "<font color='red'>Footer</font><br><br>"
Close file
Set db = ses.CurrentDatabase
Set doc = db.CreateDocument
'Create your doc.
'Add attachment to rich text:
Set richText = doc.CreateRichTextItem("Body")
Call richText.EmbedObject(EMBED_ATTACHMENT, "", "SomeFile")
Set uidoc = ws.EditDocument(True, doc)
uidoc.GotoField("Body")
uidoc.Import "html", filename$
'Process your doc.
This example generates this rich text:
Please note that this code IS NOT MINE
I took it from user John_W in a mr excel post, I'm just pasting it here because I wanted to share something that helped me as it might help others. Also, I won't link the page here because I don't think it's fair with Stack Overflow but I have a big Thank You for John_W for sharing this online.
Sub Notes_Email_Excel_Cells()
Dim NSession As Object
Dim NDatabase As Object
Dim NUIWorkSpace As Object
Dim NDoc As Object
Dim NUIdoc As Object
Set NSession = CreateObject("Notes.NotesSession")
Set NUIWorkSpace = CreateObject("Notes.NotesUIWorkspace")
Set NDatabase = NSession.GetDatabase("", "")
If Not NDatabase.IsOpen Then
NDatabase.OPENMAIL
End If
'Create a new document
Set NDoc = NDatabase.CreateDocument
With NDoc
.SendTo = "email.address#email.com" 'CHANGE THIS
.CopyTo = ""
.subject = "Pasted Excel cells " & Now
'Email body text, including marker text which will be replaced by the Excel cells
.body = "Text in email body" & vbNewLine & vbNewLine & _
"**PASTE EXCEL CELLS HERE**" & vbNewLine & vbNewLine & _
"Excel cells are shown above"
.Save True, False
End With
'Edit the just-created document to copy and paste the Excel cells into it
Set NUIdoc = NUIWorkSpace.EDITDocument(True, NDoc)
With NUIdoc
'Find the marker text in the Body item
.GotoField ("Body")
.FINDSTRING "**PASTE EXCEL CELLS HERE**"
'.DESELECTALL 'Uncomment to leave the marker text in place (cells are inserted immediately before)
'Replace it with the Excel cells
Sheets("Sheet1").Range("A1:E6").Copy 'CHANGE THIS
.Paste
Application.CutCopyMode = False
.Send
.Close
End With
Set NSession = Nothing
End Sub

Remainder Mail agent

I have form with 3 fields adress,status,ReportingDate.
Adress field contains the ID where the mil has to be sent.
Now I have created an agent where it should mail to the data present in adress field when status is incomplete and reporting date is exactly 7 days before todays date.
My Code:
Option Public
Option Declare
Sub Initialize
Dim sess As New NotesSession
Dim db As NotesDatabase
Dim doc As NotesDocument
Dim timestamp As New NotesDateTime("Today")
Dim Noresponsedate As NotesDateTime
Dim vw As NotesView
Dim diff As Integer
Dim SendTo As Variant
Call timestamp.SetNow()
Set db = sess.CurrentDatabase
Set vw = db.GetView( "data" )
Set doc = vw.GetFirstDocument()
While Not doc Is Nothing
If doc.Status(0) = "Incomplete" Then
Call checktimedifference(doc)
End if
Set doc = vw.GetNextDocument(doc)
wend
End Sub
Sub checktimedifference(doc As NotesDocument)
Dim due As NotesDateTime
Dim present As NotesDateTime
Dim timecheck As variant
Set due = New NotesDateTime ( "" )
Set present = New NotesDateTime ( "Today" )
timecheck = doc.ReportingDate(0)
due.LSLocalTime = timecheck
If due.TimeDifference (present) = -604800 Then
Call sendmailtouser(doc)
End If
End Sub
Sub sendmailtouser(doc As NotesDocument)
Dim db As NotesDatabase
Dim rtiitem As NotesRichTextItem
Dim maildoc As NotesDocument
dim recepient As variant
Set maildoc = New NotesDocument( db )
Set rtiitem = New NotesRichTextItem( maildoc, "Body" )
recepient = doc.adress(0)
maildoc.from = db.Title
maildoc.form = "memo"
maildoc.subject = "A Minor Injury Report:" & doc.Seq_No(0) & " needs your response"
maildoc.SendTo = recepient
Call rtiitem.AppendText( "Please respond to this Minor Injury Report" )
Call rtiitem.AddNewline( 2 )
Call rtiitem.AppendText( "Your response for the Minor Injury Report: " & doc.Seq_No(0) & " is required" )
Call rtiitem.AddNewline( 2 )
Call rtiitem.AppendText( "Please click on the following link to access the document.")
Call rtiitem.AppendDocLink( doc, db.Title )
Call maildoc.Send(False)
End Sub
When I am running the agent on client I am getting the following error:
Please help me to solve the error and send mail to the recepients.
Not using any error handling is very bad practice. But your error will most probably happen in the sendmailtouser- sub, where you dim a local notesdatabase- object named db without actually initializing it.
The line
set maildoc = New NotesDocument( db )
will fail.
Either declare db globally and set it in your initialize or dim ses in that sub again and set db again (worst case as you have to do it for every document)

Calling script library in agent and button

I want to use the following script library in button and also in agent.
My script library code:Validate
Option Public
Option Declare
Dim Sess As NotesSession
Dim currentDb As NotesDatabase
Dim dataDb As NotesDatabase
Dim doc As NotesDocument
Dim workspace As NotesUIWorkspace
Dim uidoc As NotesUIDocument
Dim rtitem As NotesRichTextItem
Sub Initialize
Set Sess = New NotesSession
Set currentDb = Sess.CurrentDataBase
Set workspace = New NotesUIWorkspace
Set uidoc = workspace.CurrentDocument
End Sub
Function ValidateForm ( Source As NotesUIDocument) As Boolean
On Error GoTo e
Set doc=source.Document
Dim Txt As String
Dim trimmed As string
txt = doc.Name(0)
trimmed = Trim(Txt)
If ( trimmed = "") Then
MsgBox "Please enter some text."
source.GotoField("Name")
ValidateForm= false
Else
ValidateForm= True
End If
Exit Function
e:
MsgBox "error at"& Erl() & " and error is "& Error()
End Function
In Button:
In button when i call the script library since in the validateform function it has source as notesuidocument and in button click it has souce as button it i giving me error.
Sub Click(Source As Button)
End Sub
I have tried using in agent in options using below:
Use "Validate"
and tried calling it in button using formula
#Command([ToolsRunMacro]; "Val")
But no use I am not getting the desired output.
I am new to lotus notes.Please help me in doing above tasks.
You don't need to take a parameter at all. In the initialize- Sub of your Script- Library you already set the global variable "uidoc" to the currently opened document:
Set workspace = New NotesUIWorkspace
Set uidoc = workspace.CurrentDocument
In your Function "validateForm" you simply omit the parameter and then replace "source" with "uidoc"
Set doc=source.Document
The other possibility (if you want to give the current document as a parameter):
Sub Click( Source as Button)
Dim ws as New NotesUIWorkspace
Dim uidoc as NotesUIDocument
set uidoc = ws.CurrentDocument
Call ValidateForm( uidoc )
End If
Or if you keep the initialize code in your Library:
Sub Click( Source as Button)
Call ValidateForm( uidoc )
End If
This works, as "uidoc" is a global variable, that is already initialized by the Sub initialize of your Script- Library.
HTH
Make it an agent, not a script library. If it's named Validate, use that formula you had in the button without trying to include a script library.
#Command([ToolsRunMacro]; "Validate")
Script libraries are typically used for subroutines and functions that you will call from multiple agents or other scripts, not for entire agents. You can call an agent from a button or allow users to click on it in the Action menu or any number of other ways of calling it. You don't have to put it in a script library.
You could reduce the code in the agent to be as follows:
Option Public
Option Declare
Sub Initialize
Dim workspace As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Dim doc As NotesDocument
Dim Txt As String
Dim trimmed As string
Set uidoc = workspace.CurrentDocument
On Error GoTo e
Set doc=uidoc.Document
txt = doc.Name(0)
trimmed = Trim(Txt)
If ( trimmed = "") Then
MsgBox "Please enter some text."
uidoc.GotoField("Name")
End If
exit sub
e:
MsgBox "error at"& Erl() & " and error is "& Error()
End Sub
Or, if all you want to do is verify that a field is not empty and shift focus to that field, just add the following to any field's Input Validation formula:
#If ( #ThisValue = ""; #Failure ( "You must enter a value for " + #ThisName ); #Success )

Filter Process script Library

I have a form called Approver in "Approver" db.
The form has two editable text fields: Office and Group. It also has a dialog list field superior1.
The superior1 dialog list field should show the staff details filtered based on office & group:
if office = TSP & group = HR from the approver form, then shud filter the staffs based on these fields group" & "office" with the "Staff info" view of another database "TSP_Staff" and show in superior1.
But it is not getting filtered for me. :(
I am new to this tech, so I am confused and have no one to help me in this. This is the script I used:
for the superior1 field:
Sub Entering(Source As Field)
Dim s As New NotesSession
Dim db As NotesDatabase
Dim view As NotesView
Dim uidoc As NotesUIDocument
Dim doc As Notesdocument
Dim work As New NotesUIWorkspace
Dim workspace As New NotesUIWorkspace
Dim sname As String
Dim consr As String
Dim cview As notesview
Set db = s.CurrentDatabase
Set uidoc = work.CurrentDocument
Set uidocs = workspace.currentdocument
Set cview = db.getview("(Application)")
'etype = uidoc.FieldGetText("Office")
'ftype = uidoc.FieldGetText("Group")
etype = "TSP"
ftype = "TSP1-G"
If(etype <> "" And ftype <> "") Then
Call filter
End If
Set view = db.getview("(x_search_staff)")
Set doc = view.GetDocumentByKey (uidoc.fieldgettext("Superior1"),True)
If doc Is Nothing Then
Msgbox "There is no previous transaction please select new trasaction.", 16, "Information"
Call uidoc.FieldClear("Superior1")
Call uidoc.gotofield ("Group")
Call uidoc.gotofield ("Office")
continue = False
Exit Sub
End If
Call uidoc.Refresh
End Sub
from the script library ...
Sub filter
Dim s As New notessession
Dim w As New notesuiworkspace
Dim uidoc As notesuidocument
Dim doc As notesdocument, newdoc As notesdocument, d As notesdocument, dd As notesdocument
Dim doc1 As NotesDocument, newdoc1 As NotesDocument
Dim dc As notesdocumentcollection
Dim bc As notesdocumentcollection
Dim view As notesview, v As notesview
Dim db As notesdatabase
Dim nextdoc As NotesDocument
Dim cview As notesview
Dim cnview As NotesView
Dim get_db As New notesdatabase(gsserver2, gspath2 & "Master\TSP_Staff.nsf")
Set db = s.currentdatabase
Set view = get_db.getview("(Staff Info)")
Set cview = db.getview("(x_search_staff)")
Set cnview = db.getview("(x_superior)")
Set uidoc=w.CurrentDocument
'To delet searched previous datas from form2 ----------------------------------------
Print "Please wait ..."
key = "Approver2"
Set v = db.getview("(x_delete_2)")
Set dc = v.GetAlldocumentsByKey(key,True)
'Set bc = v.GetAlldocumentsByKey(key,True)
'Call bc.RemoveAll(True)
Call dc.RemoveAll(True)
Call cview.Refresh
Call view.Refresh
Call cnview.Refresh
Call v.Refresh
'To start searching process based on Superior1 --------------------------------------
'f1= uidoc.FieldGetText("Office")
f1= uidoc.FieldGetText("Group")
'f1 = "TSP1-G"
Set dc = view.getalldocumentsbykey(f1, True)
'Set bc = view.getalldocumentsbykey(f2, True)
For b =1 To dc.count
Set doc = dc.getnthdocument(b)
Set newdoc = doc.copytodatabase(db)
'For c =1 To bc.count
'Set doc1 = bc.getnthdocument(b)
'Set newdoc1 = doc.copytodatabase(db)
If doc.form(0) = "Approver" Then
'If doc1.form(0) = "Approver" Then
newdoc.form = "Approver2"
'newdoc1.form = "Approver2"
'End If
End If
newdoc.save True, True
' Next
'newdoc.save True, True
'Next
Call w.viewrefresh
Call cview.Refresh
Call v.Refresh
Call cnview.Refresh
Call view.Refresh
Print "Process Completed....."
End Sub
if u got another way for this requirement temme in stepwise wat to do... or else... chk out ma script for errors... hope u help me :( today due date for this task...
I'm not sure how smart it is to filter the documents shown in a view by deleting documents from a database :)
My suggestion is to first post the code properly. This is simply unreadable.
How to display only subset of documents in your dialog list?
Create a hidden field on your form (you'll fill it with values you want displayed in the list using your code).
And then, on your dialog list field properties, second tab, set choices option to be "Use formula for choices" and set it to be the hidden field name.
Ask if you need more help...
Your code is very hard to follow, but if I understand your intention and parts of the filter function (does it even compile?) you could replace all of the code with this #dblookup-based formula in "use formula for choices" section of superior1 properties:
#dblookup("":"ReCache";"ServerName":"foo\Master\TSP_Staff.nsf";"(Staff Info)";Group;NameOfInterestingField);
You might want to add a #sort and/or #unique around it if the view contain duplicate values, and you might want to add the keyword [FAILSILENT] if some groups should result in an empty list.
An even simpler method could be to configure superior1 to use view dialog for choices.

Resources