【第二十四篇】C#进行A4打印
public class TriplicatePrint { private const int HeadHeight = 14; private const string FontName = "黑体"; private readonly SolidBrush _drawBrush_Black = new SolidBrush(Color.Black); private static readonly Font TableFont = new Font(FontName, 8, FontStyle.Regular);//表格字体 private readonly int _yUnit = TableFont.Height * 2;//表格高度 public int TotalNum = 0;//当前要所要打印的记录行数,由计算得到 private int WordMaxNum = 35;//最长可输出的字数 private int twoRowNum = 0;//换行的行数 private bool flag = false;//有没有换行 private int TableFootHeight = 50;//脚注高度 private TriplicateMsg ticketMsg; private DataRow _dataRow; private DataTable _dataTable; private int _firstPrintRecordNumber;//第一页的记录数 private string _headText = string.Empty; private int _pBottom;//页面下边距 private int _pHeigh;//页面左边距 private int _pLeft;//页面左边距 private int _pTop;//页面上边距 private int _pWidth;//页宽 private int _pageRecordNumber;//总记录行数 private PrintDocument _printDocument; private int _printRecordComplete;//答应成功的条数 private int _printRecordNumber;//每页打印的记录条数 private int _printingPageNumber = 1;//当前打印页 //第一页打印的记录条数 //与列名无关的统计数据行的类目数(如,总计,小计......) private int _totalPage;//总页数 private int[] _xUnit;//列宽集合 /// <summary> /// 打印信息 /// </summary> private string TicketJson; public TriplicatePrint(string order) { TicketJson = order; } /// <summary> /// 执行打印 /// </summary> public void Print() { // 通过多线程操作打印 Thread thread = new Thread(PrintOrder); thread.IsBackground = true; thread.Start(); } /// <summary> /// 打印普通消费小票 /// </summary> private void PrintOrder() { Thread.Sleep(100); if (string.IsNullOrEmpty(Setting.TriplicatePrintName)) { LoggerHelper.Info("请先设置默认打印机!"); return; } if (Setting.Triplicate == 0) { LoggerHelper.Info("未开启三联单自动打印!"); return; } if (Setting.TriplicateTicketCount < 1) { LoggerHelper.Info("打印份数小于1!"); return; } _dataTable = new DataTable(); _dataTable.Columns.Add("名称", System.Type.GetType("System.String")); _dataTable.Columns.Add("规格", System.Type.GetType("System.String")); _dataTable.Columns.Add("单位", System.Type.GetType("System.String")); _dataTable.Columns.Add("折后价", System.Type.GetType("System.String")); _dataTable.Columns.Add("数量", System.Type.GetType("System.String")); _dataTable.Columns.Add("金额", System.Type.GetType("System.String")); ticketMsg = JsonConvert.DeserializeObject<TriplicateMsg>(TicketJson); foreach (var item in ticketMsg.detaillist) { DataRow dr = _dataTable.NewRow(); dr["名称"] = item.GoodsName; dr["规格"] = item.SpecsValue; dr["单位"] = item.Unit; dr["折后价"] = item.DiscountMoney; dr["数量"] = item.Number; dr["金额"] = item.TotalMoney; _dataTable.Rows.Add(dr); } if (ticketMsg.template.header != null) { foreach (var item in ticketMsg.template.header) { _headText += item.value + "|"; } } _headText = _headText.TrimEnd('|'); bool Landscape = false; if (Setting.Landscape == 1) { Landscape = true; } _printDocument = new PrintDocument(); _printDocument.PrinterSettings.PrinterName = Setting.TriplicatePrintName; _printDocument.DefaultPageSettings.PaperSize = new PaperSize("A4", 826, 1129); _printDocument.DefaultPageSettings.Landscape = Landscape; //设置打印横向还是纵向 (True为横向,False为竖向) _pTop = _printDocument.DefaultPageSettings.Margins.Top / 3;//页面上边距 _pBottom = _printDocument.DefaultPageSettings.Margins.Bottom / 3;//页面下边距 _pWidth = _printDocument.DefaultPageSettings.Bounds.Width;//页面宽度 _pHeigh = _printDocument.DefaultPageSettings.Bounds.Height;//页面高度 _xUnit = new int[_dataTable.Columns.Count];//初始化有多少个列(存列宽进去) _printRecordNumber = Convert.ToInt32((_pHeigh - _pTop - _pBottom - _yUnit - TableFootHeight) / _yUnit);//一页打印的行数 _firstPrintRecordNumber = Convert.ToInt32((_pHeigh - _pTop - _pBottom - HeadHeight - _yUnit - TableFootHeight) / _yUnit) - 4;//第一页打印的行数 #region 计算打印总页数 foreach (DataRow dr in _dataTable.Rows) { for (int i = 0; i < _dataTable.Columns.Count; i++) { if (dr[i].ToString().Length > WordMaxNum) { twoRowNum += 1; break; } } } if (_dataTable.Rows.Count + twoRowNum + 1 > _printRecordNumber) { if ((_dataTable.Rows.Count + twoRowNum + 1 - _firstPrintRecordNumber) % _printRecordNumber == 0) { _totalPage = (_dataTable.Rows.Count + twoRowNum + 1 - _firstPrintRecordNumber) / _printRecordNumber; } else { decimal a = _dataTable.Rows.Count + twoRowNum + 1 - _firstPrintRecordNumber; decimal page = a / _printRecordNumber + 1; _totalPage = Convert.ToInt32(Math.Ceiling(page)); } } else { if (_dataTable.Rows.Count + 1 + twoRowNum < _firstPrintRecordNumber) { _totalPage = 1; } else { _totalPage = 2; } } #endregion _printDocument.PrintPage += PrintDocumentPrintPage; _printDocument.DocumentName = _headText; try { for (int i = 0; i < Setting.TriplicateTicketCount; i++) { _printDocument.Print(); } } catch { } } /// <summary> /// 打印当前页 /// </summary> private void PrintDocumentPrintPage(object sende, PrintPageEventArgs @event) { int tableWith = 0; string columnText; var font = new StringFormat { Alignment = StringAlignment.Center }; var pen = new Pen(Brushes.Black, 1);//打印表格线格式 #region 设置列宽 foreach (DataRow dr in _dataTable.Rows) { for (int i = 0; i < _dataTable.Columns.Count; i++) { int colwidth = Convert.ToInt32(@event.Graphics.MeasureString(dr[i].ToString().Trim(), TableFont).Width) + 10; if (colwidth > _xUnit[i]) { if (i == _dataTable.Columns.Count - 2) { _xUnit[i] = colwidth + 40; } else if (i == _dataTable.Columns.Count - 1) { _xUnit[i] = colwidth + 44; } else { _xUnit[i] = colwidth; } } } } int sumUnit = 0; flag = false;//是否超过页面总长 foreach (int item in _xUnit) { sumUnit += item; if (sumUnit >= _pWidth - 40) { flag = true; break; } } if (sumUnit < _pWidth / 2) { _xUnit = new int[_dataTable.Columns.Count]; _xUnit[0] = 200; _xUnit[1] = 200; _xUnit[2] = 48; _xUnit[3] = 34; _xUnit[4] = 60; _xUnit[5] = 90; } if (flag) { _xUnit = new int[_dataTable.Columns.Count]; _xUnit[0] = 400; _xUnit[1] = 400; _xUnit[2] = 48; _xUnit[3] = 34; _xUnit[4] = 80; _xUnit[5] = 100; } if (_printingPageNumber == 1) { for (int cols = 0; cols <= _dataTable.Columns.Count - 1; cols++) { columnText = _dataTable.Columns[cols].ColumnName.Trim(); int colwidth = Convert.ToInt32(@event.Graphics.MeasureString(columnText, TableFont).Width) + 10; if (colwidth > _xUnit[cols]) { _xUnit[cols] = colwidth; } } } for (int i = 0; i < _xUnit.Length; i++) { tableWith += _xUnit[i]; } #endregion _pLeft = (@event.PageBounds.Width - tableWith) / 2; int x = _pLeft; int y = _pTop; int stringY = _pTop + (_yUnit - TableFont.Height) / 2; int rowOfTop = _pTop; //第一页 if (_printingPageNumber == 1) { var subtitleHeight = 20; if (!string.IsNullOrEmpty(_headText)) { //打印表头 var arr = _headText.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries); if (arr.Length > 1) { @event.Graphics.DrawString(arr[0], new Font(FontName, HeadHeight, FontStyle.Regular), _drawBrush_Black, new Point(@event.PageBounds.Width / 2, _pTop), font); } //副标题 for (int i = 1; i < arr.Length; i++) { @event.Graphics.DrawString(arr[i], new Font(FontName, 12, FontStyle.Regular), _drawBrush_Black, new Point(@event.PageBounds.Width / 2, _pTop + HeadHeight + 20), font); subtitleHeight += new Font(FontName, 10, FontStyle.Regular).Height; } subtitleHeight += 14;//标题和表头之间的间距 } var tbTopHeight = 20;//表头高度 var tbTopLeft = _pLeft + 10; #region Top表头内容 if (ticketMsg.template.top != null) { var topNum = ticketMsg.template.top.Count; if (topNum > 0) {//居中 = 空间长度 - 自己长度的一半 @event.Graphics.DrawString(ticketMsg.template.top[0].name + ":" + ticketMsg.template.top[0].value, TableFont, _drawBrush_Black, new Point(tbTopLeft, _pTop + HeadHeight + subtitleHeight)); } if (topNum > 1) { tbTopLeft += Convert.ToInt32(@event.Graphics.MeasureString(ticketMsg.template.top[0].name + ":" + ticketMsg.template.top[0].value, TableFont).Width) + 14; @event.Graphics.DrawString(ticketMsg.template.top[1].name + ":" + ticketMsg.template.top[1].value, TableFont, _drawBrush_Black, new Point(@event.PageBounds.Width / 2 - Convert.ToInt32(@event.Graphics.MeasureString(ticketMsg.template.top[1].name + ":" + ticketMsg.template.top[1].value, TableFont).Width) / 2, _pTop + HeadHeight + subtitleHeight)); } if (topNum > 2 && topNum == 6) { tbTopLeft += Convert.ToInt32(@event.Graphics.MeasureString(ticketMsg.template.top[1].name + ":" + ticketMsg.template.top[1].value, TableFont).Width) + 14; @event.Graphics.DrawString(ticketMsg.template.top[2].name + ":" + ticketMsg.template.top[2].value, TableFont, _drawBrush_Black, new Point(_pLeft + tableWith - Convert.ToInt32(@event.Graphics.MeasureString(ticketMsg.template.top[2].name + ":" + ticketMsg.template.top[2].value, TableFont).Width) - 110, _pTop + HeadHeight + subtitleHeight)); } else { tbTopLeft += Convert.ToInt32(@event.Graphics.MeasureString(ticketMsg.template.top[1].name + ":" + ticketMsg.template.top[1].value, TableFont).Width) + 14; @event.Graphics.DrawString(ticketMsg.template.top[2].name + ":" + ticketMsg.template.top[2].value, TableFont, _drawBrush_Black, new Point(_pLeft + tableWith - Convert.ToInt32(@event.Graphics.MeasureString(ticketMsg.template.top[2].name + ":" + ticketMsg.template.top[2].value, TableFont).Width), _pTop + HeadHeight + subtitleHeight)); } if (topNum > 3) { subtitleHeight += new Font(FontName, 10, FontStyle.Regular).Height + 10; tbTopLeft = _pLeft + 10; @event.Graphics.DrawString(ticketMsg.template.top[3].name + ":" + ticketMsg.template.top[3].value, TableFont, _drawBrush_Black, new Point(tbTopLeft, _pTop + HeadHeight + subtitleHeight)); } if (topNum > 4) { tbTopLeft += Convert.ToInt32(@event.Graphics.MeasureString(ticketMsg.template.top[0].name + ":" + ticketMsg.template.top[0].value, TableFont).Width) + 14; @event.Graphics.DrawString(ticketMsg.template.top[4].name + ":" + ticketMsg.template.top[4].value, TableFont, _drawBrush_Black, new Point(@event.PageBounds.Width / 2 - Convert.ToInt32(@event.Graphics.MeasureString(ticketMsg.template.top[1].name + ":" + ticketMsg.template.top[1].value, TableFont).Width) / 2, (_pTop + HeadHeight + subtitleHeight))); } if (topNum > 5) { tbTopLeft += Convert.ToInt32(@event.Graphics.MeasureString(ticketMsg.template.top[1].name + ":" + ticketMsg.template.top[1].value, TableFont).Width) + 14; @event.Graphics.DrawString(ticketMsg.template.top[5].name + ":" + ticketMsg.template.top[5].value, TableFont, _drawBrush_Black, new Point(_pLeft + tableWith - Convert.ToInt32(@event.Graphics.MeasureString(ticketMsg.template.top[2].name + ":" + ticketMsg.template.top[2].value, TableFont).Width) - 110, (_pTop + HeadHeight + subtitleHeight))); } tbTopHeight += 14;//表头和表格中间的间隔 } #endregion //设置为第一页时行数 if (_dataTable.Rows.Count < _firstPrintRecordNumber) { _pageRecordNumber = _dataTable.Rows.Count; } else { _pageRecordNumber = _firstPrintRecordNumber; } subtitleHeight += 10; rowOfTop = y = (_pTop + HeadHeight + subtitleHeight + tbTopHeight); stringY = (_pTop + HeadHeight + subtitleHeight + tbTopHeight + (_yUnit - TableFont.Height) / 2); } else { if (flag) { _printRecordNumber = 12; } //计算,余下的记录条数是否还可以在一页打印,不满一页时为假 if (_dataTable.Rows.Count - _printRecordComplete >= _printRecordNumber) { _pageRecordNumber = _printRecordNumber; } else { _pageRecordNumber = _dataTable.Rows.Count - _printRecordComplete; } } #region 打印列名 if (_printingPageNumber == 1 || _pageRecordNumber > TotalNum) //最后一页只打印统计行时不打印列名 { //得到datatable的所有列名 for (int cols = 0; cols <= _dataTable.Columns.Count - 1; cols++) { columnText = _dataTable.Columns[cols].ColumnName.Trim(); int colwidth = Convert.ToInt32(@event.Graphics.MeasureString(columnText, TableFont).Width); @event.Graphics.DrawString(columnText, TableFont, _drawBrush_Black, x + (_xUnit[cols] / 2 - Convert.ToInt32(@event.Graphics.MeasureString(columnText, TableFont).Width) / 2), stringY);//值,字体,颜色,x坐标,y坐标 x += _xUnit[cols]; } } #endregion if (_printingPageNumber == 1) {//第一页表格顶部需要打印一条双横线 @event.Graphics.DrawLine(pen, _pLeft, rowOfTop - 4, x, rowOfTop - 4);//表格顶部的线 @event.Graphics.DrawLine(pen, _pLeft, rowOfTop - 5, x, rowOfTop - 5);//表格顶部的线 } @event.Graphics.DrawLine(pen, _pLeft, rowOfTop, x, rowOfTop);//表格顶横线 if (_printRecordComplete < _dataTable.Rows.Count) { stringY += _yUnit; y += _yUnit; @event.Graphics.DrawLine(pen, _pLeft, y, x, y);//列名下面的横线 } #region 打印单元格 数据 和 表格横线 //当前页面已经打印的记录行数 int printingLine = 0; if (_printingPageNumber == 1 && flag && _dataTable.Rows.Count >= _pageRecordNumber) { _pageRecordNumber = 9; } while (printingLine < _pageRecordNumber) { if (_printRecordComplete == _dataTable.Rows.Count) { break; } x = _pLeft; //确定要当前要打印的记录的行号 _dataRow = _dataTable.Rows[_printRecordComplete]; bool newline = true; for (int cols = 0; cols <= _dataTable.Columns.Count - 1; cols++) { if (flag) {//需要换行 if (_dataRow[cols].ToString().Length > WordMaxNum) { string[] colum = new string[2] { _dataRow[cols].ToString().Substring(0, WordMaxNum), _dataRow[cols].ToString().Substring(WordMaxNum) }; @event.Graphics.DrawString(colum[0], TableFont, _drawBrush_Black, x, stringY);//值,字体,颜色,x坐标,y坐标 @event.Graphics.DrawString(colum[1], TableFont, _drawBrush_Black, x, stringY + _yUnit);//值,字体,颜色,x坐标,y坐标 x += _xUnit[cols]; } else { if (_dataRow[0].ToString().Length < WordMaxNum && _dataRow[1].ToString().Length < WordMaxNum) {//不需要打空行 newline = false; if (cols != 0 && cols != 1) { @event.Graphics.DrawString(_dataRow[cols].ToString().Trim(), TableFont, _drawBrush_Black, x + (_xUnit[cols] / 2 - Convert.ToInt32(@event.Graphics.MeasureString(_dataRow[cols].ToString().Trim(), TableFont).Width) / 2), stringY); } else { @event.Graphics.DrawString(_dataRow[cols].ToString().Trim(), TableFont, _drawBrush_Black, x, stringY); } } else { if (cols != 0 && cols != 1) { @event.Graphics.DrawString(_dataRow[cols].ToString().Trim(), TableFont, _drawBrush_Black, x + (_xUnit[cols] / 2 - Convert.ToInt32(@event.Graphics.MeasureString(_dataRow[cols].ToString().Trim(), TableFont).Width) / 2), stringY); } else { @event.Graphics.DrawString(_dataRow[cols].ToString().Trim(), TableFont, _drawBrush_Black, x, stringY); } @event.Graphics.DrawString("", TableFont, _drawBrush_Black, x, stringY + _yUnit); } x += _xUnit[cols]; } } else { @event.Graphics.DrawString(_dataRow[cols].ToString().Trim(), TableFont, _drawBrush_Black, x + (_xUnit[cols] / 2 - Convert.ToInt32(@event.Graphics.MeasureString(_dataRow[cols].ToString().Trim(), TableFont).Width) / 2), stringY); x += _xUnit[cols]; } } if (flag && newline) { stringY += _yUnit * 2; y += _yUnit * 2; } else { stringY += _yUnit; y += _yUnit; } @event.Graphics.DrawLine(pen, _pLeft, y, x, y); printingLine += 1; _printRecordComplete += 1; if (_printRecordComplete > _dataTable.Rows.Count) { @event.HasMorePages = false; _printRecordComplete = 0; } } #endregion #region 打印单元格竖线 if (_printRecordComplete <= _dataTable.Rows.Count) { @event.Graphics.DrawLine(pen, _pLeft, rowOfTop, _pLeft, y); x = _pLeft; for (int cols = 0; cols < _dataTable.Columns.Count; cols++) { x += _xUnit[cols]; @event.Graphics.DrawLine(pen, x, rowOfTop, x, y); } } #endregion #region 合计和脚注 if (_printingPageNumber == _totalPage) {//最后加一个合计 if (_printRecordComplete == _dataTable.Rows.Count && _printingPageNumber != 1) { @event.Graphics.DrawLine(pen, _pLeft, _pTop, x, _pTop); } @event.Graphics.DrawString("合计(大写):" + ticketMsg.combined.CombinedStr, TableFont, _drawBrush_Black, _pLeft + 10, stringY); stringY += _yUnit; y += _yUnit; @event.Graphics.DrawLine(pen, _pLeft, y, x, y); @event.Graphics.DrawLine(pen, _pLeft + _xUnit[0] + _xUnit[1] + _xUnit[2] + _xUnit[3], rowOfTop, _pLeft + _xUnit[0] + _xUnit[1] + _xUnit[2] + _xUnit[3], y); @event.Graphics.DrawString(ticketMsg.combined.Number.ToString("f2"), TableFont, _drawBrush_Black, _pLeft + _xUnit[0] + _xUnit[1] + _xUnit[2] + _xUnit[3] + (_xUnit[4] / 2 - Convert.ToInt32(@event.Graphics.MeasureString(ticketMsg.combined.Number.ToString("f2").Trim(), TableFont).Width) / 2), stringY - _yUnit); @event.Graphics.DrawLine(pen, _pLeft + _xUnit[0] + _xUnit[1] + _xUnit[2] + _xUnit[3] + _xUnit[4], rowOfTop, _pLeft + _xUnit[0] + _xUnit[1] + _xUnit[2] + _xUnit[3] + _xUnit[4], y); @event.Graphics.DrawString(ticketMsg.combined.SumMoney.ToString("f2"), TableFont, _drawBrush_Black, _pLeft + _xUnit[0] + _xUnit[1] + _xUnit[2] + _xUnit[3] + _xUnit[4] + (_xUnit[5] / 2 - Convert.ToInt32(@event.Graphics.MeasureString(ticketMsg.combined.SumMoney.ToString("f2").Trim(), TableFont).Width) / 2), stringY - _yUnit); @event.Graphics.DrawLine(pen, _pLeft, rowOfTop, _pLeft, y); @event.Graphics.DrawLine(pen, x, rowOfTop, x, y); y += 20; var tbTopLeft = 0; #region 打印底部 if (ticketMsg.template.bottom != null) { if (ticketMsg.template.bottom.Count > 0) { List<TicketField> tfList = new List<TicketField>(); foreach (var item in ticketMsg.template.bottom) { if (item.key != "Address" && item.key != "Remark") { tfList.Add(item); } } if (tfList.Count > 0) { var left = _pLeft + 10; @event.Graphics.DrawString(tfList[0].name + ":" + tfList[0].value, TableFont, _drawBrush_Black, new Point(left, y)); } if (tfList.Count > 1) { var left = @event.PageBounds.Width / 2 - Convert.ToInt32(@event.Graphics.MeasureString(tfList[1].name + ":" + tfList[1].value, TableFont).Width) / 2; tbTopLeft += Convert.ToInt32(@event.Graphics.MeasureString(tfList[0].name + ":" + tfList[0].value, TableFont).Width) + 14; @event.Graphics.DrawString(tfList[1].name + ":" + tfList[1].value, TableFont, _drawBrush_Black, new Point(left, y)); } if (tfList.Count > 2) { var left = _pLeft + tableWith - Convert.ToInt32(@event.Graphics.MeasureString(tfList[2].name + ":" + tfList[2].value, TableFont).Width); if (tfList[2].key == "GKQM") { left -= 80; } tbTopLeft += Convert.ToInt32(@event.Graphics.MeasureString(tfList[1].name + ":" + tfList[1].value, TableFont).Width) + 14; @event.Graphics.DrawString(tfList[2].name + ":" + tfList[2].value, TableFont, _drawBrush_Black, new Point(left, y)); } y += 20; foreach (var item in ticketMsg.template.bottom) { switch (item.key) { case "Address": @event.Graphics.DrawString("地址:" + item.value, TableFont, _drawBrush_Black, new Point(_pLeft + 10, y)); y += 20; break; case "Remark": @event.Graphics.DrawString("备注:" + item.value, TableFont, _drawBrush_Black, new Point(_pLeft + 10, y)); y += 20; break; } } } } #endregion #region 打印脚部 if (ticketMsg.template.footer != null) { if (ticketMsg.template.footer.enable == 1) { @event.Graphics.DrawString(ticketMsg.template.footer.value, TableFont, _drawBrush_Black, new Point(_pLeft + 10, y)); } } #endregion } #endregion _printingPageNumber += 1; if (_printingPageNumber > _totalPage) { @event.HasMorePages = false; _printingPageNumber = 1; _printRecordComplete = 0; } else { @event.HasMorePages = true; } } }
public void TriplicatePrint(string ticketMsg) { new TriplicatePrint(ticketMsg).Print(); }
---------------------------------------------------------------------------------------------------------
转载请记得说明作者和出处哦-.-
作者:KingDuDu
原文出处:https://www.cnblogs.com/kingdudu/articles/12673528.html
---------------------------------------------------------------------------------------------------------