Я использую следующий код для запуска макроса VBA через взаимодействие с C # Excel:

public void macroTest()
    {
        Excel.Application xlApp = new Excel.Application();
        xlApp.Visible = true;
        string bkPath = @"C:\somePath\someBk.xlsm";
        Excel.Workbook bk = xlApp.Workbooks.Open(bkPath);
        string bkName = bk.Name;
        string macroName = "testThisMacro_m";
        string runString = "'" + bkName + "'!"+macroName;
        xlApp.Run(runString);
        bk.Close(false);
        xlApp.Quit();
    }

testThisMacro_m находится в модуле testMacro, и он работает успешно. Когда я заменяю его:

string macroName = "testThisMacro_s";

Где testThisMacro_s имеет свой код в Sheet1, строка xlApp.Run() дает следующее исключение COM:

Cannot run the macro ''someBk.xlsm'!testThisMacro_s'. 
The macro may not be available in this workbook or all macros may be disabled.

Я проверил настройки безопасности макросов, и они действительно установлены на «Отключить с уведомлением», но возможность запускать макрос из модуля, а не из рабочего листа, похоже, указывает на то, что это другая проблема, чем макробезопасность на уровне приложения.

Есть ли что-то другое, что мне нужно сделать при выполнении вызова взаимодействия с макросом на листе?

ОБНОВЛЕНИЕ: мне удалось запустить макрос, изменив вызов на:

string macroName = "Sheet1.testThisMacro_s"

Но кажется, что эти руки передают управление обратно на C # до завершения макроса, поэтому теперь мне нужно выяснить, как проверить завершение макроса (вероятно, другой вопрос).

2
sigil 22 Фев 2016 в 08:58

3 ответа

Лучший ответ

Мне удалось запустить макрос, изменив вызов на:

string macroName = "Sheet1.testThisMacro_s"
0
sigil 22 Фев 2016 в 07:07

Объект Worksheet - это объект , а объекты определяются с помощью модулей классов . Рабочие листы, рабочие тетради, пользовательские формы; они все объекты. И вы не можете просто вызвать метод объекта, если у вас нет экземпляра этого объекта.

Макросы работают с стандартными модулями , которые не являются объектами и не требуют создания экземпляров.

Application.Run не может вызывать методы объекта , поэтому макросы должны быть в стандартных модулях.

4
Mathieu Guindon 22 Фев 2016 в 06:10

Разве вспомогательная подпрограмма не решила бы обе ваши проблемы в ответ на ответ Mat's Mug относительно создания экземпляра?

В каком-то стандартном модуле:

Sub testHelperSubToBeCalledFromInterop
    Call Sheet1.testThisMacro_s
End Sub

РЕДАКТИРОВАТЬ:

enter image description here

0
Vegard 5 Окт 2016 в 07:50