从命令行或批处理文件运行Excel宏的方法?


77

我有一个Excel VBA宏,从批处理文件访问文件时需要运行它,但不是每次我都打开它(因此不使用打开文件事件)。有没有办法从命令行或批处理文件运行宏?我对这样的命令不熟悉。

假定为Windows NT环境。


1
是否可以将vbscript / jscript与Windows脚本托管一起使用?
madaboutcode

Answers:


83

您可以启动Excel,打开工作簿并从VBScript文件运行宏。

将下面的代码复制到记事本中。

更新“ MyWorkbook.xls ”和“ MyMacro ”参数。

使用vbs扩展名保存并运行它。

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 

运行宏的关键是:

xlApp.Run“ MyMacro”


10
这就是我想要的!有用。我应该添加一些必要的更改以使其正常工作:1.它是“ xlApp.Run”。2.退出之前,应使用xlApp.SaveAs,否则将不保存宏所做的任何修改。(可以使用xlApp.DisplayAlerts = False来避免出现相关的弹出窗口)。3.退出之前,应调用xlApp.ActiveWorkbook.Close或电子表格保持打开状态(尽管处于隐藏状态),这将禁用进一步的编辑。总而言之,这就是我一直在寻找的东西:)
Polymeron 2010年

1
还可以考虑添加xlApp.Visible = True,否则您将不会看到Excel或其任何可能出现的对话框。
Rachel Hettinger 2014年

1
EXCEL.exe我逐字运行此脚本时,该过程不会关闭。
安德烈C.安徒生

1
@Robert Mearns我使用此VBS在批处理模式下运行(该宏在交互模式下运行良好)。我运行了此VBS,但完全没有响应。我怀疑Set xlApp = CreateObject("Excel.Application")我的系统上没有工作。您能指导我如何使它工作吗?
Mubeen Shahid 2014年

您的excel文件中有哪些受密码保护,您想以读写方式打开它?您如何调整代码?
杰森·塞缪尔

23

最简单的方法是:

1)从批处理文件启动Excel,以打开包含您的宏的工作簿:

EXCEL.EXE /e "c:\YourWorkbook.xls"

2)从工作簿的Workbook_Open事件中调用您的宏,例如:

Private Sub Workbook_Open()
    Call MyMacro1          ' Call your macro
    ActiveWorkbook.Save    ' Save the current workbook, bypassing the prompt
    Application.Quit       ' Quit Excel
End Sub

现在,这会将控件返回到批处理文件以执行其他处理。


3
想到了这一点,但是即使我没有通过批处理文件打开它,它也将运行,这使得文件本身在不先禁用宏的情况下无法使用。
Polymeron 2010年

1
这很容易通过修改注册表设置来解决,该设置告诉Excel设置了哪个安全级别。
bvukas

当然,即使使用测试证书,对工作簿进行数字签名也总是有帮助的:)
bvukas 2010年

1
还是在没有Excel的情况下执行此操作?我的意思是与其他更专用于从命令行快速执行宏的程序一起使用。
skan,

2
如果以后必须更改某些内容,如何在不运行宏的情况下打开文件?
wviana '16

6

下面显示的方法允许从批处理文件运行定义的Excel宏,它使用环境变量将宏名从批处理传递给Excel。

将此代码放入批处理文件(使用您EXCEL.EXE的工作簿路径):

Set MacroName=MyMacro
"C:\Program Files\Microsoft Office\Office15\EXCEL.EXE" "C:\MyWorkbook.xlsm"

将此代码放入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

并将您的代码放入Excel VBA模块,如下所示:

Sub MyMacro()
    MsgBox "MyMacro is running..."
End Sub

启动批处理文件并获取结果:

宏的对话框

对于不打算运行任何宏的情况,只需将空值添加Set MacroName=到批处理中即可。


4

您可以编写一个vbscript通过createobject()方法创建excel实例,然后打开工作簿并运行宏。您可以直接调用vbscript,也可以从批处理文件中调用vbscript。

这是我偶然发现的资源:http : //www.codeguru.com/forum/showthread.php? t = 376401


3

如果您更喜欢在Excel / VBA中工作,请使用open事件并测试环境:具有信号文件,注册表项或控制open事件功能的环境变量。

您可以在外部创建文件/设置并在内部进行测试(对env-vars使用GetEnviromentVariable)并轻松进行测试。我已经编写了VBScript,但是与VBA的相似之处使我更加焦虑而不是容易。

[更多]

据我了解的问题,您想在大多数情况下/大部分时间正常使用电子表格,但要使其批量运行并做一些额外/不同的事情。您可以从excel.exe命令行打开工作表,但除非知道它在哪里,否则您无法控制它的工作。使用环境变量相对简单,并且使电子表格的测试变得容易。

为了明确起见,请使用下面的功能检查环境。在模块中声明:

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

在工作簿打开事件中(与其他事件一样):

Private Sub Workbook_Open()
    If GetEnvironmentVariable("InBatch") = "TRUE" Then
        Debug.Print "Batch"
    Else
        Debug.Print "Normal"
    End If
End Sub

添加适用的活动代码。在批处理文件中,使用

set InBatch=TRUE

3

而不是直接比较字符串(由于GetEnvironmentVariable返回长度为255的字符串,VB不会发现它们相等),请编写以下代码:

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 

3

我一直在Workbook_Open()中测试过打开的工作簿的数量。如果为1,则通过命令行打开工作簿(或用户关闭所有工作簿,然后打开该工作簿)。

If Workbooks.Count = 1 Then

    ' execute the macro or call another procedure - I always do the latter  
    PublishReport

    ThisWorkbook.Save

    Application.Quit

End If

2

@ Robert:我试图用相对路径修改您的代码,并创建了一个批处理文件来运行VBS。

VBS启动和关闭,但不启动宏...对问题可能在哪里有任何想法吗?

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

我删除了“ Application.Quit”,因为我的宏正在调用处理它的用户窗体。

干杯

编辑

我实际上已经解决了这个问题,以防万一有人想运行一个“类似”独立应用程序的用户表单:

我面临的问题:

1-我不想使用Workbook_Open事件,因为Excel处于只读状态。2-批处理命令的局限性在于,据我所知,它不能调用宏。

我首先编写了一个宏以在隐藏应用程序的同时启动用户窗体:

Sub open_form()
 Application.Visible = False
 frmAddClient.Show vbModeless
End Sub

然后,我创建了一个vbs以启动此宏(使用相对路径进行操作很棘手):

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"

最后我做了一个批处理文件来执行VBS ...

@echo off
pushd %~dp0
cscript Add_Client.vbs

请注意,我还包括了“设置回可见” 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

无论如何,谢谢您的帮助,我希望这会在有人需要时有所帮助


1

我偏爱C#。我使用linqpad运行以下程序。但是它可以像使用csc一样容易地编译并通过命令行调用来运行。

不要忘记将excel软件包添加到名称空间。

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;
    }
}

我从未见过LINQPad或CSC,因此感谢您提供独特的解决方案!
HackSlash

0

您可以检查Excel是否已经打开。无需创建另一个空白

   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

0

我通常将宏xlam与工作簿分开存储在外接程序中,因此我想打开工作簿,然后运行单独存储的宏。

由于这需要VBS脚本,因此我想使其成为“可移植的”,以便可以通过传递参数来使用它。这是最终的脚本,它包含3个参数。

  • 完整的工作簿路径
  • 宏名
  • [可选]使用Macro分离工作簿的路径

我这样测试:

"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 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.