Forma de ejecutar las macros de Excel desde la línea de comandos o un archivo por lotes?
-
20-09-2019 - |
Pregunta
Tengo una macro VBA de Excel que tengo que correr al acceder al archivo desde un archivo por lotes, pero no cada vez que lo abro (por lo tanto no utiliza el archivo abierto de eventos).Es allí una manera de ejecutar la macro desde la línea de comandos o un archivo por lotes?Yo no estoy familiarizado con dicho comando.
Asumir un entorno de Windows NT.
Solución
Puede iniciar Excel, abra el libro y ejecutar la macro desde un archivo VBScript.
Copia el código siguiente en el Bloc de notas.
Actualizar el ' MyWorkbook.xls ' y ' MiMacro ' parámetros.
Guardar con una extensión VBS y ejecutarlo.
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 línea clave que se ejecuta la macro es:
xlApp.Run "MiMacro"
Otros consejos
La forma más sencilla de hacerlo es:
1) Iniciar Excel de su archivo por lotes para abrir el libro que contiene la macro:
EXCEL.EXE /e "c:\YourWorkbook.xls"
2) Llame a su macro de evento Workbook_Open
del libro de trabajo, como por ejemplo:
Private Sub Workbook_Open()
Call MyMacro1 ' Call your macro
ActiveWorkbook.Save ' Save the current workbook, bypassing the prompt
Application.Quit ' Quit Excel
End Sub
Esto ahora devolverá el control a su archivo por lotes para hacer otro tipo de elaboración.
El método se muestra a continuación permite ejecutar macro Excel definido de archivo por lotes, que utiliza variable de entorno para pasar nombre de macro de lote a Excel.
Pon este código al archivo por lotes (utilizar sus caminos a EXCEL.EXE
y al libro):
Set MacroName=MyMacro
"C:\Program Files\Microsoft Office\Office15\EXCEL.EXE" "C:\MyWorkbook.xlsm"
Pon este código a Excel VBA ThisWorkbook del objeto:
Private Sub Workbook_Open()
Dim strMacroName As String
strMacroName = CreateObject("WScript.Shell").Environment("process").Item("MacroName")
If strMacroName <> "" Then Run strMacroName
End Sub
Y poner su código a Excel VBA módulo, como la siguiente:
Sub MyMacro()
MsgBox "MyMacro is running..."
End Sub
Iniciar el archivo por lotes y obtener el resultado:
En el caso en el que no tiene intención de ejecutar cualquier macro sólo hay que poner el valor Set MacroName=
vacío al lote.
se podría escribir un VBScript para crear una instancia de Excel mediante el método CreateObject (), a continuación, abrir el libro y ejecutar la macro. Se podría llamar a la VBScript directamente, o llame a la VBScript desde un archivo por lotes.
Aquí es un recurso Me tropecé al otro lado: http://www.codeguru.com/forum/showthread.php?t= 376401
Siempre he probado el número de libros abiertos en Workbook_Open (). Si es 1, entonces se abrió el libro por la línea de comandos (o el usuario cierra todos los libros, entonces abierto éste).
If Workbooks.Count = 1 Then
' execute the macro or call another procedure - I always do the latter
PublishReport
ThisWorkbook.Save
Application.Quit
End If
Si usted es más cómodo trabajando dentro de Excel / VBA, utilice el evento abierto y probar el entorno:. O bien tienen un archivo de señal, una entrada de registro o una variable de entorno que controla lo que hace el evento abierto
Puede crear el archivo / ajuste exterior y el interior de la prueba (GetEnviromentVariable utilizar para env-VARs) y la prueba con facilidad. He escrito VBScript, pero las similitudes con VBA me causan más angustia que la facilidad ..
[más]
A mi entender el problema, desea utilizar una hoja de cálculo normalmente la mayor parte / parte del tiempo sin embargo, hacer que se ejecute en el lote y hacer algo extra / diferente. Puede abrir la hoja desde la línea de comandos excel.exe pero no se puede controlar lo que hace a menos que sepa dónde está. El uso de una variable de entorno es relativamente simple y hace que las pruebas de la hoja de cálculo fácil.
Para aclarar, utilice la función siguiente para examinar el medio ambiente. En un declarar módulo:
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
En el evento abierto libro de trabajo (como otros):
Private Sub Workbook_Open()
If GetEnvironmentVariable("InBatch") = "TRUE" Then
Debug.Print "Batch"
Else
Debug.Print "Normal"
End If
End Sub
Añadir en el código activo según sea el caso. En el archivo por lotes, utilice
set InBatch=TRUE
En lugar de comparar directamente las cuerdas (VB no encontrarlos igual desde GetEnvironmentVariable devuelve una cadena de longitud 255) escribir lo siguiente:
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
@ Robert:He tratado de adaptar su código con la ruta de acceso relativa, y crea un archivo por lotes para ejecutar el VBS.
El VBS que se inicia y se cierra pero no se inicia la macro...Alguna idea de donde podría ser el 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
He quitado de la Aplicación".Dejar de fumar" porque mi macro es llamar a un formulario de usuario de tomar el cuidado de él.
Saludos
EDITAR
En realidad he trabajado a cabo, en caso de que alguien quiere ejecutar un formulario de usuario "por igual" una aplicación independiente:
Problemas en los que estaba enfrentando:
1 - yo no quería utilizar el Evento Workbook_Open como el excel está bloqueado en sólo lectura.2 - El comando de proceso por lotes está limitado que el hecho de que (a mi conocimiento) no puede llamar a la macro.
Por primera vez me escribió una macro para el lanzamiento de mi formulario de usuario y ocultar la aplicación:
Sub open_form()
Application.Visible = False
frmAddClient.Show vbModeless
End Sub
Entonces creé un vbs para el lanzamiento de este macro (hacerlo con una ruta de acceso relativa ha sido difícil):
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"
Y finalmente me hice un archivo por lotes para ejecutar el VBS...
@echo off
pushd %~dp0
cscript Add_Client.vbs
Tenga en cuenta que también he incluido el "volver a Establecer visible" en mi 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
De todos modos, gracias por tu ayuda, y espero que esto ayude si alguien lo necesita
Puede comprobar si Excel ya está abierto. No hay necesidad de crear otra 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
Soy parcial a C #. Me encontré con la siguiente usando LINQPad. Pero podría fácilmente ser compilado con CSC y corrió a través de la llamada desde la línea de comandos.
No se olvide de añadir paquetes de Excel para espacio de nombres.
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;
}
}