using System; using System.Collections.Generic; using System.Text; using VEPROMS.CSLA.Library; using iTextSharp.text.pdf; using iTextSharp.text; using System.IO; using VEPROMS.CSLA.Library; using System.Text.RegularExpressions; //using Volian.Generic; namespace Volian.Print.Library { public class PDFReport { private ICollection _ResultList; public ICollection ResultList { get { return _ResultList; } set { _ResultList = value; } } private string _FileName; public string FileName { get { return _FileName; } set { _FileName = value; } } private string _ReportTitle; public string ReportTitle { get { return _ReportTitle; } set { _ReportTitle = value; } } private bool _ShowAnnotations = true; public bool ShowAnnotations { get { return _ShowAnnotations; } set { _ShowAnnotations = value; } } private string _SearchString; public string SearchString { get { return _SearchString; } set { _SearchString = VEPROMS.CSLA.Library.ItemInfo.ConvertToDisplayText(value); } } public PDFReport(string reportTitle, ICollection resultList, string fileName) { _ResultList = resultList; _FileName = fileName; _ReportTitle = VEPROMS.CSLA.Library.ItemInfo.ConvertToDisplayText(reportTitle); } public void Build2() { iTextSharp.text.Document document = new iTextSharp.text.Document(PageSize.LETTER, 36, 36, 36, 36); try { PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(_FileName, FileMode.Create)); // we add some meta information to the document document.SetMargins(36, 36, 36, 36); // step 3: we open the document document.Open(); AddTable(document, 20, 80); //AddTable(document, 10, 90); //AddTable(document, 10, 100); //AddTable(document, 15, 75); //AddTable(document, 20, 70); //AddTable(document, 25, 65); //AddTable(document, 30, 60); document.Close(); } catch (Exception ex) { } } private void AddTable(iTextSharp.text.Document document, int width1, int width2) { float[] headerwidths = { width1, width2 }; PdfPTable datatable = new PdfPTable(headerwidths); datatable.HeaderRows = 3; datatable.FooterRows = 1; //datatable.Padding = 4; //datatable.DefaultCell.Padding = 4; //datatable.Spacing = 0; //datatable.setBorder(Rectangle.NO_BORDER); //datatable.Widths = headerwidths; //datatable.WidthPercentage = 100; datatable.TotalWidth = (width1 + width2) * 5; datatable.LockedWidth = true; // the first cell spans 10 columns //iTextSharp.text.Font f1 = FontFactory.GetFont("Arial Unicode MS", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 14, Font.BOLD); iTextSharp.text.Font f1 = pdf.GetFont("Arial Unicode MS", 14, 1, Color.BLACK); PdfPCell cell = new PdfPCell(new Phrase(ReportTitle, f1)); //Font f2 = FontFactory.GetFont(FontFactory.HELVETICA, 10); //FontFactory.RegisterDirectory(FontFind.FontDir); //iTextSharp.text.Font f2 = FontFactory.GetFont("Arial Unicode MS", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 10); iTextSharp.text.Font f2 = pdf.GetFont("Arial Unicode MS", 10, 0, Color.BLACK); //iTextSharp.text.Font f3 = FontFactory.GetFont("Prestige Elite Tall", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 9); iTextSharp.text.Font f3 = pdf.GetFont("Prestige Elite Tall", 9, 0, Color.BLACK); cell.HorizontalAlignment = Element.ALIGN_CENTER; //cell.Leading = 20; cell.Colspan = 2; //cell.Border = Rectangle.NO_BORDER; cell.BackgroundColor = new Color(0xD0, 0xF0, 0xF0); datatable.AddCell(cell); Color subHeaderColor = new Color(0xD0, 0xF0, 0xD0); // These cells span 2 rows //datatable.DefaultCellBorderWidth = 2; //datatable.DefaultHorizontalAlignment = 1; //datatable.DefaultRowspan = 2; datatable.DefaultCell.Padding = 4; datatable.DefaultCell.HorizontalAlignment = Element.ALIGN_CENTER; AddCell(datatable, "Step", f2, subHeaderColor); AddCell(datatable, "Text", f2, subHeaderColor); AddCell(datatable, "Step", f2, subHeaderColor); AddCell(datatable, "Text", f2, subHeaderColor); datatable.DefaultCell.HorizontalAlignment = Element.ALIGN_LEFT; //datatable.DefaultCellBorderWidth = 1; //datatable.DefaultRowspan = 1; //datatable.DefaultHorizontalAlignment = Element.ALIGN_LEFT; string lastDvPath = ""; string lastPath = ""; Color AnnoColor = new Color(0xFF, 0xFF, 0xC0); Color TextColor = Color.WHITE; Color SectColor = Color.LIGHT_GRAY; foreach (ItemInfo item in _ResultList) { if (item.SearchDVPath != lastDvPath) AddGroup(datatable, item.SearchDVPath, lastDvPath, f2, false, new Color(0xC0, 0xFF, 0xC0)); lastDvPath = item.SearchDVPath; //if (item.SearchPath != lastPath) string stepPath = AddGroup(datatable, item.SearchPath, lastPath, f2, true, new Color(0xE0, 0xFF, 0xE0)); lastPath = item.SearchPath; AddCell(datatable, stepPath, f2, (item.IsSection ? SectColor : TextColor)); if (item.DisplayText.Contains("|")) // Need a better way to determine if it is a table. AddCell(datatable, item.DisplayText, f3, TextColor); else AddCell(datatable, item.DisplayText, f2, (item.IsSection ? SectColor : TextColor)); if (item.ItemAnnotationCount > 0) { foreach (AnnotationInfo ai in item.ItemAnnotations) { AddCell(datatable, ai.MyAnnotationType.Name, f2, AnnoColor); AddCell(datatable, ai.SearchText, f2, AnnoColor); } } } document.Add(datatable); } //private static void AddCell(PdfPTable datatable, string str, iTextSharp.text.Font fnt, Color bgColor) //{ // PdfPCell cell = new PdfPCell(new Phrase(str, fnt)); // cell.BackgroundColor = bgColor; // datatable.AddCell(cell); //} private string AddGroup(PdfPTable datatable, string dvPath, string lastDvPath, Font f2, bool StripLast, Color bgColor) { int level = 0; string retval = ""; StringBuilder sb = new StringBuilder(); string ttt = dvPath.Replace("\x11", " "); string[] OldPath = lastDvPath.Split("\x7".ToCharArray()); string[] NewPath = dvPath.Split("\x7".ToCharArray()); string sep = ""; bool foundMisMatch = false; int n = NewPath.Length; if (StripLast) { retval = NewPath[--n]; if (retval.Contains("\x11")) retval = retval.Substring(0, retval.IndexOf("\x11")); } for (int j = 0; j < n; j++) { if (NewPath[j] != "" && (foundMisMatch || OldPath.Length < j + 1 || NewPath[j] != OldPath[j])) { sb.Append(sep + "".PadLeft(2 * level) + NewPath[j].Replace("\x11", " ")).Replace(@"\u8209?", "-"); sep = "\r\n"; foundMisMatch = true; } level++; } if (sb.ToString() != "") { PdfPCell cell = new PdfPCell(new Phrase(sb.ToString(), f2)); cell.Colspan = 2; cell.BackgroundColor = bgColor; cell.BorderWidthTop = 1; datatable.AddCell(cell); } return retval; } public void Build() { iTextSharp.text.Document document = new iTextSharp.text.Document(PageSize.LETTER, 36, 36, 36, 36); if (!CreateResultsPDF(document)) return; try { BuildTable1(document); } catch (Exception ex) { StringBuilder msg = new StringBuilder(); document.Add(new Paragraph("Error:")); while (ex != null) { document.Add(new Paragraph(ex.GetType().Name)); document.Add(new Paragraph(ex.Message)); ex = ex.InnerException; } } finally { if (document.IsOpen()) { document.Close(); System.Diagnostics.Process.Start(_FileName); } } } /// /// Attempt to open a file for the PDF output. /// If the file cannot be opened because it is in use, try adding a suffix /// If the file cannot be opened for some other reason, display an error message /// /// /// private bool CreateResultsPDF(iTextSharp.text.Document document) { bool result = false; string suffix = ""; int i = 0; // Try to open a file for creating the PDF. while (result == false) { string fileName = _FileName.ToLower().Replace(".pdf", suffix + ".pdf"); try { PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(fileName, FileMode.Create)); document.SetMargins(36, 36, 36, 36); document.Open(); _FileName = fileName; result = true; } catch (System.IO.IOException exIO) { if (exIO.Message.Contains("because it is being used by another process")) suffix = string.Format("_{0}", ++i);// If this file is in use, increment the suffix and try again else // If some other error, display a message and don't print the results { ShowException(exIO); return false; } } catch (Exception ex) { ShowException(ex); return false; // Could not open the output file } } return true; } private static void ShowException(Exception ex) { Console.WriteLine("{0} - {1}", ex.GetType().Name, ex.Message); StringBuilder msg = new StringBuilder(); string sep = ""; string indent = ""; while (ex != null) { msg.Append(string.Format("{0}{1}{2}:\r\n{1}{3}", sep, indent, ex.GetType().Name, ex.Message)); ex = ex.InnerException; sep = "\r\n"; indent += " "; } System.Windows.Forms.MessageBox.Show(msg.ToString(), "Error during PDF creation for search:", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation); } /// /// Use Cells within Cells to see if I can limit the way Cells break from Page to Page /// /// private void BuildTable1(iTextSharp.text.Document document) { float[] headerwidths = { 20, 80 }; PdfPTable datatable = new PdfPTable(headerwidths); datatable.HeaderRows = 3; datatable.FooterRows = 1; datatable.TotalWidth = document.PageSize.Width - document.LeftMargin - document.RightMargin; datatable.LockedWidth = true; //FontFactory.RegisterDirectory(FontFind.FontDir); //iTextSharp.text.Font f1 = FontFactory.GetFont("Arial Unicode MS", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 14, Font.BOLD); //iTextSharp.text.Font f2 = FontFactory.GetFont("Arial Unicode MS", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 10); //iTextSharp.text.Font f3 = FontFactory.GetFont("Prestige Elite Tall", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 9); iTextSharp.text.Font f1 = pdf.GetFont("Arial Unicode MS", 14, 1, Color.BLACK); iTextSharp.text.Font f2 = pdf.GetFont("Arial Unicode MS", 10, 0, Color.BLACK); iTextSharp.text.Font f3 = pdf.GetFont("Prestige Elite Tall", 9, 0, Color.BLACK); PdfPCell cell = new PdfPCell(new Phrase(ReportTitle, f1)); cell.HorizontalAlignment = Element.ALIGN_CENTER; cell.Colspan = 2; cell.BackgroundColor = new Color(0xD0, 0xF0, 0xF0); datatable.AddCell(cell); Color subHeaderColor = new Color(0xD0, 0xF0, 0xD0); datatable.DefaultCell.Padding = 4; datatable.DefaultCell.HorizontalAlignment = Element.ALIGN_CENTER; AddCell(datatable, "Step", f2, subHeaderColor); AddCell(datatable, "Text", f2, subHeaderColor); AddCell(datatable, "Step", f2, subHeaderColor); AddCell(datatable, "Text", f2, subHeaderColor); datatable.DefaultCell.HorizontalAlignment = Element.ALIGN_LEFT; string lastDvPath = ""; string lastPath = ""; Color AnnoColor = new Color(0xFF, 0xFF, 0xC0); Color TextColor = Color.WHITE; Color SectColor = Color.LIGHT_GRAY; foreach (ItemInfo item in _ResultList) { if (item.SearchDVPath != lastDvPath) AddGroup(datatable, item.SearchDVPath, lastDvPath, f2, false, new Color(0xC0, 0xFF, 0xC0)); lastDvPath = item.SearchDVPath; string stepPath = AddGroup(datatable, item.SearchPath, lastPath, f2, true, new Color(0xE0, 0xFF, 0xE0)); lastPath = item.SearchPath; AddCell(datatable, stepPath, f2, (item.IsSection ? SectColor : TextColor)); if (item.DisplayText.Contains("|")) // Need a better way to determine if it is a table. AddCell(datatable, item.DisplayText, f3, TextColor); else AddCell(datatable, item.DisplayText, f2, (item.IsSection ? SectColor : TextColor)); if (item.ItemAnnotationCount > 0) { foreach (AnnotationInfo ai in item.ItemAnnotations) { AddCell(datatable, ai.MyAnnotationType.Name, f2, AnnoColor); AddCell(datatable, ai.SearchText, f2, AnnoColor); } } } document.Add(datatable); } private void AddCell(PdfPTable datatable, string str, iTextSharp.text.Font fnt, Color bgColor) { iTextSharp.text.Font fntBold = new Font(fnt.BaseFont, fnt.Size, Font.BOLD, Color.RED); Phrase p = BuildPhrase2(str, fnt, fntBold); PdfPCell cell = new PdfPCell(p); cell.PaddingBottom = 4; cell.BackgroundColor = bgColor; datatable.AddCell(cell); } private Phrase BuildPhrase(string str, Font fnt, Font fntBold) { Phrase p = new Phrase(); if (_SearchString != null) { while (str.ToLower().Contains(_SearchString.ToLower())) { int iStart = str.ToLower().IndexOf(_SearchString.ToLower()); if (iStart > 0) p.Add(new Phrase(str.Substring(0, iStart), fnt)); Phrase p2 = new Phrase(str.Substring(iStart, _SearchString.Length), fntBold); p.Add(p2); str = str.Substring(iStart + _SearchString.Length); } } if (str.Length > 0) p.Add(new Phrase(str, fnt)); return p; } private string _RegexSearchString = null; private string RegexSearchString { get { if (_RegexSearchString == null) { _RegexSearchString = _SearchString; if (_RegexSearchString[0] == '%') _RegexSearchString = _RegexSearchString.Substring(1); if (_RegexSearchString[_RegexSearchString.Length - 1] == '%') _RegexSearchString = _RegexSearchString.Substring(0, _RegexSearchString.Length - 1); _RegexSearchString = _RegexSearchString.Replace("%", ".*"); } return _RegexSearchString; } } private Phrase BuildPhrase2(string str, Font fnt, Font fntBold) { Phrase p = new Phrase(); int lastIndex = 0; if ((_SearchString ?? "") != "") { Regex reg = new Regex(RegexSearchString, RegexOptions.Multiline | RegexOptions.IgnoreCase); foreach (Match m in reg.Matches(str)) { if (m.Index > 0) p.Add(new Phrase(str.Substring(lastIndex, m.Index - lastIndex), fnt)); Chunk chk = new Chunk(m.Value, fnt); //Phrase p2 = new Phrase(); //foreach (Chunk chk in p2.Chunks) chk.SetBackground(Color.YELLOW); p.Add(chk); lastIndex = m.Index + m.Length; } } p.Add(new Phrase(str.Substring(lastIndex), fnt)); return p; } } }