代碼,須要加入的控件: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
這是新的64位的:https://www.microsoft.com/en-us/download/details.aspx?id=54920
換行打印:https://blog.csdn.net/knowledgeables/article/details/46521381ide
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); } } }