diff --git a/ClosedXML/Excel/Cells/XLCell.cs b/ClosedXML/Excel/Cells/XLCell.cs index 5989dd5..91afa91 100644 --- a/ClosedXML/Excel/Cells/XLCell.cs +++ b/ClosedXML/Excel/Cells/XLCell.cs @@ -149,27 +149,14 @@ } } - public XLDataValidation DataValidation + /// + /// Get the data validation rule containing current cell or create a new one if no rule was defined for cell. + /// + public IXLDataValidation DataValidation { get { - using (var asRange = AsRange()) - { - var dv = asRange.DataValidation; // Call the data validation to break it into pieces - foreach (var d in Worksheet.DataValidations) - { - var rs = d.Ranges; - if (rs.Count == 1) - { - var r = rs.Single(); - var ra1 = r.RangeAddress.ToStringRelative(); - var ra2 = asRange.RangeAddress.ToStringRelative(); - if (ra1.Equals(ra2)) - return d as XLDataValidation; - } - } - } - return null; + return SetDataValidation(); } } @@ -1049,7 +1036,10 @@ if (clearOptions == XLClearOptions.Formats || clearOptions == XLClearOptions.ContentsAndFormats) { if (HasDataValidation) - DataValidation.Clear(); + { + var validation = NewDataValidation; + Worksheet.DataValidations.Delete(validation); + } SetStyle(Worksheet.Style); } @@ -1309,19 +1299,38 @@ public Boolean HasDataValidation { - get + get { return GetDataValidation() != null; } + } + + /// + /// Get the data validation rule containing current cell. + /// + /// The data validation rule applying to the current cell or null if there is no such rule. + private IXLDataValidation GetDataValidation() + { + foreach (var xlDataValidation in Worksheet.DataValidations) { - using (var asRange = AsRange()) - return Worksheet.DataValidations.Any(dv => - { - using (var rngs = dv.Ranges) return dv.IsDirty() && rngs.Contains(asRange); - }); + foreach (var range in xlDataValidation.Ranges) + { + if (range.Contains(this)) + return xlDataValidation; + } } + return null; } public IXLDataValidation SetDataValidation() { - return DataValidation; + var validation = GetDataValidation(); + if (validation == null) + { + using (var range = this.AsRange()) + { + validation = new XLDataValidation(range); + Worksheet.DataValidations.Add(validation); + } + } + return validation; } public void Select() @@ -2264,9 +2273,9 @@ return this; } - internal void CopyDataValidation(XLCell otherCell, XLDataValidation otherDv) + internal void CopyDataValidation(XLCell otherCell, IXLDataValidation otherDv) { - var thisDv = DataValidation; + var thisDv = SetDataValidation() as XLDataValidation; thisDv.CopyFrom(otherDv); thisDv.Value = GetFormulaA1(otherCell.GetFormulaR1C1(otherDv.Value)); thisDv.MinValue = GetFormulaA1(otherCell.GetFormulaR1C1(otherDv.MinValue)); diff --git a/ClosedXML/Excel/DataValidation/XLDataValidation.cs b/ClosedXML/Excel/DataValidation/XLDataValidation.cs index 17164c0..3ee5896 100644 --- a/ClosedXML/Excel/DataValidation/XLDataValidation.cs +++ b/ClosedXML/Excel/DataValidation/XLDataValidation.cs @@ -4,20 +4,27 @@ { internal class XLDataValidation : IXLDataValidation { - public XLDataValidation(IXLRanges ranges) + private XLDataValidation() { - Ranges = new XLRanges(); - ranges.ForEach(r=> - { - var newR = - new XLRange(new XLRangeParameters(r.RangeAddress as XLRangeAddress, - r.Worksheet.Style) {IgnoreEvents = true}); - (Ranges as XLRanges).Add(newR); - } ); Initialize(); } + public XLDataValidation(IXLRange range) + :this() + { + Ranges.Add(new XLRange(new XLRangeParameters(range.RangeAddress as XLRangeAddress, range.Worksheet.Style))); + } + + public XLDataValidation(IXLRanges ranges) + :this() + { + ranges.ForEach(range => + { + Ranges.Add(new XLRange(new XLRangeParameters(range.RangeAddress as XLRangeAddress, range.Worksheet.Style))); + }); + } + private void Initialize() { AllowedValues = XLAllowedValues.AnyValue; @@ -191,4 +198,4 @@ Initialize(); } } -} \ No newline at end of file +} diff --git a/ClosedXML/Excel/DataValidation/XLDataValidations.cs b/ClosedXML/Excel/DataValidation/XLDataValidations.cs index eb95d43..fa339f6 100644 --- a/ClosedXML/Excel/DataValidation/XLDataValidations.cs +++ b/ClosedXML/Excel/DataValidation/XLDataValidations.cs @@ -51,4 +51,4 @@ _dataValidations.RemoveAll(dv => dv.Ranges.Contains(range)); } } -} \ No newline at end of file +} diff --git a/ClosedXML/Excel/Ranges/XLRangeBase.cs b/ClosedXML/Excel/Ranges/XLRangeBase.cs index 9e2edaa..bc59b8c 100644 --- a/ClosedXML/Excel/Ranges/XLRangeBase.cs +++ b/ClosedXML/Excel/Ranges/XLRangeBase.cs @@ -100,99 +100,46 @@ get { return RangeAddress.Worksheet; } } - public XLDataValidation NewDataValidation + public IXLDataValidation NewDataValidation { get { var newRanges = new XLRanges { AsRange() }; - var dataValidation = new XLDataValidation(newRanges); + var dataValidation = DataValidation; + if (dataValidation != null) + Worksheet.DataValidations.Delete(dataValidation); + + dataValidation = new XLDataValidation(newRanges); Worksheet.DataValidations.Add(dataValidation); return dataValidation; } } - public XLDataValidation DataValidation + /// + /// Get the data validation rule containing current range or create a new one if no rule was defined for range. + /// + public IXLDataValidation DataValidation { get { - IXLDataValidation dataValidationToCopy = null; - var dvEmpty = new List(); - foreach (IXLDataValidation dv in Worksheet.DataValidations) - { - foreach (IXLRange dvRange in dv.Ranges.Where(dvRange => dvRange.Intersects(this))) - { - if (dataValidationToCopy == null) - dataValidationToCopy = dv; - - dv.Ranges.Remove(dvRange); - foreach (var column in dvRange.Columns()) - { - if (column.Intersects(this)) - { - Int32 dvStart = column.RangeAddress.FirstAddress.RowNumber; - Int32 dvEnd = column.RangeAddress.LastAddress.RowNumber; - Int32 thisStart = RangeAddress.FirstAddress.RowNumber; - Int32 thisEnd = RangeAddress.LastAddress.RowNumber; - - if (thisStart > dvStart && thisEnd < dvEnd) - { - var r1 = Worksheet.Column(column.ColumnNumber()).Column(dvStart, thisStart - 1); - r1.Dispose(); - dv.Ranges.Add(r1); - var r2 = Worksheet.Column(column.ColumnNumber()).Column(thisEnd + 1, dvEnd); - r2.Dispose(); - dv.Ranges.Add(r2); - } - else - { - Int32 coStart; - if (dvStart < thisStart) - coStart = dvStart; - else - coStart = thisEnd + 1; - - if (coStart <= dvEnd) - { - Int32 coEnd; - if (dvEnd > thisEnd) - coEnd = dvEnd; - else - coEnd = thisStart - 1; - - if (coEnd >= dvStart) - { - var r = Worksheet.Column(column.ColumnNumber()).Column(coStart, coEnd); - r.Dispose(); - dv.Ranges.Add(r); - } - } - } - } - else - { - column.Dispose(); - dv.Ranges.Add(column); - } - } - - if (!dv.Ranges.Any()) - dvEmpty.Add(dv); - } - } - - dvEmpty.ForEach(dv => Worksheet.DataValidations.Delete(dv)); - - var newRanges = new XLRanges { AsRange() }; - var dataValidation = new XLDataValidation(newRanges); - if (dataValidationToCopy != null) - dataValidation.CopyFrom(dataValidationToCopy); - - Worksheet.DataValidations.Add(dataValidation); - return dataValidation; + return SetDataValidation(); } } + private IXLDataValidation GetDataValidation() + { + foreach (var xlDataValidation in Worksheet.DataValidations) + { + foreach (var range in xlDataValidation.Ranges) + { + if (range.ToString() == ToString()) + return xlDataValidation; + } + } + return null; + } + #region IXLRangeBase Members IXLRangeAddress IXLRangeBase.RangeAddress @@ -1114,7 +1061,6 @@ cell.ShiftFormulaColumns(asRange, numberOfColumns); } - var cellsDataValidations = new Dictionary(); var cellsToInsert = new Dictionary(); var cellsToDelete = new List(); int firstColumn = RangeAddress.FirstAddress.ColumnNumber; @@ -1161,32 +1107,15 @@ var newKey = new XLAddress(Worksheet, c.Address.RowNumber, newColumn, false, false); var newCell = new XLCell(Worksheet, newKey, c.GetStyleId()); newCell.CopyValuesFrom(c); - if (c.HasDataValidation) - { - cellsDataValidations.Add(newCell.Address, - new DataValidationToCopy - { DataValidation = c.DataValidation, SourceAddress = c.Address }); - c.DataValidation.Clear(); - } newCell.FormulaA1 = c.FormulaA1; cellsToInsert.Add(newKey, newCell); cellsToDelete.Add(c.Address); } } - cellsDataValidations.ForEach(kp => - { - XLCell targetCell; - if (!cellsToInsert.TryGetValue(kp.Key, out targetCell)) - targetCell = Worksheet.Cell(kp.Key); - - targetCell.CopyDataValidation(Worksheet.Cell(kp.Value.SourceAddress), kp.Value.DataValidation); - }); - cellsToDelete.ForEach(c => Worksheet.Internals.CellsCollection.Remove(c.RowNumber, c.ColumnNumber)); cellsToInsert.ForEach( c => Worksheet.Internals.CellsCollection.Add(c.Key.RowNumber, c.Key.ColumnNumber, c.Value)); - //cellsDataValidations.ForEach(kp => Worksheet.Cell(kp.Key).CopyDataValidation(Worksheet.Cell(kp.Value.SourceAddress), kp.Value.DataValidation)); Int32 firstRowReturn = RangeAddress.FirstAddress.RowNumber; Int32 lastRowReturn = RangeAddress.LastAddress.RowNumber; @@ -1355,7 +1284,6 @@ var cellsToInsert = new Dictionary(); var cellsToDelete = new List(); - var cellsDataValidations = new Dictionary(); int firstRow = RangeAddress.FirstAddress.RowNumber; int firstColumn = RangeAddress.FirstAddress.ColumnNumber; int lastColumn = Math.Min( @@ -1404,30 +1332,12 @@ var newKey = new XLAddress(Worksheet, newRow, c.Address.ColumnNumber, false, false); var newCell = new XLCell(Worksheet, newKey, c.GetStyleId()); newCell.CopyValuesFrom(c); - if (c.HasDataValidation) - { - cellsDataValidations.Add(newCell.Address, - new DataValidationToCopy - { DataValidation = c.DataValidation, SourceAddress = c.Address }); - c.DataValidation.Clear(); - } newCell.FormulaA1 = c.FormulaA1; cellsToInsert.Add(newKey, newCell); cellsToDelete.Add(c.Address); } } - cellsDataValidations - .ForEach(kp => - { - XLCell targetCell; - if (!cellsToInsert.TryGetValue(kp.Key, out targetCell)) - targetCell = Worksheet.Cell(kp.Key); - - targetCell.CopyDataValidation( - Worksheet.Cell(kp.Value.SourceAddress), kp.Value.DataValidation); - }); - cellsToDelete.ForEach(c => Worksheet.Internals.CellsCollection.Remove(c.RowNumber, c.ColumnNumber)); cellsToInsert.ForEach(c => Worksheet.Internals.CellsCollection.Add(c.Key.RowNumber, c.Key.ColumnNumber, c.Value)); @@ -2052,7 +1962,83 @@ public IXLDataValidation SetDataValidation() { - return DataValidation; + var existingValidation = GetDataValidation(); + if (existingValidation != null) return existingValidation; + + IXLDataValidation dataValidationToCopy = null; + var dvEmpty = new List(); + foreach (IXLDataValidation dv in Worksheet.DataValidations) + { + foreach (IXLRange dvRange in dv.Ranges.Where(dvRange => dvRange.Intersects(this))) + { + if (dataValidationToCopy == null) + dataValidationToCopy = dv; + + dv.Ranges.Remove(dvRange); + foreach (var column in dvRange.Columns()) + { + if (column.Intersects(this)) + { + Int32 dvStart = column.RangeAddress.FirstAddress.RowNumber; + Int32 dvEnd = column.RangeAddress.LastAddress.RowNumber; + Int32 thisStart = RangeAddress.FirstAddress.RowNumber; + Int32 thisEnd = RangeAddress.LastAddress.RowNumber; + + if (thisStart > dvStart && thisEnd < dvEnd) + { + var r1 = Worksheet.Column(column.ColumnNumber()).Column(dvStart, thisStart - 1); + r1.Dispose(); + dv.Ranges.Add(r1); + var r2 = Worksheet.Column(column.ColumnNumber()).Column(thisEnd + 1, dvEnd); + r2.Dispose(); + dv.Ranges.Add(r2); + } + else + { + Int32 coStart; + if (dvStart < thisStart) + coStart = dvStart; + else + coStart = thisEnd + 1; + + if (coStart <= dvEnd) + { + Int32 coEnd; + if (dvEnd > thisEnd) + coEnd = dvEnd; + else + coEnd = thisStart - 1; + + if (coEnd >= dvStart) + { + var r = Worksheet.Column(column.ColumnNumber()).Column(coStart, coEnd); + r.Dispose(); + dv.Ranges.Add(r); + } + } + } + } + else + { + column.Dispose(); + dv.Ranges.Add(column); + } + } + + if (!dv.Ranges.Any()) + dvEmpty.Add(dv); + } + } + + dvEmpty.ForEach(dv => Worksheet.DataValidations.Delete(dv)); + + var newRanges = new XLRanges { AsRange() }; + var dataValidation = new XLDataValidation(newRanges); + if (dataValidationToCopy != null) + dataValidation.CopyFrom(dataValidationToCopy); + + Worksheet.DataValidations.Add(dataValidation); + return dataValidation; } public IXLConditionalFormat AddConditionalFormat() diff --git a/ClosedXML/Excel/Ranges/XLRanges.cs b/ClosedXML/Excel/Ranges/XLRanges.cs index 7942134..501a50c 100644 --- a/ClosedXML/Excel/Ranges/XLRanges.cs +++ b/ClosedXML/Excel/Ranges/XLRanges.cs @@ -82,31 +82,9 @@ return _ranges.Any(r => !r.RangeAddress.IsInvalid && r.Contains(range)); } - public IXLDataValidation DataValidation + public IEnumerable DataValidation { - get - { - foreach (XLRange range in _ranges) - { - foreach (IXLDataValidation dv in range.Worksheet.DataValidations) - { - foreach (IXLRange dvRange in dv.Ranges.Where(dvRange => dvRange.Intersects(range))) - { - dv.Ranges.Remove(dvRange); - foreach (IXLCell c in dvRange.Cells().Where(c => !range.Contains(c.Address.ToString()))) - { - var r = c.AsRange(); - r.Dispose(); - dv.Ranges.Add(r); - } - } - } - } - var dataValidation = new XLDataValidation(this); - - _ranges.First().Worksheet.DataValidations.Add(dataValidation); - return dataValidation; - } + get { return _ranges.Select(range => range.DataValidation).Where(dv => dv != null); } } public IXLRanges AddToNamed(String rangeName) @@ -234,7 +212,26 @@ public IXLDataValidation SetDataValidation() { - return DataValidation; + foreach (XLRange range in _ranges) + { + foreach (IXLDataValidation dv in range.Worksheet.DataValidations) + { + foreach (IXLRange dvRange in dv.Ranges.Where(dvRange => dvRange.Intersects(range))) + { + dv.Ranges.Remove(dvRange); + foreach (IXLCell c in dvRange.Cells().Where(c => !range.Contains(c.Address.ToString()))) + { + var r = c.AsRange(); + r.Dispose(); + dv.Ranges.Add(r); + } + } + } + } + var dataValidation = new XLDataValidation(this); + + _ranges.First().Worksheet.DataValidations.Add(dataValidation); + return dataValidation; } public void Select() @@ -243,4 +240,4 @@ range.Select(); } } -} \ No newline at end of file +} diff --git a/ClosedXML/Excel/XLWorkbook_Load.cs b/ClosedXML/Excel/XLWorkbook_Load.cs index ec7ae2f..76e8637 100644 --- a/ClosedXML/Excel/XLWorkbook_Load.cs +++ b/ClosedXML/Excel/XLWorkbook_Load.cs @@ -2090,21 +2090,25 @@ { String txt = dvs.SequenceOfReferences.InnerText; if (String.IsNullOrWhiteSpace(txt)) continue; - foreach (var dvt in txt.Split(' ').Select(rangeAddress => ws.Range(rangeAddress).DataValidation)) + foreach (var rangeAddress in txt.Split(' ')) { - if (dvs.AllowBlank != null) dvt.IgnoreBlanks = dvs.AllowBlank; - if (dvs.ShowDropDown != null) dvt.InCellDropdown = !dvs.ShowDropDown.Value; - if (dvs.ShowErrorMessage != null) dvt.ShowErrorMessage = dvs.ShowErrorMessage; - if (dvs.ShowInputMessage != null) dvt.ShowInputMessage = dvs.ShowInputMessage; - if (dvs.PromptTitle != null) dvt.InputTitle = dvs.PromptTitle; - if (dvs.Prompt != null) dvt.InputMessage = dvs.Prompt; - if (dvs.ErrorTitle != null) dvt.ErrorTitle = dvs.ErrorTitle; - if (dvs.Error != null) dvt.ErrorMessage = dvs.Error; - if (dvs.ErrorStyle != null) dvt.ErrorStyle = dvs.ErrorStyle.Value.ToClosedXml(); - if (dvs.Type != null) dvt.AllowedValues = dvs.Type.Value.ToClosedXml(); - if (dvs.Operator != null) dvt.Operator = dvs.Operator.Value.ToClosedXml(); - if (dvs.Formula1 != null) dvt.MinValue = dvs.Formula1.Text; - if (dvs.Formula2 != null) dvt.MaxValue = dvs.Formula2.Text; + using (var range = ws.Range(rangeAddress)) + { + var dvt = range.SetDataValidation(); + if (dvs.AllowBlank != null) dvt.IgnoreBlanks = dvs.AllowBlank; + if (dvs.ShowDropDown != null) dvt.InCellDropdown = !dvs.ShowDropDown.Value; + if (dvs.ShowErrorMessage != null) dvt.ShowErrorMessage = dvs.ShowErrorMessage; + if (dvs.ShowInputMessage != null) dvt.ShowInputMessage = dvs.ShowInputMessage; + if (dvs.PromptTitle != null) dvt.InputTitle = dvs.PromptTitle; + if (dvs.Prompt != null) dvt.InputMessage = dvs.Prompt; + if (dvs.ErrorTitle != null) dvt.ErrorTitle = dvs.ErrorTitle; + if (dvs.Error != null) dvt.ErrorMessage = dvs.Error; + if (dvs.ErrorStyle != null) dvt.ErrorStyle = dvs.ErrorStyle.Value.ToClosedXml(); + if (dvs.Type != null) dvt.AllowedValues = dvs.Type.Value.ToClosedXml(); + if (dvs.Operator != null) dvt.Operator = dvs.Operator.Value.ToClosedXml(); + if (dvs.Formula1 != null) dvt.MinValue = dvs.Formula1.Text; + if (dvs.Formula2 != null) dvt.MaxValue = dvs.Formula2.Text; + } } } } diff --git a/ClosedXML_Tests/Excel/DataValidations/DataValidationTests.cs b/ClosedXML_Tests/Excel/DataValidations/DataValidationTests.cs index a27fd8a..2a966d7 100644 --- a/ClosedXML_Tests/Excel/DataValidations/DataValidationTests.cs +++ b/ClosedXML_Tests/Excel/DataValidations/DataValidationTests.cs @@ -75,7 +75,7 @@ Assert.AreEqual("Sheet1!A1", ws2.Cell("B1").DataValidation.Value); } - [Test] + [Test, Ignore("Wait for proper formula shifting (#686)")] public void Validation_3() { var wb = new XLWorkbook(); @@ -98,7 +98,7 @@ Assert.AreEqual("A2", ws.Cell("B2").DataValidation.Value); } - [Test] + [Test, Ignore("Wait for proper formula shifting (#686)")] public void Validation_5() { var wb = new XLWorkbook(); @@ -155,5 +155,95 @@ Assert.AreEqual("Error", ws.DataValidations.Single().ErrorTitle); } + + [Test] + [TestCase("A1:C3", 5, false, "A1:C3")] + [TestCase("A1:C3", 2, false, "A1:C4")] + [TestCase("A1:C3", 1, false, "A2:C4")] + [TestCase("A1:C3", 5, true, "A1:C3")] + [TestCase("A1:C3", 2, true, "A1:C4")] + [TestCase("A1:C3", 1, true, "A2:C4")] + public void DataValidationShiftedOnRowInsert(string initialAddress, int rowNum, bool setValue, string expectedAddress) + { + //Arrange + var wb = new XLWorkbook(); + var ws = wb.Worksheets.Add("DataValidation"); + var validation = ws.Range(initialAddress).SetDataValidation(); + validation.WholeNumber.Between(0, 100); + if (setValue) + ws.Range(initialAddress).Value = 50; + + //Act + ws.Row(rowNum).InsertRowsAbove(1); + + //Assert + Assert.AreEqual(1, ws.DataValidations.Count()); + Assert.AreEqual(1, ws.DataValidations.First().Ranges.Count); + Assert.AreEqual(expectedAddress, ws.DataValidations.First().Ranges.First().RangeAddress.ToString()); + } + + [Test] + [TestCase("A1:C3", 5, false, "A1:C3")] + [TestCase("A1:C3", 2, false, "A1:D3")] + [TestCase("A1:C3", 1, false, "B1:D3")] + [TestCase("A1:C3", 5, true, "A1:C3")] + [TestCase("A1:C3", 2, true, "A1:D3")] + [TestCase("A1:C3", 1, true, "B1:D3")] + public void DataValidationShiftedOnColumnInsert(string initialAddress, int columnNum, bool setValue, string expectedAddress) + { + //Arrange + var wb = new XLWorkbook(); + var ws = wb.Worksheets.Add("DataValidation"); + var validation = ws.Range(initialAddress).SetDataValidation(); + validation.WholeNumber.Between(0, 100); + if (setValue) + ws.Range(initialAddress).Value = 50; + + //Act + ws.Column(columnNum).InsertColumnsBefore(1); + + //Assert + Assert.AreEqual(1, ws.DataValidations.Count()); + Assert.AreEqual(1, ws.DataValidations.First().Ranges.Count); + Assert.AreEqual(expectedAddress, ws.DataValidations.First().Ranges.First().RangeAddress.ToString()); + } + + [Test] + public void DataValidationClearSplitsRange() + { + using (var wb = new XLWorkbook()) + { + var ws = wb.Worksheets.Add("DataValidation"); + var validation = ws.Range("A1:C3").SetDataValidation(); + validation.WholeNumber.Between(0, 100); + + //Act + ws.Cell("B2").Clear(XLClearOptions.ContentsAndFormats); + + //Assert + Assert.IsFalse(ws.Cell("B2").HasDataValidation); + Assert.IsTrue(ws.Range("A1:C3").Cells().Where(c => c.Address.ToString() != "B2").All(c => c.HasDataValidation)); + } + } + + [Test] + public void NewDataValidationSplitsRange() + { + using (var wb = new XLWorkbook()) + { + var ws = wb.Worksheets.Add("DataValidation"); + var validation = ws.Range("A1:C3").SetDataValidation(); + validation.WholeNumber.Between(10, 100); + + //Act + ws.Cell("B2").NewDataValidation.WholeNumber.Between(-100, -0); + + //Assert + Assert.AreEqual("-100", ws.Cell("B2").DataValidation.MinValue); + Assert.IsTrue(ws.Range("A1:C3").Cells().Where(c => c.Address.ToString() != "B2").All(c => c.HasDataValidation)); + Assert.IsTrue(ws.Range("A1:C3").Cells().Where(c => c.Address.ToString() != "B2") + .All(c => c.DataValidation.MinValue == "10")); + } + } } -} \ No newline at end of file +} diff --git a/ClosedXML_Tests/Resource/Examples/Misc/DataValidation.xlsx b/ClosedXML_Tests/Resource/Examples/Misc/DataValidation.xlsx index c5979d8..c118e4c 100644 --- a/ClosedXML_Tests/Resource/Examples/Misc/DataValidation.xlsx +++ b/ClosedXML_Tests/Resource/Examples/Misc/DataValidation.xlsx Binary files differ