using System; using System.Collections.Generic; using System.Linq; using System.Data; using DocumentFormat.OpenXml; using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Spreadsheet; using System.ComponentModel; using C1.WPF.Pdf; using System.Windows.Media; using System.Windows; namespace DTS.Reports { /// /// this class handles outputting generic reports in excel using templates /// we can override it later if we need additional functionality, but /// I think right now it contains everything we need /// public class ReportBase : DTS.Common.Base.BasePropertyChanged { public delegate void ReportFileInUseDelegate(object o); public delegate bool ReportFileWillBeOverwrittenDelegate(object o); public ReportFileInUseDelegate ReportFileInUseHandler = null; public ReportFileWillBeOverwrittenDelegate ReportFileWillBeOverwrittenHandler = null; protected void ReportFileInUse(object o) { ReportFileInUseHandler?.Invoke(o); } protected void ReportFileWillBeOverwritten(object o) { ReportFileWillBeOverwrittenHandler?.Invoke(o); } /// /// many reports need to be timestamped. This function supplies a unified way of formatting the timestamp /// /// formatted timestamp as a string public static string GetFilenameTimeStamp() { DateTime now = DateTime.Now; return string.Format("{0:0000}-{1:00}-{2:00}T{3:00}{4:00}{5:00}", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second); } /// /// most of the tests contain the test setup name, so it is abstracted to a common base class here /// The test setup name is the name of the current test setup /// public string TestSetupName { get; set; } /// /// a test setup can contain a description. This is the description of the current test setup. /// public string TestDescription { get; set; } /// /// this is the current test id. Note the current test id may be blank if you are creating a report from before a test id is provided [say from edit test setup] /// public string TestId { get; set; } /// /// the date and time of the current test, or of the report if the test hasn't been started yet /// public DateTime ReportDate { get; set; } /// /// some reports show a das serial number in the header. /// This field is optional on some reports /// public string DASSerial { get; set; } /// /// the sample rate of the current test. /// this field is optional on some reports /// public double SampleRate { get; set; } /// /// the recording mode of the current test. /// this field is optional on some reports /// public string RecordingMode { get; set; } /// /// the pre-trigger time of the current test. /// this field is optional on some reports /// public double PreTriggerTime { get; set; } /// /// the post-trigger time of the current test. /// this field is optional on some reports /// public double PostTriggerTime { get; set; } /// /// the circuit closure for the trigger line. /// this field is optional on some reports /// public string TriggerClosure { get; set; } /// /// the circuit closure for the start line. /// this field is optional on some reports /// public string StartClosure { get; set; } /// /// full path to template file /// this should be the location of the report template /// private string _templateFileName; public string TemplateFilename { get => _templateFileName; set => SetProperty(ref _templateFileName, value, "TemplateFilename"); } /// /// full path to output file /// this should be the destination of the report /// private string _outputFileName; public string OutputFilename { get => _outputFileName; set => SetProperty(ref _outputFileName, value, "OutputFilename"); } private string _destinationTemplateFilename; public string DestinationTemplateFilename { get => _destinationTemplateFilename; set => SetProperty(ref _destinationTemplateFilename, value, "DestinationTemplateFilename"); } /// /// we will be doing a lot of named range lookups, so we build a table out of them for efficiency /// the key is the name of the named range, the value is the actual named range /// protected Dictionary _nameLookup = new Dictionary(); /// /// outputs a report, first deleting any existing report in the output location, then copying in the template to modify /// /// public virtual void OutputReport(DataTable[] tables, DataTable[] cellstyles) { DeleteExistingReport(); CopyTemplate(); using (SpreadsheetDocument sp = SpreadsheetDocument.Open(OutputFilename, true)) { //in xlsx, any string literal is usually part of a global list of strings, so we get that global list //so we can add to it as we need to SharedStringTablePart shareStringPart; if (sp.WorkbookPart.GetPartsOfType().Count() > 0) { shareStringPart = sp.WorkbookPart.GetPartsOfType().First(); } else { shareStringPart = sp.WorkbookPart.AddNewPart(); } //we will be relying on named ranges in order to find actual cells that we //need to put values in, so we build a dictionary of all the named ranges in the spreadsheet DefinedNames definedNames = sp.WorkbookPart.Workbook.DefinedNames; foreach (DefinedName dn in definedNames) { _nameLookup[dn.Name.Value] = dn; } //#FF7EFB6A UInt32Value fid = createFill(sp.WorkbookPart.WorkbookStylesPart.Stylesheet, System.Drawing.Color.FromArgb(Convert.ToInt32(0xFF), Convert.ToInt32(0x7E), Convert.ToInt32(0xFB), Convert.ToInt32(0x6a))); _passStyle = createCellFormat(sp.WorkbookPart.WorkbookStylesPart.Stylesheet, null, fid, null); fid = createFill(sp.WorkbookPart.WorkbookStylesPart.Stylesheet, System.Drawing.Color.LightPink); _failStyle = createCellFormat(sp.WorkbookPart.WorkbookStylesPart.Stylesheet, null, fid, null); fid = createFill(sp.WorkbookPart.WorkbookStylesPart.Stylesheet, System.Drawing.Color.CornflowerBlue); _warnStyle = createCellFormat(sp.WorkbookPart.WorkbookStylesPart.Stylesheet, null, fid, null); //the spreadsheet can contain multiple pages //for now this handles each table as a different page int idx = 0; foreach (DataTable dt in tables) { ProcessTable(dt, ref shareStringPart, sp, (null == cellstyles) ? null : cellstyles[idx]); idx++; } } } /// /// outputs a PDF report, first deleting any existing report in the output location, then copying in the template to modify /// /// public virtual void OutputReportPDF(DataTable[] tables, DataTable[] cellStyles, string sensitivityDisplayFormat) { DeleteExistingReport(); DeleteExistingPDFTemplate(); CopyExcelTemplateForPDF(); C1PdfDocument pdf = new C1PdfDocument(); using (SpreadsheetDocument sp = SpreadsheetDocument.Open(DestinationTemplateFilename, true)) { //in xlsx, any string literal is usually part of a global list of strings, so we get that global list //so we can add to it as we need to SharedStringTablePart shareStringPart; if (sp.WorkbookPart.GetPartsOfType().Count() > 0) { shareStringPart = sp.WorkbookPart.GetPartsOfType().First(); } else { shareStringPart = sp.WorkbookPart.AddNewPart(); } //we will be relying on named ranges in order to find actual cells that we //need to put values in, so we build a dictionary of all the named ranges in the spreadsheet DefinedNames definedNames = sp.WorkbookPart.Workbook.DefinedNames; foreach (DefinedName dn in definedNames) { _nameLookup[dn.Name.Value] = dn; } //#FF7EFB6A UInt32Value fid = createFill(sp.WorkbookPart.WorkbookStylesPart.Stylesheet, System.Drawing.Color.FromArgb(Convert.ToInt32(0xFF), Convert.ToInt32(0x7E), Convert.ToInt32(0xFB), Convert.ToInt32(0x6a))); _passStyle = createCellFormat(sp.WorkbookPart.WorkbookStylesPart.Stylesheet, null, fid, null); fid = createFill(sp.WorkbookPart.WorkbookStylesPart.Stylesheet, System.Drawing.Color.LightPink); _failStyle = createCellFormat(sp.WorkbookPart.WorkbookStylesPart.Stylesheet, null, fid, null); fid = createFill(sp.WorkbookPart.WorkbookStylesPart.Stylesheet, System.Drawing.Color.CornflowerBlue); _warnStyle = createCellFormat(sp.WorkbookPart.WorkbookStylesPart.Stylesheet, null, fid, null); //the spreadsheet can contain multiple pages //for now this handles each table as a different page int idx = 0; foreach (DataTable dt in tables) { if ((dt.Rows.Count > 0) && (idx > 0)) { pdf.NewPage(); } switch (dt.TableName) { case "List": pdf.Landscape = false; LeftMargin = 72; RightMargin = 72; PageHeight = 792; PageWidth = 612; RowsPerPage = 45; ColsPerPage = 9; // A-I DataRowsPerPage = 36; break; case "Layout": pdf.Landscape = true; LeftMargin = 50; RightMargin = 50; PageHeight = 612; PageWidth = 792; RowsPerPage = 33; ColsPerPage = 14; // A-N DataRowsPerPage = 22; break; case "Squibs": pdf.Landscape = true; LeftMargin = 50; RightMargin = 50; PageHeight = 612; PageWidth = 792; RowsPerPage = 34; ColsPerPage = 14; // A-N DataRowsPerPage = 26; break; case "Analog": pdf.Landscape = true; LeftMargin = 50; RightMargin = 50; PageHeight = 612; PageWidth = 792; RowsPerPage = 33; ColsPerPage = 14; // A-N DataRowsPerPage = 25; break; case "Digital_Channels": case "Squib_Channels": case "Calculated_Channels": pdf.Landscape = true; LeftMargin = 50; RightMargin = 50; PageHeight = 612; PageWidth = 792; RowsPerPage = 33; ColsPerPage = 14; // A-N DataRowsPerPage = 26; break; case "Sensor_Channels": pdf.Landscape = true; LeftMargin = 50; RightMargin = 50; PageHeight = 612; PageWidth = 792; RowsPerPage = 38; ColsPerPage = 18; // A-R DataRowsPerPage = 29; break; case "DAS": if (OutputFilename.Contains("TestSummary")) { pdf.Landscape = true; LeftMargin = 50; RightMargin = 50; PageHeight = 612; PageWidth = 792; ColsPerPage = 14; // A-N RowsPerPage = 36; DataRowsPerPage = 27; } else { //Diagnostics pdf.Landscape = true; LeftMargin = 50; RightMargin = 50; PageHeight = 612; PageWidth = 792; ColsPerPage = 14; // A-N RowsPerPage = 34; DataRowsPerPage = 25; } break; } var x = sp.WorkbookPart.GetPartsOfType().First(); var y = x.Worksheet.First(); ProcessTablePDF(dt, ref shareStringPart, sp, (null == cellStyles) ? null : cellStyles[idx], pdf, sensitivityDisplayFormat); idx++; } } pdf.Save(OutputFilename); DeleteExistingPDFTemplate(); } public void CopyReportIfNeeded(string folderNameId, string outputFileName) { var destinationFolder = System.IO.Path.Combine(folderNameId, Common.Constants.REPORT_DIR_NAME); var DestinationFilename = System.IO.Path.Combine(destinationFolder, System.IO.Path.GetFileName(outputFileName)); var fullPathOutputFilename = System.IO.Path.GetFullPath(OutputFilename); var fullPathDestinationFilename = System.IO.Path.GetFullPath(DestinationFilename); if (fullPathOutputFilename != fullPathDestinationFilename) { if (System.IO.File.Exists(DestinationFilename)) { System.IO.File.Delete(DestinationFilename); } if (!System.IO.Directory.Exists(destinationFolder)) { System.IO.Directory.CreateDirectory(destinationFolder); } System.IO.File.Copy(OutputFilename, DestinationFilename); System.IO.File.Delete(OutputFilename); } } /// /// helper class for dealing with pages in the excel report /// public class TablePage { /// /// row index for the page start. assumes all pages are done vertically, not horizontally /// we need extra logic if we want to handle going horizontal too /// public int PageStart { get; set; } /// /// row index for the page end. Assumes vertical, just like PageStart /// public int PageEnd { get; set; } /// /// row index for the table on the page /// header row inclusive /// public int RowStart { get; set; } /// /// row index for the last row in the table /// public int RowEnd { get; set; } /// /// total number of table rows handled by this page /// public int RowsHandled => RowEnd - RowStart;//rowstart includes header row, so don't add +1 } /// /// gets a list of all the pages and the table on that page, given a sheet name /// /// /// protected virtual List GetTablePages(string sheetname) { var currentPage = 1; var bDone = false; var pages = new List(); while (!bDone) { var pageStart = GetDefinedName($"{sheetname}Page{currentPage}Start"); var pageEnd = GetDefinedName($"{sheetname}Page{currentPage}End"); var tableStart = GetDefinedName($"{sheetname}Table{currentPage}Start"); var tableEnd = GetDefinedName($"{sheetname}Table{currentPage}End"); if (null != pageStart && null != pageEnd && null != tableStart && null != tableEnd) { pages.Add(new TablePage() { RowStart = GetRowIndex(tableStart), RowEnd = GetRowIndex(tableEnd), PageStart = GetRowIndex(pageStart), PageEnd = GetRowIndex(pageEnd) }); } else { bDone = true; } currentPage++; } return pages; } /// /// we have to do a lot of string parsing to go from cell references to sheet/column/row values /// so, we declare these ahead of time to save time doing it over and over again /// protected static char[] _sheetSplitter = new char[] { '!' }; protected static char[] _cellSplitter = new char[] { '$' }; /// /// gets a row index given an excel named range /// /// /// protected int GetRowIndex(DefinedName dn) { //defined names in excel are in the form SheetId!$Column$Row var tokens = dn.Text.Split(_sheetSplitter); tokens = tokens[1].Split(_cellSplitter); return int.Parse(tokens.Last()); } /// /// looks for a defined name in the worksheet, returns null otherwise /// /// /// protected virtual DefinedName GetDefinedName(string name) { if (_nameLookup.ContainsKey(name)) { return _nameLookup[name]; } else { return null; } } /// /// fill styles applies to diagnostic reports, or pass/fail style entries /// public enum FillStyles { Pass, Fail, NotTested, Warn } /// /// pass and fail styles are created at runtime, we store their index here for later use /// public UInt32Value _failStyle; public UInt32Value _passStyle; public UInt32Value _warnStyle; //private UInt32Value _notTestedStyle; /// /// these are fields that may appear in a report header/page header /// they are not required, the code will look for them in a page, and populate the fields if they are found /// protected enum PageFields { TestSetupName, TestDescription, TestId, ReportDate, DASSerial, DASSPS, RecordMode, PreTrigger, PostTrigger, TriggerClosure, StartClosure, RecordingMode } /// /// handles a one worksheet in the workbook /// A worksheet is a set of pages with a table on each page /// each table is populated using the datatable passed in /// /// table to process TableName is the SheetId /// /// protected virtual void ProcessTable(DataTable dt, ref SharedStringTablePart shareStringPart, SpreadsheetDocument sp, DataTable dtStyle) { var ws = GetWorksheetPartByName(sp, dt.TableName); if (null == ws) { return; } //get a list of all pages on this sheet var pages = GetTablePages(dt.TableName); //build a list of pages we don't need //if we have already handled all the rows we need in the sheet, we don't need anymore pages var toDelete = new List(); var rowsHandledSoFar = 0; foreach (var page in pages) { if (rowsHandledSoFar >= dt.Rows.Count) { toDelete.Add(page); } else { rowsHandledSoFar += page.RowsHandled; } } //delete unnecessary pages foreach (var page in toDelete) { pages.Remove(page); DeletePage(page, ws.Worksheet); } //if there are no rows, delete the whole worksheet ... if (dt.Rows.Count < 1) { DeleteWorksheet(sp, dt.TableName); return; } //fill in each page for (var i = 0; i < pages.Count; i++) { //set the page footer var key = $"{dt.TableName}Page{1 + i}Footer"; var dn = GetDefinedName(key); if (null == dn) { continue; } var cell = GetCell(ws.Worksheet, dn.Text); if (null == cell) { continue; } cell.CellValue = new CellValue(InsertSharedStringItem($"{dt.TableName} Page {1 + i}/{pages.Count}", shareStringPart).ToString()); cell.DataType = new EnumValue() { Value = CellValues.SharedString }; var fields = Enum.GetValues(typeof(PageFields)).Cast().ToArray(); foreach (var field in fields) { var name = $"{dt.TableName}Page{1 + i}{field.ToString()}"; dn = GetDefinedName(name); if (null != dn) { cell = GetCell(ws.Worksheet, dn.Text); if (null != cell) { switch (field) { case PageFields.DASSerial: cell.CellValue = new CellValue(InsertSharedStringItem(DASSerial, shareStringPart).ToString()); cell.DataType = new EnumValue() { Value = CellValues.SharedString }; break; case PageFields.DASSPS: cell.CellValue = new CellValue(SampleRate.ToString()); cell.DataType = new EnumValue() { Value = CellValues.Number }; break; case PageFields.PostTrigger: cell.CellValue = new CellValue(PostTriggerTime.ToString()); cell.DataType = new EnumValue() { Value = CellValues.Number }; break; case PageFields.PreTrigger: cell.CellValue = new CellValue(PreTriggerTime.ToString()); cell.DataType = new EnumValue() { Value = CellValues.Number }; break; case PageFields.RecordMode: case PageFields.RecordingMode: cell.CellValue = new CellValue(InsertSharedStringItem(RecordingMode, shareStringPart).ToString()); cell.DataType = new EnumValue() { Value = CellValues.SharedString }; break; case PageFields.ReportDate: //cell.CellValue = new CellValue(InsertSharedStringItem(ReportDate, shareStringPart).ToString()); cell.CellValue = new CellValue(ReportDate.ToOADate().ToString()); cell.DataType = new EnumValue() { Value = CellValues.Number }; break; case PageFields.StartClosure: cell.CellValue = new CellValue(InsertSharedStringItem(StartClosure, shareStringPart).ToString()); cell.DataType = new EnumValue() { Value = CellValues.SharedString }; break; case PageFields.TestDescription: cell.CellValue = new CellValue(InsertSharedStringItem(TestDescription, shareStringPart).ToString()); cell.DataType = new EnumValue() { Value = CellValues.SharedString }; break; case PageFields.TestId: cell.CellValue = new CellValue(InsertSharedStringItem(TestId, shareStringPart).ToString()); cell.DataType = new EnumValue() { Value = CellValues.SharedString }; break; case PageFields.TestSetupName: cell.CellValue = new CellValue(InsertSharedStringItem(TestSetupName, shareStringPart).ToString()); cell.DataType = new EnumValue() { Value = CellValues.SharedString }; cell.DataType = new EnumValue() { Value = CellValues.SharedString }; break; case PageFields.TriggerClosure: cell.CellValue = new CellValue(InsertSharedStringItem(TriggerClosure, shareStringPart).ToString()); cell.DataType = new EnumValue() { Value = CellValues.SharedString }; break; } } } } } //now we get to fill in the table(s) var row = 1; for (var i = 0; i < dt.Rows.Count; i++) { foreach (DataColumn c in dt.Columns) { var name = $"{dt.TableName}{c.ColumnName}{row}"; var dn = GetDefinedName(name); if (null == dn) { continue; } //user isn't required to have every column in their template if they don't want // if we don't find the cell, we go on our merry way var o = dt.Rows[i][c.ColumnName]; var cell = GetCell(ws.Worksheet, dn.Text); if (null == cell) { continue; } if (null != dtStyle) { if (null != dtStyle.Rows[i][c.ColumnName]) { var istyle = Convert.ToInt32(dtStyle.Rows[i][c.ColumnName]); var fs = (FillStyles)istyle; if (fs == FillStyles.Fail) { cell.StyleIndex = _failStyle; } else if (fs == FillStyles.Pass) { cell.StyleIndex = _passStyle; } else if (fs == FillStyles.Warn) { cell.StyleIndex = _warnStyle; } } } if (c.DataType == typeof(string)) { cell.CellValue = new CellValue(InsertSharedStringItem(o as string, shareStringPart).ToString()); cell.DataType = new EnumValue() { Value = CellValues.SharedString }; } else if (c.DataType == typeof(int)) { cell.CellValue = new CellValue(Convert.ToUInt32(o).ToString(System.Globalization.CultureInfo.InvariantCulture)); cell.DataType = new EnumValue() { Value = CellValues.Number }; } else if (c.DataType == typeof(bool)) { cell.CellValue = new CellValue(Convert.ToBoolean(o) ? "1" : "0"); cell.DataType = new EnumValue() { Value = CellValues.Boolean }; } else if (c.DataType == typeof(double)) { var d = Convert.ToDouble(o); if (double.IsNaN(d)) { cell.CellValue = new CellValue(InsertSharedStringItem("---", shareStringPart).ToString()); cell.DataType = new EnumValue() { Value = CellValues.SharedString }; } else { cell.CellValue = new CellValue(d.ToString(System.Globalization.CultureInfo.InvariantCulture)); cell.DataType = new EnumValue() { Value = CellValues.Number }; } } else if (c.DataType == typeof(DateTime)) { var date = Convert.ToDateTime(o); if (date.Year < 1900) { //there is a limitation to date values in excel, however here we are protecting from values that we just don't want to show //if the date is <1900 for our purposes, it's probably not real } else { cell.CellValue = new CellValue(date.ToOADate().ToString(System.Globalization.CultureInfo.InvariantCulture)); cell.DataType = new EnumValue() { Value = CellValues.Number }; } } else { throw new NotSupportedException("can't handle: " + c.DataType.ToString() + " yet"); } } row++; } ws.Worksheet.Save(); } public int PageHeight { get; set; } = 792; public int PageWidth { get; set; } = 612; public int LeftMargin { get; set; } = 72; public int RightMargin { get; set; } = 72; const int TopMargin = 72; const int BottomMargin = 72; public int RowsPerPage { get; set; } = 45; public int DataRowsPerPage { get; set; } = 36; // A - I public int ColsPerPage { get; set; } = 9; public int RowSize => (PageHeight - (TopMargin + BottomMargin)) / RowsPerPage; public int ColSize => (PageWidth - (LeftMargin + RightMargin)) / ColsPerPage; public int ColNumber { get; set; } = 0; public int RowNumber { get; set; } = 0; public int XPoint => (ColNumber * ColSize) + LeftMargin; public int YPoint => (RowNumber * RowSize) + TopMargin; public int FieldSize(int numColumns) { return numColumns * ColSize; } /// /// handles a one worksheet in the workbook /// A worksheet is a set of pages with a table on each page /// each table is populated using the datatable passed in /// /// table to process TableName is the SheetId /// /// protected virtual void ProcessTablePDF(DataTable dt, ref SharedStringTablePart shareStringPart, SpreadsheetDocument sp, DataTable dtStyle, C1PdfDocument pdf, string sensitivityDisplayFormat) { var font = new C1.WPF.Pdf.Font("Segoe UI", 10); // 10884 - PDF version of diagnostic report not readable // http://fogbugz/fogbugz/default.asp?10884 var color = System.Windows.Media.Colors.Black; var size = new Size(); var point = new Point(); var rect = pdf.PageRectangle; var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZAAABACADAEAFAGAHAIAJAKALAMANAOAPAQARASATAUAVAWAXAYAZ"; //temp var rowCol = new string[] { }; var ws = GetWorksheetPartByName(sp, dt.TableName); if (null == ws) { return; } //get a list of all pages on this sheet var pages = GetTablePages(dt.TableName); //build a list of pages we don't need //if we have already handled all the rows we need in the sheet, we don't need anymore pages var toDelete = new List(); var rowsHandledSoFar = 0; foreach (var page in pages) { if (rowsHandledSoFar >= dt.Rows.Count) { toDelete.Add(page); } else { rowsHandledSoFar += page.RowsHandled; } } //delete unnecessary pages foreach (var page in toDelete) { pages.Remove(page); DeletePage(page, ws.Worksheet); } //if there are no rows, delete the whole worksheet ... if (dt.Rows.Count < 1) { DeleteWorksheet(sp, dt.TableName); return; } //fill in each page var pen = new C1.WPF.Pdf.Pen(((SolidColorBrush)Application.Current.FindResource("Brush_ApplicationContentGroupBorder")).Color, 1); var dtRow = 0; for (var pageNum = 0; pageNum < pages.Count; pageNum++) { var cell = new Cell(); //set the page footer var key = $"{dt.TableName}Page{(1 + pageNum)}Footer"; var dn = GetDefinedName(key); if (dn != null) { cell = GetCell(ws.Worksheet, dn.Text); if (cell != null) { font = GetPDFFont(sp, cell); rowCol = GetRowCol(dn.Text); ColNumber = (alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A')); RowNumber = GetRowNumber(rowCol[2], pageNum); size = new Size(FieldSize(4), RowSize); //4 is temp point = new Point(XPoint, YPoint); rect = new Rect(point, size); var sf = new StringFormat(); sf.Alignment = HorizontalAlignment.Center; pdf.DrawString($"{dt.TableName} Page {1 + pageNum}/{pages.Count}", font, color, rect, sf);//Shouldn't be string literal } } var fields = Enum.GetValues(typeof(PageFields)).Cast().ToArray(); var cellString = string.Empty; foreach (var field in fields) { var name = $"{dt.TableName}Page{1 + pageNum}{field.ToString()}"; dn = GetDefinedName(name); if (dn != null) { cell = GetCell(ws.Worksheet, dn.Text); if (cell != null) { font = GetPDFFont(sp, cell); rowCol = GetRowCol(dn.Text); ColNumber = (alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A')); RowNumber = GetRowNumber(rowCol[2], pageNum); switch (field) { case PageFields.ReportDate: case PageFields.TestDescription: case PageFields.TestId: case PageFields.TestSetupName: case PageFields.RecordingMode: //In ChannelCalibration, these are 5 //In TestSummary, these are 12, 14, 12, 12, 12, and 7 //In DASLayout, these are 12 //In DiagnosticResults, these are 10 //So, use the minimum??? size = new Size(FieldSize(5), RowSize); //5 is temp break; case PageFields.DASSerial: case PageFields.DASSPS: case PageFields.RecordMode: case PageFields.PreTrigger: case PageFields.PostTrigger: case PageFields.TriggerClosure: case PageFields.StartClosure: size = new Size(FieldSize(2), RowSize); //2 is temp break; default: break; } point = new Point(XPoint, YPoint); rect = new Rect(point, size); switch (field) { case PageFields.DASSerial: case PageFields.DASSPS: case PageFields.RecordMode: case PageFields.PreTrigger: case PageFields.PostTrigger: case PageFields.TriggerClosure: case PageFields.StartClosure: pdf.DrawLine(pen, rect.TopLeft, rect.BottomLeft); pdf.DrawLine(pen, rect.TopRight, rect.BottomRight); pdf.DrawLine(pen, rect.TopLeft, rect.TopRight); pdf.DrawLine(pen, rect.BottomLeft, rect.BottomRight); break; default: break; } var sf = new StringFormat(); sf.Alignment = HorizontalAlignment.Right; var alignment = GetCellAlignment(sp, cell); if ((alignment != null) && (alignment.Horizontal != null)) { switch (alignment.Horizontal.Value) { case HorizontalAlignmentValues.Left: sf.Alignment = HorizontalAlignment.Left; break; } } switch (field) { case PageFields.ReportDate: pdf.DrawString(ReportDate.ToLongDateString(), font, color, rect, sf); break; case PageFields.TestDescription: pdf.DrawString(TestDescription, font, color, rect); break; case PageFields.TestId: pdf.DrawString(TestId, font, color, rect); break; case PageFields.TestSetupName: pdf.DrawString(TestSetupName, font, color, rect); break; case PageFields.DASSerial: pdf.DrawString((DASSerial.PadLeft(DASSerial.Length + 1)).PadRight(DASSerial.Length + 1), font, color, rect); break; case PageFields.DASSPS: pdf.DrawString(SampleRate.ToString(), font, color, rect, sf); break; case PageFields.RecordMode: //In colored header of Layout if (RecordingMode != null) { pdf.DrawString((RecordingMode.PadLeft(RecordingMode.Length + 1)).PadRight(RecordingMode.Length + 1), font, color, rect); } break; case PageFields.PreTrigger: pdf.DrawString(string.Format("{0:0.0}", PreTriggerTime).ToString(), font, color, rect, sf); break; case PageFields.PostTrigger: pdf.DrawString(string.Format("{0:0.0}", PostTriggerTime).ToString(), font, color, rect, sf); break; case PageFields.TriggerClosure: pdf.DrawString((TriggerClosure.PadLeft(TriggerClosure.Length + 1)).PadRight(TriggerClosure.Length + 1), font, color, rect); break; case PageFields.StartClosure: pdf.DrawString((StartClosure.PadLeft(StartClosure.Length + 1)).PadRight(StartClosure.Length + 1), font, color, rect); break; case PageFields.RecordingMode: //In top of DAS sheet of TestSummary pdf.DrawString(RecordingMode, font, color, rect); break; default: break; } var columnLetter = "A"; switch (field) { case PageFields.ReportDate: case PageFields.TestDescription: case PageFields.TestId: case PageFields.TestSetupName: case PageFields.RecordingMode: ColNumber = 0; RowNumber = GetRowNumber(rowCol[2], pageNum); columnLetter = "A"; cell = GetCell(ws.Worksheet, columnLetter, (uint)RowNumber); //change RowNumber (and others) to uint? font = GetPDFFont(sp, cell); size = new Size(FieldSize(4), RowSize); //4 is temp point = new Point(XPoint, YPoint); rect = new Rect(point, size); cellString = GetCellString(dn.Text.Replace(rowCol[1], "A"), ws, shareStringPart); pdf.DrawString(cellString, font, color, rect); break; case PageFields.DASSerial: case PageFields.DASSPS: case PageFields.RecordMode: case PageFields.PreTrigger: case PageFields.PostTrigger: case PageFields.TriggerClosure: case PageFields.StartClosure: ColNumber = alphabet.IndexOf(rowCol[1]); RowNumber--; columnLetter = rowCol[1]; cell = GetCell(ws.Worksheet, columnLetter, (uint)RowNumber); //change RowNumber (and others) to uint? font = GetPDFFont(sp, cell); size = new Size(FieldSize(2), RowSize); //4 is temp point = new Point(XPoint, YPoint); rect = new Rect(point, size); pdf.FillRectangle(System.Windows.Media.Color.FromRgb(221, 235, 247), rect); pdf.DrawLine(pen, rect.TopLeft, rect.BottomLeft); pdf.DrawLine(pen, rect.TopRight, rect.BottomRight); pdf.DrawLine(pen, rect.TopLeft, rect.TopRight); pdf.DrawLine(pen, rect.BottomLeft, rect.BottomRight); cellString = GetCellString(columnLetter, (uint)RowNumber, ws, shareStringPart); pdf.DrawString(" " + cellString, font, color, rect); break; default: break; } } } } //Add these to the PageFields above? key = $"{dt.TableName}Page{1 + pageNum}ChannelCalibrationListLabel"; dn = GetDefinedName(key); if (dn != null) { cell = GetCell(ws.Worksheet, dn.Text); if (cell != null) { font = GetPDFFont(sp, cell); rowCol = GetRowCol(dn.Text); ColNumber = (alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A')); RowNumber = GetRowNumber(rowCol[2], pageNum); size = new Size(FieldSize(3), RowSize); //3 is temp point = new Point(XPoint, YPoint); rect = new Rect(point, size); cellString = GetCellString(dn.Text, ws, shareStringPart); pdf.DrawString(" " + cellString, font, color, rect); } } key = $"{dt.TableName}Page{(1 + pageNum)}ChannelsLabel"; dn = GetDefinedName(key); if (dn != null) { cell = GetCell(ws.Worksheet, dn.Text); if (cell != null) { font = GetPDFFont(sp, cell); rowCol = GetRowCol(dn.Text); ColNumber = (alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A')); RowNumber = GetRowNumber(rowCol[2], pageNum); size = new Size(FieldSize(2), RowSize); //2 is temp point = new Point(XPoint, YPoint); rect = new Rect(point, size); cellString = GetCellString(dn.Text, ws, shareStringPart); pdf.DrawString(" " + cellString, font, color, rect); } } key = $"{dt.TableName}Page{1 + pageNum}DASLabel"; dn = GetDefinedName(key); if (dn != null) { cell = GetCell(ws.Worksheet, dn.Text); if (cell != null) { font = GetPDFFont(sp, cell); rowCol = GetRowCol(dn.Text); ColNumber = (alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A')); RowNumber = GetRowNumber(rowCol[2], pageNum); size = new Size(FieldSize(2), RowSize); //2 is temp point = new Point(XPoint, YPoint); rect = new Rect(point, size); cellString = GetCellString(dn.Text, ws, shareStringPart); pdf.DrawString(" " + cellString, font, color, rect); } } key = $"{dt.TableName}Page{1 + pageNum}SensorChannelsLabel"; dn = GetDefinedName(key); if (dn != null) { cell = GetCell(ws.Worksheet, dn.Text); if (cell != null) { font = GetPDFFont(sp, cell); rowCol = GetRowCol(dn.Text); ColNumber = (alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A')); RowNumber = GetRowNumber(rowCol[2], pageNum); size = new Size(FieldSize(3), RowSize); //3 is temp point = new Point(XPoint, YPoint); rect = new Rect(point, size); cellString = GetCellString(dn.Text, ws, shareStringPart); pdf.DrawString(" " + cellString, font, color, rect); } } key = $"{dt.TableName}Page{1 + pageNum}SquibsLabel"; dn = GetDefinedName(key); if (dn != null) { cell = GetCell(ws.Worksheet, dn.Text); if (cell != null) { font = GetPDFFont(sp, cell); rowCol = GetRowCol(dn.Text); ColNumber = (alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A')); RowNumber = GetRowNumber(rowCol[2], pageNum); size = new Size(FieldSize(3), RowSize); //3 is temp point = new Point(XPoint, YPoint); rect = new Rect(point, size); cellString = GetCellString(dn.Text, ws, shareStringPart); pdf.DrawString(" " + cellString, font, color, rect); } } key = $"{dt.TableName}Page{1 + pageNum}SquibChannelsLabel"; dn = GetDefinedName(key); if (dn != null) { cell = GetCell(ws.Worksheet, dn.Text); if (cell != null) { font = GetPDFFont(sp, cell); rowCol = GetRowCol(dn.Text); ColNumber = (alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A')); RowNumber = GetRowNumber(rowCol[2], pageNum); size = new Size(FieldSize(3), RowSize); //3 is temp point = new Point(XPoint, YPoint); rect = new Rect(point, size); cellString = GetCellString(dn.Text, ws, shareStringPart); pdf.DrawString(" " + cellString, font, color, rect); } } //Column headers key = $"{dt.TableName}Table{1 + pageNum}Start"; dn = GetDefinedName(key); if (dn != null) { cell = GetCell(ws.Worksheet, dn.Text); if (cell != null) { if (dn.Text.StartsWith("List")) //ChannelCalibrationList { DrawChannelCalibrationHeaderFields(sp, cell, dn, alphabet, pageNum, pdf, pen, ws, shareStringPart, color); } else if (dn.Text.StartsWith("Layout")) //Layout { DrawLayoutHeaderFields(sp, cell, dn, alphabet, pageNum, pdf, pen, ws, shareStringPart, color); } else if (dn.Text.StartsWith("DAS") && OutputFilename.Contains("TestSummary")) //TestSummary { DrawDASHeaderFields(sp, cell, dn, alphabet, pageNum, pdf, pen, ws, shareStringPart, color); } else if (dn.Text.StartsWith("Sensor_Channels")) //TestSummary { DrawSensor_ChannelsHeaderFields(sp, cell, dn, alphabet, pageNum, pdf, pen, ws, shareStringPart, color); } else if (dn.Text.StartsWith("Digital_Channels")) //TestSummary { DrawDigital_ChannelsHeaderFields(sp, cell, dn, alphabet, pageNum, pdf, pen, ws, shareStringPart, color); } else if (dn.Text.StartsWith("Squib_Channels")) //TestSummary { DrawSquib_ChannelsHeaderFields(sp, cell, dn, alphabet, pageNum, pdf, pen, ws, shareStringPart, color); } else if (dn.Text.StartsWith("Calculated_Channels")) //TestSummary { DrawCalculated_ChannelsHeaderFields(sp, cell, dn, alphabet, pageNum, pdf, pen, ws, shareStringPart, color); } else if ((dn.Text.StartsWith("DAS")) && (OutputFilename.Contains("Diagnostics"))) //Diagnostics { DrawDiagnosticsDASHeaderFields(sp, cell, dn, alphabet, pageNum, pdf, pen, ws, shareStringPart, color); } else if (dn.Text.StartsWith("Analog")) //Diagnostics { DrawAnalogHeaderFields(sp, cell, dn, alphabet, pageNum, pdf, pen, ws, shareStringPart, color); } else if (dn.Text.StartsWith("Squibs")) //Diagnostics { DrawSquibsHeaderFields(sp, cell, dn, alphabet, pageNum, pdf, pen, ws, shareStringPart, color); } } } //now we get to fill in the table(s) var pageDataRow = 1; while (pageDataRow <= DataRowsPerPage) { foreach (DataColumn c in dt.Columns) { if ((!(((dt.TableName == "Sensor_Channels") || (dt.TableName == "Squib_Channels")) && (c.ColumnName == "Module"))) && (c.ColumnName != "LTrig")) //These are currently hidden { var name = $"{dt.TableName}{c.ColumnName}{dtRow + 1}"; dn = GetDefinedName(name); if (null == dn) { continue; } //user isn't required to have every column in their template if they don't want // if we don't find the cell, we go on our merry way var o = new object(); if (dtRow >= dt.Rows.Count) { o = string.Empty; //Add an empty cell in an empty row } else { o = dt.Rows[dtRow][c.ColumnName]; cell = GetCell(ws.Worksheet, dn.Text); if (null == cell) { continue; } if (c.DataType == typeof(double)) { double d = Convert.ToDouble(o); if (double.IsNaN(d)) { o = "---"; } else { switch (c.ColumnName) { case "Exc": case "Shunt": case "Noise": case "Delay": case "Duration": case "Resistance": o = string.Format("{0:0.00}", d).ToString(System.Globalization.CultureInfo.CurrentCulture); break; case "Offset": case "Range": case "SPS": case "AAF": case "Voltage": case "Volt": o = string.Format("{0:0}", d).ToString(System.Globalization.CultureInfo.CurrentCulture); break; case "Sens": o = d.ToString(sensitivityDisplayFormat); break; default: o = string.Format("{0:0.0}", d).ToString(System.Globalization.CultureInfo.CurrentCulture); break; } } } else if (c.DataType == typeof(DateTime)) { var date = Convert.ToDateTime(o); if (date.ToShortDateString() == "1/1/0001") { o = string.Empty; } else { o = date.ToShortDateString(); } } font = GetPDFFont(sp, cell); } rowCol = GetRowCol(dn.Text); ColNumber = alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A'); RowNumber = GetRowNumber(rowCol[2], pageNum); if (name.Contains("Date")) { o = string.Format("{0:M/d/yyyy}", o); } if (name.StartsWith("ListNextCal") || name.StartsWith("LayoutDCH") || name.StartsWith("LayoutModule") || name.StartsWith("LayoutChannel") || name.StartsWith("LayoutRange") || (name.StartsWith("LayoutSens") && (!name.StartsWith("LayoutSensor"))) || name.StartsWith("LayoutFilter") || name.StartsWith("LayoutVolt") || name.StartsWith("LayoutTrigger") || name.StartsWith("DASAAF") || name.StartsWith("DASPreTrigger") || name.StartsWith("DASPostTrigger") || name.StartsWith("DASChannels") || name.StartsWith("Sensor_ChannelsAbsChanNum") || name.StartsWith("Sensor_ChannelsChannel") || name.StartsWith("Sensor_ChannelsEID") || name.StartsWith("Sensor_ChannelsEU") || name.StartsWith("Sensor_ChannelsRange") || (name.StartsWith("Sensor_ChannelsSens") && (!name.StartsWith("Sensor_ChannelsSensorSN"))) || name.StartsWith("Sensor_ChannelsPropToExc") || name.StartsWith("Sensor_ChannelsPolarity") || name.StartsWith("Sensor_ChannelsVoltage") || name.StartsWith("Sensor_ChannelsFilter") || name.StartsWith("Squib_ChannelsAbsChanNum") || name.StartsWith("Squib_ChannelsChannel") || name.StartsWith("Squib_ChannelsSensorSN") || name.StartsWith("Squib_ChannelsEID") || name.StartsWith("Squib_ChannelsDelay") || name.StartsWith("Squib_ChannelsDuration") || name.StartsWith("DASDAS") || name.StartsWith("AnalogExportNum") || name.StartsWith("AnalogDAS") || name.StartsWith("AnalogModule") || name.StartsWith("AnalogChannel") || name.StartsWith("AnalogObject") || name.StartsWith("AnalogExc") || name.StartsWith("AnalogOffset") || name.StartsWith("AnalogShunt") || name.StartsWith("AnalogRange") || name.StartsWith("AnalogNoise") || name.StartsWith("SquibsDAS") || name.StartsWith("SquibsModule") || name.StartsWith("SquibsChannel") || name.StartsWith("SquibsDelay")) { size = new Size(FieldSize(1), RowSize); } else if (name.StartsWith("DASConnection") || name.StartsWith("Squib_ChannelsDescription") || name.StartsWith("Squib_ChannelsSquibFireMode")) { size = new Size(FieldSize(3), RowSize); } else { size = new Size(FieldSize(2), RowSize); } point = new Point(XPoint, YPoint); rect = new Rect(point, size); //If text will not fit in field, decrease the font size var textSize = pdf.MeasureString(" " + o, font); var savedFont = font; while ((textSize.Width > size.Width) && (font.Size > 7.0)) { var smallerFontSize = font.Size; smallerFontSize--; font = new C1.WPF.Pdf.Font(font.Name, smallerFontSize, savedFont.Style); textSize = pdf.MeasureString(" " + o, font); } while (textSize.Width > size.Width) { o = (o as string).Remove((o as string).Length - 1); textSize = pdf.MeasureString(" " + o, font); } var alternatingRow = -1; if (OutputFilename.Contains("ChannelCalibration")) { Math.DivRem(RowNumber, 4, out alternatingRow); if ((alternatingRow == 1) || (alternatingRow == 2)) { pdf.FillRectangle(System.Windows.Media.Color.FromRgb(242, 242, 242), rect); } if ((alternatingRow == 2) || (alternatingRow == 0)) { pdf.DrawLine(pen, rect.BottomLeft, rect.BottomRight); } } else { Math.DivRem(pageDataRow, 2, out alternatingRow); if (alternatingRow == 0) { pdf.FillRectangle(System.Windows.Media.Color.FromRgb(242, 242, 242), rect); } pdf.DrawLine(pen, rect.TopLeft, rect.TopRight); pdf.DrawLine(pen, rect.BottomLeft, rect.BottomRight); pdf.DrawLine(pen, rect.TopLeft, rect.BottomLeft); pdf.DrawLine(pen, rect.TopRight, rect.BottomRight); } if ((null != dtStyle) && (dtRow < dtStyle.Rows.Count)) { if (null != dtStyle.Rows[dtRow][c.ColumnName]) { if (!string.IsNullOrWhiteSpace((o as string))) { var istyle = Convert.ToInt32(dtStyle.Rows[dtRow][c.ColumnName]); var fs = (FillStyles)istyle; if (fs == FillStyles.Fail) { pdf.FillRectangle(System.Windows.Media.Color.FromRgb(255, 204, 204), rect); } else if (fs == FillStyles.Pass) { pdf.FillRectangle(System.Windows.Media.Color.FromRgb(126, 251, 106), rect); } else if (fs == FillStyles.Warn) { pdf.FillRectangle(System.Windows.Media.Color.FromRgb(100, 149, 237), rect); } } } } pdf.DrawString(" " + o, font, color, rect); font = savedFont; } } dtRow++; pageDataRow++; if ((pageDataRow > DataRowsPerPage) && (dtRow < dt.Rows.Count)) { pdf.NewPage(); } } } } private void DrawHeaderField(int numColumns, int numRows, string columnLetter, C1PdfDocument pdf, C1.WPF.Pdf.Pen pen, WorksheetPart ws, SharedStringTablePart shareStringPart, C1.WPF.Pdf.Font font, System.Windows.Media.Color color) { var size = new Size(FieldSize(numColumns), RowSize * numRows); //1 is temp var point = new Point(XPoint, YPoint); var rect = new Rect(point, size); pdf.FillRectangle(System.Windows.Media.Color.FromRgb(221, 235, 247), rect); pdf.DrawLine(pen, rect.TopLeft, rect.BottomLeft); pdf.DrawLine(pen, rect.TopRight, rect.BottomRight); pdf.DrawLine(pen, rect.TopLeft, rect.TopRight); pdf.DrawLine(pen, rect.BottomLeft, rect.BottomRight); var cellString = GetCellString(columnLetter, (uint)RowNumber, ws, shareStringPart); var sf = new StringFormat(); sf.LineAlignment = VerticalAlignment.Bottom; pdf.DrawString(" " + cellString, font, color, rect, sf); } private void DrawChannelCalibrationHeaderFields(SpreadsheetDocument sp, Cell cell, DefinedName dn, string alphabet, int pageNum, C1PdfDocument pdf, C1.WPF.Pdf.Pen pen, WorksheetPart ws, SharedStringTablePart shareStringPart, System.Windows.Media.Color color) { // ("Location | Sensor Axis | Serial No | Cal | Next Cal") var font = GetPDFFont(sp, cell); var rowCol = GetRowCol(dn.Text); ColNumber = alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A'); RowNumber = GetRowNumber(rowCol[2], pageNum); DrawHeaderField(2, 1, "A", pdf, pen, ws, shareStringPart, font, color); //Location ColNumber++; ColNumber++; DrawHeaderField(2, 1, "C", pdf, pen, ws, shareStringPart, font, color); //Sensor Axis ColNumber++; ColNumber++; DrawHeaderField(2, 1, "E", pdf, pen, ws, shareStringPart, font, color); //Serial No ColNumber++; ColNumber++; DrawHeaderField(2, 1, "G", pdf, pen, ws, shareStringPart, font, color); //Cal ColNumber++; ColNumber++; DrawHeaderField(1, 1, "I", pdf, pen, ws, shareStringPart, font, color); //Next Cal } private void DrawLayoutHeaderFields(SpreadsheetDocument sp, Cell cell, DefinedName dn, string alphabet, int pageNum, C1PdfDocument pdf, C1.WPF.Pdf.Pen pen, WorksheetPart ws, SharedStringTablePart shareStringPart, System.Windows.Media.Color color) { var font = GetPDFFont(sp, cell); var rowCol = GetRowCol(dn.Text); ColNumber = alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A'); RowNumber = GetRowNumber(rowCol[2], pageNum); RowNumber--; DrawHeaderField(1, 2, "A", pdf, pen, ws, shareStringPart, font, color); //DCH ColNumber++; DrawHeaderField(1, 2, "B", pdf, pen, ws, shareStringPart, font, color); //Module ColNumber++; DrawHeaderField(1, 2, "C", pdf, pen, ws, shareStringPart, font, color); //Channel ColNumber++; DrawHeaderField(2, 2, "D", pdf, pen, ws, shareStringPart, font, color); //Description ColNumber++; ColNumber++; DrawHeaderField(2, 2, "F", pdf, pen, ws, shareStringPart, font, color); //Sensor S/N ColNumber++; ColNumber++; DrawHeaderField(2, 2, "H", pdf, pen, ws, shareStringPart, font, color); //ISOCode ColNumber++; ColNumber++; DrawHeaderField(1, 1, "J", pdf, pen, ws, shareStringPart, font, color); //Range ColNumber++; DrawHeaderField(1, 1, "K", pdf, pen, ws, shareStringPart, font, color); //Sens ColNumber--; RowNumber++; DrawHeaderField(2, 1, "J", pdf, pen, ws, shareStringPart, font, color); //Squib Fire Mode ColNumber++; ColNumber++; RowNumber--; DrawHeaderField(1, 1, "L", pdf, pen, ws, shareStringPart, font, color); //Filter RowNumber++; DrawHeaderField(1, 1, "L", pdf, pen, ws, shareStringPart, font, color); //Delay ColNumber++; RowNumber--; DrawHeaderField(1, 1, "M", pdf, pen, ws, shareStringPart, font, color); //Volt ColNumber++; DrawHeaderField(1, 1, "N", pdf, pen, ws, shareStringPart, font, color); //L-Trigger ColNumber--; RowNumber++; DrawHeaderField(2, 1, "M", pdf, pen, ws, shareStringPart, font, color); //Duration } private void DrawDiagnosticsDASHeaderFields(SpreadsheetDocument sp, Cell cell, DefinedName dn, string alphabet, int pageNum, C1PdfDocument pdf, C1.WPF.Pdf.Pen pen, WorksheetPart ws, SharedStringTablePart shareStringPart, System.Windows.Media.Color color) { var font = GetPDFFont(sp, cell); var rowCol = GetRowCol(dn.Text); ColNumber = (alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A')); RowNumber = GetRowNumber(rowCol[2], pageNum); DrawHeaderField(1, 1, "A", pdf, pen, ws, shareStringPart, font, color); //DAS S/N ColNumber++; DrawHeaderField(2, 1, "B", pdf, pen, ws, shareStringPart, font, color); //Firmware ColNumber++; ColNumber++; DrawHeaderField(2, 1, "D", pdf, pen, ws, shareStringPart, font, color); //Cal Date ColNumber++; ColNumber++; DrawHeaderField(2, 1, "F", pdf, pen, ws, shareStringPart, font, color); //Due Date ColNumber++; ColNumber++; DrawHeaderField(3, 1, "H", pdf, pen, ws, shareStringPart, font, color); //Connection ColNumber++; ColNumber++; ColNumber++; DrawHeaderField(2, 1, "K", pdf, pen, ws, shareStringPart, font, color); //Input (V) ColNumber++; ColNumber++; DrawHeaderField(2, 1, "M", pdf, pen, ws, shareStringPart, font, color); //Battery (V) } private void DrawDASHeaderFields(SpreadsheetDocument sp, Cell cell, DefinedName dn, string alphabet, int pageNum, C1PdfDocument pdf, C1.WPF.Pdf.Pen pen, WorksheetPart ws, SharedStringTablePart shareStringPart, System.Windows.Media.Color color) { var font = GetPDFFont(sp, cell); var rowCol = GetRowCol(dn.Text); ColNumber = alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A'); RowNumber = GetRowNumber(rowCol[2], pageNum); DrawHeaderField(2, 1, "A", pdf, pen, ws, shareStringPart, font, color); //DAS S/N ColNumber++; ColNumber++; DrawHeaderField(2, 1, "C", pdf, pen, ws, shareStringPart, font, color); //Firmware ColNumber++; ColNumber++; DrawHeaderField(2, 1, "E", pdf, pen, ws, shareStringPart, font, color); //Cal Date ColNumber++; ColNumber++; DrawHeaderField(2, 1, "G", pdf, pen, ws, shareStringPart, font, color); //Due Date ColNumber++; ColNumber++; DrawHeaderField(2, 1, "I", pdf, pen, ws, shareStringPart, font, color); //SPS ColNumber++; ColNumber++; DrawHeaderField(1, 1, "K", pdf, pen, ws, shareStringPart, font, color); //AAF ColNumber++; DrawHeaderField(1, 1, "L", pdf, pen, ws, shareStringPart, font, color); //Pre Trig ColNumber++; DrawHeaderField(1, 1, "M", pdf, pen, ws, shareStringPart, font, color); //Post Trig ColNumber++; DrawHeaderField(1, 1, "N", pdf, pen, ws, shareStringPart, font, color); //Channels } private void DrawSensor_ChannelsHeaderFields(SpreadsheetDocument sp, Cell cell, DefinedName dn, string alphabet, int pageNum, C1PdfDocument pdf, C1.WPF.Pdf.Pen pen, WorksheetPart ws, SharedStringTablePart shareStringPart, System.Windows.Media.Color color) { // ("# |DAS/Rack |Channel |Sensor S/N |EID |Description |ISOCode |EU |Range (CAC) |Sensitivity |Prop Exc |Cal Due Date |Polarity |Volt |Filter ") // Module and Ltrig are hidden for now var font = GetPDFFont(sp, cell); var rowCol = GetRowCol(dn.Text); ColNumber = (alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A')); RowNumber = GetRowNumber(rowCol[2], pageNum); DrawHeaderField(1, 1, "A", pdf, pen, ws, shareStringPart, font, color); //# ColNumber++; DrawHeaderField(2, 1, "B", pdf, pen, ws, shareStringPart, font, color); //DAS/Rack ColNumber++; ColNumber++; DrawHeaderField(1, 1, "D", pdf, pen, ws, shareStringPart, font, color); //Channel ColNumber++; DrawHeaderField(2, 1, "E", pdf, pen, ws, shareStringPart, font, color); //Sensor S/N ColNumber++; ColNumber++; DrawHeaderField(1, 1, "G", pdf, pen, ws, shareStringPart, font, color); //EID ColNumber++; DrawHeaderField(2, 1, "H", pdf, pen, ws, shareStringPart, font, color); //Description ColNumber++; ColNumber++; DrawHeaderField(2, 1, "J", pdf, pen, ws, shareStringPart, font, color); //ISOCode ColNumber++; ColNumber++; DrawHeaderField(1, 1, "L", pdf, pen, ws, shareStringPart, font, color); //EU ColNumber++; DrawHeaderField(1, 1, "M", pdf, pen, ws, shareStringPart, font, color); //Range (CAC) ColNumber++; DrawHeaderField(1, 1, "N", pdf, pen, ws, shareStringPart, font, color); //Sensitivity ColNumber++; DrawHeaderField(1, 1, "O", pdf, pen, ws, shareStringPart, font, color); //Prop Exc ColNumber++; DrawHeaderField(2, 1, "P", pdf, pen, ws, shareStringPart, font, color); //Cal Due Date ColNumber++; ColNumber++; DrawHeaderField(1, 1, "R", pdf, pen, ws, shareStringPart, font, color); //Polarity ColNumber++; DrawHeaderField(1, 1, "S", pdf, pen, ws, shareStringPart, font, color); //Volt ColNumber++; DrawHeaderField(1, 1, "T", pdf, pen, ws, shareStringPart, font, color); //Filter } private void DrawDigital_ChannelsHeaderFields(SpreadsheetDocument sp, Cell cell, DefinedName dn, string alphabet, int pageNum, C1PdfDocument pdf, C1.WPF.Pdf.Pen pen, WorksheetPart ws, SharedStringTablePart shareStringPart, System.Windows.Media.Color color) { // ("# |DAS |Module |Channel |Description |ISOCode |Scale |INV ") var font = GetPDFFont(sp, cell); var rowCol = GetRowCol(dn.Text); ColNumber = (alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A')); RowNumber = GetRowNumber(rowCol[2], pageNum); DrawHeaderField(1, 1, "A", pdf, pen, ws, shareStringPart, font, color); //# ColNumber++; DrawHeaderField(1, 1, "B", pdf, pen, ws, shareStringPart, font, color); //DAS ColNumber++; DrawHeaderField(1, 1, "C", pdf, pen, ws, shareStringPart, font, color); //Module ColNumber++; DrawHeaderField(1, 1, "D", pdf, pen, ws, shareStringPart, font, color); //Channel ColNumber++; DrawHeaderField(3, 1, "E", pdf, pen, ws, shareStringPart, font, color); //Description ColNumber++; ColNumber++; ColNumber++; DrawHeaderField(2, 1, "H", pdf, pen, ws, shareStringPart, font, color); //ISOCode ColNumber++; ColNumber++; DrawHeaderField(2, 1, "H", pdf, pen, ws, shareStringPart, font, color); //Scale ColNumber++; ColNumber++; DrawHeaderField(3, 1, "H", pdf, pen, ws, shareStringPart, font, color); //INV } private void DrawSquib_ChannelsHeaderFields(SpreadsheetDocument sp, Cell cell, DefinedName dn, string alphabet, int pageNum, C1PdfDocument pdf, C1.WPF.Pdf.Pen pen, WorksheetPart ws, SharedStringTablePart shareStringPart, System.Windows.Media.Color color) { // ("# |DAS/Rack |Channel |Name |EID |Description |ISOCode |Delay |Duration |Squib Fire Mode ") var font = GetPDFFont(sp, cell); var rowCol = GetRowCol(dn.Text); ColNumber = (alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A')); RowNumber = GetRowNumber(rowCol[2], pageNum); DrawHeaderField(1, 1, "A", pdf, pen, ws, shareStringPart, font, color); //# ColNumber++; DrawHeaderField(2, 1, "B", pdf, pen, ws, shareStringPart, font, color); //DAS/Rack ColNumber++; //DrawHeaderField(1, 1, "C", pdf, pen, ws, shareStringPart, font, color); //Module ColNumber++; DrawHeaderField(1, 1, "D", pdf, pen, ws, shareStringPart, font, color); //Channel ColNumber++; DrawHeaderField(1, 1, "E", pdf, pen, ws, shareStringPart, font, color); //Name ColNumber++; DrawHeaderField(1, 1, "F", pdf, pen, ws, shareStringPart, font, color); //EID ColNumber++; DrawHeaderField(3, 1, "G", pdf, pen, ws, shareStringPart, font, color); //Description ColNumber++; ColNumber++; ColNumber++; DrawHeaderField(2, 1, "J", pdf, pen, ws, shareStringPart, font, color); //ISOCode ColNumber++; ColNumber++; DrawHeaderField(1, 1, "L", pdf, pen, ws, shareStringPart, font, color); //Delay ColNumber++; DrawHeaderField(1, 1, "M", pdf, pen, ws, shareStringPart, font, color); //Duration ColNumber++; DrawHeaderField(3, 1, "N", pdf, pen, ws, shareStringPart, font, color); //Squib Fire Mode } private void DrawCalculated_ChannelsHeaderFields(SpreadsheetDocument sp, Cell cell, DefinedName dn, string alphabet, int pageNum, C1PdfDocument pdf, C1.WPF.Pdf.Pen pen, WorksheetPart ws, SharedStringTablePart shareStringPart, System.Windows.Media.Color color) { // ("# |Description |ISOCode |Type |Val1 |Val2 |Val3 |Units |Input Channels ") var font = GetPDFFont(sp, cell); var rowCol = GetRowCol(dn.Text); ColNumber = (alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A')); RowNumber = GetRowNumber(rowCol[2], pageNum); DrawHeaderField(1, 1, "A", pdf, pen, ws, shareStringPart, font, color); //# ColNumber++; DrawHeaderField(3, 1, "B", pdf, pen, ws, shareStringPart, font, color); //Description ColNumber++; ColNumber++; ColNumber++; DrawHeaderField(2, 1, "E", pdf, pen, ws, shareStringPart, font, color); //ISOCode ColNumber++; ColNumber++; DrawHeaderField(2, 1, "G", pdf, pen, ws, shareStringPart, font, color); //Type ColNumber++; ColNumber++; DrawHeaderField(1, 1, "I", pdf, pen, ws, shareStringPart, font, color); //Val1 ColNumber++; DrawHeaderField(1, 1, "J", pdf, pen, ws, shareStringPart, font, color); //Val2 ColNumber++; DrawHeaderField(1, 1, "K", pdf, pen, ws, shareStringPart, font, color); //Val3 ColNumber++; DrawHeaderField(1, 1, "L", pdf, pen, ws, shareStringPart, font, color); //Units ColNumber++; DrawHeaderField(2, 1, "M", pdf, pen, ws, shareStringPart, font, color); //Input Channels } private void DrawAnalogHeaderFields(SpreadsheetDocument sp, Cell cell, DefinedName dn, string alphabet, int pageNum, C1PdfDocument pdf, C1.WPF.Pdf.Pen pen, WorksheetPart ws, SharedStringTablePart shareStringPart, System.Windows.Media.Color color) { // ("# |DAS |Module |Channel |Group |Sens S/N |Description |Exc |Offset |Shunt |Range |Noise ") var font = GetPDFFont(sp, cell); var rowCol = GetRowCol(dn.Text); ColNumber = (alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A')); RowNumber = GetRowNumber(rowCol[2], pageNum); DrawHeaderField(1, 1, "A", pdf, pen, ws, shareStringPart, font, color); //# ColNumber++; DrawHeaderField(1, 1, "B", pdf, pen, ws, shareStringPart, font, color); //DAS ColNumber++; DrawHeaderField(1, 1, "C", pdf, pen, ws, shareStringPart, font, color); //Module ColNumber++; DrawHeaderField(1, 1, "D", pdf, pen, ws, shareStringPart, font, color); //Channel ColNumber++; DrawHeaderField(1, 1, "E", pdf, pen, ws, shareStringPart, font, color); //Group ColNumber++; DrawHeaderField(2, 1, "F", pdf, pen, ws, shareStringPart, font, color); //Sens S/N ColNumber++; ColNumber++; DrawHeaderField(2, 1, "H", pdf, pen, ws, shareStringPart, font, color); //Description ColNumber++; ColNumber++; DrawHeaderField(1, 1, "J", pdf, pen, ws, shareStringPart, font, color); //Exc ColNumber++; DrawHeaderField(1, 1, "K", pdf, pen, ws, shareStringPart, font, color); //Offset ColNumber++; DrawHeaderField(1, 1, "L", pdf, pen, ws, shareStringPart, font, color); //Shunt ColNumber++; DrawHeaderField(1, 1, "M", pdf, pen, ws, shareStringPart, font, color); //Range ColNumber++; DrawHeaderField(1, 1, "N", pdf, pen, ws, shareStringPart, font, color); //Noise } private void DrawSquibsHeaderFields(SpreadsheetDocument sp, Cell cell, DefinedName dn, string alphabet, int pageNum, C1PdfDocument pdf, C1.WPF.Pdf.Pen pen, WorksheetPart ws, SharedStringTablePart shareStringPart, System.Windows.Media.Color color) { // ("DAS |Module |Channel |Description |ISOCode |Fire Mode |Delay |Duration ") var font = GetPDFFont(sp, cell); var rowCol = GetRowCol(dn.Text); ColNumber = (alphabet.IndexOf(rowCol[1]) - alphabet.IndexOf('A')); RowNumber = GetRowNumber(rowCol[2], pageNum); DrawHeaderField(1, 1, "A", pdf, pen, ws, shareStringPart, font, color); //DAS ColNumber++; DrawHeaderField(1, 1, "B", pdf, pen, ws, shareStringPart, font, color); //Module ColNumber++; DrawHeaderField(1, 1, "C", pdf, pen, ws, shareStringPart, font, color); //Channel ColNumber++; DrawHeaderField(2, 1, "D", pdf, pen, ws, shareStringPart, font, color); //Description ColNumber++; ColNumber++; DrawHeaderField(2, 1, "F", pdf, pen, ws, shareStringPart, font, color); //ISOCode ColNumber++; ColNumber++; DrawHeaderField(2, 1, "H", pdf, pen, ws, shareStringPart, font, color); //Fire Mode ColNumber++; ColNumber++; DrawHeaderField(1, 1, "J", pdf, pen, ws, shareStringPart, font, color); //Delay ColNumber++; DrawHeaderField(2, 1, "K", pdf, pen, ws, shareStringPart, font, color); //Duration } public string GetCellString(string dnText, WorksheetPart ws, SharedStringTablePart shareStringPart) { var cellValue = GetCellValue(ws.Worksheet, dnText); if (cellValue == null) { return null; } int.TryParse(cellValue.Text, out int cellValueInt); var sharedStringItems = shareStringPart.SharedStringTable.Descendants(); var sharedStringItemsArray = sharedStringItems.ToArray(); return sharedStringItemsArray[cellValueInt].Text.Text.ToString(); } private string GetCellString(string columnLetter, uint rowNumber, WorksheetPart ws, SharedStringTablePart shareStringPart) { var cellValue = GetCellValue(ws.Worksheet, columnLetter, rowNumber); if (cellValue == null) { return null; } int.TryParse(cellValue.Text, out int cellValueInt); var sharedStringItems = shareStringPart.SharedStringTable.Descendants(); var sharedStringItemsArray = sharedStringItems.ToArray(); return sharedStringItemsArray[cellValueInt].Text.Text.ToString(); } private Alignment GetCellAlignment(SpreadsheetDocument sp, Cell cell) { var styles = sp.WorkbookPart.WorkbookStylesPart; var cellStyleIndex = (int)cell.StyleIndex.Value; var cellFormat = (CellFormat)styles.Stylesheet.CellFormats.ChildElements[cellStyleIndex]; return cellFormat.Alignment; } public C1.WPF.Pdf.Font GetPDFFont(SpreadsheetDocument sp, Cell cell) { var pdfFontStyle = PdfFontStyle.Regular; var cellFont = GetCellFont(sp, cell); var cellFontName = cellFont.FontName.Val; var cellFontSize = cellFont.FontSize.Val; if (cellFont.Bold != null) { pdfFontStyle |= PdfFontStyle.Bold; } if (cellFont.Italic != null) { pdfFontStyle |= PdfFontStyle.Italic; } if (cellFont.Strike != null) { pdfFontStyle |= PdfFontStyle.Strikeout; } if (cellFont.Underline != null) { pdfFontStyle |= PdfFontStyle.Underline; } return new C1.WPF.Pdf.Font(cellFontName, cellFontSize, pdfFontStyle); } private DocumentFormat.OpenXml.Spreadsheet.Font GetCellFont(SpreadsheetDocument sp, Cell cell) { var f = new DocumentFormat.OpenXml.Spreadsheet.Font(); //.Bold b = new Bold(); var styles = sp.WorkbookPart.WorkbookStylesPart; DocumentFormat.OpenXml.Spreadsheet.Fonts fonts = styles.Stylesheet.Fonts; var cellStyleIndex = (int)cell.StyleIndex.Value; var cellFormat = (CellFormat)styles.Stylesheet.CellFormats.ChildElements[cellStyleIndex]; return (DocumentFormat.OpenXml.Spreadsheet.Font)fonts.ChildElements[int.Parse(cellFormat.FontId.ToString())]; } public int GetRowNumber(string rowCol, int pageNum) { int.TryParse(rowCol, out int rowNumber); return rowNumber - (RowsPerPage * pageNum); //pageNum is 0-relative } /// /// creates a new cellformat, returns the index of the format /// /// /// /// /// /// public UInt32Value createCellFormat( Stylesheet styleSheet, UInt32Value fontIndex, UInt32Value fillIndex, UInt32Value numberFormatId) { var cellFormat = new CellFormat(); if (fontIndex != null) cellFormat.FontId = fontIndex; if (fillIndex != null) cellFormat.FillId = fillIndex; if (numberFormatId != null) { cellFormat.NumberFormatId = numberFormatId; cellFormat.ApplyNumberFormat = BooleanValue.FromBoolean(true); } styleSheet.CellFormats.Append(cellFormat); var result = styleSheet.CellFormats.Count; styleSheet.CellFormats.Count++; return result; } /// /// creates a new fill for a style /// /// /// /// public UInt32Value createFill( Stylesheet styleSheet, System.Drawing.Color fillColor) { var fill = new Fill( new PatternFill( new ForegroundColor() { Rgb = new HexBinaryValue() { Value = System.Drawing.ColorTranslator.ToHtml( System.Drawing.Color.FromArgb( fillColor.A, fillColor.R, fillColor.G, fillColor.B)).Replace("#", "") } }) { PatternType = PatternValues.Solid } ); styleSheet.Fills.Append(fill); UInt32Value result = styleSheet.Fills.Count; styleSheet.Fills.Count++; return result; } /// /// delete a page in the worksheet /// this involves deleting all the rows corresponding to the page /// as well as any merged cells /// /// /// protected virtual void DeletePage(TablePage page, Worksheet ws) { for (var i = Convert.ToUInt32(page.PageEnd); i >= Convert.ToUInt32(page.PageStart); i--) { GetRow(ws, i).Remove(); var toDelete = new List(); var mergeCells = ws.Descendants(); foreach (var m in mergeCells) { if (GetRowIndex(m) == i) { toDelete.Add(m); } } foreach (var m in toDelete) { m.Remove(); } } } /// /// ranges in excel come in the form of A1:D30, here for convenious we store the splitter for efficiency when parsing named ranges /// protected static char[] _rangeSplitter = new char[] { ':' }; /// /// gets the row index of a mergecell /// merge cells are in the form XXYY:JJKK /// where XX is the column of the upper left corner, YY is the row of the upper left corner, /// and JJ is the column of the lower right, and KK is the row of the lower right /// note that columns are in letters while rows are in digits /// /// /// protected virtual int GetRowIndex(MergeCell m) { var tokens = m.Reference.Value.Split(_rangeSplitter); //token [0] shold be in the form AA12, but we don't have a helper class for cellreference? var numbers = new string((from c in tokens[0] where char.IsDigit(c) select c).ToArray()); return int.Parse(numbers); } /// /// delete file if one already exists in the output directory /// we could alternatively time stamp then /// protected virtual void DeleteExistingReport() { if (System.IO.File.Exists(OutputFilename)) { System.IO.File.Delete(OutputFilename); } } protected virtual void DeleteExistingPDFTemplate() { if (System.IO.File.Exists(DestinationTemplateFilename)) { System.IO.File.Delete(DestinationTemplateFilename); } } /// /// copy our template file to the output directory /// presumbably the templates are all in a template directory /// and the output directory is in the test\reports directory /// protected virtual void CopyTemplate() { var fi = new System.IO.FileInfo(OutputFilename); if (!fi.Directory.Exists) { System.IO.Directory.CreateDirectory(fi.Directory.FullName); } System.IO.File.Copy(TemplateFilename, OutputFilename); } protected virtual void CopyExcelTemplateForPDF() { System.IO.File.Copy(TemplateFilename, DestinationTemplateFilename); } /// /// we've got lots of strings to go through, so we build a dictionary of all we know about for efficiency /// private Dictionary _stringLookup = null; // Given text and a SharedStringTablePart, creates a SharedStringItem with the specified text // and inserts it into the SharedStringTablePart. If the item already exists, returns its index. protected int InsertSharedStringItem(string text, SharedStringTablePart shareStringPart) { if (null == text) { text = ""; } // If the part does not contain a SharedStringTable, create one. if (shareStringPart.SharedStringTable == null) { shareStringPart.SharedStringTable = new SharedStringTable(); } if (null == _stringLookup) { var i = 0; _stringLookup = new Dictionary(); foreach (var item in shareStringPart.SharedStringTable.Elements()) { _stringLookup[item.InnerText] = i++; } } //if the string is already in the table, return it's index, otherwise add a new string to the table and return the new index if (_stringLookup.ContainsKey(text)) { return _stringLookup[text]; } else { var i = _stringLookup.Count; shareStringPart.SharedStringTable.AppendChild(new SharedStringItem(new Text(text))); shareStringPart.SharedStringTable.Save(); _stringLookup[text] = i; return i; } } /// /// gets a worksheet, given a sheet id and a spreadsheet /// /// /// /// protected WorksheetPart GetWorksheetPartByName(SpreadsheetDocument document, string sheetName) { var sheets = document.WorkbookPart.Workbook.GetFirstChild(). Elements().Where(s => s.Name == sheetName); if (sheets.Count() == 0) { // The specified worksheet does not exist. return null; } var relationshipId = sheets.First().Id.Value; var worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(relationshipId); return worksheetPart; } /// /// gets a cell given a work sheet and a strong cell reference /// cell reference should be in the form SheetId!$Column$Row, /// like DefinedNames use /// /// /// /// protected Cell GetCell(Worksheet worksheet, string nameref) { var tokens = nameref.Split(new char[] { '!' }); nameref = tokens[1]; nameref = nameref.Replace("$", ""); var theCell = worksheet.Descendants(). Where(c => c.CellReference == nameref).FirstOrDefault(); return theCell; } protected CellValue GetCellValue(Worksheet worksheet, string nameref) { var tokens = nameref.Split(new char[] { '!' }); nameref = tokens[1]; nameref = nameref.Replace("$", ""); var theCell = worksheet.Descendants(). Where(c => c.CellReference == nameref).FirstOrDefault(); return theCell.CellValue; } protected CellValue GetCellValue(Worksheet worksheet, string columnLetter, uint rowNumber) { var nameref = columnLetter + rowNumber.ToString(); var theCell = worksheet.Descendants(). Where(c => c.CellReference == nameref).FirstOrDefault(); return theCell.CellValue; } protected string[] GetRowCol(string nameref) { var tokens = nameref.Split(new char[] { '!' }); nameref = tokens[1]; var rowCol = nameref.Split(new char[] { '$' }); return rowCol; } /// /// returns a cell, given a worksheet, a column, and a row /// columns are letters in excel (example AA-ZZ) /// /// /// /// /// protected Cell GetCell(Worksheet worksheet, string columnName, uint rowIndex) { var row = GetRow(worksheet, rowIndex); if (row == null) return null; return row.Elements().Where(c => string.Compare (c.CellReference.Value, columnName + rowIndex, true) == 0).First(); } /// /// returns a row, given it's row index /// /// /// /// private Row GetRow(Worksheet worksheet, uint rowIndex) { return worksheet.GetFirstChild(). Elements().Where(r => r.RowIndex == rowIndex).First(); } protected void DeleteWorksheet(SpreadsheetDocument document, string sheetid) { var Sheetid = ""; //Open the workbook //using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, true)) { WorkbookPart wbPart = document.WorkbookPart; // Get the pivot Table Parts var pvtTableCacheParts = wbPart.PivotTableCacheDefinitionParts; var pvtTableCacheDefinationPart = new Dictionary(); foreach (var Item in pvtTableCacheParts) { var pvtCacheDef = Item.PivotCacheDefinition; //Check if this CacheSource is linked to SheetToDelete var pvtCahce = pvtCacheDef.Descendants().Where(s => s.WorksheetSource.Sheet == sheetid); if (pvtCahce.Count() > 0) { pvtTableCacheDefinationPart.Add(Item, Item.ToString()); } } foreach (var Item in pvtTableCacheDefinationPart) { wbPart.DeletePart(Item.Key); } //Get the SheetToDelete from workbook.xml var theSheet = wbPart.Workbook.Descendants().Where(s => s.Name == sheetid).FirstOrDefault(); if (theSheet == null) { // The specified sheet doesn't exist. } //Store the SheetID for the reference Sheetid = theSheet.SheetId; // Remove the sheet reference from the workbook. var worksheetPart = (WorksheetPart)(wbPart.GetPartById(theSheet.Id)); theSheet.Remove(); // Delete the worksheet part. wbPart.DeletePart(worksheetPart); //Get the DefinedNames var definedNames = wbPart.Workbook.Descendants().FirstOrDefault(); if (definedNames != null) { var defNamesToDelete = new List(); foreach (DefinedName Item in definedNames) { // This condition checks to delete only those names which are part of Sheet in question if (Item.Text.Contains(sheetid + "!")) { //System.Diagnostics.Trace.WriteLine("deleting " + Item.Text); defNamesToDelete.Add(Item); } } foreach (DefinedName Item in defNamesToDelete) { Item.Remove(); } } // Get the CalculationChainPart //Note: An instance of this part type contains an ordered set of references to all cells in all worksheets in the //workbook whose value is calculated from any formula CalculationChainPart calChainPart; calChainPart = wbPart.CalculationChainPart; if (calChainPart != null) { var calChainEntries = calChainPart.CalculationChain.Descendants().Where(c => c.SheetId == Sheetid); var calcsToDelete = new List(); foreach (var Item in calChainEntries) { calcsToDelete.Add(Item); } foreach (var Item in calcsToDelete) { Item.Remove(); } if (calChainPart.CalculationChain.Count() == 0) { wbPart.DeletePart(calChainPart); } } // Save the workbook. wbPart.Workbook.Save(); } } public static string GetTemplateReportPath() { return System.IO.Path.Combine(Environment.CurrentDirectory.Trim(), Common.Constants.REPORT_TEMPLATE_DIR_NAME); } public static string GetReportPath(string testDirectory) { return System.IO.Path.Combine(testDirectory.Trim(), Common.Constants.REPORT_DIR_NAME); } } }