13 İşlemeler f24992cae3 ... fb0d9f638b

Yazar SHA1 Mesaj Tarih
  Piotr Czajkowski fb0d9f638b It needs a version bump 10 ay önce
  Piotr Czajkowski 2964cedb09 Info about 2.9.0 10 ay önce
  Piotr Czajkowski 021af2943b Added ToObject_EnumAsString 10 ay önce
  Piotr Czajkowski 3360e5e219 Added ToObject_GuidAsString 10 ay önce
  Piotr Czajkowski 19965eb4b1 A bit of order 10 ay önce
  Piotr Czajkowski 553f4b1b2a Cleanup 10 ay önce
  Piotr Czajkowski a22f65a4dc Added ToObject_DateOnlyAsString 10 ay önce
  Piotr Czajkowski 5ef833a4b3 Added ToObject_DateTimeAsString 10 ay önce
  Piotr Czajkowski ccc9baa162 Added HandleEnum 10 ay önce
  Piotr Czajkowski 7c2619e145 Added HandleGuid 10 ay önce
  Piotr Czajkowski 9fcc40f009 Added info on 2.8.1 11 ay önce
  Piotr Czajkowski c4002192fc Cosmetics 11 ay önce
  Piotr Czajkowski 3c334d6169 Added WriteWithStartFrom 11 ay önce

+ 3 - 2
ExcelORM/ExcelORM/ExcelORM.csproj

@@ -4,7 +4,7 @@
         <TargetFramework>net8.0</TargetFramework>
         <ImplicitUsings>enable</ImplicitUsings>
         <Nullable>enable</Nullable>
-        <Version>2.8.0</Version>
+        <Version>3.0.0</Version>
         <PackageProjectUrl>https://git.liox.eu/pczajkowski/ExcelORM</PackageProjectUrl>
         <RepositoryUrl>https://github.com/pczajkowski/ExcelORM</RepositoryUrl>
         <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
@@ -14,7 +14,8 @@
 	<Authors>Piotr Czajkowski</Authors>
 	<Description>Simple library to read/write C# objects from/to Excel files. </Description>
 	<RepositoryType>GitHub</RepositoryType>
-	<PackageReleaseNotes>Handling more number types. Properly handling appending to and reading from empty file.</PackageReleaseNotes>
+	<PackageReleaseNotes>Ability to start writing from given row.
+Trying to handle dates saved as text without throwing.</PackageReleaseNotes>
     </PropertyGroup>
 
     <ItemGroup>

+ 13 - 9
ExcelORM/ExcelORM/ExcelWriter.cs

@@ -19,9 +19,9 @@ public class ExcelWriter : IDisposable
         xlWorkbook = workbook ?? throw new ArgumentNullException(nameof(workbook));
     }
 
-    private static int GenerateHeader(IXLWorksheet worksheet, PropertyInfo[] properties)
+    private static int GenerateHeader(IXLWorksheet worksheet, PropertyInfo[] properties, uint? startFrom = null)
     {
-        var rowIndex = 1;
+        var rowIndex = startFrom == null ? 1 : (int)startFrom.Value;
         var cellIndex = 1;
         foreach (var property in properties)
         {
@@ -77,19 +77,23 @@ public class ExcelWriter : IDisposable
         }
     }
 
-    private static void Write<T>(IEnumerable<T> values, IXLWorksheet worksheet, bool append, uint? headerRowIndex = null, uint? appendFrom = null) where T : class
+    private static void Write<T>(IEnumerable<T> values, IXLWorksheet worksheet, bool append, uint? headerRowIndex = null, uint? startFrom = null) where T : class
     {
         var properties = typeof(T).GetProperties();
         List<Mapping>? mapping = [];
 
         var lastRow = worksheet.LastRowUsed();
-        if (lastRow == null) append = false;
+        if (lastRow == null)
+        {
+            append = false;
+            lastRow = worksheet.FirstRow();
+        }
         
-        var rowIndex = (append, startFrom: appendFrom) switch
+        var rowIndex = (append, startFrom) switch
         { 
-            (true, not null) => (int)appendFrom,
+            (true, not null) => (int)startFrom,
             (true, null) => lastRow.RowNumber() + 1,
-            _ => GenerateHeader(worksheet, properties) 
+            _ => GenerateHeader(worksheet, properties, startFrom) 
         };
 
         if (append)
@@ -108,7 +112,7 @@ public class ExcelWriter : IDisposable
         }
     }
 
-    public void Write<T>(IEnumerable<T> values, string? worksheetName = null, bool append = false, uint? headerRowIndex = null, uint? appendFrom = null) where T : class
+    public void Write<T>(IEnumerable<T> values, string? worksheetName = null, bool append = false, uint? headerRowIndex = null, uint? startFrom = null) where T : class
     {
         var xlWorksheet = xlWorkbook.Worksheets.FirstOrDefault(x => x.Name.Equals(worksheetName, StringComparison.InvariantCultureIgnoreCase));
         
@@ -116,7 +120,7 @@ public class ExcelWriter : IDisposable
             xlWorkbook.AddWorksheet(worksheetName)
             : xlWorkbook.Worksheets.Count == 0 ? xlWorkbook.AddWorksheet() : xlWorkbook.Worksheets.First();
 
-        Write(values, xlWorksheet, append, headerRowIndex, appendFrom);
+        Write(values, xlWorksheet, append, headerRowIndex, startFrom);
     }
 
     public void SaveAs(string path, IExcelConverter? converter = null)

+ 28 - 16
ExcelORM/ExcelORM/TypeExtensions.cs

@@ -7,31 +7,43 @@ namespace ExcelORM;
 
 public static class TypeExtensions
 {
+    private static object? HandleGuid(XLCellValue value, PropertyInfo property)
+    {
+        if (Guid.TryParse(value.GetText(), out var guid))
+            return guid;
+
+        if (property.PropertyType == typeof(Guid?)) return null;
+        return Guid.Empty; 
+    }
+
+    private static object? HandleEnum(XLCellValue value, PropertyInfo property, Type? nullableUnderlyingType)
+    {
+        if (nullableUnderlyingType != null)
+        {
+            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();
         
         if (property.PropertyType == typeof(Guid) || property.PropertyType == typeof(Guid?))
-        {
-            if (Guid.TryParse(value.GetText(), out var guid))
-                return guid;
+            return HandleGuid(value, property);
 
-            if (property.PropertyType == typeof(Guid?)) return null;
-            return Guid.Empty;
-        }
+        if (property.PropertyType == typeof(DateTime) || property.PropertyType == typeof(DateTime?))
+            return DateTime.TryParse(value.GetText(), out var dateTime) ? dateTime : default;
 
-        if (property.PropertyType.IsEnum)
-        {
-            return Enum.TryParse(property.PropertyType, value.GetText(), true, out var enumValue)
-                ? enumValue : Enum.GetValues(property.PropertyType).GetValue(0);
-        }
+        if (property.PropertyType == typeof(DateOnly) || property.PropertyType == typeof(DateOnly?))
+            return DateOnly.TryParse(value.GetText(), out var dateOnly) ? dateOnly : default;
 
         var nullableUnderlyingType = Nullable.GetUnderlyingType(property.PropertyType);
-        if (nullableUnderlyingType is { IsEnum: true })
-        {
-            return Enum.TryParse(nullableUnderlyingType, value.GetText(), true, out var enumValue)
-                ? enumValue : null;
-        }
+        if (property.PropertyType.IsEnum || (nullableUnderlyingType is { IsEnum: true }))
+            return HandleEnum(value, property, nullableUnderlyingType);
         
         return value.GetText(); 
     }

+ 0 - 3
ExcelORM/ExcelORMTests/ExcelORMTests.csproj

@@ -53,9 +53,6 @@
       <None Update="testFiles\withFormula.xlsx">
         <CopyToOutputDirectory>Always</CopyToOutputDirectory>
       </None>
-      <None Update="testFiles\badDate.xlsx">
-        <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-      </None>
       <None Update="testFiles\forAppendWithRubbish.xlsx">
         <CopyToOutputDirectory>Always</CopyToOutputDirectory>
       </None>

+ 0 - 0
ExcelORM/ExcelORMTests/Test.cs → ExcelORM/ExcelORMTests/Models/Test.cs


+ 0 - 0
ExcelORM/ExcelORMTests/TestAdditionalTypes.cs → ExcelORM/ExcelORMTests/Models/TestAdditionalTypes.cs


+ 0 - 0
ExcelORM/ExcelORMTests/TestAdditionalTypesNullable.cs → ExcelORM/ExcelORMTests/Models/TestAdditionalTypesNullable.cs


+ 0 - 0
ExcelORM/ExcelORMTests/TestEnum.cs → ExcelORM/ExcelORMTests/Models/TestEnum.cs


+ 0 - 0
ExcelORM/ExcelORMTests/TestNumbersWithFormula.cs → ExcelORM/ExcelORMTests/Models/TestNumbersWithFormula.cs


+ 0 - 0
ExcelORM/ExcelORMTests/TestSkip.cs → ExcelORM/ExcelORMTests/Models/TestSkip.cs


+ 0 - 0
ExcelORM/ExcelORMTests/TestSkipMiddle.cs → ExcelORM/ExcelORMTests/Models/TestSkipMiddle.cs


+ 0 - 0
ExcelORM/ExcelORMTests/TestTypes.cs → ExcelORM/ExcelORMTests/Models/TestTypes.cs


+ 0 - 0
ExcelORM/ExcelORMTests/TestWithFormula.cs → ExcelORM/ExcelORMTests/Models/TestWithFormula.cs


+ 0 - 0
ExcelORM/ExcelORMTests/TestWithHyperlink.cs → ExcelORM/ExcelORMTests/Models/TestWithHyperlink.cs


+ 0 - 9
ExcelORM/ExcelORMTests/ReaderTests.cs

@@ -11,7 +11,6 @@ public class ReaderTests
     private const string MultipleSheetsFile = "testFiles/multipleSheets.xlsx";
     private const string DifferentTypesFile = "testFiles/differentTypes.xlsx";
     private const string WithFormulaFile = "testFiles/withFormula.xlsx";
-    private const string BadDate = "testFiles/badDate.xlsx";
     private const string AdditionalTypes = "testFiles/additionalTypes.xlsx";
     
     [Fact]
@@ -112,14 +111,6 @@ public class ReaderTests
         Assert.NotEmpty(results);
     }
     
-    [Fact]
-    public void BadDateThrows()
-    {
-        using var reader = new ExcelReader(BadDate);
-        var exception = Assert.Throws<ArgumentException>(() => reader.Read<TestTypes>().ToArray());
-        Assert.Contains("Location", exception.Message);
-    }
-    
     [Fact]
     public void ReadAdditionalTypes()
     {

+ 57 - 0
ExcelORM/ExcelORMTests/TypeExtensionsTests.cs

@@ -0,0 +1,57 @@
+using ClosedXML.Excel;
+using ExcelORM;
+
+namespace ExcelORMTests;
+
+public class TypeExtensionsTests
+{
+    public DateTime? DateTimeProperty { get; set; }
+    
+    [Fact]
+    public void ToObject_DateTimeAsString()
+    {
+        XLCellValue value = "7/27/2025";
+        
+        var propertyInfo = typeof(TypeExtensionsTests).GetProperty("DateTimeProperty");
+        var readValue = value.ToObject(propertyInfo);
+        Assert.IsType<DateTime>(readValue);
+    }
+    
+    public DateOnly? DateOnlyProperty { get; set; }
+    
+    [Fact]
+    public void ToObject_DateOnlyAsString()
+    {
+        XLCellValue value = "7/27/2025";
+        
+        var propertyInfo = typeof(TypeExtensionsTests).GetProperty("DateOnlyProperty");
+        var readValue = value.ToObject(propertyInfo);
+        Assert.IsType<DateOnly>(readValue);
+    }
+     
+    public Guid? GuidProperty { get; set; }
+    
+    [Fact]
+    public void ToObject_GuidAsString()
+    {
+        XLCellValue value = "00000000-0000-0000-0000-000000000001";
+        
+        var propertyInfo = typeof(TypeExtensionsTests).GetProperty("GuidProperty");
+        var readValue = value.ToObject(propertyInfo);
+        Assert.IsType<Guid>(readValue);
+        Assert.NotEqual(Guid.Empty, readValue);
+    }
+     
+    public TestEnum? EnumProperty { get; set; }
+    
+    [Fact]
+    public void ToObject_EnumAsString()
+    {
+        XLCellValue value = "Second";
+        
+        var propertyInfo = typeof(TypeExtensionsTests).GetProperty("EnumProperty");
+        var readValue = value.ToObject(propertyInfo);
+        Assert.IsType<TestEnum>(readValue);
+        Assert.NotEqual(TestEnum.First, readValue);
+    }
+}

+ 20 - 1
ExcelORM/ExcelORMTests/WriterTests.cs

@@ -101,7 +101,7 @@ public class WriterTests
 
         uint headerRowIndex = 3;
         using var writer = new ExcelWriter(testFile);
-        writer.Write(ArrayOfThree, append: true, headerRowIndex: headerRowIndex, appendFrom: 7);
+        writer.Write(ArrayOfThree, append: true, headerRowIndex: headerRowIndex, startFrom: 7);
         writer.SaveAs(testFile);
 
         using var reader = new ExcelReader(testFile);
@@ -362,4 +362,23 @@ public class WriterTests
         for (int i = 0; i < readArray.Length; i++)
             Assert.Equal(ArrayOfThree[i], readArray[i]);
     }
+    
+    [Fact]
+    public void WriteWithStartFrom()
+    {
+        var testFile = Path.GetRandomFileName();
+        testFile = Path.ChangeExtension(testFile, "xlsx");
+
+        const string worksheetName = "Test";
+        using var writer = new ExcelWriter(testFile);
+        writer.Write(ArrayOfThree, worksheetName);
+        writer.Write(ListOfTwo, worksheetName, startFrom: (uint)(ArrayOfThree.Length + 3));
+        writer.SaveAs(testFile);
+
+        using var reader = new ExcelReader(testFile);
+        var readArray = reader.Read<Test>(worksheetName).ToArray();
+        Assert.Equal(6, readArray.Length);
+        
+        File.Delete(testFile);
+    }
 }

BIN
ExcelORM/ExcelORMTests/testFiles/badDate.xlsx


+ 2 - 1
versions.md

@@ -8,4 +8,5 @@
 | 2.5.0 | Added Location to ArgumentException Message in ExcelReader. It'll show address of affected cell and the worksheet's name.|
 | 2.6.0 | Added support for appending starting from given row.|
 | 2.7.0 | Added support for reading properties of type Guid and enum.|
-| 2.8.0 | Handling more number types. Properly handling appending to and reading from empty file.
+| 2.8.0 | Handling more number types. Properly handling appending to and reading from empty file.|
+| 3.0.0 | Ability to start writing from given row. Trying to handle dates saved as text without throwing.|