Find and Replace specific string in Outlook message - vba

My code basically searches for the string "#XX" in the email body. The "#XX" is usually followed by a text like "#XXApple". And this "#XXApple" can be seen multiple times in the email message.
The code below works in such a way that it only replaces the first hit with spaces. However, the rest of the "#XXApple" will only be changed to "Apple"
Is there a way where I can do a "Find and Replace All" in Outlook?
obj.HTMLBody = Replace(obj.HTMLBody, "#XX", " ", 15)

Not tested or verified but this is the general idea of what I meant to say in the comment above.
Dim Cet
Dim TesPos As Int, i As Int
Cet = Split(obj.HTMLBody, " ")
For i=LBound(Cet) to Ubound(Cet)
TestPos = 5
TestPos = InStr(1,Cet(i), "#XX", CompareMethod.Text)
if TestPos = 1 then
Cet(i) = ""
Else: End if
Next i
obj.HTMLBody = ""
For i=LBound(Cet) to Ubound(Cet)
obj.HTMLBody = obj.HTMLBody & " " & Cet(i)
Next i
Debug.Print obj.HTMLBody

The Outlook object model provides three main ways for working with item bodies:
Body - a string representing the clear-text body of the Outlook item.
HTMLBody - a string representing the HTML body of the specified item.
Word editor - the Microsoft Word Document Object Model of the message being displayed. The WordEditor property of the Inspector class returns an instance of the Document class from the Word object model which you can use to set up the message body.
You can read more about all these ways in the Chapter 17: Working with Item Bodies. It us up to you which way is to choose to deal with the message body. But the Word object model provides all the required methods to get the job done.

Related

Create an appointment with required attendees in Lotus Notes using VBA in Access 2013

I am attempting to create a check out log for inventory in Access 2013. During this process you will create an appointment on the expected return date in the Lotus Notes 9 calendar. I have found enough examples to do this successfully. However I am getting stuck when trying to add people to the "RequiredAttendees" field. I am pretty sure that I am using the right field name but i keep getting the following error:
Run-time error '-2147417851 (80010105)': Automation error. The server
threw an exception.
Everything else works fine except the part that tries to add attendees. I know Lotus Notes 9 is old and I know Access 2013 is old but those are the tools I am required to work with. Any help would be appreciated.
Public Function test() As Variant
Dim StartTime As Date
Dim MailDbName As String
Dim CalenDoc As Object
Dim WorkSpace As Object
Dim AppDate As String
Dim AppTime As String
Dim Subject As String
Set WorkSpace = CreateObject("Notes.NOTESUIWORKSPACE")
AppDate = InputBox(Prompt:="Enter the return date:")
'Subject = InputBox(Prompt:="Enter the subject:")
'AppTime = InputBox(Prompt:="Enter the time:")
MailDbName = "mail\User.nsf"
strSTime = CStr(Timex)
Set CalenDoc = WorkSpace.COMPOSEDOCUMENT("MailServer", MailDbName, "Appointment")
CalenDoc.FIELDSETTEXT "AppointmentType", "3"
CalenDoc.Refresh
CalenDoc.FIELDSETTEXT "StartDate", CStr(AppDate)
CalenDoc.FIELDSETTEXT "EndDate", CStr(AppDate)
CalenDoc.FIELDSETTEXT "StartTime", "12:00 PM"
CalenDoc.FIELDSETTEXT "EndTime", "12:00 PM"
CalenDoc.FIELDSETTEXT "Subject", "Test"
GetUser = Environ("UserName")
EmailAddress = GetUser & "#company.com"
If EmailAddress = "User1#company.com" Then
CalenDoc.FIELDSETTEXT "RequiredAttendees", "User2#company.com" & "," & "User3#company.com"
CalenDoc.Refresh
ElseIf EmailAddress = "User2#company.com" Then
CalenDoc.FIELDSETTEXT "RequiredAttendees", "User1#company.com" & "," & "User3#company.com"
CalenDoc.Refresh
ElseIf EmailAddress = "User3#company.com" Then
CalenDoc.FIELDSETTEXT "RequiredAttendees", "User2#company.com" & "," & "User1#company.com"
CalenDoc.Refresh
Else
MsgBox (EmailAddress & "is not a valid email address.")
End If
'CalenDoc.gotoField "Body"
'CalenDoc.InsertText Body
CalenDoc.Refresh
'CalenDoc.Save
'CalenDoc.Close
'Set CalenDoc = Nothing
'Set WorkSpace = Nothing
I think you've been confused by looking at examples that use the back-end COM classes instead of, or maybe in addition to, examples that use the front-end OLE classes. You are using Notes.NOTESUIWORKSPACE - OLE, instead of Lotus.NotesSession - COM. That means you have to use the actual editable fields on the Appointment form, which are sometimes not what you expect them to be. In some cases, these front-end fields are not the same as the items that will end up being stored in the back-end document - and it's the back-end item names that are typically documented because they are the ones that get stored in the note.
RequiredAttendees is the stored item name, but you are getting the automation error because it's a computed field on the Appointment form, not an editable field.
Since you are using OLE, you need to enter the data into the "EnterSendTo" field. The data that you (or a user) puts in there will, in fact, end up in the RequiredAttendees item due to the magic that goes on in the formulas and scripts associated with the Appointment form.

VB.Net Hyperlinking in EWS email with class properties

I need help getting the hyperlink to work as well as getting the value stored in YestFile.FileName to show up.
I have a list of objects of class FileFromYesterday (Collection2) with 3 properties. Two properties are just Strings (FileName and Entity) but one property (URL) contains a URL as a String. I am trying to hyperlink the URL to FileName in the main.
I have a feeling that I need to use HTML to format the email somehow but I have no Idea where to begin
Dim HyperLink As String
Dim FileLine As String
Dim NewBody As String
Dim message As New EmailMessage(EWS)
message.Subject = "Monthly Financial Imported into Docushare on " & String.Format("{0:MM-dd-yyyy}", Yesterday)
NewBody = "Total of " & Collection2.Count & " Files Imported." & "\n"
For Each YestFile In Collection2
HyperLink = YestFile.FileName.Replace(".pdf", "")
FileLine = HyperLink & "Entity: " & YestFile.Entity & Environment.NewLine
NewBody = NewBody & FileLine
Next
You should be creating a HTML document in your NewBody varible so you need the pre and post tags for a HTML document eg
<html>
<body>
</body>
</html>
the body content you want should go within between the Body Tags and for thing like NewLines you need to use the appropriate HTML tags such as
<br />
Eg what ever you end up creating in you NewBody variable you should be able to write out to a file or test in any Online HTML validator https://validator.w3.org/#validate_by_input to see if its valid and how it will look before trying to send it.

Access VBA reserved word "name"

I am using Access VBA to access movie information using the API. It is working fine but I have a problem with attributes that have as name the word "name" which is a reserved word.
Let's say I want to access the production companies. I am using this code, and it is working fine if I want to get the id, but it doesn't work if I am trying to get the names because the word "name" is a reserved word in line 4.
Does anyone have an idea how to fix it?
The working code:
Set Keys1 = VBA.CallByName(jsonDecode1, "production_companies", VbGet)
movie_companies = ""
For Each Key In Keys1
movie_companies = movie_companies & **key.id** & ","
Next
The not working code:
Set Keys1 = VBA.CallByName(jsonDecode1, "production_companies", VbGet)
movie_companies = ""
For Each Key In Keys1
movie_companies = movie_companies & **Key.Name** & ","
Next
The json file:
production_companies: [ { name: "France 2 Cinéma", id: 83 }, { name: "SBS Productions", id: 8997 }, { name: "Les Films Français", id: 16782 } ],
Thank you for your reply, but i need to give you more details of what i am doing. yes i am using a collection but i didn't create it i am just importing data do the collection from a website using API, also i want to let you know that all the other properties works fine except the "name" may be because the editor capitalize the first letter of the word "Name" automatically but it doesn't capitalize the other words, how can i avoid the editor to capitalize the word "name" maybe that's the issue. Thank you again
That's the whole code:
Set sc = CreateObject("ScriptControl"): sc.language = "JScript"
Set oXMLHTTP1 = CreateObject("MSXML2.XMLHTTP")
oXMLHTTP1.Open "GET", URL, False 'Open socket to get the website
oXMLHTTP1.setRequestHeader "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"
oXMLHTTP1.send 'send request
Do While oXMLHTTP1.ReadyState <> 4
DoEvents
Loop
oResp = oXMLHTTP1.responseText 'Returns the results as a byte array
Set jsonDecode1 = sc.Eval("(" + oResp + ")")
Set Keys1 = VBA.CallByName(jsonDecode1, "production_countries", VbGet)
For Each Key In Keys1
movie_companies = movie_companies & Key.id & ","
movie_companies = movie_companies & Key.Name & ","
Next
Now i am sure that the problem is the fact that the first letter is uppercase, because i have another property named "key" and because the editor change it to "Key" with uppercase K, it is not working too :) is there a way to disabled changing the first letter to uppercase in the code editor? this will definitely fix the problem
I fixed it :), it is weird but i fixed it.
what you need to do is declare a variable "name" with the lower case "n" and after that i remove it and now the code editor don't capitalize the word "name" anymore. If i declare a variable with the first letter capital it will save it and even if i remove the declaration the next time you use it it will automatically capitalize it and you cannot remove until you declare it again with all lower :)
Thank you all
From what I can see, this has ZERO to do with reserved words.
The use of name is a valid property of a GAZILLION built in objects such as forms, reports, column names pulled from a record set etc.
The “conflict” of reserved words is ONLY in regards to SQL or using VBA variables you define (and name is in fact NOT a reserved word anyway).
You are using “someobject.Name” and thus this has ZERO to do with reserved words since a property or method of an object called “name” NEVER was a source of errors or issues in Access VBA. In fact built in methods can use reserved words.
Ignoring that you left out the data type of this function? (cannot stress how you want to code with option explicit and ALSO cannot stress how you should give a data type to that function).
However I shall make a BIG guess and assume it is a VBA collection object.
Collections in VBA don’t have a name property. So this works:
Dim c As New Collection
c.Add "Apple", "testkey1"
c.Add "Grape", "testkey2"
Dim f As Variant
For Each f In c
Debug.Print f
Next
However f.name will fail since “.name” is NOT a property or method of a collection. So this issue has nothing to do with reserved words but the simple fact that “.name” never been part of or a valid syntax for a collection object.
And if you really do need each element of the collection to have values, then your function can return a collection of “structures” but that structure will have to be a class object. So this code shows this in Action:
So the class module can be:
Class module clsStruct:
Option Compare Database
Option Explicit
Public Name As String
Public KeyName As String
Public Value As String
Now in our code:
Dim c As New Collection
Dim MyStruct As New clsStruct
MyStruct.KeyName = "hello"
MyStruct.Name = "myname"
MyStruct.Value = "my value"
c.Add MyStruct
Dim f As Variant
For Each f In c
Debug.Print f.Name, f.Value, f.KeyName
Next
Output:
myname my value hello
So you are MOST free to use “.name” as a valid property of a object you create, but the collection object by default has no such name property and thus will fail at runtime.

Is it possible to build a MessageBox message that is then passed to a message box to include new lines?

I am attempting to generate a message for the user that returns a list of missing checklist items. My question: is there a way to build a message that can then be passed to a MessageBox that includes new lines. I have considered overloading the method to accept various numbers of individual messages, but there has to be a more elegant way to do this. Below is the class that I have designed to handle this message collection, display, and future exportation to a more convenient format.
Public Class clsChecklistMissingItems
Private Shared iWrong As Integer = 0 'Number of items wrong.
Private Shared sMissingItems() As String 'Will use the number of items wrong.
Public Shared Sub CollectItem(ByVal mess As String) 'Saves the message passed to it.
ReDim Preserve sMissingItems(iWrong) 'Resize the array based on the counter.
sMissingItems(iWrong) = mess 'Assign the message to the missing items string array.
iWrong = iWrong + 1 'Increment the counter (may give us +1
End Sub
Public Sub DisplayList() 'Displays the message at the end of the execution.
'Can this be generated procedurally?
MessageBox.Show("There were " & iWrong & " missing or incorrect items." & vbNewLine &
sMissingItems(iWrong))
End Sub End Class
My alternate solution is to write a form that is formatted like a text box that will behave similar to a text box, but will have all of the described functionality.
Using arrays is not the best option. .NET has plenty of built-in collection classes that are far superior to an array, like List<T>. I understand it's tempting to use an array when you're coming from other "flavors" of Visual Basic (VBScript, VBA, etc.) because that's what you're familiar with, but you should learn what's available in the .NET FCL.
You could do something like this using a loop and a StringBuilder to build your list of messages:
Dim wrongItems As New List(Of String)()
' fill the collection however you do it...
wrongItems.AddRange({"Reason 1", "Reason 2", "Reason 3"})
Dim sb As New StringBuilder()
For Each item In wrongItems
sb.AppendLine(item)
Next
MsgBox(String.Format("There were {0} missing or incorrect items.",
wrongItems.Count) & vbNewLine & sb.ToString())
After speaking with my co-worker it was pointed out to me that VB.NET has a carriage return line feed that is designed to be concatenated into a string to represent a new line.
Public Sub DisplayList()
Dim sMessage As String = ""
For i As Integer = 0 To sMissingItems.Length - 1
sMessage = sMessage & sMissingItems(i) & vbCrLf
Next
MessageBox.Show(sMessage)
End Sub
I have not had a chance to implement using a list rather than an array at this point.

VBA Code to Create Lotus Notes Email - CC Emails Not Working

I have some VBA code that takes the various email parts as inputs and creates an email message in Lotus Notes, and sends it from a group mailbox. It sends the email out to a recipient and CC recipients, and then leaves a copy of the message in the "Sent" box of a group email account. I think the sent message in that box is sort of a dummy, as it is perhaps not the exact message as it was sent.
This works, and sends the message to the SendTo, and to the first CC address. However, if I have a second CC address, it turns the ending of the second address into gibberish. For example, if the SendTo is "mike#someemail.com", and the CC is "john#someemail.com, jim#someemail.com"... in the Sent box it appears to have sent it to mike#someemail.com, and CC to john#someemail.com and jim#someemail.com. However, the actual mail is only received by john, and the CC looks like this: "john#someemail.com, jim#pps.rte_to_v" and jim never gets the message.
On another message, the second CC ends up being jim#vwall11.com. I haven't found a pattern to the gibberish it puts at the end of the CC line instead of the correct address. It took us awhile to learn about the problem since it looks correct in the Sent mailbox.
Here's the code I'm using. I'm changing the server names, etc, but all relevant code is intact.
Private Sub TestEmail()
Call EmailFromADT("mike#somemail.com", "john#somemail.com, jim#somemail.com", "test subject", "test message", _
"", "", "", "")
End Sub
Function EmailFromADT(strSendTo As String, strCopy As String, strSubject As String, _
strText1 As String, strText2 As String, strText3 As String, _
strText4 As String, strText5 As String)
Dim notesdb As Object
Dim notesdoc As Object
Dim notesrtf As Object
Dim notessession As Object
Dim i As Integer
Set notessession = CreateObject("Notes.Notessession")
''''''''Group Mailbox'''''''''''''''''''''''''''''''''''''''''''''''''
Set notesdb = notessession.GetDatabase("servername", "mailin\notesaddr.nsf")
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Open the mail database in notes
If notesdb.IsOpen = True Then
'Already open for mail
Else
notesdb.OPENMAIL
End If
Set notesdoc = notesdb.CreateDocument
Call notesdoc.ReplaceItemValue("Subject", strSubject)
Set notesrtf = notesdoc.CreateRichTextItem("body")
Call notesrtf.AppendText(strText1 & vbCrLf & strText2 & vbCrLf & strText3 & vbCrLf & strText4 & vbCrLf & strText5)
notesdoc.SendTo = strSendTo
notesdoc.CopyTo = strCopy
notesdoc.from = UserName()
''''''''Group Mailbox'''''''''''''''''''''''''''''''''''''''''''''''''
notesdoc.principal = "Group Team"
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
notesdoc.BlindCopyTo = strBCC
Call notesdoc.Save(True, False)
notesdoc.SaveMessageOnSend = True
Call notesdoc.Send(False, strSendTo)
Set notessession = Nothing
End Function
To have multiple values in an item in a Document, you need to use an array.
Try this:
dim varCopyTo as Variant
varCopyTo = Split( strCopyTo, "," )
call notesDoc.Replaceitemvalue( "CopyTo", varCopyTo )
You could also write notesDoc.CopyTo=varCopyTo, but it is better (more secure, slightly better performance) to use ReplaceItemValue.
In addition you should add Call notesDoc.ReplaceItemValue("Form", "Memo" ) after creating the document, so that the server/client does not have to "guess" what kind of document you are creating.
notesdoc.CopyTo wants an array, not a comma-delimted string on the right hand side of the assignment. Each element in the array should be an individual address. By passing in a comma-delimited string, you're essentially passing in a single invalid address as far as Notes and Domino are concerned. I'm not entirely sure why that's being transformed in the peculiarly random way that it is, but I am sure it's definitely not going to be right that way.
And better than using the shorthand form (notesdoc.CopyTo = ...) for this code, you should probably be using Call notesdoc.ReplaceItemValue, like you do with the Subject, but passing in an array there.