Это первая статья из цикла «Работа с Excel в Delphi«

Видимо любители экономить килобайты оперативной памяти могут меня закидать помидорами или ещё чем по-хуже, но все-таки я скажу, что интеграция приложений (мегабайты оперативы) — это большой плюс нынешней разработки приложений.
Как ни крути, а время DOS и килобайтов оперативной памяти прошло. Вряд ли кто-то всерьез сейчас задумывается над тем куда это с винчестера пропал мегабайт? Да и использование в своих приложениях функциональности программ, которых ты не писал, но которые выполняют что-то лучше — это всё-таки больший прогресс, нежели корпеть год-два над программой, а потом узнать, что время-то прошло.

План статьи:

  1. Как проверить установлен ли Excel на компьютере пользователя?
  2. Определяем запущен ли Excel
  3. Как запустить Excel?
  4. Создаем пустую рабочую книгу Excel
  5. Сохраняем рабочую книгу и закрываем Excel

Итак, цель сегодняшней статьи — поделиться с Вами опытом работы с 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 можно скачать со страницы с исходниками
Следующая статья на тему работы с Excel в Delphi — «Excel в Delphi. Методы объекта WorkSheet (лист).»

Читайте также:

56 thoughts on “Работа с Excel в Delphi. Основы основ.

  1. Уведомление: Социальная сеть для блоггеров sloger.net
  2. Если документ простой, но объемный — это будет медленно. А при большом количестве таких документов — жизнь пройдет мимо.
    Вывести в Excel можно и проще.
     

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  23. 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;

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

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

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

      1. Влад, здравствуйте.
        Я могу с Вами как либо связаться и задать пару вопросов?

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

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

  26. Ребят, вы даже представить себе не можете, насколько это полезная информация))) 
    Спасибо! 

  27. Нужна помощь! 
    1) В функции  CheckExcelInstall выдает результат false хотя exel установлен(2010)… 
    2)Ругается на строчку MyExcel:=GetActiveOleObject(ExcelApp); так: «project project.exe raised exception class EOleSysError with message ‘недопустимая строка с указанием класса’.» 

  28. Доброго…
    извиняюсь вторгнусь в беседу.

    подскажите плиз как сделать следующее с помощью компонентов XLSReadWrite
    1. открыть книгу
    2. сделать поиск построчно в столбце например T при этом нужен поиск с частичным совпадением текста.
    3. организовать поиск по многим книгам за 1 проход.

    текущий пример как сделано сейчас прилагаю. Открытие книги и поиск в ней выполняются за 9 секунд в среднем в двух книгах за 18. хотелось бы уменьшить данное время на сколько это возможно.

    заранее спасибо всем откликнувшимся.
     

  29.       // Создание Excel
          ExcelApp := CreateOleObject(‘Excel.Application’);

          // Отключаем реакцию Excel на события, чтобы ускорить вывод информации
          ExcelApp.Application.EnableEvents := false;

          //  Открываем Книгу (Workbook) в режиме только для чтения
          ExcelApp.WorkBooks.Open(ExtractFilePath(ExtractFilePath(Application.ExeName)) + Book_Name, ReadOnly:=true);

          WorkBookCount := ExcelApp.WorkBooks.Count;
        end;

      Sheet := ExcelApp.WorkBooks[WorkBookCount].Sheets[Sheet_Name];
      // ThisWorkbook.Sheets(«Data»).Cells(1, 1).Select
      Sheet.Cells[1, 1].select;

      application.ProcessMessages;
      // поиск адреса ячейки
      vFind := Sheet.Range[»+Range_Find+»].Find( What:=Find_Site,
                                            LookIn:=xlValues, // поиск в значениях
                                            LookAt:=xlPart // частичное совпадение
                                           // SearchDirection:=xlNext // направление вверх
                                          ).Address;

              XL_Col := Trim(Copy(vFind, 2));
              XL_Col := Trim(Copy(XL_Col, 1, Pos(‘$’, XL_Col) -1) );
              XL_Row := Trim(Copy(vFind, 2));
              XL_Row := Trim(Copy(XL_Row, Pos(‘$’, XL_Row) +1) );

              ima_name := Sheet.Cells.Item[XL_Row, 6].Value;
              E1_Pos :=  Sheet.Cells.Item[XL_Row, 7].Value;
              E1_Qty :=  Sheet.Cells.Item[XL_Row, 8].Value;
              minE1_Qty :=  Sheet.Cells.Item[XL_Row, 9].Value;
              A2EA := Sheet.Cells.Item[XL_Row, 13].Value;
              B_Node :=  Sheet.Cells.Item[XL_Row, 14].Value;
              Node_Id :=  Sheet.Cells.Item[XL_Row, 15].Value;
              OAM_MASK := Sheet.Cells.Item[XL_Row, 16].Value;
              RBS_L3  := Sheet.Cells.Item[StrToInt(XL_Row) + 1, 18].Value;

              ShowMessage(ima_name + #13 + E1_Pos + #13 + E1_Qty + #13 + minE1_Qty + #13 + A2EA + #13 +
                B_Node + #13 + Node_Id + #13 + RBS_L3 + #13 + OAM_MASK + #13 + mub_a + #13 +
                mask_mub_a + #13 + mub_b + #13 + mask_mub_b);

  30. Вопрос поднимался выше, не ответили:
    Не компилит функция Save, «FileName:TFileName», пишет:
    1. если не определяем параметры функции SaveWorkSheet, пишет что не хватает актуальных параметров
    2. ставлю параметры, (индекс), пишет что не соответствие типов String/Integer,

    1. Borodkin, исходник в статье работает отлично. Следовательно — хотелось бы увидеть Ваш исходник для решение проблемы

  31. Vlad огромное спасибо за статью
    Просьба есть: нельзя ли перезалить модуль.. как тут уже писали он не скачивается по ссылке :(

  32. При объявлении переменой типа OleVariant, у самой переменой нету никаких методов/классов. После нажатия точки вылазит только (*, {, class, claasc и т.п. Так и должно быть?

    Хотя сами методы компилятор видит. WorkBooks, Sheet, Range, Cells и т.п.

  33. подскажите пож как сделать чтобы когда вбиваешь edit текс он выводился в excel и когда я водил опять он спускался на строчку ниже а не -заменял преждний

  34. procedure TForm1.EXSEL1Click(Sender: TObject);
    const StepRow=3;
    StepCol=1;
    var i:integer;
    WorkBk : _WorkBook;
    WorkSheet : _WorkSheet;
    begin
    ExcelApplication1.Connect;
    ExcelApplication1.WorkBooks.Add(xlWBatWorkSheet,0);
    WorkBk := ExcelApplication1.WorkBooks.Item[1];
    WorkSheet := WorkBk.WorkSheets.Get_Item(1) as _WorkSheet;
    WorkSheet.Name:=’ОТЧЕТ’;
    with WorkSheet do
    begin
    with PageSetup do
    begin
    Orientation:=2;
    CenterFooter:=’ОТЧЕТ’;
    FooterMargin;
    TopMargin:=25;
    LeftMargin:=0;
    BottomMargin:=100;
    RightMargin:=0;
    PageSetup.CenterHorizontally:=True;
    PageSetup.Zoom:=75;
    end;

    end;

    ExcelApplication1.Visible[0]:=true;
    with WorkSheet.Cells do
    begin
    Item[StepRow,StepCol].value:=’№’;
    Item[StepRow,StepCol].font.bold:=true;
    Item[StepRow,StepCol+1].value:=’Пэннін атауы’;
    Item[StepRow,StepCol+1].font.bold:=true;
    Item[StepRow,StepCol+2].value:=’Курс’;
    Item[StepRow,StepCol+2].font.bold:=true;
    Item[StepRow,StepCol+3].value:=’Болім’;
    Item[StepRow,StepCol+3].font.bold:=true;
    Item[StepRow,StepCol+4].value:=’Семестр’;
    Item[StepRow,StepCol+4].font.bold:=true;
    Item[StepRow,StepCol+5].value:=’Маман/к’;
    Item[StepRow,StepCol+5].font.bold:=true;
    Item[StepRow,StepCol+6].value:=’Лекция’;
    Item[StepRow,StepCol+6].font.bold:=true;
    Item[StepRow,StepCol+7].value:=’Практика’;
    Item[StepRow,StepCol+7].font.bold:=true;
    Item[StepRow,StepCol+8].value:=’Лабор.’;
    Item[StepRow,StepCol+8].font.bold:=true;
    Item[StepRow,StepCol+9].value:=’Рейтинг’;
    Item[StepRow,StepCol+9].font.bold:=true;
    Item[StepRow,StepCol+10].value:=’Курс. жумыс’;
    Item[StepRow,StepCol+10].font.bold:=true;
    Item[StepRow,StepCol+11].value:=’Консульт.’;
    Item[StepRow,StepCol+11].font.bold:=true;
    Item[StepRow,StepCol+12].value:=’Емтихан’;
    Item[StepRow,StepCol+12].font.bold:=true;
    Item[StepRow,StepCol+13].value:=’Онд.практика.’;
    Item[StepRow,StepCol+13].font.bold:=true;
    Item[StepRow,StepCol+14].value:=’СОЖ.’;
    Item[StepRow,StepCol+14].font.bold:=true;
    Item[StepRow,StepCol+15].value:=’Дипломдык жумыс’;
    Item[StepRow,StepCol+15].font.bold:=true;
    Item[StepRow,StepCol+16].value:=’Барлыгы:’;
    Item[StepRow,StepCol+16].font.bold:=true;

    with dm.QPredmed do
    begin
    First;
    i:=1;
    while not Eof do
    begin
    Item[StepRow+i,StepCol].value:=IntToStr(i);
    Item[StepRow+i,StepCol+1].value:=FieldByName(‘naz’).AsString;
    Item[StepRow+i,StepCol+2].Value:=FieldByName(‘kurs’).AsString;
    Item[StepRow+i,StepCol+3].Value:=FieldByName(‘facult’).AsString;
    Item[StepRow+i,StepCol+4].Value:=FieldByName(‘semestr’).AsString;
    Item[StepRow+i,StepCol+5].Value:=FieldByName(‘grup’).AsString;
    Item[StepRow+i,StepCol+6].Value:=FieldByName(‘lecture’).AsString;
    Item[StepRow+i,StepCol+7].Value:=FieldByName(‘practika’).AsString;
    Item[StepRow+i,StepCol+8].Value:=FieldByName(‘laborator’).AsString;
    Item[StepRow+i,StepCol+9].Value:=FieldByName(‘reiting’).AsString;
    Item[StepRow+i,StepCol+10].Value:=FieldByName(‘kp’).AsString;
    Item[StepRow+i,StepCol+11].Value:=FieldByName(‘konsult’).AsString;
    Item[StepRow+i,StepCol+12].Value:=FieldByName(‘ekz’).AsString;
    Item[StepRow+i,StepCol+13].Value:=FieldByName(‘okuprak’).AsString;
    Item[StepRow+i,StepCol+14].Value:=FieldByName(‘srs’).AsString;
    Item[StepRow+i,StepCol+15].Value:=FieldByName(‘prousprak’).AsString;
    Item[StepRow+i,StepCol+16].Value:=FieldByName(‘summs’).AsString;
    columns.AutoFit;
    Next;
    Inc(i);
    end;
    end;
    end;

    ExcelApplication1.Disconnect;

    end;

Добавить комментарий

Ваш e-mail не будет опубликован.