Меню

Быстрая обработка данных Excel в Delphi

Быстрая обработка данных Excel в Delphi.

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

План статьи:

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

Чтение данных из Excel

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Источник

Delphi получить все таблицы

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

Итак, компонент StringGrid имеет возможность адресации каждой отдельной ячейки по номеру столбца и строки. Содержимое ячейки (i, j), где где i — номер столбца, j — номер строки, имеет вид

StringGrid1.Cells[i, j]

и доступно как для чтения, так и для записи. Здесь, как и всегда, номера столбцов ( i ) и строк ( j ) отсчитываются от 0.

Выделенная ячейка таблицы имеет

номер столбца: StringGrid1.Col
номер строки: StringGrid1.Row

поэтому содержимое выделенной ячейки будет адресоваться так:

Не правда ли, написание такой строки — утомительный процесс. Поэтому пользуйтесь оператором присоединения with:

with StringGrid1 do
S:=Cells[Col, Row];

А лучше сразу задать в свойстве Name имя покороче, например SG.

За многие свойства компонента Delphi StringGrid отвечает свойство Options. В Инспекторе Объектов Options — это раскрывающийся список, представляющий собой элементы данного множества. Если значение элемента равно True, то он присутствует в множестве, если False — то нет.

StringGrid1.Options:=StringGrid1.Options+[goEditing]; //Включаем редактирование, другие элементы не трогаем

StringGrid1.Options:=StringGrid1.Options-[goEditing]; //Выключаем редактирование, другие элементы не трогаем

StringGrid1.Options:=[goEditing, goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRowSelect]; //Задаём список необходимых элементов

Если элементы заданы списком, это аналогично присвоению в Инспекторе Объектов этим элементам значения True, остальным — False.

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

Количество строк в Delphi StringGrid равно StringGrid1.RowCount.
Количество столбцов в Delphi StringGrid равно StringGrid1.ColCount.

Если ячейки не помещаются в таблице, появляются полосы прокрутки. При прокручивании

StringGrid1.LeftCol Номер столбца, видимого самым левым
StringGrid1.TopRow Номер строки, видимой самой верхней
StringGrid1.VisibleColCount Количество столбцов, видимых в рамках таблицы
StringGrid1.VisibleRowCount Количество строк, видимых в рамках таблицы

У таблицы StringGrid также есть свойство и для управления размером ячеек.Для всех ячеек

DefaultRowHeight — высота строк по умолчанию
DefaultColWidth — ширина столбцов по умолчанию

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

RowHeights — массив, содержащий высоты строк. То есть, например, RowHeights[5] — высота строки с индексом 5
ColWidths — массив, содержащий ширины столбцов. То есть, например, ColWidths[5] — ширина строки с номером 5

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

Поскольку ячейки компонента StringGrid можно редактировать, точно так же как и строку ввода Edit, то возникает вопрос, можно ли программно установить курсор в заданную позицию в содержимом ячейки? Оказывается, есть такая возможность. Для этого требуются дополнительный тип данных на основе таблицы и вспомогательная процедура:

type TGridCracker = class(TStringGrid);

procedure SetCaretPosition(Grid: TStringGrid; col, row, x_pos: Integer);
begin
Grid.Col := Col;
Grid.Row := Row;
with TGridCracker(Grid) do
InplaceEditor.SelStart := x_pos;
end;

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

procedure TForm1.Button1Click(Sender: TObject);
begin
StringGrid1.SetFocus;
with StringGrid1 do
SetCaretPosition(StringGrid1, Col, Row, 2);
end;

Читайте также:  Diskpart восстановление карты памяти USB флешки или жесткого диска

Правда, ещё один момент! Чтобы код сработал, нужно установить в Инспекторе Объектов значение параметра goAlwaysShoweEditor свойства Options в True. Можно это сделать также и программно, в той же процедуре нажатия кнопки:

Отдельно требуется осветить вопрос очистки содержимого таблицы StringGrid. Так как таблица StringGrid, в отличие от, например, компонента Memo, не имеет метода для очистки содержимого сразу всех ячеек, то для удаления внесённых в таблицу ранее данных приходится очищать каждую ячейку отдельно. Делается это двумя вложенными циклами for, пробегающими по столбцам и строкам:

var i, j: Integer;
begin
with StringGRid1 do
for i:=1 to RowCount-1 do //Заголовки строк не трогаем
for j:=1 to ColCount-1 do //Заголовки столбцов не трогаем
Cells[j, i]:=»;
end;

Хотя, оказывается, есть метод для очищения содержимого целого столбца или строки:

StringGrid1.Cols[i].Clear; //Очищается столбец с номером i
StringGrid1.Rows[i].Clear; //Очищается строка с номером i

Очевидно, очищение этими методами гораздо быстрее. Однако будут очищены и ячейки фиксированной зоны, содержащие, например, названия строк и столбцов, которые удалять не нужно. Их после очистки нужно просто «написать» заново, на глаз эта манипуляция совершенно незаметна. Для очистки всей таблицы достаточно последовательно очистить только строки или только столбцы:

var i, j: Integer;
begin
with StringGRid1 do
for i:=1 to RowCount-1 do //Заголовки столбцов не трогаем — цикл от 1
begin
Rows[i].Clear;
Cells[0, i]:=»Заголовок строки i»;
end;
end;

Казалось бы, можно поступить и по-другому, просто обнулить количество строк или столбцов! Однако так делать неправильно, так как при их последующем добавлении может оказаться, что каждая ячейка содержит прежние данные. А в Delphi4 даже при уменьшении количества строк или столбцов содержавшиеся в них данные вообще не пропадали, а так и повисали в воздухе! Так что так можно поступать только если в добавляемых ячейках сразу будет новое непустое содержимое.

Как узнать координаты ячейки при щелчке мышкой

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

Возможность получить координаты ячейки доступна в обработчиках событий OnMouseDown и OnMouseUp. Параметры этих событий содержат пиксельные координаты щелчка. Более естественно использовать OnMouseDown, так как это событие наступает раньше. Получив координаты в пикселах, их нужно пересчитать в индексы ячейки. Этим занимается метод таблицы StringGrid — MouseToCell:

procedure TForm1.StringGrid1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var ACol, ARow: Integer;
begin
StringGrid1.MouseToCell(X, Y, ACol, ARow); //Получаем индексы ячейки ACol и ARow
//Перемещаем фокус в ячейку с этими индексами:
StringGrid1.Col:=ACol;
StringGrid1.Row:=ARow;
end;

Графические возможности компонента StringGrid

Таблица StringGrid Delphi обладает также и графическими возможностями. Ячейки таблицы можно раскрашивать в произвольные цвета, выводить рисунки, размещать не только однострочный, но и многострочный текст. Графические возможности StringGrid определяются наличием у таблицы свойства Canvas — холста, на котором можно воспроизводить любую графику стандартными методами Delphi. Кроме того, компонент StringGrid имеет дополнительные методы, помогающие выводу графики в ячейки компонента. читать далее.

Совместная работа StringGrid и Excel

Очень многие документы создаются и хранятся в формате электронных таблиц Microsoft Excel. Несмотря на то, что эти таблицы обладают возможностями для автоматической обработки документа, нам, дельфистам, гораздо приятнее работать в привычной среде, что которая и обладает к тому же гораздо более развитыми возможностями. Давайте посмотрим, как получать данные из Excel. Естественно, табличные данные будем размещать в привычную нам таблицу StringGrid. А уж в ней мы горы своротим!

Источник



Delphi получить все таблицы


Vitamin ( 2002-05-13 10:45 ) [0]

Как в приложении получить список всех таблиц из одной базы данных?


sniknik ( 2002-05-13 10:51 ) [1]

ADOConnection1.GetTableNames(ListBox1.Items, True);


sniknik ( 2002-05-13 10:53 ) [2]

corry в D4 может и ADO как такового нет. Можно еще из системной таблици имена прочитать. А какое у тебя подключение?


Vitamin ( 2002-05-13 11:14 ) [3]

У меня в ODBC создан альяс на базу. ADO в четвертом дельфи еще нет.
Я знаю что это реально, потому как Table.TableName видит имена всех таблиц из базы, но я не знаю как это сделать.
Как обратиться к системной таблице?
Желательно с примером.


sniknik ( 2002-05-13 11:18 ) [4]

простым запросом
SELECT Name FROM MSysObjects WHERE Type = 1 and Flags = 0

Type = 1 — все таблици
Flags = 0 — только видимые и не системные

Читайте также:  Урок конференция по теме Идеи Просвещения как мировоззрение развивающейся буржуазии методическая разрабо

можно менять по разному.
и у компонента Database есть GetTableNames (по моему, неохота проверять) сделай соеденение через него.


Vitamin ( 2002-05-13 12:05 ) [5]

>простым запросом
>SELECT Name FROM MSysObjects WHERE Type = 1 and Flags = 0

>Type = 1 — все таблици
>Flags = 0 — только видимые и не системные

на этот запрос система сообщает что типа у меня нет прав доступа на чтения 🙁

А через Database1.Session.GetTableNames(Database1.AliasName,»*.*»,True,True,ComboBox1.Items);

Все заработало спасибо большое 🙂


sniknik ( 2002-05-13 13:31 ) [6]

а надо подключится тем у кого права есть или назначить. Посмотри в Access Tols->Security (сначала в Tols->Options->View включи на просмотр системные таблици)
Это так для информации, раз уже работает.

Источник

Запросы на выборку из БД в Delphi с использованием компонента ADOQuery

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

Для работы с запросами в Delphi по технологии ADO используется компонент ADOQuery. Что касается подключения компонента, работа с ним подобна работе с ADOTable. Ему так же необходимо указать ADOConnection, подключенный к БД (можно так же настроить свойство подключения к БД ConnectionString). Для отображения на форме данных ему так же нужен компонент DataSource, подключаемый к компонентам отображения и управления данными из закладки палитры Data Controls (DBGrid, DBEdit и другие).

В отличие от ADOTable, запрос не содержит свойств для выбора таблицы, которую он будет отображать. Вместо этого он имеет поле SQL, которое должно содержать текст SQL-запроса к БД для выбора необходимых данных.

Статический запрос

Для получения содержимого таблицы следует указать следующие поля ADOQuery:

Connection – выбрать из списка настроенное подключение к БД.

SQL – ввести текст любого SQL-запроса, например: «SELECT * FROM mytable».

Active – присвоить значение True.

Если при присвоении свойству Active, сведений об ошибках не было выведено, значит все выполнено правильно и далее можно пользоваться ADOQuery, как обычной таблицей для вывода его данных (вывод осуществляется аналогично таблице через компонент DataSourcе, например, в DBGrid).

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

Динамическое изменение запроса во время исполнения программы

Если в процессе работы программы, текст SQL-запроса нужно переписывать, как, например, при указании условия выборки, то можно просто программно управлять режимом исполнения запроса и содержимым его поля SQL.

Для этого применяется следующий код:

Программная работа с результатами запроса

Если результат запроса нужно не просто вывести, а выполнять с ним какую-то работу непосредственно в коде, то обратится к ним через свойство Fields. Например, код:

выведет во всплывающем окне содержимое первого поля текущей записи.

Fields[номер поля] – указывает номер столбца в сформированной запросом таблице. Самое первое будет нулевое.

AsString – указывает, что тип возвращаемого значение будет строковый. Аналогично можно указать AsInteger, чтобы получить числовое значение.

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

Источник

Получить список таблиц БД

Доброго времени суток! Помогите пожалуйста кто чем сможет. Я создал базу данных в Interbase в ней 4 таблицы, на форме у меня DBgrid, IBQuery, DataSours Скажите пожалуйста, как мне получить список таблиц которые у меня в БД есть!

Добавлено через 8 минут
Я знаю как получить список таблиц в случае если использовать IBTable:

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

Получить список таблиц
Запрос: SELECT * FROM information_schema.tables Результат: А где.

Получить список таблиц c MySQL
Здраствуйте, как сделать запрос «SHOW TABLES;» в c# и что за тип данных вернется? Спасибо

Получить список таблиц c OleDbConnection
Не судите строго за глупые вопросы я ток начинаю изучать C# . Долго искал как же всетаки выдрать.

Получить список таблиц из БД MS SQL Server
Хочу получит список таблиц из БД но не получается. Как правильно делать ?? string connStr =.

Сообщение от Владислав-2012
Вложения

Проект с эко.rar (679.2 Кб, 14 просмотров)

но мне и нужно все кроме этих таблиц, если имя таблицы = имя таблицы, которую надо прятать, тогда выходит из цикла,если нет то добавляет в комбобокс

Добавлено через 4 минуты
IBQuery5.RecordCount и можно еще вопрос, вроде бы как эта строчка вычисляет количество записей, почему она может передавать не правильные значения

Добавлено через 2 минуты
Без использования гридов и датасетов, этом причина?

Сообщение от Владислав-2012
Сообщение от Владислав-2012

а что значит trim

Добавлено через 12 минут
Спасибо, этот способ работает

Источник