Еще один вариант - при помощи DDE.
Время выгрузки - 20-21 с
PS Так как пользователь может в настройках отключить возможность обработки запросов DDE, то, перед созданием класса clientDDE, можно вставить сброс этого флага
X++:
app.IgnoreRemoteRequests(false);
ddeClient = new DDEClient("Excel", sheet.Name());
PPS По просьбе Gustav перемещаю код в окно.
Заодно добавил выгрузку ч/з буфер обмена. Для выгрузки использую TextBuffer.toClipboart().
Для переключения используется макрос DDE. Значение TRUE - выгрузка ч/з DDE, значение FALSE - clipboard
Время выгрузки примерно одинаковое для обоих вариантов
X++:
static void ExportExcelDDE(Args _args)
{
LedgerTrans ledgerTrans;
LedgerTable ledgerTable;
int timeFullStart, timeFullFinish, timeFullTotal;
int cnt = 0;
str Buf, s;
ComExcelDocument_Ru excel;
COM doc;
COM app;
COM sheet;
COM range;
DDEClient ddeClient;
TextBuffer tb;
#define.RowsCount(5000)
#define.DDE(false)
#define.xlR1C1(0xFFFFEFCA)
#if.DDE(false)
void LoadKeyboardLayout()
{
dll dll = new dll("user32");
dllFunction dllFunction = new dllFunction(dll, "LoadKeyboardLayoutA");
#define.KLF_ACTIVATE(1)
;
dllFunction.arg(ExtTypes::String, ExtTypes::DWord);
dllFunction.returns(ExtTypes::DWord);
dllFunction.call("00000419", #KLF_ACTIVATE);
}
#endif
;
// засекаем время
timeFullStart = timenow();
excel = new ComExcelDocument_Ru();
excel.newFile("", false);
doc = excel.getComDocument();
app = doc.application();
sheet = app.ActiveSheet();
buf = "RecId\tAccountNum\tAccountName\tAccountPlType\tBondBatchTrans_RU\tBondBatch_RU\tTransDate\tTxt\tAmountMST\tCrediting\n";
range = sheet.range("A:A;E:E");
range.NumberFormat("0");
range = sheet.range("B:D;F:F;H:H;J:J");
range.NumberFormat("@");
range = sheet.range("G:G");
range.NumberFormat("ДД.ММ.ГГГГ");
range = sheet.range("I:I");
range.NumberFormat("# ##0,00");
#IF.DDE(true)
app.IgnoreRemoteRequests(false);
ddeClient = new DDEClient("Excel", sheet.Name());
#ENDIF
#IF.DDE(false)
tb = new textBuffer();
LoadKeyboardLayout();
#ENDIF
cnt++;
while select ledgerTrans
join ledgerTable
where ledgerTrans.AccountNum == ledgerTable.AccountNum
&& ledgerTrans.TransDate >= str2date('dd.mm.yy',123) && ledgerTrans.TransDate <= str2date('DD.MM.YY',123)
{
// 10 полей
buf +=
strfmt(
"%1\t%2\t%3\t%4\t%5\t%6\t%7\t%8\t%9\t%10\n",
ledgerTrans.RecId, ledgerTrans.AccountNum, ledgerTable.AccountName, ledgerTable.AccountPlType,
ledgerTrans.BondBatchTrans_RU, ledgerTrans.BondBatch_RU,
date2str(ledgerTrans.TransDate, 321, 2, 3, 2, 3, 4), ledgerTrans.Txt,
strltrim(strrem(num2str(ledgerTrans.AmountMST, 10, 2, 2, 0), "+")), ledgerTrans.Crediting);
cnt++;
if (cnt > 0 && (cnt mod #RowsCount == 0))
{
s = strfmt("A%1:J%2", cnt-#RowsCount+1, cnt);
range = sheet.range(s);
#IF.DDE(true)
ddeClient.poke(range.Address(true, true, #xlR1C1), buf);
#ENDIF
#IF.DDE(false)
tb.setText(buf);
tb.toClipboard();
sheet.paste(range);
#ENDIF
buf = "";
}
if (cnt >= 65000) break;
}
if (cnt < #RowsCount)
range = sheet.range("A1:J" + int2str(cnt));
else
range = sheet.range(strfmt("A%1:J%2", cnt-(cnt mod #RowsCount)+1, cnt));
#IF.DDE(true)
ddeClient.poke(range.Address(true, true, #xlR1C1), buf);
#ENDIF
#IF.DDE(false)
tb.setText(buf);
tb.toClipboard();
sheet.paste(range);
#ENDIF
excel.visible(true);
timeFullFinish = timenow();
timeFullTotal = timeFullFinish - timeFullStart;
info('Время выполнения, сек');
info(int2str(timeFullTotal));
}