Чтение данных из нескольких ячеек.
Имея ввиду все вышеописанное, можно просто организовать чтение данных из поименованной области. Я часто нахожу такой код в Сети и в книгах, приведенный в качестве примера. Вот он:
procedure TForm1.btnReadArrayClick(Sender: TObject);
var Values: OLEVariant;
ISheet: Excel8TLB._Worksheet;
IRange: Excel8TLB.Range;
i, j: integer;
begin
if Assigned(IWorkbook) then
try
ISheet := IWorkbook.Worksheets.Item['Лист1'] as Excel8TLB._Worksheet;
try
IRange := ISheet.Range['TestRange2', EmptyParam];
Values := VarArrayCreate([1, IRange.Rows.Count, 1, IRange.Columns.Count], varVariant);
for i := 1 to IRange.Rows.Count do
for j := 1 to IRange.Columns.Count do begin
Values[i, j] := IRange.Item[i, j];
ShowMessage( Values[i, j]);
end;
finally
IRange := nil;
ISheet := nil;
end;
except
raise Exception.Create(’Не могу прочитать данные в массив!’);
end;
end;
Я создал на форме кнопку, по которой из заранее подготовленной области с именем “TestRange2″ все значения ячеек будут получены в вариантный массив Values. Вызов ShowMessage добавлен сюда только для контроля над процессом. Как видно, получить значения ячеек области достаточно просто. Вы создаете вариантный массив с количеством строк и колонок, равными размерам области, а затем, проходя по очереди все ячейки области, запоминаете их значения в массиве. Но в этом коде есть одна проблема. Чтение из ячеек можно организовать еще проще. Вот так:
procedure TForm1.btnReadArrayClick(Sender: TObject);
var Values: OLEVariant;
ISheet: Excel8TLB._Worksheet;
IRange: Excel8TLB.Range;
begin
if Assigned(IWorkbook) then
try
ISheet := IWorkbook.Worksheets.Item['Лист1'] as Excel8TLB._Worksheet;
try
IRange := ISheet.Range['TestRange2', EmptyParam];
Values := IRange.Value; // <<—
for i := 1 to IRange.Rows.Count do
for j := 1 to IRange.Columns.Count do begin
ShowMessage( Values[i, j]);
end;
finally
IRange := nil;
ISheet := nil;
end;
except
raise Exception.Create(’Не могу прочитать данные в массив!’);
end;
end;
Дело в том, что строки Values := IRange.Value вполне достаточно. Свойство Value интерфейса Range в состоянии вернуть вариантный массив. Этот код, по моему мнению, более прост и производителен, особенно на больших объемах данных. Уберите отсюда циклы с ShowMessage и убедитесь в этом.
А вот пример кода, который вернет в массиве значения всех ячеек из используемой области на листе. Проще сказать, вернет весь лист:
var Values: OLEVariant;
ISheet: Excel8TLB._Worksheet;
IRange: Excel8TLB.Range;
i, j: integer;
begin
if Assigned(IWorkbook) then
try
ISheet := IWorkbook.Worksheets.Item['Лист1'] as Excel8TLB._Worksheet;
try
IRange := ISheet.UsedRange[0];
Values := IRange.Value;
finally
IRange := nil;
ISheet := nil;
end;
except
raise Exception.Create(’Не могу прочитать данные в массив!’);
end;
end;
Здесь я использую свойство UsedRange листа. Это прямоугольная область, заключенная между “левой верхней непустой” и “правой нижней непустой” ячейками. (Кто-нибудь понял? Впрочем, в два часа ночи разве напишешь понятней!). Конечно, если в этой прямоугольной области будет много пустых ячеек, то массив получится с избыточными данными. Что бы убедиться в этом, попробуйте создать циклы с ShowMessage из предыдущего примера.
В комментариях проекта-примера вы найдете еще несколько интересных конструкций, которые мне приходится использовать для получения массивов со значениями ячеек. В качестве параметра в UsedRange я передаю 0. Это lcid, описанный в предыдущей статье.
Кстати, об lcid. В прошлый раз меня подвела зрительная память. И в самом деле, “любимый классик” пишет, что туда можно смело передавать 0. Но другой, не менее любимый классик с этим не согласен и рекомендует передавать туда результат функции GetUserDefaultLCID. Думаю, последнее более правильно. Однако В некоторых случаях, чаще в гремучей смеси Windows 2000 и Excel 2000, оба решения не проходили. Причем, выдавалось сообщение о попытке “использовать библиотеку старого формата:” и что-то еще. Так вот, вместо GetUserDefaultLCID я применяю теперь константу LOCALE_USER_DEFAULT. Более ничего объяснить не могу, так как до сих пор, проштудировав основательно MSDN, не разобрался, что же в таком случае хочет получить Microsoft в методы и свойства интерфейсов Excel, где одним из параметров требует lcid. Кто бы объяснил?..
Есть еще несколько способов чтения данных из книги, которые, впрочем, я не в силах описать здесь. Один их таких способов, это использование DDE, самый быстрый и экономичный (по ресурсам) способ, который известен еще со времен Windows 3.1.
Январь
19,
2008
— Рубрика: Delphi
Метки: MSDN, Windows 3.1, Чтение данных, ячеек
