Maneira de executar macros do Excel na linha de comando ou arquivo em lote?
-
20-09-2019 - |
Pergunta
Eu tenho uma macro do Excel VBA que preciso executar ao acessar o arquivo a partir de um arquivo em lote, mas nem toda vez que a abro (portanto, não usando o evento de arquivo aberto). Existe uma maneira de executar a macro a partir da linha de comando ou arquivo em lote? Não estou familiarizado com esse comando.
Assuma um ambiente Windows NT.
Solução
Você pode iniciar o Excel, abrir a pasta de trabalho e executar a macro a partir de um arquivo VBScript.
Copie o código abaixo no bloco de notas.
Atualizar o 'Myworkbook.xls' e 'MymacroParâmetros.
Salve -o com uma extensão VBS e execute -o.
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
A linha -chave que executa a macro é:
xlapp.run "mymacro"
Outras dicas
A maneira mais simples de fazer é:
1) Inicie o Excel do seu arquivo em lote para abrir a pasta de trabalho que contém sua macro:
EXCEL.EXE /e "c:\YourWorkbook.xls"
2) Ligue para sua macro da pasta de trabalho Workbook_Open
evento, como:
Private Sub Workbook_Open()
Call MyMacro1 ' Call your macro
ActiveWorkbook.Save ' Save the current workbook, bypassing the prompt
Application.Quit ' Quit Excel
End Sub
Isso agora retornará o controle ao seu arquivo em lote para fazer outro processamento.
O método mostrado abaixo permite executar a macro do Excel definida a partir do arquivo em lote, ele usa a variável de ambiente para passar o nome da macro do lote para o Excel.
Coloque este código no arquivo em lote (use seus caminhos para EXCEL.EXE
e para a pasta de trabalho):
Set MacroName=MyMacro
"C:\Program Files\Microsoft Office\Office15\EXCEL.EXE" "C:\MyWorkbook.xlsm"
Coloque este código no objeto Excel VBA ThisWorkbook:
Private Sub Workbook_Open()
Dim strMacroName As String
strMacroName = CreateObject("WScript.Shell").Environment("process").Item("MacroName")
If strMacroName <> "" Then Run strMacroName
End Sub
E coloque seu código no Módulo VBA Excel, como a seguinte:
Sub MyMacro()
MsgBox "MyMacro is running..."
End Sub
Inicie o arquivo em lote e obtenha o resultado:
Para o caso, quando você não pretende executar nenhuma macro, basta colocar um valor vazio Set MacroName=
para o lote.
Você pode escrever um VBScript para criar uma instância do Excel através do método createObject (), depois abrir a pasta de trabalho e executar a macro. Você pode ligar diretamente no VBScript ou ligar para o VBScript de um arquivo em lote.
Aqui está um recurso que acabei de tropeçar na Accross:http://www.codeguru.com/forum/showthread.php?t=376401
Eu sempre testei o número de pastas de trabalho abertas na Workbook_open (). Se for 1, a pasta de trabalho foi aberta pela linha de comando (ou o usuário fechou todas as pastas de trabalho e depois abriu esta).
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 você estiver mais confortável trabalhando dentro do Excel/VBA, use o evento aberto e teste o ambiente: tenha um arquivo de sinal, uma entrada de registro ou uma variável de ambiente que controla o que o evento aberto faz.
Você pode criar o arquivo/configuração do lado de fora e testar dentro (use GetenViromentVariable para Env-Vars) e teste com facilidade. Eu escrevi VBScript, mas as semelhanças com o VBA me causam mais angústia do que facilidade ..
mais
Pelo que entendi o problema, você deseja usar uma planilha normalmente a maioria/algumas vezes, mas a executa em lote e faça algo extra/diferente. Você pode abrir a folha da linha de comando do Excel.exe, mas não pode controlar o que ela faz, a menos que saiba onde está. O uso de uma variável de ambiente é relativamente simples e facilita o teste da planilha.
Para esclarecer, use a função abaixo para examinar o ambiente. Em um 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
No evento aberto da pasta de trabalho (como outros):
Private Sub Workbook_Open()
If GetEnvironmentVariable("InBatch") = "TRUE" Then
Debug.Print "Batch"
Else
Debug.Print "Normal"
End If
End Sub
Adicione o código ativo conforme aplicável. No arquivo em lote, use
set InBatch=TRUE
Em vez de comparar diretamente as strings (o VB não as encontrará iguais, pois GetenvironmentVariable retorna uma sequência de comprimento 255) Escreva este:
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: Eu tentei adaptar seu código com um caminho relativo e criei um arquivo em lote para executar o VBS.
O VBS começa e fecha, mas não inicia a macro ... alguma idéia de onde o problema poderia estar?
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
Eu removi o "Application.quit" porque minha macro está chamando uma forma de usuário cuidando dele.
Felicidades
EDITAR
Na verdade, eu trabalhei, caso alguém queira executar um formulário de usuário "igualmente" um aplicativo independente:
Questões que eu estava enfrentando:
1 - Eu não queria usar o evento da ASSIM_OPEN, pois o Excel está bloqueado apenas na leitura. 2 - O comando em lote é limitado que o fato de que (a meu conhecimento) não pode chamar a macro.
Eu escrevi uma macro pela primeira vez para lançar minha forma de usuário ao ocultar o aplicativo:
Sub open_form()
Application.Visible = False
frmAddClient.Show vbModeless
End Sub
Eu então criei um VBS para lançar esta macro (fazendo isso com um caminho relativo foi 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"
E finalmente fiz um arquivo em lote para executar o VBS ...
@echo off
pushd %~dp0
cscript Add_Client.vbs
Observe que eu também incluí o "Volto para Visível" no meu 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 qualquer forma, obrigado pela sua ajuda, e espero que isso ajude se alguém precisar
Você pode verificar se o Excel já está aberto. Não há necessidade de criar outro não é
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
Eu sou parcial para C#. Eu executei o seguinte usando o Linqpad. Mas poderia facilmente ser compilado com o CSC e executado pela linha de comando chamado.
Não se esqueça de adicionar pacotes do Excel ao espaço para nome.
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;
}
}