Can't get to any info from Lotus Notes using VBA - excel

Thanks in advance for any help!
I'm ultimately trying to pull information from specific emails based on subject line. Working up to the problem the below code was a test to pull up a subject line. However it runs through 132 documents without a single subject identified as anything other than blank. Using this same Initialize and GetDatabase method I successfully sent emails through Lotus Notes, so I don't think I'm after the wrong docs somehow. Below code written in VBA through Excel have Lotus Notes 8.5
Anyone see a reason why I would get nothing but blanks going through all of the docs in the Notes Database?
Sub LotusGetView()
Dim Nsess As New NotesSession
Dim Ndb As NotesDatabase
Dim Ndocs As NotesDocumentCollection
Dim Ndoc As NotesDocument, docNext As NotesDocument
Dim c As Long
Dim memSubj As Variant
Nsess.Initialize
Set Ndb = Nsess.GetDatabase("", "names.nsf")
Set Ndocs = Ndb.AllDocuments
c = 1
Set Ndoc = Ndocs.GetFirstDocument
Do Until Ndoc Is Nothing Or c = 1000
Set docNext = Ndocs.GetNextDocument(Ndoc)
memSubj = Ndoc.GetItemValue("Subject")(0)
If memSubj <> "" Then
MsgBox memSubj
End If
Call Ndoc.Remove(True)
Set Ndoc = docNext
c = c + 1
Loop
MsgBox c
End Sub

Your problem is this line:
Set Ndb = Nsess.GetDatabase("", "names.nsf")
You are opening names.nsf. That is the user's personal address book database. It is not the user's mail database. Your previous work to send mail worked because you don't need to access a mail database to send mail. You can send mail from anywhere. In order to read mail, you have to open the mail database.
The OpenMailDatabase method of the NotesDbDirectory class provides an easy way for you to find and open the current user's mail database.

Related

Trouble with sending emails with vba via IBM Notes

with the function below, I have the option of sending e-mails from Excel via IBM Notes. Basically, it works very well. However, I recently had to revise the code, as the message text was always inserted under the IBM Notes signature. I was able to solve this problem, but unfortunately two problems have now emerged that I did not had before.
I am grateful for every tip and every help!
UPDATE 21.12.2021 21:30: #Tode I've followed your instructions but the problems are still there. May be I've failed to put the codelines in the right order?
The problems
The "Save" function no longer works, i.e. IBM Notes also saves the e-mail in the "Sent" folder if I do not want it (parameter blnSaveEMail = false).
The second problem has to do with my work context: I have two email accounts. A personal service e-mail address jdoe#company.com (mailfile: jdoe.nsf) and a branch e-mail address mybranch#company.de (mailfile: mybranch.nsf). As far as I could determine, both mail files are in the same base directory. If I use the code below with my personal e-mail, the parameter blnQuickSend = true works without problems, if I use my branch e-mail address, IBM Notes asks me whether I want to save the changes, although I would like to send an e-mail without asking.
I hope I was able to describe my issue clearly and understandably. I thank you for your attention!
Warm greetings from Dresden
Sergeij
PS: I'am a german native :), thankfully Google helped me a lot to translate my problem in english.
The code
Public Function Send_EMail( _
varRecipient As Variant, _
varCopyTo As Variant, _
varBlindcopyTo As Variant, _
strSubject As String, _
strMessage As String, _
strAttachement As String, _
Optional blnSaveEMail As Boolean = True, _
Optional blnQuickSend As Boolean = False, _
Optional strAlternative_Mailfile As String _
) As Boolean
Dim objLotusNotes As Object
Dim objMaildatabase As Object 'Die Maildatabase
Dim strMailServer As String 'Der Mailserver
Dim strMailFile As String ' Die Maildatei
Dim objEMail As Object 'Die E-Mail in IBM Notes
Dim objAttachement As Object 'Das Anlage Richtextfile Object
Dim objSession As Object 'Die Notes Session
Dim objEmbedded As Object 'Attachement
Dim arrAttachements() As String 'Liste mehrere Anhänge
Dim lngIndex As Long
Dim strFilepath As String
Dim objNotesfield As Object 'Datenfeld in IBM Notes
Dim objCurrentEMail As Object 'Aktuelle E-Mail
'Start an IBM Notes Session
Set objSession = CreateObject("Notes.NotesSession")
'Open IBM-Notes-Database
strMailServer = objSession.GetEnvironmentString("MailServer", True)
If VBA.Len(strAlternative_Mailfile) = 0 Then
strMailFile = objSession.GetEnvironmentString("MailFile", True)
Else
strMailFile = "mail/" & strAlternative_Mailfile
End If
Set objMaildatabase = objSession.GETDATABASE(strMailServer, strMailFile)
'If your constructed path (variable strMailFile) is wrong or the database cannot be accessed
'then this line will make sure to fallback to the mailfile configured in your location document in Notes Client.
If Not objMaildatabase.IsOpen Then objMaildatabase.OPENMAIL
'Create new email
Set objEMail = objMaildatabase.CREATEDOCUMENT
'set saveoption
objEMail.ReplaceItemValue "SAVEOPTIONS", "0"
'Put content in fields
Set objNotesfield = objEMail.APPENDITEMVALUE("Subject", strSubject)
Set objNotesfield = objEMail.APPENDITEMVALUE("SendTo", varRecipient)
Set objNotesfield = objEMail.APPENDITEMVALUE("BlindCopyTo", varBlindcopyTo)
Set objNotesfield = objEMail.APPENDITEMVALUE("CopyTo", varCopyTo)
'Load workspace
Set objLotusNotes = CreateObject("Notes.NotesUIWorkspace")
'Add attachements
arrAttachements = VBA.Split(strAttachement, ";")
For lngIndex = LBound(arrAttachements) To UBound(arrAttachements)
strFilepath = arrAttachements(lngIndex)
If strFilepath <> "" And VBA.Dir(strFilepath) <> "" Then
Set objAttachement = objEMail.CREATERICHTEXTITEM("Attachment" & lngIndex)
Set objEmbedded = _
objAttachement.EMBEDOBJECT(1454, "", strFilepath, "Attachment" & lngIndex)
End If
Next
'Open eMail in frontend and assign to NotesUIDocument variable
Set objCurrentEMail = objLotusNotes.EDITDOCUMENT(True, objEMail)
'Put content into email
objCurrentEMail.GotoField "Body"
objCurrentEMail.InsertText strMessage
'Check, whether the email should be sent immediately or not
If blnQuickSend = True Then
'Send email
objCurrentEMail.Send
'Save email, if requested
If blnSaveEMail Then objCurrentEMail.Save
'Close email
objCurrentEMail.Close
End If
'Return TRUE
Send_EMail = True
End Function
Ok... where should I start... there are some logical errors in your code based on not understanding the methods you use and the difference between frontend- and backend- classes...
Let's begin at the top:
'Check whether the maildatabase is open or not 'Throws an error,
'if the database is not open
If Not objMaildatabase.IsOpen Then objMaildatabase.OPENMAIL
Your comment is wrong. No error is thrown at all. If your constructed path (variable strMailFile) is wrong or the database cannot be accessed then this line will make sure to fallback to the mailfile configured in your location document in Notes Client.
'Create new email-document
objLotusNotes.EDITDOCUMENT True, objEMail
Again: Comment is wrong. What this command does is: It opens the email that you created in backend (represented by variable objEMail) in the frontend.
'Select the current email
Set objCurrentEMail = objLotusNotes.CurrentDocument
and assigns it to a NotesUIDocument- frontend- variable (select the current email is wrong).
As "EDITDOCUMENT" already returns as NotesUIDocument, you could shorten this like this:
'Open eMail in frontend and assign to NotesUIDocument variable
Set objCurrentEMail = objLotusNotes.EDITDOCUMENT(True, objEMail)
After having created a frontenddocument you still continue to manipulate the (now linked) backend document. You should move the creation of the frontend all the way down to the end of your code as having a document open in frontend does not work well with manipulating the same document in backend, especially when handling NotesRichtextItems and attachments. So move the above lines just below the for- loop.
'Set if email should be saved or not
objEMail.SAVEMESSAGEONSEND = blnSaveEMail
Yes... but no: You set the property SAVEMESSAGEONSEND to the backend document objEMail. Unfortunately the frontend- document objCurrentEMail does not care at all for this. To have your code obey this option, you would have to use the send- method of objEMail, not the send- method of objCurrentEMail.
If you want the frontend to not save a document that it sends, you need to do it differently by setting a field called "SAVEOPTIONS" to "0":
objEMail.ReplaceItemValue( "SAVEOPTIONS", "0" )
'Send email
objCurrentEMail.Send False, varRecipient
regarding your comment: almost... unfortunately you try the NotesDocument backend method "send" (that has 2 parameters) against the NotesUIDocument- Object "objCurrentEMail.
NotesUIDocument has a send method as well, but it does not have any parameters..normally an error should be thrown here....
EITHER you try to send the backend:
objEMail.Send False, varRecipient
OR you send it in the frontend:
objCurrentEMail.Send
Your "objCurrentEMail.Close" will always ask you if you want to save the document unless you have set SAVEOPTIONS = "0". If you really want to save the document after sending, use
objCurrentEMail.Save
before the close.
Hope that helps you sort out some of the issues.

Sending an email using VBA and IBM Lotus Notes

I know about topics dealing with similar problem but none of them solves directly my problem (or at least I don't see it). I am using following code:
Sub SendEmailUsingCOM()
'*******************************************************************************************
' Unlike OLE automation, one can use Early Binding while using COM
' To do so, replace the generic "object" by "commented" UDT
' Set reference to: Lotus Domino Objects
'*******************************************************************************************
Dim nSess As Object 'NotesSession
Dim nDir As Object 'NotesDbDirectory
Dim nDb As Object 'NotesDatabase
Dim nDoc As Object 'NotesDocument
Dim nAtt As Object 'NotesRichTextItem
Dim vToList As Variant, vCCList As Variant, vBody As Variant
Dim vbAtt As VbMsgBoxResult
Dim sFilPath As String
Dim sPwd As String
'*******************************************************************************************
'To create notesession using COM objects, you can do so by using.
'either ProgID = Lotus.NotesSession
'or ClsID = {29131539-2EED-1069-BF5D-00DD011186B7}
'Replace ProgID by the commented string below.
'*******************************************************************************************
Set nSess = CreateObject("Lotus.NotesSession") 'New:{29131539-2EED-1069-BF5D-00DD011186B7}
'*******************************************************************************************
'This part initializes the session and creates a new mail document
'*******************************************************************************************
sPwd = Application.InputBox("Type your Lotus Notes password!", Type:=2)
Call nSess.Initialize(sPwd)
Set nDir = nSess.GetDbDirectory("")
Set nDb = nDir.OpenMailDatabase
Set nDoc = nDb.CreateDocument
'*******************************************************************************************
'If you want to send it to multiple recipients then use variant array to get the names from
'the specified range as below
'Add / Remove Comment mark from vCCList as per your needs.
'*******************************************************************************************
vToList = Application.Transpose(Range("A1").Resize(Range("A" & Rows.Count).End(xlUp).Row).Value)
vCCList = Application.Transpose(Range("B1").Resize(Range("B" & Rows.Count).End(xlUp).Row).Value)
'*******************************************************************************************
'If you want to send it to multiple recipients then use variant array to get the names from
'the specified range as below
'Add / Remove Comment mark from vCCList as per your needs.
'*******************************************************************************************
With nDoc
Set nAtt = .CreateRichTextItem("Body")
Call .ReplaceItemValue("Form", "Memo")
Call .ReplaceItemValue("Subject", "Test Lotus Notes Email using COM")
With nAtt
.AppendText (Range("C2").Value)
'Decide if you want to attach a file.
vbAtt = MsgBox("Do you want to attach document?", vbYesNo, "Attach Document")
Select Case vbAtt
Case 6
.AddNewLine
.AppendText ("********************************************************************")
.AddNewLine
sFilPath = Application.GetOpenFilename
Call .EmbedObject(1454, "", sFilPath) '1454 = Constant for EMBED_ATTACHMENT
Case 7
'Do Nothing
End Select
End With
Call .ReplaceItemValue("CopyTo", vCCList)
Call .ReplaceItemValue("PostedDate", Now())
Call .Send(False, vToList)
End With
End Sub
The code stops at Set nSess = CreateObject("Lotus.NotesSession") saying Run-time error 429: ActiveX component can't create object
I saw some discussions about missing nnotes.dll but when I try to add it using Tools>References> and browse to the nnotes.dll file, it says "Can't add a reference to the specified file"
For sure I miss some basic knowledge, but I would just love to make it work and send specific ranges in excel via email.
Do you know, ideally step by step, what I should do?

running mail doc, server link not working properly

Problem :
Using Agent run and send mail give a different link
Mail Contain a link which is not include database
I set it send to a yahoo mail
Sub Initialize()
Print"Agent:First Reminder for LateIn Reason started running at " & DateValue(Now()) & "," + TimeValue(Now())
Dim ss As New NotesSession
Dim db As NotesDatabase
Dim LateInVw As NotesView
Dim LateInDocs As NotesViewEntryCollection
Dim LateEntry As NotesViewEntry
Dim LateDoc As NotesDocument
Dim StaffVw As NotesView, StaffDoc As NotesDocument
Dim MailDoc As NotesDocument
Dim rtBody As NotesRichTextItem
Dim sysdoc As NotesDocument, sysVw As NotesView
Dim AttVw As NotesView, Attdoc As NotesDocument
Set db=ss.Currentdatabase
Set sysVw=db.getview("($System Settings)")
Set sysdoc=sysvw.getfirstdocument
If sysdoc Is Nothing Then Exit Sub
Set LateInVw=db.getview("(Testing Late-In Time Records)")
Set StaffVw=db.getview("($Active Staff by ID)")
Set AttVw = db.Getview("($Effective Attendance Setting By ID)")
tdy=Datevalue(Now)
'get all time records for today
Set LateInDocs=LateInVw.Allentries
Set lateEntry=LateInDocs.getfirstentry
Do While Not LateEntry Is Nothing
Set LateDoc=LateEntry.Document
Set Attdoc=Attvw.Getdocumentbykey(LateDoc.TStaffID(0), True)
If Attdoc.LateAtt(0)="Yes" Then
If LateDoc.LateReason(0)="" Then
If Not ApprovedLateIn(LateDoc, LateDoc.TAmend(0), False) Then
'get staff mail
Set staffDoc=StaffVw.Getdocumentbykey(LateDoc.TStaffID(0), True)
If Not staffdoc Is Nothing Then
'send email with link to main menu
If email$<>staffDoc.email(0) Then
' email$=staffDoc.email(0)
email$="chee111385#gmail.com"
Set Maildoc=New NotesDocument(db)
Set maildoc=db.Createdocument()
maildoc.Form="First Reminder Notification"
maildoc.Subject="Smartcard Attendance System: Late-In Notification for " +Format$(LateDoc.TDate(0),"dd/mm/yyyy")
Maildoc.StaffName=staffDoc.StaffName(0)
maildoc.Sendto="chee111385#gmail.com"
' maildoc.NotifyDate=LateDoc.Tdate(0)
maildoc.NotifyTime=Timevalue(LateDoc.TAmend(0))
maildoc.NotesServer=sysdoc.ServerPath(0)
maildoc.NotesDBPath=sysdoc.DBPath(0)
maildoc.send(True)
End If
End If
End If 'check against unimas's jadual kedatangan
End If 'check for late in reason
End If 'check late-in on/off in attendance settings
Set LateEntry=LateInDocs.Getnextentry(LateEntry)
Loop
End Sub
I will attach my image file and coding here
from this 2 image you can see that, actually i want to put as a
notes://Mulu/SmartCard Attedancce/sas-server.nsf/Scais Main?OpenFrameset
but result of the mail send out is
notes:////Scais Main?OpenFrameset
which is no server and database. I am not sure what part of my coding is wrong
Another attachment will be the form i use as mail.form
First of all: Sending an external mail with a custom form like you do it is not the best Idea, as the target system might not be able to render everything accordingly.
That said, I would first create a document that contains all data and then RENDER it to a maildoc. code would look like this:
Dim Templatedoc as NotesDocument
Dim body as NotesRichtextItem
Set Templatedoc=New NotesDocument(db)
Set Templatedoc=db.Createdocument()
Templatedoc.Form="First Reminder Notification"
Templatedoc.StaffName=staffDoc.StaffName(0)
' maildoc.NotifyDate=LateDoc.Tdate(0)
Templatedoc.NotifyTime=Timevalue(LateDoc.TAmend(0))
Templatedoc.NotesServer=sysdoc.ServerPath(0)
Templatedoc.NotesDBPath=sysdoc.DBPath(0)
Set maildoc=New NotesDocument(db)
maildoc.Form = "Memo"
maildoc.Subject="Smartcard Attendance System: Late-In Notification for " +Format$(LateDoc.TDate(0),"dd/mm/yyyy")
maildoc.Sendto="chee111385#gmail.com"
Set body = New NotesRichtextItem( maildoc, "Body" )
Call Templatedoc.RenderToRTItem( body )
maildoc.send(True)
Second: You set two fields (NotesServer and NotesDBPath) to compute your Link. But your link in reality is computed from environment- variables, and these are not set on the server.
Change your Link- Computation- Formula to:
srv := NotesServer;
pth := NotesDBPath;
That should do the trick for the link.

Searching Lotus Notes Databases

I have around 50 lotus notes databases which I need to search through (including RTFs and attachments) based on a rather complicated query (for example: If customer = a or b or c or d or e ... or z & product = x or y) then == match; and a tag to (e.g. tag = found or not found)
However, I wasn't sure the best way to go about this and wanted to check three options.
Using Lotus' 'Search in View' should, after indexing, search all the databases - however I am unsure if it will accept a long, complicated search query
Coding an agent in Lotus SCRIPT to basically perform the search in 1. but this might be a way of getting it to accept a complicated query
Using external software (e.g. X1 Professional Search) to search outside of Lotus Notes (however I am not sure if I will be able to tag the files if I identify them in windows explorer).
Edit: My idea is:
Sub Initialise
Dim session as New NotesSession
Dim db as NotesDatabase
Dim dc as NotesDocumentCollection
Dim doc as NotesDocument
Dim searcy_query$
'On current database
Set db = session.CurrentDatabase
'Force index of database
Call db.UpdateFTIndex(True)
'Construct QUERY
search_query = "(Customer1|Customer2) & (Product1|Product2)"
'Search
Set dc = db.FTSearch(query, 0)
If dc.Count=0 Then
Msgbox "No matches!"
Exit Sub
End If
‘Tag the matched documents with “Flag”
Call dc.StampAll("Flag","Active)")
End Sub
However, I am not sure if this will return all matches and also regarding #TRIM and #UPPER (where to put them into the query as I will be searching all fields and RTFs rather than specific ones)
First of all: Searching more than one database at a time can of course be done "manually" by searching each individual database, collection the results and find a way to present the documents "somehow" (what will not be easy, as documents from different databases cannot be shown in "one" view - you would need to use "shadow- documents" or a web- approach (e.g. XPages))
BUT: Lotus Notes has a built-in function to do this, it is called "Domain Indexer". You can read more about how to setup "domain index" in this IBM Link or in your administration help.
Examples for using the domain- index for multi- database- searches can be found in catalog.nsf in the form "DomainQuery".
The search- string does not have a limit as far as I know, so that you can do very complex searches with this technique and it gives you all the matches.
If you search for a LotusScript- Solution, check the documentation for NotesDatabase.ftdomainsearch for example code like this (taken from developer help):
The following code, when placed in a button on a search form within a directory catalog database, searches the directory for the specified query string, and returns all results.
Sub Click(Source As Button)
Dim s As New NotesSession
Dim db As NotesDatabase
Dim w As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Dim doc as NotesDocument
Dim quer As String
Dim srdoc as NotesDocument
Set db=s.CurrentDatabase
Set uidoc = w.currentdocument
uidoc.refresh
Set doc=uidoc.Document
quer=doc.query(0)
On Error Resume Next
If db.isopen Then
If Err <> 0 Then
Messagebox STR_DBOPEN_ERROR, 0 , STR_ERROR
Err = 0
Exit Sub
End If
Set srdoc = db.ftdomainsearch(quer, 0)
If Err <> 0 Then
Messagebox STR_NDF , 0 , STR_LOTUS_NOTES
Err=0
Exit Sub
End If
srdoc.Form="SearchResults"
Call w.EditDocument(False, srdoc, True)
End If
End Sub
If you also intend to search Rich Text, the simplier way is Full Text Search, you got the point!
The syntax for your query is:
generic_text or ([_CreationDate]<07.10.2014 and ([CustomerFieldName]="Smith" or [CustomerFieldName]="Wesson"))
For formating the Result, I'ld suggest looking at:AppendDocLink for something like:
Dim session As New NotesSession
Dim db As New NotesDatabase("", "resu.nsf")
Dim newDoc As NotesDocument
Dim rtitem As NotesRichTextItem
Dim dc As NotesDocumentCollection
Dim doc As NotesDocument
Set newDoc = New NotesDocument( db )
Set rtitem = New NotesRichTextItem( newDoc, "Body" )
'you have to loop on your 50 DBs
'Search =>from your code
Set dc = db.FTSearch(query, 0)
while not doc is nothing
Call rtitem.AppendDocLink( doc, db.Title )
Call rtitem.AddTab( 1 )
Call rtitem.AppendText( doc.FieldImportantInResult( 0 ) )
Call rtitem.AddNewLine( 1 )
Set doc = dc.GetNextDocument( doc )
Wend
newDoc.save true, true
'this part is not to add it you plane to run your search in background
Dim w As New NotesUIWorkspace
Call w.EditDocument(False, newDoc, True)

Lotus Notes: Is it possible to create a view that excludes documents in all folders other than Inbox?

I am aware that you can exclude certain folders - but you have to name them. I need a view to show only the documents in the inbox, that doesn't need updating everytime we create a new folder.
Any help would be greatly appreciated!
:)
It is not possible directly. There are no formulas that would help you build a select statement to get documents that are only in the Inbox. However, you could have an agent run on a scheduled basis (maybe every 5-10 minutes) that would update documents and flag them if they are in the inbox. Your view would then just need to select documents that have that flag set.
Updated As umeli pointed out, the flag needs to be unset when documents are moved out of the Inbox. Here's a modified script:
For example:
Dim s as New NotesSession
Dim db as NotesDatabase
Dim view as NotesView
Dim doc as NotesDocument
Dim allEntriesInbox as NotesViewEntryCollection
Dim allEntriesFlagged as NotesViewEntryCollection
Set s = New NotesSession
Set db = s.CurrentDatabase
Set view = db.GetView("($Inbox)")
Set viewFlagged = db.GetView("IsInInboxView")
Set allEntriesInbox = view.AllEntries
Set allEntriesFlagged = viewFlagged.AllEntries
allEntriesFlagged.StampAll("IsInInbox", "")
allEntriesInbox.StampAll("IsInInbox, "1")
Your view (named "IsInInboxView" in this example) should have a selection formula of IsInInbox = "1"

Resources