Files
Common-VS2019/SacsStandardProc/Proc/Excel/SaMsSpreadsheet_POI.cs
T

1798 lines
59 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using Sarand.Net.Standard.Proc.Xml;
using Sarand.Net.Standard.Proc.Zip;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using NPOI.HSSF.UserModel;
using System.Linq;
using NPOI.SS.Formula.Functions;
using NPOI.SS.Util;
using System.Drawing;
using System.Security.Policy;
using MimeKit;
using DocumentFormat.OpenXml.Drawing.Charts;
using System.Reflection;
using Sarand.Net.Standard.Base.App;
using NPOI.HSSF.Util;
using NPOI.XSSF.Model;
using System.Drawing.Imaging;
using System.Xml.Linq;
using EnumsNET;
using NPOI.OOXML.XSSF.UserModel;
namespace Sarand.Net.Standard.Proc.Excel
{
//=======================================================================
/// <summary>Excel spreadsheet as supported by NPOI.</summary>
public class SaMsSpreadsheet_POI : SaMsSpreadsheet
{
//-------------------------------------------------------------------
// Definitions.
//-------------------------------------------------------------------
// Data members.
private IWorkbook workbook;
private ISheet worksheet;
//-------------------------------------------------------------------
// Construction.
public SaMsSpreadsheet_POI() : base()
{
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
CloseWorkbook();
}
base.Dispose(disposing);
}
//-------------------------------------------------------------------
// Properties.
//-------------------------------------------------------------------
// W o r k b o o k
//-------------------------------------------------------------------
public override bool IsWorkbookValid()
{
return workbook != null;
}
public override bool CreateWorkbook()
{
CloseWorkbook();
ClearErrorState();
// Create new workbook.
workbook = new XSSFWorkbook();
AddWorksheet("Sheet1");
return true;
}
public override bool OpenWorkbook(String filePath)
{
CloseWorkbook();
ClearErrorState();
try
{
// Open workbook document.
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
try
{
// Open XML formats: xlsx etc.
workbook = new XSSFWorkbook(fs);
}
catch
{
// If reading fails, try to read workbook as XLS:
workbook = new HSSFWorkbook(fs);
}
}
}
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
return !HasErrorState();
}
public bool OpenWorkbook(byte[] workbookData)
{
CloseWorkbook();
ClearErrorState();
try
{
using (MemoryStream workbookStream = new MemoryStream(workbookData))
{
OpenWorkbook(workbookStream);
}
}
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
return !HasErrorState();
}
public bool OpenWorkbook(Stream workbookStream)
{
CloseWorkbook();
ClearErrorState();
try
{
// From start of stream.
workbookStream.Seek(0, SeekOrigin.Begin);
// Open workbook document.
try
{
workbook = new XSSFWorkbook(workbookStream);
}
catch
{
// If reading fails, try to read workbook as XLS:
workbook = new HSSFWorkbook(workbookStream);
}
}
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
return !HasErrorState();
}
//-------------------------------------------------------------------
/// <summary>Cleanse workbook - remove unreferenced styles, fonts etc etc.</summary>
public override bool CleanseWorkbook()
{
ClearErrorState();
try
{
if (workbook is HSSFWorkbook)
{
HSSFOptimiser.OptimiseCellStyles((HSSFWorkbook)workbook);
HSSFOptimiser.OptimiseFonts((HSSFWorkbook)workbook);
}
if (workbook is XSSFWorkbook)
{
// No equivalent XFFS functionality.
}
}
catch (Exception exc) { SetErrorState(SysUtil.Fn + " " + ExceptionUtil.GetErrorStateMessage(exc)); }
return !HasErrorState();
}
//-------------------------------------------------------------------
/// <summary>Save spreadsheet to file.</summary>
/// <param name="filePath"></param>
/// <param name="fileFormat">Ignored - depends on POI document version.</param>
/// <param name="bAutomaticallyOverwrite"></param>
/// <returns></returns>
public override bool SaveDocument(String filePath, int fileFormat, bool bAutomaticallyOverwrite)
{
ClearErrorState();
if (fileFormat == 0)
fileFormat = (int)XlFileFormat.xlOpenXMLWorkbook;
if (fileFormat != (int)XlFileFormat.xlOpenXMLWorkbook)
SetErrorState("Unsupported file format: " + ((XlFileFormat)fileFormat).ToString());
if (!HasErrorState() && !IsWorkbookValid())
SetErrorState(Msg_WorkbookNotOpen);
if (!HasErrorState())
{
try
{
using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
workbook.Write(fs);
}
}
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
}
return !HasErrorState();
}
//-------------------------------------------------------------------
public override bool CloseWorkbook()
{
ClearErrorState();
CloseWorksheet();
// Clear workbook.
if (workbook != null)
workbook = null;
return !HasErrorState();
}
//-------------------------------------------------------------------
/// <summary>Extract the document as a byte array.</summary>
/// <returns>Document data as byte array.</returns>
public override byte[] GetDocumentData()
{
ClearErrorState();
if (!HasErrorState() && !IsWorkbookValid())
SetErrorState(Msg_WorkbookNotOpen);
if (!HasErrorState())
{
try
{
using (MemoryStream memStream = new MemoryStream())
{
workbook.Write(memStream);
return memStream.ToArray();
}
}
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
}
return null;
}
//-------------------------------------------------------------------
// Default style.
public override void ApplyDefaultStyle(SaMsExcelStyleAttr attr)
{
try
{
// Zero font.
IFont font = workbook.GetFontAt(0);
ApplyFontAttr(font, attr);
// Zero style - is this the default for all cells?.
ICellStyle style = workbook.GetCellStyleAt(0);
ApplyAttrToCellStyle(attr, style);
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
}
//-------------------------------------------------------------------
// W o r k s h e e t s
//-------------------------------------------------------------------
// Worksheet count.
public override uint WorksheetCount { get { return (uint)workbook.NumberOfSheets; } }
public override bool SetWorksheetCount(int worksheetCount)
{
ClearErrorState();
ClearErrorState();
if (worksheetCount > 0 && worksheetCount < 11)
{
while (WorksheetCount < worksheetCount)
AddWorksheet("");
while (WorksheetCount > worksheetCount)
RemoveWorksheet(WorksheetCount);
OpenWorksheet(1);
}
else SetErrorState(SysUtil.Fn + " - Requested number of worksheets (" + worksheetCount.ToString() + ") must be between 1 and 10");
return !HasErrorState();
}
//-------------------------------------------------------------------
// Worksheet names.
public override List<String> WorksheetNames
{
get
{
ClearErrorState();
HashSet<String> names = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
if (!HasErrorState() && !IsWorkbookValid())
SetErrorState(Msg_WorkbookNotOpen);
if (!HasErrorState())
{
for (int sheetPos = 1; sheetPos <= workbook.NumberOfSheets; sheetPos++)
names.Add(workbook.GetSheetName(sheetPos));
}
return new List<String>(names);
}
}
//-------------------------------------------------------------------
// Add worksheet.
public override bool AddWorksheet(String name)
{
ClearErrorState();
if (!HasErrorState() && !IsWorkbookValid())
return SetErrorState(Msg_WorkbookNotOpen);
CloseWorksheet();
// Determine name for sheet.
if (StringUtil.IsBlank(name))
{
List<String> sheetNames = WorksheetNames;
for (int sheetPos = 1; sheetPos <= workbook.NumberOfSheets; sheetPos++)
{
name = "Sheet " + sheetPos;
if (!sheetNames.ContainsCI(name))
break;
}
}
// Add a blank sheet.
worksheet = workbook.CreateSheet(name);
return IsWorksheetValid();
}
//-------------------------------------------------------------------
/// <summary>
/// Remove worksheet.
/// <para>Worksheet 0 is the currently open sheet.</para>
/// </summary>
public override bool RemoveWorksheet(uint worksheetPos = 0)
{
ClearErrorState();
if (!IsWorkbookValid())
return SetErrorState(Msg_WorkbookNotOpen);
try
{
if (worksheetPos > WorksheetCount)
return SetErrorState("Worksheet position must be up to " + WorksheetCount);
if (worksheetPos < 1)
{
// Worksheet '0' is the current sheet.
if (worksheet != null)
worksheetPos = (uint)(workbook.GetSheetIndex(worksheet) + 1);
else return SetErrorState("Worksheet position '0' not available - no open worksheet.");
}
int worksheetIdx = ((int)worksheetPos) - 1;
if (worksheet != null)
{
// Retrieve specified sheet to compare to currently open sheet.
ISheet sheet = workbook.GetSheetAt(worksheetIdx);
// Only close current sheet if it's about to be removed.
if (sheet.SheetName.EqualsCI(worksheet.SheetName))
CloseWorksheet();
}
workbook.RemoveSheetAt(worksheetIdx);
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
return true;
}
//-------------------------------------------------------------------
// W o r k s h e e t
//-------------------------------------------------------------------
/// <summary>
/// Open worksheet by position (from 1).
/// <para>Worksheet 0 is the currently open sheet or first if none open.</para>
/// </summary>
public override bool OpenWorksheet(uint worksheetPos)
{
ClearErrorState();
if (!IsWorkbookValid()) return SetErrorState(Msg_WorkbookNotOpen);
try
{
if (worksheetPos > WorksheetCount)
return SetErrorState("Worksheet position must be up to " + WorksheetCount);
if (worksheetPos < 1)
{
// Worksheet '0' is the current sheet.
if (worksheet != null)
worksheetPos = (uint)(workbook.GetSheetIndex(worksheet) + 1);
else worksheetPos = 1;
}
int worksheetIdx = ((int)worksheetPos) - 1;
// Open worksheet.
CloseWorksheet();
worksheet = workbook.GetSheetAt(worksheetIdx);
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
return !HasErrorState();
}
//-------------------------------------------------------------------
/// <summary>Open worksheet by name (case and whitespace insensitive).</summary>
public override bool OpenWorksheet(String name)
{
ClearErrorState();
name = StringUtil.TrimWhitespace(StringUtil.OnBlank(name));
if (!IsWorkbookValid()) return SetErrorState(Msg_WorkbookNotOpen);
try
{
// Open worksheet.
for (int worksheetIdx = 0; worksheetIdx < workbook.NumberOfSheets; worksheetIdx++)
{
ISheet worksheetCandidate = workbook.GetSheetAt(worksheetIdx);
if (StringUtil.TrimWhitespace(worksheetCandidate.SheetName).EqualsCI(name))
{
CloseWorksheet();
worksheet = worksheetCandidate;
return true;
}
}
SetErrorState("Worksheet not found.");
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
return !HasErrorState();
}
//-------------------------------------------------------------------
// Close currently open worksheet.
public override bool CloseWorksheet()
{
ClearErrorState();
if (!IsWorkbookValid())
return SetErrorState(Msg_WorkbookNotOpen);
if (worksheet != null)
worksheet = null;
return !HasErrorState();
}
//-------------------------------------------------------------------
public override bool IsWorksheetValid()
{
if (!IsWorkbookValid()) return false;
return worksheet != null;
}
//-------------------------------------------------------------------
public override uint WorksheetPos { get { return (uint)(workbook.GetSheetIndex(worksheet) + 1); } }
public override String WorksheetName
{
get { return worksheet?.SheetName ?? ""; }
set { workbook.SetSheetName(workbook.GetSheetIndex(worksheet), value); }
}
public override bool SetWorksheetAttr(SaMsExcelStyleAttr attr)
{
ClearErrorState();
if (!IsWorkbookValid())
return SetErrorState(Msg_WorkbookNotOpen);
if (!IsWorksheetValid())
return SetErrorState("Worksheet is not open");
return SetErrorState(SysUtil.Fn + " " + Msg_NotSupported);
}
//-------------------------------------------------------------------
// Worksheet Page Setup.
public override bool SetPageSetup(SaMsExcelPageSetup_Config pageSetupConfig)
{
ClearErrorState();
if (!IsWorkbookValid())
return SetErrorState(Msg_WorkbookNotOpen);
if (!IsWorksheetValid())
return SetErrorState("Worksheet is not open");
//---------------------------------------------------------------
// Page setup options:
// ActiveSheet.PageSetup
// .PrintTitleRows = "$4:$4"
// .PrintTitleColumns = ""
// .PrintArea = ""
// .LeftHeader = ""
// .CenterHeader = ""
// .RightHeader = ""
// .LeftFooter = ""
// .CenterFooter = ""
// .RightFooter = ""
// .LeftMargin = Application.InchesToPoints(0.708661417322835)
// .RightMargin = Application.InchesToPoints(0.708661417322835)
// .TopMargin = Application.InchesToPoints(0.748031496062992)
// .BottomMargin = Application.InchesToPoints(0.748031496062992)
// .HeaderMargin = Application.InchesToPoints(0.31496062992126)
// .FooterMargin = Application.InchesToPoints(0.31496062992126)
// .PrintHeadings = False
// .PrintGridlines = False
// .PrintComments = xlPrintNoComments
// .PrintQuality = 600
// .CenterHorizontally = False
// .CenterVertically = False
// .Orientation = xlPortrait
// .Draft = False
// .PaperSize = xlPaperA4
// .FirstPageNumber = xlAutomatic
// .Order = xlDownThenOver
// .BlackAndWhite = False
// .Zoom = 100
// .PrintErrors = xlPrintErrorsDisplayed
// .OddAndEvenPagesHeaderFooter = False
// .DifferentFirstPageHeaderFooter = False
// .ScaleWithDocHeaderFooter = True
// .AlignMarginsHeaderFooter = True
// .EvenPage.LeftHeader.Text = ""
// .EvenPage.CenterHeader.Text = ""
// .EvenPage.RightHeader.Text = ""
// .EvenPage.LeftFooter.Text = ""
// .EvenPage.CenterFooter.Text = ""
// .EvenPage.RightFooter.Text = ""
// .FirstPage.LeftHeader.Text = ""
// .FirstPage.CenterHeader.Text = ""
// .FirstPage.RightHeader.Text = ""
// .FirstPage.LeftFooter.Text = ""
// .FirstPage.CenterFooter.Text = ""
// .FirstPage.RightFooter.Text = ""
//---------------------------------------------------------------
// Negative values leave current value.
try
{
// Print setup.
IPrintSetup printSetup = worksheet.PrintSetup;
if (pageSetupConfig.Orientation == SaXlPageOrientation.xlLandscape)
printSetup.Landscape = true;
else if (pageSetupConfig.Orientation == SaXlPageOrientation.xlPortrait)
printSetup.Landscape = false;
// Headers and footers.
worksheet.Header.Left = pageSetupConfig.HeaderLeft;
worksheet.Header.Center = pageSetupConfig.HeaderCenter;
worksheet.Header.Right = pageSetupConfig.HeaderRight;
worksheet.Footer.Left = pageSetupConfig.FooterLeft;
worksheet.Footer.Center = pageSetupConfig.FooterCenter;
worksheet.Footer.Right = pageSetupConfig.FooterRight;
// Margins.
if (pageSetupConfig.MarginLeft > 0)
worksheet.SetMargin(MarginType.LeftMargin, ToPoints(pageSetupConfig.MarginLeft, pageSetupConfig.Unit, false));
if (pageSetupConfig.MarginRight > 0)
worksheet.SetMargin(MarginType.RightMargin, ToPoints(pageSetupConfig.MarginRight, pageSetupConfig.Unit, false));
if (pageSetupConfig.MarginTop > 0)
worksheet.SetMargin(MarginType.TopMargin, ToPoints(pageSetupConfig.MarginTop, pageSetupConfig.Unit, false));
if (pageSetupConfig.MarginBottom > 0)
worksheet.SetMargin(MarginType.BottomMargin, ToPoints(pageSetupConfig.MarginBottom, pageSetupConfig.Unit, false));
if (pageSetupConfig.MarginHeader > 0)
worksheet.SetMargin(MarginType.HeaderMargin, ToPoints(pageSetupConfig.MarginHeader, pageSetupConfig.Unit, false));
if (pageSetupConfig.MarginFooter > 0)
worksheet.SetMargin(MarginType.FooterMargin, ToPoints(pageSetupConfig.MarginFooter, pageSetupConfig.Unit, false));
// Print Title Rows.
if (pageSetupConfig.PrintTitleRowFrom > 0 && pageSetupConfig.PrintTitleRowTo > 0)
{
// Prefix with '$' to fix row value.(?)
worksheet.RepeatingRows = CellRangeAddress.ValueOf(pageSetupConfig.PrintTitleRowFrom + ":" + pageSetupConfig.PrintTitleRowTo);
}
else if (pageSetupConfig.PrintTitleRowFrom == 0 && pageSetupConfig.PrintTitleRowTo == 0)
worksheet.RepeatingRows = null;
// Print Title Columns.
if (pageSetupConfig.PrintTitleColFrom > 0 && pageSetupConfig.PrintTitleColTo > 0)
worksheet.RepeatingColumns = CellRangeAddress.ValueOf(pageSetupConfig.PrintTitleColFrom + ":" + pageSetupConfig.PrintTitleColTo);
else if (pageSetupConfig.PrintTitleColFrom == 0 && pageSetupConfig.PrintTitleColTo == 0)
worksheet.RepeatingColumns = null;
// Zoom & 'Fit to' options.
if (pageSetupConfig.Zoom > 0)
worksheet.SetZoom(pageSetupConfig.Zoom);
else if (pageSetupConfig.FitToPagesTall > 0 || pageSetupConfig.FitToPagesWide > 0)
{
worksheet.SetZoom(0);
worksheet.FitToPage = false;
printSetup.FitWidth = (short)Math.Min(0, pageSetupConfig.FitToPagesWide);
printSetup.FitHeight = (short)Math.Min(0, pageSetupConfig.FitToPagesTall);
}
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
return !HasErrorState();
}
//-------------------------------------------------------------------
// Page breaks.
public override bool SetPageBreak(uint col, uint row)
{
ClearErrorState();
if (!IsWorkbookValid())
return SetErrorState(Msg_WorkbookNotOpen);
if (!IsWorksheetValid())
return SetErrorState("Worksheet is not open");
try
{
worksheet.FitToPage = false;
worksheet.SetColumnBreak((int)(col - 1));
worksheet.SetRowBreak((int)(row - 1));
}
catch (Exception exc)
{
HandleException(SysUtil.Fn, exc);
}
return !HasErrorState();
}
//-------------------------------------------------------------------
// C o l u m n s
//-------------------------------------------------------------------
public override uint ActiveColPos { get { return (uint)(worksheet.ActiveCell.Column + 1); } }
public override double GetColWidth(uint colPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
{
ClearErrorState();
if (!IsWorkbookValid()) SetErrorState(Msg_WorkbookNotOpen);
else if (!IsWorksheetValid()) SetErrorState("Worksheet is not open");
else
{
try
{
// Retrieve width (in points) from column.
double width = worksheet.GetColumnWidth((int)(colPos - 1));
// Adjust for units.
if (unit == SaExcelLogicalUnit.Pixel) return PointsToPixels(width, false);
if (unit == SaExcelLogicalUnit.Cm) return PointsToCms(width);
if (unit == SaExcelLogicalUnit.Inch) return PointsToInches(width);
return width;
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
}
return 0.0;
}
/// <summary> Default xcharacter width in pixels. </summary>
private static readonly double DEFAULT_CHARACTER_WIDTH = 7.001699924468994f; /* From Apache POI) */
public override bool SetColWidth(uint colPos, double width, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
{
ClearErrorState();
if (!IsWorkbookValid()) return SetErrorState(Msg_WorkbookNotOpen);
if (!IsWorksheetValid()) return SetErrorState("Worksheet is not open");
try
{
// Adjust for units.
double widthPixels = ConvertLength(width, unit, SaExcelLogicalUnit.Pixel, false);
// POI units for column width are 1/256th default character width.
// Ref. NPOI.Util.Units
worksheet.SetColumnWidth((int)(colPos - 1), (int)Math.Ceiling(widthPixels * 256 / DEFAULT_CHARACTER_WIDTH));
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
return !HasErrorState();
}
//-------------------------------------------------------------------
// R o w s
//-------------------------------------------------------------------
public override uint FirstRowPos { get { return (uint)(worksheet.FirstRowNum + 1); } }
public override uint LastRowPos { get { return (uint)(worksheet.LastRowNum + 1); } }
//-------------------------------------------------------------------
private IRow GetRowByIdx(int rowIdx, bool create = false)
{
IRow row = worksheet.GetRow(rowIdx);
if (row == null && create)
row = worksheet.CreateRow(rowIdx);
return row;
}
private IRow GetRowByPos(uint rowPos, bool create = false)
{
return GetRowByIdx((int)(rowPos - 1), create);
}
public int ActiveRowIdx { get { return worksheet.ActiveCell.Row; } }
public override uint ActiveRowPos { get { return (uint)(ActiveRowIdx + 1); } }
//-------------------------------------------------------------------
public override double GetRowHeight(uint rowPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
{
ClearErrorState();
if (!IsWorkbookValid()) SetErrorState(Msg_WorkbookNotOpen);
else if (!IsWorksheetValid()) SetErrorState("Worksheet is not open");
else
{
try
{
// Retrieve height (in points) from row.
IRow row = GetRowByPos(rowPos);
double height = row?.Height ?? 0.0;
// Adjust for units.
if (unit == SaExcelLogicalUnit.Pixel) return PointsToPixels(height, true);
if (unit == SaExcelLogicalUnit.Cm) return PointsToCms(height);
if (unit == SaExcelLogicalUnit.Inch) return PointsToInches(height);
return height;
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
}
return 0.0;
}
public override bool SetRowHeight(uint rowPos, double height, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
{
ClearErrorState();
if (!IsWorkbookValid()) return SetErrorState(Msg_WorkbookNotOpen);
if (!IsWorksheetValid()) return SetErrorState("Worksheet is not open");
try
{
// Adjust for units.
if (unit == SaExcelLogicalUnit.Pixel) height = PixelsToPoints(height, true);
if (unit == SaExcelLogicalUnit.Cm) height = CmsToPoints(height);
if (unit == SaExcelLogicalUnit.Inch) height = InchesToPoints(height);
// Set row height.
IRow row = GetRowByPos(rowPos, true);
row.Height = (short)height;
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
return !HasErrorState();
}
//-------------------------------------------------------------------
public override List<DataValue> GetRowValues(uint rowPos, int maxColumns = 0)
{
ClearErrorState();
List<DataValue> values = new List<DataValue>();
try
{
IRow row = GetRowByPos(rowPos);
if (row != null)
{
foreach (ICell cell in row.Cells)
{
values.Add(GetCellDataValue(cell));
if (maxColumns > 0 && values.Count >= maxColumns) break;
}
}
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
return values;
}
//-------------------------------------------------------------------
// C e l l s
//-------------------------------------------------------------------
private ICell GetCell(uint colPos, uint rowPos, bool create = false)
{
ClearErrorState();
IRow row = GetRowByPos(rowPos, create);
return GetCell(colPos, row, create);
}
private ICell GetCell(uint colPos, IRow row, bool createBlank = false)
{
ClearErrorState();
ICell cell = row?.GetCell((int)(colPos - 1), createBlank ? MissingCellPolicy.CREATE_NULL_AS_BLANK : MissingCellPolicy.RETURN_NULL_AND_BLANK);
if (cell != null && (cell.CellStyle == null || cell.CellStyle.Index == 0))
{
ICellStyle colStyle = worksheet.GetColumnStyle(cell.ColumnIndex);
if (colStyle.Index != 0)
cell.CellStyle = colStyle;
}
return cell;
}
//-------------------------------------------------------------------
public override void SetActiveCell(uint colPos, uint rowPos)
{
ClearErrorState();
try
{
worksheet.ActiveCell = new CellAddress((int)(rowPos - 1), (int)(colPos - 1));
}
catch (Exception exc)
{
HandleException(SysUtil.Fn, exc);
}
}
//-------------------------------------------------------------------
private bool IsCellFormula(uint colPos, uint rowPos)
{
ClearErrorState();
try
{
ICell cell = GetCell(colPos, rowPos);
return IsCellFormula(cell);
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
return false;
}
private bool IsCellFormula(ICell cell)
{
return cell != null && cell.CellType == NPOI.SS.UserModel.CellType.Formula;
}
private bool IsCellNumeric(uint colPos, uint rowPos)
{
ClearErrorState();
try
{
ICell cell = GetCell(colPos, rowPos);
return IsCellNumeric(cell);
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
return false;
}
private bool IsCellNumeric(ICell cell)
{
return cell != null && cell.CellType == NPOI.SS.UserModel.CellType.Numeric;
}
private bool IsCellDate(uint colPos, uint rowPos)
{
ClearErrorState();
try
{
ICell cell = GetCell(colPos, rowPos);
return IsCellDate(cell);
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
return false;
}
private bool IsCellDate(ICell cell)
{
return cell != null && NPOI.SS.UserModel.DateUtil.IsCellDateFormatted(cell);
}
//-------------------------------------------------------------------
public override String GetCellFormula(uint colPos, uint rowPos)
{
ClearErrorState();
try
{
ICell cell = GetCell(colPos, rowPos);
String formula = "";
if (cell != null)
{
if (IsCellFormula(cell))
formula = cell.CellFormula;
if (StringUtil.IsEmpty(formula) && cell != null)
formula = GetCellText(cell, true);
}
return formula;
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
return "";
}
public override String GetCellText(uint colPos, uint rowPos, bool trimWhitespace = true)
{
ClearErrorState();
try
{
ICell cell = GetCell(colPos, rowPos);
return cell != null ? GetCellText(cell, true) : "";
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
return "";
}
private String GetCellText(ICell cell, bool trimValue = true)
{
ClearErrorState();
String value = "";
try
{
value = cell.ToString();
if (trimValue) value.TrimAll();
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
return value;
}
public override DataValue GetCellValue(uint colPos, uint rowPos)
{
return GetCellDataValue(GetCell(colPos, rowPos), false);
}
private DataValue GetCellDataValue(ICell cell, bool trimTextValue = true)
{
ClearErrorState();
try
{
if (IsCellDate(cell))
return new DataValue((DateTime)(cell.DateCellValue ?? DateTime.MinValue));
if (IsCellNumeric(cell))
{
double value = cell.NumericCellValue;
if (Math.Floor(value) == value)
return new DataValue((long)value);
else
return new DataValue(value);
}
return new DataValue(cell.StringCellValue);
}
catch (Exception exc)
{
HandleException(SysUtil.Fn, exc);
}
return new DataValue();
}
//-------------------------------------------------------------------
public override bool SetCellFormula(uint colPos, uint rowPos, String value, SaMsExcelStyleAttr attr)
{
try
{
ICell cell = GetCell(colPos, rowPos, true);
cell.CellFormula = value;
// Set cell attributes (style etc).
SaMsExcelRange range = new SaMsExcelRange(colPos, rowPos);
SetRangeAttr(range, attr);
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
return !HasErrorState();
}
public override bool SetCellValue(uint colPos, uint rowPos, DataValue value, SaMsExcelStyleAttr attr)
{
try
{
ICell cell = GetCell(colPos, rowPos, true);
SetCellValue(cell, value);
// Set cell attributes (style etc).
SaMsExcelRange range = new SaMsExcelRange(colPos, rowPos);
SetRangeAttr(range, attr);
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
return !HasErrorState();
}
//-------------------------------------------------------------------
private void SetCellValue(ICell cell, Object value)
{
if (value == null)
cell.SetBlank();
else if (value is bool)
cell.SetCellValue((bool)value);
else if (value is short)
cell.SetCellValue((short)value);
else if (value is int)
cell.SetCellValue((int)value);
else if (value is long)
cell.SetCellValue((long)value);
else if (value is float)
cell.SetCellValue((float)value);
else if (value is double)
cell.SetCellValue((double)value);
else if (value is DateTime)
cell.SetCellValue((DateTime)value);
else
cell.SetCellValue(value.ToString());
}
private void SetCellValue(ICell cell, DataValue value)
{
if (value == null)
cell.SetBlank();
// Populate cell value based on value type.
switch (value.GetDataType())
{
case DataValue.DataType.Bool:
cell.SetCellValue(value.AsBool());
break;
case DataValue.DataType.Long:
cell.SetCellValue(value.AsLong());
break;
case DataValue.DataType.Double:
cell.SetCellValue(value.AsDouble());
break;
case DataValue.DataType.Decimal:
cell.SetCellValue((double)value.AsDecimal());
break;
case DataValue.DataType.Date:
cell.SetCellValue(value.AsDate());
break;
case DataValue.DataType.Time:
cell.SetCellValue(value.AsTime());
break;
case DataValue.DataType.DateTime:
cell.SetCellValue(value.AsDateTime());
break;
default:
cell.SetCellValue(value.ToString());
break;
}
}
//-------------------------------------------------------------------
public override bool SetRowFormulas(uint colPosStart, uint rowPos, List<String> values)
{
try
{
IRow row = GetRowByPos(rowPos, true);
for (Math.Max(1, colPosStart); colPosStart <= values.Count; colPosStart++)
{
Object value = values[(int)(colPosStart - 1)];
ICell cell = GetCell(colPosStart, row, true);
SetCellValue(cell, value);
}
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
return !HasErrorState();
}
public override bool SetRowValues(uint colPosStart, uint rowPos, List<DataValue> values)
{
try
{
IRow row = GetRowByPos(rowPos, true);
for (int valueIdx = 0; valueIdx < values.Count; valueIdx++)
{
uint colPos = (uint)Math.Max(1, colPosStart + valueIdx);
Object value = values[valueIdx];
ICell cell = GetCell(colPos, row, true);
SetCellValue(cell, value);
}
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
return !HasErrorState();
}
//-------------------------------------------------------------------
private void EvaluateAllFormulaCells()
{
if (workbook is XSSFWorkbook)
XSSFFormulaEvaluator.EvaluateAllFormulaCells(workbook);
else
HSSFFormulaEvaluator.EvaluateAllFormulaCells(workbook);
}
//-------------------------------------------------------------------
// C e l l S t y l e
//-------------------------------------------------------------------
private String GetBuiltInStyleFormat(int numFmtId)
{
// Ref. http://stackoverflow.com/questions/4730152/what-indicates-an-office-open-xml-cell-contains-a-date-time-value
switch (numFmtId)
{
//
case 0: return "General";
case 1: return "0";
case 2: return "0.00";
case 3: return "#,##0";
case 4: return "#,##0.00";
//
case 9: return "0%";
case 10: return "0.00%";
case 11: return "0.00E+00";
case 12: return "# ?/?";
case 13: return "# ??/??";
case 14: return "mm-dd-yy";
case 15: return "d-mmm-yy";
case 16: return "d-mmm";
case 17: return "mmm-yy";
case 18: return "h:mm AM/PM";
case 19: return "h:mm:ss AM/PM";
case 20: return "h:mm";
case 21: return "h:mm:ss";
case 22: return "m/d/yy h:mm";
//
case 37: return "#,##0 ;(#,##0)";
case 38: return "#,##0 ;[Red](#,##0)";
case 39: return "#,##0.00;(#,##0.00)";
case 40: return "#,##0.00;[Red](#,##0.00)";
//
case 44: return "_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)";
case 45: return "mm:ss";
case 46: return "[h]:mm:ss";
case 47: return "mmss.0";
case 48: return "##0.0E+0";
case 49: return "@";
//
case 27: return "[$-404]e/m/d";
case 30: return "m/d/yy";
case 36: return "[$-404]e/m/d";
case 50: return "[$-404]e/m/d";
case 57: return "[$-404]e/m/d";
//
case 59: return "t0";
case 60: return "t0.00";
case 61: return "t#,##0";
case 62: return "t#,##0.00";
case 67: return "t0%";
case 68: return "t0.00%";
case 69: return "t# ?/?";
case 70: return "t# ??/??";
}
return "";
}
private bool IsDateStyle(String numFormat)
{
// Ref. http://stackoverflow.com/questions/19034805/how-to-distinguish-inline-numbers-from-ole-automation-date-numbers-in-openxml-sp/19582685#19582685
if (IsTimeStyle(numFormat)) return false;
if (numFormat.Contains("d")) return true;
if (numFormat.Contains("m")) return true;
if (numFormat.Contains("y")) return true;
return false;
}
private bool IsTimeStyle(String numFormat)
{
if (numFormat.Contains("h")) return true;
if (numFormat.Contains(":mm")) return true;
if (numFormat.Contains("mm:")) return true;
if (numFormat.Contains(":ss")) return true;
return false;
}
private bool IsDateTimeStyle(String numFormat)
{
return (IsDateStyle(numFormat) || IsTimeStyle(numFormat));
}
//-------------------------------------------------------------------
// Cell attributes.
public override bool SetRangeAttr(SaMsExcelRange range, SaMsExcelStyleAttr attr)
{
if (attr == null) return false;
try
{
// Apply style to cells.
for (uint rowPos = range.RowFromPos; rowPos <= range.RowToPos; rowPos++)
{
IRow row = null;
if (rowPos > 0)
row = GetRowByPos(rowPos, true);
for (uint colPos = range.ColFromPos; colPos <= range.ColToPos; colPos++)
{
if (rowPos < 1 && colPos < 1)
{
// Style is to be aplied to entire sheet.
}
else if (rowPos < 1)
{
// Style is to be applied to entire column.
ICellStyle colStyle = worksheet.GetColumnStyle((int)(colPos - 1));
if (colStyle != null && colStyle.Index != 0)
{
// Column already has its own specific stlying.
ApplyAttrToCellStyle(attr, colStyle);
worksheet.SetDefaultColumnStyle((int)(colPos - 1), colStyle);
}
else
{
// Create specific styling for column.
colStyle = CloneCellStyle(colStyle);
ApplyAttrToCellStyle(attr, colStyle);
worksheet.SetDefaultColumnStyle((int)(colPos - 1), colStyle);
}
// Apply style to existing cells in column.
for (uint colRowPos = FirstRowPos; colRowPos <= LastRowPos; colRowPos++)
{
ICell cell = GetCell(colPos, colRowPos, false);
ApplyAttrToCell(attr, cell);
}
}
else if (colPos < 1)
{
// Style is to be applied to entire row.
if (row != null)
{
for (int cellColIdx = row.FirstCellNum; cellColIdx < row.LastCellNum; cellColIdx++)
{
ICell cell = row.GetCell(cellColIdx, MissingCellPolicy.RETURN_NULL_AND_BLANK);
if (cell == null) continue;
ApplyAttrToCell(attr, cell);
}
}
}
else
{
// Apply style to cell.
ICell cell = GetCell(colPos, rowPos, true);
ApplyAttrToCell(attr, cell);
}
}
}
}
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
return !HasErrorState();
}
//-------------------------------------------------------------------
private ICellStyle CloneCellStyle(ICellStyle cellStyle)
{
ICellStyle cellStyleNew = workbook.CreateCellStyle();
cellStyleNew.CloneStyleFrom(cellStyle);
return cellStyleNew;
}
//-------------------------------------------------------------------
private void ApplyAttrToCell(SaMsExcelStyleAttr attr, ICell cell)
{
if (cell == null) return;
Dictionary<String, Object> styleProperties = GetStyleProperties(attr);
if (attr.FontAttr.IsSpecified())
PopulateFontStyleProperties(styleProperties, attr, cell.CellStyle.GetFont(workbook));
if (styleProperties.IsEmpty()) return;
CellUtil.SetCellStyleProperties(cell, styleProperties);
}
private void ApplyAttrToCellStyle(SaMsExcelStyleAttr attr, ICellStyle cellStyle)
{
Dictionary<String, Object> styleProperties = GetStyleProperties(attr);
if (attr.FontAttr.IsSpecified())
PopulateFontStyleProperties(styleProperties, attr, cellStyle.GetFont(workbook));
ApplyStylingProperties(cellStyle, styleProperties);
}
private Dictionary<String, Object> GetStyleProperties(SaMsExcelStyleAttr attr)
{
// Style properties to change via CellUtil (when cell specified).
Dictionary<String, Object> styleProperties = new Dictionary<String, Object>();
if (attr.MergeCells ?? false)
{
// Merge cells.
}
if (!StringUtil.IsBlank(attr.DataFormat))
{
// Data format.
IDataFormat dataFormat = workbook.CreateDataFormat();
short dataFormatIdx = dataFormat.GetFormat(attr.DataFormat);
if (dataFormatIdx >= 0)
styleProperties.Add(CellUtil.DATA_FORMAT, dataFormatIdx);
}
// Alignment.
if (attr.HorizontalAlignment != null)
{
styleProperties.Add(CellUtil.ALIGNMENT, GetPoiHorizontalAlignment((XlHAlign)attr.HorizontalAlignment));
}
// Vertical alignment.
if (attr.VerticalAlignment != null)
{
styleProperties.Add(CellUtil.VERTICAL_ALIGNMENT, GetPoiVerticalAlignment((XlVAlign)attr.VerticalAlignment));
}
// Indentation.
if (attr.IndentLevel != null)
{
styleProperties.Add(CellUtil.INDENTION, (short)attr.IndentLevel);
}
// Wrap text.
if (attr.WrapText ?? false)
{
styleProperties.Add(CellUtil.WRAP_TEXT, (bool)attr.WrapText);
}
// Interior colour and pattern.
if (attr.ForegroundColourIndex != SaXlColourIndex.NotSpecified)
{
styleProperties.Add(CellUtil.FILL_FOREGROUND_COLOR, GetPoiColourIndex((SaXlColourIndex)attr.ForegroundColourIndex, IndexedColors.White.Index));
styleProperties.Add(CellUtil.FILL_PATTERN, FillPattern.SolidForeground);
}
else if (attr.ForegroundColourRGB != null)
{
// Convert RGB colour to palette index.
short? interiorColourIndex = GetCustomerColourIndex((int)attr.ForegroundColourRGB);
if (interiorColourIndex != null)
{
styleProperties.Add(CellUtil.FILL_PATTERN, FillPattern.SolidForeground);
styleProperties.Add(CellUtil.FILL_FOREGROUND_COLOR, interiorColourIndex);
}
}
if (attr.InteriorPattern != SaXlPattern.NotSpecified)
{
styleProperties.Add(CellUtil.FILL_PATTERN, (FillPattern)attr.InteriorPattern);
}
if (attr.BackgroundColourIndex != SaXlColourIndex.NotSpecified)
{
styleProperties.Add(CellUtil.FILL_BACKGROUND_COLOR, GetPoiColourIndex((SaXlColourIndex)attr.BackgroundColourIndex, IndexedColors.White.Index));
}
else if (attr.BackgroundPatternColour != null)
{
// Convert RGB colour to palette index.
short? interiorPatternColourIndex = GetCustomerColourIndex((int)attr.BackgroundPatternColour);
if (interiorPatternColourIndex != null)
styleProperties.Add(CellUtil.FILL_BACKGROUND_COLOR, (short)interiorPatternColourIndex);
}
// Borders.
if (attr.BorderTop.IsSpecified)
{
if (attr.BorderTop.Weight != SaXlBorderWeight.NotSpecified || attr.BorderTop.LineStyle != SaXlLineStyle.NotSpecified)
styleProperties.Add(CellUtil.BORDER_TOP, GetBorderStyle(attr.BorderTop));
if (attr.BorderTop.Color != null)
styleProperties.Add(CellUtil.TOP_BORDER_COLOR, GetPoiColourIndex((SaXlColourIndex)attr.BorderTop.Color.Value, IndexedColors.Black.Index));
else if (attr.BorderTop.ColorIndex != SaXlColourIndex.NotSpecified)
{
// Convert RGB colour to palette index.
short? colourIndex = GetCustomerColourIndex((int)attr.BorderTop.ColorIndex);
if (colourIndex != null)
styleProperties.Add(CellUtil.TOP_BORDER_COLOR, (short)colourIndex);
}
}
if (attr.BorderBottom.IsSpecified)
{
if (attr.BorderBottom.Weight != SaXlBorderWeight.NotSpecified || attr.BorderBottom.LineStyle != SaXlLineStyle.NotSpecified)
styleProperties.Add(CellUtil.BORDER_BOTTOM, GetBorderStyle(attr.BorderBottom));
if (attr.BorderBottom.Color != null)
styleProperties.Add(CellUtil.BOTTOM_BORDER_COLOR, GetPoiColourIndex((SaXlColourIndex)attr.BorderBottom.Color, IndexedColors.Black.Index));
else if (attr.BorderBottom.ColorIndex != SaXlColourIndex.NotSpecified)
{
// Convert RGB colour to palette index.
short? colourIndex = GetCustomerColourIndex((int)attr.BorderBottom.ColorIndex);
if (colourIndex != null)
styleProperties.Add(CellUtil.BOTTOM_BORDER_COLOR, (short)colourIndex);
}
}
if (attr.BorderLeft.IsSpecified)
{
if (attr.BorderLeft.Weight != SaXlBorderWeight.NotSpecified || attr.BorderLeft.LineStyle != SaXlLineStyle.NotSpecified)
styleProperties.Add(CellUtil.BORDER_LEFT, GetBorderStyle(attr.BorderLeft));
if (attr.BorderLeft.Color != null)
styleProperties.Add(CellUtil.LEFT_BORDER_COLOR, GetPoiColourIndex((SaXlColourIndex)attr.BorderLeft.Color, IndexedColors.Black.Index));
else if (attr.BorderLeft.ColorIndex != SaXlColourIndex.NotSpecified)
{
// Convert RGB colour to palette index.
short? colourIndex = GetCustomerColourIndex((int)attr.BorderLeft.ColorIndex);
if (colourIndex != null)
styleProperties.Add(CellUtil.LEFT_BORDER_COLOR, (short)colourIndex);
}
}
if (attr.BorderRight.IsSpecified)
{
if (attr.BorderRight.Weight != SaXlBorderWeight.NotSpecified || attr.BorderRight.LineStyle != SaXlLineStyle.NotSpecified)
styleProperties.Add(CellUtil.BORDER_RIGHT, GetBorderStyle(attr.BorderRight));
if (attr.BorderRight.Color != null)
styleProperties.Add(CellUtil.RIGHT_BORDER_COLOR, GetPoiColourIndex((SaXlColourIndex)attr.BorderRight.Color, IndexedColors.Black.Index));
else if (attr.BorderRight.ColorIndex != SaXlColourIndex.NotSpecified)
{
// Convert RGB colour to palette index.
short? colourIndex = GetCustomerColourIndex((int)attr.BorderRight.ColorIndex);
if (colourIndex != null)
styleProperties.Add(CellUtil.RIGHT_BORDER_COLOR, (short)colourIndex);
}
}
return styleProperties;
}
private HorizontalAlignment GetPoiHorizontalAlignment(XlHAlign hAlign)
{
switch (hAlign)
{
case XlHAlign.xlHAlignGeneral: return HorizontalAlignment.General;
case XlHAlign.xlHAlignLeft: return HorizontalAlignment.Left;
case XlHAlign.xlHAlignCenter: return HorizontalAlignment.Center;
case XlHAlign.xlHAlignRight: return HorizontalAlignment.Right;
case XlHAlign.xlHAlignJustify: return HorizontalAlignment.Justify;
case XlHAlign.xlHAlignCenterAcrossSelection: return HorizontalAlignment.CenterSelection;
case XlHAlign.xlHAlignFill: return HorizontalAlignment.Fill;
case XlHAlign.xlHAlignDistributed: return HorizontalAlignment.Distributed;
}
return HorizontalAlignment.General;
}
private VerticalAlignment GetPoiVerticalAlignment(XlVAlign vAlign)
{
switch (vAlign)
{
case XlVAlign.xlVAlignTop: return VerticalAlignment.Top;
case XlVAlign.xlVAlignJustify: return VerticalAlignment.Justify;
case XlVAlign.xlVAlignDistributed: return VerticalAlignment.Distributed;
case XlVAlign.xlVAlignCenter: return VerticalAlignment.Center;
case XlVAlign.xlVAlignBottom: return VerticalAlignment.Bottom;
}
return VerticalAlignment.None;
}
private void PopulateFontStyleProperties(Dictionary<String, Object> styleProperties, SaMsExcelStyleAttr attr, IFont fontBase)
{
int fontIndex = GetFontIndex(attr, fontBase);
if (fontIndex >= 0)
styleProperties.Add(CellUtil.FONT, (short)fontIndex);
}
private short GetFontIndex(SaMsExcelStyleAttr attr, IFont fontBase)
{
if (!attr.FontAttr.IsSpecified()) return -1;
// Base font attributes.
bool bold = fontBase.IsBold;
short color = fontBase.Color;
double heightInPoints = fontBase.FontHeightInPoints;
String name = fontBase.FontName;
bool italic = fontBase.IsItalic;
bool strikeout = fontBase.IsStrikeout;
FontSuperScript typeOffset = fontBase.TypeOffset;
FontUnderlineType underline = fontBase.Underline;
if (attr.FontAttr.Bold ?? false)
bold = true;
if (attr.FontAttr.ColourIndex != SaXlColourIndex.NotSpecified)
{
color = GetPoiColourIndex((SaXlColourIndex)attr.FontAttr.ColourIndex, IndexedColors.Black.Index);
}
if (attr.FontAttr.ColourRGB != null)
{
// Convert RGB colour to palette index.
short? colourIndex = GetCustomerColourIndex((int)attr.FontAttr.ColourRGB);
if (colourIndex != null)
color = (short)attr.FontAttr.ColourRGB;
}
if (attr.FontAttr.HeightInPoints != null && attr.FontAttr.HeightInPoints >= FontHeightInPointsMin && attr.FontAttr.HeightInPoints <= FontHeightInPointsMax)
heightInPoints = (double)attr.FontAttr.HeightInPoints;
if (!StringUtil.IsBlank(attr.FontAttr.Name))
name = attr.FontAttr.Name;
if (attr.FontAttr.Strikethrough ?? false)
strikeout = true;
if (attr.FontAttr.Superscript ?? false)
typeOffset = FontSuperScript.Super;
if (attr.FontAttr.Subscript ?? false)
typeOffset = FontSuperScript.Sub;
if (attr.FontAttr.Outline ?? false)
{
//font.OutlineFont = (short)attr.FontAttr.OutlineFont;
}
if (attr.FontAttr.Shadow ?? false)
{
//font.Shadow = true;
}
if (attr.FontAttr.Underline != null)
underline = (FontUnderlineType)attr.FontAttr.Underline;
// Check if equivalent font is already available.
IFont fontTarget = workbook.FindFont(bold, color, (short)(heightInPoints * 20), name, italic, strikeout, typeOffset, underline);
if (fontTarget == null)
{
// Create required font.
fontTarget = workbook.CreateFont();
fontTarget.IsBold = bold;
fontTarget.Color = color;
fontTarget.FontHeightInPoints = heightInPoints;
fontTarget.FontName = name;
fontTarget.IsItalic = italic;
fontTarget.IsStrikeout = strikeout;
fontTarget.TypeOffset = typeOffset;
fontTarget.Underline = underline;
}
if (fontTarget != null)
return fontTarget.Index;
SaLogger.Warn(SysUtil.Fn + " Failed to identify required font.");
return -1;
}
private void ApplyFontAttr(IFont font, SaMsExcelStyleAttr attr)
{
if (attr.FontAttr.Bold ?? false)
font.IsBold = true;
if (attr.FontAttr.ColourIndex != SaXlColourIndex.NotSpecified)
{
font.Color = GetPoiColourIndex(attr.FontAttr.ColourIndex, IndexedColors.Black.Index);
}
if (attr.FontAttr.ColourRGB != null)
{
// Convert RGB colour to palette index.
short? colourIndex = GetCustomerColourIndex((int)attr.FontAttr.ColourRGB);
if (colourIndex != null)
font.Color = (short)attr.FontAttr.ColourRGB;
}
if (attr.FontAttr.HeightInPoints != null && attr.FontAttr.HeightInPoints >= FontHeightInPointsMin && attr.FontAttr.HeightInPoints <= FontHeightInPointsMax)
font.FontHeightInPoints = (double)attr.FontAttr.HeightInPoints;
if (!StringUtil.IsBlank(attr.FontAttr.Name))
font.FontName = attr.FontAttr.Name;
if (attr.FontAttr.Strikethrough ?? false)
font.IsStrikeout = true;
if (attr.FontAttr.Superscript ?? false)
font.TypeOffset = FontSuperScript.Super;
if (attr.FontAttr.Subscript ?? false)
font.TypeOffset = FontSuperScript.Sub;
if (attr.FontAttr.Outline ?? false)
{
//font.OutlineFont = (short)attr.FontAttr.OutlineFont;
}
if (attr.FontAttr.Shadow ?? false)
{
//font.Shadow = true;
}
if (attr.FontAttr.Underline != null)
font.Underline = (FontUnderlineType)attr.FontAttr.Underline;
}
//-------------------------------------------------------------------
private short GetPoiColourIndex(SaXlColourIndex colourIndex, short defaultPoiColorIndex)
{
IndexedColors poiColor = IndexedColors.ValueOf(colourIndex.GetName());
if (poiColor != null) return poiColor.Index;
return defaultPoiColorIndex;
}
private short? GetCustomerColourIndex(int rgbColour)
{
if (workbook is HSSFWorkbook)
{
HSSFPalette palette = ((HSSFWorkbook)workbook).GetCustomPalette();
byte red = (byte)((rgbColour >> 0) & 0xff);
byte green = (byte)((rgbColour >> 8) & 0xff);
byte blue = (byte)((rgbColour >> 16) & 0xff);
// Get the color which most closely matches the color you want to use
return palette.FindSimilarColor(red, green, blue).Indexed;
}
else if (workbook is XSSFWorkbook)
{
StylesTable stylesTable = ((XSSFWorkbook)workbook).GetStylesSource();
byte red = (byte)((rgbColour >> 0) & 0xff);
byte green = (byte)((rgbColour >> 8) & 0xff);
byte blue = (byte)((rgbColour >> 16) & 0xff);
IIndexedColorMap colorMap = stylesTable.GetIndexedColors();
for (int styleIdx = 0; styleIdx < stylesTable.NumCellStyles; styleIdx++)
{
ICellStyle style = stylesTable.GetStyleAt(styleIdx);
if (RGBMatches(colorMap.GetRGB(style.FillForegroundColor), red, green, blue))
return style.FillForegroundColor;
if (RGBMatches(colorMap.GetRGB(style.FillForegroundColor), red, green, blue))
return style.FillForegroundColor;
// ToDo Other colours in style.
}
}
return null;
}
private bool RGBMatches(byte[] rgb, byte red, byte green, byte blue)
{
if (rgb.Count() != 3) return false;
if (rgb[0] != red) return false;
if (rgb[1] != green) return false;
if (rgb[2] != blue) return false;
return true;
}
//-------------------------------------------------------------------
private void ApplyStylingProperties(ICellStyle cellStyle, Dictionary<String, object> styleProperties)
{
foreach (String propertyName in styleProperties.Keys)
{
object propertyValue = styleProperties[propertyName];
if (propertyValue == null)
{
SaLogger.Info(SysUtil.Fn + " Null value for style property '" + propertyName + "'");
continue;
}
switch (propertyName)
{
// Data format.
case CellUtil.DATA_FORMAT:
if (propertyValue is short)
{
cellStyle.DataFormat = (short)propertyValue;
continue;
}
break;
// Horizontal alignment.
case CellUtil.ALIGNMENT:
if (propertyValue is HorizontalAlignment || propertyValue is short)
{
cellStyle.Alignment = (HorizontalAlignment)propertyValue;
continue;
}
break;
// Vertical alignment.
case CellUtil.VERTICAL_ALIGNMENT:
if (propertyValue is VerticalAlignment || propertyValue is short)
{
cellStyle.VerticalAlignment = (VerticalAlignment)propertyValue;
continue;
}
break;
// Indentation.
case CellUtil.INDENTION:
if (propertyValue is short)
{
cellStyle.Indention = (short)propertyValue;
continue;
}
break;
// Wrap text.
case CellUtil.WRAP_TEXT:
if (propertyValue is bool)
{
cellStyle.WrapText = (bool)propertyValue;
continue;
}
break;
// Fill colours and pattern.
case CellUtil.FILL_FOREGROUND_COLOR:
if (propertyValue is short)
{
cellStyle.FillForegroundColor = (short)propertyValue;
continue;
}
break;
case CellUtil.FILL_BACKGROUND_COLOR:
if (propertyValue is short)
{
cellStyle.FillBackgroundColor = (short)propertyValue;
continue;
}
break;
case CellUtil.FILL_PATTERN:
if (propertyValue is FillPattern || propertyValue is short)
{
cellStyle.FillPattern = (FillPattern)propertyValue;
continue;
}
break;
// Hidden.
case CellUtil.HIDDEN:
if (propertyValue is bool)
{
cellStyle.IsHidden = (bool)propertyValue;
continue;
}
break;
// Locked.
case CellUtil.LOCKED:
if (propertyValue is bool)
{
cellStyle.IsLocked = (bool)propertyValue;
continue;
}
break;
// Rotation.
case CellUtil.ROTATION:
if (propertyValue is short)
{
cellStyle.Rotation = (short)propertyValue;
continue;
}
break;
// Shrink to fit.
case CellUtil.SHRINK_TO_FIT:
if (propertyValue is bool)
{
cellStyle.ShrinkToFit = (bool)propertyValue;
continue;
}
break;
// Borders.
case CellUtil.BORDER_TOP:
if (propertyValue is BorderStyle || propertyValue is short)
{
cellStyle.BorderTop = (BorderStyle)propertyValue;
continue;
}
break;
case CellUtil.TOP_BORDER_COLOR:
if (propertyValue is short)
{
cellStyle.TopBorderColor = (short)propertyValue;
continue;
}
break;
case CellUtil.BORDER_BOTTOM:
if (propertyValue is BorderStyle || propertyValue is short)
{
cellStyle.BorderBottom = (BorderStyle)propertyValue;
continue;
}
break;
case CellUtil.BOTTOM_BORDER_COLOR:
if (propertyValue is short)
{
cellStyle.BottomBorderColor = (short)propertyValue;
continue;
}
break;
case CellUtil.BORDER_LEFT:
if (propertyValue is BorderStyle || propertyValue is short)
{
cellStyle.BorderLeft = (BorderStyle)propertyValue;
continue;
}
break;
case CellUtil.LEFT_BORDER_COLOR:
if (propertyValue is short)
{
cellStyle.LeftBorderColor = (short)propertyValue;
continue;
}
break;
case CellUtil.BORDER_RIGHT:
if (propertyValue is BorderStyle || propertyValue is short)
{
cellStyle.BorderRight = (BorderStyle)propertyValue;
continue;
}
break;
case CellUtil.RIGHT_BORDER_COLOR:
if (propertyValue is short)
{
cellStyle.RightBorderColor = (short)propertyValue;
continue;
}
break;
case CellUtil.BORDER_DIAGONAL:
if (propertyValue is BorderDiagonal || propertyValue is short)
{
cellStyle.BorderDiagonal = (BorderDiagonal)propertyValue;
continue;
}
break;
// Font.
case CellUtil.FONT:
if (propertyValue is short)
{
IFont font = workbook.GetFontAt((short)propertyValue);
if (font != null)
cellStyle.SetFont(font);
continue;
}
if (propertyValue is IFont)
{
// Shouldn't get here.
cellStyle.SetFont((IFont)propertyValue);
continue;
}
break;
default:
SaLogger.Info(SysUtil.Fn + " Unrecognised style property '" + propertyName + "'");
continue;
}
// Only get here for a valid property with invalid value type.
SaLogger.Info(SysUtil.Fn + " Invalid value type for style property '" + propertyName + "': " + propertyValue.GetType().Name);
}
}
//-------------------------------------------------------------------
private BorderStyle GetBorderStyle(SaMsExcelBorderAttr borderAttr)
{
// POI Border style:
// None No border
// Thin Thin border
// Medium Medium border
// Dashed dash border
// Dotted dot border
// Thick Thick border
// Double double-line border
// Hair hair-line border
// MediumDashed Medium dashed border
// DashDot dash-dot border
// MediumDashDot medium dash-dot border
// DashDotDot dash-dot-dot border
// MediumDashDotDot medium dash-dot-dot border
// SlantedDashDot slanted dash-dot border
BorderStyle borderStyle = BorderStyle.None;
if (borderAttr.Weight != SaXlBorderWeight.NotSpecified)
{
if (borderAttr.Weight == SaXlBorderWeight.Hairline)
borderStyle = BorderStyle.Hair;
else if (borderAttr.Weight == SaXlBorderWeight.Thin)
borderStyle = BorderStyle.Thin;
else if (borderAttr.Weight == SaXlBorderWeight.Medium)
borderStyle = BorderStyle.Medium;
else if (borderAttr.Weight == SaXlBorderWeight.Thick)
borderStyle = BorderStyle.Thick;
}
if (borderAttr.LineStyle != SaXlLineStyle.NotSpecified)
{
if (borderAttr.LineStyle == SaXlLineStyle.None)
borderStyle = BorderStyle.None;
else if (borderAttr.LineStyle == SaXlLineStyle.Double)
borderStyle = BorderStyle.Double;
else if (borderAttr.LineStyle == SaXlLineStyle.Dot)
borderStyle = BorderStyle.Dotted;
else if (borderAttr.LineStyle == SaXlLineStyle.Dash)
borderStyle = borderAttr.Weight == SaXlBorderWeight.Medium || borderAttr.Weight == SaXlBorderWeight.Thick ? BorderStyle.MediumDashed : BorderStyle.Dashed;
else if (borderAttr.LineStyle == SaXlLineStyle.Continuous)
borderStyle = borderAttr.Weight == SaXlBorderWeight.Hairline ? BorderStyle.Hair : borderAttr.Weight == SaXlBorderWeight.Thin ? BorderStyle.Thin : borderAttr.Weight == SaXlBorderWeight.Medium ? BorderStyle.Medium : borderAttr.Weight == SaXlBorderWeight.Thick ? BorderStyle.Thick : BorderStyle.Thin;
else if (borderAttr.LineStyle == SaXlLineStyle.DashDot)
borderStyle = borderAttr.Weight == SaXlBorderWeight.Medium || borderAttr.Weight == SaXlBorderWeight.Thick ? BorderStyle.MediumDashDot : BorderStyle.DashDot;
else if (borderAttr.LineStyle == SaXlLineStyle.DashDotDot)
borderStyle = borderAttr.Weight == SaXlBorderWeight.Medium || borderAttr.Weight == SaXlBorderWeight.Thick ? BorderStyle.MediumDashDotDot : BorderStyle.DashDotDot;
else if (borderAttr.LineStyle == SaXlLineStyle.SlantDashDot)
borderStyle = BorderStyle.SlantedDashDot;
}
return borderStyle;
}
private void SetCellStyle(uint colPos, uint rowPos, ICellStyle cellStyle)
{
ICell cell = GetCell(colPos, rowPos);
SetCellStyle(cell, cellStyle);
}
private void SetCellStyle(ICell cell, ICellStyle cellStyle)
{
if (cell != null)
cell.CellStyle = cellStyle;
}
//-------------------------------------------------------------------
// Add image to sheet.
public override bool InsertImage(SaMsExcelImage_Config imageConfig)
{
return SetErrorState(SysUtil.Fn + " " + Msg_NotSupported);
}
//-------------------------------------------------------------------
public override bool FreezePanes(uint colPos, uint rowPos)
{
return SetErrorState(SysUtil.Fn + " " + Msg_NotSupported);
}
//-------------------------------------------------------------------
public override bool AutoFitRows(SaMsExcelRange range)
{
try
{
for (uint rowPos = range.RowFromPos; rowPos > 0 && rowPos <= range.RowToPos; rowPos++)
{
IRow row = worksheet.GetRow((int)rowPos - 1);
if (row != null)
row.Height = -1;
}
return true;
}
catch (Exception exc) { SetErrorState(SysUtil.Fn + " " + ExceptionUtil.GetErrorStateMessage(exc)); }
return false;
}
//-------------------------------------------------------------------
public override bool SelectRange(SaMsExcelRange range)
{
return SetErrorState(SysUtil.Fn + " " + Msg_NotSupported);
}
//-------------------------------------------------------------------
}
//=======================================================================
}