fix: write data bar cfvo as min/max instead of num for lowest/highest value
DataBar().LowestValue()/HighestValue() emitted the x14 extension cfvo nodes as type="num" with a formula of 0 instead of type="min"/"max". Strict readers such as WPS Spreadsheets honor that value and lock the bar thresholds to 0, so the data bar renders incorrectly. The extension converter unconditionally overwrote the cfvo type with Numeric whenever a threshold value was present. LowestValue()/HighestValue() store a placeholder "0", so their automatic min/max bounds were turned into fixed numeric thresholds; the same override also collapsed percent, percentile and formula thresholds to num. Each cfvo is now built from its content type: automatic bounds stay autoMin/autoMax, lowest/highest bounds become min/max with no formula, and value based thresholds keep their type and emit the formula. Fixes #2843
This commit is contained in:
1 parent
8d5ee56081
commit
9508e12dc7
5 files changed
+91
-22
No files matched your search
@@ -3,14 +3,57 @@ using ClosedXML.Excel;
|
||||
using NUnit.Framework;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.IO.Packaging;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Xml.Linq;
|
||||
using SaveOptions = ClosedXML.Excel.SaveOptions;
|
||||
|
||||
namespace ClosedXML.Tests.Excel.ConditionalFormats
|
||||
{
|
||||
[TestFixture]
|
||||
public class ConditionalFormatTests
|
||||
{
|
||||
[Test]
|
||||
public void DataBarLowestHighestValueWritesMinMaxCfvoWithoutFormula()
|
||||
{
|
||||
// https://github.com/ClosedXML/ClosedXML/issues/2843
|
||||
// DataBar().LowestValue()/HighestValue() must emit the x14 cfvo nodes as
|
||||
// type="min"/type="max" without an xm:f formula. The regression wrote them
|
||||
// as type="num" locked to 0, which strict parsers (e.g. WPS) render wrong.
|
||||
XNamespace x14 = "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main";
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
using (var wb = new XLWorkbook())
|
||||
{
|
||||
var ws = wb.AddWorksheet("Sheet1");
|
||||
ws.Cell("A1").Value = 1;
|
||||
ws.Cell("A2").Value = -1;
|
||||
ws.Cell("A3").Value = 2;
|
||||
ws.Range("A1:A3").AddConditionalFormat()
|
||||
.DataBar(XLColor.Red)
|
||||
.LowestValue()
|
||||
.HighestValue();
|
||||
wb.SaveAs(ms);
|
||||
}
|
||||
|
||||
ms.Position = 0;
|
||||
using var package = Package.Open(ms, FileMode.Open, FileAccess.Read);
|
||||
var part = package.GetPart(new Uri("/xl/worksheets/sheet1.xml", UriKind.Relative));
|
||||
using var partStream = part.GetStream();
|
||||
var doc = XDocument.Load(partStream);
|
||||
|
||||
var x14DataBar = doc.Descendants(x14 + "dataBar").Single();
|
||||
var cfvos = x14DataBar.Elements(x14 + "cfvo").ToList();
|
||||
|
||||
Assert.AreEqual(2, cfvos.Count);
|
||||
Assert.AreEqual("min", cfvos[0].Attribute("type")?.Value);
|
||||
Assert.AreEqual("max", cfvos[1].Attribute("type")?.Value);
|
||||
Assert.IsFalse(
|
||||
x14DataBar.Descendants().Any(e => e.Name.LocalName == "f"),
|
||||
"x14 cfvo for lowest/highest value must not contain a formula.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MaintainConditionalFormattingOrder()
|
||||
{
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in new issue
Block a user