after searching multiple things, and getting errors
How do I upon pressing "f5" in a vba script copy the body of an email into an excel sheet /csv
where every line = a new cell below.
Thanks
Sorry, this is causing me nothing but trouble.
What I have tried so far
http://smallbusiness.chron.com/export-outlook-emails-excel-spreadsheets-41441.html
How to copy Outlook mail message into excel using VBA or Macros
http://www.vbforums.com/showthread.php?415518-RESOLVED-outlook-the-macros-in-this-project-are-disabled
http://www.ozgrid.com/forum/showthread.php?t=181512
and a few more, last year.
This will work for you. we are basically splitting the email body into an array based on a new line. Notice that this will yield blank cells if you had a blank line in the email body.
Public Sub SplitEmail() ' Ensure reference to Word and Excel Object model is set
Dim rpl As Outlook.MailItem
Dim itm As Object
Set itm = GetCurrentItem()
If Not itm Is Nothing Then
Set rpl = itm.Reply
rpl.BodyFormat = olFormatHTML
'rpl.Display
End If
Dim objDoc As Word.Document
Set objDoc = rpl.GetInspector.WordEditor
Dim txt As String
txt = objDoc.Content.text
Dim xlApp As Excel.Application
Set xlApp = CreateObject("Excel.application")
xlApp.Visible = True
Dim wb As Excel.Workbook
Set wb = xlApp.Workbooks.Add
Dim i As Long
For i = LBound(Split(txt, Chr(13)), 1) To UBound(Split(txt, Chr(13)), 1)
wb.Worksheets(1).Range("A" & i + 1).Value = Split(txt, Chr(13))(i)
Next i
End Sub
Function GetCurrentItem() As Object
Dim objApp As Outlook.Application
Set objApp = Application
On Error Resume Next
Select Case TypeName(objApp.ActiveWindow)
Case "Explorer"
Set GetCurrentItem = objApp.ActiveExplorer.Selection.Item(1)
Case "Inspector"
Set GetCurrentItem = objApp.ActiveInspector.CurrentItem
End Select
GetCurrentItem.UnRead = False
Set objApp = Nothing
End Function
The Outlook object model doesn't recognize lines in the body. You can try to resize any inspector window in Outlook and see how the body lines are changed.
Anyway, you may try to use the Word object model to get the exact lines. Outlook uses Word as an email editor. The WordEditor property of the Inspector class returns an instance of the Document class which represents the message body. You can read more about all possible ways in the Chapter 17: Working with Item Bodies article.
The How to automate Microsoft Excel from Visual Basic article explains how to automate Excel from any external application.
Related
I have a set of word documents that I want to auto-fill for different clients and I am trying to write a VBA application to accomplish that. I have information about the client, such as today's date and their name, stored in an Excel sheet, and I want to copy that information on multiple Word documents with labels on them. The goal is for every new client, the user would only need to update the client information on the Excel sheet to auto-fill the Word documents.
The below code is what I have right now. objDocument represents the Word document that I am trying to fill in and exWb is the Excel sheet in which I am trying to copy client information from. The Excel sheet has cells named TodayDate and ClientName which stores the respective client information. The Word document has ActiveX control labels named TodayDate, ClientName, and ClientName1 which will be filled in with the corresponding information from the Excel Sheet. ClientName and ClientName1 both contain the information from the "ClientName" cell, but because I cannot have 2 labels of the same name in Word, they are named as such.
Dim objDocument As Document
Set objDocument = Documents.Open(strPath)
objDocument.Activate
Dim objExcel As New Excel.Application
Dim exWb As Excel.Workbook
Set exWb = objExcel.Workbooks.Open(selectMasterPath)
On Error Resume Next
objDocument.TodayDate.Caption = exWb.Sheets("Sheet1").Range("TodayDate").Value
On Error Resume Next
objDocument.ClientName.Caption = exWb.Sheets("Sheet1").Range("ClientName").Value
On Error Resume Next
objDocument.ClientName1.Caption = exWb.Sheets("Sheet1").Range("ClientName").Value
On Error Resume Next
To make the code more readable, I would like to format it into a for loop, but I am not sure how to declare a variable that can refer to the names of Word document labels in a for loop. I was thinking of using arrays to store the names of Word labels and Excel cells and loop through the list. I suppose it would look something like this:
Dim objDocument As Document
Set objDocument = Documents.Open(strPath)
objDocument.Activate
Dim objExcel As New Excel.Application
Dim exWb As Excel.Workbook
Set exWb = objExcel.Workbooks.Open(selectMasterPath)
WordLabelList = [TodayDate, ClientName, ClientName1]
ExcelNames = ["TodayDate", "ClientName", "ClientName"]
Dim i as Integer
for i in range(1, length(WordLabelList))
On Error Resume Next
objDocument.WordLabelList[i].Caption = exWb.Sheets("Sheet1").Range(ExcelNames[i]).Value
Next
Or to make it even better, use a dictionary with ExcelNames as the key and WordLabelList as the values so that I do not have to repeat values in the ExcelNames array:
Dim objDocument As Document
Set objDocument = Documents.Open(strPath)
objDocument.Activate
Dim objExcel As New Excel.Application
Dim exWb As Excel.Workbook
Set exWb = objExcel.Workbooks.Open(selectMasterPath)
ClientInfo = {"TodayDate":[TodayDate], "ClientName": [ClientName, ClientName1]}
for info in ClientInfo
for label in ClientInfo[info].value
On Error Resume Next
objDocument.label.Caption = exWb.Sheets("Sheet1").Range(info).Value
Next
Please let me know how I can achieve any of the above with proper VBA syntax or if you have a more efficient suggestion that is better than re-writing multiple lines in original code.
The only thing you're missing seem to be a way to address an ActiveX control by its name? Once you have that your code gets much simpler.
For example:
Sub Tester()
Dim doc As Object, lbl As Object, nm
Set doc = ThisDocument
For Each nm In Array("TodayDate", "ClientName")
Set lbl = DocActiveX(doc, nm) 'get a reference to an embedded ActiveX control
If Not lbl Is Nothing Then
lbl.Caption = "this is - " & nm
Else
Debug.Print "Control '" & nm & "' not found"
End If
Next nm
End Sub
'return a reference to a named ActiveX control in document `doc`
' (or Nothing if not found)
Function DocActiveX(doc As Document, xName) As Object
Dim obj As Object
On Error Resume Next
Set obj = CallByName(doc, xName, VbGet)
On Error GoTo 0
Set DocActiveX = obj
End Function
I'm working on a VBA Word macro to create a personalized agenda. This is done trought the steps:
From VBA Word, open an Excel Spreadsheet
Copy a pre-defined range from the spreadsheet, into an array in Word
Create new Word document, inserting every row from the array on an individual page.
Thanks to the help I found here and on a few websites, I wrote a piece of code that executes these three steps.
After running the code and even closing Word, I get a message everytime I open the spreadsheet in Excel. The message is:
File.xlsm is blocked for edition by 'User' ; (my user)
I think it might be related to:
Calling Excel from VBA Word: I call Excel by creating an ApplicationObject (app_Excel) and using CreateObject method; to finish the application, I used Set app_Excel = Nothing, and then app_Excel.Quit, as seen in the code; Or
Opening a spreadsheet from VBA Word: In the first attempts I was using Excel.Workbooks.Open(,,,ReadOnly = False), then I changed it to True, with the same result.
Sub main()
'Main procedure
Word.Application.ScreenUpdating = False
Dim app_Excel As Excel.Application
Set app_Excel = CreateObject("Excel.Application")
Dim wbk_srce As Workbook
Set wbk_srce = app_Excel.Workbooks.Open("C:\0_portolon\Dias.xlsm", , True)
Dim wsh_srce As Worksheet
Set wsh_srce = wbk_srce.Worksheets(3)
wsh_srce.Activate
cell_1 = CStr("A1")
cell_2 = CStr("D216")
Dim header_range As Excel.Range
wsh_srce.Range(cell_1, cell_2).Select
Set header_range = Excel.Selection
Dim header_array() As Variant
header_array = header_range.Value
Set header_range = Nothing
Set wsh_srce = Nothing
Set sbk_srce = Nothing
app_Excel.Quit
'Creates Word document
Call create_agenda(header_array)
End Sub
How can I unlock the spreadsheet after copying its data into Word?
Thanks in advance,
Tiago
Following the suggestion given in the comments, I changed Set wbk = Nothing to wbk.Close; the code works correctly now.
Thanks.
Sub main()
'Main procedure
Word.Application.ScreenUpdating = False
Dim app_Excel As Excel.Application
Set app_Excel = CreateObject("Excel.Application")
Dim wbk_srce As Workbook
Set wbk_srce = app_Excel.Workbooks.Open("C:\0_portolon\Dias.xlsm", , True)
Dim wsh_srce As Worksheet
Set wsh_srce = wbk_srce.Worksheets(3)
wsh_srce.Activate
cell_1 = CStr("A1")
cell_2 = CStr("D216")
Dim header_range As Excel.Range
wsh_srce.Range(cell_1, cell_2).Select
Set header_range = Excel.Selection
Dim header_array() As Variant
header_array = header_range.Value
Set header_range = Nothing
Set wsh_srce = Nothing
wbk_srce.Close 'change
app_Excel.Quit
'Creates Word document
Call create_agenda(header_array)
End Sub
Using MS Word (in my case 2010 version), I have constructed a form with Content Control elements to be filled out by the user. Now I want certain entries (that I already gave titles to) be shown in a chart inside the same Word document (not in a separate Excel document).
This should be an automated process, so that if the user changes one of the Content Control entries, the chart updates itself automatically; I would also be OK if the user had to press a button in order to update the chart (but the user shouldn't have to click around a lot, since I must assume the user to have little skills.)
So I inserted an Excel chart object in my Word form document. I also wrote some VBA code inside this Excel object to read the Content Control values from the Word document as source for the chart. But I think what I really need is the VBA code to be in my Word document itself (for example to be executed upon click on a button by the user), yet I don't know how to address the Excel chart object and the cells within.
My VBA code inside the Excel object is:
Sub ChartDataAcquirer()
Dim wdApp As Object
Dim wdDoc As Object
Dim DocName As String
Dim ccX As String
Dim ccY As String
Dim datapairs As Integer
'''''''''' Variables '''''''''
DocName = "wordform.docm"
ccX = "titleX"
ccY = "titleY"
datapairs = 5
''''''''''''''''''''''''''''''
Set wdApp = GetObject(, "Word.Application")
Set wdDoc = wdApp.Documents(DocName)
Dim i As Integer
For i = 1 To datapairs
With ActiveSheet.Cells(i + 1, 1) ' The first row contains headline, therefore i+1
.Value = wdDoc.SelectContentControlsByTitle(ccX & i).Item(1).Range.Text ' The CC objects containing the x values have titles "titleX1", "titleX2" ..., therefore "ccX & i"
On Error Resume Next
.Value = CSng(wdDoc.SelectContentControlsByTitle(ccX & i).Item(1).Range.Text) ' To transform text into numbers, if user filled the CC object with numbers (which he should do)
End With
With ActiveSheet.Cells(i + 1, 2)
.Value = wdDoc.SelectContentControlsByTitle(ccY & i).Item(1).Range.Text
On Error Resume Next
.Value = CSng(wdDoc.SelectContentControlsByTitle(ccY & i).Item(1).Range.Text)
End With
Next
End Sub
I guess I need a similar code that is placed in and operates from the Word form document itself, but that is where I am stuck...
The following is demo code that shows how to access an embedded Excel chart.
Note that the Name (Shapes([indexValue])) of your chart Shape is probably different than in this code. You'll need to check and change that assignment. Also, your chart may be an InlineShape rather than a Shape, so you may need to adjust that bit, as well.
This code checks whether the Shape is actually a chart. If it is, the Chart object is accessed as well as its data sheet. Via that, it's possible to get the actual workbook, the worksheets, even the Excel application if you should need it.
Sub EditChartData()
Dim doc As Word.Document
Dim shp As Word.Shape
Dim cht As Word.Chart
Dim wb As Excel.Workbook, ws As Excel.Worksheet, xlApp As Excel.Application
Set doc = ActiveDocument
Set shp = doc.Shapes("MyChart")
If shp.HasChart Then
Set cht = shp.Chart
cht.ChartData.Activate
Set wb = cht.ChartData.Workbook
Set xlApp = wb.Application
Set ws = wb.ActiveSheet
Debug.Print ws.Cells(1, 2).Value2
End If
Set ws = Nothing
Set wb = Nothing
Set cht = Nothing
Set xlApp = Nothing
End Sub
This is the code in outlook VBA
Sub Sendmail()
Dim olItem As Outlook.MailItem
Dim xlApp As Excel.Application
Dim xlBook As Excel.Workbook
Dim xlSht As Excel.Worksheet
Dim sPath As String
Dim iRow As Long
Dim strRFIitems As String
Dim Signature As String
sPath = "**"
' // Excel
Set xlApp = CreateObject("Excel.Application")
' // Workbook
Set xlBook = xlApp.Workbooks.Open(sPath)
' // Sheet
Set xlSht = xlBook.Sheets("Sheet1")
' // Create e-mail Item
Set olItem = Application.CreateItem(olMailItem)
strRFIitems = xlSht.Range("E2")
Signature = xlSht.Range("F2")
With olItem
.To = Join(xlApp.Transpose(xlSht.Range("A2", xlSht.Range("A9999").End(xlUp))), ";")
.CC = Join(xlApp.Transpose(xlSht.Range("B2", xlSht.Range("B9999").End(xlUp))), ";")
.Subject = xlSht.Range("C2")
.Body = xlSht.Range("D2") & Signature
.Attachments.Add (strRFIitems)
.Display
End With
' // Close
xlBook.Close SaveChanges:=True
' // Quit
xlApp.Quit
Set xlApp = Nothing
Set xlBook = Nothing
Set xlSht = Nothing
Set olItem = Nothing
End Sub
The code retrieves the data from the linked Excel sheet. Now the
problem is with .Body = xlSht.Range("D2") & Signature this line
of code, where the body of the mail is retrieved from the D2 cell of
Excel sheet.
And as per my requirement, the body of the mail should contain a hyper
link and table along with the text.
Example:
Hello All,
Please update the details in the portal
portal link :http://google.com.
Please contact me for any clarifications.
Below mentioned details needs to be updated:
table has to be inserted here
Suppose above mentioned text is inserted into a cell of Excel.
List item
This portal link: http://google.com. becomes a plain text not a hyper link.
If I try to make it a hyper link the entire cell becomes hyper link. i.e even the text.
List item
How to insert table into a cell of Excel sheet and call it using Outlook VBA
Query:
How to insert a hyperlink and table along with the test
message into a cell of Excel and retrieve it as it is using the above
mentioned code and send a mail containing hyperlink and table.
For hyperlink you can use the following code:
Range("K6").Select
ActiveCell.FormulaR1C1 = "test"
Range("K6").Select
ActiveSheet.Hyperlinks.Add Anchor:=Selection, Address:= _
"http://www.google.com", TextToDisplay:="test"
Range("K6").Select
Selection.Hyperlinks(1).Follow NewWindow:=False, AddHistory:=True
Created a simple access DB with only 1 form and 1 one button to run code that opens an existing empty excel (with 1 worksheet) and writes "X" in its 1st cell. It does the job but the workbook is hidden and I have to manually unhide it. That is, after the VBA code is executed I open the excel file and it is all grayed out. I have to click the "view" tab and then select the "Unhide" option and all is fine and I can see that the cell was updated as needed. If I take out the VBA line that writes "X" in the excel file, it doesn't hide the workbook. How do I solve the problem of the workbook being hidden?
Windows 7 and Office2013.
Thank you!!!
Here is the code:
Private Sub Command0_Click()
Dim my_xl_app As Object
Dim my_xl_worksheet As Object
Dim my_xl_workbook As Object
Set my_xl_app = CreateObject("Excel.Application")
my_xl_app.UserControl = True
my_xl_app.Visible = False ' yes. I know it's the default
Set my_xl_workbook = GetObject("D:\Dropbox\MASAV\HIYUVIM\AAA.xlsx")
Set my_xl_worksheet = my_xl_workbook.Worksheets(1)
my_xl_worksheet.Cells(1, "A") = "V"
my_xl_workbook.Close SaveChanges:=True
Set my_xl_app = Nothing
Set my_xl_workbook = Nothing
Set my_xl_worksheet = Nothing
End Sub
S o l v e d !!!
Here is the code that works without hiding my entire workbook :
Private Sub Command0_Click()
Dim my_xl_app As Object
Dim my_xl_worksheet As Object
Dim my_xl_workbook As Object
Set my_xl_app = CreateObject("Excel.Application")
Set my_xl_workbook = my_xl_app.Workbooks.Open("D:\Dropbox\MASAV\HIYUVIM\AAA.xlsx")
Set my_xl_worksheet = my_xl_workbook.Worksheets(1)
my_xl_workbook.Sheets(1).Range("A1").Value = "V"
my_xl_workbook.Close SaveChanges:=True
Set my_xl_app = Nothing
End Sub
Got the answer right here in this this forum, in another thread which escaped my eyes...
Thanks a lot to all in this wonderful forum!!!!
Use this:
Workbooks(1).Windows(1).Visible = True