HCL Notes naar Lime CRM

In de afgelopen jaren zijn wij vaak bezig geweest met het converteren van IBM / HCL Notes data naar andere systemen.
Voor mail is dat vaak naar Exchange, pst bestanden, of via imap protocollen wanneer het Linux mail systemen betreft.
Documenten, vaak in maatwerk Notes applicaties is anders. Veelal ging de conversie naar PDF in een mappenstructuur met metainformatie in XML of CSV, of via database verbindingen naar SQL e.d.

Een aantal weken terug vroeg een klant, die na vele jaren helaas over moet naar een ander systeem, of wij een conversie konden uitvoeren van een maatwerk Notes ERM pakket naar Lime CRM.
Wij werden in contact gebracht met de technische mensen van Lime, in dit geval in Finland, die meteen de API documentatie beschikbaar stelde en heel behulpzaam waren met het beantwoorden van vragen.
Hierop hebben wij een Notes applicatie gemaakt gemaakt die met een combinatie van PDF afdrukken van Notes documenten, bestand export voor de bijlagen, en conversie van Notes velden naar Json API aanroepen, de Notes applicatie kon migreren naar Lime CRM.

Als vervolg hierop is nog een andere Notes applicatie op soortgelijke manier overgezet naar Lime en gekoppeld aan de relaties in Lime.

Het is natuurlijk heel erg jammer om een trouwe klant weg te zien gaan van HCL Notes, maar het geeft ook voldoening om dit technisch mogelijk te maken en met een goed resultaat af te kunnen sluiten.

HCL Domino Volt

Voeg een low-code tool toe aan uw arsenaal op een veilig platform dat u vertrouwt. Iedereen in IT kan webgebaseerde formulieren voor het vastleggen van gegevens en workflows bouwen met gegevens van Excel, meerdere gegevensbronnen of helemaal opnieuw.

Domino Volt maakt het mogelijk om nieuwe apps 60-70% sneller te bouwen, en maakt het voor ontwikkelaars en zakelijke gebruikers gemakkelijk om snel krachtige, veilige en enterprise-grade workflow-applicaties te ontwikkelen zonder gespecialiseerde vaardigheden.

Lees meer…

Terugvallen op de C API

Tussen de kerstdagen eigenlijk vrij gehouden, maar een klant heeft een redelijke simpele wens om alle encrypted berichten in een paar honderd IBM Notes mailfiles te decrypten voor een conversie naar Office 365, zonder tussenkomst van de gebruiker.
Met LotusScript liep ik helaas tegen een aantal bugs/beperkingen aan. Dus maar een virtuele Windows machine ingericht met de oude vertrouwde C compiler en Notes C API toolkit kijken of er om heen te programmeren valt.

Vanzelfsprekend is dit na enige hindernissen wel gelukt.
Met het notes.id van de gebruiker (dit is wel een noodzakelijk ding) kan een de versleuteling van een bericht in de postbus van die gebruiker opgeheven worden.
In dit geval heb ik een script gemaakt dat het ID van de gebruiker uit de ID Vault haalt, en het wachtwoord reset. Vervolgens wordt met dit ID en wachtwoord de berichten in de postbus ontsleutelt zodat de export naar Office 365 zonder problemen kan verlopen.

 

 

Opties in $Index veld in weergave ontwerp

Niet zo spannend maar wellicht toch handig om te weten is dat het veld $Index in een weergave ontwerp, als je deze bekijkt via de Designer of door middel van script, de opties voor de index van de weergave bevat.

Elke optie heeft een eigen letter met een notatie als /O enz.

Vernieuwen van de index (Refresh):

Als er geen /M, /O, of / R in het veld $Index staat, dan is de instelling “Auto, after first use”. Dit is de standaard waarde.

/O wil zeggen dat de Index “Automatic” dus automatisch wordt bijgewerkt wanneer dat nodig is.

/M staat voor de keuze “Manual” dus handmatig indexeren.

/R=3600 Dit staat voor “Auto, at most every x hours”, automatisch maar niet meer dan 1 keer per x uren waarbij de uren in ms opgegeven worden. In dit geval dus 1 keer per uur.

Verwijderen van de index na (Discard):

Wanneer er geen /P of /T in het veld $Index staat betekend dit de index na 45 dagen van inactiviteit wordt verwijderd, “If inactive for 45 days”. Dit is de standaard instelling.

/T wil zeggen dat de index na elk gebruik weer verwijderd wordt, “After each use”.

/P=24 De /P= is de parameter om de index te verwijderen (purge) in uren. /P=24 is dus na een dag van inactiviteit, instelling “If inactive for x days”.

Alleen een ontwerper of beheerder mag de index aanmaken:

/B zal in het veld staan wanneer “Restrict initial index build to designer or manager” is aangevinkt.

Deze opties samen in het veld $Index van een view object maken de Index opties. Zo kan het veld $Index bijvoorbeeld de waarde “/T/O/B” hebben of “/P=168/R=43200/B” enzovoort.

Ja en?

Ik had deze gegevens nodig om te bepalen of een onderhoudstaak geschreven in Visual Basic bepaalde weergaven moest vernieuwen of niet.

Met de NotesNoteCollection Class kun je eenvoudig de weergaven in een database krijgen en de eigenschappen uitlezen.

Dim nc As NotesNoteCollection
Set nc = db.CreateNoteCollection(False)
nc.SelectViews = True
Call nc.BuildCollection

 

 

 

 

NoteID

De NoteID van een document is een hexadecimale waarde van maximaal 8 tekens die een document uniek identificeert in een bepaalde database.

Een typische NoteID ziet er zo uit: 20FA.

Een NoteID vertegenwoordigt de locatie van een document in een specifiek databasebestand, dus documenten die replica’s van elkaar zijn, hebben over het algemeen verschillende NoteID’s.
Tenzij het document wordt verwijderd verandert een NoteID niet.

Speciale NoteID’s

Er zijn enkele speciale gereserveerde NoteID’s in Notes:

  • FFFF0002: “Over deze database” -document
  • FFFF0100: “Gebruik van deze database” -document
  • FFFF0004: Standaardformulier
  • FFFF0008: Standaardweergave
  • FFFF0010: Databasepictogram
  • FFFF0020: Database Design Collection (weergave)
  • FFFF0040: Database ACL
  • FFFF0800: Replicatieformule

notesDatabase.SetOption

Hoewel de functie notesDatabase.SetOption wel beschreven wordt in de Designer Help staan enkele waarden voor versie 8.5.1 er nog niet bij, daarom even in dit onderwerp.

Om de geavanceerde database eigenschappen met Lotusscript aan te passen bestaat de volgende  functie:

Call notesDatabase.SetOption( optionName% , flag )
Waarbij optionName% een waarde van het type Integer is.

Voor flag gebruik je True om de eigenschap aan te vinken, en False om het uit te zetten.

De volgende waarden zijn toegestaan:

12 = Geen idee wat dit doet?
36 = Vrije ruimte niet overschrijven (Don’t overwrite free space)
37 = Leesmarkeringen niet behouden (Don’t maintain unread marks)
38 = Speciale antwoordhierarchie niet ondersteunen ( Don’t support specialized response hierarchy)
41 = Documententabel optimaliseren (Optimize document table map)
44 = Eigenschap LastAccessed behouden (Maintain LastAccessed property)
45 = Transactielog uitschakelen (Disable transaction logging)
46 = Controleren op nieuws niet toestaan (Don’t allow headline monitoring)
49 = Voorlopig verwijderen toestaan (Allow soft deletions)
54 = Meer velden in database toestaan (Allow more fields in database)
65 = LZ1-compressie gebruiken voor bijlagen (Use LZ1 compression for attachments)
70 = Leesmarkeringen repliceren: Alleen clusterservers (Replicates unread marks: Clustered servers only)
71 =  Leesmarkeringen repliceren: Alle servers (Replicates unread marks: All servers)
74 =  Markeer de database als niet beschikbaar. (Out of service enabled)
75 = Threadhistorie ondersteunen (Support Response Thread History)
76 = Eenvoudig zoeken niet toestaan (Don’t allow simple search)
81 = Domino service voor bijlagen en objecten gebruiken (Use Domino Attachment and Object Service)
82 = Documentgegevens comprimeren (Compress document data)
85 = Export van viewgegevens uitschakelen (Disable export of view data)

Onbekende opties

Ik mis nog een aantal opties zoals de optie om “Weergaven automatisch bijwerken uitschakelen” (Disable automatic updating of views) en “Database-ontwerp comprimeren” (Compress database design) aan of uit te zetten.

Nieuw in 8.5: ResetUserPassword

Voor ontwikkelaars is er in Notes 8.5 een nieuwe functie bijgekomen om wachtwoorden via een applicatie te kunnen resetten: ResetUserPassword.

In LotusScript:
Call notesSession.ResetUserPassword( servername, username, password[, downloadcount ] )

In Java:
public void resetUserPassword(String servername, String username, String password[, Int downloadcount]) throws NotesException

ResetUserPassword kan alleen worden gebruikt als ID Vault is ingesteld.

Nieuw in 8.5: StampAllMulti – een voorbeeld hoe te gebruiken…

De nieuwe methode StampAllMulti voor de NotesDocumentCollection en NotesViewEntryCollection classes is een waardevolle aanvulling!
Nu kunnen we zeer snel meerdere velden in een documentenreeks van een nieuwe waarde voorzien.

Omdat er in de Lotus 8.5 Designer Help geen voorbeeld staat voor het gebruik post ik het even hier.
In dit geval maken we een document collectie door alle documenten in een view te selecteren, maken een nieuw (tijdelijk) document, vullen het document met een paar velden en roepen
de methode StampAllMulti aan om de velden uit het tijdelijke document te kopieren naar alle documenten in de collectie. Snel en effectief!

Voorbeeld:

Sub Initialize
Dim session As New NotesSession
Dim db As NotesDatabase
Dim view As NotesView
Dim vc As NotesViewEntryCollection
Dim doc As NotesDocument

Set db = session.CurrentDatabase
Set view = db.GetView(“StampMulti”)
Set vc = view.AllEntries

Set Doc = db.CreateDocument
Doc.ReplaceItemValue(“Company”,”INECO”).IsSummary = True
Doc.ReplaceItemValue(“Address”,”Hoge Riem 27″).IsSummary = True
Doc.ReplaceItemValue(“Zipcode”,”6666JA”).IsSummary = True
Doc.ReplaceItemValue(“City”,”Heteren”).IsSummary = True
Doc.ReplaceItemValue(“Country”,”The Netherlands”).IsSummary = True
Doc.ReplaceItemValue(“Phone”,”+31653353140″).IsSummary = True
Call vc.StampAllMulti( Doc )

End Sub

Uit de Help:

Replaces the values of specified items in all documents associated with the entries in a view collection.

Note
This method is new with Release 8.5.
Defined in

NotesViewEntryCollection
Syntax

Call notesViewEntryCollection.StampAllMulti( document )

EN

Parameters:

document
NotesDocument. The document contains multiple items, each with values appropriate for the item type.

Usage
If an item does not exist, it is created. If the item is of a different data type, the existing item will be deleted and a new item of the new data type created.

The item values are immediately written to the documents on the server. You do not have to use the Save method of NotesDocument after StampAllMulti. However, any documents modified by your script must be saved before calling StampAllMulti.

This method does not modify existing NotesDocument objects. Documents must be retrieved again to see the changes.

If you do not have the proper access to modify one or more of the documents in the view entry collection, this method will return ERR_NOTES_STAMP_FAILED. Only those documents you are able to modify will be stamped.

Getthreadinfo vervangt Lsi_info

Een van de dingen die ik mij zelf heb aangeleerd bij het maken van een applicatie is altijd gebruik te maken van een duidelijke foutafhandeling waarbij Lsi_info vaak werd gebruikt.

Meestal zag die code er ongeveer uit als:

Function doeDingen() As Boolean
On Error Goto ErrorHandler
‘Hier komt de code ….

Exit Function
ErrorHandler:
MsgBox Lsi_info(2) & ” : Error ” & Error & ” (” & Err & “) on line ” & Erl & “.”
Exit Function
Resume Next
End Function

Lsi_info

Lsi_info was in de vroegere versies van Lotus Notes eigenlijk de enige methode om informatie te krijgen over de huidige thread.

Een aantal regelmatig gebruikte gegevens waren:

Lsi_info(1) ‘Huidige regel in de Lotusscript Source Code
Lsi_info(2) ‘Huidige functie of sub
Lsi_info(3) ‘Huidige module
Lsi_info(6) ‘LotusScript versie
Lsi_info(9) ‘ Taal code
Lsi_info(11) ‘Totaal aantal code regels van de huidige module
Lsi_info(12) ‘Naam van de aanroepende functie of sub
Lsi_info(13) ‘Naam van de aanroepende module
Lsi_info(14) ‘Lijst van alle modules die aangeroepen zijn tot dit moment
Lsi_info(50) ‘ LotusScript Geheugen gealloceerd
Lsi_info(51) ‘LotusScript Geheugen gealloceerd van het besturingssysteem
Lsi_info(52) ‘LotusScript geheugen blokken in gebruik

IBM beweerd echter dat Lsi_info niet gebruikt mag worden omdat dit alleen bedoeld is voor intern gebruik en mogelijk voor een instabiel systeem kan zorgen, met name op 64Bit systemen.
Daarom heeft men in de meer recentere versies van Notes een nieuwe methode ter beschikking gesteld: GetThreadInfo.

GetThreadInfo

De aanbevolen schrijfwijze zou dan ook worden:

Function doeDingen() As Boolean
On Error GoTo ErrorLabel
‘En hier komt de code weer ….
Dim i As integer
i = Evaluate(“@Error”,Nothing)
ExitLabel:
Exit Function

ErrorLabel:
MsgBox GetThreadInfo(1) & ” : Error ” & Error & ” (” & Err & “) On Line ” & Erl & “.”, 16 , “Error”
Resume ExitLabel
End Function

 

Foutmelding

 

De aanroepen die ondersteund worden zijn:

Getthreadinfo(0) ‘LSI_THREAD_LINE: Huidige regel in de Lotusscript Source Code
Getthreadinfo(1) ‘LSI_THREAD_PROC: Huidige functie of sub
Getthreadinfo(2) ‘LSI_THREAD_MODULE: Huidige module
Getthreadinfo(3) ‘LSI_THREAD_VERSION: LotusScript versie
Getthreadinfo(4) ‘LSI_THREAD_LANGUAGE: Taal code
Getthreadinfo(5) ‘LSI_THREAD_COUNTRY: Regionale instelling
Getthreadinfo(6) ‘LSI_THREAD_TICKS:Krijg actuele kloktikken
Getthreadinfo(7) ‘LSI_THREAD_TICKS_PER_SEC: Krijg kloktikken per seconde (alleen ondersteund op platforms die parallelle verwerking van primitieven ondersteunen)
Getthreadinfo(8) ‘LSI_THREAD_PROCESS_ID: Huidige proces-ID ophalen (alleen ondersteund op platforms die primitieven voor parallelle verwerking ondersteunen)
Getthreadinfo(9) ‘LSI_THREAD_TASK_ID: Huidige taak-id ophalen (alleen ondersteund op platforms die primitieven voor parallelle verwerking ondersteunen)
Getthreadinfo(10) ‘LSI_THREAD_CALLPROC: Naam van de aanroepende functie of sub
Getthreadinfo(11) ‘LSI_THREAD_CALLMODULE: Naam van de aanroepende module

Bronnen:

https://www.ibm.com/support/docview.wss?uid=swg21237286 (deze link naar IBM werkt niet meer na de overname van Domino door HCL).
https://help.hcltechsw.com/dom_designer/9.0.1/appdev/LSAZ_GETTHREADINFO.html

 

LotusScript en Excel import van tekst bestand

Om 12000 documenten te exporteren naar Excel was een LotusScript agent te lang bezig met het vullen van de cellen.
Daarom is er gekozen om het bestand naar een comma gescheiden bestand weg te schrijven.
De klant vond het echter lastig om dit weer te openen in Excel, vandaar dat er een stukje code moest komen om dit te automatiseren.
Een stukje van de code:

Sub Initialize

Dim OfficeApplication As Variant
Dim workbook As Variant
Dim xlsheet As Variant
Dim ar() As Integer
Const xlNone = -4142
Const xlAutomatic = -4105
Const xlUnderlineStyleNone = -4142
Const xlThemeFontNone = -4142
Const xlInsertDeleteCells = 1
Const xlDelimited = 1
Const xlTextQualifierDoubleQuote = 1
Const xlTextFormat = 2

….. declareer dingen …

fList(“Form”) = “Form”
…. etc…

Set ws = New NotesUIWorkspace
filenames = ws.SaveFileDialog(False,”File name”,, “c:\”, “export” & Format(Today,”ddmmyyyy”) & “.txt”)
If (Isempty(filenames)) Then
Exit Sub
End If

Set curDB = Session.CurrentDatabase
Set View = curDB.GetView(“myView”)
View.AutoUpdate = False

fileNum% = Freefile()
Open filenames(0) For Output As fileNum%

Forall i In fList
mString$ = mString$ & “,” & i
End Forall
Print #fileNum%, Strright(mString$,”,”)

Set Doc = View.GetFirstDocument
Do Until Doc Is Nothing
mString$ = “”

Forall i In fList
If Doc.HasItem(Listtag(i)) Then
Set item = Doc.GetFirstItem(Listtag(i))
Select Case item.Type
Case 768
mString$ = mString$ & “,” & Replace(Doc.GetFirstItem(Listtag(i)).Text,”,”,”.”)
Case 1024
mString$ = mString$ & “,” & Replace(Format(item.Values(0),”dd-mm-yyyy”),”-“,”/”)
Case Else
mString$ = mString$ & “,” & Replace(Doc.GetFirstItem(Listtag(i)).Text,”,”,”;”)
End Select
Else
mString$ = mString$ & “,”
End If
End Forall
Print #fileNum%, Strright(mString$,”,”)

Set Doc = View.GetNextDocument(Doc)

Loop

Close fileNum%

con = “TEXT;” & filenames(0)
If Not (setOfficeApplication(“Excel.application”)) Then Exit Sub ‘ start Excel met een functie

rgbColor& = xlNone

x = 0
Forall i In fList
Redim Preserve ar(x) As Integer
ar(x) = xlTextFormat
x = x + 1
End Forall

Set workbook = OfficeApplication.Workbooks.Add ()
Set xlsheet = OfficeApplication.Workbooks(1).Worksheets(1)
With xlsheet.QueryTables.Add(con,xlsheet.Range(“A1″) )
.Name = Strright( filenames(0),”\”)
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 1252
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = ar
.TextFileTrailingMinusNumbers = True
.Refresh
End With

ExcelClose:

On Error Resume Next
OfficeApplication.Cells.EntireColumn.Autofit
OfficeApplication.Rows(“1:1″).Select
OfficeApplication.Selection.AutoFilter
OfficeApplication.Visible = True

Exit Sub
ErrorHandler:
Msgbox Lsi_info(2) & ” ” & Error & ” (” & Err & “) on line ” & Erl
Resume ExcelClose

End Sub