Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/MiniExcel.OpenXml/Templates/OpenXmlValueExtractor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ public class OpenXmlValueExtractor : IInputValueExtractor
{
var type = valueObject.GetType();

//todo: consider throwing an exception if a property has indexer instead of silently ignoring it
var propertyValues = type
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(property => property.CanRead && property.GetIndexParameters().Length == 0)
.Select(property => new { property.Name, Value = property.GetValue(valueObject) });

var fieldValues = type
Expand Down
21 changes: 12 additions & 9 deletions src/MiniExcel.OpenXml/Utils/CalcChainHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,18 @@

internal static partial class CalcChainHelper
{

// The calcChain.xml file in an Excel file (in the xl folder) is an XML file that stores the calculation chain for the workbook.
// The calculation chain specifies the order in which cells should be recalculated in order to update all formulas in the workbook correctly.
// It should include a series of <c> elements, each of which represents a cell in the workbook that contains a formula.
// Each <c> element should have a r attribute that specifies the cell's address (e.g., "A1" or "B2").
// The <c> element should also have a i attribute that specifies the index of the formula in the formulas collection (in the workbook's sheet data file).
// https://learn.microsoft.com/en-us/dotnet/api/documentformat.openxml.spreadsheet.calculationchain?view=openxml-2.8.1
public static string GetCalcChainContent( List<string> cellRefs, int sheetIndex ) {

public static string GetCalcChainContent(List<string> cellRefs, int sheetIndex )
{
var calcChainContent = new StringBuilder();
foreach (var cr in cellRefs)
{
calcChainContent.Append($"""<c r="{cr}" i="{sheetIndex}"/>""" );
calcChainContent.Append($"""<c r="{cr}" i="{sheetIndex}"/>""");
}

return calcChainContent.ToString();
Expand All @@ -23,11 +22,15 @@ public static string GetCalcChainContent( List<string> cellRefs, int sheetIndex
[CreateSyncVersion]
public static async Task GenerateCalcChainSheetAsync(Stream calcChainStream, string calcChainContent, CancellationToken cancellationToken = default)
{
var content = $"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><calcChain xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">{calcChainContent}</calcChain>";

#if NET8_0_OR_GREATER
var writer = new StreamWriter(calcChainStream, Encoding.UTF8);
await using var disposableWriter = writer.ConfigureAwait(false);
await writer.WriteAsync(content.AsMemory(), cancellationToken).ConfigureAwait(false);
#else
using var writer = new StreamWriter(calcChainStream, Encoding.UTF8);
await writer.WriteAsync($"""<?xml version="1.0" encoding="UTF-8" standalone="yes"?><calcChain xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">{calcChainContent}</calcChain>"""
#if NET7_0_OR_GREATER
.AsMemory(), cancellationToken
#endif
).ConfigureAwait(false);
await writer.WriteAsync(content).ConfigureAwait(false);
#endif
}
}
28 changes: 28 additions & 0 deletions tests/MiniExcel.OpenXml.Tests/MiniExcelIssueAsyncTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1476,4 +1476,32 @@ private class Issue138ExcelRow
public double? 波段 { get; set; }
public double? 當沖 { get; set; }
}

[Fact]
public async Task TestIssue951()
{
var templatePath = PathHelper.GetFile("xlsx/TestTemplateEasyFill.xlsx");
using var path = AutoDeletingPath.Create();

var value = new Issue951
{
Name = "Jack",
CreateDate = new DateTime(2021, 01, 01),
VIP = true,
Points = 123
};

// must not throw
await _excelTemplater.FillTemplateAsync(path.ToString(), templatePath, value);
}

class Issue951
{
public string? Name { get; set; }
public DateTime CreateDate { get; set; }
public bool VIP { get; set; }
public double Points { get; set; }

public object this[string test] => new();
}
}
28 changes: 28 additions & 0 deletions tests/MiniExcel.OpenXml.Tests/MiniExcelIssueTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3827,4 +3827,32 @@ public void TestIssue915()
Assert.Equal(7.4, result[1].Altitude);
Assert.Equal(8.6, result[2].Altitude);
}

[Fact]
public void TestIssue951()
{
var templatePath = PathHelper.GetFile("xlsx/TestTemplateEasyFill.xlsx");
using var path = AutoDeletingPath.Create();

var value = new Issue951
{
Name = "Jack",
CreateDate = new DateTime(2021, 01, 01),
VIP = true,
Points = 123
};

// must not throw
_excelTemplater.FillTemplate(path.ToString(), templatePath, value);
}

class Issue951
{
public string? Name { get; set; }
public DateTime CreateDate { get; set; }
public bool VIP { get; set; }
public double Points { get; set; }

public object this[string test] => new();
}
}
Loading