You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

135 lines
4.8 KiB

  1. 
  2. using iTextSharp.text;
  3. using iTextSharp.text.pdf;
  4. using System;
  5. using System.IO;
  6. namespace ReportEngine
  7. {
  8. public class ReportCanvas : PdfPageEventHelper
  9. {
  10. PdfContentByte _dcContent;
  11. PdfTemplate _tFooterPageTotal;
  12. readonly ReportCanvasOptions _rpoOptions;
  13. public ReportCanvas(ReportCanvasOptions i_rpoOptions)
  14. {
  15. _rpoOptions = i_rpoOptions;
  16. }
  17. public override void OnEndPage(PdfWriter writer, Document document)
  18. {
  19. // 頁尾頁數設定
  20. if (_rpoOptions.IsShowPageNumber)
  21. {
  22. var baseCenter = _rpoOptions.PageSize.Right / 2;
  23. var pageBottom = (document.BottomMargin - _rpoOptions.FontSize) / 2 + 5;
  24. var pageCenter = baseCenter; // 頁碼偏移
  25. var pageN = writer.PageNumber;
  26. string pageText = $"{pageN}/" ;
  27. var textWidth = _rpoOptions.BaseFont.GetWidthPoint(pageText, _rpoOptions.FontSize);
  28. _dcContent.SetFontAndSize(_rpoOptions.BaseFont, _rpoOptions.FontSize); // 預設文字大小
  29. _dcContent.BeginText();
  30. _dcContent.ShowTextAligned(PdfContentByte.ALIGN_LEFT, pageText, pageCenter- textWidth, pageBottom, 0);
  31. _dcContent.EndText();
  32. _dcContent.AddTemplate(_tFooterPageTotal, pageCenter, pageBottom - 1);
  33. }
  34. base.OnEndPage(writer, document);
  35. }
  36. public override void OnOpenDocument(PdfWriter writer, Document document)
  37. {
  38. base.OnOpenDocument(writer, document);
  39. _dcContent = writer.DirectContent;
  40. if (_rpoOptions.IsShowPageNumber)
  41. {
  42. _tFooterPageTotal = _dcContent.CreateTemplate(50, 50);
  43. }
  44. }
  45. public string Paint(Func<ReportPainter, ReportCanvasOptions, string> i_fPainting,
  46. [System.Runtime.CompilerServices.CallerLineNumber] int i_nCodeLine = 0,
  47. [System.Runtime.CompilerServices.CallerMemberName] string i_sMemberName = "",
  48. [System.Runtime.CompilerServices.CallerFilePath] string i_sSourcePath = "")
  49. {
  50. string sMsg;
  51. try
  52. {
  53. do
  54. {
  55. Document doc = new Document(_rpoOptions.PageSize,
  56. _rpoOptions.PageMarginLeft,
  57. _rpoOptions.PageMarginRight,
  58. _rpoOptions.PageMarginHeader,
  59. _rpoOptions.PageMarginFooter);
  60. MemoryStream memoryStream = new MemoryStream();
  61. PdfWriter writer = PdfWriter.GetInstance(doc, memoryStream);
  62. writer.CloseStream = false;
  63. if (_rpoOptions.UserEntercode != null && _rpoOptions.OwnerEntercode != null)
  64. {
  65. writer.SetEncryption(PdfWriter.STRENGTH128BITS, _rpoOptions.UserEntercode, _rpoOptions.OwnerEntercode, PdfWriter.AllowPrinting); // 設定PDF權限
  66. }
  67. writer.PageEvent = this; // 頁首頁尾設定
  68. ReportPainter rp = new ReportPainter(doc, _rpoOptions, writer);
  69. doc.Open();
  70. sMsg = i_fPainting.Invoke(rp, _rpoOptions);
  71. if (sMsg != null)
  72. {
  73. break;
  74. }
  75. doc.NewPage();
  76. // 沒有資料時顯示文字
  77. if (writer.PageNumber == 1)
  78. {
  79. rp.WriteText("無資料");
  80. }
  81. doc.Close();
  82. using var fs = new FileStream(_rpoOptions.OutputPath, FileMode.OpenOrCreate, FileAccess.Write);
  83. memoryStream.Seek(0, SeekOrigin.Begin);
  84. memoryStream.CopyTo(fs);
  85. }
  86. while (false);
  87. }
  88. catch
  89. {
  90. sMsg = $"{nameof(Paint)} unknwon exception. Call from {i_sMemberName} {i_sSourcePath}({i_nCodeLine}).";
  91. #if DEBUG
  92. System.Diagnostics.Debug.WriteLine(sMsg);
  93. #endif
  94. }
  95. return sMsg;
  96. }
  97. public override void OnCloseDocument(PdfWriter writer, Document document)
  98. {
  99. base.OnCloseDocument(writer, document);
  100. // 顯示每個頁碼的總頁數(僅此處可抓到)
  101. if (_rpoOptions.IsShowPageNumber)
  102. {
  103. _tFooterPageTotal.BeginText();
  104. _tFooterPageTotal.SetFontAndSize(_rpoOptions.BaseFont, _rpoOptions.FontSize);
  105. _tFooterPageTotal.ShowTextAligned(PdfContentByte.ALIGN_LEFT, (writer.PageNumber - 1).ToString(), 0, 1, 0);
  106. _tFooterPageTotal.EndText();
  107. }
  108. }
  109. }
  110. }