8 コミット ecc3e8591d ... 509116a88e

作者 SHA1 メッセージ 日付
  Piotr Czajkowski 509116a88e Modified notes 3 週間 前
  Piotr Czajkowski c4b38364d4 Updated dependencies 3 週間 前
  Piotr Czajkowski ce6873718a Let's be safe 4 ヶ月 前
  Piotr Czajkowski 14a0f417d6 Clearer 4 ヶ月 前
  Piotr Czajkowski 9db4a5b7b7 Redundant 4 ヶ月 前
  Piotr Czajkowski 4620baefea Cosmetics 4 ヶ月 前
  Piotr Czajkowski 88d36c7967 Simpler 4 ヶ月 前
  Piotr Czajkowski bb2a474c83 Additional checks 9 ヶ月 前

+ 3 - 4
ExcelORM/ExcelORM/ExcelDynamicReader.cs

@@ -3,7 +3,7 @@ using ExcelORM.Models;
 
 namespace ExcelORM;
 
-public class ExcelDynamicReader : IDisposable
+public sealed class ExcelDynamicReader : IDisposable
 {
     private readonly IXLWorkbook xlWorkbook;
     public bool SkipHidden { get; set; }
@@ -14,7 +14,7 @@ public class ExcelDynamicReader : IDisposable
         xlWorkbook = new XLWorkbook(path);
     }
 
-    public ExcelDynamicReader(IXLWorkbook workbook)
+    public ExcelDynamicReader(IXLWorkbook? workbook)
     {
         xlWorkbook = workbook ?? throw new ArgumentNullException(nameof(workbook));
     }
@@ -35,7 +35,6 @@ public class ExcelDynamicReader : IDisposable
                     continue;
                 }
 
-                item.Type ??= cell.Value.ValueType();
                 var cellItem = item with
                 {
                     Value = cell.Value.ToObject()
@@ -113,7 +112,7 @@ public class ExcelDynamicReader : IDisposable
         GC.SuppressFinalize(this);
     }
 
-    protected virtual void Dispose(bool disposing)
+    private void Dispose(bool disposing)
     {
         if (disposing)
         {

+ 10 - 5
ExcelORM/ExcelORM/ExcelDynamicWriter.cs

@@ -12,7 +12,7 @@ public class ExcelDynamicWriter : IDisposable
         xlWorkbook = File.Exists(path) ? new XLWorkbook(path) : new XLWorkbook();
     }
 
-    public ExcelDynamicWriter(IXLWorkbook workbook)
+    public ExcelDynamicWriter(IXLWorkbook? workbook)
     {
         xlWorkbook = workbook ?? throw new ArgumentNullException(nameof(workbook));
     }
@@ -29,15 +29,20 @@ public class ExcelDynamicWriter : IDisposable
     private static void Write(IEnumerable<List<DynamicCell>> values, IXLWorksheet worksheet, bool append)
     {
         var lastRow = worksheet.LastRowUsed();
-        if (lastRow == null) append = false;
-        
+        if (lastRow == null)
+        {
+            append = false;
+            lastRow = worksheet.FirstRow();
+        }
+
+        var valuesList = values.ToList();
         var rowIndex = append switch
         {
             true => lastRow.RowNumber() + 1,
-            false => GenerateHeader(worksheet, values.First()),
+            false => GenerateHeader(worksheet, valuesList.First()),
         };
 
-        foreach (var row in values)
+        foreach (var row in valuesList)
         {
             foreach (var cell in row)
             {

+ 3 - 4
ExcelORM/ExcelORM/ExcelORM.csproj

@@ -4,7 +4,7 @@
         <TargetFramework>net8.0</TargetFramework>
         <ImplicitUsings>enable</ImplicitUsings>
         <Nullable>enable</Nullable>
-        <Version>3.0.0</Version>
+        <Version>3.0.1</Version>
         <PackageProjectUrl>https://git.liox.eu/pczajkowski/ExcelORM</PackageProjectUrl>
         <RepositoryUrl>https://github.com/pczajkowski/ExcelORM</RepositoryUrl>
         <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
@@ -14,12 +14,11 @@
 	<Authors>Piotr Czajkowski</Authors>
 	<Description>Simple library to read/write C# objects from/to Excel files. </Description>
 	<RepositoryType>GitHub</RepositoryType>
-	<PackageReleaseNotes>Ability to start writing from given row.
-Trying to handle dates saved as text without throwing.</PackageReleaseNotes>
+	<PackageReleaseNotes>Few cosmetic changes and updated to ClosedXML 0.105.1.</PackageReleaseNotes>
     </PropertyGroup>
 
     <ItemGroup>
-	    <PackageReference Include="ClosedXML" Version="0.105.0" />
+	    <PackageReference Include="ClosedXML" Version="0.105.1" />
 	    <None Include="../../README.md" Pack="true" PackagePath="\" />
 	    <None Include="../../LICENSE" Pack="true" PackagePath="" />
     </ItemGroup>

+ 1 - 1
ExcelORM/ExcelORM/ExcelReader.cs

@@ -10,7 +10,7 @@ public class ExcelReader : IDisposable
     public bool SkipHidden { get; set; }
     public bool ObeyFilter { get; set; }
 
-    public ExcelReader(IXLWorkbook workbook)
+    public ExcelReader(IXLWorkbook? workbook)
     {
         xlWorkbook = workbook ?? throw new ArgumentNullException(nameof(workbook));
     }

+ 1 - 1
ExcelORM/ExcelORM/ExcelWriter.cs

@@ -14,7 +14,7 @@ public class ExcelWriter : IDisposable
         xlWorkbook = File.Exists(path) ? new XLWorkbook(path) : new XLWorkbook();
     }
 
-    public ExcelWriter(IXLWorkbook workbook)
+    public ExcelWriter(IXLWorkbook? workbook)
     {
         xlWorkbook = workbook ?? throw new ArgumentNullException(nameof(workbook));
     }

+ 11 - 1
ExcelORM/ExcelORM/Models/DynamicCell.cs

@@ -7,7 +7,17 @@ namespace ExcelORM.Models
         public int Position { get; set; }
         public string? Header { get; set; }
         public Type? Type { get; set; }
-        public object? Value { get; set; }
+
+        private object? value;
+        public object? Value
+        {
+            get => value;
+            set
+            {
+                this.value = value;
+                Type = value?.GetType();
+            }
+        }
 
         public static List<DynamicCell>? MapHeader(IXLCells? headerCells)
         {

+ 29 - 27
ExcelORM/ExcelORM/TypeExtensions.cs

@@ -13,7 +13,7 @@ public static class TypeExtensions
             return guid;
 
         if (property.PropertyType == typeof(Guid?)) return null;
-        return Guid.Empty; 
+        return Guid.Empty;
     }
 
     private static object? HandleEnum(XLCellValue value, PropertyInfo property, Type? nullableUnderlyingType)
@@ -23,11 +23,11 @@ public static class TypeExtensions
             return Enum.TryParse(nullableUnderlyingType, value.GetText(), true, out var enumNullableValue)
                 ? enumNullableValue : null;
         }
-        
+
         return Enum.TryParse(property.PropertyType, value.GetText(), true, out var enumValue)
             ? enumValue : Enum.GetValues(property.PropertyType).GetValue(0);
-    } 
-    
+    }
+
     private static object? GetAdditionalTypeFromText(XLCellValue value, PropertyInfo? property = null)
     {
         if (property == null) return value.GetText();
@@ -38,15 +38,17 @@ public static class TypeExtensions
             case var _ when pt == typeof(Guid) || pt == typeof(Guid?):
                 return HandleGuid(value, property);
             case var _ when pt == typeof(DateTime) || pt == typeof(DateTime?):
-                return DateTime.TryParse(value.GetText(), out var dateValue) ? dateValue : default;
+                DateTime.TryParse(value.GetText(), out var dateValue);
+                return dateValue;
             case var _ when pt == typeof(DateOnly) || pt == typeof(DateOnly?):
-                return DateOnly.TryParse(value.GetText(), out var dateOnlyValue) ? dateOnlyValue : default;
+                DateOnly.TryParse(value.GetText(), out var dateOnlyValue);
+                return dateOnlyValue;
             case { IsEnum: true }:
             case var _ when Nullable.GetUnderlyingType(pt) is { IsEnum: true }:
                 return HandleEnum(value, property, Nullable.GetUnderlyingType(property.PropertyType));
         }
-        
-        return value.GetText(); 
+
+        return value.GetText();
     }
 
     private static object? GetSpecificNumberType(XLCellValue value, PropertyInfo? property)
@@ -71,7 +73,7 @@ public static class TypeExtensions
             throw;
         }
     }
-    
+
     // Borrowed from https://github.com/ClosedXML/ClosedXML/blob/develop/ClosedXML/Excel/XLCellValue.cs#L361
     public static object? ToObject(this XLCellValue value, PropertyInfo? property = null)
     {
@@ -88,33 +90,33 @@ public static class TypeExtensions
         };
     }
 
-    public static Type ValueType(this XLCellValue value)
-    {
-        return value.Type switch
-        {
-            XLDataType.Blank => typeof(string),
-            XLDataType.Boolean => typeof(bool),
-            XLDataType.Number => typeof(double?),
-            XLDataType.Text => typeof(string),
-            XLDataType.DateTime => typeof(DateTime?),
-            XLDataType.TimeSpan => typeof(TimeSpan?),
-            _ => throw new InvalidCastException()
-        };
-    }
-
     public static void SetPropertyValue<T>(this T currentObject, PropertyInfo property, XLCellValue value)
     {
         var valueToSet = value.ToObject(property);
-        if (valueToSet == null) return;
 
         try
         {
             property.SetValue(currentObject, valueToSet);
         }
-        catch
+        catch (ArgumentException ex) // Catches issues like type mismatch or null for non-nullable
         {
-            valueToSet = value.ToString();
-            property.SetValue(currentObject, valueToSet);
+            // If the property type is string, try to set it directly from the XLCellValue's string representation.
+            if (property.PropertyType == typeof(string))
+            {
+                property.SetValue(currentObject, value.ToString());
+            }
+            else
+            {
+                // If it's not a string property, and the initial assignment failed,
+                // re-throw with more context.
+                throw new InvalidCastException($"Could not set property '{property.Name}' of type '{property.PropertyType.Name}' with value '{valueToSet}' (original XLCellValue: '{value}'). " +
+                                               $"The value returned by ToObject was incompatible, and the property type is not string for fallback conversion. See inner exception for details.", ex);
+            }
+        }
+        catch (Exception ex) // Catch any other unexpected exceptions from SetValue
+        {
+            throw new InvalidOperationException($"An unexpected error occurred while setting property '{property.Name}' of type '{property.PropertyType.Name}'. " +
+                                                $"Value attempted to set: '{valueToSet}' (original XLCellValue: '{value}'). See inner exception for details.", ex);
         }
     }
 

+ 4 - 4
ExcelORM/ExcelORMTests/DynamicReaderTests.cs

@@ -26,10 +26,10 @@ public class DynamicReaderTests
 
         var first = results.First();
         Assert.Equal(typeof(string), first[0].Type);
-        Assert.Equal(typeof(DateTime?), first[1].Type);
-        Assert.Equal(typeof(TimeSpan?), first[2].Type);
-        Assert.Equal(typeof(double?), first[3].Type);
-        Assert.Equal(typeof(double?), first[4].Type);
+        Assert.Equal(typeof(DateTime), first[1].Type);
+        Assert.Equal(typeof(TimeSpan), first[2].Type);
+        Assert.Equal(typeof(double), first[3].Type);
+        Assert.Equal(typeof(double), first[4].Type);
     }
 
     [Fact]

+ 2 - 2
ExcelORM/ExcelORMTests/ExcelORMTests.csproj

@@ -10,13 +10,13 @@
     </PropertyGroup>
 
     <ItemGroup>
-        <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
+        <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.9.0" />
         <PackageReference Include="xunit" Version="2.9.3" />
         <PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
             <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
             <PrivateAssets>all</PrivateAssets>
         </PackageReference>
-        <PackageReference Include="coverlet.collector" Version="6.0.4">
+        <PackageReference Include="coverlet.collector" Version="10.0.1">
             <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
             <PrivateAssets>all</PrivateAssets>
         </PackageReference>