una - ¿Forma de ejecutar macros de Excel desde la línea de comandos o el archivo por lotes?
ejecutar macro excel vb (10)
Tengo una macro de Excel VBA que necesito ejecutar cuando accedo al archivo desde un archivo de proceso por lotes, pero no cada vez que lo abro (de ahí que no utilice el evento de archivo abierto). ¿Hay alguna forma de ejecutar la macro desde la línea de comando o el archivo por lotes? No estoy familiarizado con tal comando.
Supongamos un entorno Windows NT.
@ Robert: He tratado de adaptar tu código con una ruta relativa, y he creado un archivo por lotes para ejecutar el VBS.
La VBS se inicia y se cierra, pero no ejecuta la macro ... ¿Alguna idea de dónde podría estar 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
Eliminé el "Application.Quit" porque mi macro está llamando a una forma de usuario que se encarga de ello.
Aclamaciones
EDITAR
De hecho, lo he resuelto, por si alguien quiere ejecutar una forma de usuario "parecida" a una aplicación independiente:
Problemas que enfrentaba:
1 - No quería utilizar el evento Workbook_Open ya que Excel está bloqueado en solo lectura. 2 - El comando por lotes está limitado por el hecho de que (que yo sepa) no puede llamar a la macro.
Primero escribí una macro para iniciar mi formulario de usuario mientras ocultaba la aplicación:
Sub open_form()
Application.Visible = False
frmAddClient.Show vbModeless
End Sub
Luego creé un vbs para iniciar esta macro (hacerlo con una ruta relativa ha sido complicado):
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 hice un archivo por lotes para ejecutar el VBS ...
@echo off
pushd %~dp0
cscript Add_Client.vbs
Tenga en cuenta que también Userform_QueryClose
el "Volver a establecer como 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 su ayuda, y espero que esto ayude si alguien lo necesita
El método que se muestra a continuación permite ejecutar una macro de Excel definida desde un archivo por lotes, usa una variable de entorno para pasar el nombre de la macro de un lote a Excel.
Coloque este código en el archivo por lotes (use sus rutas a EXCEL.EXE
y al libro de trabajo):
Set MacroName=MyMacro
"C:/Program Files/Microsoft Office/Office15/EXCEL.EXE" "C:/MyWorkbook.xlsm"
Coloque este código en 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
Y coloque su código en el módulo Excel VBA, como se muestra a continuación:
Sub MyMacro()
MsgBox "MyMacro is running..."
End Sub
Inicie el archivo por lotes y obtenga el resultado:
Para el caso en que no Set MacroName=
ejecutar ninguna macro simplemente coloque el valor vacío Set MacroName=
en el lote.
En lugar de comparar directamente las cadenas (VB no las encontrará iguales ya que GetEnvironmentVariable devuelve una cadena de longitud 255) escriba esto:
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
La forma más sencilla de hacerlo es:
1) Inicie Excel desde su archivo de proceso por lotes para abrir el libro que contiene su macro:
EXCEL.EXE /e "c:/YourWorkbook.xls"
2) Llame a su macro desde el evento Workbook_Open
del libro, 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 procesamiento.
Puede iniciar Excel, abrir el libro de trabajo y ejecutar la macro desde un archivo VBScript.
Copie el siguiente código en el Bloc de notas.
Actualice los parámetros '' MyWorkbook.xls '' y '' MyMacro ''.
Guárdelo con una extensión vbs y ejecútelo.
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 ejecuta la macro es:
xlApp.Run "MyMacro"
Puede verificar si Excel ya está abierto. No hay necesidad de crear otra esencia
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
Si se siente más cómodo trabajando en Excel / VBA, use el evento abierto y pruebe el entorno: ya sea que tenga un archivo de señal, una entrada de registro o una variable de entorno que controle lo que hace el evento abierto.
Puedes crear el archivo / configuración afuera y probar el interior (usa GetEnviromentVariable para env-vars) y prueba fácilmente. He escrito VBScript pero las similitudes con VBA me causan más angustia que facilidad.
[Más]
Según entiendo el problema, desea utilizar una hoja de cálculo normalmente la mayor parte del tiempo pero ejecutarla por lotes y hacer algo extra / diferente. Puede abrir la hoja desde la línea de comandos excel.exe pero no puede controlar lo que hace a menos que sepa dónde está. El uso de una variable de entorno es relativamente simple y facilita la prueba de la hoja de cálculo.
Para aclarar, use la función a continuación para examinar el entorno. En un módulo declarar:
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
Agregue el código activo según corresponda. En el archivo por lotes, use
set InBatch=TRUE
Siempre he probado la cantidad de libros abiertos en Workbook_Open (). Si es 1, entonces el libro de trabajo fue abierto por la línea de comando (o el usuario cerró todos los libros de trabajo, luego abrió este).
If Workbooks.Count = 1 Then
'' execute the macro or call another procedure - I always do the latter
PublishReport
ThisWorkbook.Save
Application.Quit
End If
Soy parcial a C #. Ejecuté lo siguiente usando linqpad. Pero podría compilarse fácilmente con csc y ejecutar el llamado desde la línea de comando.
No te olvides de agregar paquetes de Excel al 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;
}
}
podría escribir un vbscript para crear una instancia de excel mediante el método createobject (), luego abrir el libro de trabajo y ejecutar la macro. Puede llamar a vbscript directamente o llamar a vbscript desde un archivo por lotes.
Aquí hay un recurso que acabo de tropezar: http://www.codeguru.com/forum/showthread.php?t=376401