|
Группа: Пользователи Ранг: Новичок Сообщений: 17
Замечаний: |
На сколько я успел понять покопавшись, на лист Excel можно вставить exe-файл как объект. Подскажите а какой синтаксис в vba , чтобы к этому объекту обратится?
Грубо говоря у меня есть exe-ник, с которым я работаю через командную строку, передавая ему из макроса группу параметров, а задача сейчас вставить его в эксель, чтобы он не потерялся при постоянных перекладываниях экселевского файла.
Сообщение отредактировал Wind — Среда, 03.12.2014, 23:50
2006 г.
Excel.Application
- Как загрузить новый экземпляр Excel или подключиться к запущенному экземпляру EXCEL.EXE? Как отсоединиться от Excel и закрыть его экземпляр?
- Как запустить Excel из консольного приложения или в отдельном потоке (TThread)
- Как получить и настроить папки Excel по умолчанию?
- Чем отличается TExcelApplication от ExcelApplication, TExcelWorkbook от ExcelWorkbook?
- Как узнать локализацию Excel (русская версия или нет)?
- Как сделать, чтобы Excel работал быстрее?
- Как вывести приложение Excel на передний план?
- Как сделать так, чтоб работали английские формулы и форматы чисел в ячейках?
- Что такое Selection?
- Почему не нужно использовать ExcelApplication.Range, а следует ExcelWorksheet.Range?
- Если приложение Excel работает и пользователь выполняет в Excel, одновременно, какие либо действия, то попытка подключится к Excel и вносить в него данные, вызывает ошибку. Как этого избежать?
- Экспорт в Excel длится довольно долго. Как можно уведомлять пользователя о ходе выполнения работы?
- Переношу записанный VBA макрос рисования границы в Excel, но Delphi не знает что такое xlContinuous. Где взять значение этой константы?
- Почему я не могу найти описание компонентов палитры Delphi «Servers» в Help? Где найти документацию по работе с Excel?
- Полезные ссылки
Excel.Application
Excel Range Object
Как загрузить новый экземпляр Excel или подключиться к запущенному экземпляру EXCEL.EXE? Как отсоединиться от Excel и закрыть его экземпляр?
Для определения, будет ли запущен новый экземпляр Excel.Application или присоединение к уже запущенному, используется свойство TExcelApplication.ConnectKind. По умолчанию это свойство имеет значение ckRunningOrNew (константы определены в unit OleServer). Однако рекомендуется, если нет на то особой надобности, всегда запускать новый экземпляр Excel.Application во избежание конфликтов с запущенным раннее экземпляром Excel.Application. Свойство TExcelApplication.AutoQuit в конструкторе устанавливается по умолчанию в False (только в модуле ExcelXP в True) — это значит, что если вы хотите при отсоединении завершить работу Excel (закрыть), то нужно вызвать метод TExcelApplication.Quit или установить свойство TExcelApplication.AutoQuit равным True.
Delphi:
var XL: TExcelApplication; begin // запускаем новый экземпляр Excel'я XL := TExcelApplication.Create(nil); try XL.ConnectKind := ckNewInstance; XL.Connect; // подключение XL.AutoQuit := False; // по умолчанию это свойство True только в unit ExcelXP XL.Visible[lcid] := True; // здесь работаем с Excel'ем finally // отсоединяемся XL.UserControl := True; // отдадим управление пользователю XL.Quit; // закрыть Excel XL.Disconnect; FreeAndNil(XL); end;
C#:
private Excel.Application StartExcel(bool asNewInstance)
{
Excel.Application XL = null;
if (!(asNewInstance)) {
try {
XL = System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application")
as Excel.Application;
}
catch {
// XL = null;
}
}
if (XL == null) XL = new Excel.Application();
if (XL.Workbooks.Count == 0) XL.Workbooks.Add(Type.Missing);
XL.Visible = true;
return XL;
}
private void FinishExcel(Excel.Application XL)
{
if (XL != null) {
XL.ScreenUpdating = true;
if (! XL.Interactive) XL.Interactive = true;
XL.UserControl = true;
if (XL.Workbooks.Count == 0) {
XL.Quit();
}
else {
if (! XL.Visible) XL.Visible = true;
XL.ActiveWorkbook.Saved = true;
}
// System.Runtime.InteropServices.Marshal.ReleaseComObject(XL);
XL = null;
GC.GetTotalMemory(true); // вызов сборщика мусора
// Пока не закрыть приложение EXCEL.EXE будет висеть в процессах
}
}
How to automate Microsoft Excel from Microsoft Visual C# .NET
How to use Visual C# to automate a running instance of an Office program
GC.GetTotalMemory Method
GC Class
Как запустить Excel из консольного приложения или в отдельном потоке (TThread)
Консольное приложение и дочерний поток (класс TThread) не предполагают работу с COM сервером, как это сделано в главном потоке для Application в VCL. Для того чтобы все работало, необходим вызов функции WinAPI CoInitialize.
{$APPTYPE CONSOLE} // для консольного приложения var NeedToUninitialize: Boolean; … begin // NeedToUninitialize := Succeeded(CoInitialize(nil)); NeedToUninitialize := Succeeded(CoInitializeEx(nil, COINIT_MULTITHREADED)); try // здесь работаем с Excel'ем finally if NeedToUninitialize then CoUninitialize; end; end.
Отличие при работе в Thread — весь код работы должен быть помещен в метод TThread.Execute.
Для C# ничего дополнительно вызывать не нужно — все работает, что для WinForms, что для Console, что для объекта класса Thread().
CoInitializeEx
OleInitialize
Как получить и настроить папки Excel по умолчанию?
По умолчанию все открываемые и сохраняемые документы находятся в папке «%USERPROFILE%Мои документы» (Personal). Ссылка на эту папку содержится в свойстве TExcelApplication.DefaultFilePath (read/write). Для чтения и записи в другие папки используйте полный путь к файлу книги.
Delphi:
(XL.ActiveSheet as _Worksheet).Range['A1', EmptyParam].Formula := Format('DefaultFilePath: %s', [XL.DefaultFilePath[lcid]]);
DefaultFilePath Property
How to: Set the Default Save Path for Workbooks
Чем отличается TExcelApplication от ExcelApplication, TExcelWorkbook от ExcelWorkbook?
Все отличие TExcelApplication от ExcelApplication в том, что первый — наследник TOleServer. Это расширяет возможности для выбора способа подключения/отключения COM-сервера Excel и упрощает работу с событиями Excel.Application. Получить интерфейс ExcelApplication всегда можно из свойства TExcelApplication.DefaultInterface (DefaultInterface — штатное свойство всех наследников класса ToleServer).
Как узнать локализацию Excel’я (русская версия или нет)?
Для Delphi это можно почитать здесь.
C#:
oSheet.get_Range("A1", Type.Missing).Value2 =
XL.LanguageSettings.get_LanguageID(
Microsoft.Office.Core.MsoAppLanguageID.msoLanguageIDUI);
LanguageSettings Object
Как сделать, чтобы Excel работал быстрее?
Для ускорения работы с Excel’ем можно сделать следующие шаги:
Delphi:
// запретить перерисовку экрана XL.ScreenUpdating[lcid] := False; // отменить автоматическую калькуляцию формул XL.Calculation[lcid] := xlManual; // отменить проверку автоматическую ошибок в ячейках (для XP и выше) with XL.ErrorCheckingOptions do begin BackgroundChecking := False; NumberAsText := False; InconsistentFormula := False; end;
Не использовать метод Select, и, как следствие, свойство Selection (смотрите дальше).
Существенно повышается скорость, если вместо записи в каждую ячейку использовать запись из VarArray (смотрите дальше про объект Range). В Demo-проекте есть тест затраченного времени для различных методов записи.
Так как основное время работы с Excel’ем затрачивается на перерисовку (установка отступов для страницы, размеров строк и столбцов, атрибуты шрифтов и т.д.), то лучше всего использовать заранее подготовленный шаблон.
Как вывести приложение Excel на передний план?
Для «выноса» приложения Excel на передний план просто вызовите метод Visible объекта ExcelApplication.
Delphi:
XL.Visible[lcid] := True;
// Этот способ только для Excel версии XP и выше
SetForegroundWindow(XL.Hwnd);
C#:
XL.Visible = true;
Как сделать так, чтоб работали английские формулы и форматы чисел в ячейках?
Решение для Delphi здесь «Русский Excel и установка NumberFormat»
К сожалению, при работе с русским Excel’ем из C# проблемы те же, но, к счастью, решаются проще — через CultureInfo:
C#:
int savedCult = Thread.CurrentThread.CurrentCulture.LCID;
try {
// установим английскую "культуру"
Thread.CurrentThread.CurrentCulture = new CultureInfo(0x0409, false);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(0x0409, false);
// здесь работаем с Excel'ем, при чем работают английские формулы, DataFormat
// и колонтитулы в PageSetup
finally {
// восстановим пользовательскую "культуру" для отображения всех данных в
// привычных глазу форматах
Thread.CurrentThread.CurrentCulture = new CultureInfo(savedCult, true);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(savedCult, true);
}
Русский Excel и установка NumberFormat
How to: Set the Culture and UI Culture for Windows Forms Globalization
Что такое Selection?
Как пишут в «Best Practices for Setting Range Properties»: «Код, использующий Selection, сгенерирован записью макроса Excel, часто используется для обнаружения объекта или метода, который будет работать. Это хорошая идея, за исключением того, что записанный макрос не оптимизирован для пользователя. Обычно Excel при записи макроса использует Selection и изменяет выбор объекта при записи какой либо задачи».
Т.е. использование Selection не является обязательным и даже не рекомендуется для разработчика. Цитата оттуда же: «На практике вызывайте метод Select объекта только тогда, когда твердо намерены изменить выбранный пользователем элемент. Вы можете никогда не использовать метод Select просто потому, что это вам удобно, как разработчику. Если вы устанавливаете свойства объекта Range, у вас всегда есть альтернатива. Отказ от метода Select не только делает ваш код быстрее, но и порадует пользователей вашей программы (it makes your users happier)». Эта тема еще затронута здесь.
Selection Property
Почему не нужно использовать Excel.Application.Range, а следует ExcelWorksheet.Range?
Использование ExcelApplication.Range позволяет работать только с активным листом активной книги. Если вы открываете по ходу работы еще одну книгу или делаете активным другой лист в книге (например, добавляете новый лист), то данные будут вноситься именно в активный в данный момент лист. Чтоб не попасть в неудобную ситуациюб всегда используйте объект Range объекта ExcelWorksheet. Это не только обезопасит ваш код от попадания «куда Бог пошлет», но и позволит записывать данные сразу в несколько листов и даже книг без изменения ActiveSheet и ActiveCell.
Если приложение Excel работает и пользователь выполняет в Excel, одновременно, какие либо действия, то попытка подключится к Excel и вносить в него данные, вызывает ошибку. Как этого избежать?
При работе с запущенным приложением Excel, он может быть занят, если в это время пользователь редактирует значение в ячейке, или в нем открыто какое-либо модальное диалоговое окно (например, «Открытие документа»). Чтобы обойти эту ситуациюб всегда запускайте новую копию Excel.Application и устанавливайте свойство Interactive в False, что запретит пользователю что-либо делать в Excel’е или закрыть запущенный экземпляр Excel.Application:
Delphi:
XL := TExcelApplication.Create(nil); try XL.ConnectKind := ckNewInstance; XL.Connect; XL.Interactive[lcid] := False; // запрещаем работу пользователю с нашим экземпляром Excel'я XL.Visible[lcid] := True; // работать здесь finally // не забыть разрешить пользователю доступ к Excel'ю! XL.UserControl := True; XL.Interactive[lcid] := True; XL.Disconnect; FreeAndNil(XL); end;
The action cannot be completed because Microsoft Office Excel is busy
Interactive Property
Экспорт в Excel длится довольно долго. Как можно уведомлять пользователя о ходе выполнения работы?
Чтобы пользователь не подумалб что во время экспорта данных в Excel ваша программа и Excel «висит», лучше уведомлять его о ходе работы. Т.к. обновление экрана занимает довольно много времени и так довольно длительного процесса экспорта (хотя все же стоит подумать, как этот процесс оптимизировать и ускорить), то лучшим выходом из этой ситуации является показ этапов работы в свойстве ExcelApplication.StatusBar:
Delphi:
XL.DisplayStatusBar[lcid] := True; // покажем StatusBar, если его не было видно XL.StatusBar[lcid] := 'Читаем'; // XL.StatusBar[lcid] := 'Пишем'; // XL.StatusBar[lcid] := 'Считаем'; // XL.StatusBar[lcid] := False; // уберем наше последнее сообщение
C#:
XL.DisplayStatusBar = true; // XL.StatusBar = "Текст в статусбаре"; // XL.StatusBar = false; // "Готово"
DisplayStatusBar Property
StatusBar Property
Переношу записанный VBA макрос рисования границы в Excel, но Delphi не знает что такое xlContinuous. Где взять значение этой константы?
Это всего лишь значит, что вы пользуетесь в Delphi поздним связыванием. Добавьте в uses ExcelXP или Excel2000. Для C# нужно полностью указывать namespace, тип и имя этой константы, например Excel.XlLineStyle.xlContinuous.
Microsoft.Office.Interop.Excel Namespace
Почему я не могу найти описание компонентов палитры Delphi «Servers» в Help’е? Где найти документацию по работе с Excel’ем?
Компоненты на палитре «Servers» — это «обертка» (wrapper) популярных COM-серверов Microsoft. Для описания их объектной модели, свойств и методов используйте поставляемый с Microsoft Office VBA Help или ищите информацию на MSDN (также смотрите «Полезные ссылки» в конце).
Полезные ссылки
Microsoft Excel Object Model
Automating Excel Using the Excel Object Model
Office Development — Excel
Migrating Excel VBA Solutions to Visual Studio 2005 Tools for Office
Converting Microsoft Office VBA Macros to Visual Basic .NET and C#
Microsoft Excel 2003 Language Reference
Understanding the Excel Object Model from a .NET Developer’s Perspective
Microsoft.Office.Interop.Excel Namespace
Excel Objects
Code Examples for Excel (C#)
Серег, ТС на Офис, даже не, на Эксель шипит, никак дескать не поставить, убогому. А ты ему:
| Цитата |
|---|
| Doober написал: Покупаете лицензию на Essential Studio , устанавливаете. |
P.S. лет десять-пятнадцать назад нет кишил просто такими «искателями» оболочек ехе для экса. Я думал все уже повывелись, ан нет, есть еще упорные в нестройных рядах юзверей. А логика бьет наповал: я не могу установить офис на работе, но напишу на ВБ(ага, напишет) и там опять же инсталлировать сей шедевр придется, гы..
Запуск нового экземпляра Excel

Краткое описание
В статье описывается пример команды и скрипта для запуска нового (параллельного) приложения Excel, позволяющего работать независимо от состояния исходного файла.
Подробное описание
Приходилось ли вам, работая в Excel, сталкиваться с ситуацией, когда пересчет формул в вашем файле, работа макроса или какое-либо обновление/загрузка данных «подвешивали» Excel на столько, что либо идти пить чай в ожидании окончания обновления либо закрывать приложение через диспетчер задач?
Кто сталкивался, знает — ситуация досадная, т.к. работа может простаивать из-за того, что приходится ждать окончания запущенного процесса excel прежде чем появится возможность работать с другими excel файлами.
В справке Microsoft на эту тему есть вполне рабочее решение — запуск нового экземпляра (отдельного процесса) Excel из командной строки. Например так: excel.exe /x «C:UsersAdminDesktopМойФайл.xlsx» или для открытия пустого файла: excel.exe /x
Указанное выше решение очень даже рабочее. С одной лишь оговоркой. Новое приложение (новый процесс) станет доступно для работы только, когда «отвиснет» старое. Либо вам нужно сперва запустить новый экземпляр Excel одной из указанных выше команд и только потом запускать ваш «тяжелый» пересчет в исходном файле.
Если же так произошло, что важный пересчет уже запущен, а Excel нужен срочно, предлагаю небольшой vbs скрипт (см. файл выше). Просто распакуйте файл «new_excel.vbs» из архива и запустите его двойным кликом или через Enter. Запускать скрипт можно в любое время, не дожидаясь окончания работы (доступности) исходного файла.
Указанный выше синтаксис командной строки или код скрипта можно очень легко применять в макросах VBA. Тем самым, делая интересные в плане реализации вещи независимо от занятости/загруженности исходного файла (потока данных).
Также важно не забывать, что отдельный процесс предполагает и иные правила работы с файлами. Так например, простой копипаст формул между файлами уже работать не будет (формула скопируется как значение). Копирование листа в другую книгу также не сработает (в мастере копирования вы просто не увидите другие открытые книги). Если на уровне VBA эти тонкие моменты можно учесть и обойти, то в обычной работе с Excel этого не избежать.
Как один из плюсов работы в отдельном процессе — через диспетчер задач можно смело закрывать зависший процесс excel, другие файлы (запущенные в отдельных процессах) при этом не пострадают.
Подготовка
Откроем нашу среду разработки Delphi (в моем случае это Delphi 2010). Создадим новый проект. Должен сказать, что работа с Excel происходит через объекты COM. Поэтому нам надо подключить в раздел
USES
нашего проекта модуль
COMObj
. Так же нам понадобится модуль
ActiveX
. Это будет выглядеть примерно вот так:
unit Unit1; interface uses Windows, …, ActiveX, COMObj;
Проверка наличия установленного Microsoft Excel в операционной системе
Теперь собственно нам нужно, как писалось выше, определить наличие Excel в системе. Если он не будет обнаружен, то мы сообщим об этом пользователю и завершим программу. Для этого создадим простенькую функцию и объявим её в секции
private
нашей формы
TForm1
:
… private function CheckExcelInstalled(AValue: String): boolean; … function TForm1.CheckExcelInstalled(AValue: String): boolean; var FCLSID: TCLSID; begin Result := (CLSIDFromProgID(PChar(AValue), FCLSID) = S_OK); end;
Функция
CLSIDFromProgID
определена в модуле
ActiveX
и имеет следующее описание:
function CLSIDFromProgID(pszProgID: POleStr; out clsid: TCLSID): HResult;
Данная функция ищет
CLSID
, по соответствующему
ProgID
в реестре, в нашем случае мы ищем «Excel.Application». Если открыть реестр и перейти к ветке:
HKEY_LOCAL_MACHINESOFTWAREClasses
то там можно будет обнаружить много разделов. Среди них есть как раз нужный нам «Excel.Application» (при условии, что данное ПО установлено в системе). К сведению: у этого раздела имеется еще два подраздела:
HKEY_LOCAL_MACHINESOFTWAREClassesExcel.ApplicationCLSID
HKEY_LOCAL_MACHINESOFTWAREClassesExcel.ApplicationCurVer
Параметры функции:
—
pszProgID
: строка, содержащая ProgID.
—
clsid
: получает CLSID.
Возвращаемые значения:
—
S_OK
— CLSID создан успешно.
—
CO_E_CLASSSTRING
— CLSID зарегистрированный для ProgID неверен.
—
REGDB_E_WRITEREGDB
— ошибка записи в реестр.
—
E_OUTOFMEMORY
— нет памяти.
—
E_INVALIDARG
— указывает что один или более аргументов неверны. Стоит проверить правильность строки pszProgID.
—
E_UNEXPECTED
— неизвестная ошибка.
Теперь на событии
OnCreate
формы
TForm1
напишем следующий код:
procedure TForm1.FormCreate(Sender: TObject); begin if not CheckExcelInstalled('Excel.Application') then begin Application.MessageBox(PChar('Для работы программы необходимо ' + 'иметь установленное программное обеспечение Microsoft Excel.'#13#10 + 'Приложение будет закрыто.'), 'Ошибка', MB_ICONERROR); Halt; end; end;
При загрузке приложения ищем наличие Excel в системе. Если не находим, то выводим сообщение пользователю и закрываем программу с помощью метода
Halt
. Если находим, то просто показываем форму.
Проверить, запущен ли Microsoft Excel
Далее давайте кинем на форму одну кнопку TButton. На событии
OnClick
будем писать код работы с Excel. Первое что мы сделаем, это добавим локальную переменную типа
Variant
для доступа к Excel с именем, например,
FExcel
:
Теперь определимся, что мы хотим. Я всегда создавал новый экземпляр экселя, даже если он был уже запущен в системе. Но я это не вы. Поэтому я покажу вам, как можно использовать уже запущенный Excel. Создадим функцию и объявим ее так же в секции
private
:
… private … function CheckExcelRun(AValue: String; var ADest: Variant): boolean; … function TForm1.CheckExcelRun(AValue: String; var ADest: Variant): boolean; begin try ADest := GetActiveOleObject(AValue); Result := true; except Result := false; end; end;
Функция
GetActiveOleObject
определена в модуле
COMObj
и имеет следующее описание:
function GetActiveOleObject(const ClassName: string): IDispatch;
Функция возвращает ссылку на интерфейс
IDispatch
активного OLE-объекта указанного класса. Она использует информацию из таблицы активных объектов OLE (OLE running object table). Идентификатор класса объекта OLE в таблице активных объектов OLE передается в параметре
ClassName
. При невозможности выполнения функции GetActiveOleObject возникает исключение EOleSysError.
Теперь как пользоваться нашей функцией:
procedure TForm1.Button1Click(Sender: TObject); var FExcel: Variant; begin if not CheckExcelRun('Excel.Application', FExcel) then Exit; end;
Стоить пояснить. Если в системе запущена программа Excel, то функция
GetActiveOleObject
находит его, при этом функция
CheckExcelRun
возвращает
TRUE
. Ссылка на интерфейс передается через параметр «var ADest» нашей созданной переменной
FExcel
. Теперь вы можете работать с этим экземпляром Excel. Если же запущенный эксель не найден, то функция
GetActiveOleObject
вызывает исключение, простыми словами выходит ошибка. Поэтому мы поместили эту функцию в блок
try…except…end
. Вот в секции
except
мы присваиваем результат
FALSE
и т.о. выходим из процедуры
Button1Click
с помощью метода
Exit
. Но это все отступление. Давайте не будем искать уже запущенный ексель, а будем создавать новый и по завершению работы с ним корректно закроем его и высвободим память.
Создание нового экземпляра Microsoft Excel
Создать новый экземпляр можно с помощью функции
CreateOleObject
. Давайте сразу напишем шаблон.
procedure TForm1.Button1Click(Sender: TObject); var FExcel: Variant; begin try // Создаем новый экземпляр Excel FExcel := CreateOleObject('Excel.Application'); FExcel.Visible := true; ... // Тут ваш код finally // Если переменная не пустая, то... if not VarIsEmpty(FExcel) then begin // ...отключаем диалог с вопросом сохранять ли файл при выходе или нет FExcel.DisplayAlerts := false; // Закрываем Excel FExcel.Quit; // Присваиваем неопределенный тип, освобождая при этом // процесс excel.exe, чтобы он мог завершиться. Если этого не // сделать, то процесс останется висеть в памяти. FExcel := Unassigned; end; end; end;
Функция
VarIsEmpty
определена в модуле
Variants
и имеет следующее описание:
function VarIsEmpty(const V: Variant): Boolean;
Функция проверяет, определен ли тип значения
Variant
-переменной. Возвращает
TRUE
, если переменная имеет неопределенный тип (Unassigned). Если типу переменной соответствует значение какой-либо константы
VarType
типа
TVarData
, то функция возвращает
FALSE
.
Операции над программой Microsoft Excel из Delphi
Теперь давайте рассмотрим, что вообще можно делать с Excel из Delphi. Операций достаточно много. И все описать просто невозможно. Но если в моем описании не окажется нужного вам метода, то огорчаться не стоит. Методы можно узнать самому. Открываете Excel. Затем в меню
Сервис – Макрос – Начать запись
. Там жмем ОК и выполняем необходимые нам операции в Excel. Когда закончите, жмем на
Стоп
. Затем нажимаем комбинацию клавиш
Alt+F11
и перед нами открывается
редактор Visual Basic
. Вот в нем слева вверху есть древовидный список. В нем находится папка с названием
Modules
. В свою очередь в ней располагаются модули. Вот эти модули и есть ваши макросы. Кликнем два раза на тот модуль, который мы только что записали (если это первая запись, то модуль будет один). И тут будут отображены все ваши действия в виде исходного кода на языке Visual Basic. Вам остается только перевести это дело на Delphi.
По поводу констант. В Delphi придется объявлять их самим. Посмотреть чему они равны можно в том же редакторе Visual Basic. Делается это так. Вписываем любую нужную нам константу в редакторе. Кликаем правой клавишей мыши, чтобы появилось контекстное меню. И там выбираем пункт
«Quick Info»
. При этом будет показана всплывающая подсказка со значением этой константы. Все просто! Единственное оговорюсь. В Visual Basic будет показано так, например:
&HFFFFEFF4
, но Delphi этого не поймет. Надо объявлять в нем так:
$FFFFEFF4
.
Работа с окном (формой) Excel
FExcel.Visible := true;
Делать Excel видимым (True)/не видимым(False). При установке
Visible
в
FALSE
, программа Excel Так же пропадает из панели задач Windows.
FExcel.Application.EnableEvents := false;
Показывать (True)/не показывать(False) системные сообщения Excel. Рекомендую отключать сообщения при построении отчета. А сам код писать после создания экземпляра Excel. Это увеличит скорость создания отчета. Пример:
FExcel := CreateOleObject('Excel.Application'); FExcel.Visible := false; FExcel.Application.EnableEvents := false;
FExcel.DisplayAlerts := false;
Показывать (True)/не показывать(False) предупреждающие сообщения.
FExcel.WindowState := xlMaximized;
Состояние окна Excel:
const xlMaximized = $FFFFEFD7 (или -4137)
— развернуть Excel на весь экран.
const xlNormal = $FFFFEFD1 (или -4143)
— восстановить Excel.
const xlMinimized = $FFFFEFD4 (или -4140)
— свернуть Excel на панель задач.
FExcel.ScreenUpdating := false;
Включить (True)/отключить (False) перерисовку окон. Используется для ускорения работы макроса, т.к. в это время не обновляется экран. Я в своих проектах не использовал данный метод, но возможно построение отчета будет выполняться быстрее, если отключить обновление окон Excel. После построения отчета перерисовку окон можно будет включить обратно.
Работа над книгой (Workbooks)
FExcel.Workbooks.Open(path);
Открытие существующей книги (где path — путь к фалу). Функция Open описана так:
function Open( const Filename: String; UpdateLinks: Variant; ReadOnly: Variant; Format: Variant; Password: Variant; WriteResPassword: Variant; IgnoreReadOnlyRecommended: Variant; Origin: Variant; Delimiter: Variant; Editable: Variant; Notify: Variant; Converter: Variant; AddToMru: Variant ): Workbook;
FileName
— обязательный элемент. Имя открываемого файла, желательно с полным путем, иначе Excel будет искать этот файл в каталоге по умолчанию;
UpdateLinks
— Необязательный параметр. Определяет способ обновления связи в открываемом файле. Если данный аргумент отсутствует, то пользователю будет выдан запрос на определение способа обновления связей. Данный параметр имеет следующие допустимые значения:
0 – никакие связи не обновляются;
1 – обновляются внешние ссылки, но не обновляются удаленные ссылки;
2 – обновляются удаленные ссылки, но не обновляются внешние ссылки;
3 – обновляются оба типа ссылок
ReadOnly
— необязательный параметр. Если файл имеет атрибут только для чтения, то при открытии его в Excel выдается соответствующее предупреждение*. Чтобы его игнорировать, передайте в качестве данного параметра True.
Format
— необязательный параметр. При открытии текстового файла этот параметр определяет вид символов-разделителей. Ниже представлены допустимые значения данного аргумента:
1 – символы табуляции;
2 – запятые;
3 – пробелы;
4 – точка с запятой;
5 – разделители отсутствуют;
6 – вид разделителя определяется пользователем (с помощью параметра Delimiter).
Password
— необязательный параметр, задающий строку пароля, необходимого для открытия защищенной рабочей книги. Если при открытии защищенной книги данный аргумент отсутствует, то пользователю будет выдан запрос на ввод пароля*.
WriteResPassword
— необязательный параметр. Предназначен для задания пароля, необходимого для записи в рабочую книгу. Если при открытии защищенной книги данный аргумент отсутствует, то пользователю будет выдан запрос на ввод пароля*.
IgnoreReadOnlyRecommended
— необязательный параметр. В случае задания ему значения True этот аргумент позволяет устранить вывод сообщения с рекомендацией открытия книги только для чтения (в том случае, если данная рабочая книга была сохранена с параметром Read-Only Recommended).
Origin
— необязательный параметр. При открытии текстового файла этот параметр указывает, где был создан этот файл, что необходимо для правильного распознавания страницы кодировки. Значениями данного аргумента может быть одна из констант: xlMacintosh, xlWindows или xlMSDOS**. Если данный аргумент отсутствует, то используются текущие параметры операционной системы.
Delimiter
— необязательный параметр. Если открывается текстовый файл и параметр Format имеет значение, равное 6, то этот аргумент определяет символ-разделитель.
Editable
— необязательный параметр. Если файл является файлом MS Excel 4.0, то этот параметр при задании ему значения True позволяет открыть надстройку как видимое окно. По умолчанию ему присвоено значение False.
Notify
— необязательный параметр. Если файл не может быть открыт для записи, то при задании данному аргументу значения True файл будет добавлен в список уведомления. Если данный аргумент равен False или отсутствует, то открыть файл будет невозможно.
Converter
— необязательный параметр. Предназначен для определения индекса фильтра, который будет использован при открытии данного файла. Если фильтр не сможет распознать формат файла, то будут последовательно использованы все доступные фильтры.
AddToMRU
— необязательный параметр типа Variant. Если данный параметр имеет значение True, то рабочая книга будет добавлена в список недавно использованных файлов. По умолчанию ему присвоено значение False.
Примечание:
* Сообщения будут выведены на экран, если вы не отключили их с помощью:
FExcel.Application.EnableEvents := false;
Показывать (True)/не показывать(False) системные сообщения Excel.
** Delphi не знает о существовании констант, поэтому чтобы посмотреть их значения, нужно воспользоваться средствами VBA. Эти константы соответственно равны 1, 2 и 3.
***
FExcel.SheetsInNewWorkbook := X;
Задать количество страниц в книге, где X — это количество страниц. Диапазон значений 1..255. Данный метод применяется только с
FExcel.Workbooks.Add;
и в коде Delphi пишется перед методом Add.
FExcel.Workbooks.Add(path);
// path — путь к фалу
Создание новой книги. Причем создается стандартная книга с тремя листами. В этом методе можно указать стандартный тип шаблона Excel. Если же в нем указать имя (с полным путем) подготовленного файла (шаблоном может быть и «обычный» файл XLS, а не только файл XLT), то можно открыть книгу на диске как шаблон.
FExcel.Workbooks.Add(Template);
Template — Необязательный параметр. Этот параметр определяет, как будет создана рабочая книга. Если этот параметр будет иметь значение строки, определяющей имя файла (включая путь) существующей рабочей книги, то создается рабочая книга с использованием данного файла как шаблона. В случае когда данный параметр является одной из констант:
xlWBATExcel4IntlMacroSheet = 4;
xlWBATExcel4MacroSheet = 3;
xlWBATWorksheet = $FFFFEFB9 (или -4167);
xlWBATChart = $FFFFEFF3 (или -4109);
Создаваемая книга будет содержать один лист соответствующего типа. В том случае, если этот параметр отсутствует, то создается рабочая книга с количеством листов, определяемым значением свойства
SheetslnNewWorkbook
.
***
FExcel.Workbooks[1].SaveAs(path);
// path — путь к фалу
Сохранить книгу как… Чтобы укоротить код можно создать переменную
FWorkbook
типа
Variant
и присвоить ей ссылку либо на первую[1] книгу, либо на вновь созданную:
FWorkbook := FExcel.Workbooks[1];
либо
FWorkbook := FExcel.Workbooks.Add;
Тогда сохранение может выглядеть вот так:
FWorkbook.SaveAs(path);
// path — путь к фалу
Функция SaveAs описана так:
function SaveAs( FileName: Variant; FileFormat: Variant; Password: Variant; WriteResPassword: Variant; ReadOnlyRecommended: Variant; CreateBackup: Variant; AccessMode: Variant; ConflictResolution: Variant; AddToMru: Variant; TextCodePage: Variant; TextVisualLayout: Variant ): Workbook;
FileName
— необязательный параметр. Задает строку, определяющую имя сохраняемого файла. Можно указать полный путь или только имя файла (в этом случае файл будет сохранен в текущей папке).
FileFormat
— необязательный параметр. Данный параметр задает формат файла. Его значением может быть одна из констант, описанных в
таблице 1
. В том случае, если файл уже существует, в качестве его формата по умолчанию будет назначен формат, использовавшийся при его предыдущем сохранении.
Формат Константа Книга MS Excel xlWorkbookNormal Web-страница xlHTML Шаблон xlTemplate Текстовые файлы (с разделителями табуляции) xlTextWindows Текст Юникод xlUnicodeText Книга MS Excel 5.0/95 xlExcel7 Книга MS Excel 95/97/2000 xlExcel9795 CSV (разделители – запятые) xlCSVWindows Файл MS Excel 4.0 xlExcel4 Файл MS Excel 3.0 xlExcel3 Файл MS Excel 2.1 xlExcel2 Книга MS Excel 4.0 xlExcel4Workbook WK4 (1-2-3) xlWK4 WK3, FM3 (1-2-3) xlWK3FM3 WK3 (1-2-3) xlWK3 WK1, FMT (1-2-3) xlWK1FMT WK1, ALL (1-2-3) xlWK1ALL WK1 (1-2-3) xlWK1 WKS (1-2-3) xlWKS WQ1 (Quattro Pro/Dos) xlWQ1 DBF4 (dBase IV) xlDBF2 DBF3 (dBase III) xlDBF3 DBF2 (dBase II) xlDBF4 Форматированный текст (разделители – пробелы) xlTextPrinter Текст (Macintosh) xlTextMac Текст (MS-DOS) xlTextMSDOS CSV (Macintosh) xlCSVMac CSV (MS-DOS) xlCSVMSDOS DIF (Data Interchange Format) xlDIF SYLK (Symbolic Link) xlSYLK Надстройка MS Excel xlAddln
Таблица 1 — Форматы файлов MS Excel 2000 и соответствующие им константы.
Password
— необязательный параметр. Данный параметр определяет защитный пароль для сохраняемого файла. Пароль определяется строкой, содержащей не более 15 символов.
WriteResPassword
— необязательный параметр. Предназначен для задания строки, определяющей пароль для сохранения файла в качестве файла только для чтения. При последующем открытии файла будет выдан запрос на ввод этого пароля, и если он не будет введен, то файл будет открыт в режиме только для чтения.
ReadOnlyRecommended
— необязательный параметр. В случае присвоения ему значения True, последующее открытие файла на экране будет сопровождаться сообщением, говорящим о том, что этот файл рекомендуется открыть в режиме только для чтения.
CreateBackup
— необязательный параметр. Определяет возможность создания резервного файла (значение True).
AccessMode
— необязательный параметр. Этот параметр определяет режим доступа к рабочей книге и может иметь одно из следующих значений:
xINoChange – режим доступа не изменяется (равно 1);
xlShared – общие листы (равно 2);
xlExclusive – монопольный доступ (равно 3).
ConflictResolution
— необязательный параметр. Определяет способ разрешения конфликтов в том случае, если книга имеет общие листы. Значением данного свойства может быть значение одной из констант:
xlUserResolution — отображает окно диалога для разрешения конфликтов (равно 1);
xlLocalSessionChanges — автоматически принимаются изменения локального пользователя (равно 2);
xlOtherSessionChanges — принимаются другие изменения вместо изменений локального пользователя (равно 3).
AddToMru
— необязательный параметр. Позволяет поместить сохраняемый файл в список сохраненных файлов в меню Файл (File). Для реализации этой возможности значение этого аргумента должно равняться True.
TextCodePage
— необязательный параметр. В локализованной версии MS Office не используется.
TextVisualLayout
— необязательный параметр. В локализованной версии MS Office не используется.
***
FWorkbook.Save;
Если книга была открыта, то файл перезапишется. Если была создана новая книга, то будет задан вопрос о сохранении файла. Если вы нажмете «Нет», то будет вызвано исключение.
FWorkbook.Close;
Закрыть книгу. При этом если Excel видимый, то появится диалог с вопросом, хотите ли вы сохранить файл.
Функция Close описана так:
function Close( SaveChanges: Variant; FileName: Variant; RouteWorkbook: Variant ): Workbook;
SaveChanges
— Необязательный элемент. Если данный параметр опущен, то будет выдан запрос на сохранение файла. Если равен
FALSE
, то книга закроется без сохранения и каких-либо оповещений, даже при установленном параметре
FileName
. Если равен
TRUE
, то сразу появится проводник с предложением выбрать место, куда сохранить файл. При установленном параметре FileName, книга будет сохранена без появления каких-либо диалогов.
FileName
— Необязательный элемент. Данный параметр определяет имя файла, в который будут записаны изменения.
RouteWorkbook
— Необязательный элемент. Если он имеет значение True, то рабочая книга будет послана следующему получателю.
Примечание:
если файл уже существует, то тогда будет выведен диалог с вопросом о перезаписи файла.
Пример:
// Отключаем предупреждающие сообщения, // в нашем случае чтобы не было вопроса о том, // перезаписывать ли файл, если таковой существует FExcel.DisplayAlerts := false; // Сохраняем книгу в файл "123.xls" на диск D: FWorkbook.Close(true, 'D:123.xls');
Установка параметров страницы, предварительный просмотр и печать
FExcel.Workbooks[1].WorkSheets[1] .Name := ‘Отчёт’;
Присваиваем первому листу в первой книге имя «Отчет». Если будем работать с самим листом, то чтобы не писать много кода мы можем просто объявить новую переменную, например,
FSheet
типа
Variant
:
procedure TForm1.Button1Click(Sender: TObject); var FExcel, FSheet: Variant; begin try ... // Тут ваш код finally ... // Обязательно! нужно все созданные Variant-переменные // очищать перед выходом FSheet := Unassigned; FExcel := Unassigned; ... end; end;
Примечание
: в принципе Delphi сама следит за корректным удалением переменных, но я считаю будем правильным сделать это вручную. Не стоит полагаться на систему.
И присвоим ей ссылку на наш Лист1 первой книги:
FSheet := FExcel.Workbooks[1].WorkSheets[1]; FSheet.Name := 'Отчёт';
Вот так вот будет проще. Теперь мы будет обращаться уже к переменной
FSheet
, а не к
FExcel
.
FSheet.PageSetup.Orientation := 2;
Ориентация страницы (1 – книжная, 2 – альбомная).
FSheet.PageSetup.LeftMargin := X;
Отступ от левого края страницы
FSheet.PageSetup.RightMargin := X;
Отступ от правого края страницы
FSheet.PageSetup.TopMargin := X;
Отступ от верхнего края страницы.
FSheet.PageSetup.BottomMargin := X;
Отступ от нижнего края страницы.
FSheet.PageSetup.HeaderMargin := X;
Высота верхнего колонтитула страницы.
FSheet.PageSetup.FooterMargin := X;
Высота нижнего колонтитула страницы.
Где X — это отступ в пикселях. Можно в принципе воспользоваться функцией перевода из, например, сантиметров в пиксели. Делается это так:
FSheet.PageSetup.BottomMargin := FExcel.Application.CentimetersToPoints(1.5);
Это будет полтора сантиметра, а как там переводится в пиксели это не наша забота.
FSheet.PageSetup.Zoom := false (или значение в процентах Z);
Масштаб. Принимает следующие значения:
Z
— «Установить Z% от натуральной величины», где X – это количество процентов. Т.е. если вы решите включить масштабирование, то вам необходимо вместо
FALSE
подставить число, например: FSheet.PageSetup.Zoom := 100; (что означает 100%).
FALSE
— «Разместить не более чем на: X стр. в ширину и Y стр. в высоту, где:
FSheet.PageSetup.FitToPagesWide := 1;
Количество страниц в ширину (X).
FSheet.PageSetup.FitToPagesTall := 100;
Количество страниц в высоту (Y).
FSheet.PageSetup.CenterFooter := ‘Стр. &С из &К’
;
Центральный нижний колонтитул. В нем будет информации о номере страницы из всего страниц. Данные переменные (&C, &K и т.п.) описаны в справочнике самого Excel. Аналогично:
FSheet.PageSetup.LeftFooter:=’Левый нижний колонтитул’;
FSheet.PageSetup.RightFooter:=’Правый нижний колонтитул’;
FSheet.PageSetup.LeftHeader:=’Левый верхний колонтитул’;
FSheet.PageSetup.CenterHeader:=’Центральный верхний колонтитул’;
FSheet.PageSetup.RightHeader:=’&7Правый верхний колонтитул’;
*
Примечание:
*для изменения размера шрифта добавьте к колонтитулу управляющий символ «&» и размер шрифта, в нашем случае 7
// const xlAutomatic = $FFFFEFF7 (или -4105)
FSheet.PageSetup.FirstPageNumber := xlAutomatic;
Номер первой страницы. В данном случае «Авто».
FSheet.PageSetup.Order := 1;
Последовательность вывода страниц на печать (1 — вниз, затем вправо; 2 — вправо, затем вниз).
FSheet.PrintPreview;
Предварительный просмотр страницы. Если вы не продолжите печать, а нажмете «Отмена», то будет вызвано исключение.
Примечание
: Excel, перед выполнением этой команды, обязательно должен быть видимым (FExcel.Visible := true;).
FSheet.PrintOut;
Вывод страницы на печать. Функция PrintOut описана так:
function PrintOut( From: Variant; To: Variant; Copies: Variant; Preview: Variant; ActivePrinter: Variant; PrintToFile: Variant; Collate: Variant ): Workbook;
From
— необязательный параметр. Задает страницу, с которой начинается печать. Если этот аргумент отсутствует, то печать начинается с первой страницы.
To
— необязательный параметр. Задает последнюю печатаемую страницу. Если этот аргумент отсутствует, то печать продолжается до последней страницы.
Copies
— необязательный параметр. Задает количество печатаемых копий.
Preview
— необязательный параметр, принимающий одно из двух значений:
TRUE
— приводит к выводу перед печатью окна предварительного просмотра;
FALSE
(значение по умолчанию) — печать производится без предварительного просмотра.
ActivePrinter
— необязательный параметр. Задает имя активного принтера.
PrintToFile
— необязательный параметр. Если данный параметр имеет значение True, то производится печать в файл. При этом пользователю выдается запрос на ввод имени файла.
Collate
— необязательный параметр. Если ему задать значение True, то копии будут объединены.
Пример:
FExcel.Application.EnableEvents := true; FExcel.DisplayAlerts := true; FExcel.Visible := true; FSheet.PrintOut(1, 2, 1, False, PrintToFile := True)
Печатаем с 1 по 2 страницы, одну копию, без предварительного просмотра в файл. Заметьте, что мы пропустили параметр ActivePrinter. Мы просто объявили PrintToFile := True.
***
Статья не окончена. Продолжение следует…
При составлении справочника я использовал собственные наработки и информацию со следующих сайтов:
1)
www.taurion.ru/excel
2)
www.superadm.net/index.php?name=pages&op=cat&id=19
3)
www.afalinasoft.com/rus/tips/
4)
www.codenet.ru/progr/delphi/stat/Excel-Export.php
Так же не обошлось без составления макросов в редакторе Visual Basic и последующим переводом кода из VBA в среду разработки Delphi 2010.


