So I made a VBScript that edits excel files. The script is supposed to edit particular files, so if an unrecognizable excel file is used as input, a runtime error occurs. The problem with this is that it leaves an excel process in the background running. How can I make it so if an error occurs the process is still ended? Here is some of the basic code
Set objExcel = CreateObject("Excel.Application")
Set objWorkbook = objExcel.Workbooks.Open("C:\sequencerData.xlsx")
' Perform Editing Here. Possible runtime error over here
objWorkbook.SaveAs "C:\test.xlsx", 51
objWorkbook.Close False
objExcel.Quit
Related
I use VBA to create copies (Excel and PDF) of an Excel document.
I save in the OneDrive folder (C:\Users\XXX\OneDrive) so I can access the document from every device later. I use this folder so I can save while I am connected to internet or not.
When I am connected to internet and OneDrive everything works.
When I am not connected to internet I get
error 1004 method saveas of object _workbook failed
My macro stops but when I go to the folder the files are there.
I get the error on:
ActiveWorkbook.SaveAs Filename:=Fname, FileFormat:=xlOpenXMLWorkbookMacroEnabled, CreateBackup:=False
(Fname="C:\Users\XXX\OneDrive\YYY\ZZZ.xlsm")
I couldn't find anything related to this function not working on OneDrive while not connected to internet.
If your file is in OneDrive, I would first make sure to deactivate the AutoSave feature. I've personally had some bugs with it in the past, so it might help.
I'm not aware of this particular bug that you are experiencing, but since you are saying that the file is actually saved properly even if an error is triggered, there is a way to ignore the error and check if the file was actually saved. It would look a little like this:
Const RETRY_LIMIT = 2
Dim DoesFileExist As Boolean
dim RetryCounter as Integer
Do While RetryCounter < RETRY_LIMIT And DoesFileExist = False
On Error Resume Next
ActiveWorkbook.SaveAs Filename:=Fname, FileFormat:=xlOpenXMLWorkbookMacroEnabled, CreateBackup:=False
On Error GoTo 0
DoesFileExist = FileExists(Fname)
RetryCounter = RetryCounter + 1
Loop
If DoesFileExist = False Then
MsgBox "Error: File couldn't be saved."
Exit Sub
End If
Note that I've added a retry limit of 2 to make sure that we don't go into an infinite loop.
Also make sure to add the following function in the module you are working on to make sure the code above works.
Function FileExists(ByVal FullFileName As String) As Boolean
If Dir(FullFileName) <> vbNullString Then FileExists = True
End Function
Some explanations and caveats
If you have never used error handling statements such as : On Error Resume Next or On Error GoTo 0, I would strongly advise you to have a look at C. Pearson's Error Handling In VBA article.
To summarize, what On Error Resume Next does is simply ignore the error and let the code handle the error. In our case, the DoesFileExist does the job of making sure that the code ran without error and the if statement after the loop will make sure to stop the code if all tentative to save the file failed. This does the job, but you could also check Err.Number to handle different type of error as well.
Regarding On Error GoTo 0, to put it simply, it resets the VBA error handling to its normal state where any error will launch the usual run-time error dialog box
I ended up saving the file on my desktop and then using FileSystemObject to move the file. It works fine except that if I try to open the file right away (using VBA or directly in windows explorer) I get a network error. If I wait about 1 min I don't get that error anymore. So I decided to live with it for now.
here is an example:
Dim FSO as Object
Set FSO = CreateObject("Scripting.Filesystemobject")
FSO.MoveFile("SourceFileName", "TargetFileName")
Thank you very much for your help
I seem to have stumbled upon a problem I can't seem to figure out how to solve. I'm currently working with 2 separate workbooks, one of them is the active workbook the code is run from, the other one is a separate workbook I need to open:
On Error GoTo ErrorHandler:
Set manWb = ActiveWorkbook
Application.AutomationSecurity = msoAutomationSecurityForceDisable
Set conWb = Workbooks.Open(PARDirOTC & PARFileOTC, ReadOnly:=False)
Application.AutomationSecurity = msoAutomationSecurityByUI
ActiveWindow.Visible = False
On Error GoTo 0
I set the AutomationSecurity to msoAutomationSecurityForceDisable to prevent that second workbook from running its Workbook_Open event, which has code in it I don't need in this situation. That error handling event never seems to activate, and the code keeps going without issues.
Everything works nicely from this point on, I gather and exchange data between these 2 workbooks and nothing seems to go wrong. That is, until it gets to the point where I need to create a worksheet on the second workbook, the one called "conWb".
Set conOT = conWb.Sheets.Add(After:=conWb.Sheets(conWb.Sheets.Count))
This is the troubling line. The worksheet is created, but the code suddenly stops executing at this point. No error message at all, nothing pops up, it simply stops. I've noticed that the code apparently stops executing, and switches to the code in the newly created sheet, which is blank and has nothing in it. I can't understand why.
I've looked around, other people seem to have found similar issues, but none of their solutions worked for me. I've tried playing around with several Application settings, like EnableEvents, ScreenUpdating, AutomationSecurity, etc, but nothing works. Along the code, I've also tried to remove or comment out all of the "On Error" events, fearing that they could be hiding an error that could explain this behaviour, but it doesn't seem to be the case.
I'll highly appreciate if someone with more experience than me could help figure out what could be the reason for this behaviour. Thanks in advance.
Kind regards
Using Application.EnableEvents instead of Application.AutomationSecurity when opening the second workbook, like one of you suggested, ended up solving the entire issue. Like so:
On Error GoTo ErrorHandler:
Set manWb = ActiveWorkbook
Application.EnableEvents = False
Set conWb = Workbooks.Open(PARDirOTC & PARFileOTC, ReadOnly:=False)
Application.EnableEvents = True
ActiveWindow.Visible = False
On Error GoTo 0
As far as I know, AutomationSecurity can be used to disable all macros when opening a workbook programatically, and I thought that would be enough to prevent the Workbook_Open event, but I'm assuming that either there's some other event I wasn't aware of, or the AutomationSecurity setting works in a different way than what I initially thought.
Either way, the problem seems to be solved, so thank you.
Kind regards
I'm fixing some code written by a colleague and I've come across this hurdle where an Excel document is opened from a Sharepoint and the ChangeFileAccess method is run to change it to Read/Write. The method fails with error code 1004. The file opens so everything up to that point is working.
I can't see why it won't work, I'm hoping someone more knowledgeable than I can!
I've removed the file path and document name for the sake of anonymity.
I'm using Office 365, code in question below:
Dim ObjFileA, ObjfileB As File
FilePathA = "filepath" & fileName
Set FSO = CreateObject("Scripting.FileSystemObject")
Set App = CreateObject("Excel.Application")
Set ObjFileA = FSO.GetFile(FilePathA)
Set wbA = Workbooks.Open(ObjFileA, False, False)
wbA.Activate
wbA.ChangeFileAccess (xlReadWrite)
Set wbA = Workbooks(fileName)
Is your file already being opened as Read-Write?
I just encountered a similar problem to what you describe (Err 1004 when changing the access method, though in my case I was attempting to change the access to Read-Only on a file that was already Read-Only.)
After some testing, I get the error every time if I try to invoke wkbk.ChangeFileAccess to "change" the access type to be the same as the current access type.
If you find that the workbook might already be Read-Write, then I suggest a change to :
If wbA.ReadOnly then wbA.ChangeFileAccess (xlReadWrite)
I have some Excel macro which works on a specific Excel worksheet. It checks some table and sends reminder email to some people as needed.
I want that this macro will run once a day in order to check the table every day so I will not need to open the worksheet and to do it myself every day.Does it availabe to do it? I heard about Windows task scheduler as one option, Do you think that is a good option for my purpose?
Task Scheduler is a good option as you say. To spawn a new process and open a workbook you'd have a command line specifiying (1) The Excel executable and (2) the workbook to open so something like
C:\Program Files\Microsoft Office 15\root\office15\Excel.exe "c:\MyWorkbook.xlsm"
I'd advise double quotes around the full path to the workbook (but not required for the Excel.exe).
Then in MyWorkbook.xlsm you can write code that runs upon workbook opening, classically this has been sub Auto_Open in any standard module or Sub Workbook_Open() in the ThisWorkbook module.
I would recommend a VBScript file and make that to run every day using task scheduler. I prefer this, cause then I can open the Excel file any time of the day and the macro won't run (in case you just want it to update only at that specific time).
This is the VBscript you need to write in notepad and then save with *.vbs extension.
Option Explicit
'On Error Resume Next 'Comment-out for debugging
ExcelMacro
Sub ExcelMacro()
Dim xlApp
Dim xlBook
Set xlApp = CreateObject("Excel.Application")
Set xlBook =
xlApp.Workbooks.Open("path\to\the\file.xlsm", 0, True)
xlApp.Run "Update" 'Name of your Sub
xlBook.Save
xlBook.Close
xlApp.Quit
Set xlBook = Nothing
Set xlApp = Nothing
End Sub
Then you can set the event scheduler from the command-line, like this from here:
schtasks /Create [/S <system> [/U <username> [/P [<password>]]]]
[/RU <username> [/RP <password>]] /SC <schedule> [/MO <modifier>] [/D <day>]
[/M <months>] [/I <idletime>] /TN <taskname> /TR <taskrun> [/ST <starttime>]
[/RI <interval>] [ {/ET <endtime> | /DU <duration>} [/K] [/XML <xmlfile>] [/V1]]
[/SD <startdate>] [/ED <enddate>] [/IT] [/Z] [/F]
Other links you may find useful:
Task Scheduler from the command line? from SuperUser
What is a simple way to schedule a single event to happen at some time in the future? from Linux & Unix
How to Schedule Programs to Run Automatically in Windows 7? from Gizmo's freeware (TechSupportAlert)
Running a job from AutoSys and I am getting an error.
VBS runs an excel macro.
VBS code :
Option Explicit
Dim xlApp, xlBook
Set xlApp = CreateObject("Excel.Application")
On Error Resume Next
set xlBook = xlApp.Workbooks.Open("Z:\Confidential Restricted\Weekly_HR_Employees_Macro.xlsm",0, False)
xlApp.Run "Weekly_HR_Employees_Macro.Weekly_HR_Employees_Macro"
xlBook.Close True
xlApp.Quit
set xlBook = Nothing
Set xlApp = Nothing
Error:
Microsoft VBScript runtime error: ActiveX component can't create object: 'Excel.Application'
You are using GetObject syntax with CreateObject method. You need to use:
Set xlApp = CreateObject("Excel.Application")
Check this answer for more details.
Although the script runs on my machine, it would not run on the machine that the AutoSys job was using. I eventually found that the machine that was being used by the Autosys job does not have Microsoft Office installed.
You can use GetObject("Excel.Application"), but you need to make sure you open up an instance of excel before you use it. GetObject will get a reference to this open instance of Excel and let you use that.