Группы и рассылки:

Вы здесь

Читаем файл Excel (xls) в Delphi

Версия для печати

При написании бизнес приложений на Delphi, выполняющих какие либо расчеты, может возникнуть необходимость импорта (экспорта) данных из файлов других приложений. Одно из основных таких приложений – MS Excel. Как прочитать файлы xls в Delphi мы сейчас и рассмотрим!?

Создадим новый проект и разместим на форме три компонента:

StringGrid – находится на палитре компонентов, во вкладке Additional

stringgrid в delphi

Кнопку Button и для удобства выбора файлов, диалог открытия файлов (работа с диалогами описана здесь).

Для StringGrid, в свойствах(Properties) укажем следующее:
DefaultRowHeight – 17
FixedCols – 0
FixedRows – 0

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

На этом украшательства закончим и приступим к написанию кода.

Для работы с Excel файлами нам понадобится библиотека ComObj, входящая в стандартную поставку Delphi. Подключается она в разделе Uses. Добавьте в конце, после запятой «ComObj».

Теперь опишите процедуру Xls_Open после ключевого слова implementation:

procedure Xls_Open(XLSFile:string; Grid:TStringGrid);
 const
  xlCellTypeLastCell = $0000000B;
var
  ExlApp, Sheet: OLEVariant;
  i, j, r, c:integer;

begin
  //создаем объект Excel
  ExlApp := CreateOleObject('Excel.Application');

  //делаем окно Excel невидимым
  ExlApp.Visible := false;

  //открываем файл XLSFile
  ExlApp.Workbooks.Open(XLSFile);

  //создаем объект Sheet(страница) и указываем номер листа (1)
  //в книге, с которого будем осуществлять чтение
  Sheet := ExlApp.Workbooks[ExtractFileName(XLSFile)].WorkSheets[1];

  //активируем последнюю ячейку на листе
  Sheet.Cells.SpecialCells(xlCellTypeLastCell, EmptyParam).Activate;

    // Возвращает номер последней строки
    r := ExlApp.ActiveCell.Row;

    // Возвращает номер последнего столбца
    c := ExlApp.ActiveCell.Column;

    //устанавливаем кол-во столбцов и строк в StringGrid
    Grid.RowCount:=r;
    Grid.ColCount:=c;

    //считываем значение из каждой ячейки и копируем в нашу таблицу
     for j:= 1 to r do
       for i:= 1 to c do
         Grid.Cells[i-1,j-1]:= sheet.cells[j,i];
        //если необходимо прочитать формулы то
       //Grid.Cells[i-1,j-1]:= sheet.cells[j,i].formula;

 //закрываем приложение Excel
 ExlApp.Quit;

 //очищаем выделенную память
 ExlApp := Unassigned;
 Sheet := Unassigned;

end;

Наша процедура Xls_Open имеет два входных параметра:

  1. XLSFile – путь к файлу Excel (xls)
  2. Grid – таблица, в которую будем осуществлять вывод данных.

В комментариях к коду я постарался все расписать, объясню немного принцип работы процедуры.

Мы создаем в памяти объект ExlApp с приложением Excel.Application. Затем указываем что этот объект будет невидим для пользователя ExlApp.Visible := false (если false заменить на true, то при открытии файла мы увидим окно Excel с открываемым файлом). Далее открывается файл ExlApp.Workbooks.Open(XLSFile). Потом создаем еще один объект Sheet, который позволяет работать с листом книги Excel: Sheet := ExlApp.Workbooks[ExtractFileName(XLSFile)].WorkSheets[1]. Единица в конце указывает номер листа с которого будем читать данные (к листам можно обращаться по имени, для этого вместо 1 указываем «ИмяЛиста1»). Далее определяем кол-во строк и столбцов которые содержат данные, и используя циклы For считываем данные копируя их в StringGrid. Впринципе и все.

Для использования процедуры  Xls_Open пропишем в событие Click кнопки Button1 следующее:

If OpenDialog1.Execute then Xls_Open (OpenDialog1.FileName, StringGrid1);

Основные недостатки этого способа: медленное чтение данных (хотя для небольших файлов вполне сгодится) и необходимость установленной версии Excel на компьютере пользователя.

Полный листинг программы:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Grids, StdCtrls,ComObj;

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    Button1: TButton;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure Xls_Open(XLSFile:string; Grid:TStringGrid);
 const
  xlCellTypeLastCell = $0000000B;
var
  ExlApp, Sheet: OLEVariant;
  i, j, r, c:integer;

begin
  //создаем объект Excel
  ExlApp := CreateOleObject('Excel.Application');

  //делаем окно Excel невидимым
  ExlApp.Visible := false;

  //открываем файл XLSFile
  ExlApp.Workbooks.Open(XLSFile);

  //создаем объект Sheet(страница) и указываем номер листа (1)
  //в книге, с которого будем осуществлять чтение
  Sheet := ExlApp.Workbooks[ExtractFileName(XLSFile)].WorkSheets[1];

  //активируем последнюю ячейку на листе
  Sheet.Cells.SpecialCells(xlCellTypeLastCell, EmptyParam).Activate;

    // Возвращает номер последней строки
    r := ExlApp.ActiveCell.Row;

    // Возвращает номер последнего столбца
    c := ExlApp.ActiveCell.Column;

    //устанавливаем кол-во столбцов и строк в StringGrid
    Grid.RowCount:=r;
    Grid.ColCount:=c;

    //считываем значение из каждой ячейки и копируем в нашу таблицу
     for j:= 1 to r do
       for i:= 1 to c do
         Grid.Cells[i-1,j-1]:= sheet.cells[j,i];
        //если необходимо прочитать формулы то
       //Grid.Cells[i-1,j-1]:= sheet.cells[j,i].formula;

 //закрываем приложение Excel
 ExlApp.Quit;

 //очищаем выделенную память
 ExlApp := Unassigned;
 Sheet := Unassigned;

end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  If OpenDialog1.Execute then Xls_Open (OpenDialog1.FileName, StringGrid1);
end;

end.

 

Обновленный пример. Добавлена функция отбора строк по критерию. Так же добавлен обработчик делающий отображение шрифта "шапки" в StringGrid жирным. Все дополнения постарался по максимуму раскомментить

Прикрепленный файл: excel_open_in_delphi.zip

 

Автор: 
Deys

Комментарии

Спасибо за статью. А как сделать так, чтобы на вход программы загружался XLS, пользователь вводил бы
фамилию, а на выходе бы получал все строки, где эта фамилия присутствует? и желательно получал бы в виде тхт файла. ну или xls.

Таблица такая: Дата/Время|Фамилия|Имя|Отчество|Должность|Направление

 

Для запуска процедуры Xls_Open Вам необходимо поместить эту процедуру в событие FormCreate. Это событие создается если кликнуть два раза по пустому полю формы. Для ввода критериев отбора в цикле for необходимо добавить условие if сравнивающее значение ячейки с критерием, если совпадает то выводим в таблицу. Оставьте свой эл. адрес, сброшу пример.

 

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

 

Да, можно.
в секции
for j:= 1 to r do
for i:= 1 to c do

изменяем Grid.Cells[i-1,j-1]:= sheet.cells[j,i];

на if sheet.cells[j,i] = "текстовый тип" then Grid.Cells[k,l]:= sheet.cells[j,i];
где k,l - переменные, координаты ячейки в Grid.

 

Тогда нужо будет еще два цикла писать получается ?&nbsp;<br />
&nbsp;for l := 1 to r do&nbsp;<br />
&nbsp;for k :=1 to c do<br />
как то так что ли, а они конфликтовать так не будут ? многовато циклов просто&nbsp;&nbsp;

 

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

 

Добрый день.
Наконец-то добрался до ответа. В приложенном файле проект с добавленние условия отбора. Отбор по должности (XLS приложен). Так же добавлены несколько процедур для примера, таких как очистка StringGrid, выделение заголовка таблицы жирным шрифтом. Весь код постарался по максимуму раскомментировать. Надеюсь будет понятно.

Прикрепленный файл: Excel_Open_If_in_Delphi.zip

 

Доброго времени суток.
Заранее прошу прощения за дурной вопрос, но все же:
в исходнике - экселевская таблица, в которой юзаются только 5 столбцов.
необходимо сделать поиск по содержимому каждого отдельно взятого столбца, алгоритм поиска есть.
Вопрос, как реализовать работу с данными определенного столбца и как заставить выводить в СтрингГрид только пять столбцов и ничего более.. а ну и длину столбцов ограничить реально существующим содержимым, чтоб не было кучи пустых ячеек внизу..
Буду очень благодарен за помощь
samotoywork@gmail.com

 

У меня отображается только первый лист, а их три, как сделать чтобы можно было выбрать другой лист?

 
 //создаем объект Sheet(страница) и указываем номер листа (1)
  //в книге, с которого будем осуществлять чтение
  Sheet := ExlApp.Workbooks[ExtractFileName(XLSFile)].WorkSheets[2]; это второй лист
  Sheet := ExlApp.Workbooks[ExtractFileName(XLSFile)].WorkSheets[3]; это третий лист и т.д.
 
нужно сделать программу, в которой надо искать  в таблице для первой строчки похожую строчку по критериям (значение соответствующих 3 ячеек было меньше какого-то числа) до конца таблицы. Каждую обнаруженную 
пару выводить на печать. Далее такую же процедуру надо осуществить со второй, с третьей и т.д. строчкой.
 

Здраствуйте. что делать если открывает мелкие файлы а чуть больше уже нет

 

На сколько больший файл?

Сколько строк?

 

Здравствуйте! Ответьте пожалуйста, как надо дорабоатать ваш проект, чтобы было, например, 3 фильтра по поиску. ТО есть делаем три разных Edit, в каждом пишем нужное значение и чтобы при нажатии на одну кнопку выполнялся сразу по трем строчкам?

или хотя бы по двум. Возможно ли такое?

 

Добрый день, Идель!

Меняете следующее:

procedure Xls_Open_filter(XLSFile:string; Grid:TStringGrid; criterion1,criterion2,criterion3:string);
.......
//остальное без изменений
.......
 if (trim (lowercase(sheet.cells[j,5]))=trim(lowercase(criterion1))) or (trim (lowercase(sheet.cells[j,5]))=trim(lowercase(criterion2))) or (trim (lowercase(sheet.cells[j,5]))=trim(lowercase(criterion3))) then
.......

Это условие задает 3 критерия отбора из одного столбца, если из разных столбцов то:

if (trim (lowercase(sheet.cells[j,5]))=trim(lowercase(criterion1))) and (trim (lowercase(sheet.cells[j,6]))=trim(lowercase(criterion2))) and (trim (lowercase(sheet.cells[j,7]))=trim(lowercase(criterion3))) then

 

 

Спасибо за ответ. Помогите пожалуйста еще раз. Обрыл весь инет, нормального и четкого кода не нашел. При нажатии на кнопку нужно открывать определенный файл excel. (ПУсть будет testing.xls). То есть нужно обойтись без OpenDialog как я понимаю . Как это сделать?!

 

Если Вам нужно жестко привязаться к определенному файлу то используйте так на событие кнопки:

Xls_Open ('c:\testing.xls', StringGrid1);

 

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

 

Разобрался. Все получилось. Забыл OpenDialog удалитью Спасибо!   Как бы еще сделать так, чтобы прописывать путь домашней папки....

ТО есть, например,

сам ехе-шник у меня в 'D:\Универ\VI\XII\Delphi 7[22.05]'

а нужный excel-файл в 'D:\Универ\VI\XII\Delphi 7[22.05]\Excel\Характеристики линий\Х8Ш.xlsx'

Предполагается, что я перекину свою общую папку, в которой будет вся программа, на флэшку. (Папка "Delphi 7[22.05]")

Как мне тогда прописать путь?

Xls_Open ('GetCurrentDir\Excel\Характеристики линий\Х8Ш.xlsx', StringGrid1);   ??? НЕ ПРОХОДИТ ТАК

 

Разобрался. Спасибо.

Правильно будет так в моем случае.

Xls_Open (Extractfilepath(paramstr(0))+'Excel\Характеристики линий\Х8Ш.xlsx', StringGrid1);

 

Что дописать,что бы при нажатии на кнопку сортировка производилась сортировка по критериям: ГОД МЕСЯЦ ДЕНЬ

 

файл в 10'000 строк,программа виснет,что делать.

 

Как сделать сортировку порядку от меньшего к большему.

 

Как сделать,чтобы при нажатии на кнопку сортировка выводились программа находила одинаковые значения в 3 и 7 столбце и выводила их в string grid.

 

Большое спасибо за статью!
Я только начинаю разбираться с программированием в Дельфи. До этого имел только опыт программирования в VBA.
Очень подробно все написано, даже для не профессионала.
Однако есть изъян в изложении, а именно как открыть файл Ексель из Делфи. Вопрос освещен очень поверхностно. Возможно для профессионального программиста все понятно, но для меня совершенно не понятно.
Ясно одно, что так как записано в коде - работать не будет. Нужно указать путь, где этот файл находится. Программа сама найти не сможет. И что это за конструкция XLSFile. ничего не сказано. То ли это название экселевского файла, то ли это комбинация какого то действия XLS с файлом (видимо вместо File нужно вписать реальное название созданного Екселевского файла?????.
Такими ляпами грешат многие авторы толстенных книг по программированию и описанию программ. Начинают подробно описывать. а какой то момент(очень важный) упоминают вскольз. В результате все описание коту под .....!!!.

 

Добрый день, Александр. 

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

Как открыть файл из Делфи? Что имеете ввиду? Описанный пример использует выбор файла на компе т.е. работа с диалогами. Если Вы хотите открывать только один файл укажите явно путь. Так же в комментах от Идель есть реализации по этой теме.

И что это за конструкция XLSFile. ничего не сказано. - читаем внимательно код. Это текстовая переменная, один из параметров процедуры, в которой задается путь к файлу. 

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

 

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

Plain text

  • HTML-теги не обрабатываются и показываются как обычный текст
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Строки и параграфы переносятся автоматически.
CAPTCHA
Для предотвращения регистрации спам-роботов введите символы с картинки.
CAPTCHA на основе изображений
Введите символы, изображенные на картинке.
Разместить свое видео на сайте
Вы можете разместить свои 
видео-уроки на сайте
БЕСПЛАТНО!


Подробнее>>>