Как сгенерировать отчет с использованием базы данных на C# и .NET


Этот код показывает, как сгенерировать отчет о Mail Merge , используя шаблон DOCX и базу данных в качестве данных источник.

В нашем примере мы возьмем готовую базу данных «Northwind.mdb». Мы будем экспортировать данные из таблиц: Orders, Customers, Shippers, Employees, [Order Details] и Products для создания нашего отчета.

Далее, мы создайте шаблон в MS Word с Merge Fields полей или использования готового шаблона: «OrdersDbTemplate.docx».

Итак, мы должны взять данные из Northwind database и объединяем его с нашим шаблоном.

Шаг 1:Создайте новый DataTable введите название "orders" и заполните его всеми необходимыми данными из базы данных.
Мы воспользуемся DataTable (orders) чтобы создать заголовок таблицы (как показано на рисунке ниже) для каждого приказ.

// Execute query for retrieving data of Orders table.
            DataTable orders = ExecuteSQL(string.Join(" ",
                "SELECT DISTINCT Orders.ShipName, Orders.ShipAddress, Orders.ShipCity,",
                "Orders.ShipRegion, Orders.ShipPostalCode, Orders.ShipCountry, Orders.CustomerID,",
                "Customers.CompanyName AS Customers_CompanyName, Customers.Address, Customers.City,",
                "Customers.Region, Customers.PostalCode, Customers.Country,",
                @"[FirstName] & "" "" & [LastName] AS SalesPerson, Orders.OrderID, Orders.OrderDate,",
                "Orders.RequiredDate, Orders.ShippedDate, Shippers.CompanyName AS Shippers_CompanyName",
                "FROM Shippers INNER JOIN (Employees INNER JOIN (Customers INNER JOIN Orders ON",
                "Customers.CustomerID = Orders.CustomerID) ON Employees.EmployeeID = Orders.EmployeeID)",
                "ON Shippers.ShipperID = Orders.ShipVia"));
            orders.TableName = "Orders";
            dataSet.Tables.Add(orders);
            

В результате мы получим:

шаг 2: Создайте другую таблицу данных с именем 'OrderDetails'.
Мы будем использовать эту таблицу данных ((orderDetails), чтобы создать основную часть таблицы (как показано на рисунке ниже) для каждого заказа.

 // Execute query for retrieving data of OrderDetails table.
            DataTable orderDetails = ExecuteSQL(string.Join(" ",
                "SELECT DISTINCTROW Orders.OrderID, [Order Details].ProductID, Products.ProductName,",
                "[Order Details].UnitPrice, [Order Details].Quantity, [Order Details].Discount,",
                "([Order Details].[UnitPrice]*[Quantity]*(1-[Discount])/100)*100 AS TotalPrice",
                "FROM Products INNER JOIN (Orders INNER JOIN [Order Details] ON",
                "Orders.OrderID = [Order Details].OrderID) ON Products.ProductID = [Order Details].ProductID"));
            orderDetails.TableName = "OrderDetails";
            dataSet.Tables.Add(orderDetails);
            

В результате мы получим:

Рассчитайте промежуточный итог по каждому заказу.

 document.MailMerge.FieldMerging += (sender, e) =>
            {
                if (e.RangeName == "Order" && e.FieldName == "Subtotal")
                {
                    e.Inline = new Run(e.Document, ((double)dataSet.Tables["Orders"].Rows[e.RecordNumber - 1].
                        GetChildRows("OrderDetails").Sum(item => (double)item["TotalPrice"])).
                        ToString("$#,##0.00", CultureInfo.InvariantCulture));
                    e.Cancel = false;
                }
            };
            

Выполните процесс Mail Merge и сохраните полученный отчет в виде «Orders.docx».

Полный код

using System.Linq;
using System.Globalization;
using System.Data;
using System.Data.OleDb;

using SautinSoft.Document;

namespace Sample
{
    class Sample
    {
        static void Main(string[] args)
        {
            MailMergeUsingDatabase();
        }
        /// <summary>
        /// How to generate a Report (Mail Merge) using a DOCX template and Database as a data source.
        /// </summary>
        /// <remarks>
        /// See details at: https://www.sautinsoft.com/products/document/help/net/developer-guide/mail-merge-using-database-net-csharp-vb.php
        /// </remarks>
       static void MailMergeUsingDatabase()
        {
            // Load the DOCX-template document. 
            DocumentCore document = DocumentCore.Load(@"..\..\OrdersDbTemplate.docx");
            
            // Create a data source.
            DataSet dataSet = new DataSet();

            // Execute query for retrieving data of Orders table.
            DataTable orders = ExecuteSQL(string.Join(" ",
                "SELECT DISTINCT Orders.ShipName, Orders.ShipAddress, Orders.ShipCity,",
                "Orders.ShipRegion, Orders.ShipPostalCode, Orders.ShipCountry, Orders.CustomerID,",
                "Customers.CompanyName AS Customers_CompanyName, Customers.Address, Customers.City,",
                "Customers.Region, Customers.PostalCode, Customers.Country,",
                @"[FirstName] & "" "" & [LastName] AS SalesPerson, Orders.OrderID, Orders.OrderDate,",
                "Orders.RequiredDate, Orders.ShippedDate, Shippers.CompanyName AS Shippers_CompanyName",
                "FROM Shippers INNER JOIN (Employees INNER JOIN (Customers INNER JOIN Orders ON",
                "Customers.CustomerID = Orders.CustomerID) ON Employees.EmployeeID = Orders.EmployeeID)",
                "ON Shippers.ShipperID = Orders.ShipVia"));
            orders.TableName = "Orders";
            dataSet.Tables.Add(orders);

            // Execute query for retrieving data of OrderDetails table.
            DataTable orderDetails = ExecuteSQL(string.Join(" ",
                "SELECT DISTINCTROW Orders.OrderID, [Order Details].ProductID, Products.ProductName,",
                "[Order Details].UnitPrice, [Order Details].Quantity, [Order Details].Discount,",
                "([Order Details].[UnitPrice]*[Quantity]*(1-[Discount])/100)*100 AS TotalPrice",
                "FROM Products INNER JOIN (Orders INNER JOIN [Order Details] ON",
                "Orders.OrderID = [Order Details].OrderID) ON Products.ProductID = [Order Details].ProductID"));
            orderDetails.TableName = "OrderDetails";
            dataSet.Tables.Add(orderDetails);

            // Add parent-child relation.
            orders.ChildRelations.Add("OrderDetails", orders.Columns["OrderID"], orderDetails.Columns["OrderID"]);

            // Calculate and fill Total.
            document.MailMerge.Execute(
                new
                {
                    Total = ((double)orderDetails.Rows.Cast<DataRow>().Sum(item => (double)item["TotalPrice"])),
                });

            // Calculate Subtotal for the each order.
            document.MailMerge.FieldMerging += (sender, e) =>
            {
                if (e.RangeName == "Order" && e.FieldName == "Subtotal")
                {
                    e.Inline = new Run(e.Document, ((double)dataSet.Tables["Orders"].Rows[e.RecordNumber - 1].
                        GetChildRows("OrderDetails").Sum(item => (double)item["TotalPrice"])).
                        ToString("$#,##0.00", CultureInfo.InvariantCulture));
                    e.Cancel = false;
                }
            };

            // Execute the Mail Merge.
            // Note: As the name of the region in the template (Order) is different from the name of the table (Orders), we explicitly specify the name of the region.
            document.MailMerge.Execute(orders, "Order");

            string resultPath = "Orders.docx";

            // Save the output to file.
            document.Save(resultPath);

            // Open the result for demonstration purposes.
            System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(resultPath) { UseShellExecute = true }); 
        }

        /// <summary>
        /// Utility function that creates a connection, executes the sql-query and 
        /// return the result in a DataTable.
        /// </summary>
        static DataTable ExecuteSQL(string sqlText)
        {
            // Open the database connection.
            string str = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + @"..\..\Northwind.mdb";
            OleDbConnection conn = new OleDbConnection(str);
            conn.Open();

            // Create and execute a command.
            OleDbCommand cmd = new OleDbCommand(sqlText, conn);
            OleDbDataAdapter da = new OleDbDataAdapter(cmd);
            DataTable table = new DataTable();
            da.Fill(table);

            // Close the database.
            conn.Close();

            return table;
        }
    }
}

Скачать

Импортировать System.Linq
Imports System.Globalization
Imports System.Data
Imports System.Data.OleDb

Imports SautinSoft.Document

Namespace Sample
	Friend Class Sample
		Shared Sub Main(ByVal args() As String)
			MailMergeUsingDatabase()
		End Sub
        ''' <summary>
        ''' How to generate a Report (Mail Merge) using a DOCX template and Database as a data source.
        ''' </summary>
        ''' <remarks>
        ''' See details at: https://www.sautinsoft.com/products/document/help/net/developer-guide/mail-merge-using-database-net-csharp-vb.php
        ''' </remarks>
        Private Shared Sub MailMergeUsingDatabase()
            ' Load the DOCX-template document. 
            Dim document As DocumentCore = DocumentCore.Load("..\OrdersDbTemplate.docx")

            ' Create a data source.
            Dim dataSet As New DataSet()

			' Execute query for retrieving data of Orders table.
			Dim orders As DataTable = ExecuteSQL(String.Join(" ", "SELECT DISTINCT Orders.ShipName, Orders.ShipAddress, Orders.ShipCity,", "Orders.ShipRegion, Orders.ShipPostalCode, Orders.ShipCountry, Orders.CustomerID,", "Customers.CompanyName AS Customers_CompanyName, Customers.Address, Customers.City,", "Customers.Region, Customers.PostalCode, Customers.Country,", "[FirstName] & "" "" & [LastName] AS SalesPerson, Orders.OrderID, Orders.OrderDate,", "Orders.RequiredDate, Orders.ShippedDate, Shippers.CompanyName AS Shippers_CompanyName", "FROM Shippers INNER JOIN (Employees INNER JOIN (Customers INNER JOIN Orders ON", "Customers.CustomerID = Orders.CustomerID) ON Employees.EmployeeID = Orders.EmployeeID)", "ON Shippers.ShipperID = Orders.ShipVia"))
			orders.TableName = "Orders"
			dataSet.Tables.Add(orders)

			' Execute query for retrieving data of OrderDetails table.
			Dim orderDetails As DataTable = ExecuteSQL(String.Join(" ", "SELECT DISTINCTROW Orders.OrderID, [Order Details].ProductID, Products.ProductName,", "[Order Details].UnitPrice, [Order Details].Quantity, [Order Details].Discount,", "([Order Details].[UnitPrice]*[Quantity]*(1-[Discount])/100)*100 AS TotalPrice", "FROM Products INNER JOIN (Orders INNER JOIN [Order Details] ON", "Orders.OrderID = [Order Details].OrderID) ON Products.ProductID = [Order Details].ProductID"))
			orderDetails.TableName = "OrderDetails"
			dataSet.Tables.Add(orderDetails)

			' Add parent-child relation.
			orders.ChildRelations.Add("OrderDetails", orders.Columns("OrderID"), orderDetails.Columns("OrderID"))

			' Calculate and fill Total.
			document.MailMerge.Execute(New With {Key .Total = (CDbl(orderDetails.Rows.Cast(Of DataRow)().Sum(Function(item) CDbl(item("TotalPrice")))))})

			' Calculate Subtotal for the each order.
			AddHandler document.MailMerge.FieldMerging, Sub(sender, e)
				If e.RangeName = "Order" AndAlso e.FieldName = "Subtotal" Then
					e.Inline = New Run(e.Document, CDbl(dataSet.Tables("Orders").Rows(e.RecordNumber - 1).GetChildRows("OrderDetails").Sum(Function(item) CDbl(item("TotalPrice")))).ToString("$#,##0.00", CultureInfo.InvariantCulture))
					e.Cancel = False
				End If
			End Sub

			' Execute the Mail Merge.
			' Note: As the name of the region in the template (Order) is different from the name of the table (Orders), we explicitly specify the name of the region.
			document.MailMerge.Execute(orders, "Order")

			Dim resultPath As String = "Orders.docx"

			' Save the output to file.
			document.Save(resultPath)

			' Open the result for demonstration purposes.
			System.Diagnostics.Process.Start(New System.Diagnostics.ProcessStartInfo(resultPath) With {.UseShellExecute = True})
		End Sub

		''' <summary>
		''' Utility function that creates a connection, executes the sql-query and 
		''' return the result in a DataTable.
		''' </summary>
		Private Shared Function ExecuteSQL(ByVal sqlText As String) As DataTable
            ' Open the database connection.
            Dim str As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=..\Northwind.mdb"
            Dim conn As New OleDbConnection(str)
			conn.Open()

			' Create and execute a command.
			Dim cmd As New OleDbCommand(sqlText, conn)
			Dim da As New OleDbDataAdapter(cmd)
			Dim table As New DataTable()
			da.Fill(table)

			' Close the database.
			conn.Close()

			Return table
		End Function
	End Class
End Namespace

Скачать


Если вам нужен пример кода или у вас есть вопрос: напишите нам по адресу [email protected] или спросите в онлайн-чате (правый нижний угол этой страницы) или используйте форму ниже:



Вопросы и предложения всегда приветствуются!

Мы разрабатываем компоненты .Net с 2002 года. Мы знаем форматы PDF, DOCX, RTF, HTML, XLSX и Images. Если вам нужна помощь в создании, изменении или преобразовании документов в различных форматах, мы можем вам помочь. Мы напишем для вас любой пример кода абсолютно бесплатно.