using System; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; using System.IO; using iTextSharp.text.pdf; using iTextSharp.text; using VEPROMS.CSLA.Library; using Volian.Base.Library; namespace Volian.Print.Library { class CompleteROReport { Headers Hdrs; // Header stack object. RODataFile RO_df = null; int curheaderlen; string RODataFileName; iTextSharp.text.Document pdfReportDoc = null; PdfPTable datatable = null; private iTextSharp.text.Font _f14; // = pdf.GetFont("Arial Unicode MS", 14, 1, Color.BLACK); public iTextSharp.text.Font F14 { get { return _f14; } set { _f14 = value; } } private iTextSharp.text.Font _f10; public iTextSharp.text.Font F10 { get { return _f10; } set { _f10 = value; } } private iTextSharp.text.Font _f12; public iTextSharp.text.Font F12 { get { return _f12; } set { _f12 = value; } } private iTextSharp.text.Font _f10Bold; public iTextSharp.text.Font F10Bold { get { return _f10Bold; } set { _f10Bold = value; } } private iTextSharp.text.Font _f12Bold; public iTextSharp.text.Font F12Bold { get { return _f12Bold; } set { _f12Bold = value; } } private bool _ConvertCaretToDelta = true; public bool ConvertCaretToDelta { get { return _ConvertCaretToDelta; } set { _ConvertCaretToDelta = value; } } private bool _IncludeEmptyROFields = false; public bool IncludeEmptyROFields { get { return _IncludeEmptyROFields; } set { _IncludeEmptyROFields = value; } } private int _ROFstID; public int ROFstID { get { return _ROFstID; } set { _ROFstID = value; } } private string ReportTitle = "Complete Referenced Objects Report"; private PdfWriter _MyPDFWriter; public CompleteROReport(PdfWriter mypdfwriter, iTextSharp.text.Document document, string dataFileName, bool convertCaretToDelta, bool includeEmptyROFields) { Hdrs = new Headers(); pdfReportDoc = document; RODataFileName = dataFileName; _ConvertCaretToDelta = convertCaretToDelta; _MyPDFWriter = mypdfwriter; _IncludeEmptyROFields = includeEmptyROFields; } public void StartNewDataTable() { datatable = new PdfPTable(1); datatable.TotalWidth = pdfReportDoc.PageSize.Width - pdfReportDoc.LeftMargin - pdfReportDoc.RightMargin; datatable.LockedWidth = true; PdfPCell cell = new PdfPCell(new Phrase(ReportTitle, F14)); cell.HorizontalAlignment = Element.ALIGN_CENTER; cell.BackgroundColor = Color.WHITE; cell.BorderColor = Color.WHITE; datatable.AddCell(cell); datatable.HeaderRows = 3; datatable.DefaultCell.HorizontalAlignment = Element.ALIGN_LEFT; } public void Run() { StartNewDataTable(); RO_df = new RODataFile(RODataFileName); PrintReport(); RO_df.close(); } private Dictionary _MyDocOutline = new Dictionary(); internal Dictionary MyDocOutline { get { return _MyDocOutline; } set { _MyDocOutline = value; } } public class DocOutline { private PdfOutline _MyOutline; public PdfOutline MyOutline { get { return _MyOutline; } set { _MyOutline = value; } } private string _MyHeader; public string MyHeader { get { return _MyHeader; } set { _MyHeader = value; } } public DocOutline(PdfOutline outline, string header) { _MyHeader = header; _MyOutline = outline; } } private string ReplaceLineDrawCharsWithUnicode(string text) { text = text.Replace("\xc4", "\x2500"); // Horizontal text = text.Replace("\xb3", "\x2502"); // Vertical text = text.Replace("\xc0", "\x2514"); // Bottom Left Corner text = text.Replace("\xd9", "\x2518"); // Bottom Right Corner text = text.Replace("\xc1", "\x2534"); // Bottom Tee text = text.Replace("\xda", "\x250c"); // Upper Left Corner text = text.Replace("\xc3", "\x251c"); // Left Tee text = text.Replace("\xbf", "\x2510"); // Upper Right Corner text = text.Replace("\xc2", "\x252c"); // Top Tee text = text.Replace("\xb4", "\x2524"); // Right Tee text = text.Replace("\xc5", "\x253c"); // Plus return text; } public Phrase ConvertDOSSuperAndSubScripts(string instr, Font fnt) { int idx = 0; Chunk chk; Phrase p = new Phrase(); instr = instr.Replace("`", "\u00B0"); //degree if (ConvertCaretToDelta) instr = instr.Replace("^", "\u0394"); // delta instr = ReplaceLineDrawCharsWithUnicode(instr); // Handle super/sub scripts MatchCollection mc = Regex.Matches(instr, "[#~](.*?)[#~]"); foreach (Match m in mc) { if (idx < m.Index) { int strlen = m.Index - idx; chk = new Chunk(instr.Substring(idx, strlen), fnt); chk.SetTextRise(0); p.Add(chk); } switch (m.Value[0]) { case '#': chk = new Chunk(m.Value.Substring(1, m.Length-2), fnt); chk.SetTextRise(.25F * chk.Font.Size); p.Add(chk); idx = m.Index + m.Length; break; case '~': chk = new Chunk(m.Value.Substring(1, m.Length-2), fnt); chk.SetTextRise(-.25F * chk.Font.Size); p.Add(chk); idx = m.Index + m.Length; break; } } if (idx < instr.Length - 1) { chk = new Chunk(instr.Substring(idx), fnt); chk.SetTextRise(0); p.Add(chk); } return p; } public void AddText(string txt, Font fnt) { // break the text up on double returns (paragraphs) and put each in their own cell // this will allow for page breaks between paragraphs0 string[] delim = { "\r\n\r\n","\r\n \r\n" }; string[] strlst = txt.Split(delim,StringSplitOptions.None); foreach (string str in strlst) { PdfPCell cell = new PdfPCell(ConvertDOSSuperAndSubScripts(str, fnt)); cell.BorderColor = Color.WHITE; datatable.AddCell(cell); } } public void AddImage(string filename) { ROImageInfo roImage = ROImageInfo.GetByROFstID_FileName(_ROFstID, filename); PdfPCell spaceCell = new PdfPCell(); spaceCell.BorderColor = Color.WHITE; datatable.AddCell(spaceCell); if (roImage != null) { ROImageConfig rc = new ROImageConfig(roImage); int size = Convert.ToInt32(rc.Image_Size); iTextSharp.text.Image it_image = iTextSharp.text.Image.GetInstance(ROImageInfo.Decompress(roImage.Content, size)); it_image.ScaleToFit(_MyPDFWriter.DirectContent.PdfDocument.PageSize.Width - 144, _MyPDFWriter.DirectContent.PdfDocument.PageSize.Height - 216); PdfPCell cell = new PdfPCell(it_image); cell.BorderColor = Color.WHITE; datatable.AddCell(cell); } else { PdfPCell messageCell = new PdfPCell(new Phrase(string.Format("Image File {0} is missing.",filename))); messageCell.BorderColor = Color.WHITE; datatable.AddCell(messageCell); } } public void AddXYPlot(string plotlang) { string pngFile = VlnSettings.TemporaryFolder + @"\XYPlot1.png"; plotlang = plotlang.Replace("`", "\xB0"); plotlang = plotlang.Replace("\xF8", "\xB0"); System.Drawing.RectangleF plotRect = MSWordToPDF.CreatePlot(pngFile, plotlang, 600F, MSWordToPDF.FormForPlotGraphics); iTextSharp.text.Image it_image = iTextSharp.text.Image.GetInstance(pngFile); it_image.ScaleToFit(_MyPDFWriter.DirectContent.PdfDocument.PageSize.Width - 144, _MyPDFWriter.DirectContent.PdfDocument.PageSize.Height - 216); PdfPCell spaceCell = new PdfPCell(); spaceCell.BorderColor = Color.WHITE; datatable.AddCell(spaceCell); PdfPCell cell = new PdfPCell(it_image); cell.BorderColor = Color.WHITE; datatable.AddCell(cell); } public void PrintReport() { bool StopPrinting = false; bool UserTerminate = false; Int16 iRecType = 0; if (RO_df.GetFileLength() > 0) { // Loop until either printing is aborted or end of file. while (!StopPrinting && (iRecType = RO_df.ReadInteger16()) != -1) { //Console.WriteLine("Record Type: {0}", iRecType); switch (iRecType) { case 1: // Set Header SetHeader(); break; case 2: // Push Header PushHeader(); break; case 3: // Pop Header PopHeader(); break; case 4: // RRO Begin RROBegin(); break; case 5: // RRO End RROEnd(); break; case 6: // Msg Msg(); break; case 7: KeyField(); break; case 100: // Text Field - sometimes also XY Plot Text(); break; case 101: // Plot Field XYPlot(); break; case 102: // Image Field ImageFile(); break; case 103: // Multi Begin - Display data for setpoints Multiple(); break; case 104: // Multi End break; case 0: // nothing was entered in that field if (_IncludeEmptyROFields) NoInformatEntered(); break; case 255: pdfReportDoc.Add(datatable); pdfReportDoc.NewPage(); StartNewDataTable(); //Console.WriteLine("Record Type: {0} No Operation", iRecType); //Console.WriteLine("----------------------------------------------"); break; default: // Problem //Console.WriteLine("Record Type: {0} Unrecognized record type", iRecType); StopPrinting = true; ; UserTerminate = true; break; }; } } else { StartNewDataTable(); datatable.HeaderRows = 1; AddText("Selected Referenced Object has no data.", F12); } //Console.WriteLine("Record Type: {0}\n** Done **", iRecType); pdfReportDoc.Add(datatable); return; } public void Multiple() { Int16 typ, i, j, nw = 0; string str, sep; string buff = ""; int[] width; LastHeader(); sep = ""; // nw - number of fields nw = RO_df.ReadInteger16(); // allocate space for widths width = new int[nw]; // loop through and load field widths and names for (i = 0; i < nw; i++) { // load width width[i] = RO_df.ReadInteger16(); // load name str = RO_df.ReadText(); // how wide is the header int wtxt = str.Length; buff += sep; buff += str; // if the width is wider than the header output spaces to pad // to specified width if (width[i] > wtxt) { int extra = width[i] - wtxt; while (extra > 0) { buff += " "; extra--; } // otherwise set the width to the width of the header } else { width[i] = wtxt; } // place a vertical bar between fields sep = "|"; } sep = "\n"; buff += "\n"; // place horizonal bars between the header and the values for (i = 0; i < nw; i++) { for (j = 0; j < width[i]; j++) { buff += "-"; } if (i < nw - 1) buff += "|"; } i = 0; // While not the end of multi while ((typ = RO_df.ReadInteger16()) != 104) { if (typ == 0) {// Next row sep = "\n"; // set the separator (between rows) to a newline i = 0; } else {// more for this row // get the data str = RO_df.ReadText(); // if first time output a newline otherwise output a vertical // bar between values buff += sep; // output value if (str != null) buff += str; // set the separator to a vertical bar sep = "|"; if (width[i] > 0) { int jj; jj = width[i] - str.Length; // pad the value to the specified width while (jj > 0) { buff += " "; jj--; } } i++; } } // output the table PutHeaderAndText(buff); //Console.WriteLine("Multiple: {0} ", buff); //Console.WriteLine("----------------------------------------------"); } public void SetHeader() { string pTmp; //Console.WriteLine("Set Header"); // Get the number of header records Int16 iNewCnt = RO_df.ReadInteger16(); //Console.WriteLine("Num Header Records: {0}", iNewCnt); // Loop through the headers int iLoop = 0; for (; iLoop < Hdrs.HdrCnt; iLoop++) { if (iLoop >= iNewCnt) // If the current header index is above the new number // of headers, delete it. Hdrs.strHdrs[iLoop] = null; else { // Otherwise: Int16 iTmpRpt; // Get the repeat count for the header iTmpRpt = RO_df.ReadInteger16(); //Console.WriteLine("repeat count for header: {0}", iTmpRpt); // Get the text of the header pTmp = RO_df.ReadText(); //Console.WriteLine("Header Text: {0}", pTmp); if (!pTmp.Equals(Hdrs.strHdrs[iLoop])) { // if the old header does not equal the new header // delete the old header and create a the one Hdrs.strHdrs[iLoop] = pTmp; Hdrs.repeatCount[iLoop] = iTmpRpt; } else { // Otherwise, delete the temperary header data. pTmp = null; } } } // If there are any other headers left in the file, // load those in as well. for (; iLoop < iNewCnt; iLoop++) { int hdrRptCnt = (int)RO_df.ReadInteger16(); if (Hdrs.repeatCount.Count - 1 < iLoop) Hdrs.repeatCount.Add((int)hdrRptCnt); else Hdrs.repeatCount[iLoop] =hdrRptCnt; pTmp = RO_df.ReadText(); if (Hdrs.strHdrs.Count-1 < iLoop) Hdrs.strHdrs.Add(pTmp); else Hdrs.strHdrs[iLoop] = pTmp; //Console.WriteLine("Value: {0}", Hdrs.repeatCount[iLoop]); //Console.WriteLine("Value Text: {0}", Hdrs.strHdrs[iLoop]); //Console.WriteLine("----------------------------------------------"); } // Set the new header count Hdrs.HdrCnt = iNewCnt; } public void PushHeader() { //if (m_pPrinterOut->Row() > 55) //// m_pPrinterOut->newpage(); //pdfReportDoc.NewPage(); string pTmp = RO_df.ReadText(); curheaderlen = pTmp.Length; //Hdrs.strHdrs[Hdrs.HdrCnt] = pTmp; Hdrs.strHdrs.Add(pTmp); //Hdrs.repeatCount[Hdrs.HdrCnt] = 2; Hdrs.repeatCount.Add(2); Hdrs.HdrCnt++; Hdrs.printedLastHeader = false; //m_pPrinterOut->PushedHeader(Hdrs.strHdrs[Hdrs.HdrCnt-1]); //Console.WriteLine("Push Header"); //Console.WriteLine("Header Text: {0}", pTmp); //Console.WriteLine("----------------------------------------------"); } public void PopHeader() { if (Hdrs.repeatCount[Hdrs.HdrCnt-1] == 2) { // if the last header was pushed on header list // print eject the page if the page ran out, and // print the header with "none". //if (m_pPrinterOut->Row() > 55) // m_pPrinterOut->NewPage(); LastHeader(); //m_pPrinterOut->PutLine(0, "none"); //m_pPrinterOut->NewLine(1); } // Remove the header Hdrs.HdrCnt--; //Hdrs.strHdrs[Hdrs.HdrCnt] = null; Hdrs.strHdrs.RemoveAt(Hdrs.HdrCnt); Hdrs.repeatCount.RemoveAt(Hdrs.HdrCnt); //Console.WriteLine("Pop Header"); //Console.WriteLine("----------------------------------------------"); } public void RROBegin() { //m_pPrinterOut->NewPage(); //Console.WriteLine("RRO Begin"); //Console.WriteLine("----------------------------------------------"); // Start of a new RO, print out the headers for (int iLoop = 0; iLoop < Hdrs.HdrCnt; iLoop++) { if (!MyDocOutline.ContainsKey(iLoop) || MyDocOutline[iLoop].MyHeader != Hdrs.strHdrs[iLoop]) { PdfOutline parentOutline = null; if (iLoop == 0) parentOutline = _MyPDFWriter.DirectContent.RootOutline; else parentOutline = MyDocOutline[iLoop - 1].MyOutline; PdfDestination pdfDest = new PdfDestination(PdfDestination.FITH, _MyPDFWriter.DirectContent.PdfDocument.PageSize.Height); AddOutlineLevel(parentOutline, iLoop, Hdrs.strHdrs[iLoop], pdfDest); } AddText(Hdrs.strHdrs[iLoop], F12Bold); // should be bold and first header is centered } } private void AddOutlineLevel(PdfOutline parentOutline, int iLoop, string hdr, PdfDestination pdfDest) { if (MyDocOutline.ContainsKey(iLoop)) MyDocOutline[iLoop] = new DocOutline(new PdfOutline(parentOutline, pdfDest, hdr), hdr); else MyDocOutline.Add(iLoop,new DocOutline(new PdfOutline(parentOutline, pdfDest, hdr), hdr)); } public void RROEnd() { //m_pPrinterOut->PageEnd(); // Remove any headers that are left over //Console.WriteLine("{0} headers cleaned up.", Hdrs.HdrCnt); //Console.WriteLine("RRO End"); //Console.WriteLine("----------------------------------------------"); } public void Msg() { // Set a message to the printer on its own string szStr = RO_df.ReadText(); PutHeaderAndText(szStr); //m_pPrinterOut->NewLine(1); //m_pPrinterOut->PutChr(szStr); //m_pPrinterOut->NewLine(1); //Console.WriteLine("Message"); //Console.WriteLine("Message Text: {0}", szStr); //Console.WriteLine("----------------------------------------------"); } public void NoInformatEntered() { PutHeaderAndText("-- No information entered --"); } public void PutHeaderAndText(string txt) { if (!Hdrs.printedLastHeader) { Chunk chk = LastHeader(); Phrase p = new Phrase(); PdfPCell cell = new PdfPCell(); p.Add(chk); // add the header chunk cell.BackgroundColor = Color.WHITE; cell.BorderColor = Color.WHITE; cell.AddElement(p); datatable.AddCell(cell); } PutText(txt); } public void Text() { // Get the lenght of the text string and read it in Int16 iValue = RO_df.ReadInteger16(); string szStr = RO_df.ReadText(iValue); string temp = szStr; Chunk chk = LastHeader(); Phrase p = new Phrase(); PdfPCell cell = new PdfPCell(); p.Add(chk); // add the header chunk cell.BackgroundColor = Color.WHITE; cell.BorderColor = Color.WHITE; bool isXYPlot = szStr.StartsWith("< 72 || (szStr.IndexOf('\r') != -1)) { // If the lenght of the string plus the field title is greater // than 72 characters or has a carriage return character in it // then output the text on multiple lines //if (m_pPrinterOut->Row() > 55) // m_pPrinterOut->newpage(); // the header goes on its own line cell.AddElement(p); datatable.AddCell(cell); // text goes below the header if (isXYPlot) AddXYPlot(szStr); // xy plot - sometimes plots were put in text fields else PutText(temp); // it's just text } else { // Otherwise output the header and text on a single line p.Add(ConvertDOSSuperAndSubScripts(szStr,F10)); cell.AddElement(p); datatable.AddCell(cell); //m_pPrinterOut->SetNumberOfNewLines(0); //m_pPrinterOut->putline(0, temp); //if (m_pPrinterOut->Row() + 1 > 55) // Hdrs.repeatCount[Hdrs.HdrCnt] = 1; //else // m_pPrinterOut->newline(1); } //Console.WriteLine("Text"); //Console.WriteLine("Value: {0}", iValue); //Console.WriteLine("Text: {0}", szStr); //Console.WriteLine("----------------------------------------------"); } public void KeyField() { // use the key field as the PDF bookbark string szStr = RO_df.ReadText(); PdfDestination pdfDest = new PdfDestination(PdfDestination.FITH, _MyPDFWriter.DirectContent.PdfDocument.PageSize.Height); new PdfOutline(MyDocOutline[Hdrs.HdrCnt - 1].MyOutline, pdfDest, szStr); //Console.WriteLine("Key Field"); //Console.WriteLine("Key Text: {0}", szStr); //Console.WriteLine("----------------------------------------------"); } // Read in the image filename, height, and width public void ImageFile() { string fn = RO_df.ReadText(); Int16 ht = RO_df.ReadInteger16(); Int16 wd = RO_df.ReadInteger16(); //m_pPrinterOut->PrintImage(fn, wd, ht); //Console.WriteLine("ImageFile"); //Console.WriteLine("Name: {0}", fn); //Console.WriteLine("Height: {0}", ht); //Console.WriteLine("Width: {0}", wd); //Console.WriteLine("----------------------------------------------"); AddImage(fn); } // Read in the X/Y plot info. public void XYPlot() { // Get the lenght of the text string and read it in Int16 iValue = RO_df.ReadInteger16(); string szStr = RO_df.ReadText(iValue); string temp = szStr; Chunk chk = LastHeader(); // = new Chunk(m.Value, fnt); Phrase p = new Phrase(); PdfPCell cell = new PdfPCell(); p.Add(chk); // add the header chunk cell.BackgroundColor = Color.WHITE; cell.BorderColor = Color.WHITE; // the header goes on its own line cell.AddElement(p); datatable.AddCell(cell); AddXYPlot(szStr); //Console.WriteLine("XY Plot"); //Console.WriteLine("Value: {0}", iValue); //Console.WriteLine("Text: {0}", szStr); //Console.WriteLine("----------------------------------------------"); } // Output the string. If it is a graph, print the graph. // ParseForGraph contains the code to print the text. public void PutText(string szStr) { if (szStr == null || szStr.Equals("NONE")) { //m_pPrinterOut->putchr("NONE"); //m_pPrinterOut->newline(2); AddText("NONE", F10); return; } //m_pPrinterOut->SetNumberOfNewLines(0); AddText(szStr,F10); //m_pPrinterOut->newline(2); // Include margin so the Display Data can print with a margin of zero //m_pPrinterOut->ParseForGraph(temp, margin); } // Output the last header that was push onto the header stack // Printer::LastHeader contains the code to do this. public Chunk LastHeader() { Chunk chk;// = new Chunk(m.Value, fnt); string hdrtxt = ""; if (Hdrs.HdrCnt > 0) hdrtxt = Hdrs.strHdrs[Hdrs.HdrCnt - 1]; hdrtxt += ": "; chk = new Chunk(hdrtxt, F10Bold); Hdrs.printedLastHeader = true; return chk; //m_pPrinterOut->LastHeader(); } }// end CompSumROReport public class Headers { //public string[] strHdrs; public List strHdrs; // public int[] repeatCount; public int HdrCnt; public List repeatCount; public bool printedLastHeader; public Headers() { HdrCnt = 0; strHdrs = new List(); repeatCount = new List(); printedLastHeader = false; } } public class RODataFile { FileStream fs = null; BinaryReader br = null; public RODataFile(string fname) { fs = new FileStream(fname,FileMode.Open); br = new BinaryReader(fs); } public void close() { br.Close(); fs.Close(); } public long GetFileLength() { return fs.Length; } // Read an integer value from the data file public Int16 ReadInteger16() { try { return (Int16)br.ReadUInt16(); } catch (Exception e) { Console.WriteLine("Exception : {0}", e.Message); return -1; } } // Read a text string from the data file and returns it. // The calling program is responsible for free it // with the "delete" operator. public string ReadText() { return ReadText(-1); } public string ReadText(Int16 i16CharCount) { Int16 i16DataSize; if (i16CharCount == -1) i16DataSize = ReadInteger16(); else i16DataSize = i16CharCount; if (i16DataSize <= 0) return null; else { byte[] charbuff = new byte[i16DataSize + 1]; charbuff = br.ReadBytes(i16DataSize); string str = ""; for (int i = 0; i < i16DataSize; i++) str += Convert.ToChar(charbuff[i]).ToString(); return (str); //return (Encoding.ASCII.GetString(charbuff, 0, i16DataSize)); // this didn't handle line draw chars } } // Search through the file to find the next record public long NextRecord() { Int16 iType; Int16 RECORD_START = 255; // While not the next record and not end of file get the next meta item while ((iType = ReadInteger16()) != RECORD_START && iType != -1) { NextItem(); } return fs.Seek(0, SeekOrigin.Current); } // Get the next meta item and discard the data public long NextItem() { string pTmp; Int16 iRecType = ReadInteger16(); Int16 iNewCnt; int iLoop; switch (iRecType) { case 1: // Set Header iNewCnt = ReadInteger16(); for (iLoop = 0; iLoop < iNewCnt; iLoop++) { ReadInteger16(); pTmp = ReadText(); //delete pTmp; } break; case 2: // Push Header case 6: // Msg case 7: // Key Field case 100: // Text Field case 101: // Plot Field pTmp = ReadText(); //delete pTmp; break; case 3: // Pop Header case 4: // RRO Begin case 5: // RRO End case 103: // Multi Begin case 104: // Multi End case 0: // Do Nothing // Do nothing break; case 102: // Image Field pTmp = ReadText(); //delete pTmp; ReadInteger16(); ReadInteger16(); break; } return fs.Seek(0, SeekOrigin.Current); } // Get the block of data that is the record public byte[] GetRecord(ref int size) { byte[] data; // Get the current position long lCurPos = fs.Seek(0, SeekOrigin.Current); // Go to the end of the record and get the file position ReadInteger16(); NextRecord(); long lEndRecord = fs.Seek(0, SeekOrigin.Current); // Get the size of the record size = (int)(lEndRecord - lCurPos); // Retrieve the record from the file data = new byte[size +1]; data = br.ReadBytes(size); return data; } } }