diff --git a/docs/README.md b/docs/README.md index ec38c195..f06e7cba 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,7 +2,14 @@ ## Release Notes + + +### 0.10.1 + +- [New] SaveAs support POCO excel column name/ignore attribute + ### 0.10.0 + - [New] Query dynamic with first head will ignore blank/whitespace columns - [New] Query type mapping support Custom POCO excel column name/ignore attribute diff --git a/src/MiniExcel/Csv/CsvReader.cs b/src/MiniExcel/Csv/CsvReader.cs index c1430cca..fb5cd7e9 100644 --- a/src/MiniExcel/Csv/CsvReader.cs +++ b/src/MiniExcel/Csv/CsvReader.cs @@ -59,7 +59,7 @@ public IEnumerable> Query(Stream stream, bool useHea public IEnumerable Query(Stream stream) where T : class, new() { var type = typeof(T); - var props = Helpers.GetProperties(type); + var props = Helpers.GetSaveAsProperties(type); Dictionary idxProps = new Dictionary(); var configuration = new CsvConfiguration(); using (var reader = configuration.GetStreamReaderFunc(stream)) @@ -76,9 +76,9 @@ public IEnumerable> Query(Stream stream, bool useHea var index = 0; foreach (var v in read) { - var p = props.SingleOrDefault(w => w.Name == v); + var p = props.SingleOrDefault(w => w.ExcelColumnName == v); if (p != null) - idxProps.Add(index, p); + idxProps.Add(index, p.Property); index++; } } diff --git a/src/MiniExcel/MiniExcelLibs.csproj b/src/MiniExcel/MiniExcelLibs.csproj index fbe39699..261c6580 100644 --- a/src/MiniExcel/MiniExcelLibs.csproj +++ b/src/MiniExcel/MiniExcelLibs.csproj @@ -5,7 +5,7 @@ MiniExcel excel;xlsx;micro-helper;mini;openxml;helper; - A high performance and easy Excel(xlsx,csv) Micro-Helper that avoids OOM and without third party dependencies to create or dynamic/type POCO mapping query etc.. + A high performance and easy Excel(xlsx,csv) Micro-Helper that avoids OOM and without third-party dependencies to create or dynamic/type POCO mapping query etc.. Github : https://github.com/shps951023/MiniExcel Issues : https://github.com/shps951023/MiniExcel/issues @@ -19,7 +19,7 @@ https://github.com/shps951023/MiniExcel https://raw.githubusercontent.com/shps951023/ImageHosting/master/img/2019-01-17.13.18.32-image.png net461;netstandard2.0;net5.0 - 0.10.0 + 0.10.1 Please Check [Release Notes](https://github.com/shps951023/MiniExcel/tree/master/docs) Github diff --git a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs index 9c7d59c2..2173acdd 100644 --- a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs +++ b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetWriter.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Reflection; using System.Text; +using static MiniExcelLibs.Utils.Helpers; namespace MiniExcelLibs.OpenXml { @@ -50,7 +51,7 @@ public void SaveAs(Stream stream, object value) var maxColumnIndex = 0; List keys = new List(); - PropertyInfo[] props = null; + List props = null; string mode = null; { @@ -79,11 +80,8 @@ public void SaveAs(Stream stream, object value) { mode = "Properties"; genericType = item.GetType(); - props = Helpers.GetProperties(genericType); - //props = genericType.GetProperties(); - if (props.Length == 0) - throw new InvalidOperationException($"Generic Type : {genericType} valid properties count is 0, if you have trouble please issue for me."); - maxColumnIndex = props.Length; + props = Helpers.GetSaveAsProperties(genericType); + maxColumnIndex = props.Count; } // not re-foreach key point @@ -122,7 +120,7 @@ public void SaveAs(Stream stream, object value) foreach (var p in props) { var columname = ExcelOpenXmlUtils.ConvertXyToCell(cellIndex, yIndex); - writer.Write($"{p.Name}"); + writer.Write($"{p.ExcelColumnName}"); cellIndex++; } } @@ -248,7 +246,7 @@ internal void GenerateSheetByIDictionary(StreamWriter writer, ZipArchive archive } } - internal void GenerateSheetByProperties(StreamWriter writer, ZipArchive archive, IEnumerable value, Type genericType, PropertyInfo[] props, int rowCount, List keys, int xIndex = 1, int yIndex = 1) + internal void GenerateSheetByProperties(StreamWriter writer, ZipArchive archive, IEnumerable value, Type genericType, List props, int rowCount, List keys, int xIndex = 1, int yIndex = 1) { //body foreach (var v in value) @@ -257,7 +255,7 @@ internal void GenerateSheetByProperties(StreamWriter writer, ZipArchive archive, var cellIndex = xIndex; foreach (var p in props) { - var cellValue = p.GetValue(v); + var cellValue = p.Property.GetValue(v); var cellValueStr = ExcelOpenXmlUtils.EncodeXML(cellValue); var t = "t=\"str\""; { diff --git a/src/MiniExcel/Utils/Helpers.cs b/src/MiniExcel/Utils/Helpers.cs index 2b093aaf..d47bac75 100644 --- a/src/MiniExcel/Utils/Helpers.cs +++ b/src/MiniExcel/Utils/Helpers.cs @@ -22,8 +22,8 @@ static Helpers() } } - public static string GetAlphabetColumnName(int ColumnIndex) => _IntMappingAlphabet[ColumnIndex]; - public static int GetColumnIndex(string columnName) => _AlphabetMappingInt[columnName]; + internal static string GetAlphabetColumnName(int ColumnIndex) => _IntMappingAlphabet[ColumnIndex]; + internal static int GetColumnIndex(string columnName) => _AlphabetMappingInt[columnName]; internal static string IntToLetters(int value) { @@ -37,7 +37,7 @@ internal static string IntToLetters(int value) return result; } - public static IDictionary GetEmptyExpandoObject(int maxColumnIndex) + internal static IDictionary GetEmptyExpandoObject(int maxColumnIndex) { // TODO: strong type mapping can ignore this // TODO: it can recode better performance @@ -51,7 +51,7 @@ public static IDictionary GetEmptyExpandoObject(int maxColumnInd return cell; } - public static IDictionary GetEmptyExpandoObject(Dictionary hearrows) + internal static IDictionary GetEmptyExpandoObject(Dictionary hearrows) { // TODO: strong type mapping can ignore this // TODO: it can recode better performance @@ -62,11 +62,16 @@ public static IDictionary GetEmptyExpandoObject(Dictionary GetSaveAsProperties(this Type type) { - return type.GetProperties( - BindingFlags.Public | - BindingFlags.Instance); + List props = GetExcelPropertyInfo(type, BindingFlags.Public | BindingFlags.Instance) + .Where(prop => prop.Property.GetGetMethod() != null && !prop.Property.GetAttributeValue((ExcelIgnoreAttribute x) => x.ExcelIgnore)) + .ToList() /*ignore without set*/; + + if (props.Count == 0) + throw new InvalidOperationException($"{type.Name} un-ignore properties count can't be 0"); + + return props; } internal class ExcelCustomPropertyInfo @@ -108,11 +113,6 @@ private static IEnumerable GetExcelPropertyInfo(Type ty }); } - internal static bool IsDapperRows() - { - return typeof(IDictionary).IsAssignableFrom(typeof(T)); - } - private static readonly Regex EscapeRegex = new Regex("_x([0-9A-F]{4,4})_"); public static string ConvertEscapeChars(string input) { diff --git a/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs b/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs index 6bca34d7..4b2fa1f9 100644 --- a/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs +++ b/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs @@ -29,7 +29,7 @@ public void CustomAttributeWihoutVaildPropertiesTest() } [Fact] - public void CustomAttributesTest() + public void QueryCustomAttributesTest() { var path = @"..\..\..\..\..\samples\xlsx\TestCustomExcelColumnAttribute.xlsx"; var rows = MiniExcel.Query(path).ToList(); @@ -42,6 +42,34 @@ public void CustomAttributesTest() Assert.Null(rows[0].Test6); } + [Fact] + public void SaveAsCustomAttributesTest() + { + var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.xlsx"); + var input = Enumerable.Range(1, 3).Select( + s => new ExcelAttributeDemo + { + Test1 = "Test1", + Test2 = "Test2", + Test3 = "Test3", + Test4 = "Test4", + } + ); + MiniExcel.SaveAs(path, input); + { + var rows = MiniExcel.Query(path,true).ToList(); + var first = rows[0] as IDictionary; + Assert.Equal(new[] { "Column1", "Column2", "Test4", "Test5", "Test6" },first.Keys); + Assert.Equal("Test1", rows[0].Column1); + Assert.Equal("Test2", rows[0].Column2); + Assert.Equal("Test4", rows[0].Test4); + Assert.Null(rows[0].Test5); + Assert.Null(rows[0].Test6); + + Assert.Equal(3,rows.Count); + } + } + public class CustomAttributesWihoutVaildPropertiesTestPoco { [ExcelIgnore] @@ -173,7 +201,7 @@ public void TestDynamicQueryBasic_useHeaderRow() } { - var rows = MiniExcel.Query(path,useHeaderRow: true).ToList(); + var rows = MiniExcel.Query(path, useHeaderRow: true).ToList(); Assert.Equal("MiniExcel", rows[0].Column1); Assert.Equal(1, rows[0].Column2); @@ -715,7 +743,7 @@ public void SaveAsByIEnumerableIDictionary() using (var stream = File.OpenRead(path)) { var rows = stream.Query(useHeaderRow: false).ToList(); - Assert.Equal(3,rows.Count); + Assert.Equal(3, rows.Count); } Assert.Equal("A1:B3", Helpers.GetFirstSheetDimensionRefValue(path)); @@ -912,7 +940,7 @@ public void SaveAsBasicCreateTest() new { Column1 = "MiniExcel", Column2 = 1 }, new { Column1 = "Github", Column2 = 2} }); - + using (var stream = File.OpenRead(path)) { var rows = stream.Query(useHeaderRow: true).ToList();