1. 程式人生 > >winform使用PrintDocument控制元件列印

winform使用PrintDocument控制元件列印

程式碼,需要加入的控制元件:PrintDocument、PageSetupDialog、PrintDialog、PrintPreviewDialog、BackgroundWorker,控制元件的Document屬性要指定為PrintDocument控制元件的id。
匯入Excel用的是12.0的驅動,需要下載:http://download.microsoft.com/download/7/0/3/703ffbcb-dc0c-4e19-b0da-1463960fdcdb/AccessDatabaseEngine.exe 

using System;
using System.Collections.Generic;
using System.ComponentModel; using System.Data; using System.Data.OleDb; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Windows.Forms; namespace PrintLabels { public partial class MainForm : Form { /// <summary> /// 訊息佇列 /// Queue.Peek();//第一個元素; Queue.Dequeue();//移除第一個元素;Queue.Enqueue//新增到 Queue
<T> 的末尾 /// </summary> static Queue<Message> queuePrint = new Queue<Message>(); StringBuilder printResult = new StringBuilder();//列印結果 //int PrintCount = 0;//列印的標籤總數 string row1; string row2; string row3; string row4;
string row5; string row6; public MainForm() { InitializeComponent(); this.printDocument1.OriginAtMargins = true;//啟用頁邊距 this.pageSetupDialog1.EnableMetric = true; //以毫米為單位 dataGridView1.AutoGenerateColumns = false;//禁止自動建立列 } /// <summary> /// 匯入excel表格 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnImportExcel_Click(object sender, EventArgs e) { OpenFileDialog fd = new OpenFileDialog(); fd.Filter = "Excel(2007)檔案|*.xlsx|Excel(97-2003)檔案|*.xls|所有檔案|*.*"; fd.Title = "開啟資料夾"; string path = ""; //fd.InitialDirectory = "d:\\"; fd.FilterIndex = 1; if (fd.ShowDialog() == DialogResult.OK) { path = fd.FileName; } if (!string.IsNullOrEmpty(path)) { printResult.Remove(0, printResult.Length);//清除列印結果 DataSet ds = GetExcelTables(path);//讀取Excel到DataSet DataTable dtTotal = ds.Tables["總表$"]; List<TotalModel> totalList = GetTotalData(dtTotal); List<PurchaseModel> purchaseList = new List<PurchaseModel>();//列印資料 foreach (DataTable dt in ds.Tables) { if (!dt.TableName.Contains("總表")) { List<PurchaseModel> list = GetPurchaseData(dt, totalList); if (list.Count > 0) { purchaseList.AddRange(list); } } } string strmsg = printResult.ToString(); if (strmsg != "") { MessageBox.Show(strmsg); } else { dataGridView1.DataSource = purchaseList; } } } /// <summary> /// 列印設定 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSetPrint_Click(object sender, EventArgs e) { this.pageSetupDialog1.ShowDialog(); } //列印預覽 private void btnPrePrint_Click(object sender, EventArgs e) { this.printPreviewDialog1.ShowDialog(); } //列印DataGridView資料 private void btnPrint_Click(object sender, EventArgs e) { if (this.printDialog1.ShowDialog() == DialogResult.OK) { if (dataGridView1.Rows[0].Cells[0].Value != null) { btnPrint.Enabled = false; //加入佇列 queuePrint.Clear(); List<Message> messages = new List<Message>(); foreach (DataGridViewRow dr in dataGridView1.Rows) { if (dr.Cells["DocNo"].Value != null) { string docNo = dr.Cells["DocNo"].Value.ToString(); string destination = dr.Cells["Destination"].Value.ToString(); string warehouse = dr.Cells["Warehouse"].Value.ToString(); string proId = dr.Cells["ProId"].Value.ToString().TrimEnd(',').TrimEnd(''); string proName = dr.Cells["ProName"].Value.ToString().TrimEnd(',').TrimEnd(''); int boxNum = Convert.ToInt32(dr.Cells["BoxNum"].Value); for (int i = 1; i <= boxNum; i++) { messages.Add(new Message() { Count = 1, PM = new PurchaseModel() { BoxNum = boxNum, CurBoxNum = i, Destination = destination, DocNo = docNo, ProId = proId, ProName = proName, Warehouse = warehouse } }); } } } Print(messages);//列印 btnPrint.Enabled = true; } else { //MessageBox.Show("不允許列印空資料"); return; } } } /// <summary> /// 直接列印 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnPrint2_Click(object sender, EventArgs e) { if (this.printDialog1.ShowDialog() == DialogResult.OK) { if (dataGridView1.Rows[0].Cells[0].Value != null) { btnPrint.Enabled = false; //加入佇列 queuePrint.Clear(); List<Message> messages = new List<Message>(); foreach (DataGridViewRow dr in dataGridView1.Rows) { if (dr.Cells["DocNo"].Value != null) { string docNo = dr.Cells["DocNo"].Value.ToString(); string destination = dr.Cells["Destination"].Value.ToString(); string warehouse = dr.Cells["Warehouse"].Value.ToString(); string proId = dr.Cells["ProId"].Value.ToString().TrimEnd(',').TrimEnd(''); string proName = dr.Cells["ProName"].Value.ToString().TrimEnd(',').TrimEnd(''); int boxNum = Convert.ToInt32(dr.Cells["BoxNum"].Value); for (int i = 1; i <= boxNum; i++) { messages.Add(new Message() { Count = 1, PM = new PurchaseModel() { BoxNum = boxNum, CurBoxNum = i, Destination = destination, DocNo = docNo, ProId = proId, ProName = proName, Warehouse = warehouse } }); } } } //Print(messages); queuePrint.AddRange(messages); this.printDocument1.Print(); btnPrint.Enabled = true; } else { return; } } } #region /// <summary> /// 把匯入的DataTable資料轉化為List /// </summary> /// <param name="dt"></param> /// <param name="totalList"></param> /// <returns></returns> public List<PurchaseModel> GetPurchaseData(DataTable dt, List<TotalModel> totalList) { string dest = dt.TableName.Replace("$", ""); List<PurchaseModel> list = new List<PurchaseModel>(); for (int i = 0; i < dt.Rows.Count; i++) { DataRow dr = dt.Rows[i]; if (dr[0].ToString().Contains("採購單號")) { string docNo = dr[1].ToString(); PurchaseModel purchase = new PurchaseModel(); purchase.Destination = dest; purchase.DocNo = docNo; i += 5; for (; i < dt.Rows.Count; i++) { bool isok = false; string proName = ""; string proIdStr = ""; string warehouse = ""; int boxNum = 0; for (; i < dt.Rows.Count; i++) { string proId = dt.Rows[i][0].ToString();//商品編號 if (!string.IsNullOrEmpty(proId)) { proIdStr += proId + ""; proName += dt.Rows[i][1].ToString() + "";//商品名稱 warehouse = dt.Rows[i][3].ToString();//倉庫 int purNum = Convert.ToInt32(dt.Rows[i][4].ToString());//採購數量,計算箱數 TotalModel totalModel = totalList.Where(c => c.ProNo == proId).First(); if (totalModel == null) { string msg = "表:" + dt.TableName + " 行:" + (i + 1) + " 列:1;無法找到對應總表資料,請檢查資料格式!\r\n"; printResult.Append(msg); } else { int packageNum = totalModel.PackageNum;//箱規 boxNum += ((purNum / packageNum) + ((purNum % packageNum) > 0 ? 1 : 0));//計算出箱數 } } else { isok = true; break; } } purchase.BoxNum = boxNum; purchase.ProId = proIdStr.TrimEnd(','); purchase.ProName = proName.TrimEnd(','); purchase.Warehouse = warehouse; if (isok) { break; } } list.Add(purchase); } } return list; } /// <summary> /// 獲取總表中箱規資料 /// </summary> /// <param name="dt"></param> /// <returns></returns> public List<TotalModel> GetTotalData(DataTable dt) { List<TotalModel> list = new List<TotalModel>(); for (int i = 2; i < dt.Rows.Count; i++) { DataRow dr = dt.Rows[i]; string proNo = dr[0].ToString(); if (!proNo.Contains("合計")) { string pn = dr[dt.Columns.Count - 2].ToString(); if (pn != "") { int packageNum = Convert.ToInt32(pn); list.Add(new TotalModel() { ProNo = proNo, PackageNum = packageNum }); } } } return list; } /// <summary> /// 獲取Excel資料 /// </summary> /// <param name="fullPath"></param> /// <returns></returns> public DataSet GetExcelTables(string fullPath) { DataSet ds = new DataSet(); if (File.Exists(fullPath)) { //HDR=No 第一行就是資料 string strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fullPath + ";Extended Properties='Excel 12.0;HDR=No;IMEX=1;'"; using (OleDbConnection conn = new OleDbConnection(strConn)) { conn.Open(); foreach (DataRow item in conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null).Rows) { string tableName = item[2].ToString().Trim(); DataTable dt = new DataTable(); dt.TableName = tableName; OleDbDataAdapter odda = new OleDbDataAdapter("select * from [" + tableName + "]", conn); odda.Fill(dt); ds.Tables.Add(dt); } } } return ds; } #endregion #region 列印 internal void Print(Message msg) { Print(new List<Message>() { msg }); } internal void Print(IList<Message> list) { if (list == null || list.Count < 1) return; queuePrint.AddRange(list); if (backgroundWorker1.IsBusy == false) { backgroundWorker1.RunWorkerAsync(); } } bool IsPrinting = false; private void DoPrint() { if (IsPrinting) return; while (queuePrint.Count > 0) { printDocument1.Print(); //重要,迴圈作業,UI可接收訊息 Application.DoEvents();//此處解決過多列印佇列會使介面假死問題 } IsPrinting = false; } private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) { var worker = sender as BackgroundWorker; while (queuePrint.Count > 0) { if ((worker.CancellationPending == true)) { e.Cancel = true; break; } else { printDocument1.Print(); System.Threading.Thread.Sleep(3000); } } } /// <summary> /// 填充列印主體 /// </summary> private void fillPrintBody(PurchaseModel lp) { if (lp == null) return; row1 = "供應商名稱:xxxxxx"; row2 = "採購單號:" + lp.DocNo; row3 = "目的城市:" + lp.Destination; row4 = "倉庫:" + lp.Warehouse; row5 = "商品名稱:" + lp.ProId; row6 = "箱數:第" + lp.CurBoxNum + "箱,共" + lp.BoxNum + ""; } private void printDocument1_QueryPageSettings(object sender, System.Drawing.Printing.QueryPageSettingsEventArgs e) { } /// <summary> /// 列印前 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void printDocument1_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e) { if (queuePrint.Count < 1) { e.Cancel = true; return; } //printDialog1.PrinterSettings.Copies = 1;// (short)msg.Count; //設定每個只打印一份 var msg = queuePrint.Peek(); fillPrintBody(msg.PM); } /// <summary> /// 列印後 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void printDocument1_EndPrint(object sender, System.Drawing.Printing.PrintEventArgs e) { queuePrint.Dequeue();//移除已被列印的資料 } /// <summary> /// 列印文件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; //畫素偏移方式,畫素在水平和垂直距離上均偏移若干個單位,以進行高速鋸齒消除。 e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half; //也可以通過設定Graphics對不平平滑處理方式解決,程式碼如下: e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; Font drawFont = new Font("宋體", 10); Brush drawBrush = Brushes.Black; e.Graphics.DrawString(row1, drawFont, drawBrush, 0, 0); e.Graphics.DrawString(row2, drawFont, drawBrush, 0, 20); e.Graphics.DrawString(row3, drawFont, drawBrush, 0, 40); e.Graphics.DrawString(row4, drawFont, drawBrush, 0, 60); e.Graphics.DrawString(row5, drawFont, drawBrush, 0, 80); e.Graphics.DrawString(row6, drawFont, drawBrush, 0, 100); //float pageW = 79f; //float pageH = 50f; //var docMargins = this.printDocument1.DefaultPageSettings.Margins; //float recW = pageW - docMargins.Left - docMargins.Right; //float recH = pageH - docMargins.Top - docMargins.Bottom; //var rec1 = new RectangleF(0f, 0f, recW, recH); //var rec2 = new RectangleF(0f, 0f, recW, recH); //var rec3 = new RectangleF(0f, 0f, recW, recH); //var rec4 = new RectangleF(0f, 0f, recW, recH); //var rec5 = new RectangleF(0f, 0f, recW, recH); //var rec6 = new RectangleF(0f, 0f, recW, recH); //e.Graphics.DrawString(row1, drawFont, drawBrush, rec1, sf); //e.Graphics.DrawString(row2, drawFont, drawBrush, rec2, sf); //queuePrint.Dequeue(); //if (queuePrint.Count > 0) //{ // e.HasMorePages = true; //} //else //{ // e.HasMorePages = false; //} } #endregion } public class TotalModel { /// <summary> /// 商品編號 /// </summary> public string ProNo { get; set; } /// <summary> /// 箱規 /// </summary> public int PackageNum { get; set; } } public class PurchaseModel { public string DocNo { get; set; } public string Destination { get; set; } public string Warehouse { get; set; } public string ProName { get; set; } public int BoxNum { get; set; } public int CurBoxNum { get; set; } public string ProId { get; set; } } internal class Message { public int Count; public PurchaseModel PM { get; set; } } /// <summary> /// 佇列 /// </summary> /// <typeparam name="T"></typeparam> internal class Queue<T> : List<T> { /// <summary> /// 取出第一個元素 /// </summary> /// <returns></returns> public T Peek() { return this.FirstOrDefault(); } /// <summary> /// 刪除第一個元素 /// </summary> /// <returns></returns> public T Dequeue() { var item = this.FirstOrDefault(); if (item != null) { Remove(item); } return item; } /// <summary> /// 新增到末尾 /// </summary> /// <param name="item"></param> public void Enqueue(T item) { Add(item); } } }