Programming examples

Working with the Notes C++ API

I have just started to delve into the murky world of the Notes C++API (and the C API), and not having found much information on the web, thought I'd start my own small part of the web on the subject.

Although I'm also learning C++ as I embark on this exercise, I don't intend this column to become a C++ tutorial. I am drawing on the inspiration of the book "LotusScriptor's Plain Simple Guide to the Notes C++ API" by Lee Powell (www.notesapi.com), and "LotusScript to Lotus C API Programming" by Normunds Kalnberzins.

While Lee's book give some good examples, it does not delive deep into some of the real world examples that you might need to look at when writing API programs. I hope to fill in that gap here.

I am using Visual Studio 2003, so you will need to configure your project properties in the following way.

  1. Under "C/C++ — General" add the Notes C++ API include directory in the Additional Include Directories property — mine is C:\notescpp\include
  2. Under "C/C++ — Preprocessor" add W32 to the PreProcessor Definitives.
  3. Under "C/C++ — Code Generation", change Struct Member Alignment to 1 byte.
  4. Under "Linker — Input" add c:\notescpp\lib\mswin32\notescpp.lib to the Additional Dependancies property.

Example One: Open a database and printout the database title — the hello world of Notes API programming!

#include <stdafx.h>
// The Notes C++ API header file.
#include <LNCPPAPI.H>
// The following 2 lines are required to use any of the standard C functions such as cout.
#include <iostream>
using namespace std; // VS2003 uses namespaces so add this line. You could prefix cout with std::cout instead.

int main(int argc, char *argv[])
{
char errorBuf[LNERROR_MESSAGE_LENGTH];
LNNotesSession session;
LNDatabase nab;
LNSetThrowAllErrors( TRUE ); // get the API to trow catchable errors rather than return a status code from each operation.
try
{
session.Init();
session.GetDatabase("names.nsf", &nab, "server1/organisation");
nab.Open();
cout << "Opened database names.nsf — it's title is " << nab.GetTitle() << endl;
}

catch (LNSTATUS error )
{
LNGetErrorMessage( error, errorBuf);
cout << "Error: " << errorBuf << endl;
}
nab.Close();
session.Term();
return 0;
}

This example shows the basics of initialising a Notes Session object, getting a database object from the session, opening it, and then printing out it's title. Finally, we close the database and terminate the session.

So now we have the basics, lets expand on this, opening a view object from the database, locating a document from the view, and printing out a value from an item in the document.

Example Two: Retrieve a document from a view in the NAB and printout the person's full name from the fullname item.

#include "stdafx.h"
#include "LNCPPAPI.H"
#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
char errorBuf[LNERROR_MESSAGE_LENGTH];
LNNotesSession session;
LNDatabase nab;
LNViewFolder nabView;
LNVFFindOptions options;
LNVFEntry entry;
LNINT count;
LNDocument doc;
LNItem item;
LNString strText;

LNSetThrowAllErrors( TRUE );
try
{
session.Init();
session.GetDatabase("names.nsf", &nab, "server1/organisation");
nab.Open();

// get a view object representing the users view in the NAB
db.GetViewFolder("$Users", &nabView);
nabView.Open();

// These options affect the way in which an entry in the view is searched for.
// These settings are equivalent to the True in view.GetDocumentByKey( searchText, True) in LotusScript.
options.SetComparison(LNVFCOMPARISON_EQ); // Make the view search look for EQUALS
options.SetMatchWholeWord(TRUE); // make the view search match on a whole word only.

cout << "Searching for administrator" << endl;
view.Find("administrator", &entry, &count);

// Find will only get a viewentry object (entry), so we need to get the associated document from the entry.
entry.GetDocument( &doc );
// must open the document before we can inspect it.
doc.Open();

// get the fullname item from the document
doc.GetItem("Fullname", &item);

// item returns an array ( as would doc.getItemValue in LotusScript), so put the array[0] value into a LNString object from where we can print it out.
strText = item[0];
cout << "Fullname is " << strText ;
}

catch (LNSTATUS error )
{
LNGetErrorMessage( error, errorBuf);
cout << "Error: " << errorBuf << endl;
}

doc.Close();
nabView.Close();
nab.Close();
session.Term();
return 0;
}

Now we have added opening a view from the database, and finding an entry in the view. Locating something in the view means we have to set a few options in the LNVFFindOptions object. These are similar to using the GetDocumentByKey options, where you can specify Exact Match using True or False in the second parameter. Here we say that the comparison for a match must be EQUALS, so it be an exact match, and we set MatchWholeWord to True to stop it doing a partial match on the string.

Unlike LotusScript, finding an entry in a view index will return an entry object (like NotesViewEntry), rather than a document. So, having located the right entry in the view, we have to get the document using GetDocument() and then open it. Finally, we can locate the Item in the document we are looking for using GetItem (similar to the GetFirstItem method of NotesDocument in LotusScript). Note here we are returning the Item into a generic item class of LNItem, as we do not know it's type. To discover its type, use the LNNote.GetType() method, and then get the item into LNText etc.