Несколько предложений по исследованию
Gustav различных вариантов использования ComExcelDocument_RU
1. При создании нового файла Excel использован код
X++:
excel.newFile("", true, -1);
Замечание по поводу второго параметра
_bVisible=true - при массовой вставке данных в лист Excel будет довольно ощутимое замедление выгрузки. Еще одна особенность при таком параметре - если пользователь в листе Excel во время вызгрузи выделит ячейку мышкой, то выполнение прервется с ошибкой.
Первый (самый простой) вариант - открывать в невидимом режиме и показывать после выгрузки всех данных.
Второй вариант - запретить перед экспортом пользовательский ввод и обновления в открытой книге.
X++:
COM app;
;
...
app = doc.Application();
app.Interactive(False); // запрет пользовательского ввода
app.ScreenUpdating(False); // запрет обновления окна при изменении данных
...
app.Interactive(True);
app.ScreenUpdating(True);
2. Хотелось бы вступиться за Range
. Значительное увеличение времени в первом варианте присходит из-за реализации метода findRange(), используемого в insertValue(). Если заменить этот код на более простой (часть кода взята из второго варианта)
X++:
COM doc;
COM actSheet;
COM range;
...
doc = excel.getComDocument();
actSheet = doc.ActiveSheet();
...
while ()
{
...
range = actSheet.range(ComExcelDocument_RU::numToNameCell( 1, row));
range.Value2(ledgerTrans.RecId);
range = actSheet.range(ComExcelDocument_RU::numToNameCell( 2, row));
range.Value2(ledgerTrans.AccountNum);
...
то загрузка хотя и будет происходить медленнее второго способа, но разница будет составлять уже проценты, а не разы.
3. Окончательная реабилитация Range
.
Третий вариант с использованием только интерфейсов - вставка при помощи массивов
X++:
COM actSheet;
COM range;
Array arr;
...
while ()
{
...
arr = new Array(Types::String);
arr.value( 1, strfmt("%1", ledgerTrans.RecId));
arr.value( 2, strfmt("%1", ledgerTrans.AccountNum));
arr.value( 3, strfmt("%1", ledgerTable.AccountName));
arr.value( 4, strfmt("%1", ledgerTable.AccountPlType));
arr.value( 5, strfmt("%1", ledgerTrans.BondBatchTrans_RU));
arr.value( 6, strfmt("%1", ledgerTrans.BondBatch_RU));
arr.value( 7, strfmt("%1", ledgerTrans.TransDate));
arr.value( 8, strfmt("%1", ledgerTrans.Txt));
arr.value( 9, strfmt("%1", ledgerTrans.AmountMST));
arr.value(10, strfmt("%1", ledgerTrans.Crediting));
range = actSheet.range(strfmt("A%1:J%1", row));
range.value2(COMVariant::createFromArray(arr));
Этот вариант по сравнению со вторым в моем случае дает увеличение скорости до 7 раз
PS. Упс. Ошибка. Так делать нельзя.
X++:
excel.insertValue(range, ledgerTrans.AccountNum);
На самом деле хотел вставить
X++:
excel.insertValueInRange(range, ledgerTrans.AccountNum);
но этот метод объявлен как protected в стандарте. Если необходимо - можно изменить объявление класса, либо просто вставлять значения так
X++:
range.Value2(ledgerTrans.AccountNum);