Замерил способ "через SysExcel":
X++:
static void SpeedTest_Job3_SysExcel(Args _args)
{
LedgerTrans ledgerTrans;
LedgerTable ledgerTable;
int row;
int timeFullStart, timeFullFinish, timeFullTotal;
SysExcelCells cells;
COM rng, xlApp;
;
timeFullStart = timenow();
// обратите внимание, что если нам нужны, например, только ячейки рабочего листа 1,
// то нет необходимости выделять отдельные переменные для всех вышестоящих объектов
// можно всё указать в одной строке через точки - почти как в VBA :)
cells = SysExcelApplication::construct().workbooks().add().worksheets().itemFromNum(1).cells();
// но нам потребуется объект Application - хотя бы для того, чтобы сделать Excel видимым
// в рамках примера получим его как "COM от COM-а" любой ячейки, например, А1
rng = cells.range('A1').comObject(); // Range
xlApp = rng.Application(); // Excel.Application
xlApp.Visible(true); // в эсперименте на скорость - комментировался/раскомментировался этот оператор
// повторяю - этот "изврат" выше сделан для целей примера
// без использования COM-переменных можно было бы последовательно оформить вот так:
// SysExcelApplication xlApp;
// SysExcelCells cells;
// ................................
// xlApp = SysExcelApplication::construct();
// cells = xlApp.workbooks().add().worksheets().itemFromNum(1).cells();
// и дальше спокойно распоряжаться этими двумя переменными
// для работы с ячейками первого рабочего листа новой рабочей книги
row = 0;
while select ledgerTrans
join ledgerTable
where ledgerTrans.AccountNum == ledgerTable.AccountNum
{
row++;
if (row > 50000) break;
cells.item( row, 1).value( ledgerTrans.RecId );
cells.item( row, 2).value( ledgerTrans.AccountNum );
cells.item( row, 3).value( ledgerTable.AccountName );
cells.item( row, 4).value( strfmt('%1', ledgerTable.AccountPlType) );
cells.item( row, 5).value( ledgerTrans.BondBatchTrans_RU );
cells.item( row, 6).value( ledgerTrans.BondBatch_RU );
cells.item( row, 7).value( ledgerTrans.TransDate );
cells.item( row, 8).value( ledgerTrans.Txt );
cells.item( row, 9).value( ledgerTrans.AmountMST );
cells.item( row, 10).value( strfmt('%1', ledgerTrans.Crediting) );
}
xlApp.visible(true);
timeFullFinish = timenow();
timeFullTotal = timeFullFinish - timeFullStart;
info('Время выполнения, сек');
info(int2str(timeFullTotal));
}
Результата привожу два:
1. 1228 сек - т.е. чуть больше 20 минут - когда сразу делаем видимым окно Excel в начале процедуры (см. в коде "xlApp.Visible(true); // в эсперименте на скорость...")
2. 1060 сек - т.е. чуть меньше 18 минут - когда показываем Excel только в конце (см. в коде "// xlApp.Visible(true); // в эсперименте на скорость...")
Делать Visible(true) в начале - плохая практика,
AndyD абсолютно прав! Но в рамках эксперимента, конечно, можно посмотреть и так, и сяк
С джобами SpeedTest_Job1 и SpeedTest_Job2 имеет смысл сравнивать только первый результат, поскольку и они тоже прогонялись при начальном Visible(true). Результат "1228 сек" несколько больше, чем у _Job2 (1090 сек), и это объяснимо: представители семейства системных классов SysExcel оформлены как "обертки" над COM и, соответственно, часть времени тратится на "продирание" через эти "обертки", в то время, как _Job2 фактически использует чистый COM.
Результат "1228 сек" ниже "1060 сек" примерно на (1228-1060)/1228 = около 14 % - что я и обещал:
Цитата:
Сообщение от
Gustav
Да, разница в скорости порядка 10-15 процентов.
Конечно, с точки зрения скорости способ "через SysExcel" также оставляет желать гораздо более лучшего и в качестве широкого использования "как быстрый способ" рекомендоваться не может.
Мне он, однако, понравился другим, в частности:
- возможностью писать "почти как на VBA c многими точками" (см. комментарии в тексте джоба),
- писать нормально Value, а не Value2 (при этом класс SysExcelCell сам берет на себя ответственность за обработку value -
"до XP или после" ).