Data project added (previously Office)

This commit is contained in:
2021-05-14 13:17:39 +01:00
parent 53ccaf26e9
commit 19be985731
20 changed files with 4330 additions and 70 deletions
+7 -1
View File
@@ -18,7 +18,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution files", "Solution
ReadMe.md = ReadMe.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SacsStandardAccounts", "SacsStandardAccounts\SacsStandardAccounts.csproj", "{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SacsStandardAccounts", "SacsStandardAccounts\SacsStandardAccounts.csproj", "{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SacsStandardData", "SacsStandardData\SacsStandardData.csproj", "{1EF60484-61DB-4BDC-8BF2-394C663B6031}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -50,6 +52,10 @@ Global
{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}.Release|Any CPU.Build.0 = Release|Any CPU
{1EF60484-61DB-4BDC-8BF2-394C663B6031}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1EF60484-61DB-4BDC-8BF2-394C663B6031}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1EF60484-61DB-4BDC-8BF2-394C663B6031}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1EF60484-61DB-4BDC-8BF2-394C663B6031}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
+14 -6
View File
@@ -12,12 +12,12 @@ namespace Sarand.Net.Standard.Base.Bus
{
//-------------------------------------------------------------------
// Data members.
private int id = 0;
private Int64 id = 0;
//-------------------------------------------------------------------
// Construction.
public SysId () { }
public SysId (int id)
public SysId (Int64 id)
{
this.id = id;
}
@@ -25,7 +25,7 @@ namespace Sarand.Net.Standard.Base.Bus
//-------------------------------------------------------------------
// Properties - for serialisation.
//[XmlAttribute]
public int Id
public Int64 Id
{
get { return id; }
set
@@ -62,12 +62,16 @@ namespace Sarand.Net.Standard.Base.Bus
}
public override int GetHashCode ()
{
return id;
return id.GetHashCode();
}
//-------------------------------------------------------------------
// Conversion.
public int ToInt ()
public Int64 ToLong()
{
return ToInt(this);
}
public Int32 ToInt()
{
return ToInt(this);
}
@@ -80,7 +84,11 @@ namespace Sarand.Net.Standard.Base.Bus
return ToString(this, invalidValue);
}
// Null-safe static versions.
public static int ToInt (SysId sysId)
public static Int32 ToInt(SysId sysId)
{
return (IsValid(sysId) ? (Int32)sysId.id : 0);
}
public static Int64 ToLong(SysId sysId)
{
return (IsValid(sysId) ? sysId.id : 0);
}
+11
View File
@@ -179,6 +179,17 @@ namespace Sarand.Net.Standard.Base.Dbas
}
return String.Empty;
}
public static String GetIdentityColumnVariableTypeName(this List<DbDfnColumn> columns)
{
List<String> names = new List<String>();
foreach (var column in columns)
{
if (column.IsIdentity)
return column.GetVariableTypeName();
}
return String.Empty;
}
// Locate the column in the list:
public static DbDfnColumn GetColumnByPos(this List<DbDfnColumn> columns, short pos)
{
+18 -2
View File
@@ -21,6 +21,7 @@ namespace Sarand.Net.Standard.Base.Dbas
//-------------------------------------------------------------------
// Data members.
private readonly List<DbDfnIndexColumn> columns = new List<DbDfnIndexColumn>();
//-------------------------------------------------------------------
// Construction.
public DbDfnIndex () { }
@@ -31,6 +32,7 @@ namespace Sarand.Net.Standard.Base.Dbas
Name = name;
Unique = unique;
}
//-------------------------------------------------------------------
// Attributes.
public String Schema { get; set; } = String.Empty;
@@ -44,23 +46,36 @@ namespace Sarand.Net.Standard.Base.Dbas
public int Pages { get; set; } = 0;
public int UniqueValues { get; set; } = 0;
public bool HasColumns { get; set; } = false;
//-------------------------------------------------------------------
// Columns.
public List<DbDfnIndexColumn> Columns
{
get { return columns; }
set { columns.Clear(); columns.AddRange(value); }
get
{
lock (columns)
return new List<DbDfnIndexColumn>(columns);
}
set
{
lock (columns)
columns.Clear(); columns.AddRange(value);
}
}
public void CearColumns ()
{
lock (columns)
columns.Clear();
}
public void AddColumn (DbDfnIndexColumn column)
{
lock (columns)
columns.Add(column);
}
//-------------------------------------------------------------------
}
//=======================================================================
// Index list extensions.
public static class DbDfnIndexList
@@ -92,5 +107,6 @@ namespace Sarand.Net.Standard.Base.Dbas
return index;
}
}
//=======================================================================
}
+33 -4
View File
@@ -46,23 +46,35 @@ namespace Sarand.Net.Standard.Base.Dbas
// Columns.
public bool HasColumnByName(String columnName)
{
lock (columns)
return (columns != null && columns.Exists(col => col.Name.EqualsCI(columnName)));
}
public bool HasColumns()
{
lock (columns)
return (columns != null && columns.Count > 0);
}
public List<DbDfnColumn> Columns
{
get { return new List<DbDfnColumn>(columns); }
set { columns.Clear(); columns.AddRange(value); }
get
{
lock (columns)
return new List<DbDfnColumn>(columns);
}
set
{
lock (columns)
columns.Clear(); columns.AddRange(value);
}
}
public void CearColumns()
{
lock (columns)
columns.Clear();
}
public void AddColumn(DbDfnColumn column)
{
lock (columns)
columns.Add(column);
}
public List<String> GetPrimaryColumnNames()
@@ -84,23 +96,40 @@ namespace Sarand.Net.Standard.Base.Dbas
// Indices.
public bool HasIndexByName(String indexName)
{
lock (indices)
return (indices != null && indices.Exists(idx => idx.Name.EqualsCI(indexName)));
}
public bool HasIndices()
{
lock (indices)
return (indices != null && indices.Count > 0);
}
public List<DbDfnIndex> Indices
{
get { return new List<DbDfnIndex>(indices); }
set { indices.Clear(); indices.AddRange(value); }
get
{
lock (indices)
return new List<DbDfnIndex>(indices);
}
set
{
lock (indices)
indices.Clear(); indices.AddRange(value);
}
}
public DbDfnIndex GetIndexByName(String name)
{
lock (indices)
return indices.GetIndexByName(name);
}
public void CearIndices()
{
lock (indices)
indices.Clear();
}
public void AddIndex(DbDfnIndex Index)
{
lock (indices)
indices.Add(Index);
}
+5 -2
View File
@@ -148,6 +148,10 @@ namespace Sarand.Net.Standard.Base.Dbas
type = DbColumnDataType.Int;
break;
//---------------------------------------------------------------
case -5: // SQL_BIGINT: // -5 BIGINT Exact numeric value with precision 19 (if signed) or 20 (if unsigned) and scale 0 (signed: –2[63] <= n <= 2[63] – 1, unsigned:0 <= n <= 2[64] – 1)[3],[9].
type = DbColumnDataType.BigInt;
break;
//---------------------------------------------------------------
case 7: // SQL_REAL: // 7 REAL Signed, approximate, numeric value with a binary precision 24 (zero or absolute value 10[–38] to 10[38]).
type = DbColumnDataType.Single;
break;
@@ -175,7 +179,6 @@ namespace Sarand.Net.Standard.Base.Dbas
type = DbColumnDataType.Binary;
break;
//---------------------------------------------------------------
case -5: // SQL_BIGINT: // -5 BIGINT Exact numeric value with precision 19 (if signed) or 20 (if unsigned) and scale 0 (signed: –2[63] <= n <= 2[63] – 1, unsigned:0 <= n <= 2[64] – 1)[3],[9].
case 102: // SQL_INTERVAL_MONTH: // 102 INTERVAL MONTH(p) Number of months between two dates; p is the interval leading precision.
case 101: // SQL_INTERVAL_YEAR: // 101 INTERVAL YEAR(p) Number of years between two dates; p is the interval leading precision.
case 107: // SQL_INTERVAL_YEAR_TO_MONTH: // 107 INTERVAL YEAR(p) TO MONTH Number of years and months between two dates; p is the interval leading precision.
@@ -190,7 +193,7 @@ namespace Sarand.Net.Standard.Base.Dbas
case 112: // SQL_INTERVAL_HOUR_TO_SECOND: // 112 INTERVAL HOUR(p) TO SECOND(q) Number of hours/minutes/seconds between two date/times; p is the interval leading precision and q is the interval seconds precision.
case 113: // SQL_INTERVAL_MINUTE_TO_SECOND: // 113 INTERVAL MINUTE(p) TO SECOND(q) Number of minutes/seconds between two date/times; p is the interval leading precision and q is the interval seconds precision.
case -11: // SQL_GUID: // -11 GUID Fixed length Globally Unique Identifier.
break;
// break;
//---------------------------------------------------------------
default:
SaLogger.Debug("OdbcUtil.OdbcToDataType Unrecognised native data type: " + dataType);
+12
View File
@@ -1,4 +1,5 @@
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using System;
using System.Globalization;
@@ -282,6 +283,14 @@ namespace Sarand.Net.Standard.Base.Utils
catch (Exception) { }
return defaultValue;
}
//---------------------------------------------------------------------------
// SysId.
public static SysId ToSysId(this String value)
{
return new SysId(StringUtil.ToLong(value));
}
//---------------------------------------------------------------------------
// Hex values to integer.
/// <summary>Convert hex character to integer value.</summary>
@@ -312,6 +321,7 @@ namespace Sarand.Net.Standard.Base.Utils
}
return intValue;
}
//-------------------------------------------------------------------
// Floating point values.
public static float ToSingle (this string value, float defaultValue = 0)
@@ -344,6 +354,7 @@ namespace Sarand.Net.Standard.Base.Utils
catch (Exception) { }
return defaultValue;
}
//-------------------------------------------------------------------
// Decimal values.
public static decimal ToDecimal (this string value, decimal defaultValue = 0)
@@ -368,6 +379,7 @@ namespace Sarand.Net.Standard.Base.Utils
catch (Exception) { }
return defaultValue;
}
//-------------------------------------------------------------------
// Boolean values.
public static bool ToBool (this string value)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,206 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sarand.Net.Standard.Data.Excel
{
//=======================================================================
// Definitions.
public enum SaExcelLogicalUnit
{
Point,
Pixel,
Cm,
Inch,
//CharWidth, // Not supported.
};
//=======================================================================
/// <summary>Spreadsheet file format.
/// <para>Ref. Microsoft.Office.Interop.Excel.XlFileFormat</para></summary>
public enum SaXlFileFormat
{
Default = 0,
/// <summary>Without macro's in 2007-2013 [xlsx]. Value: 51.</summary>
OpenXMLWorkbook = XlFileFormat.xlOpenXMLWorkbook,
/// <summary>With or without macro's in 2007-2013 [xlsm]. Value: 52.</summary>
OpenXMLWorkbookMacroEnabled = XlFileFormat.xlOpenXMLWorkbookMacroEnabled,
/// <summary>Excel Binary Workbook in 2007-2013 with or without macro's [xlsb]. Value: 50.</summary>
Excel12 = XlFileFormat.xlExcel12,
/// <summary>97-2003 format in Excel 2007-2013 [xls]. Value: 56.</summary>
Excel8 = XlFileFormat.xlExcel8,
/// <summary>CSV format. Value: 6.</summary>
CSV = XlFileFormat.xlCSV,
};
/// <summary>
/// Specifies the page orientation when the worksheet is printed.
/// <para>Ref. Microsoft.Office.Interop.Excel.XlPageOrientation</para>
/// </summary>
public enum SaXlPageOrientation
{
NotSpecified = int.MinValue,
xlPortrait = XlPageOrientation.xlPortrait,
xlLandscape = XlPageOrientation.xlLandscape
}
/// <summary>
/// Specifies the weight of the border around a range.
/// <para>Ref. Microsoft.Office.Interop.Excel.XlBorderWeight</para>
/// </summary>
public enum SaXlBorderWeight
{
NotSpecified = int.MinValue,
Hairline = XlBorderWeight.xlHairline,
Thin = XlBorderWeight.xlThin,
Medium = XlBorderWeight.xlMedium,
Thick = XlBorderWeight.xlThick
}
/// <summary>
/// Specifies the line style for the border.
/// <para>Ref. Microsoft.Office.Interop.Excel.XlLineStyle</para>
/// </summary>
public enum SaXlLineStyle
{
NotSpecified = int.MinValue,
None = XlLineStyle.xlLineStyleNone,
Double = XlLineStyle.xlDouble,
Dot = XlLineStyle.xlDot,
Dash = XlLineStyle.xlDash,
Continuous = XlLineStyle.xlContinuous,
DashDot = XlLineStyle.xlDashDot,
DashDotDot = XlLineStyle.xlDashDotDot,
SlantDashDot = XlLineStyle.xlSlantDashDot,
}
/// <summary>
/// Specifies the interior pattern of a chart or interior object.
/// <para>Ref. Microsoft.Office.Interop.Excel.XlPattern</para>
/// </summary>
public enum SaXlPattern
{
NotSpecified = int.MinValue,
/// <summary>No pattern.</summary>
None = XlPattern.xlPatternNone,
/// <summary>Excel controls the pattern.</summary>
Automatic = XlPattern.xlPatternAutomatic,
/// <summary>8% gray.</summary>
Gray8 = XlPattern.xlPatternGray8,
/// <summary>16% gray.</summary>
Gray16 = XlPattern.xlPatternGray16,
/// <summary>25% gray.</summary>
Gray25 = XlPattern.xlPatternGray25,
/// <summary>50% gray.</summary>
Gray50 = XlPattern.xlPatternGray50,
/// <summary>75% gray.</summary>
Gray75 = XlPattern.xlPatternGray75,
/// <summary>75% dark moiré.</summary>
SemiGray75 = XlPattern.xlPatternSemiGray75,
/// <summary>Solid color.</summary>
Solid = XlPattern.xlPatternSolid,
/// <summary>Dark vertical bars.</summary>
Vertical = XlPattern.xlPatternVertical,
/// <summary>Dark horizontal lines.</summary>
Horizontal = XlPattern.xlPatternHorizontal,
/// <summary>Dark diagonal lines running from the lower left to the upper right.</summary>
Up = XlPattern.xlPatternUp,
/// <summary>Dark diagonal lines running from the upper left to the lower right.</summary>
Down = XlPattern.xlPatternDown,
/// <summary>Checkerboard.</summary>
Checker = XlPattern.xlPatternChecker,
/// <summary>Light horizontal lines.</summary>
LightHorizontal = XlPattern.xlPatternLightHorizontal,
/// <summary>Light vertical bars.</summary>
LightVertical = XlPattern.xlPatternLightVertical,
/// <summary>Light diagonal lines running from the upper left to the lower right.</summary>
LightDown = XlPattern.xlPatternLightDown,
/// <summary>Light diagonal lines running from the lower left to the upper right.</summary>
LightUp = XlPattern.xlPatternLightUp,
/// <summary>Grid.</summary>
Grid = XlPattern.xlPatternGrid,
/// <summary>Criss-cross lines.</summary>
CrissCross = XlPattern.xlPatternCrissCross,
LinearGradient = XlPattern.xlPatternLinearGradient,
RectangularGradient = XlPattern.xlPatternRectangularGradient
}
/// <summary>
/// Colour index.
/// <para>Ref. Microsoft.Office.Interop.Excel.XlColorIndex.</para>
/// </summary>
public enum SaXlColourIndex
{
NotSpecified = int.MinValue,
/// <summary>No color. -4142, &HFFFFEFD2.</summary>
None = XlColorIndex.xlColorIndexNone,
/// <summary>Automatic color. -4105, &HFFFFEFF7.</summary>
Automatic = XlColorIndex.xlColorIndexAutomatic,
Black = 1,
White = 2,
Red = 3,
BrightGreen = 4,
Blue = 5,
Yellow = 6,
Pink = 7,
Magenta = 7,
Turqoise = 8,
Cyan = 8,
DarkRed = 9,
Green = 10,
DarkBlue = 11,
DarkYellow = 12,
Violet = 13,
Teal = 14,
Gray25 = 15,
Gray50 = 16,
SkyBlue = 33,
LightTurqoise = 34,
LightGreen = 35,
LightYellow = 36,
PaleBlue = 37,
Rose = 38,
Lavendar = 39,
Tan = 40,
LightBlue = 41,
Aqua = 42,
Lime = 43,
Gold = 44,
LightOrange = 45,
Orange = 46,
BlueGray = 47,
Gray40 = 48,
DarkTeal = 49,
SeaGreen = 50,
DarkGreen = 51,
OliveGreen = 52,
Brown = 53,
Plum = 54,
Indigo = 55,
Gray80 = 56,
};
/// <summary>
/// RGB colour value.
/// <para>Ref. Microsoft.Office.Interop.Excel.XlRgbColor.</para>
/// </summary>
public enum SaXlRgbColor
{
NotSpecified = int.MinValue,
Red = XlRgbColor.rgbRed,
}
/// <summary>
/// Specifies the type of underline applied to a font.
/// <para>Ref. Microsoft.Office.Interop.Excel.XlUnderlineStyle</para>
/// </summary>
public enum SaXlUnderlineStyle
{
/// <summary>No underlining.</summary>
None = XlUnderlineStyle.xlUnderlineStyleNone,
/// <summary>Double thick underline.</summary>
Double = XlUnderlineStyle.xlUnderlineStyleDouble,
/// <summary>Single underlining.</summary>
Single = XlUnderlineStyle.xlUnderlineStyleSingle,
/// <summary>Single accounting - Not supported.</summary>
SingleAccounting = XlUnderlineStyle.xlUnderlineStyleSingleAccounting,
/// <summary>Double accounting - Two thin underlines placed close together.</summary>
DoubleAccounting = XlUnderlineStyle.xlUnderlineStyleDoubleAccounting
}
//=======================================================================
}
@@ -0,0 +1,569 @@
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.Data.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));
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,909 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using Sarand.Net.Standard.Data.Xml;
using Sarand.Net.Standard.Data.Zip;
namespace Sarand.Net.Standard.Data.Excel
{
//=======================================================================
/// <summary>Style properties retrieved directly from spreadsheet xml data.</summary>
public class SaMsExcelStyle
{
public SaMsExcelStyle () { }
public int NumFmtId { get; set; }
public int FontId { get; set; }
public int FillId { get; set; }
public int BorderId { get; set; }
public int XfId { get; set; }
public bool QuotePrefix { get; set; }
public bool PivotButton { get; set; }
public bool ApplyNumberFormat { get; set; }
public bool ApplyFont { get; set; }
public bool ApplyFill { get; set; }
public bool ApplyBorder { get; set; }
public bool ApplyAlignment { get; set; }
public bool ApplyProtection { get; set; }
public XlHAlign AlignHorizontal { get; set; }
public XlVAlign AlignVertical { get; set; }
public String NumFmtCode { get; set; } = "";
};
//=======================================================================
/// <summary>Excel spreadsheet read directly from xml data rather than via COM/Interop.</summary>
public class SaMsSpreadsheet_Direct : SaMsSpreadsheet
{
//-------------------------------------------------------------------
// Data members.
internal class Workbook
{
internal SaMsZipArchive WorkbookArchive { get; set; }
internal SaMsXmlDocument WorkbookDoc { get; set; }
internal SaMsXmlDocument SharedStringsDoc { get; set; }
internal SaMsXmlDocument StylesDoc { get; set; }
internal uint WorksheetCount { get; set; }
internal uint ActiveSheetPos { get; set; }
internal bool IsValid () { return (WorkbookDoc != null && WorkbookDoc.GetRootElement() != null); }
}
private Workbook workbook;
private class Worksheet
{
internal uint WorksheetPos { get; set; }
internal uint WorksheetId { get; set; }
internal String WorksheetArchivePath { get; set; }
internal String WorksheetName { get; set; }
internal SaMsXmlDocument WorksheetDoc { get; set; }
internal uint ActiveColPos { get; set; }
internal uint ActiveRowPos { get; set; }
internal class NodesData
{
internal SaMsXmlElement Cols { get; set; }
internal SaMsXmlElement ActiveCol { get; set; }
internal SaMsXmlElement Rows { get; set; }
internal SaMsXmlElement ActiveRow { get; set; }
}
internal NodesData Nodes { get; } = new NodesData();
bool IsValid () { return (WorksheetDoc != null && WorksheetDoc.GetRootElement() != null); }
}
private Worksheet worksheet;
//-------------------------------------------------------------------
// Construction.
public SaMsSpreadsheet_Direct () : 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 && workbook.IsValid());
}
public override bool CreateWorkbook ()
{
CloseWorkbook();
ClearErrorState();
// Create new workbook.
workbook = new Workbook();
workbook.WorkbookArchive = new SaMsZipArchive();
workbook.SharedStringsDoc = new SaMsXmlDocument();
workbook.StylesDoc = new SaMsXmlDocument();
return SetErrorState("Creating workbook not supported");
}
public override bool OpenWorkbook (String filePath)
{
CloseWorkbook();
ClearErrorState();
if (!File.Exists(filePath))
return SetErrorState("Workbook not found");
List<String> validExtensions = new List<string>() { /*".xls",*/ ".xlsx", ".xlsb", ".zip" };
String extension = Path.GetExtension(filePath);
if (!validExtensions.ContainsCI(Path.GetExtension(filePath)))
return SetErrorState("Invalid document type (expected xlsx/xlsb)");
try
{
// Open workbook document.
workbook = new Workbook();
workbook.WorkbookArchive = new SaMsZipArchive();
if (workbook.WorkbookArchive.OpenArchive(filePath))
{
ExtractWorkbookElementsFromArchive();
}
else return SetErrorState("Failed to open document: " + workbook.WorkbookArchive.ErrorStateMessage);
}
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.
workbook = new Workbook();
workbook.WorkbookArchive = new SaMsZipArchive();
if (workbook.WorkbookArchive.OpenArchive(workbookStream))
{
ExtractWorkbookElementsFromArchive();
}
else return SetErrorState("Failed to open document: " + workbook.WorkbookArchive.ErrorStateMessage);
}
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
return !HasErrorState();
}
private bool ExtractWorkbookElementsFromArchive ()
{
ClearErrorState();
try
{
// Extract the workbook data.
using (MemoryStream workbookFile = workbook.WorkbookArchive.ExtractFileToStream("xl/workbook.xml"))
{
if (workbookFile == null) return SetErrorState("Failed to load workbook data");
workbook.WorkbookDoc = new SaMsXmlDocument();
if (workbook.WorkbookDoc.LoadXml(workbookFile))
{
// Workbook successfully opened.
workbook.ActiveSheetPos = 1;
// Shared strings:
using (MemoryStream sharedStringsFile = workbook.WorkbookArchive.ExtractFileToStream("xl/sharedStrings.xml"))
{
if (sharedStringsFile != null)
{
workbook.SharedStringsDoc = new SaMsXmlDocument();
workbook.SharedStringsDoc.LoadXml(sharedStringsFile);
}
}
// Styles:
using (MemoryStream stylesFile = workbook.WorkbookArchive.ExtractFileToStream("xl/styles.xml"))
{
if (stylesFile != null)
{
workbook.StylesDoc = new SaMsXmlDocument();
workbook.StylesDoc.LoadXml(stylesFile);
}
}
// Set worksheet count and open first worksheet.
PopulateWorksheetCount();
OpenWorksheet(1);
}
else return SetErrorState("Failed to read workbook data");
}
}
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
return !HasErrorState();
}
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() && !workbook.IsValid())
SetErrorState("Workbook is not open");
SetErrorState("Saving workbook not supported");
return !HasErrorState();
}
public override bool CloseWorkbook ()
{
ClearErrorState();
CloseWorksheet();
// Clear workbook.
if (workbook != null)
{
try
{
if (workbook.StylesDoc != null) workbook.StylesDoc.Dispose(); workbook.StylesDoc = null;
if (workbook.SharedStringsDoc != null) workbook.SharedStringsDoc.Dispose(); workbook.SharedStringsDoc = null;
if (workbook.WorkbookDoc != null) workbook.WorkbookDoc.Dispose(); workbook.WorkbookDoc = null;
if (workbook.WorkbookArchive != null) workbook.WorkbookArchive.Dispose(); workbook.WorkbookArchive = null;
}
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
workbook = null;
}
return !HasErrorState();
}
//-------------------------------------------------------------------
// W o r k s h e e t
//-------------------------------------------------------------------
public override bool IsWorksheetValid ()
{
return (worksheet != null && worksheet.WorksheetDoc != null);
}
public override uint WorksheetCount { get { return workbook.WorksheetCount; } }
private void PopulateWorksheetCount ()
{
if (!IsWorkbookValid()) return;
try
{
// Count worksheets in workbook.
SaMsXmlElement nodeWorkbook = workbook.WorkbookDoc.GetRootElement();
SaMsXmlElement nodeSheets = nodeWorkbook.GetFirstChildElement("sheets");
workbook.WorksheetCount = (uint)nodeSheets.GetChildElements("sheet").Count;
}
catch (Exception exc) { HandleException("GetWorksheetCount", exc); }
}
public override bool SetWorksheetCount (int worksheetCount)
{
ClearErrorState();
return SetErrorState("Modifying workbook not supported");
}
public override bool AddWorksheet(String name)
{
return SetErrorState("Modifying workbook not supported");
}
public override bool RemoveWorksheet(uint worksheetPos)
{
return SetErrorState("Modifying workbook not supported");
}
public override bool OpenWorksheet (uint worksheetPos)
{
ClearErrorState();
if (!workbook.IsValid()) return SetErrorState("Workbook is not open");
if (worksheetPos > WorksheetCount) return SetErrorState("Invalid sheet specified");
if (worksheetPos <= 0) worksheetPos = Math.Max(1, workbook.ActiveSheetPos);
CloseWorksheet();
try
{
worksheet = new Worksheet();
// Locate worksheet in workbook by 0-index.
SaMsXmlElement workbookElement = workbook.WorkbookDoc.GetRootElement();
SaMsXmlElement sheetsElement = workbookElement.GetFirstChildElement("sheets");
long sheetCount = 0;
foreach (SaMsXmlElement sheetElement in sheetsElement.GetChildElements("sheet"))
{
sheetCount++;
if (sheetCount == worksheetPos)
{
// Extract the worksheet data.
uint sheetId = (uint)StringUtil.ToInt(sheetElement.GetAttributeValue("sheetId"));
String worksheetArchivePath = "xl/worksheets/sheet" + worksheetPos.ToString() + ".xml";
using (MemoryStream worksheetFile = workbook.WorkbookArchive.ExtractFileToStream(worksheetArchivePath))
{
if (worksheetFile == null) return SetErrorState("Failed to load worksheet data");
worksheet.WorksheetDoc = new SaMsXmlDocument();
if (worksheet.WorksheetDoc.LoadXml(worksheetFile))
{
workbook.ActiveSheetPos = worksheetPos;
worksheet.WorksheetPos = worksheetPos;
worksheet.WorksheetId = sheetId;
worksheet.WorksheetArchivePath = worksheetArchivePath;
worksheet.WorksheetName = sheetElement.GetAttributeValue("name");
worksheet.ActiveColPos = 1;
worksheet.ActiveRowPos = 1;
SaMsXmlElement nodeWorksheet = worksheet.WorksheetDoc.GetRootElement();
worksheet.Nodes.Cols = nodeWorksheet.GetFirstChildElement("cols");
worksheet.Nodes.ActiveCol = worksheet.Nodes.Cols.GetFirstChildElement("col");
worksheet.Nodes.Rows = nodeWorksheet.GetFirstChildElement("sheetData");
worksheet.Nodes.ActiveRow = worksheet.Nodes.Rows.GetFirstChildElement("row");
workbook.ActiveSheetPos = worksheetPos;
}
else return SetErrorState("Failed to read data for worksheet " + worksheetPos.ToString());
}
break;
}
}
if (worksheet.WorksheetDoc == null) return SetErrorState("Unable to load worksheet " + worksheetPos.ToString());
}
catch (Exception exc) { HandleException("OpenWorksheet", exc); }
return !HasErrorState();
}
public override uint WorksheetPos { get { return workbook.ActiveSheetPos; } }
public override String WorksheetName
{
get { return ""; }
set { }
}
public override bool SetWorksheetAttr (SaMsExcelItemAttr attr)
{
return SetErrorState("Not supported");
}
public override bool CloseWorksheet ()
{
ClearErrorState();
if (worksheet != null)
{
try
{
if (worksheet.WorksheetDoc != null) worksheet.WorksheetDoc.Dispose(); worksheet.WorksheetDoc = null;
if (worksheet.Nodes.Cols != null) worksheet.Nodes.Cols.Dispose(); worksheet.Nodes.Cols = null;
if (worksheet.Nodes.ActiveCol != null) worksheet.Nodes.ActiveCol.Dispose(); worksheet.Nodes.ActiveCol = null;
if (worksheet.Nodes.Rows != null) worksheet.Nodes.Rows.Dispose(); worksheet.Nodes.Rows = null;
if (worksheet.Nodes.ActiveRow != null) worksheet.Nodes.ActiveRow.Dispose(); worksheet.Nodes.ActiveRow = null;
}
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
worksheet = null;
}
return !HasErrorState();
}
//-------------------------------------------------------------------
// Worksheet Page Setup.
public override bool SetPageSetup (SaMsExcelPageSetup_Config pageSetupConfig)
{
return SetErrorState("Not supported");
}
public override bool SetPageBreak (uint col, uint row)
{
return SetErrorState("Not supported");
}
//-------------------------------------------------------------------
// C o l u m n s
//-------------------------------------------------------------------
public override uint GetActiveColPos ()
{
return worksheet.ActiveColPos;
}
private SaMsXmlElement GetColElement (uint colPos)
{
ClearErrorState();
try
{
if (worksheet.ActiveColPos == colPos) return worksheet.Nodes.ActiveCol;
int colCount = 0;
foreach (SaMsXmlElement colElement in worksheet.Nodes.Cols.GetChildElements("Col"))
{
if (++colCount == colPos)
{
if (worksheet.Nodes.ActiveCol != null) worksheet.Nodes.ActiveCol.Dispose();
worksheet.ActiveColPos = colPos;
worksheet.Nodes.ActiveCol = colElement;
return colElement;
}
}
}
catch (Exception exc) { HandleException("GetColElement", exc); }
return new SaMsXmlElement(null);
}
public override double GetColWidth (uint colPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
{
ClearErrorState();
try
{
// Retrieve width (in points) from column.
SaMsXmlNode nodeCol = GetColElement(colPos);
double width = nodeCol.GetAttributeValue("width").ToDouble();
// 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("GetColWidth", exc); }
return 0.0;
}
public override bool SetColWidth (uint colPos, double fWidth, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
{
return SetErrorState("Not supported");
}
//-------------------------------------------------------------------
// R o w s
//-------------------------------------------------------------------
public override uint GetActiveRowPos ()
{
return worksheet.ActiveRowPos;
}
SaMsXmlElement GetRowElement (uint rowPos)
{
ClearErrorState();
try
{
if (worksheet.ActiveRowPos == rowPos) return worksheet.Nodes.ActiveRow;
foreach (SaMsXmlElement rowElement in worksheet.Nodes.Rows.GetChildElements("row"))
{
if (rowElement.GetAttributeValue("r").ToLong() == rowPos)
{
if (worksheet.Nodes.ActiveRow != null) worksheet.Nodes.ActiveRow.Dispose();
worksheet.ActiveRowPos = rowPos;
worksheet.Nodes.ActiveRow = rowElement;
return rowElement;
}
}
}
catch (Exception exc) { HandleException("GetRowElement", exc); }
return new SaMsXmlElement(null);
}
public override double GetRowHeight (uint rowPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
{
ClearErrorState();
try
{
// Retrieve height (in points) from row.
SaMsXmlElement rowElement = GetRowElement(rowPos);
double height = rowElement.GetAttributeValue("ht").ToDouble();
// 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("GetRowHeight", exc); }
return 0.0;
}
public override bool SetRowHeight (uint rowPos, double fHeight, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
{
return SetErrorState("Not supported");
}
//-------------------------------------------------------------------
// R o w s
//-------------------------------------------------------------------
public override List<DataValue> GetRowDataValues (uint rowPos, int maxColumns = 0)
{
ClearErrorState();
List<DataValue> values = new List<DataValue>();
try
{
SaMsXmlElement rowElement = GetRowElement(rowPos);
foreach (SaMsXmlElement cellElement in rowElement.GetChildElements("c"))
{
// CellId may be needed in case cells are skipped in the data.
// Doesn't appear to be the case, even when previous cell is merged with next.
String cellId = cellElement.GetAttributeValue("r");
values.Add(GetCellDataValue(cellElement));
if (maxColumns > 0 && values.Count >= maxColumns) break;
}
}
catch (Exception exc) { HandleException("GetRowDataValues", exc); }
return values;
}
//-------------------------------------------------------------------
// C e l l s
//-------------------------------------------------------------------
SaMsXmlElement GetCellElement (uint colPos, uint rowPos)
{
ClearErrorState();
String cellId = GetCellId(colPos,rowPos);
try
{
SaMsXmlElement rowElement = GetRowElement(rowPos);
foreach (SaMsXmlElement cellElement in rowElement.GetChildElements("c"))
{
if (cellElement.GetAttributeValue("r").EqualsCI(cellId))
return cellElement;
}
}
catch (Exception exc) { HandleException("GetCellElement", exc); }
return new SaMsXmlElement(null);
}
public override void SetActiveCell (uint colPos, uint rowPos)
{
// ToDo SetActiveCell.
SetErrorState("Not supported");
}
//-------------------------------------------------------------------
private bool IsCellFormula (uint colPos, uint rowPos)
{
ClearErrorState();
bool bIsFormula = false;
try
{
SaMsXmlElement cellElement = GetCellElement(colPos,rowPos);
bIsFormula = !cellElement.GetAttributeValue("f").IsEmpty();
}
catch (Exception exc) { HandleException("IsCellFormula", exc); }
return bIsFormula;
}
private bool IsCellNumeric (uint colPos, uint rowPos)
{
ClearErrorState();
try
{
SaMsXmlElement cellElement = GetCellElement(colPos,rowPos);
SaMsExcelStyle cellStyle = GetCellStyle(cellElement);
return IsCellNumeric(cellElement, cellStyle);
}
catch (Exception exc) { HandleException("IsCellNumeric", exc); }
return false;
}
private bool IsCellNumeric (SaMsXmlElement cellElement)
{
ClearErrorState();
SaMsExcelStyle cellStyle = GetCellStyle(cellElement);
return IsCellNumeric(cellElement, cellStyle);
}
private bool IsCellNumeric (SaMsXmlElement cellElement, SaMsExcelStyle cellStyle)
{
ClearErrorState();
return (cellElement.GetAttributeValue("t").IsEmpty() && !IsDateTimeStyle(cellStyle.NumFmtCode));
}
private bool IsCellDate (uint colPos, uint rowPos)
{
ClearErrorState();
bool bIsDate = false;
try
{
SaMsXmlElement cellElement = GetCellElement(colPos,rowPos);
SaMsExcelStyle cellStyle = GetCellStyle(cellElement);
return IsCellDate(cellElement, cellStyle);
}
catch (Exception exc) { HandleException("IsCellDate", exc); }
return bIsDate;
}
private bool IsCellDate (SaMsXmlElement cellElement)
{
return IsCellDate(cellElement, GetCellStyle(cellElement));
}
private bool IsCellDate (SaMsXmlElement cellElement, SaMsExcelStyle cellStyle)
{
ClearErrorState();
return IsDateTimeStyle(cellStyle.NumFmtCode);
}
//-------------------------------------------------------------------
public override String GetCellFormula (uint colPos, uint rowPos)
{
ClearErrorState();
try
{
SaMsXmlElement cellElement = GetCellElement(colPos,rowPos);
String formula = cellElement.GetAttributeValue("f");
if (formula.IsEmpty())
formula = GetCellText(cellElement, true);
return formula;
}
catch (Exception exc) { HandleException("GetCellFormula", exc); }
return "";
}
private String GetCellText (SaMsXmlElement cellElement, bool trimValue = true)
{
ClearErrorState();
String value = "";
try
{
if (cellElement.GetAttributeValue("t").EqualsCI("s"))
value = GetSharedString(cellElement);
else
value = cellElement.GetChildText("v");
if (trimValue) value.TrimAll();
}
catch (Exception exc) { HandleException("GetCellText", exc); }
return value;
}
public override DataValue GetCellDataValue (uint colPos, uint rowPos)
{
return GetCellDataValue(GetCellElement(colPos, rowPos), false);
}
private DataValue GetCellDataValue (SaMsXmlElement cellElement, bool trimTextValue = true)
{
ClearErrorState();
try
{
SaMsExcelStyle cellStyle = GetCellStyle(cellElement);
if (cellElement.GetAttributeValue("t").EqualsCI("s"))
{
String value = GetSharedString(cellElement);
if (trimTextValue) value = value.TrimAll();
return new DataValue(value);
}
else
{
String value = cellElement.GetChildText("v");
if (IsDateTimeStyle(cellStyle.NumFmtCode))
return new DataValue(DateTime.FromOADate(value.ToDouble()));
if (IsCellNumeric(cellElement, cellStyle))
{
if (value.IsNumeric())
return new DataValue(value.ToLong());
if (value.IsDecimal())
{
#if DEBUG
//if (StringUtil.ToInt(value) > 600) Debugger.Break();
#endif
return new DataValue(value.ToDecimal());
}
}
if (trimTextValue) value = value.TrimAll();
return new DataValue(value);
}
}
catch (Exception exc) { HandleException("GetCellDataValue", exc); }
return new DataValue();
}
//-------------------------------------------------------------------
// Shared string for cell.
private String GetSharedString (SaMsXmlElement nodeElement)
{
ClearErrorState();
try
{
SaMsXmlElement sharedStringElement = GetSharedStringElement(nodeElement);
return sharedStringElement.GetChildText("t");
}
catch (Exception exc) { HandleException("GetSharedString", exc); }
return "";
}
private SaMsXmlElement GetSharedStringElement (SaMsXmlElement cellElement)
{
ClearErrorState();
if (workbook.SharedStringsDoc == null || cellElement == null || !cellElement.Valid) return null;
if (!cellElement.GetAttributeValue("t").EqualsCI("s") || !cellElement.GetChildText("v").IsNumeric()) return null;
// Shared strings are indexed from 0.
long sharedStringIdx = -1;
try
{
long iIdx = cellElement.GetChildText("v").ToLong();
SaMsXmlElement sstElement = workbook.SharedStringsDoc.GetRootElement();
foreach (SaMsXmlElement siElement in sstElement.GetChildElements("si"))
{
if (++sharedStringIdx == iIdx)
return siElement;
}
}
catch (Exception exc) { HandleException("GetSharedStringNode", exc); }
return new SaMsXmlElement(null);
}
//-------------------------------------------------------------------
public override bool SetCellFormula (uint colPos, uint rowPos, String value)
{
return SetErrorState("Not supported");
}
public override bool SetCellFormula (uint colPos, uint rowPos, String value, SaMsExcelItemAttr attr)
{
return SetErrorState("Not supported");
}
public override bool SetRowFormulas (uint colPosStart, uint rowPos, List<Object> values)
{
return SetErrorState("Not supported");
}
public override bool SetRangeFormulas (SaMsExcelRange range, List<Object> values)
{
return SetErrorState("Not supported");
}
//-------------------------------------------------------------------
// 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 SaMsExcelStyle GetCellStyle (SaMsXmlElement cellElement)
{
ClearErrorState();
SaMsExcelStyle style = new SaMsExcelStyle();
if (workbook.SharedStringsDoc == null || cellElement == null || !cellElement.Valid || !cellElement.GetAttributeValue("s").IsNumeric()) return style;
// Styles are indexed from 0.
long styleIdx = -1;
try
{
long cellStyleIdx = cellElement.GetAttributeValue("s").ToLong();
SaMsXmlElement styleSheetElement = workbook.SharedStringsDoc.GetRootElement();
SaMsXmlElement cellXfsElement = styleSheetElement.GetFirstChildElement("cellXfs");
foreach (SaMsXmlElement xfElement in styleSheetElement.GetChildElements("xf"))
{
if (++styleIdx == cellStyleIdx)
{
// Construct style.
style.NumFmtId = (int)xfElement.GetAttributeValue("numFmtId").ToLong();
style.FontId = (int)xfElement.GetAttributeValue("fontId").ToLong();
style.FillId = (int)xfElement.GetAttributeValue("fillId").ToLong();
style.BorderId = (int)xfElement.GetAttributeValue("borderId").ToLong();
style.XfId = (int)xfElement.GetAttributeValue("xfId").ToLong();
style.QuotePrefix = xfElement.GetAttributeValue("quotePrefix").ToBool();
style.PivotButton = xfElement.GetAttributeValue("pivotButton").ToBool();
style.ApplyNumberFormat = xfElement.GetAttributeValue("applyNumberFormat").ToBool();
style.ApplyFont = xfElement.GetAttributeValue("applyFont").ToBool();
style.ApplyFill = xfElement.GetAttributeValue("applyFill").ToBool();
style.ApplyBorder = xfElement.GetAttributeValue("applyBorder").ToBool();
style.ApplyAlignment = xfElement.GetAttributeValue("applyAlignment").ToBool();
style.ApplyProtection = xfElement.GetAttributeValue("applyProtection").ToBool();
// Alignment.
SaMsXmlNode nodeAlignment = xfElement.GetFirstChildElement("alignment");
String sAlignHorizontal = nodeAlignment.GetAttributeValue("horizontal");
if (sAlignHorizontal.EqualsCI("center")) style.AlignHorizontal = XlHAlign.xlHAlignCenter;
else if (sAlignHorizontal.EqualsCI("centerContinuous")) style.AlignHorizontal = XlHAlign.xlHAlignCenterAcrossSelection;
else if (sAlignHorizontal.EqualsCI("distributed")) style.AlignHorizontal = XlHAlign.xlHAlignDistributed;
else if (sAlignHorizontal.EqualsCI("fill")) style.AlignHorizontal = XlHAlign.xlHAlignFill;
else if (sAlignHorizontal.EqualsCI("justify")) style.AlignHorizontal = XlHAlign.xlHAlignJustify;
else if (sAlignHorizontal.EqualsCI("left")) style.AlignHorizontal = XlHAlign.xlHAlignLeft;
else if (sAlignHorizontal.EqualsCI("right")) style.AlignHorizontal = XlHAlign.xlHAlignRight;
String sAlignVertical = nodeAlignment.GetAttributeValue("vertical");
if (sAlignVertical.EqualsCI("center")) style.AlignVertical = XlVAlign.xlVAlignCenter;
else if (sAlignVertical.EqualsCI("top")) style.AlignVertical = XlVAlign.xlVAlignTop;
else if (sAlignVertical.EqualsCI("bottom")) style.AlignVertical = XlVAlign.xlVAlignBottom;
else if (sAlignVertical.EqualsCI("distributed")) style.AlignVertical = XlVAlign.xlVAlignDistributed;
else if (sAlignVertical.EqualsCI("justify")) style.AlignVertical = XlVAlign.xlVAlignJustify;
// Number format.
if (style.ApplyNumberFormat)
{
if (style.NumFmtId >= 164)
{
SaMsXmlElement numFmtsElement = styleSheetElement.GetFirstChildElement("NumFmts");
foreach (SaMsXmlElement numFmtElement in numFmtsElement.GetChildElements("numFmt"))
{
if (numFmtElement.GetAttributeValue("numFmtId").ToLong() == style.NumFmtId)
{
style.NumFmtCode = numFmtElement.GetAttributeValue("formatCode");
break;
}
}
}
else style.NumFmtCode = GetBuiltInStyleFormat(style.NumFmtId);
}
// Font.
if (style.ApplyFont)
{
}
// Fill.
if (style.ApplyFill)
{
}
// Borders.
if (style.ApplyBorder)
{
}
// Alignment.
if (style.ApplyAlignment)
{
}
// Protection.
if (style.ApplyProtection)
{
}
break;
}
}
}
catch (Exception exc) { HandleException("GetStyleNode", exc); }
return style;
}
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, SaMsExcelItemAttr attr)
{
return SetErrorState("Not supported");
}
//-------------------------------------------------------------------
// Add image to sheet.
public override bool InsertImage (SaMsExcelImage_Config imageConfig)
{
return SetErrorState("Not supported");
}
//-------------------------------------------------------------------
public override bool FreezePanes (uint colPos, uint rowPos)
{
return SetErrorState("Not supported");
}
//-------------------------------------------------------------------
public override bool AutoFit (SaMsExcelRange range)
{
return SetErrorState("Not supported");
}
//-------------------------------------------------------------------
public override bool SelectRange (SaMsExcelRange range)
{
return SetErrorState("Not supported");
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,656 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
namespace Sarand.Net.Standard.Data.Excel
{
//=======================================================================
public class SaMsSpreadsheet_OpenXml : SaMsSpreadsheet
{
//-------------------------------------------------------------------
// Data members.
private class WorkbookData
{
public SpreadsheetDocument Document { get; set; }
public MemoryStream MemoryStream { get; set; }
public WorkbookPart WorkbookPart { get { return Document.WorkbookPart; } }
}
private WorkbookData workbook;
private class WorksheetData
{
public WorksheetData(uint worksheetPos, WorksheetPart worksheetPart, Sheet sheet)
{
WorksheetPos = worksheetPos;
WorksheetPart = worksheetPart;
Sheet = sheet;
}
public uint WorksheetPos { get; }
public WorksheetPart WorksheetPart { get; }
public Sheet Sheet { get; }
public SheetData SheetData { get { return WorksheetPart.Worksheet.GetFirstChild<SheetData>(); } }
// Active column.
public uint ActiveColumnPos { get; private set; }
public Column ActiveColumn { get; private set; }
public void SetActiveColumn(uint activeColumnPos, Column activeColumn)
{
ActiveColumnPos = activeColumnPos;
ActiveColumn = activeColumn;
}
public void ClearActiveColumn()
{
ActiveColumnPos = 0;
ActiveColumn = null;
}
// Active row.
public uint ActiveRowPos { get; private set; }
public Row ActiveRow { get; private set; }
public void SetActiveRow(uint activeRowPos, Row activeRow)
{
ActiveRowPos = activeRowPos;
ActiveRow = activeRow;
}
public void ClearActiveRow()
{
ActiveRowPos = 0;
ActiveRow = null;
}
}
private WorksheetData worksheet;
private uint activeWorksheetPos;
//-------------------------------------------------------------------
// Construction.
public SaMsSpreadsheet_OpenXml() : base()
{
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
CloseWorkbook();
}
base.Dispose(disposing);
}
//-------------------------------------------------------------------
// Properties.
private WorkbookPart WorkbookPart { get { return workbook.WorkbookPart; } }
private Sheets Sheets { get { return WorkbookPart.Workbook.Sheets; } }
//-------------------------------------------------------------------
// W o r k b o o k
//-------------------------------------------------------------------
public override bool IsWorkbookValid()
{
return (workbook != null);
}
public override bool CreateWorkbook()
{
ClearErrorState();
CloseWorkbook();
try
{
workbook = new WorkbookData();
workbook.MemoryStream = new MemoryStream();
workbook.Document = SpreadsheetDocument.Create(workbook.MemoryStream, SpreadsheetDocumentType.Workbook);
}
catch (Exception exc) { SaLogger.Warn(exc.GetType().Name + ".CreateWorkbook " + ExceptionUtil.GetErrorStateMessage(exc)); }
return (workbook != null);
}
public override bool OpenWorkbook(String filePath)
{
ClearErrorState();
CloseWorkbook();
try
{
workbook = new WorkbookData();
workbook.Document = SpreadsheetDocument.Create(filePath, SpreadsheetDocumentType.Workbook);
}
catch (Exception exc) { SaLogger.Warn(exc.GetType().Name + ".OpenWorkbook " + ExceptionUtil.GetErrorStateMessage(exc)); }
return (workbook != null);
}
public override bool SaveDocument(String filePath, int fileFormat, bool bAutomaticallyOverwrite)
{
ClearErrorState();
#pragma warning disable CS0219 // Variable is assigned but its value is never used
SpreadsheetDocumentType documentType = SpreadsheetDocumentType.Workbook;
#pragma warning restore CS0219 // Variable is assigned but its value is never used
if (fileFormat == (int)XlFileFormat.xlOpenXMLTemplate || fileFormat == (int)XlFileFormat.xlTemplate || fileFormat == (int)XlFileFormat.xlTemplate8)
documentType = SpreadsheetDocumentType.Template;
else if (fileFormat == (int)XlFileFormat.xlOpenXMLWorkbookMacroEnabled)
documentType = SpreadsheetDocumentType.MacroEnabledWorkbook;
else if (fileFormat == (int)XlFileFormat.xlOpenXMLTemplateMacroEnabled)
documentType = SpreadsheetDocumentType.MacroEnabledTemplate;
else if (fileFormat == (int)XlFileFormat.xlOpenXMLAddIn || fileFormat == (int)XlFileFormat.xlAddIn || fileFormat == (int)XlFileFormat.xlAddIn8 || fileFormat == (int)XlFileFormat.xlIntlAddIn)
documentType = SpreadsheetDocumentType.AddIn;
// ToDo Save OpenXML Excel document.
return !HasErrorState();
}
public override bool CloseWorkbook()
{
ClearErrorState();
CloseWorksheet();
try
{
if (workbook != null)
{
if (workbook.Document != null) workbook.Document.Dispose();
if (workbook.MemoryStream != null) workbook.MemoryStream.Dispose();
workbook = null;
}
}
catch (Exception exc) { SaLogger.Warn(exc.GetType().Name + ".CloseWorkbook " + ExceptionUtil.GetErrorStateMessage(exc)); }
workbook = null;
return !HasErrorState();
}
//-------------------------------------------------------------------
// W o r k s h e e t
//-------------------------------------------------------------------
public override bool IsWorksheetValid()
{
return (worksheet != null);
}
public override uint WorksheetCount
{
get
{
uint worksheetCount = 0;
foreach (Sheet sheet in Sheets)
worksheetCount++;
return worksheetCount;
}
}
public override bool SetWorksheetCount(int worksheetCount)
{
ClearErrorState();
if (worksheetCount > 0 && worksheetCount < 11)
{
while (WorksheetCount < worksheetCount)
AddWorksheet("");
while (WorksheetCount > worksheetCount)
RemoveWorksheet(WorksheetCount);
OpenWorksheet(1);
}
else SetErrorState("SetWorksheetCount - Requested number of worksheets (" + worksheetCount.ToString() + ") must be between 1 and 10");
return !HasErrorState();
}
public override bool AddWorksheet(String sheetName)
{
ClearErrorState();
CloseWorksheet();
// Add a blank WorksheetPart.
WorksheetPart worksheetPart = WorkbookPart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet(new SheetData());
// Get a unique ID for the new worksheet.
Sheets sheets = WorkbookPart.Workbook.GetFirstChild<Sheets>();
uint sheetId = 1;
if (sheets.Elements<Sheet>().Count() > 0)
{
sheetId = sheets.Elements<Sheet>().Select(item => item.SheetId.Value).Max() + 1;
}
// Append the new worksheet and associate it with the workbook.
String relationshipId = WorkbookPart.GetIdOfPart(worksheetPart);
sheetName = StringUtil.OnEmpty(StringUtil.TrimAll(sheetName), "Sheet" + sheetId);
Sheet sheet = new Sheet() { Id = relationshipId, SheetId = sheetId, Name = sheetName };
sheets.Append(sheet);
worksheet = new WorksheetData(WorksheetCount, worksheetPart, sheet);
return (worksheet != null);
}
public override bool RemoveWorksheet(uint worksheetPos)
{
ClearErrorState();
// Extract Sheet by position.
int sheetCount = 0;
Sheet sheet = null;
foreach (Sheet sheetCandidate in Sheets)
{
if (++sheetCount == worksheetPos)
{
sheet = sheetCandidate;
break;
}
}
if (sheet != null)
{
// Extract the corresponding Worksheet Part.
WorksheetPart worksheetPart = (WorksheetPart)(WorkbookPart.GetPartById(sheet.Id));
// Check if the worksheet being removed is currently open.
if (worksheet != null && sheet.Id == worksheet.Sheet.Id)
CloseWorksheet();
// Remove the sheet from the workbook.
sheet.Remove();
WorkbookPart.DeletePart(worksheetPart);
return true;
}
return false;
}
public override bool OpenWorksheet(uint worksheetPos)
{
String fn = GetType().Name + ".OpenWorksheet";
ClearErrorState();
CloseWorksheet();
// Extract Sheet by position.
int sheetCount = 0;
Sheet sheet = null;
foreach (Sheet sheetCandidate in Sheets)
{
if (++sheetCount == worksheetPos)
{
sheet = sheetCandidate;
break;
}
}
if (sheet != null)
{
WorksheetPart worksheetPart = (WorksheetPart)(WorkbookPart.GetPartById(sheet.Id));
if (worksheetPart != null && sheet != null)
worksheet = new WorksheetData(worksheetPos, worksheetPart, sheet);
}
if (worksheet != null)
{
SaLogger.Warn(fn + " Failed to open worksheet " + worksheetPos);
SetErrorState("Failed to open worksheet " + worksheetPos);
}
return (worksheet != null);
}
public override uint WorksheetPos { get { return activeWorksheetPos; } }
public override String WorksheetName
{
get { return worksheet.Sheet.Name; }
set { worksheet.Sheet.Name = StringUtil.Left(value, 31); }
}
public override bool SetWorksheetAttr(SaMsExcelItemAttr attr)
{
ClearErrorState();
try
{
// ToDo OpenXml SetWorksheetAttr
}
catch (Exception exc) { HandleException("SetWorksheetAttr", exc); }
return !HasErrorState();
}
public override bool CloseWorksheet()
{
ClearErrorState();
try
{
if (worksheet != null)
{
// No worksheet components need to be disposed - they belong to the workbook.
}
worksheet = null;
}
catch (Exception exc) { HandleException("CloseWorksheet", exc); }
worksheet = null;
activeWorksheetPos = 0;
return !HasErrorState();
}
//-------------------------------------------------------------------
// Worksheet Page Setup.
public override bool SetPageSetup(SaMsExcelPageSetup_Config pageSetupConfig)
{
//---------------------------------------------------------------
// 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.
ClearErrorState();
if (worksheet == null) return false;
try
{
// Page margins - must be before the Page Setup in the worksheet.
PageMargins pageMargins = worksheet.WorksheetPart.Worksheet.GetFirstChild<PageMargins>();
if (pageMargins == null)
{
pageMargins = new PageMargins();
worksheet.WorksheetPart.Worksheet.AppendChild(pageMargins);
}
// Page Setup.
PageSetupProperties pageSetupProperties = worksheet.WorksheetPart.Worksheet.SheetProperties.PageSetupProperties;
PageSetup pageSetup = worksheet.WorksheetPart.Worksheet.GetFirstChild<PageSetup>();
if (pageSetup == null)
{
pageSetup = new PageSetup();
worksheet.WorksheetPart.Worksheet.AppendChild(pageSetup);
}
if (pageSetupConfig.Orientation == SaXlPageOrientation.xlLandscape)
pageSetup.Orientation = OrientationValues.Landscape;
else if (pageSetupConfig.Orientation == SaXlPageOrientation.xlPortrait)
pageSetup.Orientation = OrientationValues.Portrait;
// ToDo OpenXML Headers and footers.
//pageSetup.LeftHeader = pageSetupConfig.HeaderLeft;
//pageSetup.CenterHeader = pageSetupConfig.HeaderCenter;
//pageSetup.RightHeader = pageSetupConfig.HeaderRight;
//pageSetup.LeftFooter = pageSetupConfig.FooterLeft;
//pageSetup.CenterFooter = pageSetupConfig.FooterCenter;
//pageSetup.RightFooter = pageSetupConfig.FooterRight;
// Margins.
if (pageSetupConfig.MarginLeft > 0) pageMargins.Left = ToPoints(pageSetupConfig.MarginLeft, pageSetupConfig.Unit, false);
if (pageSetupConfig.MarginRight > 0) pageMargins.Right = ToPoints(pageSetupConfig.MarginRight, pageSetupConfig.Unit, false);
if (pageSetupConfig.MarginTop > 0) pageMargins.Top = ToPoints(pageSetupConfig.MarginTop, pageSetupConfig.Unit, true);
if (pageSetupConfig.MarginBottom > 0) pageMargins.Bottom = ToPoints(pageSetupConfig.MarginBottom, pageSetupConfig.Unit, true);
if (pageSetupConfig.MarginHeader > 0) pageMargins.Header = ToPoints(pageSetupConfig.MarginHeader, pageSetupConfig.Unit, true);
if (pageSetupConfig.MarginFooter > 0) pageMargins.Footer = ToPoints(pageSetupConfig.MarginFooter, pageSetupConfig.Unit, true);
/*
* ToDo OpenXML PrintTitleRows/Columns
// Print Title Rows.
if (pageSetupConfig.PrintTitleRowFrom > 0 && pageSetupConfig.PrintTitleRowTo > 0)
// Prefix with '$' to fix row value.(?)
pageSetup.PrintTitleRows = "$" + GetRowSuffix((uint)pageSetupConfig.PrintTitleRowFrom) + ":$" + GetRowSuffix((uint)pageSetupConfig.PrintTitleRowTo);
else if (pageSetupConfig.PrintTitleRowFrom == 0 && pageSetupConfig.PrintTitleRowTo == 0)
pageSetup.PrintTitleRows = "";
// Print Title Columns.
if (pageSetupConfig.PrintTitleColFrom > 0 && pageSetupConfig.PrintTitleColTo > 0)
pageSetup.PrintTitleColumns = "$" + GetColumnPrefix((uint)pageSetupConfig.PrintTitleColFrom) + ":$" + GetColumnPrefix((uint)pageSetupConfig.PrintTitleColTo);
else if (pageSetupConfig.PrintTitleColFrom == 0 && pageSetupConfig.PrintTitleColTo == 0)
pageSetup.PrintTitleColumns = "";
*/
/*
// ToDo OpenXML Zoom and 'Fit to' options.
if (pageSetupConfig.Zoom > 0)
pageSetup.Zoom = pageSetupConfig.Zoom;
else if (pageSetupConfig.FitToPagesTall > 0 || pageSetupConfig.FitToPagesWide > 0)
{
pageSetup.FitToPagesWide = Math.Min(0, pageSetupConfig.FitToPagesWide);
pageSetup.FitToPagesTall = Math.Min(0, pageSetupConfig.FitToPagesTall);
pageSetup.Zoom = 0;
}
*/
}
catch (Exception exc) { HandleException("SetPageSetup", exc); }
return !HasErrorState();
}
public override bool SetPageBreak(uint colPos, uint rowPos)
{
ClearErrorState();
if (worksheet == null) return false;
try
{
/*
* ToDo OpenXML Set page break
String cellId = GetCellId(colPos, rowPos);
Range range = worksheet.get_Range(cellId);
worksheet.HPageBreaks.Add(range);
worksheet.VPageBreaks.Add(range);
*/
}
catch (Exception exc) { HandleException("SetPageSetup", exc); }
return !HasErrorState();
}
//-------------------------------------------------------------------
public bool SelectRange()
{
// ToDo OpenXML Is SelectRange even relevant?
return false;
}
//-------------------------------------------------------------------
// C o l u m n s
//-------------------------------------------------------------------
private Column GetColumnByPos (uint columnPos)
{
if (worksheet.ActiveColumnPos != columnPos)
{
// ToDo OpenXML GetColumnByPos.
//Column column = worksheet.WorksheetPart.col
}
return worksheet.ActiveColumn;
}
public override uint GetActiveColPos()
{
if (worksheet == null) return 0;
try
{
return worksheet.ActiveColumnPos;
}
catch (Exception exc) { HandleException("GetActiveCol", exc); }
return 0;
}
public override double GetColWidth(uint colPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
{
double columnWidth = 0.0;
try
{
// ToDo OpenXML GetColWidth.
}
catch (Exception exc) { HandleException("GetColWidth", exc); }
return columnWidth;
}
public override bool SetColWidth(uint colPos, double columnWidth, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
{
ClearErrorState();
try
{
// ToDo OpenXML SetColWidth.
}
catch (Exception exc) { HandleException("SetColWidth", exc); }
return !HasErrorState();
}
//-------------------------------------------------------------------
// R o w s
//-------------------------------------------------------------------
public override uint GetActiveRowPos()
{
try
{
// ToDo OpenXML GetActiveRowPos.
}
catch (Exception exc) { HandleException("GetActiveRowPos", exc); }
return 0;
}
public override List<DataValue> GetRowDataValues(uint rowPos, int maxColumns = 0)
{
List<DataValue> values = new List<DataValue>();
return values;
}
public override double GetRowHeight(uint rowPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
{
double rowHeight = 0.0;
try
{
// ToDo OpenXML GetRowHeight.
}
catch (Exception exc) { HandleException("GetRowHeight", exc); }
return rowHeight;
}
public override bool SetRowHeight(uint rowPos, double rowHeight, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
{
ClearErrorState();
try
{
// ToDo OpenXML SetRowHeight.
}
catch (Exception exc) { HandleException("SetRowHeight", exc); }
return !HasErrorState();
}
//-------------------------------------------------------------------
// C e l l s
//-------------------------------------------------------------------
public override void SetActiveCell(uint colPos, uint rowPos)
{
// ToDo OpenXML SetActiveCell.
}
public override String GetCellFormula(uint colPos, uint rowPos)
{
// ToDo OpenXML GetCellFormula.
return "";
}
public override DataValue GetCellDataValue(uint colPos, uint rowPos)
{
// ToDo OpenXML GetCellDataValue.
return new DataValue();
}
public override bool SetCellFormula(uint colPos, uint rowPos, String value)
{
// ToDo OpenXML SetCellFormula.
return true;
}
public override bool SetCellFormula(uint colPos, uint rowPos, String value, SaMsExcelItemAttr attr)
{
// ToDo OpenXML SetCellFormula.
return true;
}
public override bool SetRowFormulas(uint colPosStart, uint rowPos, List<Object> values)
{
// ToDo OpenXML SetRowFormulas.
return true;
}
public override bool SetRangeFormulas(SaMsExcelRange range, List<Object> values)
{
// ToDo OpenXML SetRangeFormulas.
return true;
}
//-------------------------------------------------------------------
// Cell attributes.
public override bool SetRangeAttr(SaMsExcelRange range, SaMsExcelItemAttr attr)
{
ClearErrorState();
try
{
// ToDo OpenXML SetRangeAttr.
}
catch (Exception exc) { HandleException("SetRangeAttr", exc); }
return !HasErrorState();
}
private bool SetRangeAttr(Range oRange, SaMsExcelItemAttr attr)
{
ClearErrorState();
try
{
// ToDo OpenXML SetRangeAttr.
}
catch (Exception exc) { HandleException("SetRangeAttr", exc); }
return !HasErrorState();
}
//-------------------------------------------------------------------
// I m a g e s
//-------------------------------------------------------------------
// Add image to sheet.
public override bool InsertImage(SaMsExcelImage_Config imageConfig)
{
ClearErrorState();
if (worksheet == null) return false;
try
{
// ToDo OpenXML InsertImage.
}
catch (Exception exc) { HandleException("InsertImage", exc); }
return !HasErrorState();
}
//-------------------------------------------------------------------
public override bool FreezePanes(uint colPos, uint rowPos)
{
ClearErrorState();
try
{
// ToDo OpenXML FreezePanes.
}
catch (Exception exc) { HandleException("FreezePanes", exc); }
return !HasErrorState();
}
//-------------------------------------------------------------------
public override bool AutoFit(SaMsExcelRange range)
{
ClearErrorState();
try
{
// ToDo OpenXML AutoFit.
}
catch (Exception exc) { HandleException("AutoFit", exc); }
return !HasErrorState();
}
//-------------------------------------------------------------------
public override bool SelectRange(SaMsExcelRange range)
{
ClearErrorState();
try
{
// ToDo OpenXML SelectRange.
}
catch (Exception exc) { HandleException("SelectRange", exc); }
return !HasErrorState();
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,121 @@
using System;
using System.IO;
using System.Text;
using System.Xml;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Utils;
namespace Sarand.Net.Standard.Data.Xml
{
//=======================================================================
public class SaMsXmlDocument : SaErrorStateItem
{
//-------------------------------------------------------------------
// Data members.
private XmlDocument document = new XmlDocument();
//-------------------------------------------------------------------
// Construction.
public SaMsXmlDocument ()
{
}
protected override void Dispose (bool disposing)
{
if (disposing)
{
document = null;
}
}
//-------------------------------------------------------------------
// Properties.
public bool Valid { get { return (document != null); } }
//-------------------------------------------------------------------
// O p e n
//-------------------------------------------------------------------
public bool CreateNew (String rootElementName = "")
{
ClearErrorState();
document = new XmlDocument();
if (!StringUtil.IsEmpty(rootElementName))
document.AppendElement(rootElementName);
return !HasErrorState();
}
public bool LoadXml (String xml)
{
ClearErrorState();
document = new XmlDocument();
try
{
document.LoadXml(xml);
}
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
return !HasErrorState();
}
public bool LoadXml (Stream xml)
{
ClearErrorState();
document = new XmlDocument();
try
{
xml.Seek(0, SeekOrigin.Begin);
document.Load(xml);
}
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
return !HasErrorState();
}
//-------------------------------------------------------------------
// C o n v e r s i o n
//-------------------------------------------------------------------
public static Encoding DefaultEncoding { get; } = Encoding.UTF8;
public String GetXml (Encoding encoding = null)
{
return document.GetXml(encoding != null ? encoding : DefaultEncoding);
}
public String FormatXml (Encoding encoding = null)
{
return document.FormatXml(encoding != null ? encoding : DefaultEncoding);
}
//-------------------------------------------------------------------
// E l e m e n t s
//-------------------------------------------------------------------
public SaMsXmlElement GetRootElement ()
{
if (document != null) return new SaMsXmlElement(document.DocumentElement);
return null;
}
public SaMsXmlElement SetRootElement (String name)
{
// Clear existing root element.
if (document.DocumentElement != null)
document.DocumentElement.ParentNode.RemoveAll();
// Add the new root element.
return new SaMsXmlElement(document.AppendElement(name));
}
public SaMsXmlElement SetRootElement (SaXmlNamespace xmlNamespace, String name)
{
// Clear existing root element.
if (document.DocumentElement != null)
document.DocumentElement.ParentNode.RemoveAll();
// Add the new root element.
return new SaMsXmlElement(document.AppendElement(xmlNamespace, name));
}
public SaMsXmlElement SetRootElement (SaMsXmlElement rootNode)
{
// Clear existing root element.
if (document.DocumentElement != null)
document.DocumentElement.ParentNode.RemoveAll();
// Import the node into the document before appending.
XmlNode importNode = document.ImportNode(rootNode.Element, true);
document.AppendChild(importNode);
return rootNode;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
+178
View File
@@ -0,0 +1,178 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Utils;
namespace Sarand.Net.Standard.Data.Xml
{
//=======================================================================
public class SaMsXmlElement : SaMsXmlNode
{
//-------------------------------------------------------------------
// Data members.
//-------------------------------------------------------------------
// Construction.
internal SaMsXmlElement (XmlElement element) :
base(element)
{
}
protected override void Dispose (bool disposing)
{
if (disposing)
{
}
base.Dispose(disposing);
}
//-------------------------------------------------------------------
// Properties.
internal XmlElement Element { get { return (node as XmlElement); } }
public override bool Valid { get { return (Element != null); } }
//-------------------------------------------------------------------
// A t t r i b u t e s
//-------------------------------------------------------------------
public Dictionary<String, String> GetAttributes ()
{
Dictionary<String, String> attributes = new Dictionary<string, string>();
foreach (XmlAttribute attribute in Element.Attributes)
attributes[attribute.Name] = attribute.Value;
return attributes;
}
public bool HasAttribute (String name, bool caseInsensitive = false)
{
foreach (XmlAttribute attribute in Element.Attributes)
{
if ((!caseInsensitive && attribute.Name.Equals(name)) || (caseInsensitive && attribute.Name.EqualsCI(name)))
return true;
}
return false;
}
public String GetAttribute (String name, bool caseInsensitive = false)
{
foreach (XmlAttribute attribute in Element.Attributes)
{
if ((!caseInsensitive && attribute.Name.Equals(name)) || (caseInsensitive && attribute.Name.EqualsCI(name)))
return attribute.Value;
}
return "";
}
public void SetAttribute (String name, String value)
{
Element.SetAttribute(name, value);
}
public bool RemoveAttribute (String name, bool caseInsensitive = false)
{
if (!HasAttribute(name, caseInsensitive)) return false;
for (int attributeIdx =0; attributeIdx < Element.Attributes.Count; attributeIdx++)
{
XmlAttribute attribute = Element.Attributes[attributeIdx];
if ((!caseInsensitive && attribute.Name.Equals(name)) || (caseInsensitive && attribute.Name.EqualsCI(name)))
{
Element.Attributes.RemoveAt(attributeIdx);
attributeIdx--;
}
}
return true;
}
//-------------------------------------------------------------------
// C h i l d E l e m e n t s
//-------------------------------------------------------------------
public List<SaMsXmlElement> GetChildElements (String name = "")
{
List<SaMsXmlElement> childElements = new List<SaMsXmlElement>();
XmlElement element = Element;
if (element == null) return childElements;
foreach (XmlNode childNode in element.ChildNodes)
{
if (StringUtil.IsEmpty(name) || childNode.Name.EqualsCI(name))
childElements.Add(new SaMsXmlElement(childNode as XmlElement));
}
return childElements;
}
public bool HasChildElement (String name)
{
XmlElement element = Element;
if (element == null) return false;
foreach (XmlNode childNode in element.ChildNodes)
{
if (childNode.NodeType == XmlNodeType.Element && StringUtil.IsEmpty(name) || childNode.Name.EqualsCI(name))
return true;
}
return false;
}
public SaMsXmlElement GetFirstChildElement (String name = "")
{
XmlElement element = Element;
if (element == null) return null;
foreach (XmlNode childNode in element.ChildNodes)
{
if (childNode.NodeType == XmlNodeType.Element && StringUtil.IsEmpty(name) || childNode.Name.EqualsCI(name))
return new SaMsXmlElement(childNode as XmlElement);
}
return new SaMsXmlElement(null);
}
//-------------------------------------------------------------------
// A p p e n d E l e m e n t s
//-------------------------------------------------------------------
/// <summary>Append element to node by name.</summary>
public SaMsXmlElement AppendElement (String name, String text = "")
{
XmlDocument doc = Element.OwnerDocument;
XmlElement child = (XmlElement)Element.AppendChild(doc.CreateElement(name));
if (!StringUtil.IsEmpty(text))
child.AppendChild(doc.CreateTextNode(text));
return new SaMsXmlElement(child);
}
public SaMsXmlElement AppendElement (SaXmlNamespace xmlNamespace, String name, String text = "")
{
XmlDocument doc = Element.OwnerDocument;
XmlElement child = (XmlElement)Element.AppendChild(doc.CreateElement(xmlNamespace.Prefix, name, xmlNamespace.Uri));
if (!StringUtil.IsEmpty(text))
child.AppendChild(doc.CreateTextNode(text));
return new SaMsXmlElement(child);
}
//-------------------------------------------------------------------
/// <summary>Append element to node by name if value supplied.</summary>
public SaMsXmlElement AppendNonBlankElement (String name, String text)
{
if (StringUtil.IsEmpty(text)) return null;
XmlDocument doc = Element.OwnerDocument;
XmlElement child = (XmlElement)Element.AppendChild(doc.CreateElement(name));
if (!StringUtil.IsEmpty(text))
child.AppendChild(doc.CreateTextNode(text));
return new SaMsXmlElement(child);
}
public SaMsXmlElement AppendNonBlankElement (SaXmlNamespace xmlNamespace, String name, String text)
{
if (StringUtil.IsEmpty(text)) return null;
XmlDocument doc = Element.OwnerDocument;
XmlElement child = (XmlElement)Element.AppendChild(doc.CreateElement(xmlNamespace.Prefix, name, xmlNamespace.Uri));
if (!StringUtil.IsEmpty(text))
child.AppendChild(doc.CreateTextNode(text));
return new SaMsXmlElement(child);
}
//-------------------------------------------------------------------
/// <summary>Append element to node.</summary>
public SaMsXmlElement AppendElement (SaMsXmlElement element)
{
// Import the node into the document before appending.
XmlDocument doc = Element.OwnerDocument;
XmlNode appendNode = doc.ImportNode(element.Element, true);
XmlElement child = (XmlElement)Element.AppendChild(appendNode);
return new SaMsXmlElement(child);
}
//-------------------------------------------------------------------
}
//=======================================================================
}
+122
View File
@@ -0,0 +1,122 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Utils;
namespace Sarand.Net.Standard.Data.Xml
{
//=======================================================================
public class SaMsXmlNode : SaErrorStateItem
{
//-------------------------------------------------------------------
// Data members.
internal XmlNode node;
//-------------------------------------------------------------------
// Construction.
internal SaMsXmlNode (XmlNode node)
{
this.node = node;
}
protected override void Dispose (bool disposing)
{
if (disposing)
{
node = null;
}
base.Dispose(disposing);
}
//-------------------------------------------------------------------
// Properties.
internal XmlDocument OwnerDocument { get { return node != null ? node.OwnerDocument : null; } }
public String NamespaceURI { get { return node != null ? node.NamespaceURI : ""; } }
public String Prefix { get { return node != null ? node.Prefix : ""; } }
//public String Name { get { return node != null ? node.Name : ""; } }
public String LocalName { get { return node != null ? node.LocalName : ""; } }
public virtual bool Valid { get { return (node != null); } }
//-------------------------------------------------------------------
// A t t r i b u t e s
//-------------------------------------------------------------------
public String GetAttributeValue (String attributeName)
{
if (StringUtil.IsEmpty(attributeName) || node == null) return "";
foreach (XmlAttribute attribute in node.Attributes)
{
if (attribute.Name.EqualsCI(attributeName))
return attribute.Value;
}
return "";
}
//-------------------------------------------------------------------
// T e x t
//-------------------------------------------------------------------
public String GetText ()
{
if (node == null) return "";
foreach (XmlNode childNode in node.ChildNodes)
{
if (childNode.NodeType == XmlNodeType.Text || childNode.NodeType == XmlNodeType.CDATA)
return childNode.Value;
}
return "";
}
//-------------------------------------------------------------------
// C h i l d N o d e s
//-------------------------------------------------------------------
public List<SaMsXmlNode> GetChildNodes (String name = "")
{
List<SaMsXmlNode> childNodes = new List<SaMsXmlNode>();
if (node == null) return childNodes;
foreach (XmlNode childNode in node.ChildNodes)
{
if (StringUtil.IsEmpty(name) || childNode.Name.EqualsCI(name))
childNodes.Add(new SaMsXmlNode(childNode));
}
return childNodes;
}
public bool HasChildNode (String name)
{
if (node == null) return false;
foreach (XmlNode childNode in node.ChildNodes)
{
if (StringUtil.IsEmpty(name) || childNode.Name.EqualsCI(name))
return true;
}
return false;
}
public SaMsXmlNode GetFirstChildNode (String name = "")
{
if (node == null) return new SaMsXmlNode(null);
foreach (XmlNode childNode in node.ChildNodes)
{
if (StringUtil.IsEmpty(name) || childNode.Name.EqualsCI(name))
return new SaMsXmlNode(childNode);
}
return new SaMsXmlNode(null);
}
public String GetChildText (String name, String defaultValue = "")
{
SaMsXmlNode childNode = GetFirstChildNode(name);
if (childNode != null)
return childNode.GetText();
return defaultValue;
}
//-------------------------------------------------------------------
}
//=======================================================================
public static class SaMsXmlNodeList
{
}
//=======================================================================
}
+125
View File
@@ -0,0 +1,125 @@
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace Sarand.Net.Standard.Data.Xml
{
//=======================================================================
public class SaXmlNamespace
{
public SaXmlNamespace (String prefix, String uri)
{
Prefix = prefix;
Uri = uri;
}
public String Prefix { get; }
public String Uri { get; }
}
//=======================================================================
public static class SaMsXmlUtil
{
//-------------------------------------------------------------------
// Data members.
public static Encoding DefaultEncoding { get; } = Encoding.UTF8;
//-------------------------------------------------------------------
/// <summary>Retrieve the Xml Declaration from the XML document.</summary>
public static XmlDeclaration GetXmlDeclaration (this XmlDocument xmlDoc)
{
return xmlDoc.ChildNodes.OfType<XmlDeclaration>().FirstOrDefault();
}
//-------------------------------------------------------------------
// Convert XML document to string.
public static String GetXml (this XmlDocument xmlDoc, Encoding encoding = null)
{
// Ensure correct encoding for generated XML data.
if (encoding == null) encoding = DefaultEncoding;
XmlWriterSettings settings = new XmlWriterSettings() { Encoding = encoding };
using (var stringWriter = new StringWriter())
using (var xmlTextWriter = XmlWriter.Create(stringWriter, settings))
{
// Ensure that the document has the requested encoding in its XML declaration.
XmlDeclaration xmlDeclaration = xmlDoc.GetXmlDeclaration();
if (xmlDeclaration == null)
{
xmlDeclaration = xmlDoc.CreateXmlDeclaration("1.0", encoding.WebName, null);
xmlDoc.InsertBefore(xmlDeclaration, xmlDoc.DocumentElement);
}
else xmlDeclaration.Encoding = encoding.WebName;
// Write the document to String.
xmlDoc.WriteTo(xmlTextWriter);
xmlTextWriter.Flush();
return stringWriter.GetStringBuilder().ToString();
}
}
public static String FormatXml (this XmlDocument xmlDoc, Encoding encoding = null)
{
// Ensure correct encoding for generated XML data.
if (encoding == null) encoding = DefaultEncoding;
XmlWriterSettings settings = new XmlWriterSettings() { Encoding = encoding, Indent = true };
using (MemoryStream memoryStream = new MemoryStream())
using (var xmlTextWriter = new XmlTextWriter(memoryStream, encoding))
{
// XML output format.
xmlTextWriter.Formatting = Formatting.Indented;
// Ensure that the document has the requested encoding in its XML declaration.
XmlDeclaration xmlDeclaration = xmlDoc.GetXmlDeclaration();
if (xmlDeclaration == null)
{
xmlDeclaration = xmlDoc.CreateXmlDeclaration("1.0", encoding.WebName, null);
xmlDoc.InsertBefore(xmlDeclaration, xmlDoc.DocumentElement);
}
else xmlDeclaration.Encoding = encoding.WebName;
// Write the document to String.
xmlDoc.WriteTo(xmlTextWriter);
xmlTextWriter.Flush();
memoryStream.Flush();
memoryStream.Position = 0;
using (StreamReader streamReader = new StreamReader(memoryStream))
{
return streamReader.ReadToEnd();
}
}
}
//-------------------------------------------------------------------
// Append element to node.
public static XmlElement AppendElement (this XmlNode node, String name, String text = "")
{
XmlDocument doc = (node is XmlDocument ? node as XmlDocument : node.OwnerDocument);
XmlElement child = (XmlElement)node.AppendChild(doc.CreateElement(name));
if (!StringUtil.IsEmpty(text))
child.AppendChild(doc.CreateTextNode(text));
return child;
}
public static XmlElement AppendElement (this XmlNode node, SaXmlNamespace xmlNamespace, String name, String text = "")
{
XmlDocument doc = (node is XmlDocument ? node as XmlDocument : node.OwnerDocument);
XmlElement child = (XmlElement)node.AppendChild(doc.CreateElement(xmlNamespace.Prefix, name, xmlNamespace.Uri));
if (!StringUtil.IsEmpty(text))
child.AppendChild(doc.CreateTextNode(text));
return child;
}
//-------------------------------------------------------------------
// Get child text.
public static String GetChildText (this XmlNode node, String name)
{
foreach (XmlNode child in node.ChildNodes)
if (child.Name.EqualsCI(name))
return child.InnerText;
return String.Empty;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
+123
View File
@@ -0,0 +1,123 @@
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
namespace Sarand.Net.Standard.Data.Zip
{
//=======================================================================
public class SaMsZipArchive : SaErrorStateItem
{
//-------------------------------------------------------------------
// Data members.
private ZipArchive zipArchive;
//-------------------------------------------------------------------
// Construction.
public SaMsZipArchive ()
{
}
protected override void Dispose (bool disposing)
{
if (disposing)
{
if (zipArchive != null) zipArchive.Dispose();
}
}
//-------------------------------------------------------------------
// Properties.
//-------------------------------------------------------------------
// A r c h i v e F i l e
//-------------------------------------------------------------------
public bool OpenArchive (String filePath, ZipArchiveMode mode = ZipArchiveMode.Read)
{
ClearErrorState();
if (StringUtil.IsEmpty(filePath)) return SetErrorState("Filename must be supplied");
CloseArchive();
try
{
zipArchive = ZipFile.OpenRead(filePath);//, mode);
ReadOnlyCollection<ZipArchiveEntry> entries = zipArchive.Entries;
int entryCount = entries.Count;
}
catch (Exception exc)
{
SaLogger.Warn(GetType().Name + ".OpenArchive " + ExceptionUtil.GetLogMessage(exc));
return SetErrorState(ExceptionUtil.GetErrorStateMessage(exc));
}
return !HasErrorState();
}
/// <summary>Open ZIP archive from data stream.</summary>
public bool OpenArchive (Stream stream, ZipArchiveMode mode = ZipArchiveMode.Read, bool leaveOpen = true, Encoding entryNameEncoding = null)
{
ClearErrorState();
if (entryNameEncoding == null) entryNameEncoding = Encoding.Default;
CloseArchive();
try
{
zipArchive = new ZipArchive(stream, mode, leaveOpen, entryNameEncoding);
ReadOnlyCollection<ZipArchiveEntry> entries = zipArchive.Entries;
int entryCount = entries.Count;
}
catch (Exception exc)
{
SaLogger.Warn(GetType().Name + ".OpenArchive " + ExceptionUtil.GetLogMessage(exc));
return SetErrorState(ExceptionUtil.GetErrorStateMessage(exc));
}
return !HasErrorState();
}
public bool IsArchiveOpen ()
{
return (zipArchive != null);
}
/// <summary>Close eth ZIP archive.</summary>
public bool CloseArchive ()
{
ClearErrorState();
try
{
if (zipArchive != null) zipArchive.Dispose();
}
catch (Exception exc)
{
SetErrorState(ExceptionUtil.GetErrorStateMessage(exc));
SaLogger.Warn(GetType().Name + ".CloseArchive " + ExceptionUtil.GetLogMessage(exc));
}
zipArchive = null;
return !HasErrorState();
}
//-------------------------------------------------------------------
// F i l e s
//-------------------------------------------------------------------
public MemoryStream ExtractFileToStream (String filename)
{
if (!IsArchiveOpen()) return null;
foreach (ZipArchiveEntry entry in zipArchive.Entries)
{
//SaLogger.Debug(GetType().Name + ".GetFile Entry: " + entry.FullName);
if (entry.FullName.EqualsCI(filename) || entry.Name.EqualsCI(filename))
{
using (Stream entryStream = entry.Open())
{
MemoryStream stream = new MemoryStream();
entryStream.CopyTo(stream);
return stream;
}
}
}
return null;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
+21
View File
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<RootNamespace>Sarand.Net.Standard</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Folder Include="Data\Word\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="2.12.3" />
<PackageReference Include="NPOI" Version="2.5.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SacsStandardBase\SacsStandardBase.csproj" />
</ItemGroup>
</Project>
@@ -507,6 +507,8 @@ namespace Sarand.Net.Standard.Dbas.Base
String className = tableDfn.Name + "_Db";
List<String> primaryColumnNames = tableDfn.GetPrimaryColumnNames();
String identityColumnName = tableDfn.Columns.GetIdentityColumnName();
String identityColumnVariableTypeName = tableDfn.Columns.GetIdentityColumnVariableTypeName();
String identityColumnCastFromInt64 = (!identityColumnVariableTypeName.EqualsCI("Int64") && !identityColumnVariableTypeName.EqualsCI("long") ? "(" + identityColumnVariableTypeName + ")" : "");
// Class 'using's.
List<String> usingNamespaces = new List<string>(config.TableClass.Usings);
@@ -690,7 +692,7 @@ namespace Sarand.Net.Standard.Dbas.Base
if (!String.IsNullOrEmpty(identityColumnName))
{
// Execute single command to insert and query 'Scope_Identity' to retrieve Identity value.
file.WriteLine(tab3 + "_" + identityColumnName + " = Convert.ToInt32(dbCommand.ExecuteScalar());");
file.WriteLine(tab3 + "_" + identityColumnName + " = " + identityColumnCastFromInt64 + "Convert.ToInt64(dbCommand.ExecuteScalar());");
file.WriteLine(tab3 + "commandSuccess = (_" + identityColumnName + " > 0);");
}
else
@@ -710,7 +712,7 @@ namespace Sarand.Net.Standard.Dbas.Base
{
// Retrieve Identity value.
file.WriteLine(tab4 + "dbCommand.CommandText = \"SELECT Max(" + identityColumnName + ") FROM \" + TableNameFmt + \";\";");
file.WriteLine(tab4 + "_" + identityColumnName + " = Convert.ToInt32(dbCommand.ExecuteScalar());");
file.WriteLine(tab4 + "_" + identityColumnName + " = " + identityColumnCastFromInt64 + "Convert.ToInt64(dbCommand.ExecuteScalar());");
file.WriteLine(tab4 + "commandSuccess = (_" + identityColumnName + " > 0);");
}
else
@@ -380,7 +380,7 @@ namespace Sarand.Net.Standard.Dbas.Data
{
if (refresh) ClearTableDfns();
// Only populate table names and/or table schemas where not previously done.
if (tables.Count < 1 || tables.Exists(item => item.Columns.Count < 1))
if (tables.Count < 1 || tables.Exists(item => !item.HasColumns()))
{
// Use a single connection for table and schaema population.
using (DbConnection dbConnection = CreateConnection(true))
@@ -390,7 +390,7 @@ namespace Sarand.Net.Standard.Dbas.Data
PopulateTableNames(dbConnection);
foreach (DbDfnTable table in tables)
{
if (table.Columns.Count < 1)
if (!table.HasColumns())
{
PopulateTableColumns(dbConnection, table);
PopulateTableIndices(dbConnection, table);