Подписка

добавить на Яндекс

Наши проекты

Delphi+Google

Google API

Google API в Delphi - проект с открытым исходным кодом.

Chrono

Chrono

Хронометр - программа для ведения списка задач.

ODFProc

ODFProc

ODFProc - работа с документами OpenOffice в Lazarus и FreePascal.

Поддержка блога

А тут я коплю на лицензию Delphi XE на iPad =).
Сумма пожертвования не фиксирована.

Публикации

Год назад

Случайный пост

Последние

Сообщения форума

Комментарии

Свежие комментарии

Социальные сети

Google

Facebook

Twitter

Опрос

Вы сейчас или в ближайшем обозримом будущем планируете разрабатывать кроссплатформенное приложение с использованием Firemonkey?



Loading ... Loading ...

Блоги и сообщества

Статьи по Delphi DelphiFeeds.ru - Все Delphi-блоги Рунета Сообщество умных людей VR-Online.RU Бесплатный журнал для программистов и всех, кто интересуется IT Статьи и уроки по Delphi Новостной блог о высоких технологиях
Система Orphus
Опубликовал Vlad 27 августа 2009 в 17:57.
Категории: Моя работа, Основы Delphi.


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

Понравилась статья? Тогда:
Делись! Загружай! Плюсуй!
   Отправить PDF на   
Читай ещё статьи на WebDelphi.ru

Комментарии (40)

WP_Cloudy
  • Социальная сеть для блоггеров sloger.net пишет:

    Работа с Excel в Delphi. Основы основ. | Delphi в Internet…

    Рассматриваем основные функции для работы с Excel из Delphi…

  • webveter пишет:

    Если документ простой, но объемный — это будет медленно. А при большом количестве таких документов — жизнь пройдет мимо.
    Вывести в Excel можно и проще.
     

  • Vlad пишет:

    Что конкретно будет медленно? :) Запуск Excel или проверка установки Excel? Так тут ускорить процесс негде. Вывода в Excel-то пока в статье нет. Забегая вперед, могу сказать — выводить по-отдельности каждую ячейку — долго, муторно и не верно, но есть вариант как ускорить процесс в несколько десятков, а то и сотен раз.
    Да, и ещё — оставлять в комментариях ссылки не стоит. Блог и так DoFollow, кому надо — тот перейдет на ваш блог.

  • Иван пишет:

    Очень хорошие статьи. Разобрался во всём с первого раза ))) Понравилась схема в mind42 )))
    Автору остаётся сказать только спасибо!

  • Vlad пишет:

    не за что, Иван. Всегда рад помочь)

  • Алекс пишет:

    Все хорошо. Но если Excel не запущен — возникает исключение. Что с этим делать? function CheckExcelRun выбрасывает сообщение и все…Хотя по смыслу должно было вернуть False

  • Vlad пишет:

    Странно. Если Excel запущен, то должна создаваться вторая копия приложения без исключений. Код в студию :)

  • Мария пишет:

    Насчет процедуры CheckExcelRun. Если программа запускается из под Delphi и Excel не запущен, то выскакивает ошибка: Операция GetActiveOleObject недоступна. Если програма запускается не из под Delphi то все в порядке. Наверное эту проблему имел ввиду Алекс. Как решение можно при отладке программы когда возникает исключение нажимать F9.

  • underchronos пишет:

    Собственное говоря, а как при таком связывании отследить «сообщения» от Excel? Например, юзер «случайным» образом закрывает рабочую книгу, а программа все еще «хочет» работать с ней.

  • Vlad пишет:

    Честно говоря, никогда не задумывался о том как отловить сообщение от Excel и возможно ли то сдела вообще. Обычно в случае работы с книгами Excel или документами Word просто не забывал пользоваться try..except..end :) По-моему в данном случае можно покапаться в событиях Excel.

  • Динар пишет:

    произвожу экспорт в excel из delphi, все проходит как бы ровно. а неровность заключается в том что после экспорта остается жить процесс «excel.exe». пытался юзать (Excel.Quit; Excel:=Unassigned;) не хочет помогать. помогите плиз люди добрые

  • Vlad пишет:

    Вы точно один раз запускаете процесс?
    Excel.Quit; — выход из приложения
    Excel:=Unassigned; — освобождение переменной
    Этих строк 100% достаточно, чтобы завершить процесс правильно.

  • Виноградная Лиса пишет:

    Вобще очень крутая статья! Долго мучался очень я)
    Не компилируется функция Save, «FileName:TFileName» вот этот кусок. Откуда это берется?

  • SeregaAltmer пишет:

    По сабжу пока не работал, но скорее всего либо перменная FileName уже объявлена, либо тип TFileName из модуля SysUtils, где-то переопределен.

    Сообщение компилятора приведите без него только догадки строить остается.

  • SeregaAltmer пишет:

    Готовый модуль скачать не удалось… какието глюки на айфолдерс.
    Написал по «инструкции» в посте. Все работает без проблем.

  • Shotkin пишет:

    Помогите Вопрос! Я использую шаблоны в своей программе! Можно ли из Дельфи изменть путь Save as..! Что бы при слхранений пользавателем путь сохранения был изменен? Спасибо

  • Vlad пишет:

    Можно менять путь сохранения — в справке по офису посмотрите описание функции SaveAs.

  • Kar пишет:

    А можно ли проверить, что не просто запущен Excel, а уже имеется открытая конкретная книга.
    Например, хочу создать в Excel (усли уже создана, то открыть) книгу table.xls

  • Vlad пишет:

    Так это вообще без проблем:
    1. Проверяем запущен ли Excel
    2. Если запущен обращаемся к коллекции открытых книг и проверяем в коллекции нужную книгу
    3. Если книга найдена — активируем окно/работаем в фоне

  • Pups пишет:

    Эт конечно всё заебца, но в Д2009 не канает…

  • Vlad пишет:

    Канает в любой версии Delphi, даже в XE.

  • Denf пишет:

    begin
    result:=CheckExcelRun;
    if not result then
    if AutoRun then
    begin
    RunExcel;
    result:=CheckExcelRun;
    end;
    if result then MyExcel.WorkBooks.Add;
    end;

  • Denf пишет:

    Или так :-)
    begin
    result:=CheckExcelRun;
    if (not result) and (AutoRun) then
    begin
    RunExcel;
    result:=CheckExcelRun;
    end;
    if result then MyExcel.WorkBooks.Add;
    end;
     

  • Рома пишет:

    подскажите плиз,я недавно работаю с Delphi и у меня тут возникла проблемка..когда я использовал ваш код для проверки установлен Excel на компе или нет, у меня вылезла ошибка:
    [Error] Unit5.pas(17): Identifier redeclared: ‘Rez’
    объясните пожалуйста,в чем проблема?

  • Vlad пишет:

    Ну так отладчик же понятно говорит, что переменная Rez повторно объявлена. Ищите где повторное объявление. Может где в глобальных переменных повторились

  • Alex пишет:

    как подсчитать кол-во заполненых строк на листе?
    в VBA так — Cells(Rows.Count, 1).End(xlUp).Row
    а как в Delphi ее описать?

  • SmackMyBitchUp пишет:

    function isExcelInstalled:boolean;
    var
    ClassID: TCLSID;
    begin
    Result := CLSIDFromProgID(PWideChar(WideString(ExcelApp)), ClassID) = S_OK;
    end;

    Понятнее и короче.

  • артем пишет:

    Народ , а нельзя вбить какую нить формулу в excel и чтобы результат вычисления выводился в проге в Дельфи? просто я только разбираюсь в дельфи и не знаю как это через дельфи сделать..

  • igor` пишет:

    Это будет проще сделать в делфи, и на много облегчит программу.

  • kylt_lichnosti пишет:

    MyExcel.Application.EnableEvents:=DisableAlerts;
    Если при поиске и замене ничего не найдено, то выдается сообщение — даже если DisableAlerts в False.
    И почему DisableAlerts по умолчанию True — если сообщения лучше не показывать.
    В моем случае помогло MyExcel.Application.DisplayAlerts := False.

  • Vlad пишет:

    DisableAlerts и .DisplayAlerts — разницу ощущаете? :)

  • kylt_lichnosti пишет:

    Хорошо, буду догадываться.
    DisplayAlerts по идее отключает сообщения выдаваемые на экран. Но что тогда делает EnableEvents?

  • Katya пишет:

    В методе CheckExcelRun, если эксель закрыт возникает ошибка «Операция GetActiveOleObject недоступна.» а следом «invalid variant operation»

  • Katya пишет:

    И вообще работает не совсем корректно, т.к. если открыт другой документ excel то он сохраняет его, а не тот который формирует прога. Я только начинаю писать на делфи. Помогите исправить это

  • Ivan пишет:

    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;

  • GS пишет:

    Предлагаемый вариант конечно работоспособен, но у него есть важные недостатки:
    - низкая производительность (попробуйте создать таблицу например размером 100 на 10000 ячеек со сложным форматированием)
    - высокие требования к необходимой оперативной памяти (опять же см. пример с размером таблицы) 
    - необходим установленный Excel (нет экселя, нет итогового файла. актуально, если подготовка отчетов делается на выделенном сервере, где лимитирован список установленного софта)

    Лично я использую XLSReadWrite — вышеуказанных недостатков нет (таблица, указанную выше, у меня генерится за 0.4 секунды). Будет интересно — могу выложить реальный код примера

  • Vlad пишет:

    GS, было б неплохо взглянуть на такой пример. Кстати, для ускорения производительности я использую вариантный массив. Считываем за 1 раз весь лист в массив и уже потом в памяти вытаскиваем необходимые данные. Скорость возрастает в разы, а то и в десятки раз. А представленный пример — это действительно пример , который рассчитывался на абсолютно неподготовленного читателя=)

  • GS пишет:

    Упрощенный пример для 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

  • Vlad пишет:

    GS, спасибо большое. Не возражаете, если я, по мере наличия свободного времени, опубликую в блоге отдельным постом эти примеры (Естественно с указанием настоящего автора примеров). Думаю, что такой пост может пригодиться многим.

  • GS пишет:

    Буду только рад :)

Ваш ответ

Внимание: Все комментарии модерируются, и это может вызвать задержку их публикации. Отправлять комментарий заново не требуется.

Пожалуйста, заключайте исходный код в тэги [code][/code].
Если код большой, то воспользуйтесь Вставкой кода на отдельной странице и оставьте в комментарии ссылку на исходник

   


эксель