基於iTextSharp的PDF文檔操作


  公司是跨境電商,需要和各種物流打交道,需要把東西交給物流,讓他們發到世界各地。其中需要物流公司提供一個運單號,來追蹤貨物到達哪里?!

  最近在和DHL物流公司(應該是個大公司)對接,取運單號的方式是調用對方提供的API,簡單說,就是我們傳一些發貨地址和客戶信息,要發的貨物等,對方返回一個運單號和物流面單(就是我們淘寶快遞上的面單)。過程呢,還是比較順利的,經過一系列溝通,最終還是實現了功能

  下面還是說說沒有實現的功能,如果都實現了,也不用寫這篇博客了。不足之處在於DHL提供的面單,沒有提供要揀哪些貨的面單。本來一個完整的面單,包括2部分:物流公司需要貼在包裹上的面單(物流面單)和我們自己發貨部門要發哪些東西的面單(揀貨面單),兩部分組合在一起,發貨部門才能正常的完成這個包裹的發貨

  好吧,終於要引入正題了,DHL公司將物流面單以pdf文件流的形式返回,就是我們可以保存成Pdf文件,這樣就容易處理的多,我們自己的揀貨面單,如果也可以保存至Pdf文件,這樣就可以將這2個Pdf文件一塊打印出來,這算是一個折中的解決方案。

  首先,要將揀貨數據(含圖片)保存至Pdf文檔。技術點如下

    1, 將DataTable導出至Pdf

    2, DataTable中包含圖片,也要能導出

    3, Pdf類庫,字體的引入(居然需要引用字體的絕對路徑,想不通)

  下面分別講解

    1, 這點就是直接創建iTextSharp中的PdfDataTable對象,直接映射即可。代碼如下:

private static pdfText.pdf.PdfPTable CreatePdfPTableToPickupLabel(List<TradeDetailModel> listDetail, iTextSharp.text.Font font)
{
    pdfText.pdf.PdfPTable pdtTable = new pdfText.pdf.PdfPTable(5);
    pdtTable.WidthPercentage = 95;      //占寬度百分比:95%(這句很關鍵,作用是撐滿整個面單)

    int[] colWidth = { 2, 4, 2, 2, 2 }; //設置列寬比例
    pdtTable.SetWidths(colWidth);

    //此處,先插入首行,即標題
    pdtTable.AddCell(new iTextSharp.text.Phrase("圖片", font));
    pdtTable.AddCell(new iTextSharp.text.Phrase("基本信息", font));
    pdtTable.AddCell(new iTextSharp.text.Phrase("單價", font));
    pdtTable.AddCell(new iTextSharp.text.Phrase("數量", font));
    pdtTable.AddCell(new iTextSharp.text.Phrase("備注", font));

    //再插入真實揀貨數據
    int rowCount = listDetail.Count;
    for (int i = 0; i < rowCount; i++)
    {
        TradeDetailModel modelDetail = listDetail[i];

        iTextSharp.text.Image image = PdfUtil.CreatePdfImage(modelDetail.ProductImageBytes);
        pdtTable.AddCell(image);
        pdtTable.AddCell(new iTextSharp.text.Phrase(modelDetail.ProductBase, font));
        pdtTable.AddCell(new iTextSharp.text.Phrase(modelDetail.Price.ToString() + Environment.NewLine + modelDetail.ProductID, font));
        pdtTable.AddCell(new iTextSharp.text.Phrase(modelDetail.Number.ToString() + Environment.NewLine + modelDetail.ProductSpec, font));
        pdtTable.AddCell(new iTextSharp.text.Phrase(modelDetail.Remark, font));
    }

    return pdtTable;
}

    2, 這點要先生成iTextSharp中Image對象才可以,然后再隨生成PdfDataTable中,將Image對象插入單元格(注意:圖片尺寸需要定義好)。代碼如下:

/// <summary>
/// 創建Pdf所需圖像
/// </summary>
/// <param name="imageBytes"></param>
/// <param name="widthS"></param>
/// <param name="heightS"></param>
/// <returns></returns>
private static iTextSharp.text.Image CreatePdfImage(byte[] imageBytes, float widthS = 60f, float heightS = 60f)
{
    iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(imageBytes);

    //圖片大小要求統一80x80,需根據實際圖片        
    float perW = (float)Math.Round(widthS / image.Width, 2);
    float perH = (float)Math.Round(heightS / image.Height, 2);
    image.ScalePercent(perW * 100, perH * 100);

    //設置Dpi值,能夠清晰些
    image.SetDpi(124, 124);

    return image;
}  

    3, 創建字體

/// <summary>
/// 創建Pdf所需字體
/// </summary>
/// <returns></returns>
public static iTextSharp.text.Font CreatePdfFont(float fontSize = 16F)
{
    //黑體
    string fontPath = @"C:\Windows\Fonts\simhei.ttf";

    iTextSharp.text.pdf.BaseFont baseFont = iTextSharp.text.pdf.BaseFont.CreateFont(fontPath,
        iTextSharp.text.pdf.BaseFont.IDENTITY_H,
        iTextSharp.text.pdf.BaseFont.NOT_EMBEDDED);
    iTextSharp.text.Font font = new iTextSharp.text.Font(baseFont, fontSize);

    return font;
}

    下面是調用的代碼,僅供參考。注:返回的Pdf文件的絕對路徑,用於后續打印

/// <summary>
/// 生成揀貨標簽pdf文件
/// </summary>
/// <param name="modelTrade"></param>
/// <param name="dhlLabelFolderName"></param>
/// <returns></returns>
public static string CreatePickupLabel(TradeModel modelTrade,string dhlLabelFolderName)
{
    //參考地址
    //https://www.cnblogs.com/yangy1989/p/5300304.html
    //http://blog.csdn.net/lideyuans/article/details/51536676 (設置圖片百分比)

    //組裝,待生成的pdf文件完整路徑
    string logisticsNo = modelTrade.R;
    string pdfFileName = dhlLabelFolderName + logisticsNo + "_Label.pdf";

    FileStream fs = new FileStream(pdfFileName, FileMode.Create);
    pdfText.Rectangle rect = new pdfText.Rectangle(0f, 0f, 1000f, 1000f);
    pdfText.Document document = new pdfText.Document(rect, 5f, 5f, 5f, 5f);

    //創建字體
    iTextSharp.text.Font font = PdfUtil.CreatePdfFont(34F);

    pdfText.pdf.PdfWriter pdfWriter = pdfText.pdf.PdfWriter.GetInstance(document, fs);
    document.Open();

    //增加揀貨單品列表
    pdfText.pdf.PdfPTable pdfpTable = PdfUtil.CreatePdfPTableToPickupLabel(modelTrade.Details, font);
    document.Add(pdfpTable);

    //增加品名備注            
    pdfText.Paragraph pgraph1 = new pdfText.Paragraph(modelTrade.ItemsDescription, font);
    document.Add(pgraph1);

    //增加:發貨期限
    font.Color = pdfText.BaseColor.RED;
    pdfText.Paragraph pgraph2 = new pdfText.Paragraph(modelTrade.ShipLimitTimeText, font);
    document.Add(pgraph2);

    document.Close();
    fs.Close();

    return pdfFileName;
}

  

  再將這2個文件,通過C#代碼連續打印出來。支持連續打印多個Pdf文件

//直接調用cmd命令,實現直接打印
foreach (string printFile in listPrintFile)
{
    Process proc = new Process();
    proc.StartInfo.CreateNoWindow = false;
    proc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
    proc.StartInfo.UseShellExecute = true;
    proc.StartInfo.FileName = printFile;
    proc.StartInfo.Verb = "print";
    proc.Start();
    proc.Close();
}

  

  好了,最后的最后,看看效果圖吧。前2聯是DHL返回的Pdf文件,第3聯是我本地生成的Pdf文件,合並成一個完整的發貨面單

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM