diff --git a/ArrayToExcel/ArrayToExcel.cs b/ArrayToExcel/ArrayToExcel.cs index 99898dd..e85cfff 100644 --- a/ArrayToExcel/ArrayToExcel.cs +++ b/ArrayToExcel/ArrayToExcel.cs @@ -13,16 +13,16 @@ namespace ArrayToExcel { public class ArrayToExcel { - public static byte[] CreateExcel(IEnumerable items, Action>? schema = null) + public static MemoryStream CreateExcel(IEnumerable items, Action>? schema = null) { var builder = new SchemaBuilder(items); schema?.Invoke(builder); return CreateExcel(new[] { builder.Schema }.Concat(builder.Childs)); } - static byte[] CreateExcel(IEnumerable sheetSchemas) + static MemoryStream CreateExcel(IEnumerable sheetSchemas) { - using var ms = new MemoryStream(); + var ms = new MemoryStream(); using (var document = SpreadsheetDocument.Create(ms, SpreadsheetDocumentType.Workbook)) { var workbookpart = document.AddWorkbookPart(); @@ -36,6 +36,7 @@ static byte[] CreateExcel(IEnumerable sheetSchemas) foreach (var sheetSchema in sheetSchemas) { + var worksheetPart = workbookpart.AddNewPart(); worksheetPart.Worksheet = new Worksheet(); @@ -46,22 +47,26 @@ static byte[] CreateExcel(IEnumerable 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) @@ -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 }, @@ -122,10 +129,8 @@ static void AddStyles(WorkbookPart workbookPart) stylesPart.Stylesheet.Save(); } - static Row[] GetRows(IEnumerable items, List columns) + static IEnumerable GetRows(IEnumerable items, List columns) { - var rows = new List(); - var headerCells = columns.Select((x, i) => new Cell { CellReference = GetColReference(i), @@ -136,17 +141,17 @@ static Row[] GetRows(IEnumerable items, List 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) @@ -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) @@ -225,7 +230,7 @@ static string GetColReference(int index) return new string(result.ToArray()); } - static readonly HashSet _numericTypes = new () + static readonly HashSet _numericTypes = new() { typeof(short), typeof(ushort), diff --git a/ArrayToExcel/ArrayToExcel.csproj b/ArrayToExcel/ArrayToExcel.csproj index 01f776c..88c4701 100644 --- a/ArrayToExcel/ArrayToExcel.csproj +++ b/ArrayToExcel/ArrayToExcel.csproj @@ -1,14 +1,14 @@  - net45;netstandard2.0 + net45;netstandard2.0;net6.0 latest enable True ..\ArrayToExcel.snk - 2.0.3 - 2.0.3 - 2.0.3 + 2.0.4 + 2.0.4 + 2.0.4 Leonid Salavatov Leonid Salavatov 2021 diff --git a/ArrayToExcel/Extensions.cs b/ArrayToExcel/Extensions.cs index d8478fb..492582a 100644 --- a/ArrayToExcel/Extensions.cs +++ b/ArrayToExcel/Extensions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Data; +using System.IO; using System.Linq; namespace ArrayToExcel @@ -9,13 +10,36 @@ public static class Extensions { public static byte[] ToExcel(this IEnumerable items, Action>? schema = null) { - return ArrayToExcel.CreateExcel(items, schema); + using var ms = ToExcelStream(items, schema); + return ms.ToArray(); + } + + public static byte[] ToExcel(this DataTable dataTable, Action>? schema = null) + { + using var ms = ToExcelStream(dataTable, schema); + return ms.ToArray(); } public static byte[] ToExcel(this DataSet dataSet, Action>? schema = null) + { + using var ms = ToExcelStream(dataSet, schema); + return ms.ToArray(); + } + + public static MemoryStream ToExcelStream(this IEnumerable items, Action>? schema = null) + { + return ArrayToExcel.CreateExcel(items, schema); + } + + public static MemoryStream ToExcelStream(this DataTable dataTable, Action>? schema = null) + { + return ArrayToExcel.CreateExcel(dataTable.Rows.AsEnumerable(), b => dataTable.SchemaBuilder(b, schema)); + } + + public static MemoryStream ToExcelStream(this DataSet dataSet, Action>? 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)); @@ -24,11 +48,6 @@ public static byte[] ToExcel(this DataSet dataSet, Action>? schema = null) - { - return ArrayToExcel.CreateExcel(dataTable.Rows.AsEnumerable(), b => dataTable.SchemaBuilder(b, schema)); - } - public static SchemaBuilder AddSheet(this SchemaBuilder builder, DataTable dataTable, Action>? schema = null) { return builder.AddSheet(dataTable.Rows.AsEnumerable(), b => dataTable.SchemaBuilder(b, schema)); diff --git a/ArrayToExcel/SchemaBuilder.cs b/ArrayToExcel/SchemaBuilder.cs index 105dbce..1c74c2c 100644 --- a/ArrayToExcel/SchemaBuilder.cs +++ b/ArrayToExcel/SchemaBuilder.cs @@ -98,6 +98,16 @@ private List DefaultColumns(IEnumerable items) { var type = typeof(T); + if(type == typeof(object)) + { + var enumerator = items.GetEnumerator(); + + if (!enumerator.MoveNext()) + return new List(); + + type = enumerator.Current.GetType(); + } + if (typeof(IDictionary).IsAssignableFrom(type)) { var enumerator = items.GetEnumerator(); diff --git a/Examples/Example.ConsoleApp/Program.cs b/Examples/Example.ConsoleApp/Program.cs index 52be3bc..bba65e6 100644 --- a/Examples/Example.ConsoleApp/Program.cs +++ b/Examples/Example.ConsoleApp/Program.cs @@ -24,6 +24,7 @@ static void Main(string[] args) TestExpandoObject(); TestHashtable(); TestDataTable(); + TestObject(); TestTypes(); } @@ -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().ToExcel(s => s + .AddSheet(SomeItems.AsEnumerable().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 @@ -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); } diff --git a/Examples/example1.xlsx b/Examples/example1.xlsx index 1699b8c..f02fa67 100644 Binary files a/Examples/example1.xlsx and b/Examples/example1.xlsx differ diff --git a/Examples/example2.xlsx b/Examples/example2.xlsx index a7a591a..9066a50 100644 Binary files a/Examples/example2.xlsx and b/Examples/example2.xlsx differ diff --git a/Examples/example3.xlsx b/Examples/example3.xlsx index 2c0d19a..924146d 100644 Binary files a/Examples/example3.xlsx and b/Examples/example3.xlsx differ diff --git a/Examples/example4.xlsx b/Examples/example4.xlsx index f5a6bd6..a0bc336 100644 Binary files a/Examples/example4.xlsx and b/Examples/example4.xlsx differ diff --git a/Examples/example5.xlsx b/Examples/example5.xlsx index 8b547c8..718b5e5 100644 Binary files a/Examples/example5.xlsx and b/Examples/example5.xlsx differ diff --git a/Examples/example6.xlsx b/Examples/example6.xlsx index 047cfb1..abf79a0 100644 Binary files a/Examples/example6.xlsx and b/Examples/example6.xlsx differ