web-dev-qa-db-fra.com

Manière d'exécuter des macros Excel à partir d'une ligne de commande ou d'un fichier de commandes?

J'ai une macro Excel VBA que je dois exécuter lors de l'accès au fichier à partir d'un fichier de traitement par lots, mais pas à chaque fois que je l'ouvre (par conséquent, je n'utilise pas l'événement open file). Existe-t-il un moyen d’exécuter la macro à partir de la ligne de commande ou du fichier de commandes? Je ne suis pas familier avec une telle commande.

Supposons un environnement Windows NT.

69
Polymeron

Vous pouvez lancer Excel, ouvrir le classeur et exécuter la macro à partir d'un fichier VBScript.

Copiez le code ci-dessous dans le Bloc-notes.

Mettez à jour les paramètres ' MyWorkbook.xls ' et ' MyMacro '.

Enregistrez-le avec une extension vbs et lancez-le.

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 ligne de clé qui exécute la macro est la suivante:

xlApp.Run "MyMacro"

77
Robert Mearns

Le moyen le plus simple de le faire est de:

1) Démarrez Excel à partir de votre fichier de commandes pour ouvrir le classeur contenant votre macro:

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

2) Appelez votre macro depuis l'événement Workbook_Open Du classeur, par exemple:

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

Cela va maintenant renvoyer le contrôle dans votre fichier de commandes pour effectuer un autre traitement.

19
bvukas

La méthode présentée ci-dessous permet d’exécuter une macro Excel définie à partir d’un fichier de traitement par lots. Elle utilise une variable d’environnement pour transmettre le nom de la macro d’un traitement par lots à Excel.

Mettez ce code dans le fichier de commandes (utilisez vos chemins d'accès pour Excel.EXE et au classeur):

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

Placez ce code dans un objet 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

Et mettez votre code dans Excel VBA Module, comme suit:

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

Lancez le fichier de commandes et obtenez le résultat:

macro's dialog

Pour le cas où vous n’avez pas l’intention d’exécuter une macro, mettez simplement une valeur vide Set MacroName= au lot.

5
omegastripes

vous pouvez écrire un vbscript pour créer une instance d'Excel via la méthode createobject (), puis ouvrir le classeur et exécuter la macro. Vous pouvez appeler directement vbscript ou appeler vbscript à partir d'un fichier de commandes.

Voici une ressource que je viens de découvrir: http://www.codeguru.com/forum/showthread.php?t=376401

4
Fink

J'ai toujours testé le nombre de classeurs ouverts dans Workbook_Open (). Si la valeur est 1, le classeur a été ouvert à l'aide de la ligne de commande (ou l'utilisateur a fermé tous les classeurs, puis a ouvert celui-ci).

If Workbooks.Count = 1 Then

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

    ThisWorkbook.Save

    Application.Quit

End If
3
Brian Hoffman

Au lieu de comparer directement les chaînes (VB ne les trouvera pas égales car GetEnvironmentVariable renvoie une chaîne de longueur 255), écrivez ceci:

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 
2
laybmw

Si vous êtes plus à l'aise avec Excel/VBA, utilisez l'événement open et testez l'environnement: disposez d'un fichier de signal, d'une entrée de registre ou d'une variable d'environnement contrôlant le fonctionnement de l'événement.

Vous pouvez créer le fichier/paramètre en dehors et tester à l'intérieur (utilisez GetEnviromentVariable pour env-vars) et tester facilement. J'ai écrit VBScript mais les similitudes avec VBA me causent plus d'angoisse que de facilité.

[plus]

Si je comprends bien le problème, vous souhaitez utiliser une feuille de calcul normalement la plupart du temps, mais parfois la faire fonctionner par lots et faire quelque chose de plus/différent. Vous pouvez ouvrir la feuille à partir de la ligne de commande Excel.exe, mais vous ne pouvez pas contrôler ce qu'elle fait sauf si elle sait où elle se trouve. L'utilisation d'une variable d'environnement est relativement simple et facilite le test de la feuille de calcul.

Pour clarifier, utilisez la fonction ci-dessous pour examiner l'environnement. Dans un module, déclarez:

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

Dans l'événement ouvert du classeur (comme les autres):

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

Ajoutez le code actif, le cas échéant. Dans le fichier de commandes, utilisez

set InBatch=TRUE
2
Chris Chambers

@ Robert: J'ai essayé d'adapter votre code avec un chemin relatif et créé un fichier de commandes pour exécuter VBS.

La VBS démarre et se ferme mais ne lance pas la macro ... Avez-vous une idée du problème?

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

J'ai supprimé le "Application.Quit" parce que ma macro appelle un userform en prendre soin.

À votre santé

EDIT

En fait, j'ai résolu le problème, au cas où quelqu'un voudrait exécuter un formulaire utilisateur "de la même manière" qu'une application autonome:

Problèmes auxquels je faisais face:

1 - Je ne voulais pas utiliser l'événement Workbook_Open, car Excel est verrouillé en lecture seule. 2 - La commande batch est limitée au fait que (à ma connaissance) il ne peut pas appeler la macro.

J'ai d'abord écrit une macro pour lancer mon formulaire utilisateur tout en cachant l'application:

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

J'ai ensuite créé un vbs pour lancer cette macro (le faire avec un chemin relatif a été délicat):

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"

Et j'ai finalement fait un fichier batch pour exécuter le VBS ...

@echo off
pushd %~dp0
cscript Add_Client.vbs

Notez que j’ai également inclus le "Retour au visible" dans mon 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

Quoi qu'il en soit, merci pour votre aide, et j'espère que cela aidera si quelqu'un en a besoin

2
Axn40

Je suis partial à C #. J'ai couru ce qui suit en utilisant linqpad. Mais il pourrait tout aussi bien être compilé avec csc et parcouru l'appelé à partir de la ligne de commande.

N'oubliez pas d'ajouter des packages Excel à l'espace de noms.

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

Vous pouvez vérifier si Excel est déjà ouvert. Il n'y a pas besoin de créer une autre 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
1
Adam Law