Как сделать чек из программы WPF

Я думаю каждый разработчик WinForms сталкивался с мыслью, что стандартные элементы управления формами выглядят слишком унитарно, хотелось бы привнести больше дизайна в свое приложение. И, специально для таких случаев, когда нужно специализированное оформление приложения Microsoft создали библиотеку WPF - Windows Presentation Foundation. 

Если вы создаете программу учета продаж, вам необходимо формировать документы первичного учета, такие как счета и чеки. Такие документы должны отражать данные из БД. Самым правильным решением будет использование генератора отчета для создания шаблона документа и наполнения его данными. Для интеграции отчетов в приложение WPF, можно использовать библиотеки генератора отчетов. Таким образом, по какому-либо событию можно сформировать и отобразить отчет, а также экспортировать его и отправить на печать.

Прежде чем заниматься выводом отчета, необходимо создать его шаблон в дизайнере отчетов. Мы будем использовать генератор отчетов FastReport.Net в этой статье.

В товарном чеке будут выводиться данные о покупателе, продавце и проданном товаре. При расчете итоговой стоимости в некоторых странах принято отдельно указывать процент налогового сбора, рассчитывать сумму налогового сбора и финальную сумму с учетом налогового сбора. 

Поэтому в нашем примере мы рассмотрим именно такой товарный чек.

Так как данные для чека будут браться из базы, то сначала нам, нужно создать подключение к источнику данных. В качестве примера воспользуемся демонстрационной базой данных nwind.xml из поставки FastReport.Net. Потребуются таблицы: Orders, Order Details, Customer, Employee.  Наша задача создать следующий шаблон:

Sales receipt report template

Чтобы отображать данные по конкретному заказу из каждой таблицы, все они должны быть связаны. Для этого, в FastReport.Net предусмотрен механизм связывания таблиц по ключам. Таблица Orders связана с Customers и Employees. А Order Details - с Orders и Products. 

Связь таблиц - означает, что для конкретной записи заказа, из связанных таблиц будут выбираться записи по идентификатору. Таким образом мы можем взять имя покупателя из таблицы Customers для конкретной записи Orders:

 Data sources for sales receipt

Бэнд «Данные» имеет детальный бэнд, со своим заголовочным и подвальным бэндами. Для детального бэнда «Данные» определен источник Order Details. Эта таблица тоже имеет связи:

 Order Details data source

Как вы, наверное, предполагали, существует связь с таблицей Orders. А также с таблицей товаров Products, из которой можно взять наименования.

Теперь, когда понятно, что основная информация берется из таблицы Orders, а детализирующая информация по товарам из Order Details, мы рассмотрим итоги.

Первый итог Line Total (умножение количества товара на цену) рассчитывается простым перемножением полей: [[Order Details.UnitPrice] * [Order Details.Quantity]]. Этот итог рассчитывается для каждого наименования товара. 

Далее необходимо суммировать все итоговые суммы в этом столбце и отображать в поле Sub Total. Для этого нужно создать объект итога в окне Данные:

 Create new report Total

Назовем его Sub Total и зададим свойства в появившемся окне:

 Sales Receipt SubTotal settings

Как видите мы использовали функцию сложения для итога. В качестве выражения для данных мы использовали комбинацию из умножения тех же полей, что и в Line Total. Таким образом мы получим сумму всех итогов по всем наименованиям товаров. 

В поле с заголовком Tax Rate указывается процентная ставка налогового сбора. В нашем случае она равна 5 процентам.

Для поля Tax Due необходимо рассчитать сумму налогового сбора. Формула проста – итог * процентная ставка:

[[SubTotal] * 0.05]

И, наконец, финальный итог – Total Due. Он состоит из суммы Sub Total и суммы налогового сбора:

[[SubTotal] + [SubTotal] * 0.05]

На этом создание чека завершено. Необходимо сохранить шаблон отчета в проекте вашего приложения. Например, создайте папку в App_Data в проекте и сохраните в нее шаблон отчета и базу данных nwind.xml.

А теперь перейдем к приложению.

В приложении 

Для отображения отчета в приложении нам потребуется добавить на форму компонент ScrollViewer для возможного скроллирования отчета. Внутрь этого компонента добавим еще один – ListBox.

Который будет использоваться для отображения отчета в формате Xaml. На форму программы добавим три кнопки: отображение отчета, экспорт отчета в PDF, печать отчета.

Добавим код для каждой из кнопок. Итак, отображение отчета:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private void Button_Click(object sender, RoutedEventArgs e)
 {
 var report = new Report();
 report.Load("C:/Users/User/source/repos/WPFInvoice/WPFInvoice/App_Data/invoice.frx");
 var data = new DataSet();
 data.ReadXml("C:/Users/User/source/repos/WPFInvoice/WPFInvoice/App_Data/nwind.xml");
 
 report.RegisterData(data);
 report.Prepare();
 var export = new XAMLExport();
 export.HasMultipleFiles = true;
 
 using (var ms = new MemoryStream())
 {
 export.Export(report, ms);
 lb.Items.Add(new Frame()
 {
 Content = XamlReader.Load(ms)
 });
 }
 }

Здесь, мы создаем объект отчета, загружаем в него созданный нами ран шаблон отчета. Далее создаем источник данных и регистрируем в отчете. Формы в WPF приложениях строятся с помощью языка XMAL. Поэтому и отчет нужно выводить в этом формате. Для этого мы создали экспорт в этот формат и выполнили его.

Код для кнопки экспорта отчета в PDF:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 private void PDFExport_Click(object sender, RoutedEventArgs e)
 {
 var report = new Report();
 report.Load("C:/Users/User/source/repos/WPFInvoice/WPFInvoice/App_Data/invoice.frx");
 var data = new DataSet();
 data.ReadXml("C:/Users/User/source/repos/WPFInvoice/WPFInvoice/App_Data/nwind.xml");
 
 report.RegisterData(data);
 report.Prepare();
 var export = new PDFExport();
 export.HasMultipleFiles = true;
 using (var fs = new FileStream("C:/Users/User/source/repos/WPFInvoice/WPFInvoice/App_Data/report.pdf", FileMode.Create))
 {
 export.Export(report, fs);
 }
 }

Принцип здесь тот же самый, что и с отображением отчета, только мы не добавляем полученный в результате экспорта результат на форму, а сохраняем в папку.

Код для кнопки печати отчета:

1
2
3
4
5
6
7
8
 private void Print_Click(object sender, RoutedEventArgs e)
 {
 PrintDialog printDialog = new PrintDialog();
 if (printDialog.ShowDialog() == true)
 {
 printDialog.PrintVisual(lb, "Print the report");
 }
 }

Перед печатью отчета, нужно предварительно отобразить его с помощью первой кнопки. По нажатию на кнопку будет вызван диалог печати и распечатано содержимое ListBox.

А теперь запустим приложение и нажмем кнопку Show:

Sales receipt in the WPF application

Теперь вы можете не только просмотреть созданный чек, но и сохранить его в формате PDF, а также распечатать! Вы можете изменить экспорт на любой из доступных в FastReport:

HTML, BMP, PNG, JPEG, GIF, TIFF, EMF, PDF, XLSX, DOCX, PPTX, ODS, ODT, RTF, Text, XPS, XML, XAML, PS, PPML, LaTeX, Json, Dbf, Csv, XLS (Biff8), SVG, ZPL.