Видимо любители экономить килобайты оперативной памяти могут меня закидать помидорами или ещё чем по-хуже, но все-таки я скажу, что интеграция приложений (мегабайты оперативы) – это большой плюс нынешней разработки приложений.
Как ни крути, а время DOS и килобайтов оперативной памяти прошло. Врядли кто-то всерьез сейчас задумывается над тем куда это с винчестера пропал мегабайт? Да и использование в своих приложениях функциональности программ, которых ты не писал, но которые выполняют что-то лучше – это всё-таки больший прогресс, нежели корпеть год-два над программой, а потом узнать, что время-то прошло.
'
'
Итак, цель сегодняшней статьи – поделиться с Вами опытом работы с Microsoft Excel в приложениях, написанных на Delphi.
Вспомнился сейчас один случай. Когда я только начинал работать по своей специальности, пригласили меня написать программу-расчётник для экологов нашего нефтезавода. В принципе ничего серьёзного – программа считает выброс от нагревательной печи и выдает табличку результатов, которую необходимо распечатать и уложить в толстую папку с отчётами. Естественно, что в области разработки подобных приложения я далеко не пионер, поэтому дали взглянуть на аналог будущей программы, который работал ещё под DOS и печатались отчёты на дико скрипящем матричном принтере с 12-ю иголками. Ну посмотрел, элементарная таблица, расчёт немного запутан, но жить можно – начал по-тихоньку писать. И попалась мне тогда на глаза статейка про работу с Excel в Delphi. Вот я и решил попробовать выдавать отчёт не только на форму приложения, а ещё и скидывать весь ход расчёта с формулами и прочим делом в Excel…Надо сказать более сильно детской радости начальника отдела я не видел до сих пор :). Люди, всю жизнь проработавшие в DOS увидели как тот же самый расчёт может выглядеть в современных условиях. Вот теперь при определении технических заданий на каждую новую программу, обязательно присутствует пункт, гласящий, что программа должна передавать данные либо в MS Word либо в MS Excel.Соответственно и цена на разработку возрастает, иногда значительно.
Отсюда можно сделать простой и однозначный вывод – заказчики готовы пожертвовать лишними деньгами только для того, чтобы всё в программе было красиво. Excel может дать вашему приложению ту самую красоту и удобство.
Ну, а для того, чтобы каждый раз не утруждать себя выполнением однотипных операций, я разработал небольшой модуль для работы с Excel. Этот же модуль я в настоящее время дорабатываю под ещё одну задачу, но об этом после. Сегодня основы основ работы с Excel в Delphi.
1. Как проверить установлен ли Excel на компьютере пользователя?
Создаем новый модуль (unit) и подключаем в uses следующие модули:
uses ComObj, ActiveX, Variants, Windows, Messages, SysUtils, Classes;
теперь объявляем глобальную переменную:
var MyExcel: OleVariant;
Одну константу (для удобства):
const ExcelApp = 'Excel.Application';
И пишем простенькую функцию:
function CheckExcelInstall:boolean;
var
ClassID: TCLSID;
Rez : HRESULT;
begin
// Ищем CLSID OLE-объекта
Rez := CLSIDFromProgID(PWideChar(WideString(ExcelApp)), ClassID);
if Rez = S_OK then // Объект найден
Result := true
else
Result := false;
end;
Если функция CLSIDFromProgID находит CLSID OLE-объекта, то, соответственно – Excel установлен.
Но проверка на наличие установленного Excel – это только часть необходимых операций перед началом работы. Другой немаловажной проверкой является проверка на наличие уже запущенного экземпляра Excel. Если этого не делать, то может случиться такая нехорошая ситуация, когда в системе будет зарегистрировано …дцать процессов Excel и все оперативная память волшебным образом утекет “в трубу” – за такое могут и по ушам надавать. Но мы-то свои уши бережем. Пишем вторую функцию проверки.
2. Определяем запущен ли Excel
function CheckExcelRun: boolean;
begin
try
MyExcel:=GetActiveOleObject(ExcelApp);
Result:=True;
except
Result:=false;
end;
end;
Думаю тут лишних объяснений не потребуется? Всё предельно просто – если есть активный процесс Excel, то му просто получаем на него ссылку и можем использовать Excel для своих корыстных целей. Главное – не забыть проверить – может кто-то этот самый Excel забыл закрыть, но это другой момент. Будем считать, что Excel в нашем полном распоряжении.
3. Как запустить Excel?
Одно дело, когда мы получаем в распоряжение уже запущенный Excel, другое – когда Excel требуется запустить из Delphi. Напишем функцию запуска Excel:
function RunExcel(DisableAlerts:boolean=true; Visible: boolean=false): boolean;
begin
try
{проверяем установлен ли Excel}
if CheckExcelInstall then
begin
MyExcel:=CreateOleObject(ExcelApp);
//показывать/не показывать системные сообщения Excel (лучше не показывать)
MyExcel.Application.EnableEvents:=DisableAlerts;
MyExcel.Visible:=Visible;
Result:=true;
end
else
begin
MessageBox(0,'Приложение MS Excel не установлено на этом компьютере','Ошибка',MB_OK+MB_ICONERROR);
Result:=false;
end;
except
Result:=false;
end;
end;
Здесь мы в начале проверяем, установлен ли Excel в принципе и, если он все же установлен, запускам. При этом мы можем сразу показать окно Excel пользователю – для этого необходимо выставить параметр Visible в значение True.
Также рекомендую всегда отключать системные сообщения Excel, иначе, когда программа начнет говорить голосом Excel – пользователь может занервничать.
Переходим к следующему этапу работы – созданию рабочей книги.
4. Создаем пустую рабочую книгу Excel
Для создания пустой рабочей книги я обычно использую вот такую функцию:
function AddWorkBook(AutoRun:boolean=true):boolean;
begin
if CheckExcelRun then
begin
MyExcel.WorkBooks.Add;
Result:=true;
end
else
if AutoRun then
begin
RunExcel;
MyExcel.WorkBooks.Add;
Result:=true;
end
else
Result:=false;
end;
Т.е. сразу проверяю запущен ли Excel и, если он не запущен, то либо запускаю и добавляю книгу, либо просто выхожу – всё зависит от ситуации.
Здесь, думаю, следует напомнить, что, если вы выполните эту функцию, например пять раз, то получите пять открытых рабочих книг и работать с ними как Вам захочется. Главное при этом правильно обратиться к необходимой книге, а для этого можно использовать вот такую функцию:
function GetAllWorkBooks:TStringList;
var i:integer;
begin
try
Result:=TStringList.Create;
for i:=1 to MyExcel.WorkBooks.Count do
Result.Add(MyExcel.WorkBooks.Item[i].FullName)
except
MessageBox(0,'Ошибка перечисления открытых книг','Ошибка',MB_OK+MB_ICONERROR);
end;
end;
Функция возвращает список TStringList всех рабочих книг Excel открытых в данный момент. Обратите внимание, что в отличие от Delphi Excel присваивает первой книге индекс 1, а не 0 как это обычно делается в Delphi при работе, например, с теми же индексами в ComboBox’ах.
Ну, и наконец, после того, как поработали с книгами – их требуется закрыть. Точнее сохранить, а потом уж закрыть.
5. Сохраняем рабочую книгу и закрываем Excel
Для того, чтобы сохранить рабочую книгу, я использовал такую функцию:
function SaveWorkBook(FileName:TFileName; WBIndex:integer):boolean;
begin
try
MyExcel.WorkBooks.Item[WBIndex].SaveAs(FileName);
if MyExcel.WorkBooks.Item[WBIndex].Saved then
Result:=true
else
Result:=false;
except
Result:=false;
end;
end;
Если у Вас открыто 10 книг – просто вызываете функцию 10 раз, меняя значение параметра WBIndex и имени файла и дело в шляпе.
А закрывается Excel вот так:
function StopExcel:boolean;
begin
try
if MyExcel.Visible then MyExcel.Visible:=false;
MyExcel.Quit;
MyExcel:=Unassigned;
Result:=True;
except
Result:=false;
end;
end;
Вот набор тех основных функций с которых начинается вся интеграция Excel в приложения написанные на Delphi. В следующий раз займемся работой с конкретной книгой – научимся записывать и читать данные из книг. А пока я готовлю новый материал, можете узнать, что такое свадьба в одессе.
Файлы для загрузки
Модуль
Related posts:










27 Aug 2009 в 7:09 pm
Работа с Excel в Delphi. Основы основ. | Delphi в Internet…
Рассматриваем основные функции для работы с Excel из Delphi…
28 Aug 2009 в 9:04 am
Если документ простой, но объемный – это будет медленно. А при большом количестве таких документов – жизнь пройдет мимо.
Вывести в Excel можно и проще.
28 Aug 2009 в 9:28 am
Что конкретно будет медленно? :) Запуск Excel или проверка установки Excel? Так тут ускорить процесс негде. Вывода в Excel-то пока в статье нет. Забегая вперед, могу сказать – выводить по-отдельности каждую ячейку – долго, муторно и не верно, но есть вариант как ускорить процесс в несколько десятков, а то и сотен раз.
Да, и ещё – оставлять в комментариях ссылки не стоит. Блог и так DoFollow, кому надо – тот перейдет на ваш блог.
30 Sep 2009 в 8:01 pm
Очень хорошие статьи. Разобрался во всём с первого раза ))) Понравилась схема в mind42 )))
Автору остаётся сказать только спасибо!
30 Sep 2009 в 11:43 pm
не за что, Иван. Всегда рад помочь)
10 Jan 2010 в 12:14 pm
Все хорошо. Но если Excel не запущен – возникает исключение. Что с этим делать? function CheckExcelRun выбрасывает сообщение и все…Хотя по смыслу должно было вернуть False
10 Jan 2010 в 6:20 pm
Странно. Если Excel запущен, то должна создаваться вторая копия приложения без исключений. Код в студию :)
21 Mar 2010 в 12:12 pm
Насчет процедуры CheckExcelRun. Если программа запускается из под Delphi и Excel не запущен, то выскакивает ошибка: Операция GetActiveOleObject недоступна. Если програма запускается не из под Delphi то все в порядке. Наверное эту проблему имел ввиду Алекс. Как решение можно при отладке программы когда возникает исключение нажимать F9.
27 мая 2010 в 9:19 pm
Собственное говоря, а как при таком связывании отследить “сообщения” от Excel? Например, юзер “случайным” образом закрывает рабочую книгу, а программа все еще “хочет” работать с ней.
27 мая 2010 в 9:53 pm
Честно говоря, никогда не задумывался о том как отловить сообщение от Excel и возможно ли то сдела вообще. Обычно в случае работы с книгами Excel или документами Word просто не забывал пользоваться try..except..end :) По-моему в данном случае можно покапаться в событиях Excel.
13 Jun 2010 в 5:13 pm
произвожу экспорт в excel из delphi, все проходит как бы ровно. а неровность заключается в том что после экспорта остается жить процесс “excel.exe”. пытался юзать (Excel.Quit; Excel:=Unassigned;) не хочет помогать. помогите плиз люди добрые
14 Jun 2010 в 12:32 pm
Вы точно один раз запускаете процесс?
Excel.Quit; – выход из приложения
Excel:=Unassigned; – освобождение переменной
Этих строк 100% достаточно, чтобы завершить процесс правильно.
31 Aug 2010 в 12:48 pm
Вобще очень крутая статья! Долго мучался очень я)
Не компилируется функция Save, “FileName:TFileName” вот этот кусок. Откуда это берется?
31 Aug 2010 в 1:15 pm
По сабжу пока не работал, но скорее всего либо перменная FileName уже объявлена, либо тип TFileName из модуля SysUtils, где-то переопределен.
Сообщение компилятора приведите без него только догадки строить остается.
31 Aug 2010 в 2:05 pm
Готовый модуль скачать не удалось… какието глюки на айфолдерс.
Написал по “инструкции” в посте. Все работает без проблем.