公司是跨境電商,需要和各種物流打交道,需要把東西交給物流,讓他們發到世界各地。其中需要物流公司提供一個運單號,來追蹤貨物到達哪里?!
最近在和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文件,合並成一個完整的發貨面單

