|
| 1 | +using InvoiceHTMLtoPDF; |
| 2 | +using Syncfusion.Drawing; |
| 3 | +using Syncfusion.HtmlConverter; |
| 4 | +using Syncfusion.Pdf; |
| 5 | +using Syncfusion.Pdf.Graphics; |
| 6 | +using System.Text; |
| 7 | +using System.Text.Json; |
| 8 | + |
| 9 | +// Load customer data from JSON file |
| 10 | +string customerDataJsonPath = "customer_data.json"; |
| 11 | +string customerDataJsonContent = File.ReadAllText(customerDataJsonPath); |
| 12 | +List<CompanyInvoice> companies = JsonSerializer.Deserialize<List<CompanyInvoice>>(customerDataJsonContent); |
| 13 | + |
| 14 | +// Load HTML invoice template |
| 15 | +string templatePath = "invoice_template.html"; |
| 16 | +string htmlTemplate = File.ReadAllText(templatePath); |
| 17 | + |
| 18 | +// Initialize HTML to PDF converter with Blink rendering engine |
| 19 | +HtmlToPdfConverter htmlConverter = new HtmlToPdfConverter(); |
| 20 | +BlinkConverterSettings settings = new BlinkConverterSettings |
| 21 | +{ |
| 22 | + Scale = 1.0f |
| 23 | +}; |
| 24 | +htmlConverter.ConverterSettings = settings; |
| 25 | + |
| 26 | +foreach (var company in companies) |
| 27 | +{ |
| 28 | + string filledHtmlTemplate = htmlTemplate; |
| 29 | + StringBuilder itemRows = new StringBuilder(); |
| 30 | + decimal subtotal = 0; |
| 31 | + |
| 32 | + foreach (var item in company.PurchaseItems) |
| 33 | + { |
| 34 | + decimal itemTotal = item.NoOfLicensePurchased * item.UnitPrice; |
| 35 | + subtotal += itemTotal; |
| 36 | + |
| 37 | + itemRows.AppendLine($@" |
| 38 | + <tr> |
| 39 | + <td>{item.ItemName}</td> |
| 40 | + <td>{item.NoOfLicensePurchased}</td> |
| 41 | + <td class='unit-price' data-price='{item.UnitPrice}'>{item.UnitPrice:C2}</td> |
| 42 | + <td class='row-total'>{itemTotal:C2}</td> |
| 43 | + </tr>"); |
| 44 | + } |
| 45 | + |
| 46 | + // Calculate Tax and Total |
| 47 | + decimal taxRate = 0.085m; |
| 48 | + decimal salesTax = subtotal * taxRate; |
| 49 | + decimal total = subtotal + salesTax; |
| 50 | + |
| 51 | + // Replace placeholders in HTML template with actual values |
| 52 | + filledHtmlTemplate = htmlTemplate |
| 53 | + .Replace("{{PurchasedItems}}", itemRows.ToString()) |
| 54 | + .Replace("{{Subtotal}}", subtotal.ToString("F2")) |
| 55 | + .Replace("{{SalesTax}}", salesTax.ToString("F2")) |
| 56 | + .Replace("{{TotalAmountDue}}", total.ToString("F2")); |
| 57 | + |
| 58 | + // Convert filled HTML to PDF document |
| 59 | + PdfDocument document = htmlConverter.Convert(filledHtmlTemplate, ""); |
| 60 | + |
| 61 | + #region Header |
| 62 | + // ---------------------------- |
| 63 | + // HEADER SECTION |
| 64 | + // ---------------------------- |
| 65 | + |
| 66 | + // Create header section in PDF Document |
| 67 | + PdfPageTemplateElement header = new PdfPageTemplateElement(document.Pages[0].GetClientSize().Width, 120); |
| 68 | + PdfGraphics gHeader = header.Graphics; |
| 69 | + |
| 70 | + PdfFont headerFont = new PdfStandardFont(PdfFontFamily.Helvetica, 10, PdfFontStyle.Bold); |
| 71 | + PdfFont subFont = new PdfStandardFont(PdfFontFamily.Helvetica, 9); |
| 72 | + |
| 73 | + float currentYLeft = 0; |
| 74 | + float currentYRight = 0; |
| 75 | + |
| 76 | + string imagePath = "company-logo.jpg"; |
| 77 | + byte[] imageBytes = File.ReadAllBytes(imagePath); |
| 78 | + string base64String = Convert.ToBase64String(imageBytes); |
| 79 | + company.CompanyLogo = "data:image/jpeg;base64," + base64String; |
| 80 | + |
| 81 | + using (MemoryStream ms = new MemoryStream(imageBytes)) |
| 82 | + { |
| 83 | + PdfBitmap logo = new PdfBitmap(ms); |
| 84 | + gHeader.DrawImage(logo, new RectangleF(35, currentYLeft, 100, 30)); |
| 85 | + currentYLeft += 45; |
| 86 | + currentYRight += 45; |
| 87 | + } |
| 88 | + |
| 89 | + // Add customer billing information to the left |
| 90 | + gHeader.DrawString("Bill To:", headerFont, PdfBrushes.Black, new PointF(35, currentYLeft += 15)); |
| 91 | + gHeader.DrawString(company.CustomerName, headerFont, PdfBrushes.Black, new PointF(35, currentYLeft += 15)); |
| 92 | + gHeader.DrawString(company.CustomerAddress, subFont, PdfBrushes.Black, new PointF(35, currentYLeft += 15)); |
| 93 | + gHeader.DrawString($"Phone: {company.CustomerPhone} | Email: {company.CustomerEmail}", subFont, PdfBrushes.Black, new PointF(35, currentYLeft += 15)); |
| 94 | + |
| 95 | + // Add invoice details on the right |
| 96 | + float rightX = 400; |
| 97 | + PdfFont largeHeaderFont = new PdfStandardFont(PdfFontFamily.Helvetica, 18, PdfFontStyle.Bold); |
| 98 | + gHeader.DrawString("Invoice", largeHeaderFont, PdfBrushes.Black, new PointF(rightX, 5)); |
| 99 | + gHeader.DrawString($"{company.InvoiceTitle} - #{company.InvoiceNumber}", headerFont, PdfBrushes.Black, new PointF(rightX, currentYRight += 15)); |
| 100 | + gHeader.DrawString($"Date: {company.InvoiceDate:dd MMM yyyy}", subFont, PdfBrushes.Black, new PointF(rightX, currentYRight += 15)); |
| 101 | + gHeader.DrawString($"Due Date: {company.DueDate:dd MMM yyyy}", subFont, PdfBrushes.Black, new PointF(rightX, currentYRight += 15)); |
| 102 | + gHeader.DrawString($"Sales Tax No: {company.SalesTaxNumber}", subFont, PdfBrushes.Black, new PointF(rightX, currentYRight += 15)); |
| 103 | + |
| 104 | + document.Template.Top = header; |
| 105 | + |
| 106 | + #endregion |
| 107 | + |
| 108 | + #region Footer |
| 109 | + // ---------------------------- |
| 110 | + // Footer SECTION |
| 111 | + // ---------------------------- |
| 112 | + |
| 113 | + // Create Footer section in PDF Document |
| 114 | + PdfPageTemplateElement footer = new PdfPageTemplateElement(document.Pages[0].GetClientSize().Width, 70); |
| 115 | + PdfGraphics gFooter = footer.Graphics; |
| 116 | + |
| 117 | + PdfFont footerFont = new PdfStandardFont(PdfFontFamily.Helvetica, 9); |
| 118 | + PdfFont footerFontBold = new PdfStandardFont(PdfFontFamily.Helvetica, 10, PdfFontStyle.Bold); |
| 119 | + |
| 120 | + // Add thanks message |
| 121 | + string thankYouText = "Thank you for your business!"; |
| 122 | + SizeF textSize = footerFont.MeasureString(thankYouText); |
| 123 | + float centerX = (document.Pages[0].GetClientSize().Width - textSize.Width) / 2; |
| 124 | + gFooter.DrawString(thankYouText, footerFont, PdfBrushes.Black, new PointF(centerX, 0)); |
| 125 | + |
| 126 | + // Add terms and conditions |
| 127 | + string termsLabel = "Terms and Conditions: "; |
| 128 | + SizeF termsLabelSize = footerFontBold.MeasureString(termsLabel); |
| 129 | + gFooter.DrawString(termsLabel, footerFontBold, PdfBrushes.Black, new PointF(0, 20)); |
| 130 | + gFooter.DrawString(company.TermsAndConditions, footerFont, PdfBrushes.Black, new PointF(termsLabelSize.Width, 20)); |
| 131 | + |
| 132 | + // Add separator line |
| 133 | + gFooter.DrawLine(new PdfPen(PdfBrushes.Black, 0.5f), new PointF(0, 40), new PointF(600, 40)); |
| 134 | + |
| 135 | + // Add seller address and contact info |
| 136 | + gFooter.DrawString("Address:", footerFontBold, PdfBrushes.Black, new PointF(0, 45)); |
| 137 | + gFooter.DrawString(company.SellerAddress, footerFont, PdfBrushes.Black, new PointF(0, 60)); |
| 138 | + |
| 139 | + string emailLabel = "Email: "; |
| 140 | + SizeF emailLabelSize = footerFontBold.MeasureString(emailLabel); |
| 141 | + gFooter.DrawString(emailLabel, footerFontBold, PdfBrushes.Black, new PointF(450, 45)); |
| 142 | + gFooter.DrawString(company.SellerEmail, footerFont, PdfBrushes.Black, new PointF(450 + emailLabelSize.Width, 45)); |
| 143 | + |
| 144 | + string phoneLabel = "Phone: "; |
| 145 | + SizeF phoneLabelSize = footerFontBold.MeasureString(phoneLabel); |
| 146 | + gFooter.DrawString(phoneLabel, footerFontBold, PdfBrushes.Black, new PointF(450, 60)); |
| 147 | + gFooter.DrawString(company.SellerPhoneNumber, footerFont, PdfBrushes.Black, new PointF(450 + phoneLabelSize.Width, 60)); |
| 148 | + |
| 149 | + document.Template.Bottom = footer; |
| 150 | + |
| 151 | + #endregion |
| 152 | + |
| 153 | + // Save PDF |
| 154 | + Directory.CreateDirectory("../../../Output"); |
| 155 | + string outputPath = $"../../../Output/Invoice_{company.CustomerName}.pdf"; |
| 156 | + using MemoryStream stream = new MemoryStream(); |
| 157 | + document.Save(stream); |
| 158 | + File.WriteAllBytes(outputPath, stream.ToArray()); |
| 159 | + |
| 160 | + // Close the document to release resources |
| 161 | + document.Close(true); |
| 162 | +} |
| 163 | +Console.WriteLine("Documents saved successfully!"); |
0 commit comments