C# Windows应用程序中如何在单页打印多张库存计数卡片
实现.NET单页多库存卡片打印方案
核心思路是在PrintPageEventHandler中维护当前打印的物品索引,通过计算行列布局在单页内绘制多张卡片,每次触发事件时完成一页内容的绘制,直到所有数据打印完毕。以下是完整的示例方案:
1. 数据模型定义
先对应数据库字段定义库存物品模型类:
public class InventoryItem { public string ItemCode { get; set; } public string Location { get; set; } public int Quantity { get; set; } // 可按需添加其他打印字段 }
2. 窗体与打印逻辑实现
以WinForms为例,包含PrintPreviewControl的完整窗体代码:
using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; public partial class InventoryPrintForm : Form { private PrintDocument _printDocument; private List<InventoryItem> _inventoryItems; private int _currentItemIndex = 0; // 跟踪当前打印的物品位置 // 打印配置参数,可根据需求调整 private readonly int _cardsPerPage = 10; private readonly int _columns = 2; private readonly int _rows = 5; private readonly int _cardWidth = 300; // 单位:百分之一英寸 private readonly int _cardHeight = 150; private readonly int _marginLeft = 50; private readonly int _marginTop = 50; private readonly int _cardSpacing = 20; public InventoryPrintForm() { InitializeComponent(); InitPrintComponents(); LoadSampleData(); // 替换为数据库查询逻辑 } private void InitPrintComponents() { _printDocument = new PrintDocument(); _printDocument.PrintPage += PrintDocument_PrintPage; // 配置预览控件 printPreviewControl1.Document = _printDocument; printPreviewControl1.Zoom = 0.5; } private void LoadSampleData() { _inventoryItems = new List<InventoryItem>(); // 模拟95条数据,对应你的需求场景 for (int i = 1; i <= 95; i++) { _inventoryItems.Add(new InventoryItem { ItemCode = $"ITEM-{i:D3}", Location = $"LOC-{i % 10 + 1}", Quantity = new Random().Next(1, 100) }); } } private void PrintDocument_PrintPage(object sender, PrintPageEventArgs e) { int printedCount = 0; Graphics g = e.Graphics; // 逐行逐列绘制卡片 for (int row = 0; row < _rows; row++) { for (int col = 0; col < _columns; col++) { if (_currentItemIndex >= _inventoryItems.Count) break; // 计算当前卡片的坐标 int x = _marginLeft + col * (_cardWidth + _cardSpacing); int y = _marginTop + row * (_cardHeight + _cardSpacing); // 绘制卡片边框 g.DrawRectangle(Pens.Black, x, y, _cardWidth, _cardHeight); // 填充卡片内容 InventoryItem item = _inventoryItems[_currentItemIndex]; float textY = y + 20; g.DrawString($"Item: {item.ItemCode}", new Font("Arial", 12, FontStyle.Bold), Brushes.Black, x + 15, textY); textY += 25; g.DrawString($"Location: {item.Location}", new Font("Arial", 10), Brushes.Black, x + 15, textY); textY += 25; g.DrawString($"Quantity: {item.Quantity}", new Font("Arial", 10), Brushes.Black, x + 15, textY); _currentItemIndex++; printedCount++; if (printedCount >= _cardsPerPage) break; } if (printedCount >= _cardsPerPage) break; } // 判断是否需要继续打印下一页 e.HasMorePages = _currentItemIndex < _inventoryItems.Count; // 打印完成后重置索引,方便下次打印 if (!e.HasMorePages) _currentItemIndex = 0; } // 预览按钮点击事件(需在窗体添加Button控件) private void btnPreview_Click(object sender, EventArgs e) { _currentItemIndex = 0; printPreviewControl1.Refresh(); } }
关键细节说明
- 状态维护:用类级别的
_currentItemIndex跨PrintPage事件跟踪打印进度,确保多页打印时不会重复或遗漏数据。 - 布局计算:通过行列数、卡片尺寸和间距计算坐标,保证卡片在页面上均匀分布,可根据实际纸张大小调整参数。
- 单位说明:.NET打印类默认使用百分之一英寸作为单位,数值300对应实际3英寸宽度。
- 预览测试:
PrintPreviewControl直接在窗体中展示打印效果,避免纸张浪费。
你可以根据实际需求调整卡片尺寸、行列布局、文本样式等参数,替换LoadSampleData方法为数据库查询逻辑即可对接真实数据。
内容的提问来源于stack exchange,提问作者DeepH2O
相关产品推荐
相关产品推荐

