AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > Axapta FAQ > FAQ: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 03.03.2004, 17:54   #1  
Maxim Gorbunov is offline
Maxim Gorbunov
Administrator
Соотечественники
Лучший по профессии 2009
 
2,483 / 645 (26) +++++++
Регистрация: 27.11.2001
Адрес: Dubai, UAE
При работе с 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.
Вложения
Тип файла: xpo ComExcelDocument_RU.xpo (1.7 Кб, 393 просмотров)
__________________
Not registered yet? Register here!
Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me
Старый 15.08.2006, 20:39   #2  
Владимир Максимов_imported is offline
Владимир Максимов_imported
Участник
 
33 / 10 (1) +
Регистрация: 20.01.2004
Возможно то, о чем я здесь напишу и так все знают, но я столкнулся с некоторыми проблемами при использовании данного метода.

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("Ошибка при копировании данных через буфер обмена.");
	}
}
Старый 30.03.2011, 11:30   #3  
Poleax is offline
Poleax
Модератор
Аватар для Poleax
MCP
MCBMSS
Злыдни
 
1,353 / 595 (22) +++++++
Регистрация: 17.02.2005
Адрес: msk
Записей в блоге: 34
Для 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.
 


Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 21:48.