Подскажите пожалуйста, или ткните пальцем где почитать.
Как запускать отчет из скрипта и сразу же отправлять его на печать, без вывода на экран.
Версия: 3.0.2.242.
Нравится
Нужно доработать функцию ShowReport так, что бы она передавала параметр в окно предпросмотра, говорящий о том, что нужно сразу печатать без предпросмотра. Как фариант сделать функцию PrintReport.
Функцию PrepareReport в scr_BaseFastReportPreview нужно доработать так, чтобы она анализировала этот параметр и вызывала PrintReport() вместо Self.Show при необходимости.
См. функции ProcessNotify и PrepareReport.
Добрый день, _e_u_!
Вопрос печати отчета без показа решается легко, но нужно предварительно ответить на следующие вопросы:
1) Все ли отчеты требуется сразу выводить на печать или только некоторые? Или выводить на печать в зависимости от некоторых условий?
2) Содержит ли отчет, подлежащий выводу на печать, форму предварительной фильтрации или нет? Если да, то какую - стандартную (настраиваемую при редактировании сервиса FastReport) или пользовательскую ?
3) Какого типа отчет планируется подавать на печать - для выделенной записи, для выделенных записей, для всех записей?
Ответы на эти вопросы существенно влияют на реализацию. Дело в том, что подготовка и показ отчета реализованы в окне wnd_BaseFastReportPreview, и собственно показ (Show для этого окна) выполняется в нескольких местах скрипта scr_BaseFastReportPreviewScript.
Предположим, что Вас интересует вариант с выводом отчета с показом стандартной формы фильтрации. Как совершенно правильно отметил Underscore, в этом случае показ окна отчета выполняется в функции ProcessNotify() указанного выше скрипта. Вам необходимо каким-то образом определить, что данный отчет нужно сразу печатать, и вместо Self.Show() реализовать следующее:
var ReportPreviewer = frpMain;
ReportPreviewer.Print();
Self.Close();
Однако, самый сложный вопрос - определить те случаи, в которых необходимо делать печать вместо показа. Реализация зависит от ответа на вопрос №1. В любом случае, придется вносить изменения в функции ShowReport(), ShowSingleRecordReport(), ShowSelectedRecordsReport() скрипта scr_ReportUtils (в зависимости от ответа на вопрос №3), с целью передать необходимый признак в окно предпросмотра отчета wnd_BaseFastReportPreview. Непосредственно передачу признака можно реализовать установкой атрибутов окна (примеры см. в этих же функциях).
Надеюсь, данный ответ поможет определиться с постановкой и реализовать задачу.
Спасибо за ответ.
1. на данном этапе 3 отчета должны автоматом выходить, при условии что стоит галочка "вывод на печать"
2. фильтрация данных происходит в скрипте
3. отчет получается "для выделенной записи"
Если интересно, то общий принцип:
После выбора определенных условий пользователем, и нажатия ОК, запускается скрипт, который формирует 3 типа документов. Для каждого из типов давно существуют отчеты, в данный момент отчеты формируют вручную указав на нужную запись и выбрав соответствующий отчет.
Поскольку я первый раз пробую вызывать отчет из скрипта, сейчас вот пытаюсь решить проблему, как сказать отчету какие данные выводить...жизненных примеров на форуме не получилось найти.
1. Неясно, где именно установлена галочка "вывод на печать".
Для изучения общего механизма создания и показа отчетов рекомендуется изучить код функции ReportMenuItemExecute() скрипта scr_ReportUtils. Эта функция - обработчик нажатия на пункт меню списка отчетов раздела. Для отчета типа "для выделенной записи", судя по всему, должна вызываться функция ShowSingleRecordReport().
Кстати, будет очень полезно в режиме отладки проверить, как выполняется код функции при показе требуемых отчетов. Это поможет быстрее реализовать задуманное.
Внутри этой функции Вам необходимо реализовать проверку того, что если строится один из интересующих отчетов (можно реализовать проверку по коду или USI отчета), то передавать в окно предпросмотра атрибут, который будет означать необходимость печати вместо показа.
В скрипте окна предпросмотра реализовать в функции PrepareReport() реализовать считывание этого атрибута и после построения отчета вместо его показа выполнять печать. Примеров для установки и чтения атрибутов в коде достаточно, код для выполнения печати отчета см. в предыдущем сообщении.
Желаю успехов!
"Гамора Дмитрий" написал: Неясно, где именно установлена галочка
Насколько я понял нужно напечатать три конкретных отчета. Т.е. нужно создать компонет превьювера (правда не уверен что он заработает без окна). Присвоить ему отчет, вызвать метод Prepare(), отфильтровать главный датасет отчета и вызвать у превьювера Print().
И так три раза.
Если распотрошить scr_BaseFastReportPreview, то там все кроме создания превьювера есть.
Удачи.
В общем, Underscore вполне четко изложил идею.
Насчет галочки - теперь понятно, что это настройка вводится пользователем, и легко передать ее в функцию ShowSingleRecordReport(), с целью последующей передачи признака с помощью атрибутов в окно предпросмотра, чтобы затем в скрипте окна проанализировать значение признака и осуществить либо показ, либо печать.
Если остались вопросы - буду рад помочь. Готовый пример сделать трудно в основном потому, что речь идет о целом наборе доработок, и Вам будет проще реализовать свой вариант, чем дорабатывать предложенный под Ваши условия.
Да. Названия параметров и функций в конфигурации иногда просто удивляют :)
В данном случае назначение параметра GridDatasetID почти очевидно, для полной ясности можно было бы назвать GridDatasetRecordID. Название GridDatasetID сложилось исторически, появилось с самых ранних версий системы.
Тогда уже просто RecordID, раз функция ShowSingleRecordReport называется. Причем тут вообще грид и датасет?
Потому что речь идет именно о считывании ID текущей записи, выбранной в разделе. Также, в функции ShowSelectedRecordsReport() без DataGrid не обойтись вообще, т.к. информация о нескольких выбранных записях в реестре хранится исключительно в компоненте, а не датасете. При именовании переменных разработчики старались давать исчерпывающие названия функциям и переменным.
А при чем здесь ShowSelectedRecordsReport. Я именно о ShowSingleRecordReport говорил. Функция печатает отчет, отфильтровав его датасет по одной записи. То что в одном конкретном случае идентификатор этой записи берется из грида раздела еще не повод называть соответствуюзий параметр с упоминанием грида и датасета.
То что старались, я не спорю. Просто разработчики бывают разные и стараются по разному :)
Согласен с Вами, Underscore. Думаю, продолжать спор не будем. Главное - это результат, в нашем случае означает успешную реализацию функции.
Функция ReportPreviewer.Print() - функция ядра, библиотека TSReportLibrary.dll, осуществляет печать подготовленного отчета. В Вашем случае можно порекомендовать отладку кода, чтобы понять причину такого поведения.
Ну чтож, добился того, что у меня документы выпрыгивают пачками, как и хотелось:) но пока на экран
куда вставить Print() я понял, в отладчике прогонял, функция эта как будто просто мимо проходится...
может надо в нее параметр какой нибудь передать?...
и еще можно ли сказать этой функции, что печатать надо 2 копии?
Печатать можно только подготовленный отчет (т.е. после выполнения ReportPreviewer.Prepare()).
На самом деле, по нажатию кнопки "Печать" в окне предпросмотра отчета, выполняется только метод frpMain.Print(); и больше ничего.
По сути дела, Вам необходимо выполнить построение отчета, но после этого не показывать окно с отчетом, а осуществить его печать.
Метод Print() не принимает параметров, при его выполнении осуществляется показ стандартного окна настройки печати, в котором при необходимости можно установить количество копий, качество печати и т.п.
это функция из scr_ReportUtils :
function ShowSingleRecordReport(ReportUSI, FilteredDatasetUSI, GridDatasetID)
{
var Report = Services.GetNewItemByUSI(ReportUSI);
var ReportPreviewer = Services.GetNewItemByUSI('wnd_BaseFastReportPreview');
var ReportPreviewerComponent = ReportPreviewer.Attributes('ReportPreviewer');
var ReportDataset = Services.GetNewItemByUSI(FilteredDatasetUSI);
SetAttribute(ReportPreviewer, 'Report', Report);
ApplyDatasetFilter(ReportDataset, 'ID', GridDatasetID, true);
ReportPreviewer.Build(); ReportPreviewer.Prepare();
ReportPreviewerComponent.DatasetByComponentName(FilteredDatasetUSI) = ReportDataset;
это функция из scr_BaseFastReportPreview
function PrepareReport(AWindow) {
....................................
var EfPrintDocs = Connector.Attributes('EfPrintDocs');
var ActPrintDocs = Connector.Attributes('ActPrintDocs');
var InvPrintDocs = Connector.Attributes('InvPrintDocs');
if ((EfPrintDocs)||(ActPrintDocs)||(InvPrintDocs)) {
// PrintReport(); // Self.Close();
Self.Show();
}else {
Self.Show(); }
}
}
} else {
var EfPrintDocs = Connector.Attributes('EfPrintDocs');
var ActPrintDocs = Connector.Attributes('ActPrintDocs');
var InvPrintDocs = Connector.Attributes('InvPrintDocs');
if ((EfPrintDocs)||(ActPrintDocs)||(InvPrintDocs)) {
//PrintReport(); //Self.Close(); Self.Show(); }else { Self.Show(); } }}
вставляя в scr_BaseFastReportPreview функцию PrintReport() получается что на печать идет отчет не прошедший до конца
функцию ShowSingleRecordReport , а именно строку ReportPreviewerComponent.DatasetByComponentName(FilteredDatasetUSI) = ReportDataset;
по всей видимости нужно PrintReport() размещать в скрипте scr_ReportUtils ?
или я что то перепутал? попробовал, ругается на frpMain
прошу прощения за форматирование....чето оно дикое какое то тут... или я
frpMain это компонент окна предпоомотра. Понятно что в scr_ReportUtils ругается.
Кстати вызов ReportPreviewerComponent.DatasetByComponentName в scr_ReportUtils меня тоже немного смущает. Как оно работает? Мы сначала показываем отчет, а потом присваиваем датасет отчету.
Вот и меня больше всего удивляет. На первый взгляд бред написан. Но работает. :)
Можно создать frpMain. Имя кокласса TSDskWindowLibrary.DskFastReportPreviewer.
Создавать
var Previewer = Services.CreateObject('TSDskWindowLibrary.DskFastReportPreviewer');
Но! Это компонент окна и как он будет без окна работать я не знаю. У него есть метод Build.Судя по названию он что-то важное делает. Возможно нужно его вызывать до печати отчета. Хотя недавний случай со свойством IsDesigning говорит о том что всяко может быть и возможно этот метод совсем не нужен :)
Удачи. Отпишитесь, если все заработает.
скопируйте сервис wnd_BaseFastReportPreview с его скриптом
назовите его wnd_BaseFastReportPreviewWithoutShow
и поменяйте функцию
function PrepareReport(AWindow) {
CheckAttribute(AWindow, 'Report');
frpMain.Report = GetAttribute(AWindow, 'Report');
var FiltersCaption = frpMain.Report.Caption + " (Фильтры)";
var PreviewCaption = frpMain.Report.Caption + " (Предпросмотр)";
frpMain.PrepareReport();
Self.WindowCaption = PreviewCaption;
if (IsAttributeExists(AWindow, 'ShowFilterForm'))
{
if (IsAttributeExists(AWindow, 'FilterForm')) {
var FilterForm = GetAttribute(AWindow, 'FilterForm');
FilterForm.Attributes('NotifyObject') = AWindow;
FilterForm.Attributes('ReportPreviewer') = frpMain;
FilterForm.Prepare();
FilterForm.WindowCaption = FiltersCaption;
FilterForm.Show();
} else{
if (frpMain.Report.FiltersXML != EmptyStr) {
BaseFastReportPreview.FiltersWindow =
Services.GetNewItemByUSI(ReportFiltersWindowUSI);
BaseFastReportPreview.FiltersWindow.Attributes('NotifyObject') =
AWindow;
BaseFastReportPreview.FiltersWindow.Attributes('ReportPreviewer') =
frpMain;
BaseFastReportPreview.FiltersWindow.Attributes('FastReport') =
frpMain.Report;
BaseFastReportPreview.FiltersWindow.Prepare();
BaseFastReportPreview.FiltersWindow.WindowCaption = FiltersCaption;
BaseFastReportPreview.FiltersWindow.Show();
} else {
frpMain.PreviewReport();
frpMain.Print();
}
}
} else {
frpMain.PreviewReport();
frpMain.Print();
}
}
должен работать
Хм. Оказывается одного Print не хватало. Нужен еще и PreviewReport. Спасибо, запомню.
Там еще ProcessNotify нужно подправить по хорошему. Ну для того что бы работало если будет форма фильтрации. И может все-таки переделать на использование параметров. Ато две почти одинаковые формы не совсем красиво. Ну это уже на Ваше усмотрение.
Прошу прощения
var Previewer = System.CreateObject('TSDskWindowLibrary.DskFastReportPreviewer');
Может пусть окно появляется. Вызываем Print и закрываем окно. Или включаем таймер, который его закроет через какое-то время.
Self.Close() ; разве не окно предпросмотра закрывает?
как сказать, чтоб нажалась кнопка ОК в окне печати?
и в чем может быть причина зависания СРМ? абсолютно тот же код, только вместо
frpMain.PreviewReport();
frpMain.Print();
стоит
Self.Show();
он работает.
виснет непосредственно после появления окна печати. дебагер показывает последней команду frpMain.Print();
А увас нормально принтер настроен? Т.е. если сделать Self.Show(); и руками кнопку печати нажать?
Вы пробовали сделать так
...
Self.Show();
if (Признак что отчет просто печатаем) {
frpMain.Print();
Self.Close() ;
}
...
А так как я предлагал, прообывали? Показать окно-напечатать-закрыть. Программно разумеется :)
попробовал
ну во первых, как я понял frpMain.Print(); - это не печать отчета, а только отображения окна печати, сейчас стоит вопрос как программно нажать в этом окне кнопочку ОК.
а второе, в данном варианте почему то отчет стал некорректно формироваться, как будто не отфильтровались данные.
С фильтрами наверное это связано с той строкой
ReportPreviewerComponent.DatasetByComponentName(FilteredDatasetUSI) = ReportDataset;
Она не отрабатывает и датасет не фильтруется. Как-то эта печать через гланды сделана. Нужно передавать FilteredDatasetUSI GridDatasetID в атрибуты окна предпросмотра и уже в этом окне фильтровать датасет. А не делать это в ShowSingleRecordReport.
Програмно наверное не получится (вариант написания COM, который возьмет верхнее окно, найдет в нем кнопку Ок и отправит ей сообщение нажаться не рассматриваем :) ) В ReportPreviewer-е вынесен только метод Print. Параметров у него нет. Другого метода для печати без показа диалогового окна тоже нет :(
"_e_u_" написал:сейчас стоит вопрос как программно нажать в этом окне кнопочку ОК.
а второе, в данном варианте почему то отчет стал некорректно формироваться, как будто не отфильтровались данные.
Столкнулся с такой же проблемой. "Нажать" программно кнопку ОК в окне печати не удалось.
Проблема с неправильной фильтрацией набора данных для отчета решилась так:
1. В функцию ShowSelectedRecordsReport (думаю, с ShowSingleRecordReport подойдет такое же решение) добавлен еще один параметр - ForcedPrinting. При вызове функции из скрипта необходимо передавать с его помощью какое-либо значение.
2. В конце функции ShowSelectedRecordsReport после строки
ReportPreviewerComponent.DatasetByUSI(FilteredDatasetCode) = ReportDataset;
выполнить функцию PrintReport скрипта scr_BaseFastReportPreviewScript, если вызов ShowSelectedRecordsReport произведен с параметром ForcedPrinting
if (ForcedPrinting) { ReportPreviewer.ScriptControl.Run('PrintReport'); }
т.е. окно печати появится уже после того, как к отчету будет "привязан" отфильтрованный набор данных.