Upstream ClosedXML/ClosedXML state of the touched files before 9e7a0a3c79
This commit is contained in:
1 parent
9508e12dc7
commit
c8aec98c23
5 files changed
+22
-91
No files matched your search
@@ -3,57 +3,14 @@ using ClosedXML.Excel;
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Packaging;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Xml.Linq;
|
|
||||||
using SaveOptions = ClosedXML.Excel.SaveOptions;
|
|
||||||
|
|
||||||
namespace ClosedXML.Tests.Excel.ConditionalFormats
|
namespace ClosedXML.Tests.Excel.ConditionalFormats
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class ConditionalFormatTests
|
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]
|
[Test]
|
||||||
public void MaintainConditionalFormattingOrder()
|
public void MaintainConditionalFormattingOrder()
|
||||||
{
|
{
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -2,6 +2,7 @@ using ClosedXML.Extensions;
|
|||||||
using DocumentFormat.OpenXml.Office.Excel;
|
using DocumentFormat.OpenXml.Office.Excel;
|
||||||
using DocumentFormat.OpenXml.Office2010.Excel;
|
using DocumentFormat.OpenXml.Office2010.Excel;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace ClosedXML.Excel
|
namespace ClosedXML.Excel
|
||||||
{
|
{
|
||||||
@@ -10,8 +11,8 @@ namespace ClosedXML.Excel
|
|||||||
private static readonly IReadOnlyDictionary<DocumentFormat.OpenXml.Spreadsheet.ConditionalFormatValueObjectValues, ConditionalFormattingValueObjectTypeValues> CFValueToTypeMap =
|
private static readonly IReadOnlyDictionary<DocumentFormat.OpenXml.Spreadsheet.ConditionalFormatValueObjectValues, ConditionalFormattingValueObjectTypeValues> CFValueToTypeMap =
|
||||||
new Dictionary<DocumentFormat.OpenXml.Spreadsheet.ConditionalFormatValueObjectValues, ConditionalFormattingValueObjectTypeValues>
|
new Dictionary<DocumentFormat.OpenXml.Spreadsheet.ConditionalFormatValueObjectValues, ConditionalFormattingValueObjectTypeValues>
|
||||||
{
|
{
|
||||||
{ DocumentFormat.OpenXml.Spreadsheet.ConditionalFormatValueObjectValues.Max, ConditionalFormattingValueObjectTypeValues.Max },
|
{ DocumentFormat.OpenXml.Spreadsheet.ConditionalFormatValueObjectValues.Max, ConditionalFormattingValueObjectTypeValues.AutoMax },
|
||||||
{ DocumentFormat.OpenXml.Spreadsheet.ConditionalFormatValueObjectValues.Min, ConditionalFormattingValueObjectTypeValues.Min },
|
{ DocumentFormat.OpenXml.Spreadsheet.ConditionalFormatValueObjectValues.Min, ConditionalFormattingValueObjectTypeValues.AutoMin },
|
||||||
{ DocumentFormat.OpenXml.Spreadsheet.ConditionalFormatValueObjectValues.Number, ConditionalFormattingValueObjectTypeValues.Numeric },
|
{ DocumentFormat.OpenXml.Spreadsheet.ConditionalFormatValueObjectValues.Number, ConditionalFormattingValueObjectTypeValues.Numeric },
|
||||||
{ DocumentFormat.OpenXml.Spreadsheet.ConditionalFormatValueObjectValues.Percent, ConditionalFormattingValueObjectTypeValues.Percent },
|
{ DocumentFormat.OpenXml.Spreadsheet.ConditionalFormatValueObjectValues.Percent, ConditionalFormattingValueObjectTypeValues.Percent },
|
||||||
{ DocumentFormat.OpenXml.Spreadsheet.ConditionalFormatValueObjectValues.Percentile, ConditionalFormattingValueObjectTypeValues.Percentile },
|
{ DocumentFormat.OpenXml.Spreadsheet.ConditionalFormatValueObjectValues.Percentile, ConditionalFormattingValueObjectTypeValues.Percentile },
|
||||||
@@ -34,8 +35,25 @@ namespace ClosedXML.Excel
|
|||||||
ShowValue = !cf.ShowBarOnly
|
ShowValue = !cf.ShowBarOnly
|
||||||
};
|
};
|
||||||
|
|
||||||
var cfMin = BuildValueObject(cf, 1, ConditionalFormattingValueObjectTypeValues.AutoMin);
|
var cfMinType = cf.ContentTypes.TryGetValue(1, out var contentType1)
|
||||||
var cfMax = BuildValueObject(cf, 2, ConditionalFormattingValueObjectTypeValues.AutoMax);
|
? GetCFType(contentType1.ToOpenXml())
|
||||||
|
: ConditionalFormattingValueObjectTypeValues.AutoMin;
|
||||||
|
var cfMin = new ConditionalFormattingValueObject { Type = cfMinType };
|
||||||
|
if (cf.Values.Any() && cf.Values[1]?.Value != null)
|
||||||
|
{
|
||||||
|
cfMin.Type = ConditionalFormattingValueObjectTypeValues.Numeric;
|
||||||
|
cfMin.Append(new Formula() { Text = cf.Values[1].Value });
|
||||||
|
}
|
||||||
|
|
||||||
|
var cfMaxType = cf.ContentTypes.TryGetValue(2, out var contentType2)
|
||||||
|
? GetCFType(contentType2.ToOpenXml())
|
||||||
|
: ConditionalFormattingValueObjectTypeValues.AutoMax;
|
||||||
|
var cfMax = new ConditionalFormattingValueObject { Type = cfMaxType };
|
||||||
|
if (cf.Values.Count >= 2 && cf.Values[2]?.Value != null)
|
||||||
|
{
|
||||||
|
cfMax.Type = ConditionalFormattingValueObjectTypeValues.Numeric;
|
||||||
|
cfMax.Append(new Formula() { Text = cf.Values[2].Value });
|
||||||
|
}
|
||||||
|
|
||||||
var barAxisColor = new BarAxisColor { Rgb = XLColor.Black.Color.ToHex() };
|
var barAxisColor = new BarAxisColor { Rgb = XLColor.Black.Color.ToHex() };
|
||||||
|
|
||||||
@@ -56,50 +74,6 @@ namespace ClosedXML.Excel
|
|||||||
return conditionalFormattingRule;
|
return conditionalFormattingRule;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Builds a single x14 conditional formatting value object (cfvo) for a data bar threshold.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cf">The conditional format the data bar belongs to.</param>
|
|
||||||
/// <param name="index">1-based threshold index (1 = minimum, 2 = maximum).</param>
|
|
||||||
/// <param name="automaticType">
|
|
||||||
/// Type emitted for an automatic bound: autoMin for the minimum, autoMax for the maximum.
|
|
||||||
/// </param>
|
|
||||||
/// <remarks>
|
|
||||||
/// Automatic and min/max bounds are self-describing and carry no formula; only
|
|
||||||
/// value based thresholds (num/percent/percentile/formula) emit an xm:f formula.
|
|
||||||
/// </remarks>
|
|
||||||
private static ConditionalFormattingValueObject BuildValueObject(IXLConditionalFormat cf, int index, ConditionalFormattingValueObjectTypeValues automaticType)
|
|
||||||
{
|
|
||||||
cf.Values.TryGetValue(index, out var value);
|
|
||||||
var formulaText = value?.Value;
|
|
||||||
|
|
||||||
if (!cf.ContentTypes.TryGetValue(index, out var contentType))
|
|
||||||
{
|
|
||||||
return new ConditionalFormattingValueObject { Type = automaticType };
|
|
||||||
}
|
|
||||||
|
|
||||||
var type = GetCFType(contentType.ToOpenXml());
|
|
||||||
var valueObject = new ConditionalFormattingValueObject { Type = type };
|
|
||||||
|
|
||||||
if (type == ConditionalFormattingValueObjectTypeValues.Min ||
|
|
||||||
type == ConditionalFormattingValueObjectTypeValues.Max)
|
|
||||||
{
|
|
||||||
if (formulaText == null)
|
|
||||||
{
|
|
||||||
valueObject.Type = automaticType;
|
|
||||||
}
|
|
||||||
|
|
||||||
return valueObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (formulaText != null)
|
|
||||||
{
|
|
||||||
valueObject.Append(new Formula { Text = formulaText });
|
|
||||||
}
|
|
||||||
|
|
||||||
return valueObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ConditionalFormattingValueObjectTypeValues GetCFType(DocumentFormat.OpenXml.Spreadsheet.ConditionalFormatValueObjectValues value)
|
private static ConditionalFormattingValueObjectTypeValues GetCFType(DocumentFormat.OpenXml.Spreadsheet.ConditionalFormatValueObjectValues value)
|
||||||
{
|
{
|
||||||
return CFValueToTypeMap[value];
|
return CFValueToTypeMap[value];
|
||||||
|
|||||||
Reference in new issue
Block a user