Files
SourceCode/PROMS/Volian.Print.Library/PDFTransitionReport.cs
T

513 lines
17 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using VEPROMS.CSLA.Library;
using iTextSharp.text.pdf;
using iTextSharp.text;
using System.IO;
using System.Linq;
namespace Volian.Print.Library
{
public delegate void TransitionReportEvent(object sender, EventArgs args);
public class PDFTransitionReport
{
public event TransitionReportEvent TransitionProcessed;
private void OnTransitionProcessed(object sender, EventArgs args) => TransitionProcessed?.Invoke(sender, args);
public event TransitionReportEvent ProcedureProcessed;
private void OnProcedureProcessed(object sender, EventArgs args) => ProcedureProcessed?.Invoke(sender, args);
public event TransitionReportEvent DocVersionProcessed;
private void OnDocVersionProcessed(object sender, EventArgs args) => DocVersionProcessed?.Invoke(sender, args);
public string FileName { get; set; }
private PdfPCell _CurrentPageNumberCell = null;
private int _CurrentPageNumber = 1;
public int CurrentPageNumber
{
get
{
return _CurrentPageNumber;
}
set
{
if (_CurrentPageNumberCell != null)
{
_CurrentPageNumber = value;
_CurrentPageNumberCell.Phrase.Clear();
_CurrentPageNumberCell.Phrase.Add("Page " + value.ToString());
}
}
}
private readonly FolderInfo folderInfo;
private ProcedureInfo procedureInfo;
private TransitionInfoList transitionInfoList;
public int TransitionInfoCount { get; set; }
public List<DocVersionInfo> MyDocVersionList { get; set; }
public int ProcedureCount { get; set; }
private readonly string _PaperSize = "Letter";
public PDFTransitionReport(FolderInfo fi, string fileName)
{
FileName = fileName;
folderInfo = fi;
if (fi.ActiveFormat != null)
_PaperSize = fi.ActiveFormat.PlantFormat.FormatData.PDFPageSize.PaperSize; // C2020-002 paper size is now set in the format files
}
public PDFTransitionReport(ProcedureInfo pi, string fileName)
{
FileName = fileName;
procedureInfo = pi;
transitionInfoList = TransitionInfoList.GetTransitionReportData(procedureInfo.MyDocVersion.VersionID, procedureInfo.ItemID);
TransitionInfoCount = transitionInfoList.Count;
_PaperSize = pi.ActiveFormat.PlantFormat.FormatData.PDFPageSize.PaperSize; // C2020-002 paper size is now set in the format files
}
public void BuildTransitionReport()
{
Rectangle paperSize = PDFPageSize.UsePaperSize(_PaperSize); // C2020-002 paper size is now set in the format files
iTextSharp.text.Document document = new iTextSharp.text.Document(paperSize.Rotate(), 36, 36, 36, 36);
if (!CreateResultsPDF(document)) return;
try
{
if (folderInfo != null)
{
if (MyDocVersionList.Count == 1)
{
DocVersionInfo dvi = MyDocVersionList[0];
foreach (ProcedureInfo pi in dvi.Procedures.OfType<ProcedureInfo>())
{
procedureInfo = pi;
transitionInfoList = TransitionInfoList.GetTransitionReportData(dvi.VersionID, procedureInfo.ItemID);
if (transitionInfoList.Count > 0)
{
TransitionInfoCount = transitionInfoList.Count;
OnProcedureProcessed(this, new EventArgs());
BuildProcedureReport(document);
}
else
{
OnProcedureProcessed(this, new EventArgs());
}
}
}
else
{
foreach (DocVersionInfo dvi in MyDocVersionList)
{
ProcedureCount = dvi.Procedures.Count;
OnDocVersionProcessed(this, new EventArgs());
foreach (ProcedureInfo pi in dvi.Procedures.OfType<ProcedureInfo>())
{
procedureInfo = pi;
transitionInfoList = TransitionInfoList.GetTransitionReportData(dvi.VersionID, procedureInfo.ItemID);
TransitionInfoCount = transitionInfoList.Count;
OnProcedureProcessed(this, new EventArgs());
BuildProcedureReport(document);
}
}
}
}
else
{
BuildProcedureReport(document);
}
}
catch (Exception ex)
{
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);
}
}
}
PdfOutline outline = null;
ProcedureInfo lastProcedureInfo = null;
private PdfPTable BuildProcedurePDFTable(Dictionary<int, string> levels, Dictionary<int, iTextSharp.text.Font> fonts, int cols, int paddingBottom, int level)
{
PdfPTable t = new PdfPTable(cols)
{
HeaderRows = 4
};
t.DefaultCell.Padding = 4;
t.WidthPercentage = 100;
float[] widths;
if(level == 1 || level == 2 || level == 4)
widths = new float[] { 20f, 47f, 33f };
else
widths = new float[] { 33f, 47f, 20f };
t.SetWidths(widths);
//report title
Phrase h = new Phrase
{
Font = fonts[1]
};
if (folderInfo != null)
h.Add(string.Format("Procedure Set {0} Transition Report", folderInfo.Name));
else
h.Add("Transition Report");
PdfPCell c = new PdfPCell(h)
{
Colspan = cols - 1,
HorizontalAlignment = Element.ALIGN_LEFT,
PaddingBottom = paddingBottom,
BackgroundColor = new Color(System.Drawing.Color.DarkGoldenrod)
};
t.AddCell(c);
//date generated
h = new Phrase
{
Font = fonts[4]
};
h.Add(DateTime.Now.ToString("dddd MMMM d, yyyy @ h:mm tt"));
c = new PdfPCell(h)
{
HorizontalAlignment = Element.ALIGN_RIGHT,
PaddingBottom = paddingBottom,
BackgroundColor = new Color(System.Drawing.Color.DarkGoldenrod)
};
t.AddCell(c);
//procedure title
h = new Phrase
{
Font = fonts[2]
};
h.Add(string.Format("{0} - {1}", procedureInfo.DisplayNumber, procedureInfo.DisplayText));
PdfDestination dest = new PdfDestination(PdfDestination.FITH, cb.PdfDocument.PageSize.Height);
if (lastProcedureInfo != procedureInfo)
{
outline = new PdfOutline(cb.RootOutline, dest, procedureInfo.DisplayNumber, false);
lastProcedureInfo = procedureInfo;
}
c = new PdfPCell(h)
{
Colspan = cols - 1,
HorizontalAlignment = Element.ALIGN_LEFT,
PaddingBottom = paddingBottom,
BackgroundColor = new Color(System.Drawing.Color.Goldenrod)
};
t.AddCell(c);
//page number
_CurrentPageNumberCell = BuildCell(1, string.Format("Page {0}",CurrentPageNumber), fonts[4], new Color(System.Drawing.Color.Goldenrod));
_CurrentPageNumberCell.PaddingBottom = paddingBottom;
t.AddCell(_CurrentPageNumberCell);
//transition category
h = new Phrase
{
Font = fonts[3]
};
if (transitionInfoList.Count == 0)
h.Add("N/A");
else
{
h.Add(levels[level]);
dest = new PdfDestination(PdfDestination.FITH, cb.PdfDocument.PageSize.Height);
new PdfOutline(outline, dest, levels[level]);
}
c = new PdfPCell(h)
{
Colspan = cols,
HorizontalAlignment = Element.ALIGN_LEFT,
PaddingBottom = paddingBottom,
BackgroundColor = new Color(System.Drawing.Color.Khaki)
};
t.AddCell(c);
//add column headers
h = new Phrase
{
Font = fonts[4]
};
h.Add("From Procedure Location");
c = new PdfPCell(h)
{
HorizontalAlignment = Element.ALIGN_CENTER,
PaddingBottom = paddingBottom,
BackgroundColor = new Color(System.Drawing.Color.PaleGoldenrod)
};
t.AddCell(c);
h = new Phrase
{
Font = fonts[4]
};
h.Add("From Procedure Text");
c = new PdfPCell(h)
{
HorizontalAlignment = Element.ALIGN_CENTER,
PaddingBottom = paddingBottom,
BackgroundColor = new Color(System.Drawing.Color.PaleGoldenrod)
};
t.AddCell(c);
h = new Phrase
{
Font = fonts[4]
};
h.Add("To Procedure Location");
c = new PdfPCell(h)
{
HorizontalAlignment = Element.ALIGN_CENTER,
PaddingBottom = paddingBottom,
BackgroundColor = new Color(System.Drawing.Color.PaleGoldenrod)
};
t.AddCell(c);
return t;
}
PdfContentByte cb;
private void BuildProcedureReport(iTextSharp.text.Document doc)
{
Dictionary<int, string> tranTypes = FormatInfo.GetTransitionTypesByFormatID(procedureInfo.ActiveFormat.FormatID);
Dictionary<int, string> levels = new Dictionary<int, string>
{
{ 1, "Internal Transitions" },
{ 2, "External From Transitions" },
{ 3, "External To Transitions" },
{ 4, "Outside From Transitions" },
{ 5, "Outside To Transitions" }
};
Dictionary<int, iTextSharp.text.Font> fonts = new Dictionary<int, Font>
{
// C2017-036 get best available proportional font for symbols that looks close to Arial
// Note that Microsoft no longer supplies Arial Unicode MS as of Word16
{ 1, pdf.GetFont(Volian.Base.Library.vlnFont.ReportsFont, 12, 0, Color.BLACK) },
{ 2, pdf.GetFont(Volian.Base.Library.vlnFont.ReportsFont, 10, 0, Color.BLACK) },
{ 3, pdf.GetFont(Volian.Base.Library.vlnFont.ReportsFont, 8, 0, Color.BLACK) },
{ 4, pdf.GetFont(Volian.Base.Library.vlnFont.ReportsFont, 8, 0, Color.BLACK) }
};
int lastLevel = transitionInfoList.Count > 0 ? transitionInfoList[0].Level : 0; //set level to first transition level
#region buildtable
int cols = 3;
int paddingBottom = 6;
if (folderInfo != null)
doc.NewPage();
PdfPTable t = BuildProcedurePDFTable(levels, fonts, cols, paddingBottom, lastLevel);
#endregion
//gather data
if (transitionInfoList.Count == 0)
{
Phrase h = new Phrase
{
Font = fonts[4]
};
h.Add("This procedure contains no transitions");
PdfPCell c = new PdfPCell(h)
{
Colspan = cols,
HorizontalAlignment = Element.ALIGN_LEFT,
PaddingBottom = paddingBottom
};
t.AddCell(c);
}
else
{
foreach (TransitionInfo ti in transitionInfoList)
{
//add category
OnTransitionProcessed(this, new EventArgs());
if (ti.Level != lastLevel)
{
if (lastLevel > 0)
{
doc.Add(t);
doc.NewPage();
lastLevel = ti.Level;
t = BuildProcedurePDFTable(levels, fonts, cols, paddingBottom, lastLevel);
}
}
//add from path
Phrase h = new Phrase
{
Font = fonts[4]
};
h.Add(StripProcInfo(ti.PathFrom, procedureInfo));
PdfPCell c = new PdfPCell(h)
{
HorizontalAlignment = Element.ALIGN_LEFT,
PaddingBottom = paddingBottom
};
if (lastLevel > 1 && (!tranTypes[ti.TranType].Contains("{Proc") && !tranTypes[ti.TranType].Contains("other procedure"))) c.BackgroundColor = new Color(System.Drawing.Color.LightCoral);
t.AddCell(c);
//add from text
h = new Phrase
{
Font = fonts[4]
};
ItemInfo myItemInfo = ti.MyContent.ContentItems[0];
h.Add(GetTextPath(myItemInfo, 0));
c = new PdfPCell(h)
{
HorizontalAlignment = Element.ALIGN_LEFT,
PaddingBottom = paddingBottom
};
if (lastLevel > 1 && (!tranTypes[ti.TranType].Contains("{Proc") && !tranTypes[ti.TranType].Contains("other procedure"))) c.BackgroundColor = new Color(System.Drawing.Color.LightCoral);
t.AddCell(c);
//add to text
h = new Phrase
{
Font = fonts[4]
};
myItemInfo = ti.MyItemToID;
h.Add(GetTextPath(myItemInfo, ti.Level));
c = new PdfPCell(h)
{
HorizontalAlignment = Element.ALIGN_LEFT,
PaddingBottom = paddingBottom
};
if (lastLevel > 1 && (!tranTypes[ti.TranType].Contains("{Proc") && !tranTypes[ti.TranType].Contains("other procedure"))) c.BackgroundColor = new Color(System.Drawing.Color.LightCoral);
t.AddCell(c);
}
}
doc.Add(t);
}
private string StripProcInfo(string pathfrom, ProcedureInfo procedureInfo)
{
if (pathfrom.StartsWith(procedureInfo.DisplayNumber))
return pathfrom.Replace(string.Format("{0}, {1}", procedureInfo.DisplayNumber, procedureInfo.DisplayText), "").Trim();
else
return pathfrom;
}
private string GetTextPath(ItemInfo myItemInfo, int level)
{
StringBuilder sb = new StringBuilder();
if (myItemInfo.IsProcedure)
return $"{myItemInfo.MyProcedure.DisplayNumber} {myItemInfo.MyProcedure.DisplayText}";
if (myItemInfo.IsSection)
{
if (level > 1)
return $"{myItemInfo.MyProcedure.DisplayNumber} {myItemInfo.MyProcedure.DisplayText}\r\n {myItemInfo.DisplayText}";
else
return myItemInfo.DisplayText;
}
if (myItemInfo.IsHigh)
return $"{myItemInfo.ActiveSection.DisplayText}\r\n {myItemInfo.DisplayText}";
else
{
string tmp = "";
return GetTextPath(myItemInfo, sb, ref tmp);
}
}
private string GetTextPath(ItemInfo myItemInfo, StringBuilder sb, ref string indent)
{
if (myItemInfo == null)
return sb.ToString();
if (myItemInfo.IsHigh)
{
sb.Append(myItemInfo.DisplayText);
}
else
{
if (myItemInfo.ActiveParent != null)
{
GetTextPath(myItemInfo.ActiveParent as ItemInfo, sb, ref indent);
indent += " ";
sb.Append("\r\n" + indent + myItemInfo.DisplayText);
}
}
return sb.ToString();
}
private bool CreateResultsPDF(iTextSharp.text.Document document)
{
bool result = false;
string suffix = "";
int i = 0;
// just for safety, the while loop expects to find a file extension
// so make sure it has one before going into the loop
if (!FileName.ToUpper().EndsWith(".PDF"))
FileName += ".pdf";
// Try to open a file for creating the PDF.
while (result == false)
{
string fileName = FileName;
int loc = fileName.LastIndexOf(".");
if (loc > -1)
{
string fname = fileName.Substring(0, loc);
fileName = $"{fname}{suffix}.pdf";
}
else
fileName = $"{fileName}{suffix}.pdf";
try
{
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(fileName, FileMode.Create));
writer.PageEvent = new MyPageEvent(this);
document.SetMargins(36, 36, 36, 36);
document.Open();
cb = writer.DirectContent;
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);
}
private PdfPCell BuildCell(int colspan, string txt, Font f, iTextSharp.text.Color clr)
{
Phrase h = new Phrase
{
Font = f
};
h.Add(txt);
PdfPCell c = new PdfPCell(h)
{
HorizontalAlignment = iTextSharp.text.Element.ALIGN_RIGHT,
Colspan = colspan,
BackgroundColor = clr
};
return c;
}
}
public class MyPageEvent : PdfPageEventHelper
{
private readonly PDFTransitionReport _rpt = null;
public MyPageEvent(PDFTransitionReport rpt)
{
_rpt = rpt;
}
public override void OnEndPage(PdfWriter writer, iTextSharp.text.Document document)
{
base.OnEndPage(writer, document);
_rpt.CurrentPageNumber = writer.PageNumber + 1;
}
}
}