I'm trying to write a macro in Outlook that reads an Excel file that has full paths and filenames in separate cells and inserts them as hyperlinks in an email.
I found information on how to create a hyperlink in Outlook. I can't find anything on how I Outlook would get the file paths from the Excel sheet.
Error says
Compile Error: User-defined type not defined
Sub links()
Dim objExcel As New Excel.Application
Dim exWb As Excel.Workbook
Dim ExcelFileName As String
Dim FilePath As String
ExcelFileName = "C:\links.xlsx"
Set exWb = objExcel.Workbooks.Open(ExcelFileName)
FilePath = exWb.Sheets("Sheet1").Cells(1, 1)
oMsg.TextBody = Chr(34) & FilePath & Chr(34)
End Sub
In the Outlook VBA editor set a reference to Excel.
Tools | References
Tick Microsoft Excel Object Library
Add Option Explict to new modules. You will find this helpful.
Tools | Options | Editor tab
Tick Require Variable Declaration
.
Option Explicit
Sub links()
Dim objExcel As New Excel.Application
Dim exWb As Excel.Workbook
Dim ExcelFileName As String
Dim FilePath As String
Dim oMsg As mailItem
ExcelFileName = "C:\links.xlsx"
Set exWb = objExcel.Workbooks.Open(ExcelFileName)
FilePath = exWb.Sheets("Sheet1").Cells(1, 1)
On Error Resume Next
Set oMsg = ActiveInspector.currentItem
On Error GoTo 0
If oMsg Is Nothing Then
Set oMsg = CreateItem(0)
oMsg.Display
End If
' This adds to existing text.
' Must display first to save a signature
'oMsg.body = Chr(34) & FilePath & Chr(34) & oMsg.body
'or
oMsg.HTMLBody = Chr(34) & FilePath & Chr(34) & oMsg.HTMLBody
ExitRoutine:
Set oMsg = Nothing
Set exWb = Nothing
Set objExcel = Nothing
End Sub
Related
I am trying to save a list of email in msg format to htm format so that Xceptor tool can read the email as pdf. (Without a vba, Currently I manually open the email in Outlook and save as htm one by one.)
I found below script but I get
"Run Time error 287: Application-defined or object-defined error".
Sub SaveMSG_as_HTML()
Dim olMsg As MailItem
Dim strPath As String
Dim strMsg As String
Dim strHTML As String
strPath = "\\Hbap.adroot.hsbc\hk\Finance\224017\AMH_A2R_2\WRK\AAC\PL\To GFC\Movement Table\MvtXceptor\Configuration\Table18.1\"
strMsg = "RE CRR Inquiry as atJan-00-00 - --.msg"
strHTML = Left(strMsg, InStrRev(strMsg, Chr(46))) & "html"
Set olMsg = Session.OpenSharedItem(strPath & strMsg)
olMsg.SaveAs Path:=strPath & strHTML, Type:=olHTML
olMsg.Close olDiscard
lbl_Exit:
Set olMsg = Nothing
Exit Sub
End Sub
Without a vba, i need to open the email in outlook and save as htm one by one.
Without VBA? So I guess you want to use VBScript? Say, directly run it from desktop by clicking on the .vbs file? If yes, then you need to declare and create/get the outlook object before you can work with it. Otherwise how will your code know what is Session? Also olHTML and olDiscard are Outlook constants. VbScript will not know what they are.
Is this what you are trying? Paste this in Notepad and save it as Sample.Vbs
Private Const olHTML = 5
Private Const olDiscard = 1
Dim OutApp
Dim olMsg
Dim nsOutlook
Dim strPath
Dim strMsg
Dim strHTML
'~~> I used these values for testing. Change as applicable
strPath = "C:\Temp\"
strMsg = "test.msg"
strHTML = "test.html"
Set OutApp = CreateObject("Outlook.Application")
Set nsOutlook = OutApp.GetNamespace("MAPI")
Set olMsg = nsOutlook.OpenSharedItem(strPath & strMsg)
olMsg.SaveAs strPath & strHTML, olHTML
olMsg.Close olDiscard
Set olMsg = Nothing
Set nsOutlook = Nothing
Set OutApp = Nothing
I've the below code that I'm using in outlook to download an attachment from a list of emails.
The code works fine for the first iteration of the loop, but on the second iteration it errors with Run-time error '91' Object variable or With block variable not set at the step where it is attempting to save the file to a temporary folder on the desktop (i.e. the line wb.SaveAs FileFormat:=51, FileName:=xlNameAndPath).
From reading the documentation here and some testing, it seems that the issue is actually being caused in the first iteration of the loop by wb.close, this sets wb to nothing, which then causes the error in the second iteration.
If i'm right then my question is how to "Respecify a reference for the object variable"?
Sub SaveExcels()
Dim objNS As Outlook.NameSpace: Set objNS = GetNamespace("MAPI")
Dim olFolder As Outlook.MAPIFolder
Set olFolder = objNS.GetDefaultFolder(olFolderInbox)
Dim Item As Object
Dim objAttachments As Outlook.Attachments
For Each Item In olFolder.Items
If TypeOf Item Is Outlook.MailItem Then
Dim oMail As Outlook.MailItem: Set oMail = Item
' Check it contains an attachment
Set objAttachments = oMail.Attachments
lngCount = objAttachments.Count
' Check its from the right company
senderCheck = InStr(oMail.SenderEmailAddress, "company.com")
' Check that it is the right email type
subjectCheck = InStr(oMail.Subject, "TYPE")
' Check whether its the latest weeks data
receivedDate = DateValue(oMail.ReceivedTime)
todaysDate = DateValue(Now())
dateDifference = todaysDate - receivedDate
If lngCount > 0 And senderCheck > 0 And subjectCheck > 0 And dateDifference <= 7 Then
' Get the file name
strFile = objAttachments.Item(1).FileName
' Debug.Print strFile
strFolderpath = "D:\Users\" & Environ("Username") & "\Desktop\temp\"
' Combine with the path to the Temp folder.
strFileIncPath = strFolderpath & strFile
' Debug.Print strFile
' Save the attachment as a file.
objAttachments.Item(1).SaveAsFile strFileIncPath
' Extract the files into the newly created folder
Set oApp = CreateObject("Shell.Application")
oApp.NameSpace(strFolderpath).CopyHere oApp.NameSpace(strFileIncPath).Items
' Delete the zip file
Kill strFileIncPath
' Open the excel file
Dim xlApp As Object
Set xlApp = CreateObject("Excel.Application")
xlApp.Application.Visible = True
xlName = Replace(strFile, ".ZIP", "")
xlNameTemp = xlName & "_00000.xls"
xlNameAndPath = strFolderpath & xlName
Debug.Print xlNameAndPath
xlApp.Workbooks.Open strFolderpath & xlNameTemp
Dim wb As Workbook
Set wb = ActiveWorkbook
' Save as unique name and close
wb.SaveAs FileFormat:=51, FileName:=xlNameAndPath << ERROR
' Get rid of the old excel
Kill strFolderpath & xlNameTemp
' Close the workbook
wb.Close
End If
End If
Next
End Sub
I believe
Dim wb As Workbook
Set wb = xlApp.Workbooks.Open(strFolderpath & xlNameTemp)
will do the job, per the docs. (Not tested -YMMV!)
I'm exporting filtered results from my subform to Excel, and naming Excel file as I want. Here's my code :
Sub XcelExport()
Dim Results As Recordset
Dim RecCount As Integer
Dim XcelFileName As String
Dim FilePath As String
Dim wb As Excel.Workbook
Dim XcelFile As Excel.Application
'Set name of file with date
XcelFileName = "MySubform_Results_" & Format(Date, "dd/mm/yyyy") & ".xlsx"
' Set destinaton folder of saved file
FilePath = CurrentProject.Path & "\" & XcelFileName
Set XcelFile = New Excel.Application
Set wb = XcelFile.Workbooks.Add
'Fetch subform record source
Set Results = Forms![MainForm]![MySubform].Form.RecordsetClone
With wb
XcelFile.ScreenUpdating = False
' Add field names to workbook
For RecCount = 0 To Results.Fields.Count - 1
XcelFile.Cells(1, RecCount + 1).Value = Results.Fields(RecCount).Name
Next RecCount
' Copy subform results to Excel file
XcelFile.Range("A2").CopyFromRecordset Results
.SaveAs Filename:=FilePath, FileFormat:=51
XcelFile.ScreenUpdating = True
.Close
End With
Set XcelFile = Nothing
Set Results = Nothing
End Sub
Code works, with one flaw. When I run it again, it creates a new file again, but .RecordsetClone is gone, so values from Subform are not exported again. Beside that, I find it very strange that code works, just take a look at »with wb« statement – I had to reference to XcelFile on certain commands or they didn't work, regardless I allready set wb to XcelFile in code above (Set wb = XcelFile.Workbooks.Add). What Is wrong in my code, does anybody have a better solution ???
So this is final code, I hope It will be useful to someone else too.
Sub XcelExport()
Dim Results As Recordset
Dim RecCount As Integer
Dim XcelFileName As String
Dim FilePath As String
Dim wb As Excel.Workbook
Dim XcelFile As Excel.Application
'Set name of file with date
XcelFileName = "MySubform_Results_" & Format(Date, "dd/mm/yyyy") & ".xlsx"
' Set destinaton folder of saved file
FilePath = CurrentProject.Path & "\" & XcelFileName
Set XcelFile = New Excel.Application
Set wb = XcelFile.Workbooks.Add
'Fetch subform record source
Set Results = Forms![MainForm]![MySubform].Form.RecordsetClone
With wb
XcelFile.ScreenUpdating = False
' Add field names to workbook
For RecCount = 0 To Results.Fields.Count - 1
XcelFile.Cells(1, RecCount + 1).Value = Results.Fields(RecCount).Name
Next RecCount
' Copy subform results to Excel file and set Results to first row
Results.Movefirst
XcelFile.Range("A2").CopyFromRecordset Results
.SaveAs Filename:=FilePath, FileFormat:=51
XcelFile.ScreenUpdating = True
.Close
End With
Set XcelFile = Nothing
Set Results = Nothing
End Sub
I am having trouble with what seems to be something simple from what I have found so far. I am trying to link data from an excel workbook to a table on a word document through VBA. This is the code that I have found and changed slightly so far...
Sub GetData()
Dim strPath As String
Dim strFileName As String
Dim strFileExtension As String
Dim strFullName As String
strPath = "file path here"
strFileName = "file name here"
strFileExtension = "Extension here"
strFullName = strPath & strFileName & strFileExtension
Set objWorkbook = objExcel.Workbooks.Open(strFullName)
'Set the text of the cell from Excel to the cell in the specified table in
'Word (the second table in this instance)
ActiveDocument.Tables(1).Cell(2, 2).Range.Text = objWorkbook.Sheets("Sheet1") _
.Cells(2, 1)
'Close Excel bits
objWorkbook.Close
Set objWorkbook = Nothing
End Sub
The initial errors I had found were not having the excel object library checked off in References and simple syntax errors. After fixing those I am now getting a 'RunTime Error 91 Object Variable or With Block Variable not set'. This error occurs when I am attempting to set the objWorkbook variable. I have these public variable declared...
Public objExcel As Excel.Application
Public objWorkbook As Excel.Workbook
Public objWorksheet As Excel.Worksheet
Public objRange As Excel.Range
However, when I look up this error, all I find is that I need to declare these public variables. Not sure where to go from here. If anyone could push me in the right direction, that would be greatly appreciated. Also, thank you for all the help so far, this website is a life saver.
Try this:
Sub GetData()
Dim strPath As String
Dim strFileName As String
Dim strFileExtension As String
Dim strFullName As String
dim objExcel As Object, objWorkbook As Object
strPath = "file path here"
strFileName = "file name here"
strFileExtension = "Extension here"
strFullName = strPath & strFileName & strFileExtension
Set objExcel = CreateObject("Excel.Application")
Set objWorkbook = objExcel.Workbooks.Open(strFullName)
'Set the text of the cell from Excel to the cell in the specified table in
'Word (the second table in this instance)
ActiveDocument.Tables(1).Cell(2, 2).Range.Text = objWorkbook.Sheets("Sheet1").Cells(2, 1)
'Close Excel bits
objWorkbook.Close
objExcel.Quit
Set objWorkbook = Nothing
Set objExcel = Nothing
End Sub
Btw you don't need to add references if you use the CreateObject function as used above.
You had a couple of issues:
Did not define (set) the objExcel application
Weren't closing (cleaning) after execution properly
Unnecessary Public declarations of Excel objects
How can I run an Excel macro from an Outlook macro?
You will need to add the Microsoft Excel 14.0 Data Objects library. Go to Tools -> References.
You will also need to open the workbook before you can run a macro from it.
This should work:
Dim ExApp As Excel.Application
Dim ExWbk As Workbook
Set ExApp = New Excel.Application
Set ExWbk = ExApp.Workbooks.Open("C:\Folder\Folder\File.xls")
ExApp.Visible = True
ExWbk.Application.Run "ModuleName.YourMacro"
ExWbk.Close SaveChanges:=True
If you want to run this macro in the background and not open a visible instance of Excel, then set ExApp.Visible to False.
I just wanted to share how I do this. It doesn't apply to OP's needs, but the title may lead others here for more what I'm sharing. This will (optionally filter by sender/subject) save/open/run macro from spreadsheet received in outlook. I then have a macro in excel sometimes which sends notification/response etc, but I don't do this from Outlook (probably could though!).
Create a VBS script which will launch the excel file and run a macro (optionally the macro can be stored in a separate spreadsheet.)
"runmacro.vbs"
Set args = Wscript.Arguments
ws = WScript.Arguments.Item(0)
macro = WScript.Arguments.Item(1)
If wscript.arguments.count > 2 Then
macrowb = WScript.Arguments.Item(2)
End If
LaunchMacro
Sub LaunchMacro()
Dim xl
Dim xlBook
Set xl = CreateObject("Excel.application")
Set xlBook = xl.Workbooks.Open(ws, 0, True)
If wscript.arguments.count > 2 Then
Set macrowb = xl.Workbooks.Open(macrowb, 0, True)
End If
'xl.Application.Visible = True ' Show Excel Window
xl.Application.run macro
'xl.DisplayAlerts = False ' suppress prompts and alert messages while a macro is running
'xlBook.saved = True ' suppresses the Save Changes prompt when you close a workbook
'xl.activewindow.close
xl.Quit
End Sub
Outlook VBA Code (ThisOutlookSession):
https://www.slipstick.com/outlook/email/save-open-attachment/
Private Declare Function GetShortPathName Lib "kernel32" _
Alias "GetShortPathNameA" (ByVal lpszLongPath As String, _
ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long
Private Sub objItems_ItemAdd(ByVal Item As Object)
Dim objMail As Outlook.MailItem
Dim objWsShell As Object
Dim strTempFolder As String
Dim objAttachments As Outlook.Attachments
Dim objAttachment As Attachment
Dim strFileName As String
Dim Subject As String
Subject = Item.Subject
'If Subject Like "*SubTest*" Then
If Item.Class = olMail Then
Set objMail = Item
'Change sender email address
'If objMail.SenderEmailAddress = "boss#datanumen.com" Then
Set objWShell = CreateObject("WScript.Shell")
strTempFolder = Environ("Temp") & "\"
Set objWsShell = CreateObject("WScript.Shell")
Set objAttachments = objMail.Attachments
If objAttachments.Count > 0 Then
For Each objAttachment In objAttachments
strFileName = objAttachment.DisplayName
On Error Resume Next
Kill strTempFolder & strFileName
On Error GoTo 0
'Save the attachment
objAttachment.SaveAsFile strTempFolder & strFileName
'Open the attachment
vbs = (Chr(34) & "\\Server\Excel\" & "\runmacro.vbs " & Chr(34))
strFileName = GetShortFileName(strTempFolder & strFileName)
macro = "MacroName"
xlam = Environ("APPDATA") & "\Microsoft\Excel\XLSTART\Add-In.xlam"
On Error Resume Next
objWsShell.Run vbs & " " & strFileName & " " & macro & " " & xlam
objMail.UnRead = False
Next
'End If
End If
End If
'End If
End Sub
Function GetShortFileName(ByVal FullPath As String) As String
Dim lAns As Long
Dim sAns As String
Dim iLen As Integer
On Error Resume Next
If Dir(FullPath) <> "" Then
sAns = Space(255)
lAns = GetShortPathName(FullPath, sAns, 255)
GetShortFileName = Left(sAns, lAns)
End If
End Function