Видимо любители экономить килобайты оперативной памяти могут меня закидать помидорами или ещё чем по-хуже, но все-таки я скажу, что интеграция приложений (мегабайты оперативы) - это большой плюс нынешней разработки приложений.
Как ни крути, а время 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. В следующий раз займемся работой с конкретной книгой - научимся записывать и читать данные из книг. А пока я готовлю новый материал, можете узнать, что такое свадьба в одессе.
Файлы для загрузки
Модуль uMyExcel
| Делись! | Загружай! | Плюсуй! |
| | |









27 Авг 2009 в 7:09 пп
Работа с Excel в Delphi. Основы основ. | Delphi в Internet…
Рассматриваем основные функции для работы с Excel из Delphi…
28 Авг 2009 в 9:04 дп
Если документ простой, но объемный — это будет медленно. А при большом количестве таких документов — жизнь пройдет мимо.
Вывести в Excel можно и проще.
28 Авг 2009 в 9:28 дп
Что конкретно будет медленно? :) Запуск Excel или проверка установки Excel? Так тут ускорить процесс негде. Вывода в Excel-то пока в статье нет. Забегая вперед, могу сказать — выводить по-отдельности каждую ячейку — долго, муторно и не верно, но есть вариант как ускорить процесс в несколько десятков, а то и сотен раз.
Да, и ещё — оставлять в комментариях ссылки не стоит. Блог и так DoFollow, кому надо — тот перейдет на ваш блог.
30 Сен 2009 в 8:01 пп
Очень хорошие статьи. Разобрался во всём с первого раза ))) Понравилась схема в mind42 )))
Автору остаётся сказать только спасибо!
30 Сен 2009 в 11:43 пп
не за что, Иван. Всегда рад помочь)
10 Янв 2010 в 12:14 пп
Все хорошо. Но если Excel не запущен — возникает исключение. Что с этим делать? function CheckExcelRun выбрасывает сообщение и все…Хотя по смыслу должно было вернуть False
10 Янв 2010 в 6:20 пп
Странно. Если Excel запущен, то должна создаваться вторая копия приложения без исключений. Код в студию :)
21 Мар 2010 в 12:12 пп
Насчет процедуры CheckExcelRun. Если программа запускается из под Delphi и Excel не запущен, то выскакивает ошибка: Операция GetActiveOleObject недоступна. Если програма запускается не из под Delphi то все в порядке. Наверное эту проблему имел ввиду Алекс. Как решение можно при отладке программы когда возникает исключение нажимать F9.
27 мая 2010 в 9:19 пп
Собственное говоря, а как при таком связывании отследить «сообщения» от Excel? Например, юзер «случайным» образом закрывает рабочую книгу, а программа все еще «хочет» работать с ней.
27 мая 2010 в 9:53 пп
Честно говоря, никогда не задумывался о том как отловить сообщение от Excel и возможно ли то сдела вообще. Обычно в случае работы с книгами Excel или документами Word просто не забывал пользоваться try..except..end :) По-моему в данном случае можно покапаться в событиях Excel.
13 Июн 2010 в 5:13 пп
произвожу экспорт в excel из delphi, все проходит как бы ровно. а неровность заключается в том что после экспорта остается жить процесс «excel.exe». пытался юзать (Excel.Quit; Excel:=Unassigned;) не хочет помогать. помогите плиз люди добрые
14 Июн 2010 в 12:32 пп
Вы точно один раз запускаете процесс?
Excel.Quit; — выход из приложения
Excel:=Unassigned; — освобождение переменной
Этих строк 100% достаточно, чтобы завершить процесс правильно.
31 Авг 2010 в 12:48 пп
Вобще очень крутая статья! Долго мучался очень я)
Не компилируется функция Save, «FileName:TFileName» вот этот кусок. Откуда это берется?
31 Авг 2010 в 1:15 пп
По сабжу пока не работал, но скорее всего либо перменная FileName уже объявлена, либо тип TFileName из модуля SysUtils, где-то переопределен.
Сообщение компилятора приведите без него только догадки строить остается.
31 Авг 2010 в 2:05 пп
Готовый модуль скачать не удалось… какието глюки на айфолдерс.
Написал по «инструкции» в посте. Все работает без проблем.
19 Окт 2010 в 9:27 дп
Помогите Вопрос! Я использую шаблоны в своей программе! Можно ли из Дельфи изменть путь Save as..! Что бы при слхранений пользавателем путь сохранения был изменен? Спасибо
19 Окт 2010 в 3:41 пп
Можно менять путь сохранения — в справке по офису посмотрите описание функции SaveAs.
28 Дек 2010 в 8:14 пп
А можно ли проверить, что не просто запущен Excel, а уже имеется открытая конкретная книга.
Например, хочу создать в Excel (усли уже создана, то открыть) книгу table.xls
28 Дек 2010 в 11:55 пп
Так это вообще без проблем:
1. Проверяем запущен ли Excel
2. Если запущен обращаемся к коллекции открытых книг и проверяем в коллекции нужную книгу
3. Если книга найдена — активируем окно/работаем в фоне
29 Дек 2010 в 1:14 пп
Эт конечно всё заебца, но в Д2009 не канает…
29 Дек 2010 в 3:24 пп
Канает в любой версии Delphi, даже в XE.
23 Янв 2011 в 9:45 дп
begin
result:=CheckExcelRun;
if not result then
if AutoRun then
begin
RunExcel;
result:=CheckExcelRun;
end;
if result then MyExcel.WorkBooks.Add;
end;
23 Янв 2011 в 9:52 дп
Или так :-)
begin
result:=CheckExcelRun;
if (not result) and (AutoRun) then
begin
RunExcel;
result:=CheckExcelRun;
end;
if result then MyExcel.WorkBooks.Add;
end;
01 Фев 2011 в 6:48 пп
подскажите плиз,я недавно работаю с Delphi и у меня тут возникла проблемка..когда я использовал ваш код для проверки установлен Excel на компе или нет, у меня вылезла ошибка:
[Error] Unit5.pas(17): Identifier redeclared: ‘Rez’
объясните пожалуйста,в чем проблема?
01 Фев 2011 в 6:54 пп
Ну так отладчик же понятно говорит, что переменная Rez повторно объявлена. Ищите где повторное объявление. Может где в глобальных переменных повторились
02 Фев 2011 в 7:01 дп
как подсчитать кол-во заполненых строк на листе?
в VBA так — Cells(Rows.Count, 1).End(xlUp).Row
а как в Delphi ее описать?
14 Апр 2011 в 6:31 пп
function isExcelInstalled:boolean;
var
ClassID: TCLSID;
begin
Result := CLSIDFromProgID(PWideChar(WideString(ExcelApp)), ClassID) = S_OK;
end;
Понятнее и короче.
27 Апр 2011 в 9:53 пп
Народ , а нельзя вбить какую нить формулу в excel и чтобы результат вычисления выводился в проге в Дельфи? просто я только разбираюсь в дельфи и не знаю как это через дельфи сделать..
24 мая 2011 в 10:38 дп
Это будет проще сделать в делфи, и на много облегчит программу.
04 Июл 2011 в 7:38 пп
MyExcel.Application.EnableEvents:=DisableAlerts;
Если при поиске и замене ничего не найдено, то выдается сообщение — даже если DisableAlerts в False.
И почему DisableAlerts по умолчанию True — если сообщения лучше не показывать.
В моем случае помогло MyExcel.Application.DisplayAlerts := False.
04 Июл 2011 в 10:13 пп
DisableAlerts и .DisplayAlerts — разницу ощущаете? :)
04 Июл 2011 в 10:49 пп
Хорошо, буду догадываться.
DisplayAlerts по идее отключает сообщения выдаваемые на экран. Но что тогда делает EnableEvents?
02 Авг 2011 в 5:23 пп
В методе CheckExcelRun, если эксель закрыт возникает ошибка «Операция GetActiveOleObject недоступна.» а следом «invalid variant operation»
05 Авг 2011 в 11:38 дп
И вообще работает не совсем корректно, т.к. если открыт другой документ excel то он сохраняет его, а не тот который формирует прога. Я только начинаю писать на делфи. Помогите исправить это
04 Дек 2011 в 5:29 пп
var
MsExcel : Variant;
_Sheet : TStringList;
i, x : integer;
CCR_Ver, lLastRow, Name_Sheet, path : String;
begin
// 1. Открываем форму CCR
XLS_File.Execute();
if XLS_File.FileName <> » then
begin
MsExcel := CreateOleObject(‘Excel.Application’);
MsExcel.Workbooks.Open[XLS_File.FileName, 0, True];
// видимость Excel
MsExcel.Visible := False;
// Закрытие открытой книги
MsExcel.WorkBooks[MsExcel.WorkBooks.Count].Close(false);
// Закрытие Excel
MsExcel.quit;
// Перераспределение памяти
inherited;
close; // Закрытие формы frm_CCR_mos
end;
21 Дек 2011 в 9:14 пп
Предлагаемый вариант конечно работоспособен, но у него есть важные недостатки:
- низкая производительность (попробуйте создать таблицу например размером 100 на 10000 ячеек со сложным форматированием)
- высокие требования к необходимой оперативной памяти (опять же см. пример с размером таблицы)
- необходим установленный Excel (нет экселя, нет итогового файла. актуально, если подготовка отчетов делается на выделенном сервере, где лимитирован список установленного софта)
Лично я использую XLSReadWrite — вышеуказанных недостатков нет (таблица, указанную выше, у меня генерится за 0.4 секунды). Будет интересно — могу выложить реальный код примера
21 Дек 2011 в 9:29 пп
GS, было б неплохо взглянуть на такой пример. Кстати, для ускорения производительности я использую вариантный массив. Считываем за 1 раз весь лист в массив и уже потом в памяти вытаскиваем необходимые данные. Скорость возрастает в разы, а то и в десятки раз. А представленный пример — это действительно пример , который рассчитывался на абсолютно неподготовленного читателя=)
23 Дек 2011 в 12:17 пп
Упрощенный пример для Delphi 7 с использованием библиотеки XLSReadWrite:
var
IntlXls: TXLSReadWriteII2;
I, J: Integer;
begin
// создаем объект
IntlXls := TXLSReadWriteII2.Create(nil);
// название книги
IntlXls.Sheets[0].Name := ‘Название моего отчета’;
// добавляем необходимое количество строк и колонок
IntlXls.Sheets[0].Rows.AddIfNone(0, 10000);
IntlXls.Sheets[0].Columns.AddIfNone(0, 100);
// добавляем и заносим ширины ячеек (значение в пикселях)
for I := 0 to 99 do
IntlXls.Sheets[0].Columns[I].PixelWidth := 150;
// заносим высоты строк (значение здесь не в пикселях, поэтому нужно корректировать)
for I := 0 to 9999 do
IntlXls.Sheets[0].Rows[I].Height := 20 * 14;
// настраиваем
for J := 0 to 9999 do
for I := 0 to 99 do
begin
// заносим числовое значение
// если нужно например занести строку, то использовать AsString
IntlXls.Sheets [0]. AsFloat [I, J] := J + I / 100;
// выравнивание по горизонтали (доступно chaLeft, chaCenter, chaRight)
IntlXls.Sheets[0].Cell[I, J].HorizAlignment := chaLeft;
// выравнивание по вертикали (доступно cvaTop, cvaCenter, cvaBottom)
IntlXls.Sheets[0].Cell[I, J].VertAlignment := cvaTop;
// шрифт
IntlXls.Sheets[0].Cell[I, J].FontName := ‘Arial’;
IntlXls.Sheets[0].Cell[I, J].FontSize := 12;
IntlXls.Sheets[0].Cell[I, J].FontStyle := [];
IntlXls.Sheets[0].Cell[I, J].FontColor := TColorToClosestXColor(clBlue);
IntlXls.Sheets[0].Cell[I, J].Rotation := 0;
// жирное начертание
with IntlXls.Sheets[0].Cell[I, J] do
FontStyle := FontStyle + [xfsBold];
// наклонное начертание
with IntlXls.Sheets[0].Cell[I, J] do
FontStyle := FontStyle + [xfsItalic];
// цвет фона
IntlXls.Sheets[0].Cell[I, J].FillPatternForeColor :=
TColorToClosestXColor(clYellow);
// бордюр слева (аналогично и остальные бордюры)
IntlXls.Sheets[0].Cell[I, J].BorderLeftColor := TColorToClosestXColor(clBlack);
IntlXls.Sheets[0].Cell[I, J].BorderLeftStyle := cbsThin;
// объединение ячеек (здесь объединяются две ячейки по горизонтали)
if I = 49 then
IntlXls.Sheets[0].MergedCells.Add(
I,
J,
I + 1,
J
);
end;
IntlXls.SaveToFile(‘c:\demo.xls’);
IntlXls.Free;
end;
Полный пример для Delphi 7:
function ExportToExcelXls(
var AFileName: string
): Integer;
var
IntlXls: TXLSReadWriteII2;
IntlCol: Integer;
IntlRow: Integer;
IntlMainCol: Integer;
IntlMainRow: Integer;
begin
// инициализируем статус
prgrbrStatus.Max := FLinkReport.RowCount;
prgrbrStatus.Position := 0;
pnlStatus.Visible := TRUE;
pnlStatus.Refresh;
// добавлено в конце имени файла расширение ‘.XLS’?
if Length(AFileName) < 5 then
// добавляем
AFileName := AFileName + ‘.xls’
else if AnsiCompareText(Copy(AFileName, Length(AFileName) — 3, 4), ‘.xls’) <> 0 then
// добавляем
AFileName := AFileName + ‘.xls’;
// файл уже существует?
if FileExists(AFileName) then
// спросим
if Application.MessageBox(
PChar(‘Файл «‘ + AFileName + ‘» уже существует. Перезаписать?’),
‘Внимание’,
MB_TASKMODAL + MB_ICONQUESTION + MB_YESNO + MB_DEFBUTTON2
) <> IDYES then
// выходим
begin
// код ошибки
Result := UNIRPT_GENERATE_ABORT;
// выходим
Exit;
end; // if
// создаем объект
IntlXls := TXLSReadWriteII2.Create(nil);
// все делаем защищаясь
try
// название книги
IntlXls.Sheets[0].Name :=FLinkReport.Caption;
// добавляем необходимое количество строк и колонок
IntlXls.Sheets[0].Rows.AddIfNone(0, FLinkReport.Cells.RowCount + 1);
IntlXls.Sheets[0].Columns.AddIfNone(0, FLinkReport.Cells.ColCount + 1);
// добавляем и заносим ширины ячеек
for IntlCol := 0 to FLinkReport.Cells.ColCount — 1 do
IntlXls.Sheets[0].Columns[IntlCol].PixelWidth := FLinkReport.ColWidths[IntlCol];
// заносим высоты строк
for IntlRow := 0 to FLinkReport.Cells.RowCount — 1 do
IntlXls.Sheets[0].Rows[IntlRow].Height := FLinkReport.RowHeights[IntlRow] * 14;
// проходим по всем строкам
for IntlRow := 0 to FLinkReport.Cells.RowCount — 1 do
begin
// проходим по всем колонкам
for IntlCol := 0 to FLinkReport.Cells.ColCount — 1 do
begin
// определяем главную ячейку
IntlMainCol := IntlCol + FLinkReport.Cells[IntlCol, IntlRow].Range.Left;
IntlMainRow := IntlRow + FLinkReport.Cells[IntlCol, IntlRow].Range.Top;
// заносим оформление
with FLinkReport.Cells[IntlMainCol, IntlMainRow] do
begin
// главная ячейка?
if (IntlMainCol = IntlCol) and (IntlMainRow = IntlRow) then
// да, заносим текст и его оформление
begin
// значение
try
// если значение — число то заносим его как число
IntlXls.Sheets [0]. AsFloat [IntlCol, IntlRow] := StrToFloat (Value);
except
// иначе заносим его как строку
IntlXls.Sheets [0]. AsString [IntlCol, IntlRow] := Value;
end;
// выравнивание по горизонтали
case HorizAlign of
haLeft:
// выравнивание слева
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].HorizAlignment := chaLeft;
haCenter:
// выравнивание по центру
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].HorizAlignment := chaCenter;
haRight:
// выравнивание справа
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].HorizAlignment := chaRight;
end; // case
// выравнивание по вертикали
case VertAlign of
vaTop:
// выравнивание сверху
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].VertAlignment := cvaTop;
vaCenter:
// выравнивание в центре
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].VertAlignment := cvaCenter;
vaBottom:
// выравнивание снизу
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].VertAlignment := cvaBottom;
end; // case
// шрифт
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].FontName := Font.Name;
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].FontSize := Font.Size;
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].FontCharset := Font.Charset;
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].FontStyle := [];
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].FontColor := TColorToClosestXColor(Font.Color);
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].Rotation := Font. Angle;
// есть жирное начертание?
if Font.IsBold then
// есть
with IntlXls.Sheets[0].Cell[IntlCol, IntlRow] do
FontStyle := FontStyle + [xfsBold];
// есть наклонное начертание?
if Font.IsItalic then
// есть
with IntlXls.Sheets[0].Cell[IntlCol, IntlRow] do
FontStyle := FontStyle + [xfsItalic];
// цвет фона
if Color <> clWindow then
// цвет задан
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].FillPatternForeColor :=
TColorToClosestXColor(Color);
end // if
else
// просто активизируем ячейку (иначе ниже невозможно добавить бордюры)
IntlXls.Sheets[0].AsString[IntlCol, IntlRow] := »;
// бордюр слева есть?
with Borders.Left do
if LineHeight > 0 then
// настраиваем
begin
// цвет
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderLeftColor :=
TColorToClosestXColor(Color);
// толщина
if LineHeight = 1 then
// тонка
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderLeftStyle := cbsThin
else if LineHeight in [1, 2] then
// средняя толщина
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderLeftStyle := cbsMedium
else
// толстая
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderLeftStyle := cbsHair;
end; // if, with
// бордюр сверху есть?
with Borders.Top do
if LineHeight > 0 then
// настраиваем
begin
// цвет
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderTopColor :=
TColorToClosestXColor(Color);
// толщина
if LineHeight = 1 then
// тонка
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderTopStyle := cbsThin
else if LineHeight in [1, 2] then
// средняя толщина
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderTopStyle := cbsMedium
else
// толстая
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderTopStyle := cbsHair;
end; // if, with
// бордюр справа есть?
with Borders.Right do
if LineHeight > 0 then
// настраиваем
begin
// цвет
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderRightColor :=
TColorToClosestXColor(Color);
// толщина
if LineHeight = 1 then
// тонка
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderRightStyle := cbsThin
else if LineHeight in [1, 2] then
// средняя толщина
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderRightStyle := cbsMedium
else
// толстая
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderRightStyle := cbsHair;
end; // if, with
// бордюр снизу есть?
with Borders.Bottom do
if LineHeight > 0 then
// настраиваем
begin
// цвет
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderBottomColor :=
TColorToClosestXColor(Color);
// толщина
if LineHeight = 1 then
// тонка
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderBottomStyle := cbsThin
else if LineHeight in [1, 2] then
// средняя толщина
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderBottomStyle := cbsMedium
else
// толстая
IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderBottomStyle := cbsHair;
end; // if, with
// объединение нужно?
if ((Range.Width > 1) or (Range.Height > 1)) and
((IntlMainCol = IntlCol) and (IntlMainRow = IntlRow)) then
// объединяем
IntlXls.Sheets[0].MergedCells.Add(
IntlCol,
IntlRow,
IntlCol + Range.Width — 1,
IntlRow + Range.Height — 1
);
// пользователь нажал кнопку прерывания экспорта?
if btnCancel.Tag = 2 then
// да, выходим
Break;
end; // with
end; // for
// обновляем статус
prgrbrStatus.Position := prgrbrStatus.Position + 1;
Application.ProcessMessages;
// пользователь нажал кнопку прерывания экспорта?
if btnCancel.Tag = 2 then
// да, выходим
Break;
end; // for
// пользователь нажал кнопку прерывания экспорта?
if btnCancel.Tag <> 2 then
// нет
begin
// на левый верхний угол
IntlXls.Sheet[0].TopRow := 0;
IntlXls.Sheet[0].LeftCol := 0;
IntlXls.Sheet[0].Selection.ActiveRow := 0;
IntlXls.Sheet[0].Selection.ActiveCol := 0;
// статус
prgrbrStatus.Position := prgrbrStatus.Max;
Application.ProcessMessages;
// записываем в файл
IntlXls.FileName := AFileName;
IntlXls.Write;
// все успешно
Result := UNIRPT_OK;
end // if
else
// да
Result := UNIRPT_GENERATE_ABORT;
finally
// освобождаем память
IntlXls.Free;
end; // try..finally
end; // function ExportToExcelXls
23 Дек 2011 в 4:14 пп
GS, спасибо большое. Не возражаете, если я, по мере наличия свободного времени, опубликую в блоге отдельным постом эти примеры (Естественно с указанием настоящего автора примеров). Думаю, что такой пост может пригодиться многим.
23 Дек 2011 в 5:47 пп
Буду только рад :)