Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Медленная выгрузка в Excel через OLE.

315
20 января 2006 года
Nick_M
399 / / 29.05.2003
Есть набор данный TADOQuery. Задача выгрузить их в Excel. Выгружаю через OLE. Все работает без ошибок. Одна проблема - очень медленно. На выгрузку примерно 2500 записей по 10 столбцов затрачиваеться около 25 минут! Это очень много, учитывая что обычно будет обрабатываться 5-6 тыс. записей. Причем чем ближе к концу, тем больше времени затрачивается на экспорт одной записи. Если в начале выгружается в секунду ~ 6-8 записей, то потом доходит до 1 записи в секунду.
Есть ли соображения из-за чего такие тормоза?
246
20 января 2006 года
GIZMO
1.8K / / 30.07.2004
Цитата:
Originally posted by Nick_M
Есть набор данный TADOQuery. Задача выгрузить их в Excel. Выгружаю через OLE. Все работает без ошибок. Одна проблема - очень медленно. На выгрузку примерно 2500 записей по 10 столбцов затрачиваеться около 25 минут! Это очень много, учитывая что обычно будет обрабатываться 5-6 тыс. записей. Причем чем ближе к концу, тем больше времени затрачивается на экспорт одной записи. Если в начале выгружается в секунду ~ 6-8 записей, то потом доходит до 1 записи в секунду.
Есть ли соображения из-за чего такие тормоза?


ADO - сам по себе тормоз, это раз, а два код покажи...

315
20 января 2006 года
Nick_M
399 / / 29.05.2003
Цитата:
Originally posted by GIZMO
ADO - сам по себе тормоз, это раз, а два код покажи...


Тормоза не в ADO, ибо сам запрос к базе выполняется за считанные секунды. Тормоза в OLE.

315
21 января 2006 года
Nick_M
399 / / 29.05.2003
Цитата:
Originally posted by GIZMO
а два код покажи...


А код что-то вроде этого:

Код:
Variant App, Sh, cur;
try
        {
        App=Variant::GetActiveObject("Excel.Application");
        }
catch (...)
        {
        try
                {
                App=Variant::CreateObject("Excel.Application");
                }
        catch (...)
                {
                Application->MessageBox("Невозможно открыть Microsoft Excel!"
                        "Возможно Excel не установлен на компьютере.","Ошибка",MB_OK+MB_ICONERROR);
                }
        }
try
        {
        App.OlePropertyGet("WorkBooks").OleProcedure("Add");
        Sh = App.OlePropertyGet("WorkSheets",1);
        }
catch (...)
        {
        Application->MessageBox("Ошибка открытия книги Microsoft Excel!",
                "Ошибка",MB_OK+MB_ICONERROR);
        }
ADOQuery1->Open();
try
        {
        for (register int i = 0; i < ADOQuery1->RecordCount; i++)
                {
                cur = Sh.OlePropertyGet("Cells", i+1, 1);
                cur.OlePropertySet("Value", ADOQuery1->Fields->Fields[0]->AsString.c_str());
                cur = Sh.OlePropertyGet("Cells", i+1, 2);
                cur.OlePropertySet("Value", ADOQuery1->Fields->Fields[1]->AsString.c_str());
                cur = Sh.OlePropertyGet("Cells", i+1, 3);
                cur.OlePropertySet("Value", ADOQuery1->Fields->Fields[2]->AsString.c_str());
                cur = Sh.OlePropertyGet("Cells", i+1, 4);
                cur.OlePropertySet("Value", ADOQuery1->Fields->Fields[3]->AsString.c_str());
                cur = Sh.OlePropertyGet("Cells", i+1, 5);
                cur.OlePropertySet("Value", ADOQuery1->Fields->Fields[4]->AsString.c_str());
                cur = Sh.OlePropertyGet("Cells", i+1, 6);
                cur.OlePropertySet("Value", ADOQuery1->Fields->Fields[5]->AsString.c_str());
                cur = Sh.OlePropertyGet("Cells", i+1, 7);
                cur.OlePropertySet("Value", ADOQuery1->Fields->Fields[6]->AsString.c_str());
                cur = Sh.OlePropertyGet("Cells", i+1, 8);
                cur.OlePropertySet("Value", ADOQuery1->Fields->Fields[7]->AsString.c_str());
                cur = Sh.OlePropertyGet("Cells", i+1, 9);
                cur.OlePropertySet("Value", ADOQuery1->Fields->Fields[8]->AsString.c_str());
                }
        }
catch (...)
        {
        }

if (!App.IsEmpty()) App.OlePropertySet("Visible",true);

Sh.Clear();
App.Clear();

И именно в цикле тормоза и идут.
294
21 января 2006 года
Plisteron
982 / / 29.08.2003
Цитата:
Originally posted by Nick_M
А код что-то вроде этого:
 
Код:
for (register int i = 0; i < ADOQuery1->RecordCount; i++)
                {
                cur = Sh.OlePropertyGet("Cells", i+1, 1);
                cur.OlePropertySet("Value", ADOQuery1->Fields->Fields[0]->AsString.c_str());
                cur = Sh.OlePropertyGet("Cells", i+1, 2);
                cur.OlePropertySet("Value", ADOQuery1->Fields->Fields[1]->AsString.c_str());


...

Цитата:
 
Код:
cur = Sh.OlePropertyGet("Cells", i+1, 8);

                cur.OlePropertySet("Value", ADOQuery1->Fields->Fields[7]->AsString.c_str());
                cur = Sh.OlePropertyGet("Cells", i+1, 9);
                cur.OlePropertySet("Value", ADOQuery1->Fields->Fields[8]->AsString.c_str());
                }

И именно в цикле тормоза и идут.


Ясен пень, будут тормоза. Каждый раз при использовании OlePropertyGet() и OlePropertySet столько разных функций вызывается... P( Видел их объявление в заголовочных файлах? Если хочешь скорости в рантайме и не боишься трудностей, пиши через DISP-интерфейсы (делаешь в среде Import Template Library, натравливаешь на Excel.olb и вперёд...). Работать будет немного быстрее, но, чтобы всё заработало, клаву топтать придётся больше.
Извини, сейчас некогда рассказывать более подробно, но надо будет -- попытаюсь объяснить в меру своих способностей.

246
22 января 2006 года
GIZMO
1.8K / / 30.07.2004
Цитата:
Originally posted by Nick_M
А код что-то вроде этого:
 
Код:
...

И именно в цикле тормоза и идут.



Ясно. Что можно сделать:
1. Вставляй записи СТРОКАМИ, а не ячейками.
2. Формируешь строки, значения в которых разделены ТАБ-ом и вставляй через буфер обмена, примерно так:

Код:
TStringList* data = new TStringList();
    TListItem* ListItem;
    String line;
    TDateTime tm1, tm2;

    //&#226;&#241;&#242;&#224;&#226;&#232;&#236; &#226; Excel...
    XL = CreateOleObject("Excel.Application.8");
    XL.OlePropertySet("Visible", CheckBox1->Checked);
    v0 = XL.OlePropertyGet("Workbooks");
    v0.OleProcedure("Add");
    v1 = v0.OlePropertyGet("Item", 1).OlePropertyGet("Worksheets").OlePropertyGet("Item", 1);

    tm1 = Time();
    //&#239;&#229;&#240;&#226;&#224;&#255; &#241;&#242;&#240;&#238;&#234;&#224; - &#248;&#224;&#239;&#234;&#224; &#242;&#224;&#225;&#235;&#232;&#246;&#251;...
    line = ListView1->Columns->Items[0]->Caption;
    for (int i = 1; i < ListView1->Columns->Count; i++)
        line = line  + "\t" + ListView1->Columns->Items->Caption;
    data->Add(line);
    //&#228;&#224;&#235;&#229;&#229; &#228;&#238;&#225;&#224;&#226;&#235;&#255;&#229;&#236; &#241;&#242;&#240;&#238;&#234;&#232; &#226; &#234;&#238;&#242;&#238;&#240;&#251;&#245; &#241;&#235;&#238;&#226;&#224; &#240;&#224;&#231;&#228;&#229;&#235;&#229;&#237;&#251; Tab-&#238;&#236;, Excel - &#239;&#238;&#233;&#236;&#229;&#242;...
    for (int j = 0; j < ListView1->Items->Count; j++) {
        ListItem = ListView1->Items->Item[j];
        line = ListItem->Caption;
        for (int k = 0; k < ListItem->SubItems->Count; k++) {
            line = line  + "\t" + ListItem->SubItems->Strings[k];
        }
        data->Add(line);
    }
    //&#226; Clipboard...
    Clipboard()->AsText = data->Text;

    v1.OlePropertyGet("Range", "E2:E2").OleProcedure("Select"); //&#237;&#224;&#239;&#240;&#232;&#236;&#229;&#240; &#237;&#224;&#247;&#232;&#237;&#224;&#255; &#241; &#253;&#242;&#238;&#233; &#255;&#247;&#229;&#233;&#234;&#232;...
    v1.OleProcedure("Paste");

    Clipboard()->Clear();

    tm2 = Time();
    ShowMessage("done with " + TimeToStr(tm2 - tm1));

    XL.OlePropertySet("DisplayAlerts",false);
    XL.OlePropertyGet("Workbooks").OlePropertyGet("Item",1).OleProcedure("SaveAs", ChangeFileExt(Application->ExeName, ".xls"));
    XL.OleProcedure("Quit");

    delete data;
315
23 января 2006 года
Nick_M
399 / / 29.05.2003
Plisteron, GIZMO.
Спасибо за советы и помощь.
Запускал из Билдера и видел тормоза. Еще раз протестировал, запустив приложение самостоятельно. В результате скорость оказалась раз в 5 выше.
Попробую предложенные способы. Возможно скорость удасться еще поднять.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог