Skip to content

Commit

Permalink
2.0.4
Browse files Browse the repository at this point in the history
  • Loading branch information
mustaddon committed Nov 13, 2021
1 parent cae1e59 commit a3a9e6e
Show file tree
Hide file tree
Showing 11 changed files with 90 additions and 46 deletions.
67 changes: 36 additions & 31 deletions ArrayToExcel/ArrayToExcel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ namespace ArrayToExcel
{
public class ArrayToExcel
{
public static byte[] CreateExcel<T>(IEnumerable<T> items, Action<SchemaBuilder<T>>? schema = null)
public static MemoryStream CreateExcel<T>(IEnumerable<T> items, Action<SchemaBuilder<T>>? schema = null)
{
var builder = new SchemaBuilder<T>(items);
schema?.Invoke(builder);
return CreateExcel(new[] { builder.Schema }.Concat(builder.Childs));
}

static byte[] CreateExcel(IEnumerable<SheetSchema> sheetSchemas)
static MemoryStream CreateExcel(IEnumerable<SheetSchema> sheetSchemas)
{
using var ms = new MemoryStream();
var ms = new MemoryStream();
using (var document = SpreadsheetDocument.Create(ms, SpreadsheetDocumentType.Workbook))
{
var workbookpart = document.AddWorkbookPart();
Expand All @@ -36,6 +36,7 @@ static byte[] CreateExcel(IEnumerable<SheetSchema> sheetSchemas)

foreach (var sheetSchema in sheetSchemas)
{

var worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet();

Expand All @@ -46,22 +47,26 @@ static byte[] CreateExcel(IEnumerable<SheetSchema> sheetSchemas)
Name = NormSheetName(sheetSchema.SheetName),
});

if (sheetSchema.Columns.Count > 0)
var cols = worksheetPart.Worksheet.AppendChild(new Columns());
var sheetData = worksheetPart.Worksheet.AppendChild(new SheetData());

if (sheetSchema.Columns.Count == 0)
{
var cols = worksheetPart.Worksheet.AppendChild(new Columns());
cols.Append(sheetSchema.Columns.Select((x, i) => new Column() { Min = (uint)(i + 1), Max = (uint)(i + 1), Width = x.Width, CustomWidth = true, BestFit = true }));
cols.Append(new Column() { Min = 1, Max = 1, BestFit = true });
continue;
}

var rows = GetRows(sheetSchema.Items, sheetSchema.Columns);
var sheetData = worksheetPart.Worksheet.AppendChild(new SheetData());
sheetData.Append(rows);
cols.Append(sheetSchema.Columns.Select((x, i) => new Column() { Min = (uint)(i + 1), Max = (uint)(i + 1), Width = x.Width, CustomWidth = true, BestFit = true }));

worksheetPart.Worksheet.Append(new AutoFilter() { Reference = $"A1:{GetColReference(sheetSchema.Columns.Count - 1)}{rows.Length}" });
}
sheetData.Append(GetRows(sheetSchema.Items, sheetSchema.Columns));

worksheetPart.Worksheet.Append(new AutoFilter() { Reference = $"A1:{GetColReference(sheetSchema.Columns.Count - 1)}{sheetData.ChildElements.Count}" });
}

workbookpart.Workbook.Save();
}
return ms.ToArray();
ms.Position = 0;
return ms;
}

static string NormSheetName(string value)
Expand All @@ -86,8 +91,10 @@ static void AddStyles(WorkbookPart workbookPart)
stylesPart.Stylesheet.Fills = new Fills();
stylesPart.Stylesheet.Fills.AppendChild(new Fill { PatternFill = new PatternFill { PatternType = PatternValues.None } }); // required, reserved by Excel
stylesPart.Stylesheet.Fills.AppendChild(new Fill { PatternFill = new PatternFill { PatternType = PatternValues.Gray125 } }); // required, reserved by Excel
stylesPart.Stylesheet.Fills.AppendChild(new Fill {
PatternFill = new PatternFill() {
stylesPart.Stylesheet.Fills.AppendChild(new Fill
{
PatternFill = new PatternFill()
{
PatternType = PatternValues.Solid,
ForegroundColor = new ForegroundColor { Rgb = HexBinaryValue.FromString("FF4F81BD") },
BackgroundColor = new BackgroundColor { Indexed = 64 },
Expand Down Expand Up @@ -122,10 +129,8 @@ static void AddStyles(WorkbookPart workbookPart)
stylesPart.Stylesheet.Save();
}

static Row[] GetRows(IEnumerable items, List<ColumnSchema> columns)
static IEnumerable<Row> GetRows(IEnumerable items, List<ColumnSchema> columns)
{
var rows = new List<Row>();

var headerCells = columns.Select((x, i) => new Cell
{
CellReference = GetColReference(i),
Expand All @@ -136,17 +141,17 @@ static Row[] GetRows(IEnumerable items, List<ColumnSchema> columns)

var headerRow = new Row() { RowIndex = 1 };
headerRow.Append(headerCells);
rows.Add(headerRow);

var i = 2;
yield return headerRow;

var i = 2u;
foreach (var item in items)
{
var row = new Row() { RowIndex = (uint)i++ };
var row = new Row() { RowIndex = i++ };
var cells = columns.Select((x, i) => GetCell(headerCells[i].CellReference, x.Value?.Invoke(item))).ToArray();
row.Append(cells);
rows.Add(row);
yield return row;
}
return rows.ToArray();
}

static Cell GetCell(string? reference, object? value)
Expand All @@ -163,29 +168,29 @@ static Cell GetCell(string? reference, object? value)

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

var type = value.GetType();

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

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

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

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

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

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

return new (RemoveInvalidXmlChars(value.ToString()));
return new(RemoveInvalidXmlChars(value.ToString()));
}

static string RemoveInvalidXmlChars(string text)
Expand Down Expand Up @@ -225,7 +230,7 @@ static string GetColReference(int index)
return new string(result.ToArray());
}

static readonly HashSet<Type> _numericTypes = new ()
static readonly HashSet<Type> _numericTypes = new()
{
typeof(short),
typeof(ushort),
Expand Down
8 changes: 4 additions & 4 deletions ArrayToExcel/ArrayToExcel.csproj
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net45;netstandard2.0</TargetFrameworks>
<TargetFrameworks>net45;netstandard2.0;net6.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\ArrayToExcel.snk</AssemblyOriginatorKeyFile>
<AssemblyVersion>2.0.3</AssemblyVersion>
<FileVersion>2.0.3</FileVersion>
<Version>2.0.3</Version>
<AssemblyVersion>2.0.4</AssemblyVersion>
<FileVersion>2.0.4</FileVersion>
<Version>2.0.4</Version>
<Company></Company>
<Authors>Leonid Salavatov</Authors>
<Copyright>Leonid Salavatov 2021</Copyright>
Expand Down
33 changes: 26 additions & 7 deletions ArrayToExcel/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;

namespace ArrayToExcel
Expand All @@ -9,13 +10,36 @@ public static class Extensions
{
public static byte[] ToExcel<T>(this IEnumerable<T> items, Action<SchemaBuilder<T>>? schema = null)
{
return ArrayToExcel.CreateExcel(items, schema);
using var ms = ToExcelStream(items, schema);
return ms.ToArray();
}

public static byte[] ToExcel(this DataTable dataTable, Action<SchemaBuilder<DataRow>>? schema = null)
{
using var ms = ToExcelStream(dataTable, schema);
return ms.ToArray();
}

public static byte[] ToExcel(this DataSet dataSet, Action<DataTable, SchemaBuilder<DataRow>>? schema = null)
{
using var ms = ToExcelStream(dataSet, schema);
return ms.ToArray();
}

public static MemoryStream ToExcelStream<T>(this IEnumerable<T> items, Action<SchemaBuilder<T>>? schema = null)
{
return ArrayToExcel.CreateExcel(items, schema);
}

public static MemoryStream ToExcelStream(this DataTable dataTable, Action<SchemaBuilder<DataRow>>? schema = null)
{
return ArrayToExcel.CreateExcel(dataTable.Rows.AsEnumerable(), b => dataTable.SchemaBuilder(b, schema));
}

public static MemoryStream ToExcelStream(this DataSet dataSet, Action<DataTable, SchemaBuilder<DataRow>>? schema = null)
{
var tables = dataSet.Tables.AsEnumerable().ToList();
return ToExcel(tables.First(), builder =>
return ToExcelStream(tables.First(), builder =>
{
foreach (var table in tables.Skip(1))
builder.AddSheet(table, s => schema?.Invoke(table, s));
Expand All @@ -24,11 +48,6 @@ public static byte[] ToExcel(this DataSet dataSet, Action<DataTable, SchemaBuild
});
}

public static byte[] ToExcel(this DataTable dataTable, Action<SchemaBuilder<DataRow>>? schema = null)
{
return ArrayToExcel.CreateExcel(dataTable.Rows.AsEnumerable(), b => dataTable.SchemaBuilder(b, schema));
}

public static SchemaBuilder<T> AddSheet<T>(this SchemaBuilder<T> builder, DataTable dataTable, Action<SchemaBuilder<DataRow>>? schema = null)
{
return builder.AddSheet(dataTable.Rows.AsEnumerable(), b => dataTable.SchemaBuilder(b, schema));
Expand Down
10 changes: 10 additions & 0 deletions ArrayToExcel/SchemaBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ private List<ColumnSchema> DefaultColumns(IEnumerable items)
{
var type = typeof(T);

if(type == typeof(object))
{
var enumerator = items.GetEnumerator();

if (!enumerator.MoveNext())
return new List<ColumnSchema>();

type = enumerator.Current.GetType();
}

if (typeof(IDictionary<string, object?>).IsAssignableFrom(type))
{
var enumerator = items.GetEnumerator();
Expand Down
18 changes: 14 additions & 4 deletions Examples/Example.ConsoleApp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ static void Main(string[] args)
TestExpandoObject();
TestHashtable();
TestDataTable();
TestObject();
TestTypes();
}

Expand Down Expand Up @@ -185,7 +186,16 @@ static void TestDataTable()
File.WriteAllBytes($@"..\{nameof(TestDataTable)}.xlsx", excel);
}

// different types
// list of objects
static void TestObject()
{
var excel = SomeItems.AsEnumerable<object>().ToExcel(s => s
.AddSheet(SomeItems.AsEnumerable<object>().Skip(3))); // extra sheet

File.WriteAllBytes($@"..\{nameof(TestObject)}.xlsx", excel);
}

// different types + stream
static void TestTypes()
{
var items = Enumerable.Range(1, 100).Select(x => new
Expand All @@ -203,9 +213,9 @@ static void TestTypes()
String = $"text text text #{x} !!!",
});

var data = items.ToExcel();

File.WriteAllBytes($@"..\{nameof(TestTypes)}.xlsx", data);
using var excel = items.ToExcelStream();
using var file = File.Create($@"..\{nameof(TestTypes)}.xlsx");
excel.CopyTo(file);
}


Expand Down
Binary file modified Examples/example1.xlsx
Binary file not shown.
Binary file modified Examples/example2.xlsx
Binary file not shown.
Binary file modified Examples/example3.xlsx
Binary file not shown.
Binary file modified Examples/example4.xlsx
Binary file not shown.
Binary file modified Examples/example5.xlsx
Binary file not shown.
Binary file modified Examples/example6.xlsx
Binary file not shown.

0 comments on commit a3a9e6e

Please sign in to comment.