|
|
#1 |
|
Administrator
|
При работе с Excel через COM скорость обмена данными оставляет желать лучшего. Авторы форума AxForum.RU POS (http://www.axforum.ru/forums/member.php?s=...nfo&userid=2317) и DSV (http://www.axforum.ru/forums/member.php?s=...nfo&userid=1527) предложили способ, позволяющий значительно ускорить вывод больших объемов данных в Excel.
Предлагаемое решение представляет собой метод класса ComExcelDocument_RU: <div class='XPPtop'>X++</div><div class='XPP'>[color=:blue]public[/color] [color=:blue]void[/color] insertText(BookMark _bookMark, TextBuffer _text, [color=:blue]int[/color] _workSheet = 1) { COM XLSWorkSheet, XLSrange; TextBuffer tempBuffer; [color=:green]// To store clipboard contents [/color] ; [color=:green]// Initializing XLSWorkSheet object [/color] XLSWorkSheet = this.getWorkSheet(_workSheet); [color=:blue]if[/color] (!XLSWorkSheet) [color=:blue]throw[/color] error([color=:red]"@DIS6043"[/color]); [color=:green]// Initializing XLSRange object [/color] XLSrange = this.findRange(_bookMark); [color=:blue]if[/color] (!XLSrange) [color=:blue]throw[/color] error([color=:red]"@SYS27391"[/color]); XLSrange.[color=:blue]select[/color](); [color=:green]// Storing clipboard contents [/color] tempBuffer = [color=:blue]new[/color] TextBuffer(); tempBuffer.fromClipboard(); [color=:green]// Preparing text to be inserted [/color] _text.toClipboard(); [color=:green]// Inserting text from clipboard [/color] XLSWorkSheet.pasteSpecial(1); [color=:green]// 1 - "Text only" mode [/color] [color=:green]// Restoring clipboard contents [/color] tempBuffer.toClipboard(); }</div> Этот метод вставляет через буфер обмена содержимое текстового буфера _text в ячейку с именем _bookMark. То, что вставка происходит через буфер обмена, значительно ускоряет работу, так как и Axapta и Excel работают с буфером на приличной скорости. Использование "Специальной вставки" (Paste special) и режима "Только текст" (Text only) позволяет побороть проблемы, возникающие в операционных системах линейки NT, связанные с некорректным выводом русских символов при вставке из буфера обмена. В заключение небольшой пример использования метода: <div class='XPPtop'>X++</div><div class='XPP'>[color=:blue]static[/color] [color=:blue]void[/color] Job1(Args _args) { ComExcelDocument_RU excelDocument = [color=:blue]new[/color] ComExcelDocument_RU(); TextBuffer text = [color=:blue]new[/color] TextBuffer(); [color=:blue]int[/color] chr; [color=:green]// Initializing Excel [/color] excelDocument.InitApplication(); [color=:green]// Creating new Excel document [/color] excelDocument.newDocument(); [color=:green]// Preparing data for insertion [/color] [color=:blue]for[/color] (chr = char2num([color=:red]'A'[/color], 1); chr <= char2num([color=:red]'я'[/color], 1); chr++) { [color=:blue]if[/color] (chr [color=:blue]==[/color] char2num([color=:red]'a'[/color], 1) [color=:blue]||[/color] chr [color=:blue]==[/color] char2num([color=:red]'А'[/color], 1)) text.appendText([color=:red]'\n'[/color]); text.appendText(num2char(chr) + num2char(9)); [color=:blue]if[/color] (chr [color=:blue]==[/color] char2num([color=:red]'Z'[/color], 1) [color=:blue]||[/color] chr [color=:blue]==[/color] char2num([color=:red]'z'[/color], 1) [color=:blue]||[/color] chr [color=:blue]==[/color] char2num([color=:red]'Я'[/color], 1)) text.appendText([color=:red]'\n'[/color]); } [color=:green]// Inserting data into Excel [/color] excelDocument.insertText([color=:red]"C4"[/color], text); }</div> В этом Job формируется текстовый буфер, заполненый символами от A до я со знаками табуляции в качестве разделителей. Затем сформированный буфер вставляется в Excel.
__________________
Not registered yet? Register here! Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me |
|
|
|
|
#2 |
|
Участник
|
Возможно то, о чем я здесь напишу и так все знают, но я столкнулся с некоторыми проблемами при использовании данного метода.
1) Если в качестве параметра передается объект TextBuffer в который вообще ничего не записано (не пустая строка, а именно вообще ничего), то получим исключение на команде PastSpecial. Поэтому стоит добавить проверку на размер TextBiffer 2) Насколько я понимаю, логика работы с буферами в Windows примерно следующая: если в данный момент осуществляется заполнение буфера обмена, то команда, данная из другого приложения на заполнение буфера обмена будет проигнорирована. На практике, это означает примерно следующее: -) Пользователь запустил отчет и пока отчет готовит данные переключился на другое приложение. -) В этом другом приложении он дал команду на копирование буфера (Ctrl+C) -) В этот момент AXAPTA начала выполнять метод insertText() и попытка что-то добавить в буфера обмена была отвергнута -) Последующая команда PastScpecial вызвала исключение и отчет не был сформирован В качестве решения, я "зациклил" попытку вставки. В результате, получился примерно такой код Код: public void insertText(BookMark _bookMark, TextBuffer _text, int _workSheet = 1)
{
COM XLSWorkSheet, XLSrange;
TextBuffer tempBuffer; // To store clipboard contents
int nextI,
maxI = 3;
;
// Если содержимое TextBuffer вообще не введено, то PastSpecial даст ошибку,
// а если заведена пустая строка, то нет смысла делать PastSpecial
if (! _text.size())
{
return;
}
// Initializing XLSWorkSheet object
XLSWorkSheet = this.getWorkSheet(_workSheet);
if (!XLSWorkSheet)
{
throw error("@DIS6043");
}
// Initializing XLSRange object
XLSrange = this.findRange(_bookMark,_workSheet);
if (!XLSrange)
{
throw error("@SYS27391");
}
XLSrange.select();
for (nextI = 1; nextI <= maxI; nextI++)
{
try
{
// Storing clipboard contents
tempBuffer = new TextBuffer();
tempBuffer.fromClipboard();
// Preparing text to be inserted
_text.toClipboard();
// Inserting text from clipboard
XLSWorkSheet.pasteSpecial(1); // 1 - "Text only" mode
// Restoring clipboard contents
tempBuffer.toClipboard();
// В случае успеха, прерываю цикл
break;
}
catch(Exception::Error)
{
// в случае ошибки удаляю последнюю строку infolog,
// которая генерится автоматически ошибкой COM
if (infolog.line())
{
infolog.clear(infolog.line()-1);
}
// предпринимаю очередную попытку сделать вставку через буфер
}
} // for (nextI)
// Если выход из цикла for произошел "штатно", то значение счетчика будет больше максимально допустимого значения
if (nextI > maxI)
{
throw error("Ошибка при копировании данных через буфер обмена.");
}
} |
|
|
|
|
#3 |
|
Модератор
|
Для Ax 2009 был случай вывода русский слов в не верной кодировке.
Вставка в Excel из TextBuffer. Кодировка Ниже исправлена в коде исправлена одна строка на XLSWorkSheet.pasteSpecial(0); Код: public void insertText(BookMark _bookMark, TextBuffer _text, int _workSheet = 1)
{
COM XLSWorkSheet, XLSrange;
TextBuffer tempBuffer; // To store clipboard contents
int nextI,
maxI = 3;
;
// Если содержимое TextBuffer вообще не введено, то PastSpecial даст ошибку,
// а если заведена пустая строка, то нет смысла делать PastSpecial
if (! _text.size())
{
return;
}
// Initializing XLSWorkSheet object
XLSWorkSheet = this.getWorkSheet(_workSheet);
if (!XLSWorkSheet)
{
throw error("@DIS6043");
}
// Initializing XLSRange object
XLSrange = this.findRange(_bookMark,_workSheet);
if (!XLSrange)
{
throw error("@SYS27391");
}
XLSrange.select();
for (nextI = 1; nextI <= maxI; nextI++)
{
try
{
// Storing clipboard contents
tempBuffer = new TextBuffer();
tempBuffer.fromClipboard();
// Preparing text to be inserted
_text.toClipboard();
// Inserting text from clipboard
///ГЛЮК XLSWorkSheet.pasteSpecial(1); // 1 - "Text only" mode
XLSWorkSheet.pasteSpecial(0);
// Restoring clipboard contents
tempBuffer.toClipboard();
// В случае успеха, прерываю цикл
break;
}
catch(Exception::Error)
{
// в случае ошибки удаляю последнюю строку infolog,
// которая генерится автоматически ошибкой COM
if (infolog.line())
{
infolog.clear(infolog.line()-1);
}
// предпринимаю очередную попытку сделать вставку через буфер
}
} // for (nextI)
// Если выход из цикла for произошел "штатно", то значение счетчика будет больше максимально допустимого значения
if (nextI > maxI)
{
throw error("Ошибка при копировании данных через буфер обмена.");
}
}
__________________
This posting is provided "AS IS" with no warranties, and confers no rights. |
|
|
|