570 lines
26 KiB
C#
570 lines
26 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Sarand.Net.Standard.Base.Core;
|
|
using Sarand.Net.Standard.Base.Bus;
|
|
using Sarand.Net.Standard.Base.App;
|
|
using Sarand.Net.Standard.Base.Utils;
|
|
|
|
namespace Sarand.Net.Standard.Proc.Excel
|
|
{
|
|
//=======================================================================
|
|
// Some Excel enumerated values are replaced with local integers or
|
|
// equivalent enum to avoid errors related to:
|
|
// "Cannot be used across assembly boundaries because it has a
|
|
// generic type parameter that is an embedded interop type."
|
|
// eg. SaMsExcelItemAttr.HorizontalAlignment: short instead of XlHAlign.
|
|
//=======================================================================
|
|
public class SaMsExcelRange
|
|
{
|
|
public uint ColFrom { get; set; } = 0;
|
|
public uint ColTo { get; set; } = 0;
|
|
public uint RowFrom { get; set; } = 0;
|
|
public uint RowTo { get; set; } = 0;
|
|
public SaMsExcelRange() { }
|
|
public SaMsExcelRange(uint colPos, uint rowPos)
|
|
{
|
|
ColFrom = colPos;
|
|
ColTo = colPos;
|
|
RowFrom = rowPos;
|
|
RowTo = rowPos;
|
|
}
|
|
public SaMsExcelRange(uint colPosFrom, uint rowPosFrom, uint colPosTo, uint rowPosTo)
|
|
{
|
|
ColFrom = colPosFrom;
|
|
ColTo = colPosTo;
|
|
RowFrom = rowPosFrom;
|
|
RowTo = rowPosTo;
|
|
}
|
|
}
|
|
//=======================================================================
|
|
public class SaMsExcelPageSetup_Config
|
|
{
|
|
public SaMsExcelPageSetup_Config()
|
|
{
|
|
}
|
|
/// <summary>Orientation: xlPortrait (1) or xlLandscape (2). Default: Not specified (ignore)</summary>
|
|
public SaXlPageOrientation Orientation { get; set; } = SaXlPageOrientation.NotSpecified;
|
|
/// <summary>Logical unit. Default: Point.</summary>
|
|
public SaExcelLogicalUnit Unit { get; set; } = SaExcelLogicalUnit.Point;
|
|
// Headers and footers.
|
|
// NB Font & size and page no and total pages can be encoded as: '&"Batang,Regular"&14Page &P of &N'
|
|
public String HeaderLeft { get; set; } = "";
|
|
public String HeaderCenter { get; set; } = "";
|
|
public String HeaderRight { get; set; } = "";
|
|
public String FooterLeft { get; set; } = "";
|
|
public String FooterCenter { get; set; } = "";
|
|
public String FooterRight { get; set; } = "";
|
|
// Margins.
|
|
// Negative values leave current value (default=-1.0).
|
|
public double MarginLeft { get; set; } = -1.0;
|
|
public double MarginRight { get; set; } = -1.0;
|
|
public double MarginTop { get; set; } = -1.0;
|
|
public double MarginBottom { get; set; } = -1.0;
|
|
public double MarginHeader { get; set; } = -1.0;
|
|
public double MarginFooter { get; set; } = -1.0;
|
|
// Negative values to leave current value, zero to clear (default=-1).
|
|
public int PrintTitleRowFrom { get; set; } = -1;
|
|
public int PrintTitleRowTo { get; set; } = -1;
|
|
public int PrintTitleColFrom { get; set; } = -1;
|
|
public int PrintTitleColTo { get; set; } = -1;
|
|
// Zoom or 'fit to' pages.
|
|
/// <summary>Zoom: 40 = 40%, default: -1.</summary>
|
|
public int Zoom { get; set; } = -1;
|
|
/// <summary>Fit to pages - Tall. 1 = 1 page tall, default = -1. [ignored if zoom > 0]</summary>
|
|
public int FitToPagesTall { get; set; } = -1;
|
|
/// <summary>Fit to pages - Wide. 1 = 1 page wide, default = -1. [ignored if zoom > 0]</summary>
|
|
public int FitToPagesWide { get; set; } = -1;
|
|
}
|
|
//=======================================================================
|
|
public class SaMsExcelColumnHeading_Config
|
|
{
|
|
public double ColumnWidthPixelsPerCm { get; set; } = 43.0; // Between 10 and 100
|
|
public uint FirstHeadingRow { get; set; } = 1; // Must be > 0
|
|
public uint FirstHeadingColumn { get; set; } = 1; // Must be > 0
|
|
public uint FreezeColumn { get; set; } = 0; // 0 = don't freeze
|
|
public short HeadingFontSize { get; set; } = 9;
|
|
public bool HeadingTextBold { get; set; } = true;
|
|
public bool HeadingTextWrap { get; set; } = true;
|
|
/// <summary>Cell font colour index, ref. XlColorIndex</summary>
|
|
public SaXlColourIndex InteriorColourIndex { get; set; } = SaXlColourIndex.NotSpecified;
|
|
/// <summary>Cell RGB colour value, ref. XlRgbColor. Overrides colour index if changed from default value.</summary>
|
|
public int? InteriorColour { get; set; } = null;
|
|
public SaXlBorderWeight BorderWeight { get; set; } = SaXlBorderWeight.NotSpecified;
|
|
public bool SetColumnWidths { get; set; } = true;
|
|
public bool SetColumnAlignment { get; set; } = true;
|
|
public bool SetColumnDataTypeFormat { get; set; } = true; // '@' for strings, '#,##0.00' for numeric depending on thousands/decimals
|
|
public String CellFormatDate { get; set; } = "d-mmm-yy";
|
|
public String CellFormatTime { get; set; } = "hh:mm";
|
|
public String CellFormatDateTimeDelim { get; set; } = " ";
|
|
}
|
|
//=======================================================================
|
|
public class SaMsExcelImage_Config
|
|
{
|
|
public SaMsExcelImage_Config() { }
|
|
public String ImagePath { get; set; } = "";
|
|
/// <summary>Column to insert image. Default: 0 (current position).</summary>
|
|
public uint ColPos { get; set; } = 0;
|
|
/// <summary>Row to insert image. Default: 0 (current position).</summary>
|
|
public uint RowPos { get; set; } = 0;
|
|
/// <summary>Image dimension units. Default: Point.</summary>
|
|
public SaExcelLogicalUnit Unit { get; set; } = SaExcelLogicalUnit.Point;
|
|
public double TargetWidth { get; set; } = 0.0;
|
|
public double TargetHeight { get; set; } = 0.0;
|
|
public double MaxWidth { get; set; } = 0.0;
|
|
public double MaxHeight { get; set; } = 0.0;
|
|
};
|
|
//=======================================================================
|
|
public class SaMsExcelBorderAttr
|
|
{
|
|
public SaMsExcelBorderAttr(XlBordersIndex index)
|
|
{
|
|
Index = index;
|
|
}
|
|
public bool IsSpecified
|
|
{
|
|
get
|
|
{
|
|
// Any attributes specified.
|
|
if (Weight != SaXlBorderWeight.NotSpecified) return true;
|
|
if (LineStyle != SaXlLineStyle.NotSpecified) return true;
|
|
if (ColorIndex != SaXlColourIndex.NotSpecified) return true;
|
|
if (Color != null) return true;
|
|
return false;
|
|
}
|
|
}
|
|
/// <summary>Border position. XlBordersIndex.xlEdgeLeft etc</summary>
|
|
public XlBordersIndex Index { get; }
|
|
/// <summary>Border thickness. XlBorderWeight.xlThin, XlBorderWeight.xlMedium etc.</summary>
|
|
public SaXlBorderWeight Weight { get; set; } = SaXlBorderWeight.NotSpecified;
|
|
/// <summary>Border line style. XlLineStyle.xlNone, XlLineStyle.xlContinuous, XlLineStyle.xlDash etc.</summary>
|
|
public SaXlLineStyle LineStyle { get; set; } = SaXlLineStyle.NotSpecified;
|
|
/// <summary>Border colour index, re. XlColorIndex. Black = 1 etc.</summary>
|
|
public SaXlColourIndex ColorIndex { get; set; } = SaXlColourIndex.NotSpecified;
|
|
/// <summary>Border RGB colour value, ref. XlRgbColor. Overrides colour index if changed from default value.</summary>
|
|
public int? Color { get; set; } = null;
|
|
}
|
|
//=======================================================================
|
|
public class SaMsExcelFontAttr
|
|
{
|
|
/// <summary>Font name. Arial etc.</summary>
|
|
public String FontName { get; set; } = String.Empty;
|
|
/// <summary>Font style. Regular etc.</summary>
|
|
public String FontStyle { get; set; } = String.Empty;
|
|
public short? FontSize { get; set; } = null;
|
|
/// <summary>Font colour index, ref. XlColorIndex.</summary>
|
|
public SaXlColourIndex FontColourIndex { get; set; } = SaXlColourIndex.NotSpecified;
|
|
/// <summary>Font RGB colour value, ref. XlRgbColor. Overrides colour index if changed from default value.</summary>
|
|
public int? FontColor { get; set; } = null;
|
|
public bool? Bold { get; set; } = null;
|
|
public bool? Strikethrough { get; set; } = null;
|
|
public bool? Superscript { get; set; } = null;
|
|
public bool? Subscript { get; set; } = null;
|
|
public bool? OutlineFont { get; set; } = null;
|
|
public bool? Shadow { get; set; } = null;
|
|
public SaXlUnderlineStyle? Underline { get; set; } = null;
|
|
}
|
|
//=======================================================================
|
|
public class SaMsExcelItemAttr : SaMsExcelFontAttr
|
|
{
|
|
// Item attributes.
|
|
// Attributes that are changed from their default (generally null) are set against the specified range.
|
|
/// <summary>Cell data format. "@"=Text etc.</summary>
|
|
public String NumberFormat { get; set; } = String.Empty;
|
|
/// <summary>Cell horizontal alignment. XlHAlign.xlHAlignLeft, xlHAlignCenter, xlHAlignRight etc.</summary>
|
|
public short? HorizontalAlignment { get; set; } = null;
|
|
/// <summary>Cell indentation. Tabbed - left, right or distributed alignment [0 to 6]</summary>
|
|
public short? IndentLevel { get; set; } = null;
|
|
/// <summary>Cell vertical alignment. XlVAlign.xlTop, xlCenter, xlBottom, xlJustify, xlDistributed etc.</summary>
|
|
public short? VerticalAlignment { get; set; } = null;
|
|
/// <summary>Whether to allow text to wrap in cells.</summary>
|
|
public bool? WrapText { get; set; } = null;
|
|
/// <summary>Whether cells are merged.</summary>
|
|
public bool? MergeCells { get; set; } = null;
|
|
/// <summary>Font colour index, ref. XlColorIndex. Black = 1 etc.</summary>
|
|
public SaXlColourIndex InteriorColourIndex { get; set; } = SaXlColourIndex.NotSpecified;
|
|
/// <summary>Cell RGB colour value, ref. XlRgbColor. Overrides colour index if changed from default value.</summary>
|
|
public int? InteriorColour { get; set; } = null;
|
|
/// <summary>Cell pattern, ref. XlPattern. xlSolid etc.</summary>
|
|
public SaXlPattern InteriorPattern { get; set; } = SaXlPattern.NotSpecified;
|
|
/// <summary>Cell pattern colour index, ref. XlColorIndex. xlAutomatic etc.</summary>
|
|
public SaXlColourIndex InteriorPatternColourIndex { get; set; } = SaXlColourIndex.NotSpecified;
|
|
/// <summary>Cell pattern RBG Colour value, ref. XlRgbColor. Overrides colour index if changed from default value.</summary>
|
|
public int? InteriorPatternColour { get; set; } = null;
|
|
// Borders.
|
|
public SaMsExcelBorderAttr BorderLeft { get; } = new SaMsExcelBorderAttr(XlBordersIndex.xlEdgeLeft);
|
|
public SaMsExcelBorderAttr BorderTop { get; } = new SaMsExcelBorderAttr(XlBordersIndex.xlEdgeTop);
|
|
public SaMsExcelBorderAttr BorderRight { get; } = new SaMsExcelBorderAttr(XlBordersIndex.xlEdgeRight);
|
|
public SaMsExcelBorderAttr BorderBottom { get; } = new SaMsExcelBorderAttr(XlBordersIndex.xlEdgeBottom);
|
|
public SaMsExcelBorderAttr BorderInsideVertical { get; } = new SaMsExcelBorderAttr(XlBordersIndex.xlInsideVertical);
|
|
public SaMsExcelBorderAttr BorderInsideHorizontal { get; } = new SaMsExcelBorderAttr(XlBordersIndex.xlInsideHorizontal);
|
|
public List<SaMsExcelBorderAttr> Borders
|
|
{
|
|
get
|
|
{
|
|
List<SaMsExcelBorderAttr> borders = new List<SaMsExcelBorderAttr>();
|
|
borders.Add(BorderLeft);
|
|
borders.Add(BorderTop);
|
|
borders.Add(BorderRight);
|
|
borders.Add(BorderBottom);
|
|
return borders;
|
|
}
|
|
}
|
|
}
|
|
//=======================================================================
|
|
public abstract class SaMsSpreadsheet : SaErrorStateItem
|
|
{
|
|
//-------------------------------------------------------------------
|
|
// Definitions.
|
|
public static int FontSizeMin { get; } = 4;
|
|
public static int FontSizeMax { get; } = 48;
|
|
public static int NullColour { get; } = 0x4a4d4120; /* AFX_RFX_LONG_PSEUDO_NULL */
|
|
|
|
//-------------------------------------------------------------------
|
|
// Data members.
|
|
|
|
//-------------------------------------------------------------------
|
|
protected SaMsSpreadsheet()
|
|
{
|
|
}
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (disposing)
|
|
{
|
|
}
|
|
base.Dispose(disposing);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// W o r k b o o k
|
|
//-------------------------------------------------------------------
|
|
public abstract bool IsWorkbookValid();
|
|
public abstract bool CreateWorkbook();
|
|
public abstract bool OpenWorkbook(String filePath);
|
|
public abstract bool SaveDocument(String filePath, int fileFormat = (int)SaXlFileFormat.Default /* Default: XlFileFormat.xlOpenXMLWorkbook */, bool bAutomaticallyOverwrite = false);
|
|
public abstract bool CloseWorkbook();
|
|
|
|
//-------------------------------------------------------------------
|
|
// W o r k s h e e t
|
|
//-------------------------------------------------------------------
|
|
/// <summary>Is the current worksheet valid.</summary>
|
|
public abstract bool IsWorksheetValid();
|
|
/// <summary>Number of worksheets in the workbook.</summary>
|
|
public abstract uint WorksheetCount { get; }
|
|
/// <summary>Set the worksheets in the workbook - sheets are added or removed to match the value.</summary>
|
|
public abstract bool SetWorksheetCount(int worksheetCount);
|
|
/// <summary>Add a worksheet to the workbook.</summary>
|
|
public abstract bool AddWorksheet(String name);
|
|
/// <summary>Remove the nth worksheet - position from 1.</summary>
|
|
public abstract bool RemoveWorksheet(uint worksheetPos);
|
|
/// <summary>Open the nth worksheet - position from 1.</summary>
|
|
public abstract bool OpenWorksheet(uint worksheetPos);
|
|
/// <summary>Get the position of the current worksheet. 0 = not open.</summary>
|
|
public abstract uint WorksheetPos { get; }
|
|
/// <summary>Get the name of the current worksheet.</summary>
|
|
public abstract String WorksheetName { get; set; }
|
|
/// <summary>Set the default attributes for the entire worksheet</summary>
|
|
public abstract bool SetWorksheetAttr(SaMsExcelItemAttr attr);
|
|
/// <summary>Close the current worksheet.</summary>
|
|
public abstract bool CloseWorksheet();
|
|
// Worksheet Page Setup.
|
|
/// <summary>Configure the Page Setup properties.</summary>
|
|
public abstract bool SetPageSetup(SaMsExcelPageSetup_Config pageSetupConfig);
|
|
/// <summary>Configure a page break at the specified cell.</summary>
|
|
public abstract bool SetPageBreak(uint colPos, uint rowPos);
|
|
|
|
//-------------------------------------------------------------------
|
|
// C o l u m n s
|
|
//-------------------------------------------------------------------
|
|
public abstract uint GetActiveColPos();
|
|
public abstract double GetColWidth(uint colPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point);
|
|
public abstract bool SetColWidth(uint colPos, double fWidth, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point);
|
|
|
|
//-------------------------------------------------------------------
|
|
// R o w s
|
|
//-------------------------------------------------------------------
|
|
public abstract uint GetActiveRowPos();
|
|
public abstract List<DataValue> GetRowDataValues(uint rowPos, int maxColumns = 0);
|
|
public abstract double GetRowHeight(uint rowPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point);
|
|
public abstract bool SetRowHeight(uint rowPos, double fHeight, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point);
|
|
|
|
//-------------------------------------------------------------------
|
|
// C e l l s
|
|
//-------------------------------------------------------------------
|
|
public abstract void SetActiveCell(uint colPos, uint rowPos);
|
|
public abstract String GetCellFormula(uint colPos, uint rowPos);
|
|
public abstract DataValue GetCellDataValue(uint colPos, uint rowPos);
|
|
public abstract bool SetCellFormula(uint colPos, uint rowPos, String value);
|
|
public abstract bool SetCellFormula(uint colPos, uint rowPos, String value, SaMsExcelItemAttr attr);
|
|
public abstract bool SetRowFormulas(uint colStart, uint row, List<Object> values);
|
|
public abstract bool SetRangeFormulas(SaMsExcelRange range, List<Object> values);
|
|
|
|
//-------------------------------------------------------------------
|
|
// Populate headings.
|
|
public bool SetColumnHeadings(List<ColumnDfn> columns, SaMsExcelColumnHeading_Config config)
|
|
{
|
|
ClearErrorState();
|
|
double columnWidthPixelsPerCm = Math.Min(100.0, Math.Max(10.0, config.ColumnWidthPixelsPerCm));
|
|
uint firstHeadingRow = (uint)Math.Max(1, config.FirstHeadingRow);
|
|
try
|
|
{
|
|
// Populate default heading cell attributes.
|
|
SaMsExcelItemAttr attrHdrDefault = new SaMsExcelItemAttr();
|
|
attrHdrDefault.Bold = config.HeadingTextBold;
|
|
attrHdrDefault.FontSize = (short)Math.Min(80, Math.Max(2, (int)config.HeadingFontSize));
|
|
attrHdrDefault.InteriorColourIndex = config.InteriorColourIndex;
|
|
if (config.InteriorColour != null)
|
|
attrHdrDefault.InteriorColour = config.InteriorColour;
|
|
if (config.BorderWeight != SaXlBorderWeight.NotSpecified)
|
|
{
|
|
attrHdrDefault.BorderLeft.Weight = config.BorderWeight;
|
|
attrHdrDefault.BorderTop.Weight = config.BorderWeight;
|
|
attrHdrDefault.BorderRight.Weight = config.BorderWeight;
|
|
attrHdrDefault.BorderBottom.Weight = config.BorderWeight;
|
|
attrHdrDefault.BorderInsideVertical.Weight = config.BorderWeight;
|
|
}
|
|
SaMsExcelRange rangeHeadings = new SaMsExcelRange(config.FirstHeadingColumn, firstHeadingRow, (uint)(config.FirstHeadingColumn + columns.Count - 1), firstHeadingRow);
|
|
SetRangeAttr(rangeHeadings, attrHdrDefault);
|
|
|
|
// Set default column attributes.
|
|
bool defaultColumnAttributesPopulated = false;
|
|
SaMsExcelItemAttr attrColDefault = new SaMsExcelItemAttr();
|
|
if (config.SetColumnAlignment)
|
|
{
|
|
attrColDefault.HorizontalAlignment = (short)XlHAlign.xlHAlignLeft;
|
|
defaultColumnAttributesPopulated = true;
|
|
}
|
|
if (config.SetColumnDataTypeFormat)
|
|
{
|
|
attrColDefault.NumberFormat = "@"; // '@' = 'Text' format.
|
|
defaultColumnAttributesPopulated = true;
|
|
}
|
|
if (defaultColumnAttributesPopulated)
|
|
{
|
|
SaMsExcelRange rangeColumns = new SaMsExcelRange(config.FirstHeadingColumn, 0, (uint)(config.FirstHeadingColumn + columns.Count - 1), 0);
|
|
SetRangeAttr(rangeColumns, attrColDefault);
|
|
}
|
|
|
|
// Populate column headings and specific styles.
|
|
List<Object> values = new List<Object>();
|
|
for (int columnIdx = 0; columnIdx < columns.Count; columnIdx++)
|
|
{
|
|
ColumnDfn column = columns[columnIdx];
|
|
uint col = (uint)(Math.Max(1, config.FirstHeadingColumn) + columnIdx);
|
|
SaMsExcelRange range = new SaMsExcelRange(col, firstHeadingRow);
|
|
|
|
// Specific heading cell attributes - none supported as yet.
|
|
bool headingCellHasSpecificAttr = false;
|
|
SaMsExcelItemAttr attrHdr = new SaMsExcelItemAttr();
|
|
if (headingCellHasSpecificAttr)
|
|
SetRangeAttr(range, attrHdr);
|
|
|
|
// Column width and caption:
|
|
if (config.SetColumnWidths) SetColWidth(col, column.Width / columnWidthPixelsPerCm, SaExcelLogicalUnit.Cm);
|
|
values.Add(column.Caption);
|
|
|
|
// Column attributes:
|
|
bool columnHasSpecificAttributes = false;
|
|
SaMsExcelItemAttr attrCol = new SaMsExcelItemAttr();
|
|
if (config.SetColumnAlignment && column.Alignment != ColumnAlignment.Left && column.Alignment != ColumnAlignment.Default)
|
|
{
|
|
columnHasSpecificAttributes = true;
|
|
switch (column.Alignment)
|
|
{
|
|
case ColumnAlignment.Center: attrCol.HorizontalAlignment = (short)XlHAlign.xlHAlignCenter; break;
|
|
case ColumnAlignment.Right: attrCol.HorizontalAlignment = (short)XlHAlign.xlHAlignRight; break;
|
|
}
|
|
}
|
|
if (config.SetColumnDataTypeFormat && column.DataType != DataValue.DataType.String)
|
|
{
|
|
columnHasSpecificAttributes = true;
|
|
if (column.DataType == DataValue.DataType.Long || column.DataType == DataValue.DataType.Double || column.DataType == DataValue.DataType.Decimal)
|
|
{
|
|
// Numeric format: "#,##0.00"
|
|
String numberFormat = "0";
|
|
if (column.NumThousands != '\0')
|
|
{
|
|
numberFormat = "###" + numberFormat;
|
|
numberFormat = numberFormat.Insert(1, column.NumThousands.ToString()); // Ends up as '#,##0'.
|
|
}
|
|
if ((column.DataType == DataValue.DataType.Double || column.DataType == DataValue.DataType.Decimal) && column.NumDecimals > 0)
|
|
numberFormat += "." + "0".PadRight(column.NumDecimals, '0');
|
|
attrCol.NumberFormat = numberFormat + ";[Red]-" + numberFormat;
|
|
}
|
|
else if (column.DataType == DataValue.DataType.Date) attrCol.NumberFormat = config.CellFormatDate;
|
|
else if (column.DataType == DataValue.DataType.Time) attrCol.NumberFormat = config.CellFormatTime;
|
|
else if (column.DataType == DataValue.DataType.DateTime) attrCol.NumberFormat = config.CellFormatDate + config.CellFormatDateTimeDelim + config.CellFormatTime;
|
|
}
|
|
if (columnHasSpecificAttributes)
|
|
SetRangeAttr(new SaMsExcelRange(col, 0), attrCol);
|
|
// Freeze the window below if a colmn has been specified:
|
|
if (config.FreezeColumn > 0) FreezePanes(config.FreezeColumn, firstHeadingRow + 1);
|
|
}
|
|
// Populate header captions.
|
|
SetRowFormulas(config.FirstHeadingColumn, firstHeadingRow, values);
|
|
// Set header row to wrap text:
|
|
if (config.HeadingTextWrap)
|
|
{
|
|
SaMsExcelItemAttr attrRow = new SaMsExcelItemAttr();
|
|
attrRow.WrapText = true;
|
|
SetRangeAttr(new SaMsExcelRange(0, firstHeadingRow), attrRow);
|
|
// Auto fit the header row (set height to fit text):
|
|
AutoFit(new SaMsExcelRange(0, firstHeadingRow));
|
|
}
|
|
}
|
|
catch (Exception exc) { HandleException("SetColumnHeadings", exc); }
|
|
return !HasErrorState();
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Cell attributes.
|
|
public abstract bool SetRangeAttr(SaMsExcelRange range, SaMsExcelItemAttr attr);
|
|
|
|
//-------------------------------------------------------------------
|
|
// Add image to sheet.
|
|
public abstract bool InsertImage(SaMsExcelImage_Config imageConfig);
|
|
|
|
//-------------------------------------------------------------------
|
|
public abstract bool FreezePanes(uint colPos, uint rowPos);
|
|
|
|
//-------------------------------------------------------------------
|
|
public abstract bool AutoFit(SaMsExcelRange range);
|
|
|
|
//-------------------------------------------------------------------
|
|
public abstract bool SelectRange(SaMsExcelRange range);
|
|
|
|
//-------------------------------------------------------------------
|
|
// Utilities.
|
|
public static String GetRangeId(SaMsExcelRange range, bool fixedCols = false, bool fixedRows = false)
|
|
{
|
|
// Not fixed: "A9:AB34"
|
|
// Fixed cols: "$A9:$AB34"
|
|
// Fixed rows: "A$9:AB$34"
|
|
// Fixed: "$A$9:$AB$34"
|
|
return (fixedCols ? "$" : "") + GetColumnPrefix(range.ColFrom) + (fixedRows ? "$" : "") + GetRowSuffix(range.RowFrom) + ":" + (fixedCols ? "$" : "") + GetColumnPrefix(range.ColTo) + (fixedRows ? "$" : "") + GetRowSuffix(range.RowTo);
|
|
}
|
|
public static String GetColumnPrefix(uint colPos)
|
|
{
|
|
// 1=A,2=B,3=C...26=Z,27=AA,28=AB etc
|
|
uint dividend = colPos;
|
|
string columnName = String.Empty;
|
|
uint modulo = 0;
|
|
while (dividend > 0)
|
|
{
|
|
modulo = (dividend - 1) % 26;
|
|
columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
|
|
dividend = (uint)((dividend - modulo) / 26);
|
|
}
|
|
return columnName;
|
|
}
|
|
public static int GetIndexForCol(String column)
|
|
{
|
|
// A=1,B=2,C=3...Z=26,AA=27 etc
|
|
int col = (column[0] - 'A');
|
|
if (column.Length > 1)
|
|
col = (column[1] * 26) + column[0];
|
|
return col;
|
|
}
|
|
public static String GetColumnId(uint colPos)
|
|
{
|
|
// To reference entire column: A:A,B:A,C:A...Z:Z,AA:AA etc
|
|
return GetColumnPrefix(colPos) + ":" + GetColumnPrefix(colPos);
|
|
}
|
|
public static String GetRowSuffix(uint rowPos)
|
|
{
|
|
// 1,2,3...26,27,28 etc
|
|
return (rowPos > 0 ? rowPos.ToString() : "");
|
|
}
|
|
public static String GetRowId(uint rowPos)
|
|
{
|
|
// To reference entire row: 1:1,2:2,3:3 etc
|
|
return GetRowSuffix(rowPos) + ":" + GetRowSuffix(rowPos);
|
|
}
|
|
public static String GetCellId(uint colPos, uint rowPos)
|
|
{
|
|
return GetColumnPrefix(colPos) + GetRowSuffix(rowPos);
|
|
}
|
|
public static DateTime ExtractDate(String value)
|
|
{
|
|
DateTime date = DateTime.MinValue;
|
|
// TODO SaMsSpreadsheet.ExtractDate
|
|
return date;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// L e n g t h U n i t C o n v e r s i o n
|
|
//-------------------------------------------------------------------
|
|
// Points
|
|
// - 72 per inch
|
|
// EMU - English Metric Unit
|
|
// - 914400 EMUs per inch
|
|
// - EMU = inch * 914400
|
|
// - EMU = pixel * 914400 / 96 (assuming 96 dpi)
|
|
//-------------------------------------------------------------------
|
|
public static double PointsPerInch { get; } = 72;
|
|
public static double PixelsPerInch { get; } = 96;
|
|
public static double CmsPerInch { get; } = 2.54f;
|
|
public double ConvertLength(double fLength, SaExcelLogicalUnit eUnitFrom, SaExcelLogicalUnit eUnitTo, bool bVertical)
|
|
{
|
|
// Convert length to points:
|
|
double fLengthPoints = fLength;
|
|
if (eUnitFrom == SaExcelLogicalUnit.Pixel) fLengthPoints = PixelsToPoints(fLength, bVertical);
|
|
else if (eUnitFrom == SaExcelLogicalUnit.Cm) fLengthPoints = CmsToPoints(fLength);
|
|
else if (eUnitFrom == SaExcelLogicalUnit.Inch) fLengthPoints = InchesToPoints(fLength);
|
|
// Convert points to target units:
|
|
double fLengthTarget = fLengthPoints;
|
|
if (eUnitTo == SaExcelLogicalUnit.Pixel) fLengthTarget = PointsToPixels(fLengthPoints, bVertical);
|
|
else if (eUnitTo == SaExcelLogicalUnit.Cm) fLengthTarget = PointsToCms(fLengthPoints);
|
|
else if (eUnitTo == SaExcelLogicalUnit.Inch) fLengthTarget = PointsToInches(fLengthPoints);
|
|
return fLengthTarget;
|
|
}
|
|
public double ToPoints(double fLength, SaExcelLogicalUnit eUnitFrom, bool bVertical)
|
|
{
|
|
return ConvertLength(fLength, eUnitFrom, SaExcelLogicalUnit.Point, bVertical);
|
|
}
|
|
public double FromPoints(double fLength, SaExcelLogicalUnit eUnitTo, bool bVertical)
|
|
{
|
|
return ConvertLength(fLength, SaExcelLogicalUnit.Point, eUnitTo, bVertical);
|
|
}
|
|
public virtual double PointsToPixels(double points, bool bVertical)
|
|
{
|
|
// Pixel size depends on monitor resolution.
|
|
// REf. https://stackoverflow.com/questions/139655/convert-pixels-to-points
|
|
// Assume 96 pixels per inch.
|
|
return points * PixelsPerInch / PointsPerInch;
|
|
}
|
|
public virtual double PointsToCms(double points)
|
|
{
|
|
return PointsToInches(points) * CmsPerInch;
|
|
}
|
|
public virtual double PointsToInches(double points)
|
|
{
|
|
return points / PointsPerInch;
|
|
}
|
|
public virtual double PixelsToPoints(double pixels, bool bVertical)
|
|
{
|
|
// Pixel size depends on monitor resolution.
|
|
// REf. https://stackoverflow.com/questions/139655/convert-pixels-to-points
|
|
// Assume 96 pixels per inch.
|
|
return pixels / PixelsPerInch * PointsPerInch;
|
|
}
|
|
public virtual double CmsToPoints(double cms)
|
|
{
|
|
return InchesToPoints(cms / CmsPerInch);
|
|
}
|
|
public virtual double InchesToPoints(double inches)
|
|
{
|
|
return inches * PointsPerInch;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
protected void HandleException(String fn, Exception exc)
|
|
{
|
|
SaLogger.Error(GetType().Name + "." + fn + " " + ExceptionUtil.GetLogMessage(exc));
|
|
SetErrorState("Problems were encountered interfacing to Excel - " + ExceptionUtil.GetErrorStateMessage(exc));
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
}
|
|
//=======================================================================
|
|
}
|