Запуск макроса Excel через C#: запускать макрос из одной книги в другой?
Я хочу запустить макрос, давайте назовем его Macro01 из WorkSheet01 на WorkSheet02.
Используя пространство имен Microsoft.Office.Interop.Excel, я открыл WorkSheet01.
public void Main_CodedStep()
{
// Object for missing (or optional) arguments.
object oMissing = System.Reflection.Missing.Value;
// Create an instance of Microsoft Excel
Excel.ApplicationClass oExcel = new Excel.ApplicationClass();
// Make it visible
oExcel.Visible = true;
// Open Worksheet01.xlsm
Excel.Workbooks oBooks = oExcel.Workbooks;
Excel._Workbook oBook = null;
oBook = oBooks.Open("C:\\Users\\Admin\\Documents\\Worksheet01.xlsm", oMissing, oMissing,
oMissing, oMissing, oMissing, oMissing, oMissing, oMissing,
oMissing, oMissing, oMissing, oMissing, oMissing, oMissing);
}
Затем я использую автоматический скрипт, чтобы получить отчет. Этот отчет открывается через приглашение загрузки IE, а не Interop.
Проблема возникает, когда я пытаюсь запустить макрос через C# (я сделал еще один новый Excel.ApplicationClass(); только так он скомпилирован, я считаю, что это один из моих ошибок.)
public void FirstMacro_CodedStep()
{
// Create an instance of Microsoft Excel
Excel.ApplicationClass oExcel = new Excel.ApplicationClass();
Console.WriteLine("ApplicationClass: " + oExcel);
// Run the macro, "First_Macro"
RunMacro(oExcel, new Object[]{"Worksheet01.xlsm!First_Macro"});
//Garbage collection
GC.Collect();
}
private void RunMacro(object oApp, object[] oRunArgs)
{
oApp.GetType().InvokeMember("Run", System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.InvokeMethod, null, oApp, oRunArgs);
}
Когда этот метод запускается, он запускает макрос из Worksheet01 на Worksheet01 вместо Worksheet02. Также он искал лист в "Мои документы", поэтому я переместил его, чтобы посмотреть, что произойдет.
Резюме:
- Открыть рабочий лист01
- С помощью скриптов получить и открыть отчет (Worksheet02) из MSIE
- Запустите Macro01 из Worksheet01 в Worksheet02
Ресурсы:
http://support.microsoft.com/kb/306683
http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.aspx
Для тех, кто хотел бы попробовать это, добавьте это в ваши директивы using:
using System.Reflection;
using Microsoft.Office.Core; //Added to Project Settings' References from C:\Program Files (x86)\Microsoft Visual Studio 10.0\Visual Studio Tools for Office\PIA\Office14 - "office"
using Excel = Microsoft.Office.Interop.Excel; //Added to Project Settings' References from C:\Program Files (x86)\Microsoft Visual Studio 10.0\Visual Studio Tools for Office\PIA\Office14 - "Microsoft.Office.Interop.Excel"
4 ответа
Я нашел решение, которым хотел бы поделиться. Сначала я удалил бит, где я открыл Worksheet01. Затем мой автоматический скрипт сохранил.CSV в Мои документы. Затем я использовал код, который должен был открыть Worksheet01, чтобы открыть загруженный файл. Ключевым моментом на этом этапе является то, что Worksheet01 находится в папке Documents с Worksheet02. Наконец, я использовал код для запуска макроса из Worksheet01, который работает на Worksheet02.
public void WebTest_CodedStep()
{
// Object for missing (or optional) arguments.
object oMissing = System.Reflection.Missing.Value;
// Create an instance of Microsoft Excel
Excel.ApplicationClass oExcel = new Excel.ApplicationClass();
// Make it visible
oExcel.Visible = true;
// Define Workbooks
Excel.Workbooks oBooks = oExcel.Workbooks;
Excel._Workbook oBook = null;
// Get the file path
string path = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
path = path + "\\Worksheet02.csv";
//Open the file, using the 'path' variable
oBook = oBooks.Open(path, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing);
// Run the macro, "First_Macro"
RunMacro(oExcel, new Object[]{"Worksheet01.xlsm!First_Macro"});
// Quit Excel and clean up.
oBook.Close(false, oMissing, oMissing);
System.Runtime.InteropServices.Marshal.ReleaseComObject (oBook);
oBook = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject (oBooks);
oBooks = null;
oExcel.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject (oExcel);
oExcel = null;
//Garbage collection
GC.Collect();
}
private void RunMacro(object oApp, object[] oRunArgs)
{
oApp.GetType().InvokeMember("Run", System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.InvokeMethod, null, oApp, oRunArgs);
}
Я запустил этот код C# VSTO для вызова макроса VBA, вот синтаксис, который я использую:
this.Application.Run("mymacro");
Редактировать:
Макросы имеют всю рабочую книгу, возможно, вам нужно сделать Sheet2 активным рабочим листом перед запуском макроса, например:
foreach (Worksheet worksheet in workbook.Sheets.ComLinq<Worksheet>())
{
if (worksheet.Name == "Sheet2") worksheet.Activate();
}
Это сработало для меня, у меня есть файлы xlsm с макросом под названием «ref». Часть кода макроса предназначена для выхода из приложения Excel (Application.Quit).
Этот код откроет файл, запустит макрос и затем закроет его:
using _Excel = Microsoft.Office.Interop.Excel;
using Microsoft.Office.Interop.Excel;
public static void runMacro (string sourceFile)
{
_Application excel = new _Excel.Application();
excel.Visible = true;
string pathToExcelXlsmFile = sourceFile;
Workbook wb;
Worksheet ws;
int sheetNumber = 3; // sheet number where macro is in
wb = excel.Workbooks.Open(pathToExcelXlsmFile);
ws = wb.Worksheets[sheetNumber];
//Call VBA code
string runMacro = Path.GetFileName(sourceFile) + "!ref";
excel.GetType().InvokeMember("Run", System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.InvokeMethod, null, excel, new Object[] { runMacro});
excel.Quit();
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(excel);
}
public void ExecuteMacro()
{
// using Excel = Microsoft.Office.Interop.Excel;
// using System;
// using System.IO;
string path = Environment.CurrentDirectory;
string filePath = "";
string[] fileEntries = Directory.GetFiles(".\\Source");
foreach (string fileName in fileEntries)
{
if (fileName.IndexOf(".xlsm") > 0 && fileName.IndexOf("$")<1) filePath = fileName;
}
if (filePath == "") return;
filePath = filePath.Replace(".\\", "\\");
string fileDest = filePath.Replace("Source","Processed");
filePath = path+filePath;
fileDest = path+fileDest;
Excel.Application ExcelApp = new Excel.Application();
Excel.Workbook wb = ExcelApp.Workbooks.Open(filePath, ReadOnly: false);
try
{
ExcelApp.Visible = false;
ExcelApp.Run("UpdateSheets");
try
{
File.Delete(fileDest);
}
catch (Exception) { }
wb.SaveAs(fileDest);
}
catch (Exception) { }
wb.Close(false);
ExcelApp.Application.Quit();
ExcelApp.Quit();
}