VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > c#编程 >
  • C#的打印功能——订单报表生成与打印

第二部分:桌面应用开发
10. 打印功能——订单报表生成与打印
实例介绍
之前做电商后台时,财务每月要打印几百份订单报表,每次都得导出Excel再调整列宽、加页眉页脚,折腾半天还容易格式错乱。后来用WPF的FlowDocument做了个报表生成工具:直接把订单数据排成规范表格,带公司logo、页眉(订单报表+日期)、页脚(页码),点一下就能预览或打印,财务说效率至少提升了三倍。这节就带你给电商后台加订单报表打印功能,彻底解vb.net教程C#教程python教程SQL教程access 2010教程决手动排版的痛点。
需求分析
订单报表打印要解决“高效生成规范报表并打印”的问题,具体需求如下:
1.报表内容:包含订单号、客户名称、下单日期、订单金额、支付状态等核心字段;
2.样式规范:带公司logo、页眉(报表标题+打印日期)、页脚(页码/总页数)、表格边框、交替行颜色;
3.交互功能:打印预览(调整参数)、直接打印、导出PDF(用于存档);
4.批量处理:支持选择多个订单批量打印,自动分页;
5.性能优化:大数据量(比如1000+订单)时自动分页,避免内存溢出;
6.参数定制:允许设置纸张大小(A4/A5)、方向(纵向/横向)、边距;
7.错误处理:打印失败时提示(比如打印机未连接),无数据时禁止打印。
代码实现
前置条件:.NET 6+、WPF;延续电商后台场景,定义Order模型和OrderViewModel;需安装NuGet包 iTextSharp(用于PDF导出,可选)或使用WPF自带的XPS转PDF。
场景1:基础打印(直接打印订单列表)
用FlowDocument生成订单报表,通过PrintDialog直接打印。
步骤1:定义Order模型和ViewModel
csharp

	// Order模型:订单数据
	public class Order
	{
	public string OrderId { get; set; } // 订单号
	public string CustomerName { get; set; } // 客户名称
	public DateTime OrderDate { get; set; } // 下单日期
	public decimal TotalAmount { get; set; } // 订单金额
	public string PaymentStatus { get; set; } // 支付状态(已支付/待支付)
	}
	
	// OrderViewModel:订单数据逻辑
	public partial class OrderViewModel : ObservableObject
	{
	[ObservableProperty]
	private ObservableCollection<Order> _orderList = new();
	
	public OrderViewModel()
	{
	// 模拟订单数据
	OrderList.Add(new Order { OrderId = "ORD20240001", CustomerName = "张三", OrderDate = DateTime.Now.AddDays(-5), TotalAmount = 199.99m, PaymentStatus = "已支付" });
	OrderList.Add(new Order { OrderId = "ORD20240002", CustomerName = "李四", OrderDate = DateTime.Now.AddDays(-3), TotalAmount = 299.50m, PaymentStatus = "已支付" });
	OrderList.Add(new Order { OrderId = "ORD20240003", CustomerName = "王五", OrderDate = DateTime.Now.AddDays(-1), TotalAmount = 450.00m, PaymentStatus = "待支付" });
	}
	}

步骤2:MainWindow.xaml添加打印按钮
xml
<Button Content="打印订单报表" Click="PrintOrderReport_Click" Margin="10" Style="{StaticResource PrimaryButtonStyle}"/>
步骤3:MainWindow.xaml.cs实现打印逻辑
csharp

	using System.Windows;
	using System.Windows.Controls;
	using System.Windows.Documents;
	using System.Windows.Media;
	
	private void PrintOrderReport_Click(object sender, RoutedEventArgs e)
	{
	// 1. 创建打印对话框
	var printDialog = new PrintDialog();
	
	// 2. 设置默认打印参数(A4纸,纵向)
	printDialog.PrintTicket.PageMediaSize = new PageMediaSize(PageMediaSizeName.A4);
	printDialog.PrintTicket.PageOrientation = PageOrientation.Portrait;
	
	// 3. 显示打印对话框(用户确认后执行打印)
	if (printDialog.ShowDialog() == true)
	{
	// 4. 生成订单报表(FlowDocument)
	var report = CreateOrderReport();
	
	// 5. 打印报表
	printDialog.PrintDocument(((IDocumentPaginatorSource)report).DocumentPaginator, "订单报表打印");
	}
	}
	
	// 生成订单报表(FlowDocument)
	private FlowDocument CreateOrderReport()
	{
	var viewModel = DataContext as OrderViewModel;
	if (viewModel == null || viewModel.OrderList.Count == 0)
	{
	MessageBox.Show("无订单数据可打印!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
	return new FlowDocument();
	}
	
	// 1. 初始化FlowDocument(A4纸,边距2cm)
	var doc = new FlowDocument
	{
	PageWidth = 816, // A4宽度(1英寸=96像素,21cm≈816像素)
	PageHeight = 1056, // A4高度(29.7cm≈1056像素)
	PagePadding = new Thickness(72), // 边距1英寸(72像素)
	FontFamily = new FontFamily("微软雅黑"),
	FontSize = 12
	};
	
	// 2. 添加页眉(报表标题+打印日期)
	var header = new Paragraph(new Run($"订单报表 - 打印日期:{DateTime.Now:yyyy-MM-dd HH:mm}"))
	{
	FontSize = 16,
	FontWeight = FontWeights.Bold,
	HorizontalAlignment = HorizontalAlignment.Center,
	Margin = new Thickness(0, 0, 0, 20)
	};
	doc.Blocks.Add(header);
	
	// 3. 添加订单表格
	var orderTable = new Table();
	orderTable.CellSpacing = 0; // 单元格间距为0
	orderTable.BorderThickness = new Thickness(1);
	orderTable.BorderBrush = Brushes.Black;
	
	// 3.1 定义列(订单号、客户、日期、金额、状态)
	orderTable.Columns.Add(new TableColumn { Width = new GridLength(150) });
	orderTable.Columns.Add(new TableColumn { Width = new GridLength(120) });
	orderTable.Columns.Add(new TableColumn { Width = new GridLength(150) });
	orderTable.Columns.Add(new TableColumn { Width = new GridLength(120) });
	orderTable.Columns.Add(new TableColumn { Width = new GridLength(100) });
	
	// 3.2 添加表头行
	var headerRow = new TableRow();
	headerRow.Background = Brushes.LightGray;
	headerRow.FontWeight = FontWeights.Bold;
	
	// 表头单元格
	headerRow.Cells.Add(CreateTableCell("订单号"));
	headerRow.Cells.Add(CreateTableCell("客户名称"));
	headerRow.Cells.Add(CreateTableCell("下单日期"));
	headerRow.Cells.Add(CreateTableCell("订单金额(元)"));
	headerRow.Cells.Add(CreateTableCell("支付状态"));
	
	// 添加表头到表格
	var headerGroup = new TableRowGroup();
	headerGroup.RowGroups.Add(new TableRowGroup());
	headerGroup.Rows.Add(headerRow);
	orderTable.RowGroups.Add(headerGroup);
	
	// 3.3 添加订单数据行
	var dataGroup = new TableRowGroup();
	int rowIndex = 0;
	foreach (var order in viewModel.OrderList)
	{
	var row = new TableRow();
	// 交替行颜色(偶数行浅灰)
	if (rowIndex % 2 == 1)
	row.Background = new SolidColorBrush(Color.FromArgb(20, 0, 0, 0));
	
	// 数据单元格
	row.Cells.Add(CreateTableCell(order.OrderId));
	row.Cells.Add(CreateTableCell(order.CustomerName));
	row.Cells.Add(CreateTableCell(order.OrderDate.ToString("yyyy-MM-dd")));
	row.Cells.Add(CreateTableCell(order.TotalAmount.ToString("N2")));
	row.Cells.Add(CreateTableCell(order.PaymentStatus));
	
	dataGroup.Rows.Add(row);
	rowIndex++;
	}
	orderTable.RowGroups.Add(dataGroup);
	
	// 4. 添加表格到文档
	doc.Blocks.Add(orderTable);
	
	return doc;
	}
	
	// 辅助方法:创建表格单元格
	private TableCell CreateTableCell(string text)
	{
	return new TableCell(new Paragraph(new Run(text))
	{
	Padding = new Thickness(5),
	Margin = new Thickness(0)
	})
	{
	BorderThickness = new Thickness(0.5),
	BorderBrush = Brushes.Black
	};
	}

场景2:打印预览
添加打印预览功能,用户可在打印前查看报表样式和分页。
步骤1:MainWindow.xaml添加预览按钮
xml
<Button Content="打印预览" Click="PrintPreview_Click" Margin="10" Style="{StaticResource SecondaryButtonStyle}"/>
步骤2:MainWindow.xaml.cs实现预览逻辑
csharp

	private void PrintPreview_Click(object sender, RoutedEventArgs e)
	{
	var report = CreateOrderReport();
	if (report.Blocks.Count == 0) return;
	
	// 1. 创建打印预览窗口
	var previewWindow = new Window
	{
	Title = "订单报表预览",
	Width = 900,
	Height = 1000,
	WindowStartupLocation = WindowStartupLocation.CenterOwner,
	Owner = this
	};
	
	// 2. 添加DocumentViewer(显示FlowDocument)
	var viewer = new DocumentViewer
	{
	Document = report
	};
	previewWindow.Content = viewer;
	
	// 3. 显示预览窗口
	previewWindow.ShowDialog();
	}

场景3:导出PDF报表
将订单报表导出为PDF文件(用于存档或邮件发送)。
步骤1:安装NuGet包
安装 iTextSharp(版本5.5.13.3)或 PdfSharp(二选一,这里用iTextSharp)。
步骤2:添加导出PDF按钮
xml
<Button Content="导出PDF报表" Click="ExportPdf_Click" Margin="10" Style="{StaticResource TertiaryButtonStyle}"/>
步骤3:实现导出逻辑
csharp

	using iTextSharp.text;
	using iTextSharp.text.pdf;
	using System.IO;
	using System.Windows;
	
	private void ExportPdf_Click(object sender, RoutedEventArgs e)
	{
	var viewModel = DataContext as OrderViewModel;
	if (viewModel == null || viewModel.OrderList.Count == 0)
	{
	MessageBox.Show("无订单数据可导出!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
	return;
	}
	
	// 1. 显示保存文件对话框
	var saveDialog = new SaveFileDialog
	{
	Filter = "PDF文件|*.pdf",
	FileName = $"订单报表_{DateTime.Now:yyyyMMdd}.pdf",
	InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
	};
	
	if (saveDialog.ShowDialog() == true)
	{
	// 2. 生成PDF文件
	using (var fs = new FileStream(saveDialog.FileName, FileMode.Create))
	{
	// 初始化PDF文档(A4)
	var document = new Document(PageSize.A4, 72, 72, 72, 72); // 边距1英寸
	PdfWriter.GetInstance(document, fs);
	document.Open();
	
	// 添加标题
	var titleFont = FontFactory.GetFont("微软雅黑", 16, Font.BOLD);
	var title = new Paragraph($"订单报表 - 导出日期:{DateTime.Now:yyyy-MM-dd HH:mm}", titleFont)
	{
	Alignment = Element.ALIGN_CENTER,
	SpacingAfter = 20
	};
	document.Add(title);
	
	// 添加表格
	var table = new PdfPTable(5); // 5列
	table.WidthPercentage = 100; // 占满页面宽度
	table.SetWidths(new float[] { 20, 15, 20, 15, 15 }); // 列宽比例
	
	// 表头样式
	var headerFont = FontFactory.GetFont("微软雅黑", 12, Font.BOLD);
	var headerCellStyle = new PdfPCell();
	headerCellStyle.BackgroundColor = BaseColor.LIGHT_GRAY;
	headerCellStyle.HorizontalAlignment = Element.ALIGN_CENTER;
	headerCellStyle.Padding = 5;
	
	// 添加表头
	table.AddCell(new PdfPCell(new Phrase("订单号", headerFont)) { BackgroundColor = BaseColor.LIGHT_GRAY, HorizontalAlignment = Element.ALIGN_CENTER, Padding =5 });
	table.AddCell(new PdfPCell(new Phrase("客户名称", headerFont)) { BackgroundColor = BaseColor.LIGHT_GRAY, HorizontalAlignment = Element.ALIGN_CENTER, Padding =5 });
	table.AddCell(new PdfPCell(new Phrase("下单日期", headerFont)) { BackgroundColor = BaseColor.LIGHT_GRAY, HorizontalAlignment = Element.ALIGN_CENTER, Padding =5 });
	table.AddCell(new PdfPCell(new Phrase("订单金额", headerFont)) { BackgroundColor = BaseColor.LIGHT_GRAY, HorizontalAlignment = Element.ALIGN_CENTER, Padding =5 });
	table.AddCell(new PdfPCell(new Phrase("支付状态", headerFont)) { BackgroundColor = BaseColor.LIGHT_GRAY, HorizontalAlignment = Element.ALIGN_CENTER, Padding =5 });
	
	// 添加数据行
	var dataFont = FontFactory.GetFont("微软雅黑", 10);
	int rowIndex =0;
	foreach (var order in viewModel.OrderList)
	{
	var cellStyle = new PdfPCell();
	cellStyle.Padding =5;
	cellStyle.HorizontalAlignment = Element.ALIGN_CENTER;
	
	// 交替行颜色
	if (rowIndex%2 ==1)
	cellStyle.BackgroundColor = new BaseColor(240,240,240);
	
	table.AddCell(new PdfPCell(new Phrase(order.OrderId, dataFont)) { Padding=5, HorizontalAlignment=Element.ALIGN_CENTER, BackgroundColor= rowIndex%2==1?new BaseColor(240,240,240):BaseColor.WHITE });
	table.AddCell(new PdfPCell(new Phrase(order.CustomerName, dataFont)) { Padding=5, HorizontalAlignment=Element.ALIGN_CENTER, BackgroundColor= rowIndex%2==1?new BaseColor(240,240,240):BaseColor.WHITE });
	table.AddCell(new PdfPCell(new Phrase(order.OrderDate.ToString("yyyy-MM-dd"), dataFont)) { Padding=5, HorizontalAlignment=Element.ALIGN_CENTER, BackgroundColor= rowIndex%2==1?new BaseColor(240,240,240):BaseColor.WHITE });
	table.AddCell(new PdfPCell(new Phrase(order.TotalAmount.ToString("N2"), dataFont)) { Padding=5, HorizontalAlignment=Element.ALIGN_CENTER, BackgroundColor= rowIndex%2==1?new BaseColor(240,240,240):BaseColor.WHITE });
	table.AddCell(new PdfPCell(new Phrase(order.PaymentStatus, dataFont)) { Padding=5, HorizontalAlignment=Element.ALIGN_CENTER, BackgroundColor= rowIndex%2==1?new BaseColor(240,240,240):BaseColor.WHITE });
	
	rowIndex++;
	}
	
	document.Add(table);
	document.Close();
	}
	
	MessageBox.Show($"PDF报表已导出到:
{saveDialog.FileName}", "导出成功", MessageBoxButton.OK, MessageBoxImage.Information);
	}
	}

逐行讲解
场景1:基础打印核心代码
1.PrintDialog初始化:创建PrintDialog实例,设置默认纸张大小(A4)和方向(纵向);
2.ShowDialog:显示打印对话框,用户选择打印机和参数后返回true;
3.FlowDocument创建:FlowDocument是WPF中用于流式排版的文档,支持自动分页、样式定制;
1.PageWidth/PageHeight:设置A4纸的像素大小(1英寸=96像素,A4=21cm×29.7cm≈816×1056像素);
2.PagePadding:设置页面边距(72像素=1英寸);
4.Table创建:Table用于展示表格数据,定义列宽、表头、数据行;
1.CellSpacing:单元格间距设为0,让边框连续;
2.交替行颜色:通过rowIndex%2判断,偶数行设浅灰色,提升可读性;
5.PrintDocument:将FlowDocument转为DocumentPaginator,传递给PrintDialog打印。
场景2:打印预览
1.DocumentViewer:WPF自带的文档预览控件,直接绑定FlowDocument即可显示;
2.预览窗口:创建独立窗口放置DocumentViewer,用户可缩放、翻页查看报表样式;
场景3:PDF导出(iTextSharp)
1.iTextSharp初始化:创建Document实例,设置A4纸和边距;
2.PdfWriter:将Document内容写入文件流;
3.PdfPTable:iTextSharp中的表格控件,设置列宽比例、表头样式、数据行;
4.交替行颜色:通过rowIndex判断,设置单元格背景色;
基础知识拓展

  1. FlowDocument vs FixedDocument
特性 FlowDocument FixedDocument
排版方式 流式排版(自适应窗口大小) 固定布局(内容位置固定,类似PDF)
分页 自动分页(根据页面大小) 手动分页(需显式添加PageContent)
适用场景 长文本、报表、文档(需自适应) 固定格式文档(如PDF、海报、证书)
打印支持 支持(需转为DocumentPaginator) 支持(天生分页)
编辑性 支持(可添加TextBox等交互控件) 不支持(静态内容)
  1. 打印参数定制
    纸张方向:printDialog.PrintTicket.PageOrientation = PageOrientation.Landscape(横向);
    自定义纸张大小:new PageMediaSize(PageMediaSizeName.Custom, width, height);
    边距设置:FlowDocument的PagePadding或PrintDialog的PrintTicket.PageMediaSize.Margin;
    打印机选择:printDialog.PrintQueue可指定默认打印机,或通过LocalPrintServer.GetPrintQueues()获取所有打印机列表。
  2. 批量打印优化
    异步打印:大数据量时用Task.Run(() => printDialog.PrintDocument(...))避免UI阻塞;
    分页加载:将订单数据分批次生成FlowDocument,每批次打印一页;
    打印队列管理:用PrintSystemJobInfo监控打印任务状态(成功/失败/取消)。
  3. PDF导出的其他方法
    WPF自带XPS转PDF:先将FlowDocument保存为XPS文件,再用第三方工具(如Ghostscript)转为PDF;
    PdfSharp:开源PDF库,支持直接生成PDF,语法更接近WPF;
    Syncfusion PDF:商业库,功能强大(支持表格、图片、页眉页脚),但需付费。
    总结
    订单报表打印的核心是报表生成和打印交互:
    1.报表生成:用FlowDocument实现灵活排版,支持表格、样式、分页;
    2.打印交互:PrintDialog负责用户选择打印机和参数,DocumentViewer实现预览;
    3.PDF导出:用iTextSharp或PdfSharp生成PDF文件,满足存档需求;
    4.性能优化:大数据量时分页、异步打印,避免UI阻塞。
    掌握这些技巧后,你可以轻松实现各种复杂报表的打印功能,从电商订单到财务报表,再到物流单据,都能高效处理!

本站原创,转载请注明出处:https://www.xin3721.com/ArticlecSharp/c49469.html


相关教程