Modo per eseguire macro di Excel dalla riga di comando o da un file batch?
-
20-09-2019 - |
Domanda
Ho una macro VBA di Excel che devo eseguire quando accedo al file da un file batch, ma non ogni volta che lo apro (quindi non utilizzo l'evento file aperto).C'è un modo per eseguire la macro dalla riga di comando o dal file batch?Non ho familiarità con un comando del genere.
Supponiamo un ambiente Windows NT.
Soluzione
È possibile avviare Excel, aprire la cartella di lavoro ed eseguire la macro da un file VBScript.
Copia il codice qui sotto nel blocco note.
Aggiornare il ' MyWorkbook.xls ' e ' MyMacro ' parametri.
Salva con estensione VBS ed eseguirlo.
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
La linea di chiave che esegue la macro è:
xlApp.Run "MyMacro"
Altri suggerimenti
Il modo più semplice per farlo è quello di:
1) Avviare Excel dal file batch per aprire la cartella di lavoro che contiene la macro:
EXCEL.EXE /e "c:\YourWorkbook.xls"
2) Chiamare la macro dall'evento Workbook_Open
della cartella di lavoro, come ad esempio:
Private Sub Workbook_Open()
Call MyMacro1 ' Call your macro
ActiveWorkbook.Save ' Save the current workbook, bypassing the prompt
Application.Quit ' Quit Excel
End Sub
Questa sarà ora tornare il controllo al file batch per fare altre lavorazioni.
Il metodo illustrato di seguito consente di eseguire macro di Excel definito da file batch, utilizza variabile d'ambiente per passare nome della macro da lotto a Excel.
Inserire il codice per il file batch (utilizzare i percorsi per EXCEL.EXE
e alla cartella di lavoro):
Set MacroName=MyMacro
"C:\Program Files\Microsoft Office\Office15\EXCEL.EXE" "C:\MyWorkbook.xlsm"
Inserire il codice in Excel VBA ThisWorkBook Oggetto:
Private Sub Workbook_Open()
Dim strMacroName As String
strMacroName = CreateObject("WScript.Shell").Environment("process").Item("MacroName")
If strMacroName <> "" Then Run strMacroName
End Sub
E mettere il codice per modulo VBA di Excel, come nel seguente modo:
Sub MyMacro()
MsgBox "MyMacro is running..."
End Sub
Lanciare il file batch e ottenere il risultato:
Per il caso in cui non si intende eseguire qualsiasi macro appena messo valore Set MacroName=
vuoto al lotto.
si potrebbe scrivere un VBScript per creare un'istanza di Excel tramite il metodo CreateObject (), quindi aprire la cartella di lavoro ed eseguire la macro. Si potrebbe o chiamare il VBScript direttamente, oppure chiamare il VBScript da un file batch.
Ecco una risorsa Ho appena imbattuto dall'altra parte: http://www.codeguru.com/forum/showthread.php?t= 376401
Ho sempre provato il numero di cartelle di lavoro aperte in Workbook_Open (). Se è 1, allora la cartella di lavoro è stata aperta dalla linea di comando (o l'utente ha chiuso tutte le cartelle di lavoro, quindi aperto questo uno).
If Workbooks.Count = 1 Then
' execute the macro or call another procedure - I always do the latter
PublishReport
ThisWorkbook.Save
Application.Quit
End If
Se sei più comodo lavorare all'interno di Excel / VBA, utilizzare l'evento aperto e testare l'ambiente:. O disporre di un file di segnale, una voce di registro o di una variabile d'ambiente che controlla ciò che l'evento aperto fa
È possibile creare il file / impostazione esterna e prova all'interno (utilizzare GetEnviromentVariable per ENV-Vars) e il test facilmente. Ho scritto VBScript ma le somiglianze con VBA mi causa più angoscia di facilità ..
[più]
Per quanto ho capito il problema, che si desidera utilizzare un foglio di calcolo normalmente la maggior parte / alcuni del tempo ma ce l'ha eseguito in batch e fare qualcosa in più / di diverso. È possibile aprire il foglio dalla riga di comando excel.exe, ma non si può controllare ciò che fa a meno che non sa dove si trova. Utilizzando una variabile ambiente è relativamente semplice e rende testare il foglio facile.
Per chiarire, utilizzare la funzione qui sotto per esaminare l'ambiente. In una dichiarazione del modulo:
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 caso Apri cartella di lavoro (come gli altri):
Private Sub Workbook_Open()
If GetEnvironmentVariable("InBatch") = "TRUE" Then
Debug.Print "Batch"
Else
Debug.Print "Normal"
End If
End Sub
Aggiungi in codice attivo in quanto applicabili. Nel file batch, utilizzare
set InBatch=TRUE
Invece di confrontare direttamente le stringhe (VB non li troverà uguale dal GetEnvironmentVariable restituisce una stringa di lunghezza 255) scrivere questo:
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
@ Roberto:Ho provato ad adattare il tuo codice con un percorso relativo e ho creato un file batch per eseguire VBS.
Il VBS si avvia e si chiude ma non lancia la macro...Qualche idea su dove potrebbe essere il problema?
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
Ho rimosso "Application.Quit" perché la mia macro chiama un modulo utente occupandosi di esso.
Saluti
MODIFICARE
In realtà l'ho risolto, nel caso in cui qualcuno voglia eseguire un modulo utente "allo stesso modo" come un'applicazione autonoma:
Problemi che stavo affrontando:
1 - Non volevo utilizzare l'evento Workbook_Open poiché Excel è bloccato in sola lettura.2 - Il comando batch è limitato dal fatto che (per quanto ne so) non può chiamare la macro.
Per prima cosa ho scritto una macro per avviare il mio modulo utente nascondendo l'applicazione:
Sub open_form()
Application.Visible = False
frmAddClient.Show vbModeless
End Sub
Ho quindi creato un vbs per avviare questa macro (farlo con un percorso relativo è stato complicato):
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"
E alla fine ho creato un file batch per eseguire VBS...
@echo off
pushd %~dp0
cscript Add_Client.vbs
Tieni presente che ho incluso anche la voce "Ripristina visibile" nel mio file 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
Comunque grazie per il tuo aiuto e spero che questo possa essere d'aiuto se qualcuno ne ha bisogno
È possibile verificare se Excel è già aperto. Non c'è bisogno di creare un altro 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
Io ho un debole per C #. Ho eseguito il seguente utilizzando LINQPad. Ma potrebbe altrettanto facilmente essere compilato con CSC e corse attraverso la chiamata da linea di comando.
Non dimenticate di aggiungere pacchetti excel al 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;
}
}