|
|
namespace ReportEngine { using iTextSharp.text; using iTextSharp.text.pdf; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Text;
public class ReportPainter { public enum ImageScale { IS_KeepOrigin = 0, IS_Width = 1, IS_FitWidth = 2 }
public class ColumnMeta { public string Title { get; set; } public float Width { get; set; }
public string DisplayFormat { get; set; } }
public class TableMeta {
public DataTable Table { get; set; }
public List<ColumnMeta> Columns { get; set; } }
public class DataCell { public enum EDC_TYPE { EDC_CONTENT = 0, EDC_EMPTY = 1 } public int ColumnSpan { get; set; } = 1;
public int RowSpan { get; set; } = 1;
public int Align { get; set; } = Element.ALIGN_LEFT;
public int VAlign { get; set; } = Element.ALIGN_MIDDLE;
public string Content { get; set; }
public EDC_TYPE CellType { get; set; } = EDC_TYPE.EDC_CONTENT;
public float Height { get; set; } = -1; }
public class CellTable { public int ColumnNum { get; set; } = 10;
public float ColumnWidth { get; set; } = 75; public List<DataCell> Cells { get; set; } }
readonly Document _dDocument;
readonly ReportCanvasOptions _rcoOption;
readonly PdfWriter _pfWriter;
readonly double dFontHeight; public ReportPainter(Document i_dDocument, ReportCanvasOptions i_rcoOption, PdfWriter i_pfWriter) { _dDocument = i_dDocument;
_rcoOption = i_rcoOption;
_pfWriter = i_pfWriter;
float ascent = _rcoOption.BaseFont.GetAscentPoint("Some String", _rcoOption.FontSize); float descent = _rcoOption.BaseFont.GetDescentPoint("Some String", _rcoOption.FontSize); dFontHeight = ascent - descent; }
public void NewPage() => _dDocument.NewPage();
public void WriteText(string text = "\r\n", int i_nAlign = PdfContentByte.ALIGN_LEFT, Font font = null) { Paragraph p = new Paragraph(text, font ?? _rcoOption.NormalFont) { Alignment = i_nAlign }; _dDocument.Add(p); }
public string WriteImage(string i_sFilePath, int i_nAlign = PdfContentByte.ALIGN_LEFT, ImageScale i_isScale = ImageScale.IS_KeepOrigin) { string sMsg = null;
if (System.IO.File.Exists(i_sFilePath)) { Image image = Image.GetInstance(filename: i_sFilePath);
switch (i_isScale) { case ImageScale.IS_KeepOrigin: { _dDocument.Add(image); } break; case ImageScale.IS_Width: { float fNewWidth = _rcoOption.PageSize.Width - _rcoOption.PageMarginRight - _rcoOption.PageMarginLeft; float fHeight = fNewWidth * image.Height / image.Width; image.ScaleToFit(fNewWidth, fHeight); _dDocument.Add(image); } break; case ImageScale.IS_FitWidth: { float fNewWidth = _rcoOption.PageSize.Width; float fHeight = fNewWidth * image.Height / image.Width; float fY = _pfWriter.GetVerticalPosition(true);
image.ScaleToFit(fNewWidth, fHeight); image.SetAbsolutePosition(0, fY - fHeight);
Paragraph p = new Paragraph { image }; _dDocument.Add(p);
int nLine = (int)Math.Ceiling(fHeight / dFontHeight / 2) + 2;
for (int n = 0; n < nLine; n++) // Workaround for vertical shift
{ WriteText(); }
} break; default: break; }
} else { sMsg = $"Image not exist! Path = {i_sFilePath}"; } return sMsg; }
public void WriteTable(CellTable i_ctTableInfo, int i_nAlign = PdfContentByte.ALIGN_CENTER) { List<float> lf = new List<float>();
for (int nIdx = 0; nIdx < i_ctTableInfo.ColumnNum; nIdx++) { lf.Add(i_ctTableInfo.ColumnWidth); }
PdfPTable pptTable = GeneratePTable(lf.ToArray(), 0);
foreach (DataCell dc in i_ctTableInfo.Cells) { if (dc.CellType == DataCell.EDC_TYPE.EDC_CONTENT) { pptTable.AddCell(GeneratePCell(dc.Content, dc.RowSpan, dc.ColumnSpan, dc.Align, dc.VAlign)); } else if (dc.CellType == DataCell.EDC_TYPE.EDC_EMPTY) { StringBuilder sb = new StringBuilder();
for (int nIdx = 0; nIdx < dc.RowSpan; nIdx++) { sb.Append(Environment.NewLine); }
PdfPCell pc = new PdfPCell(new Phrase(sb.ToString())) { Colspan = dc.ColumnSpan };
if(dc.Height != -1) { pc.FixedHeight = dc.Height; } pptTable.AddCell(pc); } }
Paragraph para = new Paragraph { Alignment = i_nAlign }; para.Add(pptTable); _dDocument.Add(para); }
public void WriteTable(TableMeta i_tmMeta, int i_nAlign = PdfContentByte.ALIGN_CENTER) { PdfPTable pptTable = GeneratePTable(i_tmMeta.Columns.Select(f => f.Width).ToArray());
string[] asTitles = i_tmMeta.Columns.Select(f => f.Title).ToArray(); foreach (string sTitle in asTitles) { pptTable.AddCell(GeneratePCell(sTitle, align: Element.ALIGN_CENTER)); }
DataTable dtData = i_tmMeta.Table; // 表格內容
foreach (DataRow row in dtData.Rows) { foreach (ColumnMeta cm in i_tmMeta.Columns) { var cellValue = GetValue(row, cm);
pptTable.AddCell(GeneratePCell(cellValue, align: Element.ALIGN_CENTER)); } }
var cell = GeneratePCell(string.Format("Total records: {0}", dtData.Rows.Count), 1, i_tmMeta.Columns.Count, Element.ALIGN_LEFT); pptTable.AddCell(cell);
Paragraph para = new Paragraph { Alignment = i_nAlign }; para.Add(pptTable); _dDocument.Add(para); }
public void WriteTable(PdfPTable i_pptTable, int i_nAlign = PdfContentByte.ALIGN_CENTER) { Paragraph para = new Paragraph { Alignment = i_nAlign }; para.Add(i_pptTable); _dDocument.Add(para); }
public void WriteTable(DataTable i_dtTable, int i_nAlign = PdfContentByte.ALIGN_CENTER) { Paragraph para = new Paragraph(); PdfPTable pdfTable = GenerateTable(i_dtTable);
para.Alignment = i_nAlign; para.Add(pdfTable); _dDocument.Add(para); }
protected PdfPTable GenerateTable(DataTable dataTable) { // 欄位設定
DataColumn[] columns = dataTable.Columns.Cast<DataColumn>().OrderBy(x => x.Ordinal).ToArray(); float[] columnWidths = GetColumnWidths(columns);
PdfPTable pdfTable = GeneratePTable(columnWidths, 1);
// 表頭
var captions = columns.Select(x => x.Caption ?? x.ColumnName); foreach (var caption in captions) { var cell = GeneratePCell(caption); pdfTable.AddCell(cell); }
// 表格內容
foreach (DataRow row in dataTable.Rows) { foreach (var column in columns) { var cellValue = GetValue(row, column);
var cell = GeneratePCell(cellValue, align: Element.ALIGN_CENTER); pdfTable.AddCell(cell); } }
// 表尾
// 如果不存在指定變數,或變數設定false就不顯示,反之顯示
if (dataTable.ExtendedProperties["RowCount"] as bool? != false) { var cell = GeneratePCell(string.Format("總計: {0} 筆紀錄", dataTable.Rows.Count), 1, columns.Length, Element.ALIGN_LEFT); pdfTable.AddCell(cell); }
return pdfTable; }
public string GetValue(DataRow row, ColumnMeta column) { if (!row.Table.Columns.Contains(column.Title)) { return ""; }
DataColumn dc = row.Table.Columns[column.Title];
var value = row[dc];
// 當有設定欄位時,以欄位為主
if (column.DisplayFormat != null) { return string.Format(column.DisplayFormat, value); }
var type = dc.DataType; if (type == typeof(int)) { return string.Format("{0:N0}", value); } else if (type == typeof(double) || type == typeof(decimal)) { return string.Format("{0:0,0.##}", value); } else if (type == typeof(DateTime)) { return string.Format("{0:yyyy/MM/dd HH\\:mm\\:ss}", value); } else if (type == typeof(TimeSpan)) { return string.Format("{0:hh\\:mm}", value); }
return value.ToString(); } /// <summary>
/// 新增表格
/// </summary>
/// <param name="numColumns">最多幾個儲存格</param>
/// <param name="headerRows">固定標題列</param>
/// <returns></returns>
public string GetValue(DataRow row, DataColumn column) { var value = row[column]; if (value == null) { return ""; } // 當有設定欄位時,以欄位為主
var format = column.ExtendedProperties["Format"] as string; if (!string.IsNullOrEmpty(format)) { return string.Format(format, value); }
var type = column.DataType; if (type == typeof(int)) { return string.Format("{0:N0}", value); } else if (type == typeof(double) || type == typeof(decimal)) { return string.Format("{0:0,0.##}", value); } else if (type == typeof(DateTime)) { return string.Format("{0:yyyy/MM/dd HH\\:mm}", value); } else if (type == typeof(TimeSpan)) { return string.Format("{0:hh\\:mm}", value); }
return value.ToString(); } protected float[] GetColumnWidths(DataColumn[] columns) { return columns.Select(x => x.ExtendedProperties.ContainsKey("Width") ? Convert.ToSingle(x.ExtendedProperties["Width"]) : 80f).ToArray(); }
public PdfPTable GeneratePTable(float[] columnWidths, int headerRows = 1) { var table = new PdfPTable(columnWidths.Length) { HeaderRows = headerRows }; table.SetTotalWidth(columnWidths); table.SetWidths(columnWidths);
table.LockedWidth = true;
return table; }
public PdfPCell GeneratePCell(string text, int rowspan = 1, int colspan = 1, int align = Element.ALIGN_LEFT, int verticalAlign = Element.ALIGN_MIDDLE) { return new PdfPCell(new Phrase(text, _rcoOption.NormalFont)) { PaddingBottom = 5, HorizontalAlignment = align, VerticalAlignment = verticalAlign, Rowspan = rowspan, Colspan = colspan }; } } }
|