exiting/restarting a word macro that controls excel - excel

I'm running a word macro that
initializes Excel
creates a temporary workbook in excel
when exiting the word userform, terminates excel
However, it seems there is some residual Excel instances/workbook that is not fully closed because when I start the word macro again, I get error: 462, remote server machine ...
initialize userform in a word document:
private sub commandbutton1_click()
dim exc as excel.application
set exc as new excel.application
dim wb as excel.workbook
set wb = exc.workbook.saveas filename:="wordexc" 'creates temp workbook
userform1.show
end sub
run excel processing via a userform1 commandbutton:
private sub commandbutton2_click()
excel.workbook("wordexc").close 'closes temp workbook
dim wb as excel.workbook
set wb = excel.workbook.saveas filename:="wordexc" 'this wb is for actual use
'i do not delete this wb after running cuz it has stored data that will be used
'if user cliks commandbutton2 again, it will be deleted and new wbook with new data
'is created
'processing code
end sub
private sub queryclose (etc...)
'Close Excel
Dim sKillExcel As String
sKillExcel = "TASKKILL /F /IM Excel.exe"
Shell sKillExcel, vbHide
end sub
btw i think the problem is the last part:
Dim sKillExcel As String
sKillExcel = "TASKKILL /F /IM Excel.exe"
Shell sKillExcel, vbHide
Cuz if I stop the macro and terminate EXCEL in task manager, it doesn't give me this problem if I run the macro again...
i
I also tried other methods, like calling a excel workbook i saved in a directory instead of a temporary one via createobject("excel.application") in one sub, exc.quit, but I have to use that termination code above cuz otherwise EXCEL still shows in task manager.

Besides not declaring your objects correctly, you are not (if I may say so) flushing the toilet correctly.
See this example (UNTESTED)
I am using Latebinding instead of Early Binding so that this code is compatible with any version of Excel
'~~> Define your Excel objects so that they are available
'~~> in other userform sub procedures as well.
Dim oXLApp As Object, oXLwb As Object
Private Sub CommandButton1_Click()
Set oXLApp = CreateObject("Excel.Application")
'~~> Show Excel
oXLApp.Visible = True
'~~> Add a new workbook
Set oXLwb = oXLApp.Workbooks.Add
'
'~~> Do some stuff
'
'~~> Save the file
oXLwb.SaveAs "C:\wordexc.xlsx", FileFormat:=51
oXLwb.Close SaveChanges:=False
End Sub
'~~> Close and Quit Excel (Flush Toilet)
Private Sub CommandButton2_Click()
oXLApp.Quit
Set oXLwb = Nothing
Set oXLApp = Nothing
End Sub

Why not do something like this? Basically, you define your excel object globally, and then you can call it's "Quit" method later.
Private objExcel As Excel.Application
Private Sub CommandButton1_Click()
Set objExcel = New Excel.Application
objExcel.Visible = True
End Sub
Private Sub CommandButton2_Click()
objExcel.Quit
End Sub

Related

ExcelAnt add-ins in Workbook_Open won't run if the workbook was opened by another workbook's macro

Currently making a quick macro that opens a bunch of other workbooks in new instances:
Sub open_files()
Dim Path As String
Dim Fname As String
Dim xlApp As Object
MyFiles = Dir("C:\my_folder\*xls*")
Do While MyFiles <> ""
Set xlApp = CreateObject("Excel.Application")
xlApp.Visible = True
xlApp.Workbooks.Open ("C:\my_folder\" & MyFiles)
MyFiles = Dir
Loop
End Sub
This works fine on sheets that don't have any ExcelAnt functions in Workbook_Open, but for those that do, I get a popup that says: "Run-time error '1004': cannot run the macro 'Connect'. The macro may not be available in this workbook or all macros may be disabled. "
I've tried forcing in the add-in before running the "connect" part of the code but to no avail.
Public Sub Workbook_Open()
Dim TestWkbk As Workbook
Set TestWkbk = Nothing
On Error Resume Next
Set TestWkbk = Workbooks("ExcelAnt-AddIn64.xll")
On Error GoTo 0
If TestWkbk Is Nothing Then
Set TestWkbk = Workbooks.Open("C:\ExcelAnt\ExcelAnt-AddIn64.xll")
End If
Dim hostenv As String
hostenv = Left(Environ("computername"), 3)
Application.Run "Connect", "prd"
End Sub
To clarify, the sheet if opened manually works fine.
Any help would be appreciated. Thanks in advance.
Use RegisterXLL with the new instance of Excel (xlApp).
xlApp.RegisterXLL "C:\ExcelAnt\ExcelAnt-AddIn64.xll"

How to fix closing Excel from inside Access

I want to close an Excel workbook from inside Access using VBA code. The following code opens the workbook and runs a VBA module in the workbook correctly. Closing the workbook prompts with the standard Save dialogue which I want to avoid.
I tried modifying the statement .Workbooks.Close to .Workbooks.Close SaveChanges:=True but that actually crashes the code.
Public Function Open_Share_Price_Excel()
' Change Cursor to Hourglass
Screen.MousePointer = 11
Dim Expath, ModName As String
Dim XLApp As Object
Set XLApp = CreateObject("Excel.Application")
'
'Define where the Excel Spreadsheet is and the module to run
'
Expath = "C:\Users\peter\Documents\Financial Affairs\Shares\Share Price Bing.xlsm"
ModName = "Combined_Module"
With XLApp
.Application.Visible = True
.Application.DisplayAlerts = False
.UserControl = True
.Workbooks.Open Expath
.Run ModName
.Workbooks.Close
End With
XLApp.Quit
Set XLApp = Nothing
'Change Cursor back and display finished message
Screen.MousePointer = 0
MsgBox ("Price Update Finished - OK to Continue")
End Function
I tried modifying the statement .Workbooks.Close to .Workbooks.Close SaveChanges:=True but that actually crashes the code.
Any suggestions welcome.
Secondly, I would like to ensure that I close all the excel workbooks as I understand that the workbook Personal.xlsx may also be open. When I manually close the Excel spreadsheet it closes, but then EXcel immediately re-opens with a blank workbook.
Help this newbie please
What you need to do is to set the opened workbook to a variable Set OpenedWb = .Workbooks.Open(Expath) so you can access exactly that workbook to close it OpenedWb.Close SaveChanges:=True.
.Workbooks.Close does not work because Workbooks repersents all workbooks and not a specific one (but you must close each workbook on its own).
Please note that Dim Expath, ModName As String only declares ModName As String but Expath As Variant. In VBA you need to specify a type for every variable, otherwise it is Variant by default. So you must use: Dim Expath As String, ModName As String to make them both strings.
Your Function does not return anything. Therfore it should be a procedure Sub instead of a function.
You would end up using something like below:
Public Sub Open_Share_Price_Excel()
' Change Cursor to Hourglass
Screen.MousePointer = 11
'
'Define where the Excel Spreadsheet is and the module to run
'
Dim Expath As String
Expath = "C:\Users\peter\Documents\Financial Affairs\Shares\Share Price Bing.xlsm"
Dim ModName As String
ModName = "Combined_Module"
Dim XLApp As Object
Set XLApp = CreateObject("Excel.Application")
With XLApp
.Application.Visible = True
.Application.DisplayAlerts = False
.UserControl = True
Dim OpenedWb As Object
Set OpenedWb = .Workbooks.Open(Expath)
.Run ModName
OpenedWb.Close SaveChanges:=True
End With
XLApp.Quit
Set XLApp = Nothing
'Change Cursor back and display finished message
Screen.MousePointer = 0
MsgBox ("Price Update Finished - OK to Continue")
End Sub

Excel template's VBA code not working after I insert it into a new workbook

I create an Excel template with fixed format and VBA stored in.
Whenever I insert the Excel template into a new workbook, the VBA code will not follow and apply. Only the format follows.
Does anyone know why?
This is the code stored in Template.xltm. Under ThisWorkbook
Sub Auto_Open()
Workbooks.Open Filename:="C:\Users\ASUS User\Desktop\MP\source.xlsm"
ThisWorkbook.Activate
End Sub
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Columns(2).AutoFit
Rows().AutoFit
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim wBook As Workbook
On Error Resume Next
Set wBook = Workbooks("source.xlsm")
If wBook Is Nothing Then
'The Workbook Is Not open'
' Nothing to do as workbook is not open
Set wBook = Nothing
On Error GoTo 0
Else 'Workbook is open
' Close the workbook and save any changes
Workbooks("source.xlsm").Close SaveChanges:=True
Set wBook = Nothing
On Error GoTo 0
End If
End Sub
Does VBA code in excel macro enable template follows the template?
You need to make sure your workbook is saved as a Macro-enabled template, with the file extension .xltm instead of the standard .xltx template extension.

excel 2007 Workbook_open not working

I am trying to clear Print Area And Autofilter when excel opens:
Am total novice in Excel vba so Assmebled the followingcode from googling around
This code I have put in ThisWorkbook of Personal.xlsb in the XLstart folder and ofcourse the macro security has been set to enable all macros
Option Explicit
Public WithEvents xlApp As Excel.Application
Private Sub Workbook_Open()
Set xlApp = Application
End Sub
Private Sub Workbook_Close()
Set xlApp = Nothing
End Sub
Private Sub xlApp_WorkbookOpen(ByVal Wb As Workbook)
Application.EnableEvents = False
Call ClrPrntArea
Application.EnableEvents = True
End Sub
Here is the ClrPrntArea
Sub ClrPrntArea()
Dim ws As Object
For i = 1 To ActiveWorkbook.Worksheets.count
With Worksheets(i)
.PageSetup.PrintArea = ""
.PageSetup.FitToPagesWide = 1
End With
Next
End Sub
I will also be putting another macro call to module in personal xlsb for resetting the autofiter once above starts working..Any inputs will be really helpfull
in PERSONAL.xlsb, module ThisWorkbook, try the below; it's nearly the same code as in your request, with some modif's:
application object declared Private
event routine uses the local WB object variable handed over as parameter, instead of the ActiveWorkbook object
replaced For ... Next by For Each ... Next and working with local object variables
trap processing of PERSONAL.xlsb itself
Once you're happy remove all the MsgBox statements (and the Else), they are just to show what is happening and when.
Private WithEvents Excel_App As Excel.Application
' runs when Excel_App encounters a Workbook_Open() event
Private Sub Excel_App_WorkbookOpen(ByVal WB As Workbook)
Dim WS As Worksheet
If WB.Name <> "PERSONAL.xlsb" Then
MsgBox "PERSONAL.xlsb: Excel_App_WorkbookOpen(): " & WB.Name
For Each WS In WB.Worksheets
WS.PageSetup.PrintArea = ""
WS.PageSetup.FitToPagesWide = 1
If WS.FilterMode Then
WS.ShowAllData
End If
Next
Else
MsgBox "PERSONAL.xlsb: Excel_App_WorkbookOpen(): myself"
End If
End Sub
' runs when PERSONAL.xlsb is opened
' assign current Excel application to object variable Excel_App
Private Sub Workbook_Open()
MsgBox "PERSONAL.xlsb: Workbook_Open()"
Set Excel_App = Application
End Sub
Note:
When the event handler doesn't start when you double-click an Excel file (e.g. on your desktop), close all Excel applications and inspect the task manager for additional orphaned Excel processes which need to be killed. It happened to me while playing around with this code

Way to run Excel macros from command line or batch file?

I have an Excel VBA macro which I need to run when accessing the file from a batch file, but not every time I open it (hence not using the open file event). Is there a way to run the macro from the command line or batch file? I'm not familiar with such a command.
Assume a Windows NT environment.
You can launch Excel, open the workbook and run the macro from a VBScript file.
Copy the code below into Notepad.
Update the 'MyWorkbook.xls' and 'MyMacro' parameters.
Save it with a vbs extension and run it.
Option Explicit
On Error Resume Next
ExcelMacroExample
Sub ExcelMacroExample()
Dim xlApp
Dim xlBook
Set xlApp = CreateObject("Excel.Application")
Set xlBook = xlApp.Workbooks.Open("C:\MyWorkbook.xls", 0, True)
xlApp.Run "MyMacro"
xlApp.Quit
Set xlBook = Nothing
Set xlApp = Nothing
End Sub
The key line that runs the macro is:
xlApp.Run "MyMacro"
The simplest way to do it is to:
1) Start Excel from your batch file to open the workbook containing your macro:
EXCEL.EXE /e "c:\YourWorkbook.xls"
2) Call your macro from the workbook's Workbook_Open event, such as:
Private Sub Workbook_Open()
Call MyMacro1 ' Call your macro
ActiveWorkbook.Save ' Save the current workbook, bypassing the prompt
Application.Quit ' Quit Excel
End Sub
This will now return the control to your batch file to do other processing.
The method shown below allows to run defined Excel macro from batch file, it uses environment variable to pass macro name from batch to Excel.
Put this code to the batch file (use your paths to EXCEL.EXE and to the workbook):
Set MacroName=MyMacro
"C:\Program Files\Microsoft Office\Office15\EXCEL.EXE" "C:\MyWorkbook.xlsm"
Put this code to Excel VBA ThisWorkBook Object:
Private Sub Workbook_Open()
Dim strMacroName As String
strMacroName = CreateObject("WScript.Shell").Environment("process").Item("MacroName")
If strMacroName <> "" Then Run strMacroName
End Sub
And put your code to Excel VBA Module, like as follows:
Sub MyMacro()
MsgBox "MyMacro is running..."
End Sub
Launch the batch file and get the result:
For the case when you don't intend to run any macro just put empty value Set MacroName= to the batch.
you could write a vbscript to create an instance of excel via the createobject() method, then open the workbook and run the macro. You could either call the vbscript directly, or call the vbscript from a batch file.
Here is a resource I just stumbled accross:
http://www.codeguru.com/forum/showthread.php?t=376401
If you're more comfortable working inside Excel/VBA, use the open event and test the environment: either have a signal file, a registry entry or an environment variable that controls what the open event does.
You can create the file/setting outside and test inside (use GetEnviromentVariable for env-vars) and test easily. I've written VBScript but the similarities to VBA cause me more angst than ease..
[more]
As I understand the problem, you want to use a spreadsheet normally most/some of the time yet have it run in batch and do something extra/different. You can open the sheet from the excel.exe command line but you can't control what it does unless it knows where it is. Using an environment variable is relatively simple and makes testing the spreadsheet easy.
To clarify, use the function below to examine the environment. In a module declare:
Private Declare Function GetEnvVar Lib "kernel32" Alias "GetEnvironmentVariableA" _
(ByVal lpName As String, ByVal lpBuffer As String, ByVal nSize As Long) As Long
Function GetEnvironmentVariable(var As String) As String
Dim numChars As Long
GetEnvironmentVariable = String(255, " ")
numChars = GetEnvVar(var, GetEnvironmentVariable, 255)
End Function
In the Workbook open event (as others):
Private Sub Workbook_Open()
If GetEnvironmentVariable("InBatch") = "TRUE" Then
Debug.Print "Batch"
Else
Debug.Print "Normal"
End If
End Sub
Add in active code as applicable. In the batch file, use
set InBatch=TRUE
Instead of directly comparing the strings (VB won't find them equal since GetEnvironmentVariable returns a string of length 255) write this:
Private Sub Workbook_Open()
If InStr(1, GetEnvironmentVariable("InBatch"), "TRUE", vbTextCompare) Then
Debug.Print "Batch"
Call Macro
Else
Debug.Print "Normal"
End If
End Sub
I have always tested the number of open workbooks in Workbook_Open(). If it is 1, then the workbook was opened by the command line (or the user closed all the workbooks, then opened this one).
If Workbooks.Count = 1 Then
' execute the macro or call another procedure - I always do the latter
PublishReport
ThisWorkbook.Save
Application.Quit
End If
# Robert: I have tried to adapt your code with a relative path, and created a batch file to run the VBS.
The VBS starts and closes but doesn't launch the macro... Any idea of where the issue could be?
Option Explicit
On Error Resume Next
ExcelMacroExample
Sub ExcelMacroExample()
Dim xlApp
Dim xlBook
Set xlApp = CreateObject("Excel.Application")
Set objFSO = CreateObject("Scripting.FileSystemObject")
strFilePath = objFSO.GetAbsolutePathName(".")
Set xlBook = xlApp.Workbooks.Open(strFilePath, "Excels\CLIENTES.xlsb") , 0, True)
xlApp.Run "open_form"
Set xlBook = Nothing
Set xlApp = Nothing
End Sub
I removed the "Application.Quit" because my macro is calling a userform taking care of it.
Cheers
EDIT
I have actually worked it out, just in case someone wants to run a userform "alike" a stand alone application:
Issues I was facing:
1 - I did not want to use the Workbook_Open Event as the excel is locked in read only.
2 - The batch command is limited that the fact that (to my knowledge) it cannot call the macro.
I first wrote a macro to launch my userform while hiding the application:
Sub open_form()
Application.Visible = False
frmAddClient.Show vbModeless
End Sub
I then created a vbs to launch this macro (doing it with a relative path has been tricky):
dim fso
dim curDir
dim WinScriptHost
set fso = CreateObject("Scripting.FileSystemObject")
curDir = fso.GetAbsolutePathName(".")
set fso = nothing
Set xlObj = CreateObject("Excel.application")
xlObj.Workbooks.Open curDir & "\Excels\CLIENTES.xlsb"
xlObj.Run "open_form"
And I finally did a batch file to execute the VBS...
#echo off
pushd %~dp0
cscript Add_Client.vbs
Note that I have also included the "Set back to visible" in my Userform_QueryClose:
Private Sub cmdClose_Click()
Unload Me
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
ThisWorkbook.Close SaveChanges:=True
Application.Visible = True
Application.Quit
End Sub
Anyway, thanks for your help, and I hope this will help if someone needs it
I'm partial to C#. I ran the following using linqpad. But it could just as easily be compiled with csc and ran through the called from the command line.
Don't forget to add excel packages to namespace.
void Main()
{
var oExcelApp = (Microsoft.Office.Interop.Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
try{
var WB = oExcelApp.ActiveWorkbook;
var WS = (Worksheet)WB.ActiveSheet;
((string)((Range)WS.Cells[1,1]).Value).Dump("Cell Value"); //cel A1 val
oExcelApp.Run("test_macro_name").Dump("macro");
}
finally{
if(oExcelApp != null)
System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcelApp);
oExcelApp = null;
}
}
I generally store my macros in xlam add-ins separately from my workbooks so I wanted to open a workbook and then run a macro stored separately.
Since this required a VBS Script, I wanted to make it "portable" so I could use it by passing arguments. Here is the final script, which takes 3 arguments.
Full Path to Workbook
Macro Name
[OPTIONAL] Path to separate workbook with Macro
I tested it like so:
"C:\Temp\runmacro.vbs" "C:\Temp\Book1.xlam" "Hello"
"C:\Temp\runmacro.vbs" "C:\Temp\Book1.xlsx" "Hello" "%AppData%\Microsoft\Excel\XLSTART\Book1.xlam"
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
You can check if Excel is already open. There is no need to create another isntance
If CheckAppOpen("excel.application") Then
'MsgBox "App Loaded"
Set xlApp = GetObject(, "excel.Application")
Else
' MsgBox "App Not Loaded"
Set wrdApp = CreateObject(,"excel.Application")
End If

Resources