Управление свойствами веб отчета внешними контролами

16.08.2017

В этой статье я хочу рассмотреть возможность работы с отчетом с помощью элементов управления веб формы в проекте ASP .Net MVC.

Итак, задача - создать веб приложение, которое будет позволять:

1)      загружать веб отчет;

2)      экспортировать отчет в один из трех форматов;

3)      отображать/скрывать панель инструментов веб отчета;

4)      настраивать стиль кнопок на панели инструментов;

5)      запускать отчет в Online дизайнере.

Приступим. Для начала проведем некоторые подготовительные работы, чтобы запустить веб отчет в MVC приложении. Добавляем ссылки на библиотеки: FastReport и FastReport.Web.

В папке Views->Shared нужно отредактировать файл _Layout.cshtml. Добавляем скрипты и стили в заголовок:

1
2
3
4
<head>
 @WebReportGlobals.Scripts()
 @WebReportGlobals.Styles()
</head>

Опять же в папке Views есть файл Web.config. Добавляем в него пространства имен:

1
2
3
4
 <namespaces>
 <add namespace="FastReport" />
 <add namespace="FastReport.Web" />
 </namespaces>

В корне проекта есть еще один Web.config. В него добавляем обработчик, сразу после секции modules:

1
2
3
4
5
6
 <modules>

 </modules>
 <handlers>
 <add name="FastReportHandler" path="FastReport.Export.axd" verb="*" type="FastReport.Web.Handlers.WebExport"/>
 </handlers>

В HomeController добавляем логику работы с отчетом.

В методе Index будем загружать отчет и передавать его во вью.

1
2
3
4
5
6
7
8
 public ActionResult Index()
 {
 SetReport();
 webReport.Width = Unit.Percentage(100);
 webReport.Height = Unit.Percentage(100);
 ViewBag.WebReport = webReport;
 return View();
 }

Я вынес загрузку отчета в отдельный метод, который мы рассмотрим ниже. Устанавливаем ширину и высоту веб отчета в 100%. С помощью ViewBag передаем отчет в представление. И возвращаем представление Index.

Чтобы использовать объект отчета в разных методах я создал глобальную переменную – экземпляр объекта WebReport.

1
public WebReport webReport = new WebReport();

1)  Теперь рассмотрим загрузку отчета:

1
2
3
4
5
6
7
8
private void SetReport()
 {
 string report_path = GetReportPath();
 System.Data.DataSet dataSet = new System.Data.DataSet();
 dataSet.ReadXml(report_path + "nwind.xml");
 webReport.Report.RegisterData(dataSet, "NorthWind");
 webReport.Report.Load(report_path + "Master-Detail.frx");
 }

Задаем путь к папке с отчетами. Для удобства я создал отдельный метод с присвоением переменной пути к отчетам. Далее, создаем экземпляр объекта DataSet. Загружаем в него базу данных XML. Затем, регистрируем источник данных в объекте отчета. И, наконец, загружаем шаблон отчета в объект WebReport.

Метод установки пути к папке с отчетами:         

1
2
3
4
private string GetReportPath()
 {
 return this.Server.MapPath("~/App_Data/");
 }

2)      Давайте, не переходя ко вью добавим еще метод выбора экспорта отчета:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void ReportExport(string type)
 {
 SetReport();
 switch (type)
 {
 case "pdf":
 webReport.ExportPdf();
 break;
 case "csv":
 webReport.ExportCsv();
 break;
 default:
 webReport.ExportWord2007();
 break;
 }

Тут мы загрузили отчет. В зависимости от значения параметра type производим один из трех видов экспорта.

Теперь откроем представление Index.

Добавим на форму выпадающий список с тремя вариантами экспорта:

1
2
3
4
5
6
7
8
9
10
11
 @using (Html.BeginForm("ReportExport", "Home"))
 {
 @Html.DropDownList("Type", new List<SelectListItem>()
{
 new SelectListItem(){ Text= "PDF", Value = "pdf"},
 new SelectListItem(){ Text= "CSV", Value = "csv"},
 new SelectListItem(){ Text= "Word", Value = "doc"},
}, "Select export type")
 <input id="pdf" type="submit" value="Export" />
 }
@ViewBag.WebReport.GetHtml()

Здесь мы использовали html хэлпер, с помощью которого создали форму, указывающую на контроллер “Home” и экшен (метод) “ReportExport”. Помните, мы уже создали такой метод в контроллере. Внутри формы мы создаем элемент DropDownList и наполняем его значениями. Конечно, можно было создать модель данных. Но, так как список состоит всего из трех элементов, я заполнил его прямо в представлении. После выпадающего списка расположена кнопка типа submit, по которой будет обновляться веб страница.

Как вы помните, метод ReportExport принимает параметр type – значение из выпадающего списка. В зависимости от выбранного значения будет произведен экспорт отчета в соответствующий формат.

3)     Теперь реализуем сокрытие панели инструментов отчета. Во вью это будет выглядеть так:

1
2
3
4
@using (Html.BeginForm("Index", "Home"))
{
@Html.CheckBox("Toolbar", true, new { @onchange = "this.form.submit()" }) Toolbar
}

Как и в предыдущем примере, мы создаем форму. Однако, в этот раз указываем экшен Index – там, где у нас отображается отчет. Внутри формы мы создали элемент CheckBox. Его значение будем передавать в метод Index. На этот раз я решил не добавлять очередную кнопку для обновления страницы, а воспользовался событием @onchange, где указал функцию отправки формы "this.form.submit()". Теперь, при изменении значения checkbox страница будет обновляться.

По аналогии с экспортом отчета, мы должны передать в метод параметр. В данном случае это “Toolbar”. Будет передан строковый эквивалент булевой функции. Перейдем к нашему контролу, а именно к экшену Index:

1
2
3
4
5
6
7
8
9
10
11
12
13
public ActionResult Index(string toolbar)
 {
 SetReport();
 webReport.Width = Unit.Percentage(100);
 webReport.Height = Unit.Percentage(100);
 if (toolbar == "true")
 webReport.ShowToolbar = true;
 else
 webReport.ShowToolbar = false;
 
 ViewBag.WebReport = webReport;
 return View();
 }

В методе добавился один параметр и условие. В зависимости от значения параметра toolbar мы принимаем решение включать или отключать панель инструментов.

4)      Переходим к созданию элементов управления, с помощью которых мы сможем выбирать стиль иконок. В предыдущий пример с формой мы добавим еще четыре элемента RadioButton:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@using (Html.BeginForm("Index", "Home"))
 {
 <table>
 <tr>
 <td>
 @Html.CheckBox("Toolbar", true, new { @onchange = "this.form.submit()" }) Toolbar
 </td>
 <tr>
 <tr>
 <td>Black Buttons:</td><td> @Html.RadioButton("Radio", "Black Buttons", true, new { style = "width: 13px;", @onchange = "this.form.submit()" })</td>
 </tr>
 <tr>
 <td>Green Buttons:</td><td> @Html.RadioButton("Radio", "Green Buttons", false, new { style = "width: 13px;", @onchange = "this.form.submit()" })</td>
 </tr>
 <tr>
 <td>Blue Buttons:</td><td>@Html.RadioButton("Radio", "Blue Buttons", false, new { style = "width: 13px;", @onchange = "this.form.submit()" })</td>
 </tr>
 <tr>
 <td>Red Buttons:</td><td>@Html.RadioButton("Radio", "Red Buttons", false, new { style = "width: 13px;", @onchange = "this.form.submit()" })</td>
 </tr>
 </table>
@ViewBag.WebReport.GetHtml()

 Для улучшения внешнего вида, я поместил элементы в таблицу. Рассмотрим один из элементов RadioButton:

Html.RadioButton("Radio", "Black Buttons", true, new { style = "width: 13px;", @onchange = "this.form.submit()" })

Здесь имя контрола – “Radio”. Именно так будет называться еще один параметр в экшене Index. Затем, следует значение – “Black Buttons”. То есть, на панели инструментов будут отображаться черные кнопки. Следующее значение – будет ли отмечена радио кнопка по умолчанию. Последний параметр представляет собой объект HtmlAttributes. Здесь можно указать любой из доступных атрибутов для тэга <input type="radio" />. Я воспользовался этим и указал ширину контрола и событие onchange по аналогии с предыдущим элементом checkbox.

Итак, всего четыре радио кнопки – четыре стиля иконок в панели инструментов. Вернемся к нашему экшену Index:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public ActionResult Index(string toolbar, string radio)
 {
 SetReport();
 webReport.Width = Unit.Percentage(100);
 webReport.Height = Unit.Percentage(100);
 if (toolbar == "true")
 webReport.ShowToolbar = true;
 else
 webReport.ShowToolbar = false;
switch (radio)
 {
 case "Red Buttons":
 webReport.ToolbarIconsStyle = ToolbarIconsStyle.Red;
 break;
 case "Green Buttons":
 webReport.ToolbarIconsStyle = ToolbarIconsStyle.Green;
 break;
 case "Blue Buttons":
 webReport.ToolbarIconsStyle = ToolbarIconsStyle.Blue;
 break;
 default:
 webReport.ToolbarIconsStyle = ToolbarIconsStyle.Black;
 break;
 }
 
 ViewBag.WebReport = webReport;
 return View();
 }

 Добавился еще один параметр – radio. В конструкции Switch я назначаю нужный стиль, в зависимости от значения radio.

Давайте вынесем обработку параметров toolbar и radio в отдельные методы, для порядка. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public void ShowToolbar(string toolbar)
 {
 if (toolbar == "true")
 webReport.ShowToolbar = true;
 else
 webReport.ShowToolbar = false;
 }
 
 public void ToolbarStyle(string radio)
 {
 switch (radio)
 {
 case "Red Buttons":
 webReport.ToolbarIconsStyle = ToolbarIconsStyle.Red;
 break;
 case "Green Buttons":
 webReport.ToolbarIconsStyle = ToolbarIconsStyle.Green;
 break;
 case "Blue Buttons":
 webReport.ToolbarIconsStyle = ToolbarIconsStyle.Blue;
 break;
 default:
 webReport.ToolbarIconsStyle = ToolbarIconsStyle.Black;
 break;
 }
 }

Index тоже изменился:

1
2
3
4
5
6
7
8
9
10
public ActionResult Index(string toolbar, string radio)
 {
 SetReport();
 webReport.Width = Unit.Percentage(100);
 webReport.Height = Unit.Percentage(100);
ShowToolbar(toolbar);
 ToolbarStyle(radio);
 ViewBag.WebReport = webReport;
 return View();
 }

5)      Осталось реализовать последнюю задуманную функцию – запуск отчета в Online дизайнере. Скажу сразу, чтобы его отобразить, необходимо получить сборку OnlineDesigner с сайта разработчика и включить ее в проект. Просто разархивируйте и добавьте всю папку WebReportDesigner в корень проекта.

Добавим в форму из предыдущего примера кнопку и скрытое поле:

1
2
<input id="dsg" type="submit" value="@ViewBag.Result" onclick="document.getElementById('hid').value='@ViewBag.WebReport.DesignReport.ToString()'"/>
<input id="hid" type="hidden" name="dsg">

 По нажатию на кнопку будет отправлена форма. Обратите внимание, что атрибут value определяется через ViewBag. Мы передаем значение кнопки из контрола. Чуть позже вы поймете зачем я так сделал. Для кнопки назначено событие oncklick. В нем я присваиваю значение элементу hidden. Обратите внимание, что благодаря ViewBag я получаю значение свойства веб отчета. Таким образом, если на странице показан Дизайнер отчетов, то значение поля hidden будет ture, иначе false.

Для поля hidden задаем атрибут id=”hid”. Благодаря идентификатору мы находим нужный элемент на форме. Теперь весь код для представления выглядит так:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@{
 ViewBag.Title = "Home Page";
}
<div style="float:left">
 @using (Html.BeginForm("ReportExport", "Home"))
 {
 @Html.DropDownList("Type", new List<SelectListItem>()
{
 new SelectListItem(){ Text= "PDF", Value = "pdf"},
 new SelectListItem(){ Text= "CSV", Value = "csv"},
 new SelectListItem(){ Text= "Word", Value = "doc"},
}, "Select export type")
 <input id="pdf" type="submit" value="Export" />
 }
 <div align="left">
 @using (Html.BeginForm("Index", "Home"))
 {
 <table>
 <tr>
 <td>
 @Html.CheckBox("Toolbar", true, new { @onchange = "this.form.submit()" }) Toolbar
 </td>
 <td>
 <input id="dsg" type="submit" value="@ViewBag.Result" onclick="document.getElementById('hid').value='@ViewBag.WebReport.DesignReport.ToString()'"/>
 <input id="hid" type="hidden" name="dsg">
 </td>
 <tr>
 <tr>
 <td>Black Buttons:</td><td> @Html.RadioButton("Radio", "Black Buttons", true, new { style = "width: 13px;", @onchange = "this.form.submit()" })</td>
 </tr>
 <tr>
 <td>Green Buttons:</td><td> @Html.RadioButton("Radio", "Green Buttons", false, new { style = "width: 13px;", @onchange = "this.form.submit()" })</td>
 </tr>
 <tr>
 <td>Blue Buttons:</td><td>@Html.RadioButton("Radio", "Blue Buttons", false, new { style = "width: 13px;", @onchange = "this.form.submit()" })</td>
 </tr>
 <tr>
 <td>Red Buttons:</td><td>@Html.RadioButton("Radio", "Red Buttons", false, new { style = "width: 13px;", @onchange = "this.form.submit()" })</td>
 </tr>
 </table>
 }
 </div>
</div>
 
 @ViewBag.WebReport.GetHtml()

 Перейдем к контроллеру.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public ActionResult Index(string toolbar, string radio, string dsg)
 {
 SetReport();
 webReport.Width = Unit.Percentage(100);
 webReport.Height = Unit.Percentage(100);
 ShowToolbar(toolbar);
 ToolbarStyle(radio);
 ViewBag.Result = ShowDesigner(dsg);
 ViewBag.WebReport = webReport;
 return View();
 }
 
 public string ShowDesigner(string dsg)
 {
 if (dsg == "False")
 {
 webReport.DesignReport = true;
 return "Show Report";
 }
 else if (dsg == "True")
 {
 webReport.DesignReport = false;
 return "Show Designer";
 }
 return "Show Designer";
 }

 Как видите добавился еще один параметр в методе Index. Его имя соответствует имени элемента hidden во вью. Также добавилась строка: «ViewBag.Result = ShowDesigner(dsg);».

В ней я передаю имя кнопки в представление. Новый метод ShowDesigner включает или отключает дизайнер отчета и возвращает имя кнопки.

Запустим приложение:

Выпадающий список с тремя видами экспорта:

 

Отключаем тулбар:

 

А теперь включим онлайн дизайнер отчетов:

 

Отобразим отчет и включим тулбар. Выберем какой-нибудь стиль для кнопок на тулбаре:

 

Таким образом, мы создали внешние элементы управления с помощью которых управляем свойствами объекта WebReport в приложении ASP .Net MVC. 

.NET FastReport ASP.NET MVC WebReport .NET FastReport ASP.NET MVC WebReport
10 февраля 2025

Как попробовать FastReport .NET WEB перед покупкой

Протестировав WEB пак перед покупкой, вы сможете сделать осознанный выбор: подходит ли вам FastReport .NET для ваших задач.
14 марта 2023

Будущее генерации отчетов с помощью Blazor WebAssembly

Пошаговая инструкция по созданию демо приложения на .NET 6 и 7 прямо в браузере с помощью Blazor WebAssembly в FastReport .NET.
14 февраля 2023

Как настроить веб-сервер Apache2 для FastReport .NET

Запускаем веб-сервер Apache2 в операционной системе Linux для FastReport .NET и .NET 5 с помощью нескольких простых команд.