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.

È stato utile?

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:

 finestra di dialogo di macro

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;
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top