Programmatically Update /Add Database to DQL Design Catalog

For high speed access to internal information about views and view columns, DQL processing uses design data extracted from view notes. Currently this information will be stored in a new database, named GQFdsgn.cat.

It is created using new updall flags. It does not replicate and is solely used as a fast-path tool to access design data at runtime.

Here is some LotusScript code to add / update the design of a named Notes application to the catalog. The NSFDesignHarvest call is currently undocumented. Use it at your own risk.

'DECLARATIONS

Public Const UPDATE_DESIGN_CATALOG = 0
Public Const ADD_TO_DESIGN_CATALOG = 1

Const NNOTES ="nnotes.dll"
Const LIBNOTES ="libnotes.so"

Declare Public Function WIN_NSFDbOpen Lib NNOTES Alias "NSFDbOpen" _
(ByVal dbName As String, hDb As Long) As Integer
Declare Public Function LIN_NSFDbOpen Lib LIBNOTES Alias "NSFDbOpen" _
(ByVal dbName As String, hDb As Long) As Integer
Declare Public Function WIN_NSFDbClose Lib NNOTES Alias "NSFDbClose" _
(ByVal hDb  As Long) As Integer
Declare Public Function LIN_NSFDbClose Lib LIBNOTES Alias "NSFDbClose" _
(ByVal hDb  As Long) As Integer
Declare Public Function WIN_NSFDesignHarvest Lib NNOTES Alias "NSFDesignHarvest" _
(ByVal hDb  As Long, ByVal flag  As Long) As Integer
Declare Public Function LIN_NSFDesignHarvest Lib LIBNOTES Alias "NSFDesignHarvest" _
(ByVal hDb  As Long, ByVal flag  As Long) As Integer

' API FUNCTIONS
Private Function NSFDbOpen( db As String, hDB As Long) As Integer
	If isDefined("WINDOWS") Then
		NSFDbOpen = WIN_NSFDbOpen(db,hDb)
	ElseIf isDefined("LINUX") Then
		NSFDbOpen = LIN_NSFDbOpen(db,hDb)
	End If
End Function

Private Function NSFDbClose (hDb As Long)
	If isDefined("WINDOWS") Then
		NSFDbClose = WIN_NSFDbClose(hDb)
	ElseIf isDefined("LINUX") Then
		NSFDbClose = LIN_NSFDbClose(hDb)
	End If
End Function

Private Function NSFDesignHarvest (hDb As Long, flag As long) As Integer
	If isDefined("WINDOWS") Then
		NSFDesignHarvest = WIN_NSFDesignHarvest(hDb, flag)
	ElseIf isDefined("LINUX") Then
		NSFDesignHarvest = LIN_NSFDesignHarvest(hDb, flag)
	End If
End Function

Public Function catalogDesign(sDb As String, flag As Long) As Integer
	
	Dim hDb As Long
	Dim rc As Integer
	
	If flag > 1 Then flag = 1
	If flag < 0 Then flag = 0
	
	rc = NSFDbOpen(sDb, hDb)
	
	If rc = 0 Then
		rc = NSFDesignHarvest(hDb, flag)
		rc = NSFDbClose(hDb)
	End If
	
	catalogDesign = rc 
	
End Function


SyntaxHighlighter Evolved: LotusScript Brush

SyntaxHighlighter Evolved: LotusScript Brush is a small WordPress plugin that adds support for the LotusScript language to the great SyntaxHighlighter Evolved plugin by Alex Mills.

I have submitted a request to add the plugin to the official WordPress plugin directory. The review process will take some time.

In the meantime, you can start using SyntaxHighlighter Evolved: LotusScript Brush right now.

Download the plugin from here , unpack it and upload to your /wp-content/plugins directory.

Update 04-FEB-2019: The plugin is now available in the WordPress plugin directory.

Next activate the plugin

SyntaxHighlighter Evolved: LotusScript Brush will now be available as a new language in the Block Editor (“Code Languages”)

SyntaxHighlighter Evolved: LotusScript Brush highlights classes, method and properties, keywords, strings, comments and directives.


NotesHttpRequest LotusScript example

NotesHttpRequest is a new LotusScript class in Notes V10.0.1 used to make HTTP requests to web servers.

The example wraps the get(), post(), put() and deleteResource() methods in a LotusScript class.

I have also put together a small Node.js / Express.js project that can be used as test server for the NotesHttpRequest example.

Class HttpRequestWrapper

%REM
	Library 10010.http
	Created Jan 8, 2019 by Ulrich Krause/singultus
%END REM
Option Public
Option Declare

Const BASE_URL_PORT = "http://192.168.178.35:3001/api/"
Const CLASS_CUSTOMER ="customers"

Const CUSTOMER_5 = |{
					"firstname" : "Ulrich",
					"lastname" : "Krause",
					"age" : 59,
					"id" : 5
				}|

Const CUSTOMER_5_UPDATE = |{
					"firstname" : "Heinz Ulrich",
					"lastname" : "Krause",
					"age" : 59,
					"id" : 5
				}|
				
%REM
	Class HttpRequestWrapper
%END REM
Public Class HttpRequestWrapper
	
	Private m_session As NotesSession
	Private m_url As String
	Private m_class As String
	Private m_json As String
	Private m_httpRequest As NOTESHTTPREQUEST
	
	%REM
		Sub New
	%END REM
	Public Sub New()
		Set m_session = New NotesSession
		Set m_httpRequest = me.m_session.CreateHttpRequest()
		
		m_httpRequest.Preferstrings = True
		
		m_url = BASE_URL_PORT
		m_class = CLASS_CUSTOMER
	End Sub
	
	%REM
		Function getApiVersion
	%END REM
	Public sub getApiVersion()
		m_json = m_httpRequest.Get(BASE_URL_PORT)
		MsgBox m_json
	End Sub
	
	%REM
		Sub getAllObj
	%END REM
	Public Sub getAllObj()
		m_json = m_httpRequest.Get(_
		BASE_URL_PORT + CLASS_CUSTOMER)
		
		MsgBox m_json
	End Sub
	
	%REM
		Sub getObjById
	%END REM
	Public Sub getObjById(id As String)
		m_json = m_httpRequest.Get(_
		BASE_URL_PORT + CLASS_CUSTOMER + "/" + id)
		
		MsgBox m_json	
	End Sub
	
	%REM
		Sub createObj
	%END REM
	Public Sub createObj()
		m_json = m_httpRequest.Post(_
		BASE_URL_PORT + CLASS_CUSTOMER,_
		removeCRLF(CUSTOMER_5))
		
		MsgBox m_json	
	End Sub
	
	%REM
		Sub updateObj
	%END REM
	Public Sub updateObj(id As String)
		m_json = m_httpRequest.Put(_
		BASE_URL_PORT + CLASS_CUSTOMER + "/" + id,_
		removeCRLF(CUSTOMER_5_UPDATE))
		
		MsgBox m_json
	End Sub
	
	%REM
		Sub deleteObj
	%END REM
	Public Sub deleteObj(id As String)
		m_json = m_httpRequest.DeleteResource(_
		BASE_URL_PORT + CLASS_CUSTOMER + "/" + id)
		
		MsgBox m_json
	End Sub
End Class

Public Function removeCRLF(json As String) As String
	removeCRLF = Replace(Replace(json, Chr(13), ""),Chr(10),"")
End Function

Sample usage:

Use "10010.http"

Sub Click(Source As Button)
	Dim httpRequestWrapper As New HttpRequestWrapper()

	Call httpRequestWrapper.getApiVersion()
	Call httpRequestWrapper.createObj()
	Call httpRequestWrapper.deleteObj("3")
	Call httpRequestWrapper.getAllObj()
	Call httpRequestWrapper.updateObj("5")
	Call httpRequestWrapper.getObjById("5")
End Sub



NotesJsonNavigator.getElementByPointer example

Sample code:

Const white = |{"color": "white", "category": "value","code": {"rgba": [0,0,0,1],"hex": "#FFF"}}|

Public Sub testJsonNavGetElementByPointer()
	Dim session As New NotesSession
	Dim jsnav As NotesJSONNavigator 
	Dim el As NOTESJSONELEMENT
	
	Set jsnav = session.CreateJSONNavigator(removeCRLF(white)) 
	
	'// returns "value"
	Set el = jsnav.Getelementbypointer("/category")
	MsgBox "category: " + el.Value
	
	'// returns "#FFF"
	Set el = jsnav.Getelementbypointer("/code/hex")
	MsgBox "hex: " + el.Value
	
	'// returns the 4th element in the rgba array  "1"
	Set el = jsnav.Getelementbypointer("/code/rgba/3")
	MsgBox "code/rgba/3: " + el.Value
End Sub

General information about JSON pointer: https://tools.ietf.org/html/rfc6901


NotesJsonNavigator.getNthElement does not obey boundries

I stumbled upon an issue with NotesJsonNavigator getNthElement(index) method.

It looks like there is no boundry check, which leads to some inconsitent behaviour and unpredictable results.

Here is the code that I used in my test.

%REM
	Sub testJsonNavGetNthElement
%END REM
Public Sub testJsonNavGetNthElement
	Dim s As New NotesSession 
	Dim jsnav As NotesJSONNavigator
	Dim el As NotesJSONElement
	
	Set jsnav = s.CreateJSONNavigator(|{ "element1" : "value 1", "element2" : "value 2", "element3 ": "value 3" }|)	
	
	Set el = jsnav.GetNthElement(0)
	Stop
	Set el = jsnav.GetNthElement(1)
	Stop
	Set el = jsnav.GetNthElement(2)
	Stop
	Set el = jsnav.GetNthElement(3)
	Stop
	Set el = jsnav.GetNthElement(1000)
	Stop
End Sub

The issue occurs with index < 1 and > upper bound of the array.

Index 0 AND index 1 both return the same value; “value 1“.
Index 1000 returns NULL or nothing.

This is not the expected behaviour. At least I would expect some “out of bounds” error.
Also, it is not clear for me what the base for the index is. Do we start counting at 0 or do we start with 1 ?

According to the documentation, the index is 1-based.


NotesDominoQuery sample

I have put together a small sample to demonstrate how to use NotesDominoQuery from LotusScript.

I created a new Class DQLWrapper. A little bit over the top, I know.

%REM
	Library 10010.dql
	Created Dec 30, 2018 by Ulrich Krause/singultus
%END REM
Option Declare

%REM
	Class DqlWrapper
%END REM
Public Class DqlWrapper
	
	m_query As String
	m_session As NotesSession
	m_db As NotesDatabase
	m_ndq As NotesDominoQuery
	
	%REM
		Sub New
	%END REM
	Public Sub New(strDbFilePath As String)
		Set me.m_session = New NotesSession
		Set me.m_db = me.m_session.Getdatabase("",strDbFilePath, False)
		If ( me.m_db.Isopen ) then
			Set me.m_ndq = me.m_db.Createdominoquery()
		Else
			' // do some error handling
		End if
	End Sub

	%REM
		Public function executeQuery()
	%END REM	
	Public function executeQuery() As NotesDocumentCollection
		If ( me.m_query <> "" ) then
			Set executeQuery = me.m_ndq.Execute(me.m_query)
		Else
			Set executeQuery = nothing
		End If
	End Function

	%REM
		Public Function explainQuery()
	%END REM	
	Public Function explainQuery() As String
		If ( me.m_query <> "" ) Then
			explainQuery = me.m_ndq.Explain(me.m_query)
		Else
			explainQuery = ""
		End If
		
	End Function
	
	%REM
		Public Function explainQuery()
	%END REM	
	Public Function parseQuery() As String
		If ( me.m_query <> "" ) Then
			parseQuery = me.m_ndq.parse(me.m_query)
		Else
			parseQuery = ""
		End If
		
	End Function	

	%REM
		Property query
	%END REM	
	Public Property Set query As String
		me.m_query = query
	End property
	
End Class

The query itself is executed from an agent that runs on the server. At the moment it is not possible to run a query client/ server.

Here is the code for the agent

%REM
	Agent dql.execute
	Created Dec 30, 2018 by Ulrich Krause/singultus
%END REM
Option Public
Option Declare
Use "10010.dql"

Sub Initialize
	Dim query As String
	Dim col As  NotesDocumentCollection
	query = "firstname = 'Ulrich' And lastname = 'Krause'"
	
	Dim dql As New DQlWrapper("names.nsf")
	dql.query = query
	
	If (  LCase(dql.parseQuery()) ="success" ) Then
		
		Set col = dql.executeQuery()
		MsgBox "QRY returns # docs: " + CStr(col.count)
		
		If ( col.count > 0 ) then
			Dim doc As NotesDocument
			Set doc = col.Getfirstdocument()
			MsgBox "UNID of first doc: " + doc.Universalid
		End if
	Else 
		
		MsgBox dql.explainQuery()
	End If
	
End Sub

You can now start the agent from the server console. You will get the number of documents for this query and the UNID of the first document found.

te amgr run "ec11.nsf" 'dql.execute'
[0DFC:001F-0FFC] 30.12.2018 13:49:10 AMgr: Start executing agent 'dql.execute' in 'ec11.nsf'
[0DFC:001F-0FFC] 30.12.2018 13:49:10 Agent Manager: Agent message: QRY returns # docs: 1
[0DFC:001F-0FFC] 30.12.2018 13:49:10 Agent Manager: Agent message: UNID of first doc: D8436D0F4E546BA3C12573FE0070AE88
[0DFC:001F-0FFC] 30.12.2018 13:49:10 AMgr: Agent 'dql.execute' in 'ec11.nsf' completed execution

If your query contains errors / is not understandable, you will see an output similar like this on your console

[0DFC:0020-11D0] 30.12.2018 13:59:45   Agent Manager: Agent 'dql.execute' error: Domino Query execution error:   Query is not understandable -  syntax error     - processing or expecting operator (=, <, <= …) token syntax    (Call hint: OSCalls::OSLocalAllc, Core call 
0) firstname = 'Ulrich' And lastname IS 'Krause' …………………………….^……….. ****
[0DFC:0020-11D0] 30.12.2018 13:59:45 AMgr: Agent 'dql.execute' in 'ec11.nsf' completed execution


Modify Header / Footer items via Lotusscript ( and API )

Header / Footer items are of type Richtext and you cannot modify them directly using standard LotusScript.

I’ ve put together all the necessary code and wrapped the API calls into a class to achive the goal. The class works on Windows and Linux. Mac support is possible but I have no Mac to test with.

In addition the application contains code to get the size ( and other properties ) of embedded images in a richtext item. Another code snippet provides functionality to test if a richtext item is empty.

The code is an example to show how to access Notes RichText items on the CD Record level using LS2CAPI techniques.

The application is used as a sample database for EntwicklerCamp 2010, 10-Mar-2010, Gelsenkirchen, Germany.

OpenNTF: Download sample application

A word of warning: If you really not understand how the code works, DO NOT USE IT !!


LotusScript Debugger on Linux

I wanted to debug Lotusscript on my VM Linux Box. The OS is Ubuntu 9.10 and the client is Notes 8.5.1.
When I switch on the debugger and step into the script, the debugger loses focus on every step, regardless if you use the mouse or F8.

Anyone else having the same problem? Not sure if it is a bug or if debugging is not supported or something else …


Calendar Cleanup – undocumented LS functions

I am researching the Calendar Cleanup action in the Lotus Notes Calendar view.
The action executes a LotusScript agent that has two undocumented db calls CreateArchiveSettings and ArchiveNowByPolicy. The functions are used since the feature was introduced in Notes 7.

Obviously nobody ever looked into the code as there are no Google search results except this post on LDD that is still unanswered.


Get Logical / physical size and DAOS size with LotusScript

The admin client shows information about logical / physical size as well as DAOS size for a database.

Sizes1

But how to get this information via LotusScript? For the logical size you can use db.size. For the physical size there is no property in the NotesDatabase Class. But C-API to the rescue.

Put the following piece of code into the declaration section of a button or script library

Declare Function NSFDbOpen Lib "nnotes.dll" Alias "NSFDbOpen" (Byval dbName As String, hDb As Long) As Integer
Declare Function NSFDbClose Lib "nnotes.dll" Alias "NSFDbClose" (hDb As Long) As Integer
Declare Function NSFDbSpaceUsage Lib "nnotes.dll" Alias "NSFDbSpaceUsage" (Byval hDB As Long, retAllocatedBytes As Long, retFreeBytes As Long) As Integer

Now you can call the functions to retrieve the data

Sub Click(Source As Button)
Dim dbHandle As Long
Dim usedBytes As Long
Dim freeBytes As Long
Dim ServerName As String
Dim dbName As String
ServerName = "YourServerHere"
dbName = "YourDatabaseHere.nsf"
Dim db As New NotesDatabase ( ServerName, dbName )
Call NSFDbOpen ( ServerName +"!!" + dbName, dbHandle)
If dbHandle <> 0 Then
Call NSFDbSpaceUsage(dbHandle, usedBytes, freeBytes)
Msgbox  "Logical Size: " & Cstr(db.Size) & " Bytes || Physical Size: " & Cstr(usedBytes + freeBytes) & " Bytes" & " || DAOS: " + Cstr(db.Size -(usedBytes + freeBytes))
End If
NSFDbClose dbHandle
End Sub

This code snippet produces the following output.

Sizes

The DAOS size simply calculates as the difference between logical and physical size.


Get Column Totals with LotusScript

Here is a quick post in addition to my recent post on how to get sums / subtotals for a given category in a view with LotusScript.

totalsls

Assume, you want to get the total number of solved tickets. In my sample the value in question is located in column 7 at the very end of the ($ddTickets_ByMonthRep) view.

Here is the code that does the trick.

Sub Click(Source As Button)
	Dim s As New NotesSession
	Dim db As NotesDatabase
	Set db = s.CurrentDatabase
	Dim v As NotesView
	Dim n As NotesViewNavigator
	Dim e As NotesViewEntry
	Set v = db.GetView("($ddTickets_ByMonthRep)")
	Set n = v.CreateViewNav
	Set e = n.GetLast
	If e.IsTotal Then
		Msgbox e.ColumnValues(7)
	End If
End Sub

More (Yet) Undocumented Database Properties

Here is a list of yet undocumented values for the GetOtion / SetOption method of the NotesDatabase class.

GetOption(82) / SetOption(82,true) = Enable Compress document data
GetOption(81) / SetOption(81,true) = Use DAOS

Use DAOS also created a new field $DAOS in the NotesIcon design note if the field is not available and update the field value to 1 (enabled) or 0 (disabled) when the field is already present

Both are only available with ODS 51

GetOption(74) / SetOption(74,true) = still unknown, but adds O to $Flags

And here are a few database properties that can be get / set by modifying the $Flags field programmatically

$Flags = I = Inherit operating system theme from Notes preferences (ODS 51)
$Flags = q = Compress Database Design
$Flags = C = Allow connections to external databases using DCRs

Finally, if you want to find out, if the “Enable enhanced HTML Generation” property is enabled, check if field $AllowPost8HTML is available in the NotesIcon design note. The according theme is stored in $DBTheme.


Undocumented NotesDatabase.Get / SetOptions

Today, I was looking for which value to use with the SetOption method of the Notesdatabase class, I discovered as few other undocumented values that can be used to get and set some database options programmatically using Lotus Script.

75 = Support Response Thread History
76 = Don’t allow simple search

And, finally for the new Option in Notes 8.0.2

85 = Disable Export Of View Data

There is also a value of 74, but I could not figure out, which option corresponds to this value.


Export View Data (Update)

Last month I wrote about the new “Disable View Export” feature in Notes 8.0.2. In another post I stated that it is not possible to set this option programmatically using LotusScript.

Yesterday I stumbled upon an IBM Lotus Software Knowledgebase technote. This technote says that

Enabling or disabling of this option can also be done using an API call (setOption) or a  LotusScript (SetOption).

I cannot find anything about this in the designer help.  Has anybody any information about which (undocumented) “DBOPT_ …” constant to use with the notesDatabase.SetOption( optionName% , flag ) function?

UPDATE: 85 = Disable Export Of View Data
more undocumented stuff


Programmatically Check If Export Of View Data Is Disabled

In Lotus Notes /Domino 8.0.2 you can disable the export of view data by selecting this option in the application properties. To programmatically check if the export is disabled, you can use the following LotusScript.

Function IsExportDisabled () As Boolean
	IsExportDisabled = False
	Dim s As New NotesSession
	Dim db As NotesDatabase
	Set db = s.CurrentDatabase
	Dim IconDoc As NotesDocument
	Set IconDoc = db.GetDocumentByID("FFFF0010")
	If ( Not IconDoc Is Nothing ) Then
		If IconDoc.HasItem("$DisableExport") Then
			IsExportDisabled = True
		End If
	End If
End Function

Notes stores the information in the application’s icon design document. If export is disabled, the $DisableExport field is present. The script simply checks if the field is available. If so, export is disabled and the function returns true else false.


Mail Rules Extended

I recently posted an idea on IdeaJam to enhance the mail rules dialog on a Domino server to overcome the restriction of only use the “hard coded” conditions. There have been several attemps to enhance the dialog in the past ( Chris Linfoot for example ), but none of them adresses the use of a formula as a condition.

I’ve modified Chris’s sample db and added the requested functionality. You can download it here. To use it in your environment, replace the (RulesDlg) form and the Rules Script Lib in your names.nsf with the according design elements in the download.
Keep in mind that modifying the Domino Directory is dangerous if you are not sure of what your doing.


Is User A Member Of A (Nested) Group ?

Working with nested groups, it can be hard to determine if a user is member of the “base” group. The following class contains a method to do the job.

IsGroupMember ( GroupName, UserName ) calls method ExplodeGroup, which fills an array with all members of the group. It also resolves nested groups.

IsGroupMember now checks if the username is a member of this array using Lotusscript function ArrayGetIndex.

Class NotesDominoDirectory

	Private strServer As String

	Public Sub new (server As String )
		strServer = server
	End Sub

	Public Function ExplodeGroup (GroupName As String) As Variant

		Dim s As New Notessession
		Dim db As New NotesDatabase ( Me.strServer, "names.nsf" )
		Dim doc As NotesDocument
		Dim view As NotesView
		Dim i As Integer, j As Integer, k As Integer
		Dim arrGrp1, arrGrp2 As Variant

		Set view=Db.GetView ("($VIMGroups)")
		Set doc=View.GetDocumentByKey (GroupName)
		Redim arrMembers (1) As Variant
		j = 0

		If Not (doc Is Nothing) Then
			arrGrp1= Doc.GetItemValue ("Members")
			For i= 0 To Ubound (arrGrp1)
				arrGrp2= Me.ExplodeGroup (arrGrp1 (i))
				Redim Preserve arrMembers (Ubound (arrGrp2) + j) As Variant
				For k= 0  To Ubound (arrGrp2)
					arrMembers (j) = arrGrp2 (k)
					j = j + 1
				Next
			Next
		Else
			Redim arrMembers (0) As Variant
			arrMembers (0) = GroupName
		End If

		ExplodeGroup= Arrayunique (arrMembers)

	End Function 

	Public Function IsGroupMember ( strGroup As String, strUser As String ) As Boolean

		IsGroupMember = False

		If (Arraygetindex (Me.ExplodeGroup (strGroup), strUser , 5))  Then
			IsGroupMember = True
		End If

	End Function

	Public Function IsGroupMemberExt ( strGroup As String, strUser As String ) As Boolean
		' uses undocumented function
		Dim arrMembers As Variant
		IsGroupMemberExt = False
		arrMembers =
            Evaluate(|@ExpandNameList("|& strServer & |":"names.nsf";"|& strGroup &|")| )
		If (Arraygetindex ( arrMembers, strUser, 5)) Then
			IsGroupMemberExt = True
		End If
	End Function

End Class

Here is a sample of how to check if Ulrich Krause is member of group “Everybody”

Sub Click(Source As Button)
	Dim res As Variant
	Dim dd As New NotesDominoDirectory ("serv01/singultus")
	Msgbox dd.IsGroupMember ( "Everybody" , "CN=Ulrich Krause/O=singultus")
End Sub

There is also an undocumented @formula @ExpandNameList to expand a group and all nested groups to all the names.

Function IsGroupMemberExt ( strGroup As String, strUser As String ) As Boolean
	' uses undocumented function
	Dim arrMembers As Variant
	IsGroupMemberExt = False
	arrMembers =
         Evaluate(|@ExpandNameList("|& strServer &|":"names.nsf";"|& strGroup &|")| )
	If (Arraygetindex ( arrMembers, strUser, 5))  Then
	     IsGroupMemberExt = True
	End If
End Function

WordPress Plugin For LotusScript And Formula Syntax Highlighting

I’m using wordpress for blogging and have wp-syntax installed for quite a while as a syntax colour code/highlighter. wp-syntax supports many languages. But it does not support Lotus Script or @Formula language out of the box.

You can easily add support for these languages by adding a file to GeSHi, the Generic Syntax Highlighter, which is used in wp-syntax and some other plugins for wordpress.

I had done this a year ago for Notes 7. Now Richard Civil posted a new version for Notes 8. If your blog is based on wordpress and you are looking for an easy to implement, easy to use syntax colour code/highlighter to prettify your Lotus Script or formula code, jump over to RichardCivil.net.


Programmatically Change The Design Of A Local Database

From the Lotus Notes KnowledgeBase (#1280243)

You want to programmatically change or update the design of a local Lotus Notes® database from a template. For your particular scenario, replication is not an option. The database is local to the client, and there is no server replica to pull the design changes from. So you would like to use LotusScript to programmatically change the design.

First of all, the template with which you want to update the database design much also be local to this Notes client. If that is true, one way to accomplish this task is to use the LotusScript Shell command to call the convert program located on the Notes client.
The convert program takes the same commands as the server-based convert task. For example, if you want to update the local names.nsf database with the latest personal address book template, you could use the following code on a Microsoft® Windows® platform because the name of the program on Windows is nconvert.exe:

Sub Initialize
Dim result As Variant
result = Shell("nconvert -d names.nsf * pernames.ntf")
End Sub

When you call the convert program, it reads the notes.ini file and retrieves the ID value form the KeyFileName entry. The convert program runs under the authority of that ID.
You will be prompted to enter the password for that ID before the task continues if

  • the Notes client is not running, or
  • the Notes client is running and you have not selected “Don’t prompt for a password from other Notes-based programs” in your User Security preferences. (If you check that option, you are not prompted for a password if the Notes client is running.)

Get A JSONReader And JSONWriter For FREE

JSONTroy Reimer of SNAPPS donates LotusScript JSONWriter and JSONReader to the community.
You can download Version 1.0 of JSONReader and JSONWriter here.

The database (json.nsf) contains LotusScript classes for parsing and creating JSON text.
These classes are contained in five script libraries: ls.snapps.JSONArray, ls.snapps.JSONObject, ls.snapps.JSONReader, ls.snapps.JSONWriter, and ls.snapps.JSONWrapperConverters.

The JSONArray and JSONObject classes are wrapper classes that are used by the JSONReader class. Additional information can be found in the “Help – About This Database” document.

The JSON LotusScript Classes are also available on OpenNTF.