首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 列印 A4 紙張完整實作:自動分頁與動態資料渲染

     編輯:關於C#

在 VB6 中列印 A4 文件,內容從 DB 或 DataGrid 動態獲取,實現非常簡單。但在 .NET 中,VB6 好用的 Printer 物件不見了,被 PrintDocument 元件取代。兩者行為不同,但多數情況可複製功能。查閱 MSDN 發現無直接對應用法,需自行實作。雖然 .NET 列印功能更強大,但極其複雜,教科書範例都要先開啟文件、LoadFile、計算行數、設定屬性,無法直接拿來用,只好自行改寫。

列印核心架構

列印啟動方法

public bool PrintDoc() {
    try {
        // 獲取列印內容
        string strSQL = "exec [usp_PalletPrintDocInfo] '" + Parameters.strStation + "', '" + Parameters.strPalletID + "'";
        dsPrintInfo = doDB.GetDataSet(strSQL);
        if (dsPrintInfo.Tables[0].Rows.Count < 1 || dsPrintInfo.Tables[1].Rows.Count < 1) {
            Parameters.strMsg = "Get Print Information Error";
            return false;
        }
        // 列印
        PrintDocument printDocument = new PrintDocument();
        printDocument.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);
        printDocument.Print();
        ///// 列印預覽,除錯時可用,節省紙張
        // PrintPreviewDialog ppd = new PrintPreviewDialog();
        // PrintDocument pd = new PrintDocument();
        // pd.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);
        // ppd.Document = pd;
        // ppd.ShowDialog();
        return true;
    } catch (Exception ex) {
        Parameters.strMsg = ex.Message.ToString();
        return false;
    }
}

PrintPage 事件處理:自動分頁核心邏輯


// 列印 A4 用變數
#region 列印變數
DataSet dsPrintInfo; // 要列印資訊,表一 SN 資訊,表二 WO 資訊
private int lineNo; // 當前列印行號
private int lineQty; // 總共要列印行數(估算值,略大於實際)
private int printingPageNo = 0; // 當前列印頁號
#endregion

private void pd_PrintPage(object sender, PrintPageEventArgs e) {
    string strLine;
    float leftMargin = (e.MarginBounds.Left) * 3 / 4;
    float topMargin = e.MarginBounds.Top * 2 / 3;
    float verticalPosition = topMargin;
    Font mainFont = new Font("Courier New", 10);
    // 每頁行數,超過需換頁
    int linesPerPage = (int)(e.MarginBounds.Height * 1.05 / mainFont.GetHeight(e.Graphics));

    // 文件格式:第一頁列印表頭
    #region 文件格式
    if (printingPageNo == 0) {
        mainFont = new Font("Courier New", 24, FontStyle.Bold);
        strLine = String.Format("{0,21}", "FQA Report");
        e.Graphics.DrawString(strLine, mainFont, Brushes.Black, leftMargin, verticalPosition, new StringFormat());
        verticalPosition += mainFont.GetHeight(e.Graphics);

        mainFont = new Font("Courier New", 16, FontStyle.Bold);
        strLine = "Pallet ID: " + dsPrintInfo.Tables[0].Rows[0]["Pallet_ID"].ToString();
        e.Graphics.DrawString(strLine, mainFont, Brushes.Black, leftMargin, verticalPosition, new StringFormat());
        verticalPosition += mainFont.GetHeight(e.Graphics);

        mainFont = new Font("3 of 9 Barcode", 24, FontStyle.Bold);
        strLine = "*" + dsPrintInfo.Tables[0].Rows[0]["Pallet_ID"].ToString() + "*";
        e.Graphics.DrawString(strLine, mainFont, Brushes.Black, leftMargin * 4, verticalPosition, new StringFormat());
        verticalPosition += mainFont.GetHeight(e.Graphics);

        mainFont = new Font("Courier New", 16, FontStyle.Bold);
        strLine = "QCI_PN: " + dsPrintInfo.Tables[0].Rows[0]["PARTNUMBER"].ToString();
        e.Graphics.DrawString(strLine, mainFont, Brushes.Black, leftMargin, verticalPosition, new StringFormat());
        verticalPosition += mainFont.GetHeight(e.Graphics);

        strLine = "Date: " + DateTime.Now;
        e.Graphics.DrawString(strLine, mainFont, Brushes.Black, leftMargin, verticalPosition, new StringFormat());
        verticalPosition += mainFont.GetHeight(e.Graphics);

        strLine = "Line: " + dsPrintInfo.Tables[0].Rows[0]["Mfg_Line"].ToString();
        e.Graphics.DrawString(strLine, mainFont, Brushes.Black, leftMargin, verticalPosition, new StringFormat());
        verticalPosition += mainFont.GetHeight(e.Graphics);

        strLine = "Model: " + dsPrintInfo.Tables[0].Rows[0]["Model"].ToString();
        e.Graphics.DrawString(strLine, mainFont, Brushes.Black, leftMargin, verticalPosition, new StringFormat());
        verticalPosition += mainFont.GetHeight(e.Graphics) * 2;

        // 表頭預計佔 15 行
        linesPerPage -= 15;
        // 總行數約為資料行數 + 15
        lineQty = dsPrintInfo.Tables[0].Rows.Count + 15;
    }
    #endregion

    // 列印 SN、BoxID、PalletID 明細列表
    #region 明細列表
    mainFont = new Font("Courier New", 10);
    strLine = String.Format("{0,-10}", "NO#") +
              String.Format("{0,-25}", "System S/N") +
              String.Format("{0,-25}", "BOX_ID") +
              String.Format("{0,-25}", "Pallet_ID");
    e.Graphics.DrawString(strLine, mainFont, Brushes.Black, leftMargin, verticalPosition, new StringFormat());
    verticalPosition += mainFont.GetHeight(e.Graphics);

    // 列印分隔線
    mainFont = new Font("Courier New", 3);
    e.Graphics.DrawLine(new Pen(Color.Black), leftMargin, verticalPosition, e.MarginBounds.Right, verticalPosition);
    verticalPosition += mainFont.GetHeight(e.Graphics);

    // 列印資料列
    int count = 0; // 當前頁行數計數
    mainFont = new Font("Courier New", 10);
    while (count < linesPerPage && lineNo < this.lineQty) {
        if (lineNo < dsPrintInfo.Tables[0].Rows.Count) {
            string strLineTemp = String.Format("{0,-10}", dsPrintInfo.Tables[0].Rows[lineNo]["NO"].ToString()) +
                                 String.Format("{0,-25}", dsPrintInfo.Tables[0].Rows[lineNo]["SN"].ToString()) +
                                 String.Format("{0,-25}", dsPrintInfo.Tables[0].Rows[lineNo]["BOX_ID"].ToString()) +
                                 String.Format("{0,-25}", dsPrintInfo.Tables[0].Rows[lineNo]["Pallet_ID"].ToString());
            e.Graphics.DrawString(strLineTemp, mainFont, Brushes.Black, leftMargin, verticalPosition, new StringFormat());
            verticalPosition += mainFont.GetHeight(e.Graphics);
            count++; // 注意:放在 If 內,否則單頁時尾部資訊會跑到第二頁
        }
        lineNo++;
    }
    #endregion

    // 判斷是否還有頁面
    if (lineQty > lineNo) {
        e.HasMorePages = true;
    } else {
        e.HasMorePages = false;
    }

    // 列印尾部資訊(僅最後一頁)
    #region 尾部資訊
    if (!e.HasMorePages) {
        mainFont = new Font("Courier New", 10);
        e.Graphics.DrawLine(new Pen(Color.Black), leftMargin, verticalPosition, e.MarginBounds.Right, verticalPosition);
        verticalPosition += mainFont.GetHeight(e.Graphics);
        foreach (DataRow dr in dsPrintInfo.Tables[1].Rows) {
            mainFont = new Font("Courier New", 16);
            strLine = String.Format("{0,-3}", "WO:") + String.Format("{0,-16}", dr["WO"].ToString()) +
                      String.Format("{0,-7}", "Qty:") + String.Format("{0,-10}", dr["Qty"].ToString());
            e.Graphics.DrawString(strLine, mainFont, Brushes.Black, leftMargin, verticalPosition, new StringFormat());
            verticalPosition += mainFont.GetHeight(e.Graphics);
        }
        foreach (DataRow dr in dsPrintInfo.Tables[2].Rows) {
            mainFont = new Font("Courier New", 16);
            strLine = String.Format("{0,-9}", "TotalQty:") + String.Format("{0,-10}", dr["TotalQty"].ToString()) +
                      String.Format("{0,-7}", "BoxQty:") + String.Format("{0,-10}", dr["BoxQty"].ToString());
            e.Graphics.DrawString(strLine, mainFont, Brushes.Black, leftMargin, verticalPosition, new StringFormat());
            verticalPosition += mainFont.GetHeight(e.Graphics);
        }
    }
    #endregion

    printingPageNo++; // 頁號加一
}

列印效果截圖

總結

如此簡單功能,在 .NET 實現確實複雜,尤其是自動分頁。雖然整體功能強大許多,但把原本好用的功能移除了。以上程式碼改寫成 VB.NET 也差不多。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved