Home | Blog Roll |  Link Roll |  Colophon/About| |


Archive for the ‘Show-n-Tell+Thursday’ Category

SnTT: Notes Document Structured Text Export for Multilingual (UTF-8)

Thursday, November 15th, 2007

This Lotus Notes Domino “Show and Tell Thursday” was promoted by Paul Harrison’s new blog and his sntt post on (Welcome Paul, and thank you!) My current nightmare involves a lot of Multilingual madness. Within Notes/Domino is not a big deal (it’s all auto-magical) , but getting it in and out can be tough.

So a couple of observations to Paul’s posting (if only to remind my future self) :

  • Under (for R7) “File”, “Preferences”, User Preferences” , there is a Tab for “International” and a setting for “”Import/Export characters.” I’m using “Unicode ()”.
  • Microsoft Excel (2000) CSV imports and “Save as..” does not handle UTF-8, although there is a “Save as..” “Unicode Text”. (there maybe a option to respect UTF-8 in there, and it maybe handled by Excel 2003 or Excel 2007, but that’s what I have!)
  • Open Office’s (2.3) Calc asks me what Character set to Import the csv file with. Calc also asks me the character set to use in the creation of CSV files.

It’s also worth highlighting Kevin Pettitt’s recent post : and the (new to me, and free) tool from AGE Computer Consultancy. Very nicely done.

The code in my previously written post can easily be modified to (in particular the “Open” statement for the CSV export) to allow for a “UTF-8″ character set.

Update :  For importing text into Notes, what I’ve found works best for me is: “save as” CVS from Open Office Calc, and make sure your saving as UTF-8, no double quotes (”) for the text delimiter, and a ~ rather than a coma (,) for field delimiter (because the text can content coma’s); create a .COL file; Import in the Notes Client as Tabular Text (rename the .csv file to a .txt file).

SNTT : Trapping Document Delete in LotusScript to skip Document processing

Thursday, March 8th, 2007

This all started because I wanted to skip certain processing on a document if a document was going to be deleted (if it was going to be deleted the process was redundant).

There is a nice DeleteDocument method for the notesUIDocument object which “Marks the current document for deletion and closes it.”, but I needed to know if it had been “Marked for Deletion”. Nothing. No nice notesDocument or notesUIDocument properties to tell me “IF” it has been marked for deletion. Ack!

So I had to invent my own, at least until lotus exposes one! (Hint, Hint! feature request!)

The saving feature here is that the Database Querydocumentdelete event is fired before the Documement QueryClose event.

Sub Querydocumentdelete(Source As Notesuidatabase, Continue As Variant)
dim dc as notesdocumentcollection
Set dc = source.documents
dim doc as notesdocument
Set doc = dc.GetFirstDocument
Do While Not doc Is Nothing ' mark that this document is going to be deleted
doc.MarkedForDeletion = "YES"
Call doc.Save (True,False,False)
Set doc = dc.GetNextDocument(doc)
Loop
end sub

I also coded up the Database Querydocumentundelete event in case that the document gets unmarked for deletion before it actually get deleted so the desired process of the document will happen next time.

Sub Querydocumentundelete(Source As Notesuidatabase, Continue As Variant)
dim dc as notesdocumentcollection
Set dc = source.documents
dim doc as notesdocument
Set doc = dc.GetFirstDocument
While Not(doc Is Nothing)
If Doc.HasItem("MARKEDFORDELETION") Then
' the MARKEDFORDELETION item is set in the Database Querydocumentdelete event
doc.RemoveItem("MARKEDFORDELETION") ' this is no longer being deleted so the remove the mark
Call doc.Save(True,False,True)
End If
Set doc = dc.getnextdocument(doc)
Wend
end sub

And then with all the setup work done I check in the Documents Queryclose event whether the documents is about to be deleted.

Sub Queryclose(Source As Notesuidocument, Continue As Variant)
If Source.document.HasItem("MARKEDFORDELETION") Then
' the MARKEDFORDELETION item is set in the Database Querydocumentdelete event
Exit Sub
End If
'otherwise do you whatever you would usually do
exit sub

If you wanted to only trap the delete that happens within the document, but not from the view then in the Querydocumentdelete event you would look to see if “workspace.CurrentView is Nothing” is true.

I previously bloged on a related subject :

Happy deleting…. (technorati.com tags :, )

SNTT : Testing for Unique Multi Values in a Lotus Notes Form field

Thursday, January 11th, 2007

Last week I posted on Testing for Unique values in a Lotus Notes Form field, then Nathan’s Comment made me reprise the code. (Learn and share or “CITOKATE”)

I promised to show how to test for Unique multiple values (or compound values), Like making sure the names (First Name + Last Name) are unique for each Company (as represented by Company Id or Name which It test for last week), on a person form.

Originally I was using an array of field names to build my search string to do me db.search, but that feels very obsolete now.

Happily the new “isValueUniqueForFormViaView” function can also be used if you build the view (Lookup People Unique to Company) sorted by a first field which is CompanyId+FirstName+LastName, with a select on the valid people documents (SELECT FORM=”PEOPLE” & STATUS = “ACTIVE”).

and call it like this :

Sub Querysave(Source As Notesuidocument, Continue As Variant) Dim ViewName as string Dim key As String key = Source.Document.GetItemValue(“CompanyId” )(0)+_ Source.Document.GetItemValue(“FirstName” )(0) +_ Source.Document.GetItemValue(“LastName” )(0) ViewName = “Lookup People Unique to Company” If Not IsValueUniqueForFormViaView (Source.Document,_ ViewName,_ Key) Then Messagebox “The First and Last Name must be unique.,_ MB_OK+MB_ICONSTOP,_ db.title + ” Business Rule Error” Continue = False Exit Sub End If end Sub

and the Function is the same, although fixed up a bit :

Function IsValueUniqueForFormViaView (Doc As NotesDocument,_ ViewName As String,_ FieldValue As Variant ) ‘Doc,the back-end Document we are testing. ‘ViewName,a view sorted by the field name, ‘ containing the documents we want to test. ‘FieldValue, the value we what to test for uniqueness Dim session As New NotesSession Dim db As Notesdatabase Dim view As NotesView Dim vc As NotesViewEntryCollection Set db = session.CurrentDatabase Set view = db.GetView( ViewName ) If view Is Nothing Then Msgbox “Error with View “ &_ ViewName,16 ,_ db.Title + ” Checking for Uniqueness” IsValueUniqueForFormViaView = False Exit Function End If Set vc = view.GetAllEntriesByKey( FieldValue, True ) If vc.count > 1 Then Goto HandleFalse If vc.Count = 0 Then Goto HandleTrue If vc.Count= 1 Then If Doc.UniversalID = vc.GetFirstEntry.document.UniversalID Then ‘ same document , so we should be okay Goto HandleTrue End If End If HandleFalse: IsValueUniqueForFormViaView = False Exit Function HandleTrue: IsValueUniqueForFormViaView = True End Function

This LotusScript was converted to HTML using the ls2html routine,
provided by Julian Robichaux at nsftools.com.

(technorati.com tags :, )

SNTT : Test for Unique values in a Lotus Notes Form field

Thursday, January 4th, 2007

A new Year and more Show-n-Tell+Thursday Lotus Domino examples! The pressure is on.

Suppose you need to ensure that a value is unique for a field for a given form and the documents created by that form. Like a “CompanyName” field on a “Company” form. How would you go about that in the Lotus Notes client?

First, would I assume that this is a important field, therefore it’s required, so in the forms QuerySave you need to do field validated on the from (you could use the techniques I described in SnTT : LotusScript Required Field Validation without pain, but feel free to use you own). You could do validated before or after.

I would also test to see if the value had changed before testing for uniqueness. You don’t need to test it every time!

But the QuerySave is where to test for uniqueness, before the document is saves, and if that fails I pop up a nice user friendly error message and the stop the save to change the value, or close with out saving.

Sub Querysave(Source As Notesuidocument, Continue As Variant) If Not IsValueUniqueForFormViaView (Source.Document,_ “LookupCompanyByName”,_ Source.Document.CompanyName) Then Messagebox “The Company Name must be unique.”,_ MB_OK+MB_ICONSTOP,_ db.title + ” Business Rule Error” Continue = False Exit Sub End If End Sub

Update : I’ve update the code sample here, since it was breaking things in IE. I’ve revised the code along lines suggested by Nathan’s very valid point in the comments.

A big assumption here is that use have a view, selecting just valid Company forms and indexed by “Company Name” values ,to pass to the function.

To do this I need the back-end document, and I need to know the Form (this is not on the document until after the form is saved, hence I pass it), and the single value field being testing.

I build a search string which limits the results to the Form, and uses the trim and upper case function to see if the value is already there. You can add AddtionalCondtions to exclude some documents on a static test like: (the pipe | is equal to a quote ” character, and makes it easier to make sure I closed all my quotes) |Status = “Current”| or |Status = “| + Source.Document.Status(0) + |”| .

Once I have a document collection, I look at the number of documents in the collection (count). Values of more than 1 or zero are easy, if the value is 1 then I ask “is this the same document I’m trying to save or not”, if not the the value is not unique.

Update : See Nathan’s very valid point in the comments. As a alternative I would modify the function by passing the viewname used to test uniqueness. I’ve Added a “IsValueUniqueForFormViaView” function to the attached code that works just that way. (Thanks Nathan! CITOKATE!)

Function IsValueUniqueForFormViaView (Doc As NotesDocument, ViewName As String, FieldValue As Variant ) ‘Doc,the back-end Document we are testing. ‘ViewName,a view sorted by the field name, ‘ containing the documents we want to test. ‘FieldValue, the value we what to test for uniqueness Dim session As New NotesSession Dim db as Notesdatabase Dim view AS NotesView Set db = session.CurrentDatabase Set view = db.GetView( ViewName ) If view Is Nothing Then MsgBox “Error Problem with View “ & ViewName IsValueUniqueForFormViaView = False Exit Function End If Set vc = view.GetAllEntriesByKey( FieldValue, True ) If vc.count > 1 Then Goto HandleFalse If vc.Count = 0 Then Goto HandleTrue If vc.Count= 1 Then If Doc.UniversalID = vc.GetFirstEntry.document.UniversalID Then Goto HandleTrue end if ‘ we just found the same document , so we should be okay End If HandleFalse: IsValueUniqueForFormViaView = False Exit Function HandleTrue: IsValueUniqueForFormViaView = True End Function

I’ve attached the above code to make copy and paste easy: IsValueUniqueForForm.txt.

The Function(s) should also be usable for a Domino server web form. (Although this is currently untested by me). I have tested this in R6.x, although it should work R5 and everything more recent.

So what to do if you have a bunch of fields which must be unique for the from? (like First Name and Last Name) ? That’s for next week ! (technorati.com tags :, )

SNTT Structured DbColumn’s in Lotus Notes

Thursday, December 21st, 2006

Back in February I posted Structured DBlookup’s in Lotus Notes. Very popular. Implicit in that was that the same could be applied to DbColumn’s, but the web (and Google) is all about being explicit, so here we go :

class := "Notes";
Cache := "NoCache";
server := @Subset(@DbName; 1);
database := @Subset(@DbName; -1);
view := "In Progress";
columnNumber :=1;
value := @DbColumn( class : cache ; server : database ; view ; columnNumber );
@If(@IsError(value);@Return(@Text(value));@Unique(@Sort(Value)));

The commentary in the Structured DBlookup’s in Lotus Notes post still applies.

The changes from the DBLookup are : no key and you have to read a columnNumber, not a field name.

In general : Having views just for lookups are a very very good thing. You can append columns to such a lookup view but should never insert or delete them. (you don’t know what you might break) As of R6 you can use the @Sort function to order the result without a new lookup view. I also did a @Unique to remove duplicate, which is usually a good thing to do.

It’s self-documenting and error checking - so I’m less likely to make a mistake. Enjoy (technorati.com tags : , ) and Happy Holidays / New Year.

Update (Jan 3 2007): Based on this Notes Forum comment by Ben Langhinrichs, I would revise the last 2 lines to :

value := @Unique(@trim(@DbColumn( class : cache ; server : database ; view ; columnNumber )));
@If(@IsError(value);@Return(@Text(value));@Sort(Value));

since in R6.x+,Interim results in a formula can be greater than 64KB, but the end result of the formula cannot.

SNTT : Export any Lotus Notes View to Excel from Domino Web, automagically

Thursday, December 14th, 2006

As an update to Export any Lotus Notes View to CSV or Excel, automagically, and as an answer to a being asked how you would do this, here is some similar code to export a view from the web brower to Excel :

WebExcelPrint.txt

Import it into a Lotus Script Agent, and call it with a url like http://ServerName/YourDatabase.nsf/WebAgentName?OpenAgent&ViewNameToExport

The Initialize routine parse’s the ViewNameToExport off of the Query String, and opens that view object.

The tricky/clever/sneaky part is the :
Print |Content-Type:application/vnd.ms-excel|
which will create and open (if excel is a registed application) the spreadsheet sheet.

You can also do something like this, after that line,:
Print |Content-disposition: attachment; filename=| & ViewName & |.xls|
which we let you set the filename of the spreadsheet.

You can also do a bunch more formating of the table cells, and I believe you can pass thur some Excel formulas. (see Microsofts’ Excel Web Connectivity Kit for more details on this.)

See (new father) Jake Howlett’s excelent CodeStore article on Keeping the boss happy for more variations. Enjoy (technorati.com tags :, )

SNTT : Export any Lotus Notes View to CSV or Excel, automagically

Thursday, December 7th, 2006

Here is a some very generic code which will work on any Lotus Notes View to print out the contents to a Comma Separated Value (CSV) file, or as an Excel File, with minimum formating, as a general export routines.

ViewCSVPrint.txt
ViewExcelPrint.txt

Import them to a manual agent or a shared action button, open a view and go.

The CVS export prompts you for a file Location, the Excel export (assuming you have MS Excel installed) opens a excel file (it makes it visible at the end) with the results. (you could easily modidy the Excel export to prompt for a - or just use a hard coded default - file path and name, and save to the file system.

A couple of things to note :

  • The ViewCSVPrint routine in the CVS export does not use any UI objects so it could be called by a scheduled agent and run on the server, as long as you supply a valid View object (using a notesDatabase.GetView( viewName$ ) call) and a valid FileNamePath. By giving the file a “.csv” extension the file can be auto magically opened in excel, as well as processed by other programs. (CSV and XML files are the Lingua franca’s of computer systems.)
  • The Excel export must run on a workstation, which must have Excel installed. It is possible to use Java (or other languages) libraries that create excel files on a sever, but I’m not going there. I’m using the LSX OLE libraries available and you can figure out more by looking at Microsoft’s own excel VBA help.
  • In the Excel export I’m using an ugly hack in the intializeColumnArrayValues sub routine to map the column number to the excel column letter label. This limits it to 12 columns at presents, but would be trival to extend. Even better if I figured out some clever way to translate column # 17 to chr(”A”) + 14 - 1 = “n” or something. When I can marshal my brain cells I’ll do just that for a future SNTT.
  • The CVS also runs very very fast for very large numbers of rows, compared to the Excel export. Seconds compared to minutes.
  • Both exports works best with flat (non- categorized) views where all the columns have titles and without hidden columns. This is because I’m using a ViewEntryCollection which never contains categories. But, they will work ony any view.
  • For the Excel export, I’m splitting and freezing the header row, and doing some fit to size on the data, but that’s it. You could do some more formatting by querying the columns and depending on the type (number or data) or formating (left alignment, number of decimals) then apply that to the excel data column.

Enjoy (technorati.com tags :, )

Update : See also
SNTT : Export any Lotus Notes View to Excel from Domino Web, automagically

Update March 20th 2007 : Lotus Guru, aka Kevin Pettitt, borrowed the code here and worked it to Make Attractive Exports of Categorized Notes Views. That’a Boy Kev!

Opening a Lotus Notes Profile Document in Read Only mode

Wednesday, October 25th, 2006

I needed to display for “regular” users information that was maintained database wide (preferable via a profile form). Although the usual “@Command( [EditProfileDocument] ; formname; uniqueKey )” worked fine for the db admin people to edit/maintain the information, there was no corresponding “OpenProfileDocument” or such. I wasn’t having much luck forcing a editmode profile document back into readmode for non admin people (using my IsInROle routine ), and I was about to go to a normal form and view when I figured out this way to open a Profile Document in non edit (read only) mode (in this case stuck in a button):

Dim workspace As New NotesUIWorkspace
Dim session As New NotesSession
Dim db As NotesDatabase
Dim doc As NotesDocument
Set db = session.CurrentDatabase
Set doc = db.GetProfileDocument("ProfileDocName" )
Call workspace.EditDocument( False, doc, True )

The work is all is those last two line : the GetProfile get the document object for the profile “ProfileDocName”, and the EditDocument opens it on the ui workspace in Read Mode, with the profile Doc object, and opens inRead only mode -so you don’t have to worry about them switching to edit mode.

(technorati.com tags :, )

Q&D Action button to set Date Value with Lotus Notes Formula Language

Thursday, October 12th, 2006

A quick and dirty way for doing this. No error checking, big assumptions about the input to the prompt being right.

nd := @Prompt([OKCANCELEDIT]; "Enter the New Date"; "YYYY/MM/DD."; @Today);
@If (nd ="";@Return("");"");
y := @Left (nd;"/");
m := @Left(@Right (nd;"/");"/");
d:= @right(@Right (nd;"/");"/");

FIELD DateFieldOnForm := @Date(@TextToNumber (y) ;@TextToNumber ( m)
;@TextToNumber ( d) )

the Key is parsing the string with @lefts and such, and then TextTonumber, to put humpty Dumpty back together again. The @Date means it is a Date field on the document, not a text string.

The better, clean, way would be to use LotusScript and open a form in Dialog box mode, the form having a Calander tool on it.

Using Lotus Notes ACL Roles rather than Groups Names in our ACL

Thursday, October 5th, 2006

Why should you use Role names to define functionality? Because : it’s easier to check if someone belongs to a role than a group, and I can’t control what a client (or the Notes Administrator) is going to call a given group.

ACL settings for a pseudo Role-Group need to be documented perhaps in the “Using” document for a given db.

Having a Group for each Role in the ACL ( “DbName_Reader”; DbName_Editor_withoutDelete”; “DbName_Admin” ) is another good idea worth the work of setting up rather that just reusing existing group names. (and it helps avoiding deleting a group, then finding out is was used in another apllication - six days later, when the vp of X calls your boss. Then could set up general departmental user groups “Controler_BAs”, or some such, which you then use to you populate the application level groups.

Mapping between Groups and Roles can also be done via a profile document Once done you can send emails out to a Group, or be able to edit a Groups member directly from the database application. See : Avoiding Hard Coding of Group Names.


Close
  • Social Web
  • E-mail
E-mail It