Есть два пути для получения доступа к серверам автоматизации:
Позднее связывание (Интерфейс IDispatch)
При использовании данного метода имена функций и типы параметров решаются во время выполнения программы, все параметры определены вариантным типом.
Поскольку во время компиляции невозможно определить соответствия имен функций и типов параметров, данный метод чреват ошибками.
Так как имена функций и типы параметров должны проверяться во время выполнения программы, данный метод выполняется медленно.
Единственное преимущество данного метода при программировании в Delphi заключается в том, что отпадает необходимость передачи всех параметров вызываемой функции.
Раннее связывание (Использование библиотеки типов/интерфейсов)
При использовании данного метода имена функций и типы параметров полностью решаются во время компиляции.
Библиотека типов должна импортироваться в Delphi. Библиотека типов является языковым нейтральным описанием всех объектов и функций, поддерживаемых сервером. (Это подобно файлу заголовка языка C).
При вызове функции должны обязательно присутствовать все параметры, даже те, которые в документации указаны как дополнительные (необязательные). Это позволяет обнаружить и исправить множество ошибок еще до запуска программы.
Скорость выполнения значительно быстрее, чем при использовании позднего связывания.
Из-за преимуществ второго метода остальная часть документа демонстрирует принципы создания приложений с ранним связыванием. Все приложения, использующие Excel автоматизацию, должны пользоваться последним методом, если нет причин для первого.
Подготовка библиотеки типов.
Модуль Pascal должен быть создан на основе файла библиотеки типов.
Выберите пункт меню Project|Import Type Library.
Нажмите кнопку Add и выберите следующий файл
c:\program files\microsoft office\office\excel8.olb
Нажмите OK.
К сожалению, данный модуль с проектом явно не компилируется, хотя и включается в него, вероятно из-за того, что приложение считает данный модуль нечто вроде текстового приложения.
Наиболее простой путь заключается в следующем: удалите модуль excel_tlb из проекта и только после этого добавьте его в список используемых модулей.
Документация
Справочный файл c:\program files\microsoft office\office\vbaxl8.hlp содержит информацию о доступных объектах Excel.
"Записыватель" макросов позволяет быстро создавать VBA-код. После этого он довольно может легко быть портирован в Delphi.
Пример автоматизации
Код следующего примера демонстрирует создание простой электронной таблицы и наполнение ее данными. Не забудьте добавить excel_tlb в список используемых модулей.
Настоятельно рекомендую хранить код автоматизации в отдельном модуле, это поможет избежать проблем конфликта имен.
Unit sheet; //-------------------------------------------------------------------- interface //-------------------------------------------------------------------- uses windows, sysutils, excel_tlb; Procedure CreateSpreadsheet; //-------------------------------------------------------------------- implementation //-------------------------------------------------------------------- Procedure CreateSpreadsheet(filename : string); var xla : _Application;xlw : _Workbook;LCID : integer;begin xla := CoApplication.Create;LCID := GetUserDefaultLCID;tryxla.Visible[LCID] := true;// пустая книга//xlw := xla.Workbooks.Add(xlWBATWorksheet, LCID);// новая книга на основе шаблонаxlw := xla.Workbooks.Add('c:\delphi\excel\sample\demo.xlt',LCID);xla.Range['A1', 'A1'].Value := 'Date';xla.Cells[1, 2].Value := FormatDateTime('dd-mmm-yyyy', Now);xla.Cells[3, 1].Value := 'Numbers';xla.Range['B3', 'E3'].Value := VarArrayOf([1, 10, 100, 1000]);xla.Range['F3', 'F3'].Formula := '=Sum(B3:E3)';OLEVariant(xla).Run('Demo',FormatDateTime('dd-mmm-yyyy', Now));xlw.SaveAs(filename,xlWorkbookNormal,'','',False,False,xlNoChange,xlLocalSessionChanges,true,0,0,LCID);finallyxla.Quit;end;end; //-------------------------------------------------------------------- end. |
|
uses windows, sysutils, excel_tlb; |
xla := CoApplication.Create; |
LCID := GetUserDefaultLCID; |
xla.visible[LCID] := true; |
xlw := xla.Workbooks.Add('c:\delphi\excel\sample\demo.xlt', LCID); |
xlw := xla.Workbooks.Add(xlWBATWorksheet, LCID); |
xla.Range['A1', 'A1'].Value := 'Date';xla.Cells[1, 2].Value := FormatDateTime('dd-mmm-yyyy', Now); |
xla.Range['A2', 'D2'].Value := VarArrayOf([1, 10, 100, 1000]); |
xla.Range['E2', 'E2'].Formula := '=Sum(a2:d2)'; |
OLEVariant(xla).Run('Demo',FormatDateTime('dd-mmm-yyyy', Now)); |
xlw.SaveAs(filename,xlWorkbookNormal,'', '',False,False,xlNoChange, xlLocalSessionChanges,true, 0, 0, LCID); |
xla.quit; |
Размер электронной таблицы (строки * колонки) | Заполнение ячейка за ячейкой | Заполнение одной колонки за один проход | Заполнение всей таблицы за один проход |
10 * 10 | 0:01 | 0:01 | >0:01 |
100 * 10 | 0:07 | 0:01 | 0:01 |
1000 * 10 | 1:13 | 0:07 | 0:05 |
5000 * 10 | 5:22 | 0:35 | 0:25 |
Приблизительно ячейки/секунды | 150 | 1500 | 2000 |
//----------------------------------------------------------------------- procedure FillByCell; var xla : _Application;xlw : _Workbook;LCID : integer;i,j : integer;begin xla := CoApplication.Create;LCID := GetUserDefaultLCID;tryxlw := xla.Workbooks.Add(xlWBATWorksheet, LCID);for i:=1 to ROWS do beginfor j:=1 to 10 do beginxla.Cells[i,j] := i+j;end;end;xlw.close(false, '', false, LCID);finallyxla.Quit;end;end; //----------------------------------------------------------------------- procedure FillByRow; var xla : _Application;xlw : _Workbook;CellFrom : string;CellTo : string;i,j : integer;Row : array[1..10] of variant;LCID : integer;begin xla := CoApplication.Create;LCID := GetUserDefaultLCID;tryxlw := xla.Workbooks.Add(xlWBATWorksheet, LCID);for i:=1 to ROWS do beginfor j:=1 to 10 do beginRow[j] := i+j;end;CellFrom := 'A' + InttoStr(i);CellTO := 'J' + InttoStr(i);xla.Range[CellFrom, CellTo].Value := VarArrayOf(Row);end;xlw.close(false, '', False, LCID);finallyxla.Quit;end;end; //----------------------------------------------------------------------- procedure FillBySheet; var xla : _Application;xlw : _Workbook;CellFrom : string;CellTo : string;i,j : integer;range : Variant;row : array [1..10] of Variant;LCID : integer;begin xla := CoApplication.Create;LCID := GetUserDefaultLCID;tryxlw := xla.Workbooks.Add(xlWBATWorksheet, LCID);Range := VarArrayCreate([1, ROWS], varVariant);for i:=1 to ROWS do beginfor j:=1 to 10 do beginrow[j] := i+j;end;Range[i] := VarArrayOf(row);end;CellFrom := 'A' + InttoStr(1);CellTO := 'J' + InttoStr(ROWS);xla.Range[CellFrom, CellTo].FormulaArray := Range;xlw.close(false, '', False, LCID);finallyxla.Quit;end;end; |
unit sheet; interface uses EXCEL_TLB, windows, sysutils; //------------------------------------------------------------------------- type tExcel = classprivatexla : _Application;xlw : _Workbook;LCID : integer;procedure fSetVisible(Visible : boolean);function fGetVisible : boolean;procedure fSetCell(Cell : string; Value : OLEVariant);function fGetCell(Cell : string) : OleVariant;publicconstructor create;destructor destroy; override;procedure AddWorkBook(Template : OleVariant);procedure SaveAs(filename : string);property Visible : booleanread fGetVisible write fSetVisible;property Cell[Cell : string] : OleVariantread fGetCell write fSetCell;end; //------------------------------------------------------------------------- Procedure CreateSpreadsheet(filename : string); //------------------------------------------------------------------------- implementation //------------------------------------------------------------------------- constructor tExcel.create; begin LCID := GetUserDefaultLCID;xla := CoApplication.Create;end; //------------------------------------------------------------------------- destructor tExcel.destroy; begin xla.Quit;inherited;end; //------------------------------------------------------------------------- procedure tExcel.AddWorkBook(Template : OleVariant); begin xlw := xla.Workbooks.Add(Template, LCID);end; //------------------------------------------------------------------------- procedure tExcel.fSetVisible(Visible : boolean); begin xla.visible[lcid] := Visible;end; //------------------------------------------------------------------------- function tExcel.fGetVisible : boolean; begin result := xla.visible[lcid];end; //------------------------------------------------------------------------- procedure tExcel.fSetCell(Cell : string; Value : OLEVariant); begin xla.Range['A1', 'A1'].Value := value;end; //------------------------------------------------------------------------- function tExcel.fGetCell(Cell : string) : OleVariant; begin result := xla.Range['A1', 'A1'].Value;end; //------------------------------------------------------------------------- procedure tExcel.SaveAs(filename : string); begin xlw.SaveAs(filename,xlWorkbookNormal,'','',False,False,xlNoChange,xlLocalSessionChanges,true,0,0,LCID);end; |
Procedure CreateSpreadsheet(filename : string); var xl : tExcel;begin xl := tExcel.create;tryxl.AddWorkBook('c:\graham\excel\sample2\ssddemo.xlt');xl.visible := true;xl.cell['a1'] := 'тест';xl.SaveAs(filename);finallyxl.free;end;end; |