I am working on a project where I need to get ms access table/data from mail body and execute some command in SAP. I can manage SAP part but issue is that how to get information from mail body. i tried linking my mailbox in access but it shows me all mail body text but i need some specified contents only. example
Hello,
Please supplement budget
WBS Amt
N.10002077.001 1
from above what i need is just "N.10002077.001" and "1" ,but how to get that information only in table is the issue?
Further, what I will get in my mail will be table with 2 column but access imports it as a simple text.
It is impossible to give a definite answer to your question because it is too vague but it is possible to get you started.
Have a look at this answer of mine: https://stackoverflow.com/a/12146315/973283. The question is not relevant other than the OP did not understand that showing screenshots told us little about what the body looked like to a VBA macro. The answer includes a macro that copies selected properties from every email in Inbox to an Excel worksheet. This will allow you to see what an email’s body looks like to a VBA macro.
How will you identify the emails from which you wish to extract data? The two simple choices are:
Look at every email in a folder and identify the interesting one by examining the subject, sender or some other property.
Select the interesting emails then run a macro which uses ActiveExplorer to access the selected emails.
The answer referenced above demonstrates technique 1. There are lots of answers demonstrating technique 2 but I can add an example macro if necessary.
An email typically has an Html body and a text body. If an email has an Html body, that is the one shown to the user. A macro can access either or both. Your screen shot looks like a text body although appearances can be deceptive. If it is a text body, the email does not have an Html body.
If it is a text body, the layout of the body is probably something like:
Hello,{cr}{lf}
Please supplement budget{cr}{lf}
WBS{tab}{tab}{tab}{tab}{tab}Amt{cr}{lf}
N.10002077.001{tab}{tab}1{cr}{lf}
This assumes, the sender has used variable numbers of tabs to line up the columns.
You could use Split on vbCr & vbLf to convert the string body into an array of strings with one line per array entry. Discard lines up to and including the line starting “WBS” then process each line down to any signature. Split each line on vbTab and expect to find two entries with values with the rest blank.
See how far you can get with the above hints then clarify your answer if you need more information.
Is there a reason why my MS Word VBA macro is ignoring a dropdown list I placed inside a shape (a rich text box)? I've tried referring to it by tag, name, number, etc. I even had the macro tell me the count of content controls:
MsgBox(ActiveDocument.ContentControls.Count)
I get 0.
Nothing works. If I take it out of the shape, it works fine. MS Word gives me a count of 1 item. But for some reason MS Word won't acknowledge it inside the shape. Any help on how to do this?
Edited as my previous post was completely wrong.
Each textbox in the main text story is a Shape which you can access using an index number. A shape has various properties but text etc. is in its Textframe, if it has one. But in that case the Range you need is not called Range but TextRange. So, e.g. the first contentControl in Shape 2 is
ActiveDocument.Shapes(2).TextFrame.TextRange.ContentControls(1)
You will probably need to iterate through your shapes and you may need to verify that a given shape is a textbox and/or that it has a TextFrame.
If your text box is in another Story such as a header or footer, you will probably need to identify the relevant StoryRange.
An Outlook message can contain attachments (see fig., borrowed from http://blogs.mccombs.utexas.edu/the-most/2011/01/28/email-attachments-in-the-body-of-outlook-messages/):
A set of inline attachments (IA, left fig.), understood as any object besides text
A set of bar attachments (BA, right fig.)
I have several questions on accessing them via VBA. They are cross-related, so it is worth posting them all together.
Is there a comprehensive way to access IA?
In many cases, I found that the collection MailItem.Inspector.WordEditor.InlineShapes (IS) is IS=IA. Is this always true?
Is there a comprehensive way to access BA?
In many cases, I found that the collection MailItem.attachments (AT) is AT=IA+BA. But I have found exceptions: emails with nonempty IA and empty AT. Some use of AT might perhaps help, even with what I found.
Having a reference to an item in IA, is there any way of knowing if there is a corresponding item in AT (there may be not, according to #2), and if so identify it, IA->AT?
Reversing the question in #3:
Having a reference to an item in AT, is there any way of inquiring if it is an InlineShape, and if so knowing which item in IA it corresponds to, AT->IA?
Is there any way of establishing the connections BA<->AT, similarly as in questions #3 and #4 for IA<->AT?
PS: I am using Outlook 2010, and according to http://www.msoutlook.info/question/261 and http://support.microsoft.com/kb/222330 that may bring about different results from Outlook 2007, etc.
Is there a comprehensive way to access IA? In many cases, I found that the collection MailItem.Inspector.WordEditor.InlineShapes (IS) is IS=IA. Is this always true?
NO. InlineShapes may contain items that you would not likely consider "attachments" per se, for instance, a corporate logo embedded in your signature, etc. will appear as an InlineShape which is not an "attachment" (although plain text email may include this as an attachment...)
Inline "Attachments" (inserted as object | create from file, for example) appear as Type = wdInlineShapePicture and they do not have an OLEFormat property (which surprises me...)
Is there a comprehensive way to access BA?
In many cases, I found that the collection MailItem.attachments (AT) is AT=IA+BA. But I have found exceptions: emails with nonempty IA and empty AT. Some use of AT might perhaps help, even with what I found.
Per my second comment, above, the inline shape "attachments" appear as wdInlineShapePicture but I believe they are treated as "attachments" in a roundabout way. Iterating the attachments collection you may notice items with generic names like "image002.png" I believe these are essentially "linked" through a metadata file (which may also show as an attachment item "oledata.mso", to another generically named attachment (like "image001.wmz". None of these attachments, which are part of the .Attachments collection, will appear as a "bar attachment".
The above screenshot comes from this email where I created a dictionary object to store the attachments by name (key). This email has 2 "bar attachments" and 2 "inline attachments". Note that the "bar attachments" are represented by their real "name", whereas the "inline attachments" are split in to the wmz/png files.
Having a reference to an item in IA, is there any way of knowing if there is a corresponding item in AT (there may be not, according to #2), and if so identify it, IA->AT?
I don't believe so. The "oledata.mso" file is not something that you can read or parse, as far as I'm aware, and this seems to be the only thing that connects the wmz/png files.
Reversing the question in #3:
Having a reference to an item in AT, is there any way of inquiring if it is an InlineShape, and if so knowing which item in IA it corresponds to, AT->IA?
No. As far as I can tell there is no "correspondence" between the inline shapes and the attachments. Even if you were to insert the same file as both an Attachment and an Object/InlineShape, these are separate and distinct items.
Here is another example email:
And the corresponding items in Attachments collection:
Is there any way of establishing the connections BA<->AT
Based on my research, possibly.
You can examine the HTML source of the email body, and parse out the inline shapes. Below you can see that the png/wmz from the last screenshot are present.
If you store ALL attachments in a dictionary object (assume m is a MailItem object):
Dim dictAttachments as Object
Set dictAttachments = CreateOBject("Scripting.Dictionary")
Dim attch As Attachments
Dim att as Attachment
Dim s as Integer
s = 0
Set attch = m.Attachments
For Each att In attch
Set dictAttachments(att.DisplayName) = att
s = s + 1
Next
Then if you have identified the png/wmz from the HTML Source, you can remove them from the dictAttachments object using the .Remove method.
dictAttachments.Remove("image001.wmz") 'etc.
Then, the dictionary object will contain only the "Bar Attachments".
The trouble with this (I have tried to do this now...) is that I'm not able to find a way to parse the HTML (using an HTMLFile object) to get the PNG -- it's in a part of the HTMLBody which is essentially commented out/conditionally rendered and so it does not respond to getElementsByTagName method, etc.
While I would always prefer to work with the HTML/XML objects (it's usually a bad idea to try and parse HTML with normal string functions), this may be a necessary exception. You could do something simply like:
Dim itm as Variant
For each itm in dictAttachments.Keys()
If Instr(1, m.HtmlBody, "cid:" & itm & "#") > 0 Then
dictAttachments.Remove(itm)
End If
Next
'Ignore the oledata.mso, too:
If dictAttachments.Exists("oledata.mso") Then dictAttachments.Remove("oledata.mso")
Now the dictionary ONLY contains the "Bar Attachment(s)"
Is there any way of establishing the connections BA<->AT, similarly as in questions #3 and #4 for IA<->AT?
I don't think there is any connection that you could possibly make. They are separate items and treated separately. Even when they are the same file, there's just no information in the InlineShape which would be useful for attempting to do this.
Email in HTML Format
All of the above is for HTML format emails. In the case of HTML mail, the problem is not so much in the Attachments but rather a limitation of the InlineShapes and InlineShape objects in that context.
Email in RTF Format
In the case of RTF mailbody, rather than being split png/wmz files, the attchment does appear by name in the Attachments collection, the other item 2 is actually a JPG as part of my signature.
HOWEVER, you will be able to observe that attachments in RTF have an OLEFormat property which and more specifically they have an OLEFormat.ClassType = "Outlook.FileAttach"
So you may be able to do something simple, like:
Select case m.BodyFormat
Case olFormatRichText
For each shp in doc.InlineShapes
If Not shp.OleFormat Is Nothing Then
If shp.OLEFormat.ClassType = "Outlook.FileAttach" Then
'Do something here
End If
End If
Next
Case olFormatHTML
' Do something like the example above for HTML
Case olFormatPlainText
' Do something different, if needed, for plain text emails
Case olFormatUnspecified
' not sure what to do here and it's not really my problem to figure out...
End Select
Now, given it as part of InlineShapes, I don't think you can "connect" it to a specific item in the Attachments collection. You will be better suited to simply iterate the Attachments collection.
Note: In my example (a very simple one) the two dictionaries/collections appear to be indexed the same way, but I would caution against assuming this will always be the case. So while you may be able to delete by index position, I am not sure that is a safe/reliable assumption.
It should not be possible in RTF format to have an empty Attachments collection and an "Inline Attachment".
There appears to be a large number of possible cases, depending on the combination of the following Enums (and perhaps some others):
MailItem.BodyFormat.
An OlBodyFormat, for the body text.
Possible values:
olFormatHTML,
olFormatPlain,
olFormatRichText,
olFormatUnspecified
InlineShape.Type.
An WdInlineShapeType, for each shape.
Possible values:
wdInlineShapeChart,
wdInlineShapeDiagram,
wdInlineShapeEmbeddedOLEObject,
wdInlineShapeHorizontalLine,
wdInlineShapeLinkedOLEObject,
wdInlineShapeLinkedPicture,
wdInlineShapeLinkedPictureHorizontalLine,
wdInlineShapeLockedCanvas,
wdInlineShapeOLEControlObject,
wdInlineShapeOWSAnchor,
wdInlineShapePicture,
wdInlineShapePictureBullet,
wdInlineShapePictureHorizontalLine,
wdInlineShapeScriptAnchor
Attachment.Type.
An OlAttachmentType, for each attachment.
Possible values:
olByReference,
olByValue,
olEmbeddeditem,
olOLE
I have examined some of these cases. The information provided is based on this limited information.
Is there a comprehensive way to access IA?
I would say YES, with MailItem.Inspector.WordEditor.InlineShapes (IA).
Depending on the personal definition of "attachment", there might be some items in this collection that are not regarded as such. The access is comprehensive though: there may be more items than looked for, but none is left out.
Is there a comprehensive way to access BA?
I would say YES, with MailItem.Attachments (AT).
I found an explanation for emails with nonempty IA and empty AT.
They have InlineShapes of type wdInlineShapeLinkedPicture. But even in this case, there are at least two possibilities, according to InlineShape.Hyperlink:
1) There is no Hyperlink.
This is the case when images are embedded, adding one item to IA per InlineShape, and at least one item to AT (there may be many InlineShapes, linked to a single Attachment).
In this case, properties of LinkFormat reveal useful info, including the name of the item in AT related the item in IA.
2) There is an Hyperlink (case partly the culprit for the different findings).
This is the case when images are hyperlinked and not embedded. Images show up in the email, adding one item to IA per InlineShape, but they do not add items to AT.
In this case, properties of Hyperlink and LinkFormat reveal useful info.
Case 1 appears to be the standard way of attaching images (up to Office 2013?). Using case 2 appears to require some tweaking (see this, this, this, and this).
Having a reference to an item in IA, is there any way of knowing if there is a corresponding item in AT (there may be not, according to #2), and if so identify it, IA->AT?
YES, at least in some cases.
When InlineShape.Type=wdInlineShapeLinkedPicture, if there is no InlineShape.Hyperlink then there is an item in AT. It can be found by pairing InlineShape.LinkFormat.SourceName (up to character #) with some Attachment.DisplayName.
On the other hand, I could not do this when InlineShape.Type=wdInlineShapeEmbeddedOLEObject (e.g., an inline attached Excel workbook).
I will edit with additional findings.
PS1: http://www.msoutlook.info/ has very useful info.
E.g.,
http://www.msoutlook.info/question/126,
http://www.msoutlook.info/question/205,
http://www.msoutlook.info/question/21,
http://www.msoutlook.info/question/261.
PS2: perhaps using some developers interface provides some access beyond VBA. I.e., some YESes to teh questions, which for VBA are NOs.
See
http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.inlineshape.hyperlink%28v=office.14%29.aspx
and
http://msdn.microsoft.com/es-es/microsoft.office.interop.outlook.attachment_members.
The first picture is for an email in the RTF format. The attachment icons are rendered inside the message body. The second screenshot is for a plain or HTNML message. In both cases the attachments can be accessed through the MailItem.Attachments collection.
I am using VBA on Word and trying to do a task with a simple description:
Make document content fit on 1 or 2 pages, without leaving a lot of empty space on the last page.
To do that, I started with one simple step:
Determine total document content height.
(to later manipulate font size and line spacing according to my needs)
Problem is:
ActiveDocument.Content.Paragraphs lists all paragraphs with no regards to hierarchy. If I have a table in the content, all its contents will be listed, so I can't just use that to infer document content height.
I would like to work over the document structure tree, like
doc.header
doc.contents
paragraph1
table1
cell1
t1c1p1
cell2
t1c2p1
t1c2p2
paragraph2
paragraph3
doc.footer
And iterate only over the direct children of the content root to get their heights.
But I am having a hard time finding a way to do that. Can anyone give me some help?