add $= formula handling with $enumrowstart/end placeholder replacments (#621)

Co-authored-by: meld-cp <18450687+meld-cp@users.noreply.github.com>
This commit is contained in:
meld-cp 2024-07-05 23:27:03 +12:00 committed by Wei Lin
parent b3a980cf2a
commit 1caf3fee3b
3 changed files with 62 additions and 0 deletions

View File

@ -304,6 +304,10 @@ namespace MiniExcelLibs.OpenXml
int rowIndexDiff = 0;
var rowXml = new StringBuilder();
// for formula cells
int enumrowstart = -1;
int enumrowend = -1;
// for grouped cells
bool groupingStarted = false;
bool hasEverGroupStarted = false;
@ -410,6 +414,7 @@ namespace MiniExcelLibs.OpenXml
{
var first = true;
var iEnumerableIndex = 0;
enumrowstart = newRowIndex;
foreach (var item in rowInfo.CellIEnumerableValues)
{
@ -732,14 +737,43 @@ namespace MiniExcelLibs.OpenXml
}
}
enumrowend = newRowIndex-1;
}
else
{
// convert cells starting with '$=' into formulas
var cs = row.SelectNodes($"x:c", _ns);
foreach (XmlElement c in cs)
{
/* Target:
<c r="C8" s="3">
<f>SUM(C2:C7)</f>
</c>
*/
var vs = c.SelectNodes($"x:v", _ns);
foreach (XmlElement v in vs)
{
if (!v.InnerText.StartsWith("$="))
{
continue;
}
var fNode = c.OwnerDocument.CreateElement("f", Config.SpreadsheetmlXmlns);
fNode.InnerText = v.InnerText.Substring(2);
c.InsertBefore(fNode, v);
c.RemoveChild(v);
}
}
innerXml = row.InnerXml;
rowXml.Clear()
.Append(outerXmlOpen)
.AppendFormat(@" r=""{0}"">", newRowIndex)
.Append(innerXml)
.Replace($"{{{{$rowindex}}}}", newRowIndex.ToString())
.Replace($"{{{{$enumrowstart}}}}", enumrowstart.ToString())
.Replace($"{{{{$enumrowend}}}}", enumrowend.ToString())
.AppendFormat("</{0}>", row.Name);
writer.Write(CleanXml(rowXml, endPrefix)); // pass StringBuilder for netcoreapp3.0 or above

View File

@ -721,6 +721,34 @@ namespace MiniExcelTests
}
}
[Fact]
public void TestIEnumerableWithFormulas()
{
{
var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.xlsx");
var templatePath = @"../../../../../samples/xlsx/TestTemplateBasicIEnumerableFillWithFormulas.xlsx";
//1. By POCO
var value = new
{
employees = new[]
{
new {name="Jack",department="HR", salary= 90000},
new {name="Lisa",department="HR", salary=150000},
new {name="John",department="HR", salary= 64000},
new {name="Mike",department="IT", salary= 87000},
new {name="Neo", department="IT", salary= 98000},
new {name="Joan",department="IT", salary=120000}
}
};
MiniExcel.SaveAsByTemplate(path, templatePath, value);
var dimension = Helpers.GetFirstSheetDimensionRefValue(path);
Assert.Equal("A1:C13", dimension);
}
}
[Fact]
public void TemplateTest()
{