VBA Class() buliding same object class structur in excel as in outlook - vba

what I want to achieve is to build the same class structer as I have in Outlook. Means:
sFilename = item.Attachments.item(i).Filename '"myTFile.txt"
I have written code in Outlook. I cannot change and test while Outlook is running so I try to write the code upfront in Excel and I try to build the class structur the same as in outlook that I donĀ“t have to change the code afterwards, so for instance:
sFileName = item.Attachments.item(i).Filename
I tried with Properties Get in that way:
Building classes:
clsMail with content:
Property Get item() As clsItem
Set item = New clsItem
End Property
clsItem with content:
Property Get Sender() As String
sFileName = "myFile.txt"
Dim objFSO As Object: Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FileExists(sFileName) Then
Dim objShell As Object, objFolder As Object, objFolderItem As Object
Set objShell = CreateObject("Shell.Application"): Set objFolder = objShell.Namespace(sPathEDIportalLogs)
Set objFolderItem = objFolder.ParseName("myFile.txt")
Sender = Split(objFolder.GetDetailsOf(objFolderItem, 10), "\")(1)
End If
End Property
Property Get ReceivedTime() As Date
ReceivedTime = Date
End Property
Property Get Subject() As String
Subject = "Subject Text"
End Property
Property Get Attachments() As clsAttachments
Set Attachments = New clsAttachments
End Property
So far so good till item.Attachments
But now I am struggeling with the rest item(i).Filename
Again item and as array. I tried a lot but get it not done.
Who can help.
I'm hitting an out of stack space error:

You're recursing. Infinitely.
item(0) is calling into your getter.
which is accessing item(0).
which is calling into your getter.
which is accessing item(0).
Sort-of-unrelated, but very important side note: Accessing a getter should NEVER change anything. It's a horrible code practice. It'll shoot you in the foot more than you'll ever imagine.
Don't do it.. :)

Related

AIP classification with VBA

I'm looking for some way to classify (AIP addon) emails through VBA. So far, we have used the Document Tagging Outlook addon. here I used the command:
Tag.applicationForMacro.MacroOutlookClassify(something)
AIP labels are stored in Outlook items by using user properties. You can use the PropertyAccessor.GetProperty method to get a custom property value:
Sub DemoPropertyAccessorGetProperty()
Dim PropName, Header As String
Dim oMail As Object
Dim oPA As Outlook.PropertyAccessor
'Get first item in the inbox
Set oMail = _
Application.Session.GetDefaultFolder(olFolderInbox).Items(1)
'PR_TRANSPORT_MESSAGE_HEADERS
PropName = "http://schemas.microsoft.com/mapi/proptag/0x007D001E"
'Obtain an instance of PropertyAccessor class
Set oPA = oMail.PropertyAccessor
'Call GetProperty
Header = oPA.GetProperty(PropName)
Debug.Print (Header)
End Sub
I'd suggest using MFCMapi or OutlookSpy for exploring the low-level properties of Outlook items.

Copying a lotus notus database view and paste into word document

The code below reads and inserts the email from lotus notes to an excel sheet. However I would like to read a lotus notes database and copy its content and paste it as a rich text into a word document.
I assume this line of code needs to be modified.
Set nitem = .GetFirstItem("Body")
What would be the best way to go about this?
Public Sub Lotus_Notes_Current_Email4()
Dim NSession As Object 'NotesSession
Dim NUIWorkSpace As Object 'NotesUIWorkspace
Dim NUIdoc As Object 'NotesUIDocument
Dim nitem As Object 'NotesItem
Dim lines As Variant
Set NSession = CreateObject("Notes.NotesSession")
Set NUIWorkSpace = CreateObject("Notes.NotesUIWorkspace")
Set NUIdoc = NUIWorkSpace.CurrentDocument
If Not NUIdoc Is Nothing Then
With NUIdoc.Document
Set nitem = .GetFirstItem("Body")
If Not nitem Is Nothing Then
lines = Split(nitem.Text, vbCrLf)
Sheets(1).Activate
Range("H8").Resize(UBound(lines) + 1, 1).Value = Application.WorksheetFunction.Transpose(lines)
End If
End With
Else
MsgBox "Lotus Notes is not displaying an email"
End If
Set NUIdoc = Nothing
Set NUIWorkSpace = Nothing
Set NSession = Nothing
End Sub
Your assumption is incorrect. Your entire script needs to be rewritten.
If you want to copy the contents of a view, then you need to start by opening a NotesView object. Your current code is opening a NotesDocument object. To get the NotesView, you might want to use the CurrentView property NotesUIWorkspace to get a NotesUIView object, and then use that objects View property.
Once you have the NotesView object, then I'm guessing you might want to want to use the columns property to get at the data, but there are other ways you could go about it. Pretty much no matter what you do, though, you're going to have to handle the formatting of the data on your own.

In outlook vba how can I find what datetime a mail item was read?

I would like to be able to find out what time/date emails received in microsoft outlook were read.
I can't see that the information is saved by Outlook. Nor does it appear the LastModificationTime reflects this either - it isn't updated when an item is marked as read (at least in Outlook 2007)
Assuming this is correct, I have decided to store this information in the future, and created a userproperty to reflect this. I've hooked the mailitem.PropertyChange event handler with the following code, but it's not a very universal solution - I'll have to put the code into every Outlook app I use. Is there a more efficient way of doing it?
This code in placed in the ThisOutlookSession module (and Outlook restarted)
Private WithEvents objExplorer As Outlook.Explorer
Private WithEvents myItem As Outlook.MailItem
Private Sub Application_Startup()
Set objExplorer = Application.ActiveExplorer
End Sub
Private Sub objExplorer_SelectionChange()
If objExplorer.CurrentFolder.DefaultItemType = olMailItem Then
If objExplorer.Selection.count > 0 Then
Set myItem = objExplorer.Selection(1)
End If
End If
End Sub
Private Sub myItem_PropertyChange(ByVal Name As String)
' Debug.Print Name & "=" & myItem.UnRead
If Name = "UnRead" And myItem.UnRead = False Then
Dim myProperty As Outlook.UserProperty
Set myProperty = myItem.UserProperties("ReadTime")
If (myProperty Is Nothing) Then Set myProperty = myItem.UserProperties.Add("ReadTime", olNumber)
myProperty.Value = Now()
myItem.Save
' Debug.Print Format(myItem.UserProperties("ReadTime"), "hh:mm:ss dd/mm/yy")
ElseIf Name = "UnRead" And myItem.UnRead = True Then
myItem.UserProperties("ReadTime").Delete
End If
' Debug.Print
End Sub
Thanks
You are right, the Outlook object model doesn't provide anything about the Read status (the time when it was marked as read).
VBA is not designed for distributing on multiple PCs. You need to develop an Outlook add-in instead. That's exactly for what they were introduced. See Walkthrough: Creating Your First Application-Level Add-in for Outlook to get started.
You cannot do that - strictly speaking, read/unread state is not even part of the message: it is stored separately. And Exchange Public Folders store stores that state on the per-user basis.
If you set the user property, it will not be persisted unless you call Save, but that will change the last modification time.

Accessing Text Body of Outlook MailItem Object - HTML and Plaintext

[EDIT] This problem does not appear to exist in C#. See reworked code at the bottom.
This has baffled me for two days now and has finally led me to making my first post on here.
I am coding in the visual basic editor of Excel 2007.
I am using the Outlook 2007 object library, from Excel 2007, not Outlook. Not sure if this matters.
I'm writing a program that will run periodically on a mail folder and parse out important information from emails as they arrive. The emails in question look like plain text, but are identified by the VBA Locals window as being olFormatHTML! To test this, I click "reply" for one of the emails and then attempt to paste an Excel range into the body of the email, and Outlook gives me a popup (Compatibility Checker) that gives me the option to "switch to HTML". Looks like plaintext. Further, opening the message, clicking "Other Actions" --> Encoding yields Unicode (UTF-8). So why in the world, when I expand this MailItem object in the Locals window, does Excel think it is an HTML email?
This MailItem's .Body is empty, and this MailItem's .HTMLBody does not contain the actual contents of the email, which are nonempty when viewed through Outlook. Here's what the HTMLBody value is:
"<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta name=ProgId content=Word.Document><met"
Code to create Outlook application object, navigate to desired folder and pass MailItem object to the parser (skip if you're familiar with this part):
' Navigate to desired folder and pass information to text analyzer.
Sub AccessInbox(timeStamp As Date)
Dim olApp As Outlook.Application
Dim objNamespace As Outlook.Namespace
Dim objFolder As Outlook.MAPIFolder
Dim sharedFolder As Outlook.MAPIFolder
Set olApp = New Outlook.Application
Set objNamespace = olApp.GetNamespace("MAPI")
' Explicitly went through hierarchy since I'll be using with a shared Mailbox eventually.
Set objMailbox = objNamespace.Folders("Mailbox - My Name")
Set objFolder = objMailbox.Folders("Inbox")
Set sharedFolder = objFolder.Folders("Folder With Stuff")
'mostly irrelevant, see ParseEmailText code below this
Dim emailTimeStamp As Date
For Each Item In sharedFolder.Items
' Inbox can contain other kinds of objects than MailItem.
If TypeOf Item Is MailItem Then
Dim thisEmail As Object
Set thisEmail = olApp.CreateItem(MailItem)
thisEmail = Item
' Check to see if email has already been analyzed.
emailTimeStamp = thisEmail.ReceivedTime
If emailTimeStamp > timeStamp Then
' Send to email text analyzxer.
ParseEmailText thisEmail
Else
Exit For
End If
End If
Next
End Sub
Code to parse email body:
Sub ParseEmailText(email As Outlook.MailItem)
emBody = email.Body
' This is the part where I wish I could just access the email's body, but it is empty.
End Sub
[EDIT] I reworked this basic code in C# and the MailItem.Body is NOT blank anymore. In fact it works exactly as expected. Any ideas why VBA sucks so much?
class Parser
{
//Outlook variables
Microsoft.Office.Interop.Outlook.Application app = null;
Microsoft.Office.Interop.Outlook._NameSpace ns = null;
Microsoft.Office.Interop.Outlook.MailItem item = null;
Microsoft.Office.Interop.Outlook.MAPIFolder inboxFolder = null;
Microsoft.Office.Interop.Outlook.MAPIFolder atFolder = null;
public Parser()
{
}
public void ParseInbox()
{
//open outlook
//Access Outlook (only need to do this once)
app = new Microsoft.Office.Interop.Outlook.Application();
ns = app.GetNamespace("MAPI"); //Returns a NameSpace object of the specified type. The only supported name space type is "MAPI".
ns.Logon(null, null, false, false); //Namespace.Logon method: Logs the user on to MAPI, obtaining a MAPI session.
inboxFolder = ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
atFolder = inboxFolder.Folders["Folder With Stuff"];
for (int i = atFolder.Items.Count; i > 0; i--)
{
item = (Microsoft.Office.Interop.Outlook.MailItem)atFolder.Items[i];
string emailText = item.Body;
}
}
}
You need to use the Set keyword when setting a reference to an object. This line in your code creates a new email object (which is using your default setting of HTML email):
Set thisEmail = olApp.CreateItem(MailItem)
And then this line of code isn't using the Set keyword:
thisEmail = Item
So your variable isn't referncing the object you think but the new email.
Try using:
Set thisEmail = Item
Or, instead, replace both of these lines:
Set thisEmail = olApp.CreateItem(MailItem)
thisEmail = Item
With this line:
Set thisEmail = Item

Outlook VBA troubleshooting

I have the following block of VBA code, which should create a popup box with the first name for each contact in my default folder.
Sub DeleteaContact()
Dim myOutlook As Outlook.Application
Dim myInformation As NameSpace
Dim myContacts As Items
Dim myItems As ContactItem
Set myOutlook = CreateObject("Outlook.Application")
Set myInformation = myOutlook.GetNamespace("MAPI")
Set myContacts = myInformation.GetDefaultFolder(olFolderContacts).Items
For Each myItems In myContacts
MsgBox (myItems.FirstName)
Next
End Sub
For some reason I am getting a sporadic type mismatch error at the end of the loop.
Can anyone shed some light on this subject as to why?
Folders can store more than just the data type you'd expect. Change myItems to
Dim myItems As Object
and change the message box to
Debug.Print TypeName(myItems)
Then check the Immediate Window (Ctl+G) to see if any of the items are not ContactItem. If you determine you have something in there that's not a contact, you simply need to test for it. Keep myItems as Object, but use code like
If TypeName(myItems) = "ContactItem" Then
MsgBox myItems.FirstName
End If
Generally, I leave my variables typed as the specific item (e.g. ContactItem) while I'm writing the code and then convert them all to Object when I'm done. That way you get the benefit of Intellisense while you're coding.
Try changing:
MsgBox (myItems.FirstName)
to:
MsgBox myItems.FirstName
as VBA doesn't like unnecessary parentheses