From a68a6560f575d782da0102bdc59a012a8f599a36 Mon Sep 17 00:00:00 2001 From: Michele Bastione Date: Mon, 17 Feb 2025 22:15:55 +0100 Subject: [PATCH 1/2] Added support for Uri mapping --- samples/xlsx/TestUriMapping.xlsx | Bin 0 -> 7911 bytes src/MiniExcel/Utils/TypeHelper.cs | 7 ++++++ tests/MiniExcelTests/MiniExcelOpenXmlTests.cs | 21 ++++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 samples/xlsx/TestUriMapping.xlsx diff --git a/samples/xlsx/TestUriMapping.xlsx b/samples/xlsx/TestUriMapping.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..1dcc72b028aa7a09c9e2172f59bbc775dffe4333 GIT binary patch literal 7911 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 literal 0 HcmV?d00001 diff --git a/src/MiniExcel/Utils/TypeHelper.cs b/src/MiniExcel/Utils/TypeHelper.cs index b37294d0..394599d9 100644 --- a/src/MiniExcel/Utils/TypeHelper.cs +++ b/src/MiniExcel/Utils/TypeHelper.cs @@ -151,6 +151,13 @@ public static bool IsNumericType(Type type, bool isNullableUnderlyingType = fals else newValue = Enum.Parse(pInfo.ExcludeNullableType, itemValue?.ToString(), true); } + else if (pInfo.ExcludeNullableType == typeof(Uri)) + { + var rawValue = itemValue?.ToString(); + if (!Uri.TryCreate(rawValue, UriKind.RelativeOrAbsolute, out var uri)) + throw new InvalidCastException($"Value \"{rawValue}\" cannot be converted to Uri"); + newValue = uri; + } else { // Use pInfo.ExcludeNullableType to resolve : https://github.com/shps951023/MiniExcel/issues/138 diff --git a/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs b/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs index ad9e0f65..74c8a5dd 100644 --- a/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs +++ b/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs @@ -381,6 +381,27 @@ public void AutoCheckTypeTest() } } + public class ExcelUriDemo + { + public string Name { get; set; } + public int Age { get; set; } + public Uri Url { get; set; } + } + + [Fact] + public void UriMappingTest() + { + var path = "../../../../../samples/xlsx/TestUriMapping.xlsx"; + using (var stream = File.OpenRead(path)) + { + var rows = stream.Query().ToList(); + + Assert.Equal("Felix", rows[1].Name); + Assert.Equal(44, rows[1].Age); + Assert.Equal(new Uri("https://friendly-utilization.net"), rows[1].Url); + } + } + [Fact()] public void TestDatetimeSpanFormat_ClosedXml() { From 4a34060af7ef5f89ac655675b88b14f73dea4bdc Mon Sep 17 00:00:00 2001 From: Michele Bastione Date: Tue, 11 Mar 2025 23:48:43 +0100 Subject: [PATCH 2/2] Fixed parsing bug in the conversion to double - Fixed problem where, after the latest commit, numeric strings were not being converted to double correctly due to a ToString call that lacked invariant localization - Also added a missing Dispose call in MiniExcelDataReader, and a couple more superficial changes --- src/MiniExcel/MiniExcelDataReader.cs | 2 +- .../OpenXml/ExcelOpenXmlSheetReader.cs | 11 ++------ src/MiniExcel/Utils/TypeHelper.cs | 20 +++++++++------ src/MiniExcel/Utils/XmlReaderHelper.cs | 25 +++++++------------ tests/MiniExcelTests/MiniExcelIssueTests.cs | 6 ++--- 5 files changed, 27 insertions(+), 37 deletions(-) diff --git a/src/MiniExcel/MiniExcelDataReader.cs b/src/MiniExcel/MiniExcelDataReader.cs index 5d525174..6a130444 100644 --- a/src/MiniExcel/MiniExcelDataReader.cs +++ b/src/MiniExcel/MiniExcelDataReader.cs @@ -69,7 +69,6 @@ public override string GetName(int i) /// public override int GetOrdinal(string name) { - _keys.IndexOf(name); return _keys.IndexOf(name); } @@ -81,6 +80,7 @@ protected override void Dispose(bool disposing) if (disposing) { _stream?.Dispose(); + _source?.Dispose(); } _disposed = true; } diff --git a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetReader.cs b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetReader.cs index d3db6528..67537af2 100644 --- a/src/MiniExcel/OpenXml/ExcelOpenXmlSheetReader.cs +++ b/src/MiniExcel/OpenXml/ExcelOpenXmlSheetReader.cs @@ -7,7 +7,6 @@ using System.IO; using System.IO.Compression; using System.Linq; -using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Xml; @@ -496,14 +495,8 @@ private void SetCellsValueAndHeaders(object cellValue, bool useHeaderRow, ref Di if (itemValue == null) continue; - if (pInfo.ExcludeNullableType == typeof(double) && (!Regex.IsMatch(itemValue?.ToString(), "^-?\\d+(\\.\\d+)?([eE][-+]?\\d+)?$") || itemValue?.ToString().Trim().Equals("NaN") == true))//double.NaN 无效值处理 - { - newV = TypeHelper.TypeMapping(v, pInfo, newV, double.NaN, rowIndex, startCell, configuration); - } - else - { - newV = TypeHelper.TypeMapping(v, pInfo, newV, itemValue, rowIndex, startCell, configuration); - } + + newV = TypeHelper.TypeMapping(v, pInfo, newV, itemValue, rowIndex, startCell, configuration); } } rowIndex++; diff --git a/src/MiniExcel/Utils/TypeHelper.cs b/src/MiniExcel/Utils/TypeHelper.cs index 5daef177..bcacf328 100644 --- a/src/MiniExcel/Utils/TypeHelper.cs +++ b/src/MiniExcel/Utils/TypeHelper.cs @@ -16,9 +16,7 @@ public static IEnumerable> ConvertToEnumerableDictio while (reader.Read()) { yield return Enumerable.Range(0, reader.FieldCount) - .ToDictionary( - i => reader.GetName(i), - i => reader.GetValue(i)); + .ToDictionary(reader.GetName, reader.GetValue); } } @@ -69,7 +67,9 @@ public static bool IsNumericType(Type type, bool isNullableUnderlyingType = fals var columnName = pInfo.ExcelColumnName ?? pInfo.Property.Name; var startRowIndex = ReferenceHelper.ConvertCellToXY(startCell).Item2; var errorRow = startRowIndex + rowIndex + 1; - throw new ExcelInvalidCastException(columnName, errorRow, itemValue, pInfo.Property.Info.PropertyType, $"ColumnName : {columnName}, CellRow : {errorRow}, Value : {itemValue}, it can't cast to {pInfo.Property.Info.PropertyType.Name} type."); + + var msg = $"ColumnName: {columnName}, CellRow: {errorRow}, Value: {itemValue}. The value cannot be cast to type {pInfo.Property.Info.PropertyType.Name}."; + throw new ExcelInvalidCastException(columnName, errorRow, itemValue, pInfo.Property.Info.PropertyType, msg); } } @@ -96,7 +96,7 @@ public static bool IsNumericType(Type type, bool isNullableUnderlyingType = fals else if (DateTimeOffset.TryParse(vs, _config.Culture, DateTimeStyles.None, out var _v)) newValue = _v; else - throw new InvalidCastException($"{vs} can't cast to datetime"); + throw new InvalidCastException($"{vs} cannot be cast to DateTime"); } else if (pInfo.ExcludeNullableType == typeof(DateTime)) { @@ -127,7 +127,7 @@ public static bool IsNumericType(Type type, bool isNullableUnderlyingType = fals else if (double.TryParse(vs, NumberStyles.None, CultureInfo.InvariantCulture, out var _d)) newValue = DateTimeHelper.FromOADate(_d); else - throw new InvalidCastException($"{vs} can't cast to datetime"); + throw new InvalidCastException($"{vs} cannot be cast to DateTime"); } else if (pInfo.ExcludeNullableType == typeof(TimeSpan)) { @@ -153,7 +153,12 @@ public static bool IsNumericType(Type type, bool isNullableUnderlyingType = fals else if (double.TryParse(vs, NumberStyles.None, CultureInfo.InvariantCulture, out var _d)) newValue = TimeSpan.FromMilliseconds(_d); else - throw new InvalidCastException($"{vs} can't cast to TimeSpan"); + throw new InvalidCastException($"{vs} cannot be cast to TimeSpan"); + } + else if (pInfo.ExcludeNullableType == typeof(double)) // && (!Regex.IsMatch(itemValue.ToString(), @"^-?\d+(\.\d+)?([eE][-+]?\d+)?$") || itemValue.ToString().Trim().Equals("NaN"))) + { + var invariantString = Convert.ToString(itemValue, CultureInfo.InvariantCulture); + newValue = double.TryParse(invariantString, NumberStyles.Any, CultureInfo.InvariantCulture, out var _v2) ? _v2 : double.NaN; } else if (pInfo.ExcludeNullableType == typeof(bool)) { @@ -204,6 +209,5 @@ public static bool IsAsyncEnumerable(this Type type, out Type genericArgument) return genericArgument != null; } #endif - } } diff --git a/src/MiniExcel/Utils/XmlReaderHelper.cs b/src/MiniExcel/Utils/XmlReaderHelper.cs index bc63b472..5b03e5e5 100644 --- a/src/MiniExcel/Utils/XmlReaderHelper.cs +++ b/src/MiniExcel/Utils/XmlReaderHelper.cs @@ -9,7 +9,7 @@ namespace MiniExcelLibs.Utils internal static class XmlReaderHelper { /// - /// Pass and + /// Pass <?xml> and <worksheet> /// /// public static void PassXmlDeclartionAndWorksheet(this XmlReader reader) @@ -26,7 +26,7 @@ public static void SkipToNextSameLevelDom(XmlReader reader) { while (!reader.EOF) { - if (!XmlReaderHelper.SkipContent(reader)) + if (!SkipContent(reader)) break; } } @@ -65,36 +65,29 @@ public static bool IsStartElement(XmlReader reader, string name, params string[] public static string GetAttribute(XmlReader reader, string name, params string[] nss) { - foreach (var ns in nss) - { - var attribute = reader.GetAttribute(name, ns); - if (attribute != null) - { - return attribute; - } - } - - return null; + return nss + .Select(ns => reader.GetAttribute(name, ns)) + .FirstOrDefault(at => at != null); } public static IEnumerable GetSharedStrings(Stream stream, params string[] nss) { using (var reader = XmlReader.Create(stream)) { - if (!XmlReaderHelper.IsStartElement(reader, "sst", nss)) + if (!IsStartElement(reader, "sst", nss)) yield break; - if (!XmlReaderHelper.ReadFirstContent(reader)) + if (!ReadFirstContent(reader)) yield break; while (!reader.EOF) { - if (XmlReaderHelper.IsStartElement(reader, "si", nss)) + if (IsStartElement(reader, "si", nss)) { var value = StringHelper.ReadStringItem(reader); yield return value; } - else if (!XmlReaderHelper.SkipContent(reader)) + else if (!SkipContent(reader)) { break; } diff --git a/tests/MiniExcelTests/MiniExcelIssueTests.cs b/tests/MiniExcelTests/MiniExcelIssueTests.cs index 2ddc4893..7cb626f8 100644 --- a/tests/MiniExcelTests/MiniExcelIssueTests.cs +++ b/tests/MiniExcelTests/MiniExcelIssueTests.cs @@ -1190,7 +1190,7 @@ public void TestIssue209() Assert.Equal(4, ex.Row); Assert.Equal("Error", ex.Value); Assert.Equal(typeof(int), ex.InvalidCastType); - Assert.Equal("ColumnName : SEQ, CellRow : 4, Value : Error, it can't cast to Int32 type.", ex.Message); + Assert.Equal("ColumnName: SEQ, CellRow: 4, Value: Error. The value cannot be cast to type Int32.", ex.Message); } } @@ -1739,7 +1739,7 @@ public void TestIssueI3X2ZL() catch (InvalidCastException ex) { Assert.Equal( - "ColumnName : Col2, CellRow : 6, Value : error, it can't cast to DateTime type.", + "ColumnName: Col2, CellRow: 6, Value: error. The value cannot be cast to type DateTime.", ex.Message ); } @@ -1752,7 +1752,7 @@ public void TestIssueI3X2ZL() catch (InvalidCastException ex) { Assert.Equal( - "ColumnName : Col1, CellRow : 3, Value : error, it can't cast to Int32 type.", + "ColumnName: Col1, CellRow: 3, Value: error. The value cannot be cast to type Int32.", ex.Message ); }