Считать ячейки с excel delphi

уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Праздники ещё не закончились, работать лень, но надо как-то уже прекращать заниматься кишкоблудством и начинать работать в полную силу. Ну, а чтобы как-то себя расшевелить и начать уже работу в блоге, решил первый пост сделать простым — снова сказать несколько слов про Excel. Дело в том, что с момента выхода поста под названием «Работа с Excel в Delphi. Основы основ.» прошло практически полтора года и этот пост (почему-то вопреки всем ожиданиям) очень прочно закрепился в выдаче поисковиков. Это, конечно хорошо, но этот пост (читай название) дает лишь небольшое представление о том как работать с Excel в Delphi. Никто ведь не изучает сразу квантовую механику с первого класса? Сначала учимся основам вообще — математика, физика и т.д. Так я решил поступить в начале рассказа про Excel — сначала дать общее представление, а потом потихоньку раскрывать тему более подробно и детально. Но поисковики немного спутали карты, подняв пост выше других про Excel. Соответственно, те из посетителей, кто уже имеют представление о работе с Excel, видя представленные в статье примеры, возмущаются по поводу того, что чтение данных в этом случае будет происходить медленно. И я не спорю, да проход по каждой ячейке листа — это жуткие тормоза. А ускорить процесс чтения можно и необходимо. Поэтому можно считать, что эта статья — расширение к основам.

За полтора года мне предлагали кучу вариантов того как ускорить чтение данных с листа Excel — от использования MSXML и других готовых библиотек до самопальных процедур и функций. Что ж, любую задачу можно решить несколькими способами. Рассмотрим несколько вариантов и определимся какой из вариантов окажется наиболее быстрым. Ну, а какой вариант окажется более удобным — это уже каждый решит для себя сам.

Вначале рассмотрим вариант чтения данных использованием которого грешат те, кто только начинает свое знакомство с Excel в Delphi — чтение данных из каждой ячейки по отдельности. Тестовая процедура с таким вариантом чтения может выглядеть следующим образом:

procedure TForm16.SlowVariant;
var Rows, Cols, i,j: integer;
    WorkSheet: OLEVariant;
    d: TDateTime;
begin
  //открываем книгу
  ExcelApp.Workbooks.Open(edFile.Text);
  //получаем активный лист
  WorkSheet:=ExcelApp.ActiveWorkbook.ActiveSheet;
  //определяем количество строк и столбцов таблицы
  Rows:=WorkSheet.UsedRange.Rows.Count;
  Cols:=WorkSheet.UsedRange.Columns.Count;
 
  StringGrid1.RowCount:=Rows;
  StringGrid1.ColCount:=Cols;
 
  //засекаем время начала чтения
  d:=Now;
 
  //выводим данные в таблицу
  for I := 0 to Rows-1 do
    for j := 0 to Cols-1 do
        StringGrid1.Cells[J,I]:=WorkSheet.UsedRange.Cells[I+1,J+1].Value;
 
 Label2.Caption:='Время чтения всего листа: '+FormatDateTime('hh:mm:ss:zzz',
    Now()-d);
end;

Счётчик будет в итоге содержать время чтения и вывода в StringGrid данных. Можно было бы сделать счётчик исключительно на чтение данных с листа, но я решил не перегружать исходник лишними переменными. Если будет желание — можете переписать чуть-чуть исходник и получить «чистое» время чтения.

Для теста этого варианта был создан лист Excel, содержащий 143 строки и 142 столбца с данными, т.е. 20306 ячеек с данными. На рисунке ниже представлено значение счётчика после чтения данных:

12 секунд на чтение…а если будет 1000 строк и 1000 столбцов? Так можно и не дождаться окончания операции.

Если внимательно посмотреть на процедуру, представленную выше, то можно видеть, что в цикле мы каждый раз при каждой итерации вначале получаем диапазон, занятый данными, затем в этом диапазоне получаем определенную ячейку и только потом считываем значение в ячейке. На самом деле столько лишних операций для чтения данных с листа не требуется. Тем более, когда данные располагаются непрерывным массивом. Более выгодным в этом случае вариантом чтения будет чтение данных сразу из всего диапазона в массив.

На деле реализация этого варианты работы окажется даже проще, чем представленного выше. Смотрите сами. Вот вариант чтения данных целым диапазоном:

procedure TForm16.RangeRead;
var Rows, Cols, i,j: integer;
    WorkSheet: OLEVariant;
    FData: OLEVariant;
    d: TDateTime;
begin
  //открываем книгу
  ExcelApp.Workbooks.Open(edFile.Text);
  //получаем активный лист
  WorkSheet:=ExcelApp.ActiveWorkbook.ActiveSheet;
  //определяем количество строк и столбцов таблицы
  Rows:=WorkSheet.UsedRange.Rows.Count;
  Cols:=WorkSheet.UsedRange.Columns.Count;
 
  //считываем данные всего диапазона
  FData:=WorkSheet.UsedRange.Value;
 
  StringGrid1.RowCount:=Rows;
  StringGrid1.ColCount:=Cols;
 
//засекаем время начала чтения
  d:=Now;
 
//выводим данные в таблицу
  for I := 0 to Rows-1 do
    for j := 0 to Cols-1 do
        StringGrid1.Cells[J,I]:=FData[I+1,J+1];
 
    Label2.Caption:='Время чтения всего листа: '+FormatDateTime('hh:mm:ss:zzz',
    Now()-d);
end;

Здесь мы ввели всего одну переменную FData типа Variant. В эту переменную мы прочитали за 1 операцию весь диапазон, занятый данными. После того как диапазон прочитан FData будет содержать матрицу, каждый элемент которой будет типом данных, определенным в Excel.

Смотрим на время выполнения операции:

Как видите, прирост скорости оказался колоссальным, учитывая даже то, что в счётчик попало время обновления StringGrid’а.

Здесь было бы уместно показать и обратный метод работы с Excel, т.е. запись данных на лист Excel с использованием вариантного массива.

Запись данных в Excel

В случае, если нам необходимо записать большой объем данных на лист Excel нам необходимо провести обратную операцию, т.е. вначале создать вариантный массив, затем записать в этот массив данные после чего записать весь массив одной операцией в Excel. Для примера я написал процедуру, которая считывает большой объем данных из StringGrid и записывает эти данные на второй лист открытой книги Excel:

procedure TForm16.WriteData;
var i,j: integer;
    FData: Variant;
    Sheet,Range: Variant;
begin
//создаем вариантный массив
  FData:=VarArrayCreate([1,StringGrid1.RowCount,1,StringGrid1.ColCount],varVariant);
//заполняем массив данными из StringGrid
  for i:=1 to VarArrayHighBound(FData,1) do
    for j:=1 to VarArrayHighBound(FData,2) do
      FData[i,j]:=StringGrid1.Cells[J-1,I-1];
{активируем второй лист книги}
//открываем книгу
ExcelApp.Workbooks.Open(edFile.Text);
//активируем
Sheet:=ExcelApp.ActiveWorkBook.Sheets[2];
Sheet.Activate;
//выделяем диапазон для вставки данных
Range:=Sheet.Range[Sheet.Cells[1,1],Sheet.Cells[VarArrayHighBound(FData,1),VarArrayHighBound(FData,2)]];
//вставляем данные
Range.Value:=FData;
//показываем окно Excel
ExcelApp.Visible:=True;
end;

Здесь мы вначале создаем двумерный вариантный массив, используя метод VarArrayCreate, после чего заполняем массив данным и передаем этот массив в Excel. Обратите внимание, что при записи в Excel не используются никакие циклы — запись происходит в 2 простых действия:

  • выделяем диапазон, используя в качестве границ диапазона первую и последнюю ячейки
  • присваиваем диапазону значение из массива.

Для полноты картины ниже на рисунке представлено значение счётчика, который отсчитал время от момента создания массива до активации приложения Excel включительно:

Естественно, что с ростом объема данных будет расти и время выполнения операции. Так, например, лист, содержащий 1000 строк и 256 столбцов с данными заполнялся около 7 секунд. Если для Вас такое время неприемлемо, то представленная выше процедура может быть немного ускорена использованием пары методов VarArrayLock() и VarArrayUnLock(), но при этом следует учитывать, что матрица FData будет транспонирована.

Что ещё стоит сказать по поводу чтения/записи данных в Excel? Наверное то, что предложенные выше методы работы в обязательном порядке требуют наличия установленного Excel на том компьютере где запускается Ваша программа. В связи с этим обстоятельством может потребоваться более универсальный способ работы с Excel. Здесь, опять же, может быть несколько вариантов работы, но я покажу, а точнее укажу только на один из них — с использованием библиотека XLSReadWrite.

Про эту библиотеку мне поведал один из читателей блога в комментарии как раз-таки к посту «»Работа с Excel в Delphi. Основы основ«. Чтобы лишний раз Вас не переправлять на комментарий с примером использования этой библиотеки, я с разрешения GS (ник автора кода) просто опубликую здесь уже готовые примеры использования библиотеки XLSReadWrite:

Упрощенный пример для Delphi 7

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;

Полный пример работы с библиотекой:

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 +.xlselse 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.ColCount1 do
      IntlXls.Sheets[0].Columns[IntlCol].PixelWidth :=
        FLinkReport.ColWidths[IntlCol];
    // заносим высоты строк
    for IntlRow := 0 to FLinkReport.Cells.RowCount1 do
      IntlXls.Sheets[0].Rows[IntlRow].Height := FLinkReport.RowHeights
        [IntlRow] * 14;
    // проходим по всем строкам
    for IntlRow := 0 to FLinkReport.Cells.RowCount1 do
    begin
      // проходим по всем колонкам
      for IntlCol := 0 to FLinkReport.Cells.ColCount1 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.Width1, IntlRow + Range.Height1);
          // пользователь нажал кнопку прерывания экспорта?
          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

Вот такой подробный пример предоставил нам GS в своем комментарии. Спасибо ему за это. Мне же в заключении остается только добавить и подчеркнуть, что самые правильные ответы и примеры к вопросам, касающимся работы с Excel содержаться в Справке для разработчиков в самом Excel и надо только воспользоваться поиском. Например, если вам довольно часто приходится перетаскивать данные из базы данных в Excel и в работе используется ADO, то специально для таких случаев в справке рассказывается про интересный метод объекта Range под названием CopyFromRecordset, а если вам надо разукрасить свою таблицу Excel в разные цвета и установить разные виды границ ячеек, то специально для таких случаев в справке приводится подробные перечень всех перечислителей Excel’я.  В общем много чего есть — надо только этим воспользоваться и все получится. Ну, а если не получится, то милости прошу — задавайте вопросы здесь или на нашем форуме.

Книжная полка

Название:Разработка приложений Microsoft Office 2007 в Delphi

Описание Описаны общие подходы к программированию приложений MS Office. Даны программные методы реализации функций MS Excel, MS Word, MS Access и MS Outlook в среде Delphi.

купить книгу delphi на ЛитРес

3.7
3
голоса

Рейтинг статьи

уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Вначале рассмотрим вариант чтения данных использованием которого грешат те, кто только начинает свое знакомство с Excel в Delphi — чтение данных из каждой ячейки по отдельности. Тестовая процедура с таким вариантом чтения может выглядеть следующим образом:

procedure TForm16.SlowVariant;
var Rows, Cols, i,j: integer;
    WorkSheet: OLEVariant;
    d: TDateTime;
begin
  //открываем книгу
  ExcelApp.Workbooks.Open(edFile.Text);
  //получаем активный лист
  WorkSheet:=ExcelApp.ActiveWorkbook.ActiveSheet;
  //определяем количество строк и столбцов таблицы
  Rows:=WorkSheet.UsedRange.Rows.Count;
  Cols:=WorkSheet.UsedRange.Columns.Count;
 
  StringGrid1.RowCount:=Rows;
  StringGrid1.ColCount:=Cols;
 
  //засекаем время начала чтения
  d:=Now;
 
  //выводим данные в таблицу
  for I := 0 to Rows-1 do
    for j := 0 to Cols-1 do
        StringGrid1.Cells[J,I]:=WorkSheet.UsedRange.Cells[I+1,J+1].Value;
 
 Label2.Caption:='Время чтения всего листа: '+FormatDateTime('hh:mm:ss:zzz',
    Now()-d);
end;

Счётчик будет в итоге содержать время чтения и вывода в StringGrid данных.

Для теста этого варианта был создан лист Excel, содержащий 143 строки и 142 столбца с данными, т.е. 20306 ячеек с данными.

На время чтения ушло 12 секунд.

12 секунд на чтение…а если будет 1000 строк и 1000 столбцов? Так можно и не дождаться окончания операции.

Если внимательно посмотреть на процедуру, представленную выше, то можно видеть, что в цикле мы каждый раз при каждой итерации вначале получаем диапазон, занятый данными, затем в этом диапазоне получаем определенную ячейку и только потом считываем значение в ячейке. На самом деле столько лишних операций для чтения данных с листа не требуется. Тем более, когда данные располагаются непрерывным массивом. Более выгодным в этом случае вариантом чтения будет чтение данных сразу из всего диапазона в массив.

На деле реализация этого варианты работы окажется даже проще, чем представленного выше. Смотрите сами. Вот вариант чтения данных целым диапазоном:

procedure TForm16.RangeRead;
var Rows, Cols, i,j: integer;
    WorkSheet: OLEVariant;
    FData: OLEVariant;
    d: TDateTime;
begin
  //открываем книгу
  ExcelApp.Workbooks.Open(edFile.Text);
  //получаем активный лист
  WorkSheet:=ExcelApp.ActiveWorkbook.ActiveSheet;
  //определяем количество строк и столбцов таблицы
  Rows:=WorkSheet.UsedRange.Rows.Count;
  Cols:=WorkSheet.UsedRange.Columns.Count;
 
  //считываем данные всего диапазона
  FData:=WorkSheet.UsedRange.Value;
 
  StringGrid1.RowCount:=Rows;
  StringGrid1.ColCount:=Cols;
 
//засекаем время начала чтения
  d:=Now;
 
//выводим данные в таблицу
  for I := 0 to Rows-1 do
    for j := 0 to Cols-1 do
        StringGrid1.Cells[J,I]:=FData[I+1,J+1];
 
    Label2.Caption:='Время чтения всего листа: '+FormatDateTime('hh:mm:ss:zzz',
    Now()-d);
end;

Здесь мы ввели всего одну переменную FData типа Variant. В эту переменную мы прочитали за 1 операцию весь диапазон, занятый данными. После того как диапазон прочитан FData будет содержать матрицу, каждый элемент которой будет типом данных, определенным в Excel.

Время выполнения операции 0.022 секунды!

Как видите, прирост скорости оказался колоссальным, учитывая даже то, что в счётчик попало время обновления StringGrid’а.

Вот и всё, Удачи!

Мяу Мяу

0 / 0 / 0

Регистрация: 06.01.2016

Сообщений: 4

1

09.01.2016, 16:56. Показов 8087. Ответов 4

Метки delphi excel (Все метки)


Студворк — интернет-сервис помощи студентам

Хелп котаны. Почему ничего не присваивает?)) Главное в ячейку можно записать, а считать нет. Что делать?)

Delphi
1
S:=Excel.Range['A7'];



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

09.01.2016, 16:56

4

Joey

Джоуи

1073 / 635 / 240

Регистрация: 05.05.2015

Сообщений: 3,546

Записей в блоге: 2

09.01.2016, 22:17

2

Лучший ответ Сообщение было отмечено Мяу Мяу как решение

Решение

Во-первых, после Range[‘A7’] добавить .Value;
во-вторых, что за объект Excel? Если это только excel application, то

Delphi
1
Excel.ActiveWorkbook.ActiveSheet.Range['A7'].Value;



1



Мяу Мяу

0 / 0 / 0

Регистрация: 06.01.2016

Сообщений: 4

10.01.2016, 00:44

 [ТС]

3

Я делал все по этому гайду Инструкция: Использование Excel из Delphi
Value не помог

Добавлено через 12 минут
Все. Я понял. Вот такая сокращенная запись работает, если ты что то записываешь в документ или видоизменяешь его. Например:

Delphi
1
Excel.Range['A7']:='dsadad';

А если ты хочешь считывать, то надо писать полностью.

Delphi
1
s:=Excel.WorkBooks[1].WorkSheets[1].Range[A7];

И кстати Value не нужен.



0



4891 / 4030 / 1012

Регистрация: 29.08.2013

Сообщений: 25,716

Записей в блоге: 3

10.01.2016, 01:22

4

и кстати, что ты будешь делать если экселя нет на компе?



0



Мяу Мяу

0 / 0 / 0

Регистрация: 06.01.2016

Сообщений: 4

10.01.2016, 01:37

 [ТС]

5

Все изи. Сделаю какой нибудь месадж, типо на компе нет Excel))И вообще меня это не волнует. У меня задание состоит в другом).
Кстати по поводу Value))) Он все таки нужен, но для условных операторов) Странно как то. Главное считывать можно, а вот условный оператор ругается.

Delphi
1
2
 S:=Excel.WorkBooks[1].WorkSheets[1].Range['A7'];
if Excel.WorkBooks[1].WorkSheets[1].Range['A7'].Value='' then S:='dsdsd';



0



Довольно распространенная задача в программировании – загрузка данных в проект из внешнего файла. В отличие от загрузки из обычного текстового файла, загрузка из Excel, как и любого другого специального файла или подключение к базе данных, требует отдельного механизма реализации.

В данной статье рассматривается один из наиболее удобных способов работы с подгружаемыми из Excel данными. Значения всех ячеек страницы Excel вносятся в двумерный массив типа Variant. Затем с этим массивом уже можно работать любыми привычными способами.

В общем виде все сводится к подключению программы к файлу Excel, получению необходимого диапазона ячеек и присвоении вашему массиву значения заданного диапазона ячеек.

const
   xlCellTypeLastCell = $0000000B;
var
   ExcelApp, ExcelSheet: OLEVariant;
   MyMass: Variant;
   x, y: Integer;
begin
   // создание OLE-объекта Excel
   ExcelApp := CreateOleObject('Excel.Application');

   // открытие книги Excel
   ExcelApp.Workbooks.Open('C:my_excel.xls');

   // открытие листа книги
   ExcelSheet := ExcelApp.Workbooks[1].WorkSheets[1];

   // выделение последней задействованной ячейки на листе
   ExcelSheet.Cells.SpecialCells(xlCellTypeLastCell).Activate;

   // получение значений размера выбранного диапазона
   x := ExcelApp.ActiveCell.Row;
   y := ExcelApp.ActiveCell.Column;

   // присвоение массиву диапазона ячеек на листе
   MyMass := ExcelApp.Range['A1', ExcelApp.Cells.Item[X, Y]].Value;

   // закрытие книги и очистка переменных
   ExcelApp.Quit;
   ExcelApp := Unassigned;
   ExcelSheet := Unassigned;
end;

* Метод SpecialCells используется для выделения определенных ячеек на основании оценки их содержимого или других характеристик. Применяемое здесь значение параметра-константы xlCellTypeLastCell указывает методу выделить последнюю ячейку используемого диапазона, т.е. саму нижнюю правую ячейку в диапазоне, где введено хоть какое-то значение. Это позволяет копировать не все ячейки листа, а лишь диапазон, содержащий какие-либо данные.

Для использования команд работы с OLE-объектами для этого кода нужно добавить библиотеку:

uses
  ComObj;

После указанных операций данные введены в массив, из которого их можно перенести в компонент StringGrid или использовать их по своему усмотрению. Стоит заметить, что в полученном таким образом массиве данные индексы располагаются в следующем порядке: [номер строки, номер столбца]. Это видно из следующего примера вывода данных массива в компонент StringGrid.

// назначение размера StringGrid по размеру полученного диапазона ячеек
MyStringGrid.RowCount := x;
MyStringGrid.ColCount := y;

// заполнение таблицы StringGrid значениями массива
for x := 1 to MyStringGrid.ColCount do
  for y := 1 to MyStringGrid.RowCount do
      MyStringGrid.Cells[x-1, y-1] := MyMass[y, x];

В данном обзоре рассмотрены
основные конструкции,
позволяющие получить доступ к
книге Excel из DELPHI.

Организация доступа к книге
EXCEL

Для
взаимодействия с MS excel в
программе необходимо
использовать модуль ComObj
uses ComObj;
и объявить переменную для
доступа к MS excel следующего
типа:
var Excel:
Variant;

Инициализация
переменной Excel в простейшем
случае можно осуществить так:
   
Excel := CreateOleObject(‘Excel.Application’);

Создание
новой книги:
   
Excel.Workbooks.Add;

Открытие
существующей книги (где
path
— путь к фалу с расширением xls.):
   
Excel.Workbooks.Open[path];

Открытие
существующей книги только для
чтения:
   
Excel.Workbooks.Open[path, 0,
True];

Закрытие
Excel:
   
Excel.ActiveWorkbook.Close;
    Excel.Application.Quit;

Блокировка
запросов (подтвеждений,
уведомлений) Excel, например,
запретить запрос на сохранение
файла:
   
Excel.DisplayAlerts:=False;

Отображаем
Excel на экране:
   
Excel.Visible := True;
или скрываем:
   
Excel.Visible := False;

Печать
содержимого активного листа
excel:
   
Excel.ActiveSheet.PrintOut;

Чтение/запись данных в EXCEL

Доступ к
ячейке в текущей книге Excel
можно осуществить следующим
образом:
   
Excel.Range[‘B2′]:=’Привет!’;-
для записи значения в ячейку или
   
s:=Excel.Range[‘B2’]; —
для чтения,
где B2
— адрес ячейки.

Или используя стиль ссылок R1C1:

   
Excel.Range[excel.Cells[2, 2]]:=’Привет!’;,
где [2, 2]
— координата ячейки.

Вообще, ячейке Excel можно
присваивать любое значение
(символьное, целое, дробное,
дата) при этом Excel установит
форматирование в ячейке
применяемое по умолчанию.

Формат ячеек в EXCEL

Выделить
(выбрать) группу ячеек для
последующей работы можно так:
  
Excel.Range[Excel.Cells[1, 1],
Excel.Cells[5, 3]].Select;
или
  
Excel.Range[‘A1:C5’].Select;
при этом будет выделена область
находящаяся между ячейкой A1 и
C5.

После
выполнения выделения можно
установить:
1) объединение ячеек
  
Excel.Selection.MergeCells:=True;
2) перенос по словам
  
Excel.Selection.WrapText:=True;
3) горизонтальное выравнивание

  
Excel.Selection.HorizontalAlignment:=3;
при присваивании значения 1
используется выравнивание по
умолчанию, при 2 — выравнивание
слева, 3 — по центру, 4 —
справа.
4) вериткальное выравнивание
  
Excel.Selection.VerticalAlignment:=1;
присваиваемые значения
аналогичны горизонтальному
выравниванию.
5) граница для ячеек
  
Excel.Selection.Borders.LineStyle:=1;
При значении 1 границы ячеек
рисуются тонкими сплошными
линиями.
Кроме этого можно указать
значения для свойства Borders,
например, равное 3. Тогда
установится только верхняя
граница для блока выделения:
   Excel.Selection.Borders[3].LineStyle:=1;
Значение свойства Borders задает
различную комбинацию граней
ячеек.
В обоих случаях можно
использовать значения в
диапазоне от 1 до 10.

Использование паролей в
EXCEL

Установка
пароля для активной книги может
быть произведена следующим
образом:
try
   // попытка установить пароль
   Excel.ActiveWorkbook.protect(‘pass’);
except
   // действия при неудачной попытке установить пароль
end;
где pass — устанавливаемый
пароль на книгу.

Снятие пароля
с книги аналогично, использовуем
команду
Excel.ActiveWorkbook.Unprotect(‘pass’);
где pass — пароль, установленный
для защиты книги.

Установка и
снятие пароля для активного
листа книги Excel производится
командами
Excel.ActiveSheet.protect(‘pass’);
// установка пароля
Excel.ActiveSheet.Unprotect(‘pass’);
// снятие пароля
где pass — пароль, установленный
для защиты книги.

Вспомогательные операции в
EXCEL

Удаление
строк со сдвигом вверх:
   
Excel.Rows[‘5:15’].Select;
    Excel.Selection.Delete;
при выполнении данных действий
будут удалены строки с 5 по 15.

Установка
закрепления области на активном
листе Excel
   
 // снимаем закрепление области,
если оно было задано
   Excel.ActiveWindow.FreezePanes:=False;
     // выделяем нужную ячейку, в данном случае D3
   Excel.Range[‘D3’].Select;
     // устанавливаем закрепление области
   Excel.ActiveWindow.FreezePanes:=True;

Удачной работы!

Источник:

В данном обзоре рассмотрены
основные конструкции,
позволяющие получить доступ к
книге Excel из DELPHI.

Организация доступа к книге
EXCEL

Для
взаимодействия с MS excel в
программе необходимо
использовать модуль ComObj
uses ComObj;
и объявить переменную для
доступа к MS excel следующего
типа:
var Excel:
Variant;

Инициализация
переменной Excel в простейшем
случае можно осуществить так:
   
Excel := CreateOleObject(‘Excel.Application’);

Создание
новой книги:
   
Excel.Workbooks.Add;

Открытие
существующей книги (где
path
— путь к фалу с расширением xls.):
   
Excel.Workbooks.Open[path];

Открытие
существующей книги только для
чтения:
   
Excel.Workbooks.Open[path, 0,
True];

Закрытие
Excel:
   
Excel.ActiveWorkbook.Close;
    Excel.Application.Quit;

Блокировка
запросов (подтвеждений,
уведомлений) Excel, например,
запретить запрос на сохранение
файла:
   
Excel.DisplayAlerts:=False;

Отображаем
Excel на экране:
   
Excel.Visible := True;
или скрываем:
   
Excel.Visible := False;

Печать
содержимого активного листа
excel:
   
Excel.ActiveSheet.PrintOut;

Чтение/запись данных в EXCEL

Доступ к
ячейке в текущей книге Excel
можно осуществить следующим
образом:
   
Excel.Range[‘B2′]:=’Привет!’;-
для записи значения в ячейку или
   
s:=Excel.Range[‘B2’]; —
для чтения,
где B2
— адрес ячейки.

Или используя стиль ссылок R1C1:

   
Excel.Range[excel.Cells[2, 2]]:=’Привет!’;,
где [2, 2]
— координата ячейки.

Вообще, ячейке Excel можно
присваивать любое значение
(символьное, целое, дробное,
дата) при этом Excel установит
форматирование в ячейке
применяемое по умолчанию.

Формат ячеек в EXCEL

Выделить
(выбрать) группу ячеек для
последующей работы можно так:
  
Excel.Range[Excel.Cells[1, 1],
Excel.Cells[5, 3]].Select;
или
  
Excel.Range[‘A1:C5’].Select;
при этом будет выделена область
находящаяся между ячейкой A1 и
C5.

После
выполнения выделения можно
установить:
1) объединение ячеек
  
Excel.Selection.MergeCells:=True;
2) перенос по словам
  
Excel.Selection.WrapText:=True;
3) горизонтальное выравнивание

  
Excel.Selection.HorizontalAlignment:=3;
при присваивании значения 1
используется выравнивание по
умолчанию, при 2 — выравнивание
слева, 3 — по центру, 4 —
справа.
4) вериткальное выравнивание
  
Excel.Selection.VerticalAlignment:=1;
присваиваемые значения
аналогичны горизонтальному
выравниванию.
5) граница для ячеек
  
Excel.Selection.Borders.LineStyle:=1;
При значении 1 границы ячеек
рисуются тонкими сплошными
линиями.
Кроме этого можно указать
значения для свойства Borders,
например, равное 3. Тогда
установится только верхняя
граница для блока выделения:
   Excel.Selection.Borders[3].LineStyle:=1;
Значение свойства Borders задает
различную комбинацию граней
ячеек.
В обоих случаях можно
использовать значения в
диапазоне от 1 до 10.

Использование паролей в
EXCEL

Установка
пароля для активной книги может
быть произведена следующим
образом:
try
   // попытка установить пароль
   Excel.ActiveWorkbook.protect(‘pass’);
except
   // действия при неудачной попытке установить пароль
end;
где pass — устанавливаемый
пароль на книгу.

Снятие пароля
с книги аналогично, использовуем
команду
Excel.ActiveWorkbook.Unprotect(‘pass’);
где pass — пароль, установленный
для защиты книги.

Установка и
снятие пароля для активного
листа книги Excel производится
командами
Excel.ActiveSheet.protect(‘pass’);
// установка пароля
Excel.ActiveSheet.Unprotect(‘pass’);
// снятие пароля
где pass — пароль, установленный
для защиты книги.

Вспомогательные операции в
EXCEL

Удаление
строк со сдвигом вверх:
   
Excel.Rows[‘5:15’].Select;
    Excel.Selection.Delete;
при выполнении данных действий
будут удалены строки с 5 по 15.

Установка
закрепления области на активном
листе Excel
   
 // снимаем закрепление области,
если оно было задано
   Excel.ActiveWindow.FreezePanes:=False;
     // выделяем нужную ячейку, в данном случае D3
   Excel.Range[‘D3’].Select;
     // устанавливаем закрепление области
   Excel.ActiveWindow.FreezePanes:=True;

Удачной работы!




Подготовка

Откроем нашу среду разработки Delphi (в моем случае это Delphi 2010). Создадим новый проект. Должен сказать, что работа с Excel происходит через объекты COM. Поэтому нам надо подключить в раздел

USES

нашего проекта модуль

COMObj

. Так же нам понадобится модуль

ActiveX

. Это будет выглядеть примерно вот так:

unit Unit1;
 
interface
 
uses
  Windows,, ActiveX, COMObj;



Проверка наличия установленного Microsoft Excel в операционной системе

Теперь собственно нам нужно, как писалось выше, определить наличие Excel в системе. Если он не будет обнаружен, то мы сообщим об этом пользователю и завершим программу. Для этого создадим простенькую функцию и объявим её в секции

private

нашей формы

TForm1

:

private
    function CheckExcelInstalled(AValue: String): boolean;function TForm1.CheckExcelInstalled(AValue: String): boolean;
var
  FCLSID: TCLSID;
begin
  Result := (CLSIDFromProgID(PChar(AValue), FCLSID) = S_OK);
end;

Функция

CLSIDFromProgID

определена в модуле

ActiveX

и имеет следующее описание:

function CLSIDFromProgID(pszProgID: POleStr; out clsid: TCLSID): HResult;

Данная функция ищет

CLSID

, по соответствующему

ProgID

в реестре, в нашем случае мы ищем «Excel.Application». Если открыть реестр и перейти к ветке:


HKEY_LOCAL_MACHINESOFTWAREClasses

то там можно будет обнаружить много разделов. Среди них есть как раз нужный нам «Excel.Application» (при условии, что данное ПО установлено в системе). К сведению: у этого раздела имеется еще два подраздела:


HKEY_LOCAL_MACHINESOFTWAREClassesExcel.ApplicationCLSID

HKEY_LOCAL_MACHINESOFTWAREClassesExcel.ApplicationCurVer

Параметры функции:



pszProgID

: строка, содержащая ProgID.



clsid

: получает CLSID.

Возвращаемые значения:



S_OK

— CLSID создан успешно.



CO_E_CLASSSTRING

— CLSID зарегистрированный для ProgID неверен.



REGDB_E_WRITEREGDB

— ошибка записи в реестр.



E_OUTOFMEMORY

— нет памяти.



E_INVALIDARG

— указывает что один или более аргументов неверны. Стоит проверить правильность строки pszProgID.



E_UNEXPECTED

— неизвестная ошибка.

Теперь на событии

OnCreate

формы

TForm1

напишем следующий код:

procedure TForm1.FormCreate(Sender: TObject);
begin
  if not CheckExcelInstalled('Excel.Application') then
  begin
    Application.MessageBox(PChar('Для работы программы необходимо ' +
          'иметь установленное программное обеспечение Microsoft Excel.'#13#10
          + 'Приложение будет закрыто.'), 'Ошибка', MB_ICONERROR);
    Halt;
  end;
end;

При загрузке приложения ищем наличие Excel в системе. Если не находим, то выводим сообщение пользователю и закрываем программу с помощью метода

Halt

. Если находим, то просто показываем форму.



Проверить, запущен ли Microsoft Excel

Далее давайте кинем на форму одну кнопку TButton. На событии

OnClick

будем писать код работы с Excel. Первое что мы сделаем, это добавим локальную переменную типа

Variant

для доступа к Excel с именем, например,

FExcel

:

Теперь определимся, что мы хотим. Я всегда создавал новый экземпляр экселя, даже если он был уже запущен в системе. Но я это не вы. Поэтому я покажу вам, как можно использовать уже запущенный Excel. Создадим функцию и объявим ее так же в секции

private

:

privatefunction CheckExcelRun(AValue: String; var ADest: Variant): boolean;function TForm1.CheckExcelRun(AValue: String; var ADest: Variant): boolean;
begin
  try
    ADest := GetActiveOleObject(AValue);
    Result := true;
  except
    Result := false;
  end;
end;

Функция

GetActiveOleObject

определена в модуле

COMObj

и имеет следующее описание:

function GetActiveOleObject(const ClassName: string): IDispatch;

Функция возвращает ссылку на интерфейс

IDispatch

активного OLE-объекта указанного класса. Она использует информацию из таблицы активных объектов OLE (OLE running object table). Идентификатор класса объекта OLE в таблице активных объектов OLE передается в параметре

ClassName

. При невозможности выполнения функции GetActiveOleObject возникает исключение EOleSysError.

Теперь как пользоваться нашей функцией:

procedure TForm1.Button1Click(Sender: TObject);
var
  FExcel: Variant;
begin
  if not CheckExcelRun('Excel.Application', FExcel) then
    Exit;
end; 

Стоить пояснить. Если в системе запущена программа Excel, то функция

GetActiveOleObject

находит его, при этом функция

CheckExcelRun

возвращает

TRUE

. Ссылка на интерфейс передается через параметр «var ADest» нашей созданной переменной

FExcel

. Теперь вы можете работать с этим экземпляром Excel. Если же запущенный эксель не найден, то функция

GetActiveOleObject

вызывает исключение, простыми словами выходит ошибка. Поэтому мы поместили эту функцию в блок

try…except…end

. Вот в секции

except

мы присваиваем результат

FALSE

и т.о. выходим из процедуры

Button1Click

с помощью метода

Exit

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



Создание нового экземпляра Microsoft Excel

Создать новый экземпляр можно с помощью функции

CreateOleObject

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

 procedure TForm1.Button1Click(Sender: TObject);
var
  FExcel: Variant;
begin
  try
    // Создаем новый экземпляр Excel
    FExcel := CreateOleObject('Excel.Application');
    FExcel.Visible := true;
    ... // Тут ваш код
  finally
    // Если переменная не пустая, то...
    if not VarIsEmpty(FExcel) then
    begin
      // ...отключаем диалог с вопросом сохранять ли файл при выходе или нет
      FExcel.DisplayAlerts := false;
      // Закрываем Excel
      FExcel.Quit;
      // Присваиваем неопределенный тип, освобождая при этом 
      // процесс excel.exe, чтобы он мог завершиться. Если этого не
      // сделать, то процесс останется висеть в памяти.
      FExcel := Unassigned;
    end;
  end;
end;

Функция

VarIsEmpty

определена в модуле

Variants

и имеет следующее описание:

function VarIsEmpty(const V: Variant): Boolean;

Функция проверяет, определен ли тип значения

Variant

-переменной. Возвращает

TRUE

, если переменная имеет неопределенный тип (Unassigned). Если типу переменной соответствует значение какой-либо константы

VarType

типа

TVarData

, то функция возвращает

FALSE

.



Операции над программой Microsoft Excel из Delphi

Теперь давайте рассмотрим, что вообще можно делать с Excel из Delphi. Операций достаточно много. И все описать просто невозможно. Но если в моем описании не окажется нужного вам метода, то огорчаться не стоит. Методы можно узнать самому. Открываете Excel. Затем в меню

Сервис – Макрос – Начать запись

. Там жмем ОК и выполняем необходимые нам операции в Excel. Когда закончите, жмем на

Стоп

. Затем нажимаем комбинацию клавиш

Alt+F11

и перед нами открывается

редактор Visual Basic

. Вот в нем слева вверху есть древовидный список. В нем находится папка с названием

Modules

. В свою очередь в ней располагаются модули. Вот эти модули и есть ваши макросы. Кликнем два раза на тот модуль, который мы только что записали (если это первая запись, то модуль будет один). И тут будут отображены все ваши действия в виде исходного кода на языке Visual Basic. Вам остается только перевести это дело на Delphi.

По поводу констант. В Delphi придется объявлять их самим. Посмотреть чему они равны можно в том же редакторе Visual Basic. Делается это так. Вписываем любую нужную нам константу в редакторе. Кликаем правой клавишей мыши, чтобы появилось контекстное меню. И там выбираем пункт

«Quick Info»

. При этом будет показана всплывающая подсказка со значением этой константы. Все просто! Единственное оговорюсь. В Visual Basic будет показано так, например:

&HFFFFEFF4

, но Delphi этого не поймет. Надо объявлять в нем так:

$FFFFEFF4

.


Работа с окном (формой) Excel


FExcel.Visible := true;


Делать Excel видимым (True)/не видимым(False). При установке

Visible

в

FALSE

, программа Excel Так же пропадает из панели задач Windows.


FExcel.Application.EnableEvents := false;


Показывать (True)/не показывать(False) системные сообщения Excel. Рекомендую отключать сообщения при построении отчета. А сам код писать после создания экземпляра Excel. Это увеличит скорость создания отчета. Пример:

FExcel := CreateOleObject('Excel.Application');
FExcel.Visible := false;
FExcel.Application.EnableEvents := false;


FExcel.DisplayAlerts := false;


Показывать (True)/не показывать(False) предупреждающие сообщения.


FExcel.WindowState := xlMaximized;


Состояние окна Excel:


const xlMaximized = $FFFFEFD7 (или -4137)

— развернуть Excel на весь экран.


const xlNormal = $FFFFEFD1 (или -4143)

— восстановить Excel.


const xlMinimized = $FFFFEFD4 (или -4140)

— свернуть Excel на панель задач.


FExcel.ScreenUpdating := false;


Включить (True)/отключить (False) перерисовку окон. Используется для ускорения работы макроса, т.к. в это время не обновляется экран. Я в своих проектах не использовал данный метод, но возможно построение отчета будет выполняться быстрее, если отключить обновление окон Excel. После построения отчета перерисовку окон можно будет включить обратно.


Работа над книгой (Workbooks)


FExcel.Workbooks.Open(path);


Открытие существующей книги (где path — путь к фалу). Функция Open описана так:

function Open(
  const Filename: String; 
  UpdateLinks: Variant; 
  ReadOnly: Variant;
  Format: Variant; 
  Password: Variant; 
  WriteResPassword: Variant; 
  IgnoreReadOnlyRecommended: Variant; 
  Origin: Variant;
  Delimiter: Variant; 
  Editable: Variant; 
  Notify: Variant;
  Converter: Variant; 
  AddToMru: Variant
): Workbook;


FileName

— обязательный элемент. Имя открываемого файла, желательно с полным путем, иначе Excel будет искать этот файл в каталоге по умолчанию;


UpdateLinks

— Необязательный параметр. Определяет способ обновления связи в открываемом файле. Если данный аргумент отсутствует, то пользователю будет выдан запрос на определение способа обновления связей. Данный параметр имеет следующие допустимые значения:

0 – никакие связи не обновляются;

1 – обновляются внешние ссылки, но не обновляются удаленные ссылки;

2 – обновляются удаленные ссылки, но не обновляются внешние ссылки;

3 – обновляются оба типа ссылок


ReadOnly

— необязательный параметр. Если файл имеет атрибут только для чтения, то при открытии его в Excel выдается соответствующее предупреждение*. Чтобы его игнорировать, передайте в качестве данного параметра True.


Format

— необязательный параметр. При открытии текстового файла этот параметр определяет вид символов-разделителей. Ниже представлены допустимые значения данного аргумента:

1 – символы табуляции;

2 – запятые;

3 – пробелы;

4 – точка с запятой;

5 – разделители отсутствуют;

6 – вид разделителя определяется пользователем (с помощью параметра Delimiter).


Password

— необязательный параметр, задающий строку пароля, необходимого для открытия защищенной рабочей книги. Если при открытии защищенной книги данный аргумент отсутствует, то пользователю будет выдан запрос на ввод пароля*.


WriteResPassword

— необязательный параметр. Предназначен для задания пароля, необходимого для записи в рабочую книгу. Если при открытии защищенной книги данный аргумент отсутствует, то пользователю будет выдан запрос на ввод пароля*.


IgnoreReadOnlyRecommended

— необязательный параметр. В случае задания ему значения True этот аргумент позволяет устранить вывод сообщения с рекомендацией открытия книги только для чтения (в том случае, если данная рабочая книга была сохранена с параметром Read-Only Recommended).


Origin

— необязательный параметр. При открытии текстового файла этот параметр указывает, где был создан этот файл, что необходимо для правильного распознавания страницы кодировки. Значениями данного аргумента может быть одна из констант: xlMacintosh, xlWindows или xlMSDOS**. Если данный аргумент отсутствует, то используются текущие параметры операционной системы.


Delimiter

— необязательный параметр. Если открывается текстовый файл и параметр Format имеет значение, равное 6, то этот аргумент определяет символ-разделитель.


Editable

— необязательный параметр. Если файл является файлом MS Excel 4.0, то этот параметр при задании ему значения True позволяет открыть надстройку как видимое окно. По умолчанию ему присвоено значение False.


Notify

— необязательный параметр. Если файл не может быть открыт для записи, то при задании данному аргументу значения True файл будет добавлен в список уведомления. Если данный аргумент равен False или отсутствует, то открыть файл будет невозможно.


Converter

— необязательный параметр. Предназначен для определения индекса фильтра, который будет использован при открытии данного файла. Если фильтр не сможет распознать формат файла, то будут последовательно использованы все доступные фильтры.


AddToMRU

— необязательный параметр типа Variant. Если данный параметр имеет значение True, то рабочая книга будет добавлена в список недавно использованных файлов. По умолчанию ему присвоено значение False.



Примечание:


* Сообщения будут выведены на экран, если вы не отключили их с помощью:


FExcel.Application.EnableEvents := false;


Показывать (True)/не показывать(False) системные сообщения Excel.

** Delphi не знает о существовании констант, поэтому чтобы посмотреть их значения, нужно воспользоваться средствами VBA. Эти константы соответственно равны 1, 2 и 3.

***


FExcel.SheetsInNewWorkbook := X;


Задать количество страниц в книге, где X — это количество страниц. Диапазон значений 1..255. Данный метод применяется только с


FExcel.Workbooks.Add;


и в коде Delphi пишется перед методом Add.


FExcel.Workbooks.Add(path);

// path — путь к фалу

Создание новой книги. Причем создается стандартная книга с тремя листами. В этом методе можно указать стандартный тип шаблона Excel. Если же в нем указать имя (с полным путем) подготовленного файла (шаблоном может быть и «обычный» файл XLS, а не только файл XLT), то можно открыть книгу на диске как шаблон.


FExcel.Workbooks.Add(Template);


Template — Необязательный параметр. Этот параметр определяет, как будет создана рабочая книга. Если этот параметр будет иметь значение строки, определяющей имя файла (включая путь) существующей рабочей книги, то создается рабочая книга с использованием данного файла как шаблона. В случае когда данный параметр является одной из констант:

xlWBATExcel4IntlMacroSheet = 4;



xlWBATExcel4MacroSheet = 3;



xlWBATWorksheet = $FFFFEFB9 (или -4167);



xlWBATChart = $FFFFEFF3 (или -4109);


Создаваемая книга будет содержать один лист соответствующего типа. В том случае, если этот параметр отсутствует, то создается рабочая книга с количеством листов, определяемым значением свойства

SheetslnNewWorkbook

.

***


FExcel.Workbooks[1].SaveAs(path);

// path — путь к фалу

Сохранить книгу как… Чтобы укоротить код можно создать переменную

FWorkbook

типа

Variant

и присвоить ей ссылку либо на первую[1] книгу, либо на вновь созданную:


FWorkbook := FExcel.Workbooks[1];

либо

FWorkbook := FExcel.Workbooks.Add;


Тогда сохранение может выглядеть вот так:


FWorkbook.SaveAs(path);

// path — путь к фалу

Функция SaveAs описана так:

function SaveAs(
  FileName: Variant; 
  FileFormat: Variant; 
  Password: Variant;
  WriteResPassword: Variant;
  ReadOnlyRecommended: Variant;
  CreateBackup: Variant;
  AccessMode: Variant;
  ConflictResolution: Variant;
  AddToMru: Variant;
  TextCodePage: Variant;
  TextVisualLayout: Variant
): Workbook;


FileName

— необязательный параметр. Задает строку, определяющую имя сохраняемого файла. Можно указать полный путь или только имя файла (в этом случае файл будет сохранен в текущей папке).


FileFormat

— необязательный параметр. Данный параметр задает формат файла. Его значением может быть одна из констант, описанных в

таблице 1

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

Формат                                            Константа
 
Книга MS Excel                                    xlWorkbookNormal
Web-страница                                      xlHTML
Шаблон                                            xlTemplate
Текстовые файлы (с разделителями табуляции)       xlTextWindows
Текст Юникод                                      xlUnicodeText
Книга MS Excel 5.0/95                             xlExcel7
Книга MS Excel 95/97/2000                         xlExcel9795
CSV (разделители – запятые)                       xlCSVWindows
Файл MS Excel 4.0                                 xlExcel4
Файл MS Excel 3.0                                 xlExcel3
Файл MS Excel 2.1                                 xlExcel2
Книга MS Excel 4.0                                xlExcel4Workbook
WK4 (1-2-3)                                       xlWK4
WK3, FM3 (1-2-3)                                  xlWK3FM3
WK3 (1-2-3)                                       xlWK3
WK1, FMT (1-2-3)                                  xlWK1FMT
WK1, ALL (1-2-3)                                  xlWK1ALL
WK1 (1-2-3)                                       xlWK1
WKS (1-2-3)                                       xlWKS
WQ1 (Quattro Pro/Dos)                             xlWQ1
DBF4 (dBase IV)                                   xlDBF2
DBF3 (dBase III)                                  xlDBF3
DBF2 (dBase II)                                   xlDBF4
Форматированный текст (разделители – пробелы)     xlTextPrinter
Текст (Macintosh)                                 xlTextMac
Текст (MS-DOS)                                    xlTextMSDOS
CSV (Macintosh)                                   xlCSVMac
CSV (MS-DOS)                                      xlCSVMSDOS
DIF (Data Interchange Format)                     xlDIF
SYLK (Symbolic Link)                              xlSYLK
Надстройка MS Excel                               xlAddln

Таблица 1 — Форматы файлов MS Excel 2000 и соответствующие им константы.


Password

— необязательный параметр. Данный параметр определяет защитный пароль для сохраняемого файла. Пароль определяется строкой, содержащей не более 15 символов.


WriteResPassword

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


ReadOnlyRecommended

— необязательный параметр. В случае присвоения ему значения True, последующее открытие файла на экране будет сопровождаться сообщением, говорящим о том, что этот файл рекомендуется открыть в режиме только для чтения.


CreateBackup

— необязательный параметр. Определяет возможность создания резервного файла (значение True).


AccessMode

— необязательный параметр. Этот параметр определяет режим доступа к рабочей книге и может иметь одно из следующих значений:

xINoChange – режим доступа не изменяется (равно 1);

xlShared – общие листы (равно 2);

xlExclusive – монопольный доступ (равно 3).


ConflictResolution

— необязательный параметр. Определяет способ разрешения конфликтов в том случае, если книга имеет общие листы. Значением данного свойства может быть значение одной из констант:

xlUserResolution — отображает окно диалога для разрешения конфликтов (равно 1);

xlLocalSessionChanges — автоматически принимаются изменения локального пользователя (равно 2);

xlOtherSessionChanges — принимаются другие изменения вместо изменений локального пользователя (равно 3).


AddToMru

— необязательный параметр. Позволяет поместить сохраняемый файл в список сохраненных файлов в меню Файл (File). Для реализации этой возможности значение этого аргумента должно равняться True.


TextCodePage

— необязательный параметр. В локализованной версии MS Office не используется.


TextVisualLayout

— необязательный параметр. В локализованной версии MS Office не используется.

***


FWorkbook.Save;


Если книга была открыта, то файл перезапишется. Если была создана новая книга, то будет задан вопрос о сохранении файла. Если вы нажмете «Нет», то будет вызвано исключение.


FWorkbook.Close;


Закрыть книгу. При этом если Excel видимый, то появится диалог с вопросом, хотите ли вы сохранить файл.

Функция Close описана так:

function Close(
  SaveChanges: Variant; 
  FileName: Variant; 
  RouteWorkbook: Variant
): Workbook;


SaveChanges

— Необязательный элемент. Если данный параметр опущен, то будет выдан запрос на сохранение файла. Если равен

FALSE

, то книга закроется без сохранения и каких-либо оповещений, даже при установленном параметре

FileName

. Если равен

TRUE

, то сразу появится проводник с предложением выбрать место, куда сохранить файл. При установленном параметре FileName, книга будет сохранена без появления каких-либо диалогов.


FileName

— Необязательный элемент. Данный параметр определяет имя файла, в который будут записаны изменения.


RouteWorkbook

— Необязательный элемент. Если он имеет значение True, то рабочая книга будет послана следующему получателю.



Примечание:

если файл уже существует, то тогда будет выведен диалог с вопросом о перезаписи файла.


Пример:

// Отключаем предупреждающие сообщения,
// в нашем случае чтобы не было вопроса о том,
// перезаписывать ли файл, если таковой существует
FExcel.DisplayAlerts := false;
// Сохраняем книгу в файл "123.xls" на диск D:
FWorkbook.Close(true, 'D:123.xls');


Установка параметров страницы, предварительный просмотр и печать


FExcel.Workbooks[1].WorkSheets[1] .Name := ‘Отчёт’;


Присваиваем первому листу в первой книге имя «Отчет». Если будем работать с самим листом, то чтобы не писать много кода мы можем просто объявить новую переменную, например,

FSheet

типа

Variant

:

 procedure TForm1.Button1Click(Sender: TObject);
var
  FExcel, FSheet: Variant;
begin
  try
    ... // Тут ваш код
  finally
    ...
      // Обязательно! нужно все созданные Variant-переменные 
      // очищать перед выходом
      FSheet := Unassigned;
      FExcel := Unassigned;
    ...
  end;
end;



Примечание

: в принципе Delphi сама следит за корректным удалением переменных, но я считаю будем правильным сделать это вручную. Не стоит полагаться на систему.

И присвоим ей ссылку на наш Лист1 первой книги:

FSheet := FExcel.Workbooks[1].WorkSheets[1];
FSheet.Name := 'Отчёт';

Вот так вот будет проще. Теперь мы будет обращаться уже к переменной

FSheet

, а не к

FExcel

.


FSheet.PageSetup.Orientation := 2;


Ориентация страницы (1 – книжная, 2 – альбомная).


FSheet.PageSetup.LeftMargin := X;


Отступ от левого края страницы


FSheet.PageSetup.RightMargin := X;


Отступ от правого края страницы


FSheet.PageSetup.TopMargin := X;


Отступ от верхнего края страницы.


FSheet.PageSetup.BottomMargin := X;


Отступ от нижнего края страницы.


FSheet.PageSetup.HeaderMargin := X;


Высота верхнего колонтитула страницы.


FSheet.PageSetup.FooterMargin := X;


Высота нижнего колонтитула страницы.

Где X — это отступ в пикселях. Можно в принципе воспользоваться функцией перевода из, например, сантиметров в пиксели. Делается это так:


FSheet.PageSetup.BottomMargin := FExcel.Application.CentimetersToPoints(1.5);


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


FSheet.PageSetup.Zoom := false (или значение в процентах Z);


Масштаб. Принимает следующие значения:


Z

— «Установить Z% от натуральной величины», где X – это количество процентов. Т.е. если вы решите включить масштабирование, то вам необходимо вместо

FALSE

подставить число, например: FSheet.PageSetup.Zoom := 100; (что означает 100%).


FALSE

— «Разместить не более чем на: X стр. в ширину и Y стр. в высоту, где:


FSheet.PageSetup.FitToPagesWide := 1;


Количество страниц в ширину (X).


FSheet.PageSetup.FitToPagesTall := 100;


Количество страниц в высоту (Y).


FSheet.PageSetup.CenterFooter := ‘Стр. &С из &К’

;

Центральный нижний колонтитул. В нем будет информации о номере страницы из всего страниц. Данные переменные (&C, &K и т.п.) описаны в справочнике самого Excel. Аналогично:


FSheet.PageSetup.LeftFooter:=’Левый нижний колонтитул’;

FSheet.PageSetup.RightFooter:=’Правый нижний колонтитул’;

FSheet.PageSetup.LeftHeader:=’Левый верхний колонтитул’;

FSheet.PageSetup.CenterHeader:=’Центральный верхний колонтитул’;

FSheet.PageSetup.RightHeader:=’&7Правый верхний колонтитул’;

*



Примечание:

*для изменения размера шрифта добавьте к колонтитулу управляющий символ «&» и размер шрифта, в нашем случае 7


// const xlAutomatic = $FFFFEFF7 (или -4105)



FSheet.PageSetup.FirstPageNumber := xlAutomatic;


Номер первой страницы. В данном случае «Авто».


FSheet.PageSetup.Order := 1;


Последовательность вывода страниц на печать (1 — вниз, затем вправо; 2 — вправо, затем вниз).


FSheet.PrintPreview;


Предварительный просмотр страницы. Если вы не продолжите печать, а нажмете «Отмена», то будет вызвано исключение.



Примечание

: Excel, перед выполнением этой команды, обязательно должен быть видимым (FExcel.Visible := true;).


FSheet.PrintOut;


Вывод страницы на печать. Функция PrintOut описана так:

function PrintOut(
  From: Variant; 
  To: Variant; 
  Copies: Variant;
  Preview: Variant;
  ActivePrinter: Variant;
  PrintToFile: Variant;
  Collate: Variant
): Workbook;


From

— необязательный параметр. Задает страницу, с которой начинается печать. Если этот аргумент отсутствует, то печать начинается с первой страницы.


To

— необязательный параметр. Задает последнюю печатаемую страницу. Если этот аргумент отсутствует, то печать продолжается до последней страницы.


Copies

— необязательный параметр. Задает количество печатаемых копий.


Preview

— необязательный параметр, принимающий одно из двух значений:


TRUE

— приводит к выводу перед печатью окна предварительного просмотра;


FALSE

(значение по умолчанию) — печать производится без предварительного просмотра.


ActivePrinter

— необязательный параметр. Задает имя активного принтера.


PrintToFile

— необязательный параметр. Если данный параметр имеет значение True, то производится печать в файл. При этом пользователю выдается запрос на ввод имени файла.


Collate

— необязательный параметр. Если ему задать значение True, то копии будут объединены.

Пример:

FExcel.Application.EnableEvents := true;
FExcel.DisplayAlerts := true;
FExcel.Visible := true;
FSheet.PrintOut(1, 2, 1, False, PrintToFile := True)

Печатаем с 1 по 2 страницы, одну копию, без предварительного просмотра в файл. Заметьте, что мы пропустили параметр ActivePrinter. Мы просто объявили PrintToFile := True.

***



Статья не окончена. Продолжение следует…

При составлении справочника я использовал собственные наработки и информацию со следующих сайтов:

1)

www.taurion.ru/excel

2)

www.superadm.net/index.php?name=pages&op=cat&id=19

3)

www.afalinasoft.com/rus/tips/

4)

www.codenet.ru/progr/delphi/stat/Excel-Export.php

Так же не обошлось без составления макросов в редакторе Visual Basic и последующим переводом кода из VBA в среду разработки Delphi 2010.

Понравилась статья? Поделить с друзьями:
  • Считать число ячеек в excel
  • Сын полка скачать книгу word
  • Сым мы сым for excel
  • Считать только цифры excel
  • Съешь еще этих мягких французских булок да выпей чаю word