How to create a lotus notes document from a dxl file, with win32com in Python? - lotus-notes

I have export a lotus notes document into a dxl file.
Now, I want to read the exported dxl file in another lotus notes id. How to create a lotus notes document from the dxl file?
Grammar of lotus script seems not suitable for python win32com.

The HCL Domino Designer Help provides detailed information about LotusScript/COM/OLE Classes and has a lot of examples on how to use them. The documentation can be accessed online here.
Use NotesSession and NotesDXLImporter as a starting point.
DXL information (text, file) can be imported into a target database by creating an instance of NotesDXLImporter using NotesSession.CreateDXLImporter and calling NotesDXLImporter.Import on the created instance. Options to be used for the import can be set on NotesDXLImporter.
The following code snippet originates from the HCL Domino Designer help.
Sub Initialize
Dim session As New NotesSession
Dim db As NotesDatabase
Dim dbCopy As NotesDatabase
Set db = session.CurrentDatabase
filename$ = Left(db.FileName, Len(db.FileName) - 4)
REM Open dxl file named after current database
Dim stream As NotesStream
Set stream = session.CreateStream
If Not stream.Open("c:\dxl\" & filename$ & ".dxl") Then
Messagebox "Cannot open " & filename$,, "Error"
Exit Sub
End If
If stream.Bytes = 0 Then
Messagebox "File did not exist or was empty",, filename$
Exit Sub
End If
REM Create new database named current database + "Copy"
Set dbCopy = New NotesDatabase("", "")
Call dbCopy.Create("", filename$ & "Copy", True)
REM Import DXL into new database
Dim importer As NotesDXLImporter
Set importer = session.CreateDXLImporter(stream, dbCopy)
importer.ReplaceDBProperties = True
importer.ReplicaRequiredForReplaceOrUpdate = False
importer.ACLImportOption = DXLIMPORTOPTION_REPLACE_ELSE_IGNORE
importer.DesignImportOption = DXLIMPORTOPTION_CREATE
Call importer.Process
End Sub
I have never done Notes COM API programming using Python's win32com but using VisualBasic and C#. Technically there should be no difference.

Related

VBA Sharepoint Check In File after Upload

Been using this code for a while to upload a file to SharePoint and noticed the other day that when the file is uploaded, it is checked out to myself automatically and have to go into SharePoint and manually check-in so that others can view the file. Any way to modify or add to my code below to auto check-in a file after it uploads? Totally stumped and any help would be greatly appreciated.
Sub SharePointUpload()
Dim WSN
Dim spAdd
Set WSN = CreateObject("WScript.Network")
spAdd = "https://mysharepoint/test"
WSN.mapnetworkdrive "N:", spAdd
ActiveWorkbook.Save
Dim SharepointAddress As String
Dim LocalAddress As String
Dim objNet As Object
Dim FS As Object
' Where you will enter Sharepoint location path
SharepointAddress = "\\mysharepoint\test"
' Where you will enter the local file path
LocalAddress = "C:\data\sample_file.xlsm"
Set objNet = CreateObject("WScript.Network")
Set FS = CreateObject("Scripting.FileSystemObject")
If FS.FileExists(LocalAddress) Then
FS.CopyFile LocalAddress, SharepointAddress
Else: MsgBox "File does not exist!"
End If
Set objNet = Nothing
Set FS = Nothing
WSN.removenetworkdrive "N:"
End Sub
I had the same issue with our SharePoint Document library even with option Require Check Out switched off - some documents (Word, Excel) were uploaded as Checked Out automatically (green arrow mark) whereas others were in fact Checked In from upload. Moreover when I wanted to Check In manually such documents, I got error message about missing mandatory field, although there was no field in the library set as mandatory.
The reason in my case was the field Title. This field is presented in library as default text field and it is also presented in Office files. I noticed that for Office files with empty field Title the document is automatically Checked Out during upload. When uploaded document contained some text in Title property, no Check Out was set. I also tried to use workflow to change the Title and then Check Out file (after creation), but it was not working - initial Check In was required to start the workflow. Manual change of document properties works but that's too tedious...
The first programmatic option to handle this issue could be to fill Title property of uploaded document when empty (i.e. add file name or any other text). Should work well with many languages. Example with Python:
from docx import Document
path = 'D:/myfile.docx'
document = Document(path)
document_property = document.core_properties
if not document_property.title:
document_property.title = 'Everything is Awesome'
document.save(path)
In VBA Title should accessible via Wb.BuiltinDocumentProperties("Title").
Another successful option for me was to find column Title in Columns of Document library and rename it to something else (I used Titlex as new name), then try to upload new document with empty Title - this time there was no automatic Check Out for the uploaded document. Then I could set the Titlex back to Title without returning the issue.

How can Lotus Notes detect whether a document is currently being opened?

As title.
How can Lotus Notes detect whether a document is currently being opened?
The solution should without "Document locking" because of User's User needs.
I have 1 maindoc and 1 subdoc, but subdoc and maindoc are not parents.
I use the "IsUIDocOpen" but it just worked at currentdocument.
Is there any other way to do this?
If you ask just for one client, then this is doable without document locking, but it needs some advanced techniques:
You can use NotesUIWorkspace to get a currently open document for any given backend document if you set parameter "newInstance" to false.
To get the currently open document (as uidocument, but of course you can use .Document property to get NotesDocument from it) you use the following code. If it returns nothing then the document is not open:
Dim ses as New NotesSession
Dim ws as New NotesUIWorkspace
Dim docToGetFrontendFor as NotesDocument
Dim uidoc as NotesDocument
Set docToGetFrontendFor = .... 'somehow get the document you wanna have the frontend for
Call ses.SetEnvironmentvar( "PreventOpen" , "TRUE" )
Set uidoc = ws.EditDocument( False, docToGetFrontendFor, False, "", True, False )
If not uidoc is Nothing then '-document was open already
'- do whatever with the frontend- document
Why the ses.SetEnvironmentvar( "PreventOpen" , "TRUE" )?
The EditDocument opens the document regardless of it being open already or not.
You need to prevent the document from opening, if it is not already open. Therefor you manipulate the "QueryOpen"- Event of the Form of the document:
Sub Queryopen(Source As Notesuidocument, Mode As Integer, Isnewdoc As Variant, Continue As Variant)
Dim ses as New NotesSession
Dim strPrevent as String
strPrevent = ses.GetEnvironmentstring( "PreventOpen" )
Call ses.SetEnvironmentVar( "PreventOpen" , "" )
If strPrevent = "TRUE" Then Continue = False
End Sub
So: The document does NOT open, if PreventOpen is set, so if it is not already open it will stay closed.
This approach has one big downside: The Notes Client has a "BUG": If you open a document and save it and then open it again with my code, then it will Open in a second window DESPITE the parameter "newInstance" set to false unless you closed and reopened that document.
Explained:
Create Document
Save document
Close document
Reopen document
Use my code
==> Works as the code just "reuses" the window
Create Document
Save document
Use my code
==> Will try to open a second instance for the document and then return NOTHING as this new instance does not open because of the code...

Lotus Notes Database Search

i am trying to write a code to open VBA and do search based on the cell value in A1 (integer). i managed to write a code up to point where i can open the lotus notes and go to specific database. I tried many online codes but couldn't manage to find the code to search in that database. "Lotus.NotesSession" doesn't work the excel version i use. Could you please help me to finish this code. Code is below:
Sub macro4()
Dim uiWs As Object
Dim dbname As String
Dim serverName As String
Dim db As NotesDatabase
Dim doccol As NotesDocumentCollection
Dim varA As Integer
dbname = "***"
serverName = "***"
Set uiWs = CreateObject("Notes.NotesUIWorkSpace")
Call uiWs.OpenDatabase(serverName, dbname)
Set db = uiWs.GetDatabase(serverName, dbname) ---->where i get the error
varA.Value = Sheets("sheet1").Range("A1").Value
Set doccol = db.FTSearch(varA, Nothing, 0)
End Sub
In Notes there are two "parent"- classes to derive everything from. The NotesUIWorkspace is the class for the "frontend": It contains everything that you SEE in the client. The NotesSession is the class for the backend. NotesDatabase is a backend- class. To correctly get your database, you need to use NotesSession:
Set ses = CreateObject("Notes.NotesSession")
Set db = ses.GetDatabase(serverName, dbname)
You mixed up COM and OLE Integration. The thing you tried to use (Lotus.NotesSession) is for COM only and you need to include Notes in your project to use this.
For your example to work you need to use the OLE integration: Notes.NotesSession
Now to your "Search"- Code:
There are two different ways to search a NotesDatabase:
There is the Fulltextsearch and the "normal" search.
The Fulltextsearch just searches for your value everywhere in all documents and returns a collection. A search for "Tom" in a mailfile will find all mails / calendar entries that where:
sent by Tom
received by Tom
have the word "Tom" in subject or body or an attachment of the mail.
The syntax for FTSearch is:
Set doccol = db.FTSearch( YourSearchValue )
You can restrict the search to one certain field by using a special syntax for your search. e.G. to only search in the "From" field you could write
[From] = "YourSearchValue"
In FTSearch the "=" always means "contains"
The normal search uses a Formula (in #Formula- syntax) to search for a document. It needs the right syntax, otherwise it will not find anything. A formula to search all documents that come from "Tom" would be:
#Contains( From ; "Tom" )
The syntax for search is:
Set doccol = db.Search( YourQueryAsExampleAbove, Nothing, 0 )
With Nothing = Cutoffdate (if given only return documents created or modified after the date) and 0 = max. number of documents to return (0 = return everything).
So your example code for the could be something like:
strQuery = "FieldToSearch = " & Sheets("sheet1").Range("A1").Value
Set doccol = db.Search( strQuery, Nothing, 0 )
After calling OpenDatabase successfully, you can use
set uiDb = uiWS.CurrentDatabase
That will get a NotesUIDatabase object, and then you can use
set db= uiDb.Database
That will get you the NotesDatabase object that you need in order to call the FTSearch method.

$Ref flag reappears even after deletion

We have an Xpage based Web mail-in application. Some emails are coming with $Ref field (response document). We wanted to convert them into normal document by removing $Ref field so that it will no longer a response one. We are able to delete the $ref field but it reappears again after saving the documents from web interface(xpage) and it makes all such documents again response document. This started happening recently and working well earlier. Can you please suggest what is the root cause? How to stop it?
Sub Initialize
On Error GoTo ErrorHandler
Dim s As New NotesSession
Dim db As NotesDatabase
Dim coll As NotesDocumentCollection
Dim doc As NotesDocument
Dim count As Long
Set db = s.Currentdatabase
Set coll = db.Unprocesseddocuments
MessageBox "Count : " & coll.Count
'Exit Sub
count = 1
Set doc = coll.Getfirstdocument()
While Not doc Is Nothing
If doc.Hasitem("$Ref") Then
Call doc.Removeitem("$Ref")
Call doc.Save(false, false)
End If
Print count
count = count + 1
Set doc = coll.Getnextdocument(doc)
Wend
Exit Sub
ErrorHandler:
MessageBox "Error " & Error & " at line " & Erl
Exit Sub
End Sub
Try changing your save method to Call doc.Save(true, false).
This will force the document save, and also prevent creating a response.
Also verify that you are running the agent on a server not accessable to active users. Also verify that you are only running your agent once, and that it isn't enabled on multible replicas.
Have you tried using If(doc.isResponse) Then instead of If doc.Hasitem("$Ref") Then
Note: I am looking in the java editor, but assume that the isResponse method is also in LS.
Wheather a document is a response is controlled by a property of the used form. As long as you do not assign another form that is a "Document" and not a "Response", you will most probably not be able to remove the "isresponse"- flag. As already told: most probably your xpage saves the "frontend" document after your backend manipulation and resets the state (form validation enabled in xpage properties). But without source code of the xpage one cannot tell.
Check the form name. Emails can use either the "Memo" form or the "Reply" form. Emails using the Reply form are response documents. You may also need to change the form to "Memo".

Lotus Notes - Export emails to plain text file

I am setting up a Lotus Notes account to accept emails from a client, and automatically save each email as a plain text file to be processed by another application.
So, I'm trying to create my very first Agent in Lotus to automatically export the emails to text.
Is there a standard, best practices way to do this?
I've created a LotusScript Agent that pretty much works. However, there is a bug - once the Body of the memo exceeds 32K characters, it starts inserting extra CR/LF pairs.
I am using Lotus Notes 7.0.3.
Here is my script:
Sub Initialize
On Error Goto ErrorCleanup
Dim session As New NotesSession
Dim db As NotesDatabase
Dim doc As NotesDocument
Dim uniqueID As Variant
Dim curView As NotesView
Dim docCount As Integer
Dim notesInputFolder As String
Dim notesValidOutputFolder As String
Dim notesErrorOutputFolder As String
Dim outputFolder As String
Dim fileNum As Integer
Dim bodyRichText As NotesRichTextItem
Dim bodyUnformattedText As String
Dim subjectText As NotesItem
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
'INPUT OUTPUT LOCATIONS
outputFolder = "\\PASCRIA\CignaDFS\CUser1\Home\mikebec\MyDocuments\"
notesInputFolder = "IBEmails"
notesValidOutputFolder = "IBEmailsDone"
notesErrorOutputFolder="IBEmailsError"
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
Set db = session.CurrentDatabase
Set curview = db.GetView(notesInputFolder )
docCount = curview.EntryCount
Print "NUMBER OF DOCS " & docCount
fileNum = 1
While (docCount > 0)
'set current doc to
Set doc = curview.GetNthDocument(docCount)
Set bodyRichText = doc.GetFirstItem( "Body" )
bodyUnformattedText = bodyRichText.GetUnformattedText()
Set subjectText = doc.GetFirstItem("Subject")
If subjectText.Text = "LotusAgentTest" Then
uniqueID = Evaluate("#Unique")
Open "\\PASCRIA\CignaDFS\CUser1\Home\mikebec\MyDocuments\email_" & uniqueID(0) & ".txt" For Output As fileNum
Print #fileNum, "Subject:" & subjectText.Text
Print #fileNum, "Date:" & Now
Print #fileNum, bodyUnformattedText
Close fileNum
fileNum = fileNum + 1
Call doc.PutInFolder(notesValidOutputFolder)
Call doc.RemoveFromFolder(notesInputFolder)
End If
doccount = doccount-1
Wend
Exit Sub
ErrorCleanup:
Call sendErrorEmail(db,doc.GetItemValue("From")(0))
Call doc.PutInFolder(notesErrorOutputFolder)
Call doc.RemoveFromFolder(notesInputFolder)
End Sub
Update
Apparently the 32KB issue isn't consistent - so far, it's just one document that starts getting extra carriage returns after 32K.
With regards the 32Kb thing, instead of this:
Set bodyRichText = doc.GetFirstItem( "Body" )
... you might want to consider iterating all "Body" fields in the email document. When dealing with large amounts of rich text, Domino "chunks" said content into multiple rich text fields. Check some documents you're processing: you may well see multiple instances of the "Body" field when you look at document properties.
I'm not sure what is causing the 32K bug, but I know there are lots of limitations in the order of 32K or 64K within Lotus Notes, so perhaps you're running into one of those. I can't imagine what would add extra CR/LFs. Perhaps you could try using the GetFormattedText method on the NotesRichTextItem class and see if it fares better?
It's more complicated, but you might also be able to use the NotesRichTextNavigator class to iterate through all the paragraphs in the memo, outputting them one at a time. Breaking up the output that way might eliminate the CR/LF problem.
Lastly I always suggest Midas' LSX for dealing with rich text in Lotus Notes. They sell an add-on that gives you much more control over rich text fields.
As for best practices, one that comes to mind when I read your code is the looping construct. It is more efficient to get the first document in a view, process it, and then get the next doc and check whether it is equal to Nothing. That sets the loop to run through the view in index order, and eliminates the need to search through the index to find the Nth document each time. It also saves you from maintaining a counter. The gist is as follows:
Set doc = curview.GetFirstDocument()
While Not (doc Is Nothing)
'Do processing here...
Set doc = curview.GetNextDocument(doc)
Wend
The external eMail most likely comes in as MIME. So you could check the document.hasMime and then use the mime classes to get to the content. Then you don't have a 64k limit. Samples are in the help - or reply if you want code.

Resources