I have a couple issues with this script. It seems to grab the emails w/o issues but still delivers the “function requires valid ADT argument” message. It seems to be more annoying than harmful. I searched this forum and found entries that referenced deleted objects that were no longer accessible (e.g. a loop that deletes docs in Db). It mentioned using adoc1 and adoc2 vs. just adoc1. We are only grabbing emails and sending… no document deletions at all. What needs to be done to remove the message? Also, we need to save the document before sending (doc is open when button is clicked) or else there will be no contents in the body. I used uidoc.save right after the initial DIM statements. After the loops are done, I need to close/exit the memo. I had a uidoc.close (true) after the loop but it never seems to make it that far. Maybe it needs to be doc instead of uidoc on the exit.
Sub Click(Source As Button)
Dim ws As New NotesUIWorkspace
'get back end document for current ui document
Dim doc As NotesDocument
Set doc = ws.CurrentDocument.Document
’ set from address
doc.ReplaceItemValue "principal", "test@test.com"
’ set reply address - if required
doc.ReplaceItemValue "replyto", "test@test.com"
’ open email address database
Dim adb As New NotesDatabase("server", "emailtest.nsf")
If adb.IsOpen = False Then Exit Sub
’ open address view
Dim view As NotesView
Set view = adb.GetView("emails")
If view Is Nothing Then Exit Sub
’ get first document
Dim adoc As NotesDocument
Set adoc = view.GetFirstDocument
Dim who, x
’ loop and send
Do Until adoc Is Nothing
who = ""
For x = 1 To 100
who = who & adoc.GetItemValue("email")(0) & ";"
Print "adding address: " who
Set adoc = view.GetNextDocument(adoc)
If adoc Is Nothing Then Exit For
Next
who = Fulltrim(Split(who, ";"))
Print "sending message"
doc.ReplaceItemValue "blindcopyto", who
doc.Send False
Set adoc = view.GetNextDocument(adoc)
Loop
Michael, since you have a Do loop which executes until adoc is nothing, and a For loop which executes 100 times or until adoc is nothing, is it possible that adoc gets set to Nothing somewhere in the For loop (less than 100 docs in the view), and when you try to do the GetNextDoc as part of the Do loop, adoc has no value at that point?
Thanks and good point… we are testing in a view that has 10 documents (vs. 1000s). Could that be the issue? What would happen if you had 1020 docs? The final batch will always be an odd #.
who = ""
For x = 1 To 100
who = who & adoc.GetItemValue("email")(0) & ";"
Print "adding address: " who
Set adoc = view.GetNextDocument(adoc)
If adoc Is Nothing Then Exit For
Next
who = Fulltrim(Split(who, ";"))
Print "sending message"
doc.ReplaceItemValue "blindcopyto", who
doc.Send False
'Change your getnextdoc to below code
If Not (adoc Is Nothing) Then
Set adoc = view.GetNextDocument(adoc)
End If
Loop
Thanks… am testing now. Will post results in a couple seconds. I did try and lower it to “For x = 1 To 10” but still received the ADT message. Am trying yours now…
Are you saying that you don’t need to save the uidoc at all? Are you just using that to have a place to put the addressing info so you can send it or is there info in that doc, i.e., in a Body field that needs to be sent as part of the email?
Thanks for “staying with me” on this one… I like the way the question was asked. A user will create a memo (HTML mail) then hit the button. To answer your question… yes, the contents of the document (inc. SendTo as “test@test.com”) must be sent. Once sent (and loop is done), I need to make sure the document is saved (or even in sent folder is fine) and closed. The “call uidoc.save” allowed me to see the contents but the sendto was not showing up… was wondering about the placement in the script.
Ok, the way I see it is that with the For loop in there, let’s say there are 150 docs with addresses in the “emails” view. With the way this is written now, you would collect the first 100 addresses, put them into the blindcopyto field and send the email. Then, on the next iteration of the For…Next loop, you would get the remaining 50 into blindcopyto and send the email the second time.
Then, when it is finished, you want to save the uidoc. When you save it, the blindcopyto field will contain only the 50 email addresses. Does it matter that you will lose the first 100 or does it not matter what is in the blindcopyto field when the uidoc is saved?
Why not just put all the addresses into the blindcopyto and send the email just once to all, then save the uidoc?
This would make 100% sense (re: all 150 in the field at once)… but there are several 1000! We will actually bump the “Fpr x = 1 to 100” to a larger # like 300. 300 still only equals ~16K. We might even up the # to 400-500. I did test the loop (shutdown the router) and it worked fine on the real data. I let it process a few iterations then deleted from mail.boxes. It is 100% OK that the final addresses are the only ones in the blindcopyto field. We just want a record of what was sent. re: the save… will it need to be saved twice (once before loop and one at the end)? I was having to do the uidoc.save before the loop otherwise the body text/images were missing.
Michael, take a look at the code below. I did some rewriting of your original code.
When dealing with mail addressing fields, it is best to use an array to populate them, so what I did was set up a bcc variant array, then started looping through the docs in the email address view using a counter, bccctr%, to limit the number of addresses in the array to 100 at a time. This lets us loop through the entire view and send the email each time we hit the 100 mark and reset the counter variable.
After it finishes the loop, it then checks to see if any addresses have been collected but not used. This would apply if there were say 145 docs in the email view.
Take a look and let me know if this might work any better.
Dim ws As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Dim doc As NotesDocument
Dim view As NotesView ' open address view
Dim adoc As NotesDocument
Dim adb As New NotesDatabase("server", "emailtest.nsf") ' open email address database
If adb.IsOpen Then
Set uidoc = ws.CurrentDocument
Set doc = uidoc.Document 'get back end document for current ui document
doc.ReplaceItemValue "principal", "test@test.com" ' set from address
doc.ReplaceItemValue "replyto", "test@test.com" ' set reply address - if required
Set view = adb.GetView("emails")
If Not (view Is Nothing) Then
'Dim who, x
Dim bcc() As Variant
Redim bcc(0)
bccctr% = -1
Set adoc = view.GetFirstDocument ' get first document
Do Until adoc Is Nothing ' loop and send
bccctr% = bccctr% + 1
Redim Preserve bcc(bccctr%)
bcc(bccctr%) = adoc.email(0)
Print "adding address: " & bcc(bccctr%)
If bccctr% = 99 Then
Print "sending message"
doc.blindcopyto = bcc
Call doc.Send( False)
bccctr% = -1
End If
Set adoc = view.GetNextDocument(adoc)
Loop
If bccctr% >= 0 Then
Print "sending message"
doc.blindcopyto = bcc
Call doc.Send( False)
End If
Call uidoc.Save
Call uidoc.Close
Else
Msgbox "unable to access emails view in emailtest.nsf"
End If
Else
Msgbox "Unable to open emailtest.nsf"
End If
Great… will test now. All was working OK excpet for prompt at the end. I attempt to use “call uidoc.close” but the save/send&file/draft/discard prompt still appears. I did attempt to include doc.saveoptions= “0” 1 line before the uidoc.close. Are the quotes needed? I’ll try yours now… thanks again. I’ll be back in a few minutes.
Tried the script… seemed to process fine. I did notice that the contents of the body were missing. I had to insert a call uidoc.save to get the contents to show up. I also added a dim sendnow as integer and a YES/NO prompt to ask the user if he/she wants to proceed. I did encounter the save dialog at the end. I was hoping to see the final msgbox, click OK then be taken back to the view. I did add a msgbox at the end. You know what would be nice? If the msgbox contained the exact # of docs sent… instead of msgbox “Your emails have been sent” → msgbox “ emails were sent”.
Excellent… I’m posting the code here. I am getting an object variable not set error. I’m assuming it os the new entry (tried adding addcount as long - must be wrong). Also, I included the uidoc.save in the beginning because the body contents were missing w/o a save early on. What is missing here?
Dim ws As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Dim doc As NotesDocument
Dim view As NotesView ' open address view
Dim adoc As NotesDocument
Dim sendnow As Integer
sendnow = ws.Prompt (PROMPT_YESNO, _
"Send Now?", "Do you want to send to all customers now?")
If sendnow = 0 Then
Exit Sub
End If
Call uidoc.Save
Dim adb As New NotesDatabase("server", "test.nsf") ' open email address database
If adb.IsOpen Then
Set uidoc = ws.CurrentDocument
Set doc = uidoc.Document 'get back end document for current ui document
doc.ReplaceItemValue "principal", "test@test.com" ' set from address
doc.ReplaceItemValue "replyto", "test@test.com" ' set reply address - if required
doc.ReplaceItemValue "sendto", "test@test.com"
Set view = adb.GetView("emails")
If Not (view Is Nothing) Then
'Dim who, x
Dim bcc() As Variant
Redim bcc(0)
bccctr% = -1
Dim AddCount As Long
Set adoc = view.GetFirstDocument ' get first document
Do Until adoc Is Nothing ' loop and send
bccctr% = bccctr% + 1
Redim Preserve bcc(bccctr%)
bcc(bccctr%) = adoc.email(0)
Print "adding address: " & bcc(bccctr%)
AddCount& = AddCount& + 1
If bccctr% = 299 Then
Print "sending message"
doc.blindcopyto = bcc
Call doc.Send( False)
bccctr% = -1
End If
Set adoc = view.GetNextDocument(adoc)
Loop
If bccctr% >= 0 Then
Print "sending message"
doc.blindcopyto = bcc
Call doc.Send( False)
End If
Call uidoc.Save
Call uidoc.Close
Else
Msgbox "unable to access emails view in target database"
End If
Else
Msgbox "Unable to open target database"
End If
Msgbox Cstr(AddCount&) & " emails were sent."
Perfect… that got rid of the ADT message! …and I did not adjust the “For x = 1 to 100”. My only remaining issue… how to exit out of the document (was saved earlier -w- “call uidoc.save” without receiving the dialog to send&file/saveasdraft/discard… I just want it to close out. Also… I notice that my my sendto is not automatically populated with our test address .
Dim ws As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Set uidoc = ws.CurrentDocument
'get back end document and save for current ui document
Dim doc As NotesDocument
Set doc = ws.CurrentDocument.Document
’ set from address
doc.ReplaceItemValue "principal", "test@test.com"
’ set reply address - if required
doc.ReplaceItemValue "replyto", "test@test.com"
' set reply address - if required
doc.ReplaceItemValue "sendto", "test@test.com"
Call uidoc.Save
…then the rest of the script (open Db, loop, etc…)
Is the save in the right place? Maybe it should be in front of the ReplaceItem lines. I’m also wondering about the call uidoc.close (should it be something else or is true/false missing afterwards). Thanks for your continued assistance.