Вызов функции макроса Excel с помощью Excel C API

Я новичок в разработке XLL и пытаюсь вызвать зарегистрированную функцию в качестве макроса в моем XLL. Я пытаюсь получить доступ для записи к ячейкам, смежным с моей вызывающей ячейкой.

Похоже, что функция xlSet даст мне возможность сделать это. Но не похоже, что эту функцию можно вызвать из моей функции Xll https://docs.microsoft.com/en-us/office/client-developer/excel/xlset

Из API кажется, что эту функцию нужно вызывать из макроса. Я пытался использовать функцию xlUDF, чтобы «обмануть» excel, заставив думать, что я запускаю функцию как макрос, но мне не повезло. Функция xlUDF вызывается, но xlSet по-прежнему не работает.

Как мне вызвать макрос, который может вызывать эту функцию? Кажется, С#/ExcelDna имеет эквивалент:

object xlApp = ExcelDnaUtil.Application;
xlApp.GetType().InvokeMember("Run", BindingFlags.InvokeMethod, null, xlApp, new object[]{macroName});

Спасибо заранее!


person David Co    schedule 08.04.2020    source источник


Ответы (1)


Это запрещено для вызова команды из функции XLL по соображениям безопасности (особенно для доступа к записи..). В вашем случае Excel не позволяет потоку вычислений, который запускает вашу функцию Xll (A), вызывать вашу зарегистрированную команду (B) и, таким образом, «xlset», потому что в противном случае вы могли бы, например, разбить Excel, изменив ячейку (через команду), которая может — один из аргументов функции (A).

xlSet ведет себя как функция, эквивалентная команде класса 3; то есть он доступен только внутри DLL, когда DLL вызывается из объекта, макроса, меню, панели инструментов, сочетания клавиш или кнопки «Выполнить» в диалоговом окне «Макрос» (доступ на вкладке «Вид» на ленте, начиная с Excel 2007, и меню «Инструменты» в более ранних версиях). источник

Поэтому, если вы хотите использовать xlset, вам необходимо: 1) вызвать его из функции, зарегистрированной как макрос, и 2) вы не можете вызывать этот макрос из своего xll, т.е. макрос должен вызываться конечным пользователем или программой Excel. Объектная модель (VBA, VSTO...).

Что касается ExcelDna, я считаю, что он решает проблему, вызывая макрос (B) из другого потока, COM-сервера, который обращается к объектной модели Excel. В этом случае функция XLL (A) делегирует вызов только потоку, который не ограничен. Но это может быть опасно.

Изменить:

Я разговаривал с ОП в чате, и оказалось, что он хотел расширить область ячейки через объектную модель Excel. Но в этом больше нет необходимости: с осени 2018 года Excel автоматически изменяет размер массива xltypeMulti, возвращаемого UDF (динамический массив).

person Malick    schedule 08.04.2020
comment
Спасибо Малик! Я думаю, что пытался выполнить то, что вы упомянули выше: - person David Co; 09.04.2020
comment
Спасибо Малик! Я думаю, что пытался выполнить то, что вы упомянули выше, путем: 1. Создания потока в моей зарегистрированной функции XLL. Например. CreateThread(NULL, 0, DisplayGrid, argsArray, 0, NULL) 2. Затем моя функция DisplayGrid вызовет другую функцию как макрос (я думаю) с помощью команды xlUDF. Однако это никогда не работало, и я не могу понять, почему. Например. Excel12(xlfEvaluate, &xNameValue, 1, &xNameText); Excel12(xlUDF, &xRes, 2, &xNameValue, &xlRet); 3. Мне так и не удалось вызвать xlSet в моей функции DoDisplay, но я намеревался вызвать ее отсюда. - person David Co; 09.04.2020
comment
У вас есть примеры того, как это можно сделать? - person David Co; 09.04.2020
comment
Нет, вам нужно вызвать функцию макроса через объектную модель Excel. Если вы хотите придерживаться C++, вам нужно сделать это через COM, поэтому, чтобы импортировать правильную библиотеку, получите указатель на Excel в xlAutoOpen() и в какой-то момент вызовите _ptrExcel->Run(MyMacro). См. также: github.com/Excel-DNA/ExcelDna/wiki /COM-object-model-notes сказано, что даже в этом случае вы не сможете писать, см. codeproject.com/Articles/15837/, чтобы узнать, как импортировать библиотеку. Excel C API отлично подходит для функций, для всего остального я бы рекомендовал искать VSTO. - person Malick; 09.04.2020
comment
Заранее спасибо @Malick. Мне удалось получить указатель на экземпляр excel и оценить dispId для функции «Выполнить» (259). Однако я получил исключение при запуске фактического макроса. hr = pXlApp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dps, &result, NULL, NULL); Не могли бы вы увидеть, что здесь не так? Я надеялся, что этот TestMacro будет вызываться через вызов Run - person David Co; 11.04.2020
comment
Я создал комнату: chat.stackexchange.com/rooms/ 106591/ - person Malick; 11.04.2020
comment
Извини, Малик, у меня недостаточно репутации, чтобы присоединиться к этой комнате. Но чтобы ответить на ваш вопрос, я без проблем могу вызвать свой макрос из сотового. Я думаю, это означает, что он зарегистрирован правильно? - person David Co; 11.04.2020
comment
вы должны быть в состоянии присоединиться к комнате сейчас - person Malick; 11.04.2020
comment
:( извини еще говорит мне нужна репутация не ниже 20 - person David Co; 11.04.2020
comment
хорошо, теперь у вас достаточно репутации, давайте продолжим в чате - person Malick; 11.04.2020