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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 21.01.2009, 12:37   #1  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
Классы для генерации отчетов в Excel
Привет всем.
Часто приходится создавать экселевские отчеты. Вначале пользовался джобом AndyD Исследование скорости экспорта данных из Axapta в Excel (коллективный эксперимент)
Вывод в xml формате, как мне кажется, наиболее привлекателен и возможностями форматирования, и скоростью. Но джоб нужно каждый раз править под свои нужды, поэтому возникла мысль несколько это автоматизировать. Выкладываю классы позволяющие создавать такие экселевские отчеты. Основные цели, которых мне хотелось достигнуть при проектировании этих классов:
- сохранить скорость вывода отчетов;
- упростить создание отчетов;
- получить возможность гибко настраивать и расширять функциональность отчетов;
- убрать ограничение на количество выводимых данных;

При тестировании скорость вывода 50000 строк в простом цикле (без запроса в бд) около 30 секунд, на серваке отработало за 10 сек.

Простейший пример отчета:
X++:
    VendTable       vendTable;
    IXMLExcelReport rep = new CXMLExcelReport();
    ;

    while select vendTable
        rep.send([vendTable.AccountNum, vendTable.Name, today(), 100.0012]);

    rep.show();
О том, как задавать стили, ширину, фиксировать ячейки и.т.д. в примерах в проекте .

Последний раз редактировалось Eldar9x; 10.06.2011 в 13:29.
За это сообщение автора поблагодарили: tolstjak (1), Logger (6), coolibin (2), MironovI (2), Daiver (1), aidsua (1), _scorp_ (3), kalex_a (1), vazerdim (1), ZornFire (1).
Старый 21.01.2009, 13:02   #2  
Ivanhoe is offline
Ivanhoe
Участник
Аватар для Ivanhoe
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
4,143 / 2156 (80) +++++++++
Регистрация: 29.09.2005
Адрес: Санкт-Петербург
Вопрос по форматированию в Excel:

1. решена ли проблема с высотой строк и объединенными ячейкам? Если в строке есть объединенные ячейки, то автоподбор высоты по строке перестает работать (ограничение Excel).
2. решена ли проблема с выводом "перевода строки" в ячейке? Чтобы в одной ячейке можно было сделать несколько абзацев, как при ручном вводе в Excel по ALT+Enter (ограничение Axapta-вского генератора xml)/
__________________
Ivanhoe as is..
Старый 21.01.2009, 13:16   #3  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
Цитата:
Вопрос по форматированию в Excel:
попробую решить
Старый 21.01.2009, 13:46   #4  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
2-е решается легко, достаточно форматировать текст в виде:
str s = strfmt("Строка 1%1%2%3%4%5Строка 2%1%2%3%4%5Строка 3", '&','#','1','0',';');
и в стиле задать " <Alignment ss:Vertical=\"Bottom\" ss:WrapText=\"1\"/>"

Насчет первого - пытаюсь вкурить, поясните. Как можно это обойти, если это ограничение самого excel...
Старый 21.01.2009, 13:58   #5  
Ivanhoe is offline
Ivanhoe
Участник
Аватар для Ivanhoe
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
4,143 / 2156 (80) +++++++++
Регистрация: 29.09.2005
Адрес: Санкт-Петербург
Ограничение Excel, но некоторые отчеты, особенно табличного вида, без этого не построить красиво.

Видел разные решения - например, в некой простой строке вставить текст, узнать высоту строки (которая автоматически подобралась) и выставить высоту явно. Правда, такое решение видел при работе через COM. Как решить через xml - надо думать.

По поводу перевода строки в ячейке, у меня не получалось так сделать, буду смотреть Ваш проект
__________________
Ivanhoe as is..
Старый 21.01.2009, 14:11   #6  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
Цитата:
буду смотреть Ваш проект
думаю, искать в строке символ \n это загубить всю скорость, лучше форматировать на месте, но указвать доп. стиль.

Последний раз редактировалось Eldar9x; 10.06.2011 в 13:29.
Старый 22.01.2009, 12:26   #7  
andrewK is offline
andrewK
Участник
 
45 / 22 (1) +++
Регистрация: 03.11.2005
"Переменная GRD_InventTreeGroup не объявлена."
А где можно найти эту переменную?
Старый 22.01.2009, 12:52   #8  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
Нигде - это из наших доработок. В классе Tester код в методе test() табличную переменную можно чем-нибудь другим заменить
Старый 05.03.2009, 15:52   #9  
Daiver is offline
Daiver
Участник
Самостоятельные клиенты AX
 
177 / 44 (2) +++
Регистрация: 19.07.2005
Адрес: Москва
Привет.
Попробовал использовать эти классы для вывода относительно большого массива данных (например 113 столбцов, 970 строк), получаю ошибку:

"Сообщение (17:07:23)
Ошибка времени выполнения: Недостаточно памяти для исполнения кода.

Трассировка стека

(S)\Classes\CXMLRowBuilder\buf - line 4
(S)\Classes\CXMLExcelReport\swapBuf - line 14
(S)\Classes\CXMLExcelReport\show - line 8"

При меньшем объеме данных такой проблемы не возникает.
Также её можно обойти, если например через каждые 100 строк делать swap.

Не подскажешь, в чем может быть проблема?

ЗЫ: версия Акс 4 SP2EE FP1. Версия Excel 2003 (11.5612.5606)
ЗЫЫ: Для 4-ки в классе CXMLExcelReport метод new, система требует ExecutePermission.assert(); ...
За это сообщение автора поблагодарили: Shmel_83 (1).
Старый 05.03.2009, 16:02   #10  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
классы делал на 3-ку. Скоро выложу и для четверки. Насчет проблемы, щас 4-ки под рукой нет, посмотрю позже. Можешь проверить для меньшего количества столбцов (10-20) как в четверке отработает, или при запуске с клиента?
Старый 05.03.2009, 16:23   #11  
Daiver is offline
Daiver
Участник
Самостоятельные клиенты AX
 
177 / 44 (2) +++
Регистрация: 19.07.2005
Адрес: Москва
Цитата:
Сообщение от Eldar9x Посмотреть сообщение
классы делал на 3-ку. Скоро выложу и для четверки. Насчет проблемы, щас 4-ки под рукой нет, посмотрю позже. Можешь проверить для меньшего количества столбцов (10-20) как в четверке отработает, или при запуске с клиента?
При swapQty 1000: Строк 970, если столбцов более 66 то вылетает ошибка. Если оставить 66, но увеличить строки, например до 980, то снова ошибка. Снижаем swapQty, ошибка пропадает. Я у себя оставил swapQty 100 ...
Если кол-во строк не большое, например взял 100, то и при swapQty 1000 все нормально.

Последний раз редактировалось Daiver; 05.03.2009 в 16:25.
Старый 06.03.2009, 10:44   #12  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
Сделал небольшое наблюдение.

При swapQty = 10000, код
X++:
    IXMLExcelReport report = new CXMLExcelReportEx();
    ;

    for (i = 1; i <= 10970; i++)
    {

        con = connull();
        for (j = 1; j <= 213; j++)
        {
            con += "Некая строка для вывода";
        }
        con += i;

        report.send(con);
    }

    report.show();
валится в момент передачи данных в excel (метод swapBuf)
this.range(curRow,1,curRow+curLines-1,xmlRowBuilder.cols()).value(#xlRangeValueXMLSpreadsheet, xmlRowBuilder.buf());

При этом длина строки buf составила 145705719, что, если я не ошибаюсь, сотсавляет примерно 145 MB !!!
Уменьшение swapQty до 5000 распечатало отчет нормально. Но даже в этом случае на вызов метода range.value ушло несколько секунд.
Есть подозрение, что передача большого объема данных в excel чревато нехорошими последствиями. Буду проверять в 4ке

ps/ знакомая ошибка, кстати Обратная разработка в AX4

psps/ базовый класс оставил со swapQty 1000. На будущее, если строите отчет на основе этих классов, не берите в качестве движка базовый (сам так делал). Создавайте на его основе наследника, и уже его используйте для генерации отчета. Тогда в случае разрастания какого-нибудь отчета в колонках, достаточно будет перегрузить swapQty только на нем.

Последний раз редактировалось Eldar9x; 06.03.2009 в 10:58.
Старый 10.03.2009, 14:11   #13  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
Выкладываю обновленные классы:
1) Добавлена возможность контролировать (без перегрузки метода) предельный размер буфера до выгрузки (swapQty). по умолчанию выставлено в 1000;
X++:
report.swapQty(1000);
2) Добавлена возможность контролировать размеры буфера во избежание его переполнения:
задается командой
X++:
report.autoSwap(true);
по умолчанию выключено
макимальный размер буфера (по умолчанию выставлен 1000000) задается командой
X++:
report.maxStr(1000000);
Это гарантирует работу при любом размере отчета, но несколько замедляет его вывод, поэтому при большом числе колонок лучше регулировать swapQty.
3) Добавлена возможность выводить многострочные ячейки. Для этого ячейке указывается стиль WRAP_STR. Можно добавлять свои стили с перенесом строки, но их нужно включить в метод CXMLStyles::wrapTextStyles()
X++:
report.send([1, today(), "Строка 1\nСтрока 2\nСтрока 3"], ["", "EX5_NUM", "", "WRAP_STR"]);
4) Формат ячейки теперь определяется автоматически, если не задан конкретный стиль.

Последний раз редактировалось Eldar9x; 10.06.2011 в 13:28.
За это сообщение автора поблагодарили: blokva (2).
Старый 23.03.2009, 11:15   #14  
tolstjak is offline
tolstjak
Участник
 
440 / 16 (1) ++
Регистрация: 05.01.2003
Подскажите пожалуйста как вывести в первой строке отчета его заглавие " ОСВ по ........"?
Использую класс CXMLInventReport т.к в нем есть диалог..
__________________
Александр
Старый 23.03.2009, 11:41   #15  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
Простой вариант:
в методе Run до цикла по таблице
X++:
    xmlExcelReport.write("ОСВ по", 1, 1, 1, 3, 1, "CLR_CNR_STR"); // выводим текст
    xmlExcelReport.curRow(2); // сдвигаем текущую позицию вниз
Параметры метода:
- текст
- стартовая строка
- стартовая колонка
- конечная строка
- конечная колонка
- tabsheet
- стиль для ячейки.
Недостаток:
При переходе на новую страницу заголовок не будет печататься

Более правильный вариант, лишенный указанного недостатка:
делаем наследника от CXMLExcelReportEx (в качестве примера можно взять Tutorial_CXMLExcelJobReport).
делаем наследника от CXMLExcelRunBase, перегружаем в нем xmlExcelReportClass (вернуть надо classnum созданного наследника от CXMLExcelReportEx) и используем его так же, как вы использовали CXMLInventReport.

стили можно задавать так, хотя это и длиньше, но более правильно.
staticmethodstr(CXMLStyles, CLR_CNR_STR)

Последний раз редактировалось Eldar9x; 23.03.2009 в 11:49.
Старый 23.03.2009, 12:37   #16  
tolstjak is offline
tolstjak
Участник
 
440 / 16 (1) ++
Регистрация: 05.01.2003
Цитата:
Сообщение от Eldar9x Посмотреть сообщение
xmlExcelReport.curRow(2); // сдвигаем текущую позицию вниз
Спасибо за подсказку.
Ругается на функцию: Задано неправильное число аргументов функции.
Буду разбираться.
__________________
Александр
Старый 23.03.2009, 12:49   #17  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
Цитата:
Задано неправильное число аргументов функции.
инкрементную компиляцию после импорта делали?
Надо для CXMLExcelReport, CXMLExcelRunBase
а версия аксапты какая?
Старый 23.03.2009, 12:53   #18  
tolstjak is offline
tolstjak
Участник
 
440 / 16 (1) ++
Регистрация: 05.01.2003
Цитата:
Сообщение от Eldar9x Посмотреть сообщение
инкрементную компиляцию после импорта делали?
Надо для CXMLExcelReport, CXMLExcelRunBase
а версия аксапты какая?
Делал.

Вместо xmlExcelReport.curRow(2);
сделал xmlExcelReport.setcurRow(2);
заглавие отчета появилось.

Большое спасибо еще раз.
__________________
Александр

Последний раз редактировалось tolstjak; 23.03.2009 в 13:10.
Старый 23.03.2009, 13:27   #19  
Eldar9x is offline
Eldar9x
MCTS
Аватар для Eldar9x
Oracle
MCBMSS
 
1,064 / 166 (8) ++++++
Регистрация: 29.09.2006
Адрес: Казань
Нее. setCurRow() лучше не использовать. От методов get set я избавляюсь, видимо забыл удалить в этих проектах. Они нигде не должны использоваться. Метода curRow() достаточно, чтобы и установить и получить значение. Видимо у вас до импорта старая версия висела в приложении (еще из первого поста, который я почему-то не могу редактировать...).
Сделайте следующее, откройте classDeclaration CXMLExcelRunBase, внесите в него какие-нибудь изменения (пробел поставьте где-нибудь) и перекомпилируйте целиком весь класс, потом снова инкрементную компиляцию. То же самое можно проделать с другими классами. Я бы вообще снес все классы под корень и импортировал заново.
Старый 23.03.2009, 13:35   #20  
tolstjak is offline
tolstjak
Участник
 
440 / 16 (1) ++
Регистрация: 05.01.2003
Цитата:
Сообщение от Eldar9x Посмотреть сообщение
Нее. setCurRow() лучше не использовать. От методов get set я избавляюсь, видимо забыл удалить в этих проектах. Они нигде не должны использоваться. Метода curRow() достаточно, чтобы и установить и получить значение. Видимо у вас до импорта старая версия висела в приложении (еще из первого поста, который я почему-то не могу редактировать...).
Сделайте следующее, откройте classDeclaration CXMLExcelRunBase, внесите в него какие-нибудь изменения (пробел поставьте где-нибудь) и перекомпилируйте целиком весь класс, потом снова инкрементную компиляцию. То же самое можно проделать с другими классами. Я бы вообще снес все классы под корень и импортировал заново.
ОК.
так и сделаю.
__________________
Александр
Теги
excel, xml, отчет

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Исследование скорости экспорта данных из Axapta в Excel (коллективный эксперимент) Gustav DAX: База знаний и проекты 79 13.02.2014 13:18
[Excel] - Несколько версий Excel на машине клиента Андре DAX: Программирование 11 07.08.2007 13:45
Вызов Item() для коллекций Excel Владимир Максимов DAX: Программирование 15 17.08.2006 19:47
Проект "Движок отчётов с поддержкой Excel" Alks DAX: База знаний и проекты 6 07.01.2005 02:53
Экспорт отчетов в Excel tolstjak DAX: Прочие вопросы 10 18.02.2004 09:12
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

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

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

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