Calling a VBA macro from bat file - vba

I have a vba macro to un-merge the merged cells and repeat in excel, but i need to run this macro without opening the excel and also the same logic will be applied to multiple excels so i need a batch file which calls the vba and apply to the excel in a folder. Is there any way to do it.?

You can call this VBscript from a batch file (in a loop)
Usage:
CScript inject.vbs "C:\johan\VbaStuff\Empty workbook.xlsx" "C:
\johan\VbaStuff\DummyMacro.bas" "AddDateToA1"
inject.vbs:
dim oArgs, i, FSO
dim fileName, macroFileName, functionName
dim oApplication, oWorkbooks, oWorkbook, oVbProject
dim oComponents, oModule, fullFunction
Set oArgs = WScript.Arguments
For i = 0 to oArgs.Count - 1
WScript.Echo "Arg" & i & ": " & oArgs(i)
Next
WScript.Echo ""
if oArgs.Count < 3 then
WScript.Echo "Too few arguments"
WScript.Quit
end if
fileName = oArgs(0)
macroFileName = oArgs(1)
functionName = oArgs(2)
set FSO = CreateObject("Scripting.FileSystemObject")
if not FSO.FileExists(fileName) then
WScript.Echo "Excel file does not exist"
WScript.Quit
end if
if not FSO.FileExists(macroFileName) then
WScript.Echo "Macro file does not exist"
WScript.Quit
end if
set oApplication = CreateObject("Excel.Application")
oApplication.DisplayAlerts = False
WScript.Echo "Injecting in Excel version: " & oApplication.Version
set oWorkbooks = oApplication.Workbooks
set oWorkbook = oWorkbooks.Open(fileName)
WScript.Echo oWorkbook.Name
set oVbProject = oWorkbook.VBProject
WScript.Echo oVbProject.Name
set oComponents = oVbProject.VBComponents
set oModule = oComponents.Import(macroFileName)
fullFunction = Trim(oModule.Name & "." & functionName)
WScript.Echo "Full function: '" & fullFunction & "'"
oApplication.Run(fullFunction)
oComponents.Remove(oModule)
oWorkbook.Save()
WScript.Echo "Saved changes"
oWorkbook.Close(False)
Call oApplication.Quit()
set oModule = Nothing
set oComponents = Nothing
set oVbProject = Nothing
set oWorkbook = Nothing
set oWorkbooks = Nothing
set oApplication = Nothing
set FSO = Nothing
Dummy macro for completeness:
Attribute VB_Name = "DummyMacro"
Sub AddDateToA1()
Dim oCell As Range
Dim sTime As String
Set oCell = ThisWorkbook.Sheets(1).Cells(1, 1)
sTime = CStr(TimeValue(Now))
oCell.Value = sTime
MsgBox "Wrote time " & sTime & " to " & oCell.Address(0, 0, xlA1, 1)
End Sub

Related

Getting "Remote server machine does not exist or not available" in Outlook VBScript

I have written on Outlook VBScript which downloads the attachment from Outlook. But now I am encountering an error
Remote Server machine does not exist or is unavailable
I get this error a few time and also sometimes this code runs without any error. I was able to track the exact point of failure. The line is
Set olns = olApp.GetNameSpace("MAPI")
I have almost tried everything yet I am not able to to find the solution.
Set Arg = WScript.Arguments
Dim item1
Dim objsubject
Dim intcount
Dim i
Dim savename
Dim vTextFile
Dim filename
Dim extension
Dim t
Dim Itimestamp
Dim savefolder
Dim vSenderEmailAddress
Dim vFlagTextFileCreate
vFlagTextFileCreate = True
savefolder = "C:\Users\SANxSAxAABOTDEV\Documents\Automation Anywhere Files\Automation Anywhere\My Tasks\ThrdOutlookTest"
vTextFile = savefolder & "\File Report.txt"
Set fso = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
Set olApp = GetObject(, "Outlook.Application")
If Err.Number <> 0 Then 'Could not get instance of Outlook, so create a new one
Err.Clear
Set olApp = CreateObject("Outlook.Application")
End If
On Error Goto 0
Set olns = olApp.GetNameSpace("MAPI")
olns.Logon "Outlook", , False, True
Set objFolder = olns.GetDefaultFolder(6)
'objFolder.InAppFolderSyncObject = True
'syc.Start
For Each item1 In objFolder.Items
If item1.Unread = True Then
objsubject = item1.Subject
If InStr(UCase(objsubject) ,"RPA BOT") Then
intCount = item1.Attachments.Count
If intcount > 0 Then
For i = 1 To intcount
If InStr(item1.Attachments(i).filename, ".xls") Then
t = Now()
'Adding timestamp to the file to make it unique
Itimestamp = Right("0" & Hour(t), 2) & _
Right("0" & Minute(t), 2) & _
Right("0" & Second(t), 2)
fileName = Left(item1.Attachments(i).filename, InStr(item1.Attachments(i).filename, ".xl") - 1)
extension = Right(item1.Attachments(i).filename, Len(item1.Attachments(i).filename) - InStr(item1.Attachments(i).filename, ".xl"))
savename = saveFolder & "\" & fileName & "_" & Itimestamp & "." & extension
item1.Attachments(i).SaveAsFile savename
WScript.Sleep 1000
If item1.SenderEmailType = "SMTP" Then
vSenderEmailAddress = item1.SenderEmailAddress
ElseIf item1.SenderEmailType = "EX" Then
vSenderEmailAddress = item1.Sender.GetExchangeUser.PrimarySmtpAddress
End If 'If item1.SenderEmailType
'Create InfoFile If does not exist
If vFlagTextFileCreate = True Then
vFlagTextFileCreate = False
fso.CreateTextFile vTextFile
End If
Set ts = fso.OpenTextFile(vTextFile, 8, True, 0)
ts.WriteLine fileName & "_" & Itimestamp & "." & extension & "|" & item1.Subject & "|" & vSenderEmailAddress & vbLf
ts.Close
End If 'If InStr(item1.Attachments(i).filename
Next
'Turning the unread mail to read
item1.Unread = False
End If 'If intcount > 0 Then
End If 'If Instr(objsubject ,
End If 'If item1.Unread=True
Next
olns.Logoff
Set olns = Nothing
Set olApp = Nothing
WScript.Quit
I did some research and came to know that this issue may be caused due to the fact that the outlook session is already opened before running the script. So I added a patch before Set fso = CreateObject("Scripting.FileSystemObject") to kill all the outlook.exe session. I did not get any error for a while. I don't know if this is correct. I would be happy to know your feedback on this.
Killing the outlook.exe session before I create the object for Outlook.Application solved my error. I added a patch before Set fso = CreateObject("Scripting.FileSystemObject") to kill outlook.exe sessions. Below is the patch
strComputer = "."
Set Arg = WScript.Arguments
Process = "outlook.exe"
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcess = objWMIService.ExecQuery ("Select * from Win32_Process Where Name like '" & Process & "%'")
For Each p in colProcess
On Error Resume Next
p.Terminate
On Error GoTo 0
Next
SET objWMIService = Nothing
SET colProcess = Nothing

Access VBA Version Check Front End

I am going to be splitting an Access database into a Front End (everything except tables) and Back End (tables only). I will put the Back End file on a network share and distribute the Front End file to each user so they have their own copy. When it comes time to update the Front End I would like a message to appear when they open their version to indicate it is out of date and hopefully prevent any access.
I was thinking of creating a table on the Front End and on the Back End that stores the version number of the Front End (e.g. 1.02). Then when I update the version of the Front End in the table on the Back End the old Front Ends will pop up a message and stop working.
So I created the tables and created a query to show the Front End version number in both the Front End version table and the Back End version table. Now how do I auto run this query and pop up a message and stop access when the version numbers are different???
Is there a better way???
Thank you in advance.
It is much simpler to use a shortcut to launch the application pulling a fresh copy each time from a networked distribution folder. On a modern network it takes a second or so, and the user will always have an updated and non-bloated copy.
All you need is a script. I wrote up once a full article on how to handle this even in a Citrix environment:
Deploy and update a Microsoft Access application in a Citrix environment
The script establishes two copies of the frontend. That you may not need, thus you can reduce the script somewhat:
Option Explicit
' Launch script for PPT test/development/operation.
' Version 1.3.0
' 2013-09-15
' Cactus Data. Gustav Brock
Const DESKTOP = &H10
Const LOCALAPPDATA = &H1C
Dim objFSO
Dim objAppShell
Dim objDesktopFolder
Dim objLocalAppDataFolder
Dim objLocalFolder
Dim objRemoteFolder
Dim strLocalFolder
Dim strRemoteFolder
Dim strDesktopFolder
Dim strLocalAppDataFolder
Dim strLocalAppDataDsgFolder
Dim strLocalAppDataDsgPptFolder
Dim strDsgSubfolder
Dim strPptSubfolder
Dim strPptAppSubfolder
Dim strPptNcSuffix
Dim strAppName
Dim strAppSuffix
Dim strShortcutName
Dim strAppLocalPath
Dim strAppLocalBackPath
Dim strAppRemotePath
Dim strShortcutLocalPath
Dim strShortcutRemotePath
Dim strRegPath
Dim strRegKey
Dim strRegValue
Dim booNoColour
Dim varValue
' Adjustable parameters.
strDsgSubfolder = "DSG"
strPptSubfolder = "PPT"
strPPtNcSuffix = "NC"
' ---------------------------------------------------------------------------------
' Uncomment one folder name only:
'strPptAppSubfolder = "Development"
strPptAppSubfolder = "Operations"
'strPptAppSubfolder = "Test"
' ---------------------------------
' Indicate if the script is for the normal version (0) or the no-colour version (1):
booNoColour = 0
' ---------------------------------------------------------------------------------
strRemoteFolder = "K:\_Shared\Sales Planning\Environments\" & strPptAppSubfolder
If booNoColour = 1 Then
strAppSuffix = strPptNcSuffix
Else
strAppSuffix = ""
End If
strAppName = "SalesPlanningTool" & strAppSuffix & ".accdb"
If strPptAppSubfolder = "Operations" Then
If strAppSuffix = "" Then
strShortcutName = "RunPPT.lnk"
Else
strShortcutName = "RunPPT " & strAppSuffix & ".lnk"
End If
Else
If strAppSuffix = "" Then
strShortcutName = "RunPPT " & strPptAppSubfolder & ".lnk"
Else
strShortcutName = "RunPPT " & strAppSuffix & " " & strPptAppSubfolder & ".lnk"
End If
End If
' Enable simple error handling.
On Error Resume Next
' Find user's Desktop and AppData\Local folder.
Set objAppShell = CreateObject("Shell.Application")
Set objDesktopFolder = objAppShell.Namespace(DESKTOP)
strDesktopFolder = objDesktopFolder.Self.Path
Set objLocalAppDataFolder = objAppShell.Namespace(LOCALAPPDATA)
strLocalAppDataFolder = objLocalAppDataFolder.Self.Path
' Dynamic parameters.
strLocalAppDataDsgFolder = strLocalAppDataFolder & "\" & strDsgSubfolder
strLocalAppDataDsgPptFolder = strLocalAppDataDsgFolder & "\" & strPptSubfolder
strLocalFolder = strLocalAppDataDsgPptFolder & "\" & strPptAppSubfolder
strAppLocalPath = strLocalFolder & "\" & strAppName
strShortcutLocalPath = strDesktopFolder & "\" & strShortcutName
' Permanent parameters.
strAppRemotePath = strRemoteFolder & "\" & strAppName
strShortcutRemotePath = strRemoteFolder & "\" & strShortcutName
' Create the File System Object.
Set objFSO = CreateObject("Scripting.FileSystemObject")
If Not objFSO.FolderExists(strRemoteFolder) Then
Call ErrorHandler("No access to " & strRemoteFolder & ".")
Else
Set objRemoteFolder = objFSO.GetFolder(strRemoteFolder)
' If local folder does not exist, create the folder.
If Not objFSO.FolderExists(strLocalFolder) Then
If Not objFSO.FolderExists(strLocalAppDataDsgFolder) Then
Set objLocalFolder = objFSO.CreateFolder(strLocalAppDataDsgFolder)
If Not Err.Number = vbEmpty Then
Call ErrorHandler("Folder " & strLocalAppDataDsgFolder & " could not be created.")
End If
End If
If Not objFSO.FolderExists(strLocalAppDataDsgPPtFolder) Then
Set objLocalFolder = objFSO.CreateFolder(strLocalAppDataDsgPptFolder)
If Not Err.Number = vbEmpty Then
Call ErrorHandler("Folder " & strLocalAppDataDsgPptFolder & " could not be created.")
End If
End If
If Not objFSO.FolderExists(strLocalFolder) Then
Set objLocalFolder = objFSO.CreateFolder(strLocalFolder)
If Not Err.Number = vbEmpty Then
Call ErrorHandler("Folder " & strLocalFolder & " could not be created.")
End If
End If
End If
Set objLocalFolder = objFSO.GetFolder(strLocalFolder)
End If
If Not objFSO.FileExists(strAppRemotePath) Then
Call ErrorHandler("The application file:" & vbCrLf & strAppRemotePath & vbCrLF & "could not be found.")
Else
' Close a running PPT.
Call KillTask("PPT")
' Wait while TaskKill is running twice to close the instance(s) of PPT and PPT Background.
Call AwaitProcess("taskkill.exe")
Call KillTask("PPT Background")
' Wait while TaskKill is running twice to close the instance(s) of PPT and PPT Background.
Call AwaitProcess("taskkill.exe")
' Copy app to local folder.
If objFSO.FileExists(strAppLocalPath) Then
objFSO.DeleteFile(strAppLocalPath)
If Not Err.Number = 0 Then
Call ErrorHandler("The application file:" & vbCrLf & strAppName & vbCrLF & "can not be refreshed/updated. It may be in use.")
End If
End If
If objFSO.FileExists(strAppLocalPath) Then
Call ErrorHandler("The local application file:" & vbCrLf & strAppLocalPath & vbCrLF & "could not be replaced.")
Else
objFSO.CopyFile strAppRemotePath, strAppLocalPath
If Not Err.Number = vbEmpty Then
Call ErrorHandler("Application could not be copied to " & strLocalFolder & ".")
End If
' Create copy for PPT Background.
strAppLocalBackPath = Replace(Replace(strAppLocalPath, ".accdb", ".accbg"), "SalesPlanningTool", "SalesPlanningToolBack")
objFSO.CopyFile strAppLocalPath, strAppLocalBackPath
If Not Err.Number = vbEmpty Then
Call ErrorHandler("Background application could not be copied to " & strLocalFolder & ".")
End If
End If
' Copy shortcut.
objFSO.CopyFile strShortcutRemotePath, strShortcutLocalPath
If Not Err.Number = vbEmpty Then
Call ErrorHandler("Shortcut could not be copied to your Desktop.")
End If
End If
' Write Registry entries for Access security.
strRegKey = "HKEY_CURRENT_USER\Software\Microsoft\Office\14.0\Access\Security\"
strRegValue = "VBAWarnings"
strRegPath = strRegKey & strRegValue
varValue = 1
Call WriteRegistry(strRegPath, varValue,"REG_DWORD")
strRegKey = strRegKey & "Trusted Locations\LocationLocalAppData\"
strRegValue = "AllowSubfolders"
strRegPath = strRegKey & strRegValue
varValue = 1
Call WriteRegistry(strRegPath, varValue, "REG_DWORD")
strRegValue = "Date"
strRegPath = strRegKey & strRegValue
varValue = Now
varValue = FormatDateTime(varValue, vbShortDate) & " " & FormatDateTime(varValue, vbShortTime)
Call WriteRegistry(strRegPath, varValue, "REG_SZ")
strRegValue = "Description"
strRegPath = strRegKey & strRegValue
varValue = "Local AppData"
Call WriteRegistry(strRegPath, varValue, "REG_SZ")
strRegValue = "Path"
strRegPath = strRegKey & strRegValue
varValue = strLocalAppDataFolder & "\"
Call WriteRegistry(strRegPath, varValue, "REG_SZ")
' Run PPT.
If objFSO.FileExists(strAppLocalPath) Then
Call RunApp(strAppLocalPath, False)
Else
Call ErrorHandler("The local application file:" & vbCrLf & strAppLocalPath & vbCrLF & "could not be found.")
End If
Set objRemoteFolder = Nothing
Set objLocalFolder = Nothing
Set objLocalAppDataFolder = Nothing
Set objDesktopFolder = Nothing
Set objAppShell = Nothing
Set objFSO = Nothing
WScript.Quit
' Supporting subfunctions
' -----------------------
Sub RunApp(ByVal strFile, ByVal booBackground)
Dim objShell
Dim intWindowStyle
' Open as default foreground application.
intWindowStyle = 1
Set objShell = CreateObject("WScript.Shell")
objShell.Run Chr(34) & strFile & Chr(34), intWindowStyle, False
Set objShell = Nothing
End Sub
Sub KillTask(ByVal strWindowTitle)
Dim objShell
Set objShell = CreateObject("WScript.Shell")
objShell.Run "TaskKill.exe /FI ""WINDOWTITLE eq " & strWindowTitle & """", 7, False
Set objShell = Nothing
End Sub
Sub AwaitProcess(ByVal strProcess)
Dim objSvc
Dim strQuery
Dim colProcess
Dim intCount
Set objSvc = GetObject("winmgmts:root\cimv2")
strQuery = "select * from win32_process where name='" & strProcess & "'"
Do
Set colProcess = objSvc.Execquery(strQuery)
intCount = colProcess.Count
If intCount > 0 Then
WScript.Sleep 300
End If
Loop Until intCount = 0
Set colProcess = Nothing
Set objSvc = Nothing
End Sub
Sub WriteRegistry(ByVal strRegPath, ByVal varValue, ByVal strRegType)
' strRegType should be:
' "REG_SZ" for a string
' "REG_DWORD" for an integer
' "REG_BINARY" for a binary or boolean
' "REG_EXPAND_SZ" for an expandable string
Dim objShell
Set objShell = CreateObject("WScript.Shell")
Call objShell.RegWrite(strRegPath, varValue, strRegType)
Set objShell = Nothing
End Sub
Sub ErrorHandler(Byval strMessage)
Set objRemoteFolder = Nothing
Set objLocalFolder = Nothing
Set objLocalAppDataFolder = Nothing
Set objDesktopFolder = Nothing
Set objAppShell = Nothing
Set objFSO = Nothing
WScript.Echo strMessage
WScript.Quit
End Sub

Outputting VBA results to text file in Outlook 2010

I am trying to make the below output into a text file on my desktop. I am very new (as in today) and I found the below script online, I have gotten my head around what each but does however I am struggling to make it output as a text file. I am not sure where the commands should go (beginning middle or end?) to do this. I have found one command but I am getting errors left right and centre. Please help.
Sub CountItemsInMBX()
Dim outapp As Outlook.Application
Set outapp = CreateObject("Outlook.Application")
Dim olns As Outlook.NameSpace
Set olns = outapp.GetNamespace("MAPI")
Debug.Print GetSubFolderCount(olns.GetDefaultFolder(olFolderInbox).Parent)
End Sub
Function GetSubFolderCount(objParentFolder As MAPIFolder) As Long
Dim currentFolders As Folders
Dim fldCurrent As MAPIFolder
Set currentFolders = objParentFolder.Folders
If currentFolders.Count > 0 Then
Set fldCurrent = currentFolders.GetFirst
While Not fldCurrent Is Nothing
TempFolderCount = TempFolderCount + GetSubFolderCount(fldCurrent)
Set fldCurrent = currentFolders.GetNext
Wend
Debug.Print objParentFolder.Name & " - " & objParentFolder.Items.Count
GetSubFolderCount = TempFolderCount + objParentFolder.Items.Count
Else
Debug.Print objParentFolder.Name & " - " & objParentFolder.Items.Count
GetSubFolderCount = objParentFolder.Items.Count
End If
End Function
The following is your code, converted to call a function, passing it a string, that will write to a text file. Change the file path & name to suit your needs.
Personally, I don't like the call method because it is a waste to check if the file exists, etc. for every call. However, since your code had two subroutines that need to write text, I was too lazy to embed the proper code in your code. You could either leave as is (if seldom used), or combine together if desired.
Option Explicit
Sub CountItemsInMBX()
Dim outapp As Outlook.Application
Dim olns As Outlook.NameSpace
Set outapp = CreateObject("Outlook.Application")
Set olns = outapp.GetNamespace("MAPI")
'Debug.Print GetSubFolderCount(olns.GetDefaultFolder(olFolderInbox).Parent)
Write_To_MyLog GetSubFolderCount(olns.GetDefaultFolder(olFolderInbox).Parent)
End Sub
Function GetSubFolderCount(objParentFolder As MAPIFolder) As Long
Dim currentFolders As Folders
Dim fldCurrent As MAPIFolder
Dim TempFolderCount As Integer
Set currentFolders = objParentFolder.Folders
If currentFolders.Count > 0 Then
Set fldCurrent = currentFolders.GetFirst
While Not fldCurrent Is Nothing
TempFolderCount = TempFolderCount + GetSubFolderCount(fldCurrent)
Set fldCurrent = currentFolders.GetNext
Wend
'Debug.Print objParentFolder.Name & " - " & objParentFolder.Items.Count
Write_To_MyLog objParentFolder.Name & " - " & objParentFolder.Items.Count
GetSubFolderCount = TempFolderCount + objParentFolder.Items.Count
Else
'Debug.Print objParentFolder.Name & " - " & objParentFolder.Items.Count
Write_To_MyLog objParentFolder.Name & " - " & objParentFolder.Items.Count
GetSubFolderCount = objParentFolder.Items.Count
End If
End Function
Public Function Write_To_MyLog(sText As String)
Dim oFSO As FileSystemObject
Dim oFile As File
Dim oStream As TextStream
On Error GoTo Error_trap
Set oFSO = New FileSystemObject
If Not oFSO.FileExists("C:\Temp\Outlook_Folders.txt") Then
Set oStream = oFSO.CreateTextFile("C:\Temp\Outlook_Folders.txt")
oStream.WriteLine " "
Else
Set oFile = oFSO.GetFile("C:\Temp\Outlook_Folders.txt")
Set oStream = oFile.OpenAsTextStream(ForAppending, TristateMixed)
End If
oStream.WriteLine sText
oStream.Close
Set oStream = Nothing
Set oFile = Nothing
Set oFSO = Nothing
Early_Exit:
Exit Function
Error_trap:
Dim strError As String
strError = "In subroutine: Write_To_MyLog " & vbCrLf & _
Err.Number & vbCrLf & vbCrLf & Err.Description & vbCrLf & _
"At Line: " & Erl
Err.Source = "Module_Utilities: Write_To_MyLog at Line: " & Erl
MsgBox "Error: " & strError
'Write_To_Log strError ' This is a call to a function that saves the error info to a database table.
Resume Early_Exit
Resume Next
End Function

Save An Email As PDF Without Displaying SaveAs Dialog Box

I have an Outlook macro that saves an email as a PDF. It is passed the name of the file (EmailName) from the subject\input box and the folder (strFolder) to save to.
I am using PDFTK to create the PDF.
I show the SaveAs dialog box to save.
If dlgSaveAs.Show = -1 Then
strCurrentFile = dlgSaveAs.SelectedItems(1)
Is there a way of saving the email as PDF without showing the SaveAs dialog box to confirm the file name\folder?
----------------------------------------------------------------------------
Public Function EVAL_SaveAsPDFfile(EmailName As String, strFolder As String) As String
'====================================================
' Description: Outlook macro to save a selected item in the pdf-format
' Requires Word 2007 SP2 or Word 2010
' Requires a reference to "Microsoft Word Object Library"
' (version is 12.0 or 14.0)
' In VBA Editor; Tools-> References...
'====================================================
' also microsoft shell controls and automation
'=============================================
' set share location
'=============================================
' On Error GoTo ErrorHandling
'Root folder
Dim strTempFileName As String
strTempFileName = "\\asfs1\cons\clients"
If (Right(strFolder, 1) = "\") Then
Else
strFolder = strFolder + "\"
End If
'PDFTK
Dim program As String
program = strTempFileName & "\crm\pdftk.exe"
Dim directoremail As String
directoremail = "email#address.co.uk"
FUNC_SYSTEM_FolderExistsCreate (strFolder)
FUNC_SYSTEM_FolderExistsCreate (strTempFileName)
Set FSO = CreateObject("Scripting.FileSystemObject")
If FSO.FolderExists(strTempFileName) Then
'Get all selected items
Dim MyOlNamespace As Outlook.NameSpace
Set MyOlNamespace = Application.GetNamespace("MAPI")
Set MyOlSelection = Application.ActiveExplorer.Selection
'Make sure at least one item is selected
If MyOlSelection.Count <> 1 Then
Response = MsgBox("Please select a single item", vbExclamation, "Save as PDF")
Exit Function
End If
'Retrieve the selected item
Set MySelectedItem = MyOlSelection.Item(1)
'Get the user's TempFolder to store the item in
Dim tmpString As String
Dim tmpFileName As String, newFileName As String
tmpString = strTempFileName & "\crm\temp\" & Format(Now, "yyyyMMddHHmmss")
'construct the filename for the temp mht-file
tmpFileName = tmpString & ".mht"
'newFileName = tmpString & ".pdf"
newFileName = EmailName & ".pdf"
'Save the mht-file
MySelectedItem.SaveAs tmpFileName, olMHTML
'Create a Word object
Dim wrdApp As Word.Application
Dim wrdDoc As Word.document
Set wrdApp = CreateObject("Word.Application")
'Open the mht-file in Word without Word visible
Set wrdDoc = wrdApp.Documents.Open(FileName:=tmpFileName, Visible:=False)
'Define the SafeAs dialog
Dim dlgSaveAs As FileDialog
Set dlgSaveAs = wrdApp.FileDialog(msoFileDialogSaveAs)
'Determine the FilterIndex for saving as a pdf-file
'Get all the filters
Dim fdfs As FileDialogFilters
Dim fdf As FileDialogFilter
Set fdfs = dlgSaveAs.Filters
'Loop through the Filters and exit when "pdf" is found
Dim i As Integer
i = 0
For Each fdf In fdfs
i = i + 1
If InStr(1, fdf.Extensions, "pdf", vbTextCompare) > 0 Then
Exit For
End If
Next fdf
'Set the FilterIndex to pdf-files
dlgSaveAs.FilterIndex = i
'Get location of My Documents folder
Dim WshShell As Object
Dim SpecialPath As String
Set WshShell = CreateObject("WScript.Shell")
SpecialPath = WshShell.SpecialFolders(16)
'Construct a safe file name from the message subject
Dim msgFileName As String
msgFileName = MySelectedItem.subject
Set oRegEx = CreateObject("vbscript.regexp")
oRegEx.Global = True
oRegEx.Pattern = "[\\/:*?""<>|]"
msgFileName = Trim(oRegEx.Replace(msgFileName, ""))
'Set the initial location and file name for SaveAs dialog
'=============================================
' set default location
'=============================================
Dim strCurrentFile As String
If (TypeOf MyOlSelection.Item(1) Is Outlook.mailitem) Then
strCurrentFile = GetClientFolder(MyOlSelection.Item(1))
End If
If strCurrentFile = vbNullString Then
dlgSaveAs.InitialFileName = strFolder
Else
If FileFolderExists(strCurrentFile & "\") Then
dlgSaveAs.InitialFileName = strCurrentFile & "\"
Else
dlgSaveAs.InitialFileName = strFolder
End If
End If
dlgSaveAs.Execute
Set objFSO = CreateObject("Scripting.FileSystemObject")
' minimize outlook to show save as dialog
Set OutlookObj = GetObject(, "Outlook.Application")
OutlookObj.ActiveExplorer.WindowState = olMinimized
Dim objShell As Shell
Set objShell = New Shell
'' objShell.MinimizeAll
'Show the SaveAs dialog and save the message as pdf
newFileName = Replace(newFileName, ":", " -", Start:=1)
dlgSaveAs.InitialFileName = strFolder + newFileName
dlgSaveAs.Execute
If dlgSaveAs.Show = -1 Then
strCurrentFile = dlgSaveAs.SelectedItems(1)
'Verify if pdf is selected
If Right(strCurrentFile, 4) <> ".pdf" Then
Response = MsgBox("Sorry, only saving in the pdf-format is supported." & vbNewLine & vbNewLine & "Save as PDF instead?", vbInformation + vbOKCancel)
If Response = vbCancel Then
' wrdDoc.Close
' wrdApp.Quit
Exit Function
ElseIf Response = vbOK Then
intPos = InStrRev(strCurrentFile, ".")
If intPos > 0 Then
strCurrentFile = Left(strCurrentFile, intPos - 1)
End If
strCurrentFile = strCurrentFile & ".pdf"
End If
End If
'Save as pdf
wrdApp.ActiveDocument.ExportAsFixedFormat OutputFileName:=newFileName, ExportFormat:=wdExportFormatPDF, OpenAfterExport:=False, OptimizeFor:=wdExportOptimizeForPrint, Range:=wdExportAllDocument, From:=0, To:=0, Item:=wdExportDocumentContent, IncludeDocProps:=True, KeepIRM:=True, CreateBookmarks:=wdExportCreateNoBookmarks, DocStructureTags:=True, BitmapMissingFonts:=True, UseISO19005_1:=False
EVAL_SaveAsPDFfile = strCurrentFile
' now append the temp file with the chosen one
'=============================================
' set pdftk location
'=============================================
Dim tempPDF
tempPDF = tmpString & " temp.pdf"
' if existing file, append to old
If objFSO.FileExists(strCurrentFile) Then
Dim command As String
command = Chr(34) & program & Chr(34) & " " & Chr(34) & newFileName & Chr(34) & " " & Chr(34) & strCurrentFile & Chr(34) & " cat output " & Chr(34) & tempPDF & Chr(34)
Dim oShell
Set oShell = CreateObject("WScript.Shell")
fdsk = oShell.Run(command, 1, True)
Set oShell = Nothing
' MsgBox ("Temp: " & tempPDF + ", Current: " & strCurrentFile)
objFSO.CopyFile tempPDF, strCurrentFile, True
Else
' create file to be overwriten
Dim fsonewpdf As Object
Set fsonewpdf = CreateObject("Scripting.FileSystemObject")
Dim oFile As Object
Set oFile = fsonewpdf.CreateTextFile(strCurrentFile)
oFile.WriteLine "test"
oFile.Close
Set fsonewpdf = Nothing
Set oFile = Nothing
objFSO.CopyFile newFileName, strCurrentFile, True
End If
'copy new file to saveas file
'delete temp files
If objFSO.FileExists(tempPDF) Then
objFSO.DeleteFile tempPDF
End If
If objFSO.FileExists(newFileName) Then
objFSO.DeleteFile newFileName
End If
'close the document and Word
wrdDoc.Close
'wrdApp.Quit
If objFSO.FileExists(tmpFileName) Then
objFSO.DeleteFile tmpFileName
End If
Else
' close the document and Word
wrdDoc.Close
'wrdApp.Quit
End If
If objFSO.FileExists(tmpFileName) Then
objFSO.DeleteFile tmpFileName
End If
' maximize outlook now that we have finished
''OutlookObj.ActiveExplorer.WindowState = olMaximized
'objShell.UndoMinimizeALL
Set objShell = Nothing
Set dlgSaveAs = Nothing
'Cleanup
Set MyOlNamespace = Nothing
Set MyOlSelection = Nothing
Set MySelectedItem = Nothing
Set wrdDoc = Nothing
Set wrdApp = Nothing
Set oRegEx = Nothing
End If
'ErrorHandling:
' MsgBox "The Email failed to save, please delete the Evaluation record and try again or manually save the email as a PDF and add it.", vbOKOnly, "Error Saving Email"
' EVAL_SaveAsPDFfile = ""
End Function

Copy mails from local folder to public/shared folder

This Outlook macro is supposed to, when the local folder has 5 emails, ask the user to move them to a public shared folder and delete the original 5 emails.
I keep getting this "Operation failed" error message on the line below.
**Set NewFolder = myFolder.CopyTo(PblcSharedFolder)**
From comment: This line is meant to copy the entire folder of five emails.
Sub MoveEmail()
Dim app As New Outlook.Application
Dim nameSpace As Outlook.nameSpace
Dim currentExplorer As Outlook.Explorer
Dim currentSelection As Outlook.selection
Dim currentMailItem As MailItem
Dim emailCopy As MailItem
Dim myFolder
Dim PblcSharedFolder As MAPIFolder
Dim NewFolder As MAPIFolder
Dim i As Integer
Dim folderName
Dim mailboxNameString
Dim result
folderName = "Local Folder"
mailboxNameString = "My Inbox Name"
Set nameSpace = app.GetNamespace("MAPI")
Set currentExplorer = app.ActiveExplorer
Set currentSelection = currentExplorer.selection
Set myFolder = nameSpace.Folders(mailboxNameString).Folders("Inbox").Folders(folderName)
If (myFolder.Items.Count = 5) Then
result = MsgBox("Would you like to move the content of your Local folder to the Public-shared Folder?", vbYesNo)
If result = vbYes Then
Set PblcSharedFolder = nameSpace.GetDefaultFolder(olPublicFoldersAllPublicFolders)
Set PblcSharedFolder = PblcSharedFolder.Folders("Subfolder")
Set PblcSharedFolder = PblcSharedFolder.Folders("Public Shared Folder")
Set NewFolder = myFolder.CopyTo(PblcSharedFolder)
NewFolder.Name = "_" & nameSpace.CurrentUser.Name & " " & Now
For i = myFolder.Items.Count To 1 Step -1
myFolder.Items(i).Delete
Next i
Else
Stop
End If
End If
For i = 1 To currentSelection.Count
Set currentMailItem = currentSelection.Item(i)
Debug.Print "[" & Date & " " & Time & "] moving #" & m & _
": xfolder = " & folderName & _
"; subject = " & currentMailItem.Subject & "..."
currentMailItem.To = nameSpace.CurrentUser.Name
currentMailItem.Move myFolder
Next i
End Sub
untested!
If result = vbYes Then
Set PblcSharedFolder = nameSpace.GetDefaultFolder(olPublicFoldersAllPublicFolders)
Set PblcSharedFolder = PblcSharedFolder.Folders("Subfolder")
Set PblcSharedFolder = PblcSharedFolder.Folders("Public Shared Folder")
Dim myCopiedItem As Outlook.MailItem
For i = myFolder.Items.Count To 1 Step -1
Set myCopiedItem = myFolder.Items(i).Copy
myCopiedItem.Move PblcSharedFolder
myFolder.Items(i).Delete
Next i
Else
Stop
End If
I did to be honest not quite unterstand what this line is for:
NewFolder.Name = "_" & nameSpace.CurrentUser.Name & " " & Now