Skip to content

Commit

Permalink
2.4.1
Browse files Browse the repository at this point in the history
  • Loading branch information
mustaddon committed Feb 2, 2024
1 parent a216866 commit 0a6f811
Show file tree
Hide file tree
Showing 15 changed files with 213 additions and 171 deletions.
6 changes: 3 additions & 3 deletions ArrayToExcel/ArrayToExcel.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
<Nullable>enable</Nullable>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\ArrayToExcel.snk</AssemblyOriginatorKeyFile>
<AssemblyVersion>2.4.0</AssemblyVersion>
<FileVersion>2.4.0</FileVersion>
<Version>2.4.0</Version>
<AssemblyVersion>2.4.1</AssemblyVersion>
<FileVersion>2.4.1</FileVersion>
<Version>2.4.1</Version>
<Company></Company>
<Authors>Leonid Salavatov</Authors>
<Copyright>Leonid Salavatov 2024</Copyright>
Expand Down
85 changes: 85 additions & 0 deletions ArrayToExcel/CellDefault.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
using DocumentFormat.OpenXml.Spreadsheet;
using System.Globalization;
using System;
using ArrayToExcel._internal;
using System.Collections.Generic;

namespace ArrayToExcel;

public class CellDefault(object? value) : ICellValue
{
public void Apply(Cell cell, uint row) => Apply(cell, value);

internal static void Apply(Cell cell, object? value)
{
cell.CellValue = GetCellValue(value);
cell.DataType = GetCellType(value);
cell.StyleIndex = cell.DataType == CellValues.Date ? 2 : 4u;
}

internal static CellValue GetCellValue(object? value)
{
if (value == null) return new();

var type = value.GetType();

if (type == typeof(bool))
return new((bool)value ? _boolVals[1] : _boolVals[0]);

if (type == typeof(DateTime))
return new(((DateTime)value).ToString(_dateFormat, _cultureInfo));

if (type == typeof(DateTimeOffset))
return new(((DateTimeOffset)value).ToString(_dateFormat, _cultureInfo));

if (type == typeof(double))
return new(((double)value).ToString(_cultureInfo));

if (type == typeof(decimal))
return new(((decimal)value).ToString(_cultureInfo));

if (type == typeof(float))
return new(((float)value).ToString(_cultureInfo));

return new(NormCellText(value.ToString()!));
}


internal static string NormCellText(string value)
{
return RegularExpressions.InvalidXmlChars().Replace(value.Length > _maxCellText ? value.Substring(0, _maxCellText) : value, string.Empty);
}

internal static CellValues GetCellType(object? value)
{
var type = value?.GetType() ?? typeof(object);

if (type == typeof(bool))
return CellValues.Boolean;

if (_numericTypes.Contains(type))
return CellValues.Number;

if (type == typeof(DateTime) || type == typeof(DateTimeOffset))
return CellValues.Date;

return CellValues.String;
}

static readonly HashSet<Type> _numericTypes = [
typeof(short),
typeof(ushort),
typeof(int),
typeof(uint),
typeof(long),
typeof(ulong),
typeof(double),
typeof(decimal),
typeof(float)];

static readonly CultureInfo _cultureInfo = CultureInfo.GetCultureInfo("en-US");
static readonly string _dateFormat = "s";
static readonly string[] _boolVals = ["0", "1"];

const int _maxCellText = 32767;
}
16 changes: 16 additions & 0 deletions ArrayToExcel/CellFormula.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using DocumentFormat.OpenXml.Spreadsheet;
using System;

namespace ArrayToExcel;

public class CellFormula(Func<uint, string, string> cellText) : ICellValue
{
public CellFormula(Func<uint, string> rowText) : this((row, cell) => rowText(row)) { }
public CellFormula(string text) : this((row, col) => text) { }

public void Apply(Cell cell, uint row)
{
cell.CellFormula = new DocumentFormat.OpenXml.Spreadsheet.CellFormula(cellText(row, cell.CellReference!));
cell.StyleIndex = 4;
}
}
28 changes: 28 additions & 0 deletions ArrayToExcel/CellHyperlink.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using DocumentFormat.OpenXml.Spreadsheet;
using System;

namespace ArrayToExcel;

public class CellHyperlink(string link, string? text = null) : ICellValue
{
public CellHyperlink(Uri link, string? text = null)
: this(link.ToString(), text ?? link.OriginalString) { }

public void Apply(Cell cell, uint row)
{
cell.CellFormula = new DocumentFormat.OpenXml.Spreadsheet.CellFormula(_format.Value);
cell.StyleIndex = 3;
}

readonly Lazy<string> _format = new(() => Format(link, text));

static string Format(string link, string? text)
{
return string.Format(string.IsNullOrWhiteSpace(text) || text == link
? "HYPERLINK(\"{0}\")"
: "HYPERLINK(\"{0}\",\"{1}\")",
Fix(link), Fix(text));
}

static string? Fix(string? val) => val?.Replace("\"", "\"\"");
}
13 changes: 13 additions & 0 deletions ArrayToExcel/CellPercent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using DocumentFormat.OpenXml.Spreadsheet;

namespace ArrayToExcel;

public class CellPercent(object? value) : ICellValue
{
public void Apply(Cell cell, uint row)
{
cell.CellValue = CellDefault.GetCellValue(value);
cell.DataType = CellDefault.GetCellType(value);
cell.StyleIndex = 5;
}
}
24 changes: 24 additions & 0 deletions ArrayToExcel/CellText.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Spreadsheet;

namespace ArrayToExcel;

public class CellText(string? value, bool wrap = false) : ICellValue
{
public void Apply(Cell cell, uint row) => Apply(cell, value, wrap);

internal static void Apply(Cell cell, string? value, bool wrap)
{
cell.InlineString = GetInlineString(value ?? string.Empty);
cell.DataType = CellValues.InlineString;
cell.StyleIndex = wrap ? 4 : 6u;
}

static InlineString GetInlineString(string value)
{
return new InlineString(new DocumentFormat.OpenXml.Spreadsheet.Text(CellDefault.NormCellText(value))
{
Space = SpaceProcessingModeValues.Preserve
});
}
}
121 changes: 9 additions & 112 deletions ArrayToExcel/ExcelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;

Expand Down Expand Up @@ -173,11 +172,11 @@ static IEnumerable<Row> GetRows(IEnumerable items, List<ColumnSchema> columns, b

yield return headerRow;

var i = 2u;
var i = 1u;
foreach (var item in items)
{
var row = new Row() { RowIndex = i++ };
row.Append(columns.Select((x, i) => GetCell(row.RowIndex, headerCells[i].CellReference, x.Value?.Invoke(item), wrapText)));
var row = new Row() { RowIndex = ++i };
row.Append(columns.Select((x, j) => GetCell(i, headerCells[j].CellReference, x.Value?.Invoke(item), wrapText)));
yield return row;
}
}
Expand All @@ -186,105 +185,18 @@ static Cell GetCell(uint rowIndex, string? cellReference, object? value, bool wr
{
var cell = new Cell { CellReference = cellReference };

if (value is string str)
{
cell.InlineString = GetInlineString(str);
cell.DataType = CellValues.InlineString;
cell.StyleIndex = wrapText ? 4 : 6u;
}
else if (value is Text text)
{
cell.InlineString = GetInlineString(text.Value ?? string.Empty);
cell.DataType = CellValues.InlineString;
cell.StyleIndex = text.Wrap ? 4 : 6u;
}
else if (value is Formula formula)
{
cell.CellFormula = new CellFormula(formula.RowText(rowIndex));
cell.StyleIndex = 4;
}
else if (value is Hyperlink hyperlink)
{
cell.CellFormula = new CellFormula(hyperlink.ToString());
cell.StyleIndex = 3;
}
if (value is ICellValue cellValue)
cellValue.Apply(cell, rowIndex);
else if (value is string str)
CellText.Apply(cell, str, wrapText);
else if (value is Uri uri)
{
cell.CellFormula = new CellFormula(new Hyperlink(uri).ToString());
cell.StyleIndex = 3;
}
else if (value is Percent percent)
{
cell.CellValue = GetCellValue(percent.Value);
cell.DataType = GetCellType(percent.Value);
cell.StyleIndex = 5;
}
new CellHyperlink(uri).Apply(cell, rowIndex);
else
{
cell.CellValue = GetCellValue(value);
cell.DataType = GetCellType(value);
cell.StyleIndex = cell.DataType == CellValues.Date ? 2 : 4u;
}
CellDefault.Apply(cell, value);

return cell;
}

static CellValue GetCellValue(object? value)
{
if (value == null) return new();

var type = value.GetType();

if (type == typeof(bool))
return new((bool)value ? "1" : "0");

if (type == typeof(DateTime))
return new(((DateTime)value).ToString("s", _cultureInfo));

if (type == typeof(DateTimeOffset))
return new(((DateTimeOffset)value).ToString("s", _cultureInfo));

if (type == typeof(double))
return new(((double)value).ToString(_cultureInfo));

if (type == typeof(decimal))
return new(((decimal)value).ToString(_cultureInfo));

if (type == typeof(float))
return new(((float)value).ToString(_cultureInfo));

return new(NormCellText(value.ToString()!));
}

static InlineString GetInlineString(string value)
{
return new InlineString(new DocumentFormat.OpenXml.Spreadsheet.Text(NormCellText(value))
{
Space = SpaceProcessingModeValues.Preserve
});
}

static string NormCellText(string value)
{
return RegularExpressions.InvalidXmlChars().Replace(value.Length > _maxCellText ? value.Substring(0, _maxCellText) : value, string.Empty);
}

static CellValues GetCellType(object? value)
{
var type = value?.GetType() ?? typeof(object);

if (type == typeof(bool))
return CellValues.Boolean;

if (_numericTypes.Contains(type))
return CellValues.Number;

if (type == typeof(DateTime) || type == typeof(DateTimeOffset))
return CellValues.Date;

return CellValues.String;
}

static string GetColReference(int index)
{
var result = new List<char>();
Expand All @@ -299,22 +211,7 @@ static string GetColReference(int index)
return new string([.. result]);
}

static readonly HashSet<Type> _numericTypes = [
typeof(short),
typeof(ushort),
typeof(int),
typeof(uint),
typeof(long),
typeof(ulong),
typeof(double),
typeof(decimal),
typeof(float)];

static readonly CultureInfo _cultureInfo = CultureInfo.GetCultureInfo("en-US");

static readonly string _digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

const int _maxSheetName = 31;

const int _maxCellText = 32767;
}
10 changes: 0 additions & 10 deletions ArrayToExcel/Formula.cs

This file was deleted.

27 changes: 0 additions & 27 deletions ArrayToExcel/Hyperlink.cs

This file was deleted.

8 changes: 8 additions & 0 deletions ArrayToExcel/ICellValue.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using DocumentFormat.OpenXml.Spreadsheet;

namespace ArrayToExcel;

public interface ICellValue
{
void Apply(Cell cell, uint row);
}
6 changes: 0 additions & 6 deletions ArrayToExcel/Percent.cs

This file was deleted.

Loading

0 comments on commit 0a6f811

Please sign in to comment.