Страница 1 из 3
Рендеринг отчёта с разными параметрами
Добавлено: 29 дек 2015, 13:52
Леонид
Добрый день!
Возникла такая ситуация: необходимо распечатать пакет документов, в частности счетов-фактур.
Мы решили её примерно таким способом:
Код: Выделить всё
// create main report
StiReport stiReport = new StiReport()
{
NeedsCompiling = false,
IsRendered = true,
};
// clear blank page
stiReport.RenderedPages.Clear();
// create sub report
StiReport subReport = new StiReport();
subReport.Load("test.mrt"); // load report <--- если перенести эту строку в первую строку цикла foreach, то всё работает, как ожидалось
// numbers list for a test
List<int> numbers = new List<int>() { 111, 222, 333 };
// traverse through the list
foreach (int x in numbers)
{
subReport.Dictionary.Variables["AVar_0"].Value = x.ToString(); // set report variable
subReport.Dictionary.Synchronize(); // synch dictionary
// render sub report
subReport.Render(false);
// add rendered pages
foreach (StiPage repPage in subReport.RenderedPages)
{
repPage.Report = stiReport; // set main report as a container
stiReport.RenderedPages.Add(repPage); // add each page of the report to the main report
}
subReport.RenderedPages.Clear(); // drop rendered pages
subReport.IsRendered = false; // drop rendered flag
}
// show final report
stiReport.Show();
Собственно вопрос в том, почему при выполнении вышеуказанного кода метод Render выполняется, но данные остаются те же, что были, когда он вызывался первый раз.
При это, если вызывать метод Load каждый раз перед рендерингом (методом Render), то всё работает, как ожидалось.
В вышеуказанном примере на каждой из трёх страниц будет выводится 111, а должно выводится 111 на первой странице, 222 на второй и 333 на третьей. Что мы делаем не так?
Re: Рендеринг отчёта с разными параметрами
Добавлено: 29 дек 2015, 16:10
Aleksey
Здравствуйте,
Пожалуйста, попробуйте использовать следующий код:
Код: Выделить всё
...
subReport.Load("e:\\1.mrt"); // load report <--- если перенести эту строку в первую строку цикла foreach, то всё работает, как ожидалось
subReport.Compile();
// numbers list for a test
List<int> numbers = new List<int>() { 111, 222, 333 };
// traverse through the list
foreach (int x in numbers)
{
subReport["AVar_0"] = x; // set report variable
//subReport.Dictionary.Synchronize(); // synch dictionary
// render sub report
subReport.Render(false);
...
Спасибо.
Re: Рендеринг отчёта с разными параметрами
Добавлено: 29 дек 2015, 17:07
Леонид
Очень круто!
Работает!!! Огромное спасибо!
P.S. Единственное, что
Вызывает Object of type 'System.Int32' cannot be converted to type 'System.String'., поэтому писать нужно
Re: Рендеринг отчёта с разными параметрами
Добавлено: 30 дек 2015, 01:59
Ivan
Здравствуйте.
Дайте нам знать, если вам понадобится ещё какая-нибудь помощь.
Спасибо.
Re: Рендеринг отчёта с разными параметрами
Добавлено: 20 янв 2016, 17:28
Леонид
Добрый вечер!
В процессе работы выяснился некоторый неприятный нюанс - если в отчёте есть Connection (в нашем случае это подключение к Oracle) и DataSource, то отчёт выполняется верно, т.е. данные выводятся, но все корректно.
Поясню на том же простом примере. У нас есть простой массив из чисел 111, 222, 333, 444 и 555, его мы выводим в переменную на DataBand1, - всё работает корректно.
Дальше, у нас есть Connection (к Oracle) и DataSource с таким вот (для примера, разумеется) простым select'ом:
Код: Выделить всё
select (case when :DOC_CODE = 111 then 'Номер 1'
when :DOC_CODE = 222 then 'Номер 2'
when :DOC_CODE = 333 then 'Номер 3'
when :DOC_CODE = 444 then 'Номер 4'
when :DOC_CODE = 555 then 'Номер 5'
end) as caption_field
from dual
При этом здесь есть входящий параметр DOC_CODE типа decimal, его мы используем в событии объекта Report BeginRender() так:
Код: Выделить всё
Field1 = AVar_0;
// set param value
DataSource1.Parameters["DOC_CODE"].ParameterValue = decimal.Parse(AVar_0);
// connect to data source
DataSource1.Connect();
// set result
Caption1 = DataSource1.CAPTION_FIELD;
В результате данные в Field1 (который выводится на DataBand1) отображаются корректно, а данные из select'а "со сдвигом" ровно на одну страницу, т.е. на первой странице они пустые, а со второй отображаются как "Номер 1", на третьей "Номер 2" и т.д., а должно отображаться с первой страницы.
Причём, если установить значение переменной AVar_0 ещё до метода Compile(), то строка "Номер1" выведется на первой странице, как надо, но проблему это не решает, т.к. "Номер1" выведется и на второй странице, и далее, как описано выше.
Полностью рабочий код на C#:
Код: Выделить всё
// create main report
StiReport stiReport = new StiReport()
{
NeedsCompiling = false,
IsRendered = true,
};
// clear blank page
stiReport.RenderedPages.Clear();
// create sub report
StiReport subReport = new StiReport();
subReport.Load("test.mrt"); // load report
// subReport.Dictionary.Variables["AVar_0"].Value = docCodesList[0].docCode.ToString(); // take first code from list
(subReport.Dictionary.Databases[0] as StiOracleDatabase).ConnectionString = oraConnectionString; // set connection string before compiling
subReport.Dictionary.Synchronize();
subReport.Compile(); // compile report
// numbers list for a test
List<int> numbers = new List<int>() { 111, 222, 333, 444, 555 };
// traverse through the list
foreach (int x in numbers)
{
subReport["AVar_0"] = x.ToString(); // set report variable
// render sub report
subReport.Render(false);
// add rendered pages
foreach (StiPage repPage in subReport.RenderedPages)
{
repPage.Report = stiReport; // set main report as a container
stiReport.RenderedPages.Add(repPage); // add each page of the report to the main report
}
}
// show final report
stiReport.Show();
Рабочий тестовый пример во вложении.
Re: Рендеринг отчёта с разными параметрами
Добавлено: 21 янв 2016, 14:33
Aleksey
Здравствуйте,
Не смогли воспроизвести проблему. Пожалуйста, уточните какую версию вы используете.
Спасибо.
Re: Рендеринг отчёта с разными параметрами
Добавлено: 21 янв 2016, 14:49
Леонид
Добрый день!
Версия отчёта: 2015.2.0.0.
Да, с цифрами на DataBand1 проблем и не было, я говорил о цифрах из select'а Oracle, значения из которого записываются в ReportTitle1 (см. скриношот). Проблема не решена, т.к. Вы её не воспроизвели.
Re: Рендеринг отчёта с разными параметрами
Добавлено: 22 янв 2016, 16:54
Aleksey
Здравствуйте,
Вы подключаете данные в BeginRender событии, там еще нет данных. Пожалуйста, перенесите ваш код в событие BeforePrint страницы.
Спасибо.
Re: Рендеринг отчёта с разными параметрами
Добавлено: 26 янв 2016, 17:26
Леонид
Добрый день!
Проверил много раз, в итоге, да, на тестовых данных всё работает, но на наших почему-то по-прежнему нет.
Буду готовить вам отчёт, как он есть с реальными данными, чтобы показать суть. Там будет всего несколько страниц (для теста хватит). Не пойму в чём дело.
Однако, у нас более 190 отчётов, в которых метод .Connect прописан в событии BeginRender объекта отчёта, поэтому конечно, не хотелось бы всё это переносить во всех отчётах в событие BeforePrint.
На данный момент, мы делаем так: получаем список кодов отчётов и кодов документов, затем пробегаемся по всем уникальным кодам отчётов, чтобы загрузить их в MemoryStream из OracleBlob (т.к. они могу повторятся, например, накладных может быть 500 или более, т.к. они печатаются за период для налоговой), и получается, что меняют только данные, а так пока сделали отчёт, который загружает blob'ы (реально это .mrt-файлы) из базы, а потом просто делаем в цикле (как в тестовом примере) .Load(reportBody), где reportBody это просто MemoryStream получаемый из списка типа List<MemoryStream> по коду отчёта.
Однако, это медленно, и ~1000 страниц рендерится таким образом ~11-12 минут вместо одной, как в случае с .Compile().
Так что через какое-то время подготовлю тестовую версию отчёта и попрошу вас помочь разобраться, возможно, я что-то не знаю или не учёл.
Re: Рендеринг отчёта с разными параметрами
Добавлено: 27 янв 2016, 16:08
Aleksey
Здравствуйте, Леонид
Необходим пример отчета для анализа. Постараемся разобраться.
Спасибо.