[excel] быстро выдернуть данные из excel-а во внешнюю прогу?

Christina

думаю как быстрее перекинуть данные из ячеек экселя в массив вижал бэйсика (и наоборот).
в книжке написано, что лучше обращаться не к каждой ячейке, а использовать метод .FormulaArray для объекта Range. Замерил время, получилось только медленней.
Кто-нить знает, возможно ли это сделать быстрее, чем обращением к каждой ячейке?

Dasar

ODBC/OleDb с какой скоростью данные выдергивают?

yolki

ODBC/OleDb с какой скоростью данные выдергивают?
Из экселя - с очень медленной.
Самый быстрый из известных мне способов - DDE, но у него свои косяки есть.
один из самых заметных - "эффект 4/7", когда строка "4/7" определяется экселем как седьмое апреля и данные передаются уже как "дата"

Christina

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

Olenenok

yolki

вот тебе кусок из дельфёвого кода:

// Взять данные из Excel'я
// =======================
function QueryData(
IBook // Книга с листом
: I_Workbook;
ISheet // Лист, с которго будут браться данные
: I_Worksheet;
var Data // Данные
: TValueTable;
SelRange // Выбираемая область
: I_Range)
// код возврата
: integer;
var
xlDDE // Соединение DDE
: TDDEClientConv;
i,j, // индексы
sx,sy, // размеры
lp,p // позиции в буфере
: integer;
Buf: string;
begin
Result:=0;
xlDDE := TDDEClientConv.Create(nil);
try
if xlDDE.SetLink('EXCEL', '['+IBook.Name+']'+ISheet.Name) then
Buf:=xlDDE.RequestData(OLEVariant(SelRange).Address[ReferenceStyle:=xlR1C1])
else result:=-1;
finally
xlDDE.Free;
end;
if (Result=-1) then
begin
writeln('failed to gain data');
exit;
end;
// writeln('gained data.');
// writeln(buf);
sy:=SelRange.rows.count;
sx:=SelRange.columns.count;
SetLength(Data,sy);
for i:=0 to sy-1 do
SetLength(Data[i],sx);

i:=0;j:=0;
lp:=1;p:=1;

while p<=length(buf) do
begin
case Buf[p] of
egin
Data[i,j]:=StrToFloatDef(copy(Buf,lp,p-lp0);
inc(j);
lp:=p+1;
end;
egin
Data[i,j]:=StrToFloatDef(copy(Buf,lp,p-lp-10);
lp:=p+1;
inc(i);
j:=0;
end;
; // игнорировать этот символ
end;
inc(p);
end;
// StrDispose(Buf);
end;

// Послать данные в Excel
// ======================
function SendData(
IBook // Книга, которой принадлежит лист
: I_Workbook;
ISheet // Лист, в который будут записываться данные
: I_Worksheet;
Data // Данные
: TValueTable;
SelRange // Регион, куда складывать данные
: I_Range)
// код возврата
: integer;
var
xlDDE // Соединение DDE
: TDDEClientConv;
i,j // индексы
: integer;

Buf : string;
begin
Buf:=''; Result:=0;
for j:=0 to length(Data[0])-1 do
begin
for i:=0 to length(Data)-1 do
begin
Buf:=Buf+Format('%6.4f',[Data[i,j]]);
if i<length(Data)-1 then Buf:=Buf+#09;
end;
if j<length(Data[0])-1 then Buf:=Buf+#10;
end;

xlDDE := TDDEClientConv.Create(nil);
try
if xlDDE.SetLink('EXCEL', ISheet.Name) then
xlDDE.PokeData(OLEVariant(SelRange).Address[ReferenceStyle:=xlR1C1], PChar(Buf
else result:=-1;
finally
xlDDE.Free;
end;
end;

разбирайся-портируй в свой бейсик

yolki

Рекомендуется к ознакомлению:
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=313

Dasar

> Из экселя - с очень медленной.
очень медленной - это сколько записей в секунду?

vall

сохранить csv во временный файл и распарсить.

Corrector

 
.FormulaArray для объекта Range. Замерил время, получилось только медленней.

удивительно, я тоже замерял время, получилось на 1-2 порядка быстрее. Надеюсь, ты Range не для каждой ячейки используешь, а для диапазона ячеек?
если не помогает, сохраняй в текстовый файл, потом открывай его из бейсика.

Christina

Dim a(1 To 30, 1 To 300) As Integer
begin = Timer
Set myRange = Worksheets("лист1").Range("A1:AD300")
myRange.FormulaArray = ""
Debug.Print (Timer - begin)
может что не так?

9173306234

сохранить csv во временный файл и распарсить.
+1

Christina

help

nawok

If you transfer data by using an array instead of cell by cell, you can realize an enormous performance gain with a lot of data. Consider this line from the earlier code, which transfers data to 300 cells in the worksheet.
oSheet.Range("A2").Resize(100, 3).Value = DataArray

http://support.microsoft.com/kb/306022

Christina

спасибо.
а как из экселя в массив?

nawok

Вероятно так
DataArray = oSheet.Range("A2").Resize(100, 3).Value  

Christina

так низя, к сожаленью
плз. подскажите, кто знает (данные из ячеек в массив)

Andbar

Самый быстрый из известных мне способов - DDE, но у него свои косяки есть.
а мегаизвратный способ через буффер обмена?
Оставить комментарий
Имя или ник:
Комментарий: