01.02.2005, 14:07 | #1 |
Участник
|
Приветствую всех!
Я сейчас буду задавать много глупый вопрос. Цель моя - выгружать отчеты во внешнее хранилище. Нужно все - и само содержимое отчета (в формате HTML/PDF) и "распарсенная" информация - значение полей отчета. Вопрос #1. Есть такая штука в отчетах "Опции/канал вывода". Было бы просто супер-круто добавить туда свой канал вывода "внешнее хранилище отчетов"! Возможно ли это? Есть такое чувство что да, куда копать? Вопрос #2. Как программно запустить отчет и указать канал вывода "файл". Тыкните в документацию или класс, пожалуйста! |
|
01.02.2005, 14:21 | #2 |
Участник
|
1. Вроде да. Коламбус продает решение, где добавлен канал вывода в Excel (насколько я понял из разговоров с Коламбусами). Куда копать - не знаю.
2. Рыть в сторону класса SysPrintOptions, PrintJobSettings |
|
01.02.2005, 16:54 | #3 |
Участник
|
Да, у коламбуса есть такой продукт...
Я тут нарыл класс ReportOutputUser, можно создать от него населедника и использовать в качестве print medium, как я понимаю это и есть канал вывода. Возникает закономерный вопрос - почему же до сих пор никто не сделал универсального наследника, выгружающего отчет в Excel? Это же будет работать с любым уже существующим отчетом - не надо писать дополнительного кода в отчете, в отличие от подхода, предлагаемого в MegadomReport. Где собака зарылась? |
|
01.02.2005, 17:04 | #4 |
Участник
|
Цитата:
Сообщение от lexa_q
Возникает закономерный вопрос - почему же до сих пор никто не сделал универсального наследника, выгружающего отчет в Excel?
Правильный вопрос: почему такую разработку еще никто не выложил в открытый доступ? |
|
01.02.2005, 17:47 | #5 |
Участник
|
8)))
Ставлю правильный вопрос: есть ли в открытом доступе пример, как ВЫЗВАТЬ отчет так, чтобы формированием занимался мой наследник ReportOutputUser. Ковыряю xpo-шник системный, и че-то никак не врублюсь... Они там конечно круто все развели внутри: ReportOutputUser createViewer(...) { ..... switch (outputType) { case ReportOutputUserType::HTML: { ret = new WebReportHTML(jobsCursor, pagesCursor, report); return ret; } .... Ну а как в эту маханику внедрить мой класс? Тем более что Axapta не дает расширить enum ReportOutputUserType и тем более перекрыть ClassFactory::createViewer. Я так мыслю что надо копать в сторону ReportRun - видимо, он вызывает createViewer(), но раскопки стали ходить по кругу уже... |
|
01.02.2005, 18:09 | #6 |
Участник
|
lexa_q, спокойнее.
Пользуйтесь перекрестными ссылками. Леко найти, что в первом топике я неполностью указал класс. Параметрами отчета заведует класс PrintJobSettings. Далее смотрите, на метод viewerType этого класса. Смотрите что в системном перечислении ReportOutputUserType есть два зарезервированных пункта Viewer4. Viewer5. Далее посмотрите на перечисление PrintMedium и обратите внимание на зарезервированное слово ViewerClass. Обратите внимание, что этот ViewerClass трактуется в форме печати SysPrintForm как файл... Далее поищите на течнете и поройтесь в перекрестных ссылках. В общем, в панику впадать не стоит. Все достаточно логично. Нужно только время, чтобы разобраться... |
|
01.02.2005, 18:14 | #7 |
Участник
|
Цитата:
Сообщение от lexa_q
Ну а как в эту маханику внедрить мой класс? Тем более что Axapta не дает расширить enum ReportOutputUserType и тем более перекрыть ClassFactory::createViewer.
С чего это вы не можете его перекрыть? Кроме того, в этом методе есть чудесный класс SysDummyPrintViewer <div class='XPPtop'>X++</div><div class='XPP'>ReportOutputUser createViewer(PrintJobHeader jobsCursor, PrintJobPages pagesCursor, ReportOutputUserType outputType, ReportRun report=NULL) { ReportOutputUser ret; [color=:blue]switch[/color] (outputType) { [color=:blue]case[/color] ReportOutputUserType::HTML: { ret = [color=:blue]new[/color] WebReportHTML(jobsCursor, pagesCursor, report); [color=:blue]return[/color] ret; } [color=:blue]case[/color] ReportOutputUserType::Viewer5: { ret = [color=:blue]new[/color] WebReportGraph(jobsCursor, pagesCursor, report); [color=:blue]return[/color] ret; } [color=:blue]case[/color] ReportOutputUserType::PDF: { [color=:blue]return[/color] [color=:blue]new[/color] PDFViewer(jobsCursor, pagesCursor); } [color=:blue]case[/color] ReportOutputUserType::[color=:blue]Default[/color]: [color=:blue]case[/color] ReportOutputUserType::Viewer4: { [color=:blue]return[/color] [color=:blue]new[/color] SysDummyPrintViewer(jobsCursor, pagesCursor); } } [color=:blue]return[/color] NULL; }</div> |
|
01.02.2005, 18:20 | #8 |
Участник
|
В общем, замечательная такая иерархия выстраивается...
Ее и используйте. |
|
03.02.2005, 13:27 | #9 |
Участник
|
В общем, как я понял, подход такой:
I. Модифицируем форму SysPrintForm, чтобы она предлагала новый канал вывода - наш. В методе initSendTo() добавляем пункт в список II. В SysPrintForm.closeOK() надо задать параметры генерации, хранимые в clientSysPrintOptions. 2 параметра: 1) clientSysPrintOptions.parmTarget(PrintMedium::ViewerClass) это прводит к тому, что ReportRun() вызывает ClassFactory::createViewer(). 2) clientSysPrintOptions.parmViewerType( *XXX*) *XXX* передатся в createViewer как параметр outputType. III. Модифицируем метод <div class='XPPtop'>X++</div><div class='XPP'>ClassFactory::createViewer(PrintJobHeader jobsCursor, PrintJobPages pagesCursor, ReportOutputUserType outputType, ReportRun report=NULL) { ... [color=:blue]case[/color] *XXX*: [color=:blue]return[/color] [color=:blue]new[/color] MyViewer(); }</div> Внимание, вопрос! 8) Перечисление ReportOutputUserType не расширяемо - в него не добавить свое значение *XXX* ! Там есть неиспользуемое значение Viewer4, но не хотелось бы на него завязываться. Я попробовал в качестве *XXX* передавать просто число 100, и ловить в createViewer() тоже 100. Работает. Но пахнет это плохо! Как быть? Верен ли описанный подход? Тут народ в http://www.axforum.ru/forums/showthread.ph...32267#post32267 тоже делал свой канал, они наверняка в курсе. Но при попытке написать им письмо сайт просит обратиться к админу, т.е. к mazzy. Обращаюсь! Mazzy, ка им написать? |
|
03.02.2005, 14:04 | #10 |
Участник
|
Ёпть! Вот же оно! Блин. Если бы я в своё время докопался до этого, то был бы уже такой отчёт в общем доступе! Пришлось извращатся через MegadomeReport...
Цитата:
Это же будет работать с любым уже существующим отчетом - не надо писать дополнительного кода в отчете, в отличие от подхода, предлагаемого в MegadomReport.
|
|
03.02.2005, 14:22 | #11 |
Участник
|
Цитата:
Я попробовал в качестве *XXX* передавать просто число 100, и ловить в createViewer() тоже 100. Работает. Но пахнет это плохо!
|
|
03.02.2005, 15:01 | #12 |
Участник
|
Размышления по поводу и без.
Экспорт отчётов в эксель очень просто сделать например вот таким способом: 1. экспортируем отчёт в txt файл 2. импортируем этот файл в эксель ...неудобно, но зато работает и сразу даёт понять что экспорт всех отчётов в эксель задача не такая уж и прямолинейная - добавление нового канала вывода, поддерживающего все методы startPage, startSection... и т.п. выльется в совершенно бесполезную работу, по той причине, что данные в эксель экспортируются не для распечатки, а для анализа. Табличного анализа. Т.е. все данные должны быть подбиты в строгие строки и колонки, чтобы по ним можно было суммировать, сортировать и т.п. Тут возникает множество проблем стандартного дизайна отчётов. Во первых - как правило отчёты состоят из секций, а секции как известно стоят одна под одной, нарушая табличный порядок, плюс еще у подсекций могут выводится подолнительные заголовки. Плюс к тому возникает вопрос - разумно ли в excel выводить подитоги, если он сам это умеет делать. Плюс еще у каждой страницы может быть начало и конец, плюс еще куча мелочей, в результате если посмотреть то что получается при выводе достаточно сложного отчёта в txt наглядно видно почему придётся изрядно поломать голову за написанием универсального канала вывода для всех уже существующих отчётов в Excel. |
|
03.02.2005, 15:19 | #13 |
Участник
|
Цитата:
Сообщение от lexa_q
Тут народ в http://www.axforum.ru/forums/showthread.ph...32267#post32267 тоже делал свой канал, они наверняка в курсе. Но при попытке написать им письмо сайт просит обратиться к админу, т.е. к mazzy. Обращаюсь! Mazzy, ка им написать?
Я написал участникам обсуждения на ахфоруме. Если они захотят - ответят. |
|
03.02.2005, 15:21 | #14 |
Участник
|
Цитата:
Сообщение от =A=L=X=
Размышления по поводу и без.
Экспорт отчётов в эксель очень просто сделать например вот таким способом: 1. экспортируем отчёт в txt файл 2. импортируем этот файл в эксель ...неудобно, но зато работает и сразу даёт понять что экспорт всех отчётов в эксель задача не такая уж и прямолинейная Но все равно было бы красиво, если бы кто-нибудь (а еще лучше разработчики Аксапты) таки сделали бы такой канал. |
|
03.02.2005, 15:48 | #15 |
Участник
|
Цитата:
Сообщение от lexa_q
Внимание, вопрос! 8)
Перечисление ReportOutputUserType не расширяемо - в него не добавить свое значение *XXX* ! Там есть неиспользуемое значение Viewer4, но не хотелось бы на него завязываться. Я попробовал в качестве *XXX* передавать просто число 100, и ловить в createViewer() тоже 100. Работает. Но пахнет это плохо! Как быть? Верен ли описанный подход? Пользовательский канал определяется там так: printJobSettings.setTarget(PrintMedium::viewerClass); printJobSettings.viewerType(ReportOutputUserType:efault); и к классу reportOutputUser навешивается наследник для управления выводом. |
|
03.02.2005, 18:04 | #16 |
Участник
|
Да, точно! У ReportOutputUser есть описание! Слона-то и не заметил!
Mazzy, спасибо! lugachy, спасибо! В описании они предлагают перекрывать prompt() отчета для установки printJobSettings.setTarget/setViewerType. Это не гуд так как придется добавлять этот код во все отчеты. Господа, есть соображения как вставить свой класс-перехватчик отчета без "хака" с передачей 100 (*XXX*) в createViewer? Есть ли еще место, куда можно внедриться типа SysPrintForm? lugachy, как Вы сделали у себя? =A=L=X=, вы совершенно правы насчет всех этих startSection/startPage. Оформление и отступы не нужны, нужны сухие данные. lugachy заставил Аксапту не бить отчет на страницы: Цитата:
Решил проблему так:
В методе формы SysPrintForm.closeOk() для своего канала вывода (экселя)устанавливаю свойство viritualPageHeight в 0. После этого аксапта понимает что нет пределов по высоте и больше не пытается разбивать отчет на страницы. Если все удастся, не вижу причин не выложить в общий доступ скелет получившегося канала - без кода выгружки во внешнюю систему. |
|
03.02.2005, 18:23 | #17 |
Участник
|
Цитата:
Сообщение от lexa_q
Господа, есть соображения как вставить свой класс-перехватчик отчета без "хака" с передачей 100 (*XXX*) в createViewer? Есть ли еще место, куда можно внедриться типа SysPrintForm?
В 3.0 не проверял. Будьте предельно внимательны и осторожны. Ни в коем случае НЕ ВЫПОЛНЯЙТЕ этих действий на РАБОЧЕЙ БАЗЕ. Я ничего не гарантирую, ниже только предположения.
|
|
04.02.2005, 10:02 | #18 |
Участник
|
Цитата:
Сообщение от lexa_q
В описании они предлагают перекрывать prompt() отчета для установки printJobSettings.setTarget/setViewerType. Это не гуд так как придется добавлять этот код во все отчеты.
Модифицируем методы:: buildSendToList(***) { *** *** //самый конец метода formListItem = new FormListItem("Excel", imageListAppl_Print.image(#ImageExcel), PrintMedium::ViewerClass); sendTo.addItem(formListItem); } changeTarget(***) { //В конец тала switch'a добавляем case PrintMedium::ViewerClass : element.setTargetSettings(#TAB_PRINTER, "Вывести отчет в Excel", PrintMedium::ViewerClass, true); break; И нет никакой необходимости править каждый отчет. Если вам необходимо создать несколько каналов вывода (я, например, такой задачи еще не придумал), то это можно сделать с помощью дополнительного енума, и аксапту ломать не придется. В качестве примера по реализации Viewer-класса могу порекомендовать посмотреть классы WebReportHTML и WebReportBase. Скажите, вы уже определились конкретно что вы хотите получить?? В каком виде вы хотите получать отчеты в Эксель? Если у вас задача получать в экселе красивые отчеты, да еще и для заказчика - бросайте это дело. Или по крайней мере определитесь сначала что и как вы хотите получить. Для заказчика лучше разработаь мастер отчетов, по типу штатного мастера отчетов, только для Экселя. } |
|
04.02.2005, 11:06 | #19 |
Участник
|
О красоте речь скорее всего не идет, т.к. экспортировать в эксель чтобы потом это просто распечатать глупо.
Скорее всего желательно следующее поведение: а) сообщить движку отчётов что весь отчет должен выводится в одну страницу (уже даже объяснили как) б) прологи и эпилоги выводить без извратов - как получится в) секции выводить не в подчинении друг к другу, а разворачивать их в плоскую таблицу, т.е.: заголовок секции 1 секция1 (а) заголовок секции 2 секция2 (а) секция2 (б) заголовок секции 1 секция1 (б) заколовок секции 2 секция2 (в) превратить в заголовок секции 1 заголовок секции 2 секция1 (а) секция2 (а) секция1 (а) секция2 (б) секция1 (б) секция2 (в) Чем больше думаю о том как такое реализовать, тем больше мыслей что придётся остановится на MegadomeReport. |
|
04.02.2005, 11:49 | #20 |
Участник
|
Такое сделать вполне возможно.
|
|