طريقة تشغيل وحدات ماكرو Excel من سطر الأوامر أو الملف الدفعي؟
-
20-09-2019 - |
سؤال
لدي ماكرو Excel VBA الذي أحتاج إلى تشغيله عند الوصول إلى الملف من ملف دفعي، ولكن ليس في كل مرة أفتحه (وبالتالي لا أستخدم حدث الملف المفتوح).هل هناك طريقة لتشغيل الماكرو من سطر الأوامر أو الملف الدفعي؟أنا لست على دراية بمثل هذا الأمر.
تفترض بيئة Windows NT.
المحلول
يمكنك تشغيل برنامج Excel وفتح المصنف وتشغيل الماكرو من ملف VBScript.
انسخ الكود أدناه في المفكرة.
تحديث "MyWorkbook.xls' و 'مايماكرو' حدود.
احفظه بامتداد 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.تشغيل "MyMacro"
نصائح أخرى
وأبسط طريقة للقيام بذلك هي:
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
وهذا سوف يعود الآن للسيطرة على الملف الدفعي للقيام معالجة أخرى.
وأسلوب هو مبين أدناه يسمح لتشغيل محددة ماكرو Excel من ملف دفعي، فإنه يستخدم متغير البيئة لتمرير اسم الماكرو من دفعة إلى Excel.
ووضع هذا الرمز إلى ملف دفعي (استخدام مسارات لEXCEL.EXE
والمصنف):
Set MacroName=MyMacro
"C:\Program Files\Microsoft Office\Office15\EXCEL.EXE" "C:\MyWorkbook.xlsm"
ووضع هذا الرمز إلى كائن اكسل 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=
القيمة فارغة إلى دفعة واحدة.
هل يمكن إرسال بريد VBScript لإنشاء مثيل من التفوق عبر أسلوب CreateObject ()، ثم قم بفتح المصنف وتشغيل الماكرو. هل يمكن إما استدعاء فبسكريبت مباشرة، أو استدعاء VBScript من ملف دفعة واحدة.
وهنا هو مورد أنا فقط تعثرت تزوجنا: http://www.codeguru.com/forum/showthread.php؟t= 376401
ولقد اختبرت دائما عدد المصنفات المفتوحة في 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
إذا كنت تعمل أكثر راحة داخل اكسل / VBA، استخدم الحدث مفتوح واختبار البيئة: إما أن يكون ملف إشارة، إدخال التسجيل أو متغير البيئة أن الضوابط ما حدث مفتوحة يفعل
يمكنك إنشاء ملف / إعداد خارج وداخل اختبار (استخدام GetEnviromentVariable للفار الحياة الفطرية) والاختبار بسهولة. لقد كتب فبسكريبت لكن أوجه التشابه مع 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
وبدلا من مقارنة مباشرة السلاسل (VB لن تجد لها يساوي منذ GetEnvironmentVariable بإرجاع سلسلة من طول 255) أكتب هذا:
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
@ روبرت:لقد حاولت تكييف التعليمات البرمجية الخاصة بك مع مسار نسبي، وقمت بإنشاء ملف دفعي لتشغيل 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
على أية حال، شكرًا لمساعدتك، وآمل أن يكون هذا مفيدًا إذا احتاجه شخص ما
ويمكنك معرفة ما اذا كان اكسل مفتوح مسبقا. ليست هناك حاجة لخلق 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
وأنا جزئي إلى C #. ركضت باستخدام linqpad التالية. ولكن يمكن بسهولة مثلما يتم تجميعها مع ديوان الخدمة المدنية وركض من خلال استدعاء من سطر الأوامر.
لا تنس أن تضيف حزم تتفوق على مساحة الاسم.
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;
}
}