Automation (VBA, Notes 6.5)

The below code works in our current environment (Win2000, Access 2000, Notes Client 5.0.9a).

We are moving to WinXP, Access 2003, Notes 6.5. The below code works, except that it does not include the body of the email.

Any ideas?

Function fSendEmail(strFileName, strPosterLoc) As Boolean

'In: strFilename: File to attach to email

’ strPosterLoc: Location to Email for

'Out: Sends an email via Lotus Notes

’ Succsess = True/False

'Maint Log:

'Who When What

'— ---- ----

'WJSchan 2/2/04 - Added:

’ notesDoc.Principal = strSharedMailBox

’ notesDoc.ReplyTo = strSharedMailBox

’ notesDoc.SaveMessageOnSend = True

’ So that the email would look like it came from ‘Trust Financial Controls-St Paul’,

’ and be saved in the sent folder.

’ - Changed email so that the Shared Email Box was not cc:'d

’ - Changed subject line to → Please “Reply with History”

’ from → Please “Reply to Trust Financial Controls-St Paul”

'WJSchan 2/10/04 - Added Users ID to the bottom of the email body, so for research purposes

’ we would know who the email came from.

’ In the sent folder of TFC-SP it will always show from the user who is looking

’ at the email.

'On Error GoTo fSendEmail_ErrHandle

Dim db As Database, rsContacts, notesSess As Object

Dim notesDB As Object, notesDoc As Object, notesItem As Object

Dim varEmailAddress As Variant

Dim strBody As String, EmbedMyfile As Object, i As Integer, intCount As Integer

Dim strRecipient() As String, intPos As Integer

Dim strSharedMailBox As String

Const conQuote = “”“”

Const conDeptName = “Trust Financial Controls - St. Paul”

Const conStreetAddr = “60 Livingston Avenue”

Const conMailStation = “Mailstation: EP-MN-WN3M”

Const conCityStateZip = “St. Paul, MN 55107”

Const conFaxNumber = “(651) 767-9222”

Set db = CurrentDb()

Set rsContacts = db.OpenRecordset(“SELECT * FROM qry_Contacts_To_Email WHERE (((Owner) Like ‘" & strPosterLoc & "’));”)

If rsContacts.RecordCount = 0 Then

Call MsgBox("There are no items to email!", vbOKOnly + vbExclamation, "No items qualify")

fSendEmail = False

GoTo fSendEmail_Exit

End If

'Start lotus - if lotus is not already open the user will need to enter a password

Set notesSess = CreateObject(“Notes.Notessession”)

'Mail Settings:

Set notesDB = notesSess.GetDatabase(“**********", "”) 'Taken out for LDD Posting

rsContacts.MoveFirst

Do While Not rsContacts.EOF

'These mail settings must be re-created everytime the a new mail is sent,

'so that the SaveMessageOnSend option works correctly.

'They must be set to nothing at the bottom of the loop as well:

Set notesDoc = notesDB.CreateDocument

Set notesItem = notesDoc.CreateRichTextItem("BODY")

Set EmbedMyfile = notesItem.EMBEDOBJECT(1454, "", strFileName, "") 'Attachment



varEmailAddress = rsContacts("Contacts")



If rsContacts("Contact_Unknown") Then

    notesDoc.Subject = "Aged Exceptions - " & conQuote & "UNKNOWN Contact" & conQuote

Else

    notesDoc.Subject = "Aged Exceptions (Location: '" & rsContacts("Owner") _

        & "') - Action Required -- Please " & conQuote & "Reply with History" & conQuote

End If



strBody = "We have determined that poster location '" & rsContacts("Owner") & "' "

strBody = strBody & "has " & rsContacts("Items") & " exception(s) that will be aged "

strBody = strBody & rsContacts("AgeCriteria") & " days or older as of Friday, "

strBody = strBody & rsContacts("AgeAsOf") & ". The attached Excel Spreadsheet is a list of "

strBody = strBody & "all aged items in accounts reconciled by Trust Financial Controls - St. Paul. "

strBody = strBody & "You can find your items by sorting on Poster Location or by using the filter "

strBody = strBody & "for your poster location." & ddm_DoubleSpace

strBody = strBody & "Our goal is to clear ALL exceptions prior to day 15, and those which have "

strBody = strBody & "surpassed 15 days are escalated as needed to management." & ddm_DoubleSpace

strBody = strBody & "Please respond within 2 business days with a status update as to when the items "

strBody = strBody & "will clear." & ddm_DoubleSpace

strBody = strBody & "Thank you for your assistance." & ddm_DoubleSpace

strBody = strBody & "TFCSP Reference: " & GetUserName() & ddm_DoubleSpace

strBody = strBody & "* * * * * * * * * * * * * *" & vbCrLf

strBody = strBody & conDeptName & vbCrLf

strBody = strBody & conStreetAddr & vbCrLf

strBody = strBody & conMailStation & vbCrLf

strBody = strBody & conCityStateZip & vbCrLf

strBody = strBody & "Fax " & conFaxNumber

notesDoc.body = strBody



'Find the number of Recipients -- You must ReDim the Array with only the number of Recipients!!!

intCount = 1 'Assume there is one

For i = 1 To Len(varEmailAddress)

    If Mid(varEmailAddress, i, 1) = "," Then intCount = intCount + 1

Next i

intCount = intCount - 1 'Arrays start @ Zero

ReDim strRecipient(intCount) As String

If intCount > 0 Then

    For i = 0 To intCount

        If i < intCount Then

            intPos = InStr(1, varEmailAddress, ",")

            strRecipient(i) = Mid(varEmailAddress, 1, intPos - 1)

            varEmailAddress = Mid(varEmailAddress, intPos + 2, Len(varEmailAddress))

        ElseIf i = intCount Then

            strRecipient(i) = Mid(varEmailAddress, 1, Len(varEmailAddress))

        End If

    Next i

ElseIf intCount = 0 Then 'There was only one Recipient

    strRecipient(intCount) = varEmailAddress

End If

notesDoc.SendTo = strRecipient

'notesDoc.CopyTo = strUser 'Use for cc

'notesDoc.BlindCopyTo = strUser 'Use for bcc

strSharedMailBox = rsContacts("SharedMailBox")

notesDoc.Principal = strSharedMailBox

notesDoc.ReplyTo = strSharedMailBox

notesDoc.SaveMessageOnSend = True

Call notesDoc.Send(False) 'Send the email!



Set notesItem = Nothing

Set notesDoc = Nothing

Set EmbedMyfile = Nothing



rsContacts.MoveNext

Loop

'Succsess

fSendEmail = True

fSendEmail_Exit:

On Error Resume Next

rsContacts.Close

Set rsContacts = Nothing

Set notesItem = Nothing

Set notesDoc = Nothing

Set EmbedMyfile = Nothing

Exit Function

fSendEmail_ErrHandle:

Select Case Err.Number

Case 7294 'Email Recipient not valid

    Call MsgBox("Email to Poster Location '" & rsContacts("Owner") & "' failed!" & ddm_DoubleSpace _

        & "Re: '" & varEmailAddress & "' is not a valid email address." & ddm_DoubleSpace _

        & "Have the work co-ordinator fix this poster location, and re-send the email " _

        & "to just this location. All other emails were sent successfully.", vbCritical + vbOKOnly, _

        "Error sending email ...")

    UpdateActionLog ("Email to poster location '" & rsContacts("Owner") & "'failed. " _

        & "Email address: '" & varEmailAddress & "' is not valid")

    Resume Next

Case Else

    fSendEmail = False

    Call CommonErrorMsg("Command: " & "fSendEmail", Err.Number, Err.HelpFile, Err.HelpContext)

End Select

End Function

Subject: Instead of: notesDoc.body = strBody Try: Call notesItem.AppendText(strBody)

Subject: Automation (VBA, Notes 6.5)

You have two competing Body fields. To add text to the body, use notesItem.AppendText(string). And please rename that variable – never use reserved words as variable names; they will come back to bite you some day.

Subject: What Stan says…PLUS

…by all means don’t concatenate all your strings via “&” (because this is slow and inefficient).

Use “+” instead.

BAD :strBody = strBody & "Fax " & conFaxNumber

GOOD: strBody = strBody + "Fax " + conFaxNumber

If conFaxNumber isn’t a string, then use this:

strBody = strBody + "Fax " + Cstr(conFaxNumber)

Thomas - IBM

Subject: RE: What Stan says…PLUS

Thanks for the tips. The code now works as expected.

Subject: RE: What Stan says…PLUS

Thomas,

is using a Cstr really more efficient than “&” and if so, what is the difference.

This is just a curiosity question.

Subject: RE: What Stan says…PLUS

Yeah … what’s wrong with &?

Is it really that slow that I should worry about including Cstr each and every time I’m putting together some text?

Subject: RE: What Stan says…PLUS

Yes, I am wondering the same thing too. I use & as the concatanation operator all the time. The Designer Help mentions the following, but does not say which is faster. Based on the structure of the instruction, it seems that the & operator should be preferred over +.

Use the ampersand (&) operator to ensure a concatenation operation. The plus (+) operator also concatenates two character strings, but LotusScript determines whether to interpret the plus as a concatenation operator or an addition operator on the basis of the operands in the expression in which it appears.

</Designer Help>

The Redbook ‘Performance Considerations for Domino Applications’, provides a lot of tips on string operation using LotusScript. In all the examples provided, the & operator is being used instead of the + operator. This is what is noted in that redbook, too.

Use Automatic Conversion When Converting Numbers to Strings

The automatic conversion that happens when a text is concatenated with a number is, in fact, slightly more efficient than doing the manual conversion. The difference is small, so this is not something to change code for. It is mentioned here to allow designers the freedom to use either technique, knowing they are not affecting performance if they prefer one style over another. Fragment A is slightly faster than fragment B.

Fragment A

s2$ = “Text ” & ii

Fragment B

s2$ = “Text ” & Cstr(ii%)

Note In fragment A, when using automatic conversion, you cannot add a% suffix to indicate integer type (since the syntax wants string types).

Subject: Damien Katz says there probably isn’t a huge difference

See my question How slow is an ampersand? and his answer in the comments, along with some other useful comments from others.

Subject: Thank you (WAS: Damien Katz says there probably isn’t a huge difference)

Subject: Thank you (WAS: Damien Katz says there probably isn’t a huge difference)

The speed difference between & and + in string concatenations is less than 0.1% with long strings, where + is faster, but with small strings and lots of & and + operations, & is faster.

Subject: RE: Thank you (WAS: Damien Katz says there probably isn’t a huge difference)

… but as much as 30% in particular. The concatenator seems to be faster than explicit conversions (Cstr) for simple scalar literals. (See File Save’s tests over at Ben’s site.) However, that is one version of the copiler and runtime on one version of Notes on one particular install.

Generalisations are bad. I go along with Donald Knuth – write the code correctly, and don’t optimise until the compiler/interpreter has proven itself incompetent. If there are known (that’s KNOWN, not fabled or merely suspected) issues with a legal method, then optimise, if not, then otherwise.

Subject: So, which do you think is correct?

I mean, should we use “&” or “+” or simply use whichever we prefer, in your opinion? Ironically, I always use Cstr for numbers even if I also use “&”, which makes no sense. I do it more because I may be wrong about a type than anything else.

Subject: RE: So, which do you think is correct?

Personally, I use + religiously simply because I’m less likely to make a major error when switching back to @Functions. & is exclusively a logical AND there, and it can really bungle your debugging efforts if you get them confused.

Subject: RE: So, which do you think is correct?

Interesting … but I think I’m going to leave my code alone for now. & is just fine for me and I like it when my agents finish. :o)

Handy tip (thanks) but I’m not about to go into my code and rewrite everything into arrays.

Subject: *Interesting point. Does make copying back and forth easier

Subject: *Interesting point. Does make copying back and forth easier

On the other hand, when different programming languages use same symbols for different operations, you make easily mistakes, just think how many times you have done if(a=b) {} in Java(Script) or C(++) :)I think it’s good to be always awake and aware in what programming language you are coding, and not throw things in which you were used to in other languages. Isn’t it kinda the same as when you speak many languages, and you start to mix the words between each. Also here, beeing aware is the best solution imo, but yeah I know people who get totally confused when you first speak english to them, and then suddenly switch to german (because you realize their english isn’t so good and you know they speak german as native language, so you just wanna be polite), and they don’t realize the switch and keep answering in english :slight_smile:

Subject: RE: *Interesting point. Does make copying back and forth easier

“you make easily mistakes, just think how many times you have done if(a=b) {} in Java(Script) or C(++)”

But that’s exactly my point. By using + instead of & in LS, you are bringing the languages into closer syntactic alignment, which reduces the likelihood that you’ll make a mistake.

This was a practice that started for me about 6 years ago, when I’d spent a solid 4 weeks writing nothing by LS, and then went back to some simple form design. I couldn’t figure out why I kept getting errors and other strangeness when I’d write a CFD field with: FirstName & " " & LastName

At the time, my thought was “I spend 80% of my time in one of these two languages – I might as well pick a practice that minimizes the differences between the two.”

Subject: RE: So, which do you think is correct?

You can always try both, and put a TimerStart=Timer and TimerEnd=Timer around the script and see which performs faster. I don’t know how the & and + code is implemented, so I can only judge their performance from specific tests. Would be nice to have a formula or some facts to estimate which operator would perform better, even before testing it in practice.

If you want fast code, you don’t use LotusScript in first place, the fastest results would probably be achieved with a self-written NSF engine, if you can figure out how to keep the NSF structure intact. The C API provides good speed and compatibility, minus the speed loss caused by compatibility issues (which again pays back in (re-)development time). If the total time counts, the combined programming time with LotusScript and the execution time probably beats any custom solution in most cases, depending how often you run the code.

Subject: RE: So, which do you think is correct?

I go as fast as a belt and two sets of braces (suspenders) will let me go, Ben. When the dust settles, I’d rather my code ran through to the end and returned a valid result than shave a millisecond or two. I never knowingly rely on implicit conversion – it may be safe in this environmnet, but I’ve been bitten a few too many times to trust THAT dog anymore. I, like yourself, tend to use “& Cstr(thingy) &”.