Вопрос создания DLL для интеграции с Microsoft Excel в среде Delphi является актуальным для разработчиков, желающих расширить функционал Excel с помощью собственных компонентов. В данной статье мы рассмотрим, как передать ссылку на текущую сессию Excel в созданный в Delphi DLL, что позволит взаимодействовать с Excel без необходимости запускать отдельный экземпляр программы.
Описание проблемы
Разработчики, работающие с Turbo Delphi 2006, сталкиваются с задачей создания DLL, которая будет вызываться из Excel в рамках комбинации VBA/DLL. Основная проблема заключается в том, чтобы передать в DLL ссылку на текущую сессию Excel, не запуская при этом новый экземпляр программы. Существующие примеры кода часто демонстрируют запуск отдельной сессии Excel, что не является желаемым решением.
Решение с использованием COM/ActiveX
Для решения этой задачи можно использовать технологии COM/ActiveX, которые позволяют создавать объекты, совместимые с Excel. При правильной реализации, вы получите необходимый интерфейс IDispatch, который можно использовать для взаимодействия с Excel.
Использование ActiveX Controls в Delphi
Delphi предоставляет набор ActiveX-контролов, которые дают полный доступ к функциям Excel и другим приложениям Office. Эти компоненты обычно находятся на вкладке "Серверы" в палитре инструментов. Если их там нет, можно установить их, выбрав "Компоненты|Установить пакеты" и найдя нужный в списке.
Пример названий компонентов: "Microsoft Office Sample Automation Server Wrapper Components", доступных для Windows XP и Windows 2000, которые также будут работать в Windows Vista.
Создание COM-объекта
Если ваша цель — добавить функциональность в Excel, использование COM-объекта может быть предпочтительным, так как Excel хорошо принимает COM-объекты. В качестве альтернативы, можно создать обычную DLL, которую можно использовать аналогично тому, как Excel использует любые другие DLL.
Создание COM-расширения
Описываемая задача связана с написанием COM-расширения, которое требует создания автоматизированной DLL и реализации интерфейса IDTExtensibility2. После этого, в метод OnConnection будет передан интерфейс Application Excel.
Не забудьте зарегистрировать вашу DLL как расширение, чтобы Excel автоматически загружал её при запуске.
Использование Add-in Express
Для упрощения процесса создания Office-расширений можно использовать Add-in Express. Этот фреймворк и компоненты значительно упрощают разработку, позволяя избежать сложностей, связанных с интерфейсом IDTExtensibility2. Однако стоит отметить, что Add-in Express является платным продуктом.
Пример кода на Object Pascal
Пример кода на Object Pascal для создания COM-объекта может выглядеть следующим образом:
unit Unit1;
interface
uses
System.SysUtils,
System.Classes,
Winapi.ActiveX;
type
TMyComObject = class(TComObject, IDispatch, IMyInterface)
private
FExcelApp: IDispatch;
public
constructor CreateNew;
function GetExcelApp: IDispatch; stdcall;
property ExcelApp: IDispatch read GetExcelApp;
end;
{ TMyComObject }
constructor TMyComObject.CreateNew;
begin
inherited CreateComObject;
// Инициализация компонента
end;
function TMyComObject.GetExcelApp: IDispatch;
begin
// Получение ссылки на текущий экземпляр Excel
// ...
Result := FExcelApp;
end;
interface
type
IMyInterface = interface(IInterface)
['{00020400-0000-0000-C000-000000000046}']
function GetExcelApp: IDispatch; stdcall;
end;
implementation
{ TMyComObject }
function TMyComObject._GetIDsOfNames(const IID: TGUID; const Names: PPOLESTR; NameCount: Integer; LCID: Integer; var NamesSupported: LongBool; out NamesResult: HRESULT): HRESULT; stdcall;
function TMyComObject._Invoke(DispatchID: DWord; const IID: TGUID; TargetAddr: PVOID; MethodNum: Word; LangID: Word; DispFlags: LongWord; var Params: PVARENUM; var Result: PVARENUM; var ExcepInfo: PEXCEPINFO; var ArgErr: PWord): HRESULT; stdcall;
function TMyComObject._QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function TMyComObject._AddRef: LongWord; stdcall;
function TMyComObject._Release: LongWord; stdcall;
function TMyComObject._GetTypeInfoCount(var Count): HRESULT; stdcall;
function TMyComObject._GetTypeInfo(var Index: UInteger; var LCID: LongWord; out TypeInfo): HRESULT; stdcall;
function TMyComObject._GetIDsOfNamesHelper(const Names: PPOLESTR; NameCount: Integer; var NamesSupported: LongBool; out NamesResult: HRESULT): HRESULT; stdcall;
function TMyComObject._InvokeHelper(MethodNum: Word; VarCount: Integer; var RetVal: PVARENUM; var Params: PVARENUM; InvocationType: Word; LCID: Word): HRESULT; stdcall;
function TMyComObject._GetTypeInfoDirect: HRESULT; stdcall;
function TMyComObject._DispGetParam(ParamNum: Integer; var Param: PVARENUM): HRESULT; stdcall;
function TMyComObject._DispPutParam(ParamNum: Integer; var Param: PVARENUM): HRESULT; stdcall;
function TMyComObject._DispInvoke(Params: PVARENUM; LCID: Word; var RetVal: PVARENUM): HRESULT; stdcall;
function TMyComObject._FastBindObj(Obj: PObject; var Bind: PBindInfo): HRESULT; stdcall;
function TMyComObject._FastBindParam(Obj: PObject; Param: Integer; var Params: PVARENUM): HRESULT; stdcall;
function TMyComObject._FastBindNames(Obj: PObject; Names: PPOLESTR; NameCount: Integer; var NamesSupported: LongBool): HRESULT; stdcall;
function TMyComObject._FastGetTypeOfThis: HRESULT; stdcall;
function TMyComObject._FastQueryInterface(Obj: PObject; IID: TGUID; var Interface: PVOID): HRESULT; stdcall;
function TMyComObject._FastGetClassType(Obj: PObject; var ClassType: PTypeInfo): HRESULT; stdcall;
function TMyComObject._FastGetDispParam(Obj: PObject; ParamNum: Integer; var Param: PVARENUM): HRESULT; stdcall;
function TMyComObject._FastGetTypeInfo(Obj: PObject; Index: UInteger; LCID: LongWord; var TypeInfo: PTypeInfo): HRESULT; stdcall;
function TMyComObject._FastGetNextDispParam(Obj: PObject; ParamNum: Integer; var Param: PVARENUM): HRESULT; stdcall;
function TMyComObject._FastGetInvokeRecipient(Obj: PObject; MethodNum: Word; var Recipient: PObject): HRESULT; stdcall;
function TMyComObject._FastGetInvokeResult(Recipient: PObject; MethodNum: Word; Params: PVARENUM; LCID: Word; InvocationType: Word; var RetVal: PVARENUM): HRESULT; stdcall;
function TMyComObject._FastQueryByName(Obj: PObject; Names: PPOLESTR; NameCount: Integer; var NamesSupported: LongBool; var Type: PTypeInfo; var Var: Variant): HRESULT; stdcall;
function TMyComObject._FastQueryByIndex(Obj: PObject; Index: UInteger; LCID: LongWord; var Type: PTypeInfo; var Var: Variant): HRESULT; stdcall;
function TMyComObject._FastPutDispParam(Obj: PObject; ParamNum: Integer; var Param: PVARENUM): HRESULT; stdcall;
function TMyComObject._FastCreateInstance(Obj: PObject; var NewObj: PObject): HRESULT; stdcall;
function TMyComObject._FastCreateInstanceEx(Obj: PObject; Params: PVARENUM; ClassType: PTypeInfo; var NewObj: PObject): HRESULT; stdcall;
function TMyComObject._FastBindSourceObj(Obj: PObject; var Bind: PBindInfo): HRESULT; stdcall;
function TMyComObject._FastCastToType(Obj: PObject; Type: PTypeInfo; var NewObj: PObject): HRESULT; stdcall;
function TMyComObject._FastClone(Obj: PObject; var NewObj: PObject): HRESULT; stdcall;
function TMyComObject._FastPut(Obj: PObject; Index: UInteger; LCID: LongWord; Type: PTypeInfo; Var: Variant): HRESULT; stdcall;
function TMyComObject._FastGetType(Obj: PObject; LCID: LongWord; var Type: PTypeInfo): HRESULT; stdcall;
initialization
{$R *.res}
end.
Этот код представляет собой базовый шаблон для создания COM-объекта в Delphi, который может быть использован для взаимодействия с Excel. Обратите внимание, что для полноценной реализации необходимо реализовать методы интерфейса IDTExtensibility2 и обработать получение ссылки на текущий экземпляр Excel.
Заключение
В данной статье мы рассмотрели, как разработчики в среде Turbo Delphi 2006 могут создать DLL для интеграции с Excel, передавая ссылку на текущую сессию Excel в созданный в Delphi COM-объект. Использование ActiveX Controls, создание COM-расширений и применение Add-in Express могут значительно упростить этот процесс. Приведенный пример кода на Object Pascal демонстрирует начальные шаги для создания такого COM-объекта.
Разработчики в среде Delphi создают DLL для интеграции с Microsoft Excel, используя технологии COM/ActiveX для передачи ссылки на текущую сессию Excel в созданный компонент, без необходимости запускать новый экземпляр программы.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.