234 lines
11 KiB
C#
234 lines
11 KiB
C#
using System;
|
|
using ClosedXML.Excel;
|
|
using NUnit.Framework;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
|
|
namespace ClosedXML.Tests.Excel.ConditionalFormats
|
|
{
|
|
[TestFixture]
|
|
public class ConditionalFormatTests
|
|
{
|
|
[Test]
|
|
public void MaintainConditionalFormattingOrder()
|
|
{
|
|
// The input file contains duplicates of same dxf and thus the output also contains some duplicate dxf.
|
|
TestHelper.LoadSaveAndCompare(
|
|
@"Other\StyleReferenceFiles\ConditionalFormattingOrder\inputfile.xlsx",
|
|
@"Other\StyleReferenceFiles\ConditionalFormattingOrder\ConditionalFormattingOrder.xlsx");
|
|
}
|
|
|
|
[TestCase(true, 7)]
|
|
[TestCase(false, 8)]
|
|
public void SaveOptionAffectsConsolidationConditionalFormatRanges(bool consolidateConditionalFormatRanges, int expectedCount)
|
|
{
|
|
var options = new SaveOptions
|
|
{
|
|
ConsolidateConditionalFormatRanges = consolidateConditionalFormatRanges
|
|
};
|
|
|
|
var wb = new XLWorkbook();
|
|
var ws = wb.AddWorksheet("Sheet");
|
|
|
|
ws.Range("D2:D3").AddConditionalFormat().DataBar(XLColor.Red).LowestValue().HighestValue();
|
|
ws.Range("B2:B3").AddConditionalFormat().DataBar(XLColor.Red).LowestValue().HighestValue();
|
|
ws.Range("E2:E6").AddConditionalFormat().ColorScale().LowestValue(XLColor.Red).HighestValue(XLColor.Blue);
|
|
ws.Range("F2:F6").AddConditionalFormat().ColorScale().LowestValue(XLColor.Red).HighestValue(XLColor.Blue);
|
|
ws.Range("G2:G7").AddConditionalFormat().WhenIsUnique().Fill.SetBackgroundColor(XLColor.Blue);
|
|
ws.Range("H2:H7").AddConditionalFormat().WhenIsUnique().Fill.SetBackgroundColor(XLColor.Blue);
|
|
ws.Range("I2:I6").AddConditionalFormat().WhenContains("test");
|
|
ws.Range("J2:J6").AddConditionalFormat().WhenContains("test");
|
|
using (var ms = new MemoryStream())
|
|
{
|
|
wb.SaveAs(ms, options);
|
|
var wb_saved = new XLWorkbook(ms);
|
|
Assert.AreEqual(expectedCount, wb_saved.Worksheet("Sheet").ConditionalFormats.Count());
|
|
}
|
|
}
|
|
|
|
[TestCase(true, 1)]
|
|
[TestCase(false, 2)]
|
|
public void SaveOptionAffectsConsolidationDataValidationRanges(bool consolidateDataValidationRanges, int expectedCount)
|
|
{
|
|
var options = new SaveOptions
|
|
{
|
|
ConsolidateDataValidationRanges = consolidateDataValidationRanges
|
|
};
|
|
|
|
var wb = new XLWorkbook();
|
|
var ws = wb.AddWorksheet("Sheet");
|
|
ws.Range("C2:C5").CreateDataValidation().Decimal.Between(1, 5);
|
|
ws.Range("D2:D5").CreateDataValidation().Decimal.Between(1, 5);
|
|
|
|
using (var ms = new MemoryStream())
|
|
{
|
|
wb.SaveAs(ms, options);
|
|
var wb_saved = new XLWorkbook(ms);
|
|
Assert.AreEqual(expectedCount, wb_saved.Worksheet("Sheet").DataValidations.Count());
|
|
}
|
|
}
|
|
|
|
[TestCase("en-US")]
|
|
[TestCase("fr-FR")]
|
|
[TestCase("ru-RU")]
|
|
public void SaveConditionalFormat_CultureIndependent(string culture)
|
|
{
|
|
using (var ms = new MemoryStream())
|
|
{
|
|
var expectedValue = 1.5;
|
|
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(culture);
|
|
using (var wb = new XLWorkbook())
|
|
{
|
|
var ws = wb.AddWorksheet();
|
|
var i = 1;
|
|
ws.Cell(i++, 1).AddConditionalFormat().WhenEquals(expectedValue).Fill.SetBackgroundColor(XLColor.Red);
|
|
ws.Cell(i++, 1).AddConditionalFormat().WhenNotEquals(expectedValue).Fill.SetBackgroundColor(XLColor.Red);
|
|
ws.Cell(i++, 1).AddConditionalFormat().WhenGreaterThan(expectedValue).Fill.SetBackgroundColor(XLColor.Red);
|
|
ws.Cell(i++, 1).AddConditionalFormat().WhenLessThan(expectedValue).Fill.SetBackgroundColor(XLColor.Red);
|
|
ws.Cell(i++, 1).AddConditionalFormat().WhenEqualOrGreaterThan(expectedValue).Fill.SetBackgroundColor(XLColor.Red);
|
|
ws.Cell(i++, 1).AddConditionalFormat().WhenEqualOrLessThan(expectedValue).Fill.SetBackgroundColor(XLColor.Red);
|
|
ws.Cell(i++, 1).AddConditionalFormat().WhenBetween(expectedValue, expectedValue).Fill.SetBackgroundColor(XLColor.Red);
|
|
ws.Cell(i++, 1).AddConditionalFormat().WhenNotBetween(expectedValue, expectedValue).Fill.SetBackgroundColor(XLColor.Red);
|
|
|
|
wb.SaveAs(ms);
|
|
}
|
|
|
|
using (var wb = new XLWorkbook(ms))
|
|
{
|
|
var ws = wb.Worksheets.First();
|
|
|
|
var conditionalFormatValues = ws.ConditionalFormats
|
|
.SelectMany(cf => cf.Values.Values)
|
|
.Select(v => v.Value)
|
|
.Distinct();
|
|
|
|
Assert.AreEqual(1, conditionalFormatValues.Count());
|
|
Assert.AreEqual("1.5", conditionalFormatValues.Single());
|
|
}
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void CellIs_type_reads_only_required_formula_arguments()
|
|
{
|
|
// The CellIs uses formula tags as arguments. Some producers generate extra empty
|
|
// formula tags and ClosedXml should be able to load CellIs conditional formatting
|
|
// with such extra tags without an exception. The test file has been modified to
|
|
// include extra formula tags and test checks that extra tags are ignored.
|
|
TestHelper.LoadAndAssert((_, ws) =>
|
|
{
|
|
AssertFormulaArgs(ws, XLCFOperator.Between, "$D$2", "$E$2");
|
|
AssertFormulaArgs(ws, XLCFOperator.NotBetween, "$D$3", "$E$3");
|
|
AssertFormulaArgs(ws, XLCFOperator.GreaterThan, "$D$4");
|
|
AssertFormulaArgs(ws, XLCFOperator.LessThan, "$D$5");
|
|
AssertFormulaArgs(ws, XLCFOperator.Equal, "$D$6");
|
|
}, @"Other\ConditionalFormats\Extra_formulas_CellIs_type.xlsx");
|
|
|
|
static void AssertFormulaArgs(IXLWorksheet ws, XLCFOperator cfOperator, params string[] expectedFormulas)
|
|
{
|
|
var cf = ws.ConditionalFormats.Single(cf => cf.ConditionalFormatType == XLConditionalFormatType.CellIs && cf.Operator == cfOperator);
|
|
Assert.AreEqual(expectedFormulas.Length, cf.Values.Count);
|
|
CollectionAssert.AreEqual(expectedFormulas, cf.Values.Select(v => v.Value.Value));
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void Expression_type_skips_empty_formula_tags()
|
|
{
|
|
// The Expression uses formula tag as arguments. Some producers generate extra empty
|
|
// formula tags and ClosedXml should be able to load Expression conditional formatting
|
|
// with such extra tags without an exception. The test file has been modified to
|
|
// include extra formula tags and test checks that extra tags are ignored.
|
|
TestHelper.LoadAndAssert((_, ws) =>
|
|
{
|
|
AssertFormulaArgs(ws, "A1:A1", "$C$1=5");
|
|
AssertFormulaArgs(ws, "A2:A2", "$C$2=4");
|
|
}, @"Other\ConditionalFormats\Extra_formulas_Expression_type.xlsx");
|
|
|
|
static void AssertFormulaArgs(IXLWorksheet ws, string range, string expectedFormula)
|
|
{
|
|
var cf = ws.ConditionalFormats.Single(cf => cf.ConditionalFormatType == XLConditionalFormatType.Expression && cf.Range.RangeAddress.ToString() == range);
|
|
Assert.AreEqual(1, cf.Values.Count);
|
|
CollectionAssert.AreEqual(expectedFormula, cf.Values[1].Value);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void Range_setter_throws_on_range_from_different_worksheet()
|
|
{
|
|
using var wb = new XLWorkbook();
|
|
var ws1 = wb.AddWorksheet();
|
|
var cf = ws1.Range("A1").AddConditionalFormat();
|
|
var ws2 = wb.AddWorksheet();
|
|
var differentSheetRange = ws2.Range("B5");
|
|
|
|
Assert.Throws<ArgumentException>(() => cf.Range = differentSheetRange);
|
|
}
|
|
|
|
[Test]
|
|
public void Ranges_setter_throws_on_range_from_different_worksheet()
|
|
{
|
|
using var wb = new XLWorkbook();
|
|
var ws1 = wb.AddWorksheet();
|
|
var cf = ws1.Range("A1").AddConditionalFormat();
|
|
|
|
var ranges = ws1.Ranges("B1");
|
|
var differentSheetRange = wb.AddWorksheet().Range("C1");
|
|
ranges.Add(differentSheetRange);
|
|
|
|
Assert.That(() => cf.Ranges = ranges, Throws.TypeOf<ArgumentException>().With.Message.Contains("must be from worksheet"));
|
|
}
|
|
|
|
[Test]
|
|
public void Ranges_setter_throws_on_empty_ranges()
|
|
{
|
|
using var wb = new XLWorkbook();
|
|
var ws1 = wb.AddWorksheet();
|
|
var cf = ws1.Range("A1").AddConditionalFormat();
|
|
|
|
var emptyRanges = ws1.Ranges("");
|
|
|
|
Assert.That(() => cf.Ranges = emptyRanges, Throws.TypeOf<ArgumentException>().With.Message.Contains("empty"));
|
|
}
|
|
|
|
[Test]
|
|
public void Text_formats_are_loaded_as_value()
|
|
{
|
|
// Issue #2690: Ensure that CF for text are loaded as a value and not as a formula.
|
|
TestHelper.CreateSaveLoadAssert(
|
|
(_, ws) =>
|
|
{
|
|
ws.AddConditionalFormat().WhenContains("Contains")
|
|
.Fill.SetBackgroundColor(XLColor.Red);
|
|
|
|
ws.AddConditionalFormat().WhenNotContains("Not Contains")
|
|
.Fill.SetBackgroundColor(XLColor.Green);
|
|
|
|
ws.AddConditionalFormat().WhenStartsWith("Starts With")
|
|
.Fill.SetBackgroundColor(XLColor.Blue);
|
|
|
|
ws.AddConditionalFormat().WhenEndsWith("Ends With")
|
|
.Fill.SetBackgroundColor(XLColor.Black);
|
|
},
|
|
(_, ws) =>
|
|
{
|
|
AssertTextCfValue(ws, XLConditionalFormatType.ContainsText, "Contains");
|
|
AssertTextCfValue(ws, XLConditionalFormatType.NotContainsText, "Not Contains");
|
|
AssertTextCfValue(ws, XLConditionalFormatType.StartsWith, "Starts With");
|
|
AssertTextCfValue(ws, XLConditionalFormatType.EndsWith, "Ends With");
|
|
});
|
|
return;
|
|
|
|
static void AssertTextCfValue(IXLWorksheet ws, XLConditionalFormatType type, string text)
|
|
{
|
|
var cf = ws.ConditionalFormats.Single(x => x.ConditionalFormatType == type);
|
|
Assert.AreEqual(1, cf.Values.Count);
|
|
Assert.AreEqual(text, cf.Values[1].Value);
|
|
Assert.IsFalse(cf.Values[1].IsFormula);
|
|
}
|
|
}
|
|
}
|
|
}
|