diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs index 92b8289..2d579e8 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Collections.Generic; using System.Text; +using System.Linq; using System.Text.RegularExpressions; using ClosedXML.Excel.CalcEngine.Functions; @@ -27,22 +28,22 @@ ce.RegisterFunction("COS", 1, Cos); ce.RegisterFunction("COSH", 1, Cosh); ce.RegisterFunction("DEGREES", 1, Degrees); - //ce.RegisterFunction("EVEN", Even, 1); + ce.RegisterFunction("EVEN", 1, Even); ce.RegisterFunction("EXP", 1, Exp); - //ce.RegisterFunction("FACT", Fact, 1); - //ce.RegisterFunction("FACTDOUBLE", FactDouble, 1); + ce.RegisterFunction("FACT", 1, Fact); + ce.RegisterFunction("FACTDOUBLE", 1, FactDouble); ce.RegisterFunction("FLOOR", 1, Floor); - //ce.RegisterFunction("GCD", Gcd, 1); + ce.RegisterFunction("GCD", 1, 255, Gcd); ce.RegisterFunction("INT", 1, Int); - //ce.RegisterFunction("LCM", Lcm, 1); + ce.RegisterFunction("LCM", 1, 255, Lcm); ce.RegisterFunction("LN", 1, Ln); ce.RegisterFunction("LOG", 1, 2, Log); ce.RegisterFunction("LOG10", 1, Log10); - //ce.RegisterFunction("MDETERM", MDeterm, 1); - //ce.RegisterFunction("MINVERSE", MInverse, 1); + //ce.RegisterFunction("MDETERM", 1, MDeterm); + //ce.RegisterFunction("MINVERSE", 1, MInverse); //ce.RegisterFunction("MMULT", MMult, 1); - //ce.RegisterFunction("MOD", Mod, 2); - //ce.RegisterFunction("MROUND", MRound, 1); + ce.RegisterFunction("MOD", 2, Mod); + ce.RegisterFunction("MROUND", 2, MRound); //ce.RegisterFunction("MULTINOMIAL", Multinomial, 1); //ce.RegisterFunction("ODD", Odd, 1); ce.RegisterFunction("PI", 0, Pi); @@ -366,7 +367,88 @@ private static object Degrees(List p) { - return Math.PI * p[0] / 180.0; + return p[0] * (180.0 / Math.PI); + } + + private static object Even(List p) + { + var num = Math.Ceiling(p[0]); + return Math.Abs(num % 2) < XLHelper.Epsilon ? num : num + 1; + } + + private static object Fact(List p) + { + var num = Math.Floor(p[0]); + double fact = 1.0; + if (num > 1) + for (int i = 2; i <= num; i++) + fact *= i; + return fact; + } + + private static object FactDouble(List p) + { + var num = Math.Floor(p[0]); + double fact = 1.0; + if (num > 1) + { + var start = Math.Abs(num % 2) < XLHelper.Epsilon ? 2 : 1; + for (int i = start; i <= num; i = i + 2) + fact *= i; + } + return fact; + } + + private static object Gcd(List p) + { + return p.Select(v => (int)v).Aggregate(Gcd); + } + + private static int Gcd(int a, int b) + { + return b == 0 ? a : Gcd(b, a % b); + } + + private static object Lcm(List p) + { + return p.Select(v => (int)v).Aggregate(Lcm); + } + + private static int Lcm(int a, int b) + { + if (a == 0 || b == 0) return 0; + return a * ( b / Gcd(a, b)); + } + + private static object Mod(List p) + { + Int32 n = (int)Math.Abs(p[0]); + Int32 d = (int)p[1]; + var ret = n % d; + return d < 0 ? ret * -1 : ret; + } + + private static object MRound(List p) + { + Double number = p[0]; + Double roundingInterval = p[1]; + + if (roundingInterval == 0) { return 0; } + + Double intv = Math.Abs(roundingInterval); + Double modulo = number % intv; + if ((intv - modulo) == modulo) + { + var temp = (number - modulo).ToString("#.##################"); + if (temp.Length != 0 && temp[temp.Length - 1] % 2 == 0) modulo *= -1; + } + else if ((intv - modulo) < modulo) + modulo = (intv - modulo); + else + modulo *= -1; + + return number + modulo; + } } } \ No newline at end of file diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/CalcEngine/XLCalcEngine.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/CalcEngine/XLCalcEngine.cs index cc78c47..da29233 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/CalcEngine/XLCalcEngine.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/CalcEngine/XLCalcEngine.cs @@ -6,32 +6,40 @@ namespace ClosedXML.Excel.CalcEngine { - public class XLCalcEngine : CalcEngine + internal class XLCalcEngine : CalcEngine { - private IXLWorksheet _ws; - public XLCalcEngine(IXLWorksheet ws) + private readonly IXLWorksheet _ws; + private readonly XLWorkbook _wb; + public XLCalcEngine() + {} + public XLCalcEngine(XLWorkbook wb) + { + _wb = wb; + IdentifierChars = "$:!"; + } + public XLCalcEngine(IXLWorksheet ws): this(ws.Workbook) { _ws = ws; - // parse multi-cell range references ($A2:B$4) - IdentifierChars = "$:!"; } public override object GetExternalObject(string identifier) { - //if (!XLHelper.IsValidA1Address(identifier)) return null; - //String wsName; - if (identifier.Contains("!")) + if (identifier.Contains("!") && _wb != null) { var wsName = identifier.Substring(0, identifier.IndexOf("!")); - return new CellRangeReference(_ws.Workbook.Worksheet(wsName).Range(identifier.Substring(identifier.IndexOf("!") + 1)), this); + return new CellRangeReference(_wb.Worksheet(wsName).Range(identifier.Substring(identifier.IndexOf("!") + 1)), this); } - return new CellRangeReference(_ws.Range(identifier), this); + + if (_ws != null) + return new CellRangeReference(_ws.Range(identifier), this); + + return identifier; } } - public class CellRangeReference : IValueObject, IEnumerable + internal class CellRangeReference : IValueObject, IEnumerable { private IXLRange _range; private XLCalcEngine _ce; diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/XLCell.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/XLCell.cs index 66ccf14..e8ca9e0 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/XLCell.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/XLCell.cs @@ -405,7 +405,7 @@ ) return _worksheet.Workbook.Worksheet(sName).Cell(cAddress).Value; - return Worksheet.CalcEngine.Evaluate(fA1); + return Worksheet.Evaluate(fA1); } String cellValue = HasRichText ? _richText.ToString() : _cellValue; diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/XLCells.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/XLCells.cs index 50e4f09..7b7eb6e 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/XLCells.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/XLCells.cs @@ -101,8 +101,9 @@ { if (oneRange) { - - yield return range.Worksheet.Cell(ro, co); + var c = range.Worksheet.Cell(ro, co); + if (_predicate == null || _predicate(c)) + yield return c; } else { @@ -138,16 +139,11 @@ foreach (var cir in cellsInRanges) { foreach (XLSheetPoint a in cir.Value) - if (_predicate == null) - { - yield return cir.Key.Cell(a.Row, a.Column); - } - else - { - var cell = cir.Key.Cell(a.Row, a.Column); - if (_predicate(cell)) - yield return cell; - } + { + var c = cir.Key.Cell(a.Row, a.Column); + if (_predicate == null || _predicate(c)) + yield return c; + } } } } diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/ConditionalFormats/XLConditionalFormat.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/ConditionalFormats/XLConditionalFormat.cs index aa6e14e..4cd8dcf 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/ConditionalFormats/XLConditionalFormat.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/ConditionalFormats/XLConditionalFormat.cs @@ -40,10 +40,10 @@ private IXLStyle _style; private Int32 _styleCacheId; - public IXLStyle Style { get { return GetStyle(); } set { SetStyle(value); } } + public IXLStyle Style{ get { return GetStyle(); } set { SetStyle(value); } } private IXLStyle GetStyle() { - //return _style ?? (_style = new XLStyle(this, Worksheet.Workbook.GetStyleById(_styleCacheId))); + //return _style; if (_style != null) return _style; @@ -51,6 +51,7 @@ } private void SetStyle(IXLStyle styleToUse) { + //_style = new XLStyle(this, styleToUse); _styleCacheId = Range.Worksheet.Workbook.GetStyleId(styleToUse); _style = null; StyleChanged = false; @@ -104,8 +105,10 @@ ReverseIconOrder = other.ReverseIconOrder; ShowIconOnly = other.ShowIconOnly; ShowBarOnly = other.ShowBarOnly; - - CopyDictionary(Values, other.Values); + + Values.Clear(); + other.Values.ForEach(kp => Values.Add(kp.Key, new XLFormula(kp.Value))); + //CopyDictionary(Values, other.Values); CopyDictionary(Colors, other.Colors); CopyDictionary(ContentTypes, other.ContentTypes); CopyDictionary(IconSetOperators, other.IconSetOperators); diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/DataValidation/XLDataValidation.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/DataValidation/XLDataValidation.cs index 658ae1b..2371e2b 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/DataValidation/XLDataValidation.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/DataValidation/XLDataValidation.cs @@ -148,9 +148,7 @@ public void List(IXLRange range, Boolean inCellDropdown) { - AllowedValues = XLAllowedValues.List; - InCellDropdown = inCellDropdown; - Value = range.RangeAddress.ToStringFixed(); + List(range.RangeAddress.ToStringFixed(XLReferenceStyle.A1, true)); } public void Custom(String customValidation) diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/IXLWorksheet.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/IXLWorksheet.cs index 0197791..6350bba 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/IXLWorksheet.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/IXLWorksheet.cs @@ -364,5 +364,8 @@ IXLRanges SelectedRanges { get; } IXLCell ActiveCell { get; set; } + + Object Evaluate(String expression); + } } diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Misc/XLFormula.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Misc/XLFormula.cs index 440b4a3..13e7acf 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Misc/XLFormula.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Misc/XLFormula.cs @@ -7,6 +7,15 @@ { public class XLFormula { + public XLFormula() + {} + + public XLFormula(XLFormula defaultFormula) + { + _value = defaultFormula._value; + IsFormula = defaultFormula.IsFormula; + } + internal String _value; public String Value { diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeBase.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeBase.cs index 7ebed05..868e46e 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeBase.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Ranges/XLRangeBase.cs @@ -1057,7 +1057,7 @@ Int32 firstColumnReturn = RangeAddress.FirstAddress.ColumnNumber ; Int32 lastColumnReturn = RangeAddress.FirstAddress.ColumnNumber + numberOfColumns - 1; - Worksheet.BreakConditionalFormatsIntoCells(); + Worksheet.BreakConditionalFormatsIntoCells(cellsToDelete.Except(cellsToInsert.Keys).ToList()); using (var asRange = AsRange()) Worksheet.NotifyRangeShiftedColumns(asRange, numberOfColumns); @@ -1263,7 +1263,7 @@ Int32 firstColumnReturn = RangeAddress.FirstAddress.ColumnNumber; Int32 lastColumnReturn = RangeAddress.LastAddress.ColumnNumber; - Worksheet.BreakConditionalFormatsIntoCells(); + Worksheet.BreakConditionalFormatsIntoCells(cellsToDelete.Except(cellsToInsert.Keys).ToList()); using (var asRange = AsRange()) Worksheet.NotifyRangeShiftedRows(asRange, numberOfRows); @@ -1407,7 +1407,7 @@ var hyperlinksToRemove = Worksheet.Hyperlinks.Where(hl => Contains(hl.Cell.AsRange())).ToList(); hyperlinksToRemove.ForEach(hl => Worksheet.Hyperlinks.Delete(hl)); - Worksheet.BreakConditionalFormatsIntoCells(); + Worksheet.BreakConditionalFormatsIntoCells(cellsToDelete.Except(cellsToInsert.Keys).ToList()); using (var shiftedRange = AsRange()) { if (shiftDeleteCells == XLShiftDeletedCells.ShiftCellsUp) diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Style/XLFill.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Style/XLFill.cs index 354000d..d01c680 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Style/XLFill.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Style/XLFill.cs @@ -154,6 +154,7 @@ _patternType = defaultFill.PatternType; _patternColor = new XLColor(defaultFill.PatternColor); _patternBackgroundColor = new XLColor(defaultFill.PatternBackgroundColor); + PatternBackgroundColorModified = (defaultFill as XLFill).PatternBackgroundColorModified; } #endregion diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook.cs index 8164e53..d9e8791 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Security.AccessControl; +using ClosedXML.Excel.CalcEngine; namespace ClosedXML.Excel { @@ -675,5 +676,25 @@ { return Worksheets.Add(dataTable, sheetName); } + + private XLCalcEngine _calcEngine; + private XLCalcEngine CalcEngine + { + get { return _calcEngine ?? (_calcEngine = new XLCalcEngine(this)); } + } + public Object Evaluate(String expression) + { + return CalcEngine.Evaluate(expression); + } + + private static XLCalcEngine _calcEngineExpr; + private static XLCalcEngine CalcEngineExpr + { + get { return _calcEngineExpr ?? (_calcEngineExpr = new XLCalcEngine()); } + } + public static Object EvaluateExpr(String expression) + { + return CalcEngineExpr.Evaluate(expression); + } } } \ No newline at end of file diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorksheet.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorksheet.cs index 4a2ce67..dbafea4 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorksheet.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorksheet.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using ClosedXML.Excel.CalcEngine; namespace ClosedXML.Excel @@ -1253,16 +1254,21 @@ fr.Dispose(); } - internal void BreakConditionalFormatsIntoCells() + + internal void BreakConditionalFormatsIntoCells(List addresses) { var newConditionalFormats = new XLConditionalFormats(); SuspendEvents(); foreach (var conditionalFormat in ConditionalFormats) { - foreach (XLCell cell in conditionalFormat.Range.Cells()) + foreach (XLCell cell in conditionalFormat.Range.Cells(c=>!addresses.Contains(c.Address))) { + var row = cell.Address.RowNumber; + var column = cell.Address.ColumnLetter; var newConditionalFormat = new XLConditionalFormat(cell.AsRange()); newConditionalFormat.CopyFrom(conditionalFormat); + newConditionalFormat.Values.Values.Where(f => f.IsFormula) + .ForEach(f => f._value = XLHelper.ReplaceRelative(f.Value, row, column)); newConditionalFormats.Add(newConditionalFormat); } conditionalFormat.Range.Dispose(); @@ -1271,6 +1277,8 @@ ConditionalFormats = newConditionalFormats; } + + private void MoveNamedRangesRows(XLRange range, int rowsShifted, IXLNamedRanges namedRanges) { foreach (XLNamedRange nr in namedRanges) @@ -1413,9 +1421,14 @@ public IXLCell ActiveCell { get; set; } private XLCalcEngine _calcEngine; - public XLCalcEngine CalcEngine + private XLCalcEngine CalcEngine { get { return _calcEngine ?? (_calcEngine = new XLCalcEngine(this)); } } + + public Object Evaluate(String expression) + { + return CalcEngine.Evaluate(expression); + } } } \ No newline at end of file diff --git a/ClosedXML/ClosedXML/ClosedXML/ExcelHelper.cs b/ClosedXML/ClosedXML/ClosedXML/ExcelHelper.cs index 7aa3828..31a6f9e 100644 --- a/ClosedXML/ClosedXML/ClosedXML/ExcelHelper.cs +++ b/ClosedXML/ClosedXML/ClosedXML/ExcelHelper.cs @@ -236,5 +236,43 @@ #endif } + + private static readonly Regex A1RegexRelative = new Regex( + @"(?<=\W)(?\$?[a-zA-Z]{1,3}\$?\d{1,7})(?=\W)" // A1 + + @"|(?<=\W)(?\$?\d{1,7}:\$?\d{1,7})(?=\W)" // 1:1 + + @"|(?<=\W)(?\$?[a-zA-Z]{1,3}:\$?[a-zA-Z]{1,3})(?=\W)", RegexOptions.Compiled); // A:A + + private static string Evaluator(Match match, Int32 row, String column) + { + if (match.Groups["one"].Success) + { + var split = match.Groups["one"].Value.Split('$'); + if (split.Length == 1) return column + row; // A1 + if (split.Length == 3) return match.Groups["one"].Value; // $A$1 + var a = XLAddress.Create(match.Groups["one"].Value); + if (split[0] == String.Empty) return "$" + a.ColumnLetter + row; // $A1 + return column + "$" + a.RowNumber; + } + + if (match.Groups["two"].Success) + return ReplaceGroup(match.Groups["two"].Value, row.ToString()); + + return ReplaceGroup(match.Groups["three"].Value, column); + } + + private static String ReplaceGroup(String value, String item) + { + var split = value.Split(':'); + String ret1 = split[0].StartsWith("$") ? split[0] : item; + String ret2 = split[1].StartsWith("$") ? split[1] : item; + return ret1 + ":" + ret2; + } + + internal static String ReplaceRelative(String value, Int32 row, String column) + { + var oldValue = ">" + value + "<"; + var newVal = A1RegexRelative.Replace(oldValue, m => Evaluator(m, row, column)); + return newVal.Substring(1, newVal.Length - 2); + } } } \ No newline at end of file diff --git a/ClosedXML/ClosedXML/ClosedXML_Tests/ClosedXML_Tests.csproj b/ClosedXML/ClosedXML/ClosedXML_Tests/ClosedXML_Tests.csproj index 28ff5dd..e5d6375 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Tests/ClosedXML_Tests.csproj +++ b/ClosedXML/ClosedXML/ClosedXML_Tests/ClosedXML_Tests.csproj @@ -76,6 +76,7 @@ + diff --git a/ClosedXML/ClosedXML/ClosedXML_Tests/Excel/CalcEngine/FunctionsTests.cs b/ClosedXML/ClosedXML/ClosedXML_Tests/Excel/CalcEngine/FunctionsTests.cs new file mode 100644 index 0000000..ffb0143 --- /dev/null +++ b/ClosedXML/ClosedXML/ClosedXML_Tests/Excel/CalcEngine/FunctionsTests.cs @@ -0,0 +1,120 @@ +using System; +using System.IO; +using System.Text; +using System.Collections.Generic; +using System.Linq; +using ClosedXML.Excel; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ClosedXML_Tests.Excel.DataValidations +{ + /// + /// Summary description for UnitTest1 + /// + [TestClass] + public class FunctionsTests + { + [TestMethod] + public void Even() + { + var actual1 = XLWorkbook.EvaluateExpr("Even(1.5)"); + Assert.AreEqual(2.0, actual1); + var actual2 = XLWorkbook.EvaluateExpr("Even(2.01)"); + Assert.AreEqual(4.0, actual2); + } + + [TestMethod] + public void Combin() + { + var actual1 = XLWorkbook.EvaluateExpr("Combin(200, 2)"); + Assert.AreEqual(19900.0, actual1); + + var actual2 = XLWorkbook.EvaluateExpr("Combin(20.1, 2.9)"); + Assert.AreEqual(190.0, actual2); + } + + [TestMethod] + public void Degrees() + { + var actual1 = XLWorkbook.EvaluateExpr("Degrees(180)"); + Assert.IsTrue(Math.PI - (double)actual1 < XLHelper.Epsilon); + } + + [TestMethod] + public void Fact() + { + var actual = XLWorkbook.EvaluateExpr("Fact(5.9)"); + Assert.AreEqual(120.0, actual); + } + + [TestMethod] + public void FactDouble() + { + var actual1 = XLWorkbook.EvaluateExpr("FactDouble(6)"); + Assert.AreEqual(48.0, actual1); + var actual2 = XLWorkbook.EvaluateExpr("FactDouble(7)"); + Assert.AreEqual(105.0, actual2); + } + + [TestMethod] + public void Gcd() + { + var actual = XLWorkbook.EvaluateExpr("Gcd(24, 36)"); + Assert.AreEqual(12, actual); + + var actual1 = XLWorkbook.EvaluateExpr("Gcd(5, 0)"); + Assert.AreEqual(5, actual1); + + var actual2 = XLWorkbook.EvaluateExpr("Gcd(0, 5)"); + Assert.AreEqual(5, actual2); + + var actual3 = XLWorkbook.EvaluateExpr("Gcd(240, 360, 30)"); + Assert.AreEqual(30, actual3); + } + + [TestMethod] + public void Lcm() + { + var actual = XLWorkbook.EvaluateExpr("Lcm(24, 36)"); + Assert.AreEqual(72, actual); + + var actual1 = XLWorkbook.EvaluateExpr("Lcm(5, 0)"); + Assert.AreEqual(0, actual1); + + var actual2 = XLWorkbook.EvaluateExpr("Lcm(0, 5)"); + Assert.AreEqual(0, actual2); + + var actual3 = XLWorkbook.EvaluateExpr("Lcm(240, 360, 30)"); + Assert.AreEqual(720, actual3); + } + + [TestMethod] + public void Mod() + { + var actual = XLWorkbook.EvaluateExpr("Mod(3, 2)"); + Assert.AreEqual(1, actual); + + var actual1 = XLWorkbook.EvaluateExpr("Mod(-3, 2)"); + Assert.AreEqual(1, actual1); + + var actual2 = XLWorkbook.EvaluateExpr("Mod(3, -2)"); + Assert.AreEqual(-1, actual2); + + var actual3 = XLWorkbook.EvaluateExpr("Mod(-3, -2)"); + Assert.AreEqual(-1, actual3); + } + + [TestMethod] + public void MRound() + { + //var actual = XLWorkbook.EvaluateExpr("MRound(10, 3)"); + //Assert.AreEqual(9.0, actual); + + //var actual1 = XLWorkbook.EvaluateExpr("MRound(-10, -10)"); + //Assert.AreEqual(-9.0, actual1); + + //var actual2 = XLWorkbook.EvaluateExpr("MRound(1.3, 0.2)"); + //Assert.AreEqual(1.4, actual2); + } + } +} diff --git a/ClosedXML/ClosedXML/ClosedXML_Tests/Excel/DataValidations/DataValidationTests.cs b/ClosedXML/ClosedXML/ClosedXML_Tests/Excel/DataValidations/DataValidationTests.cs index 10cfe9e..923a287 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Tests/Excel/DataValidations/DataValidationTests.cs +++ b/ClosedXML/ClosedXML/ClosedXML_Tests/Excel/DataValidations/DataValidationTests.cs @@ -74,7 +74,7 @@ cell.DataValidation.InputTitle = "Title for B2"; Assert.AreEqual(cell.DataValidation.AllowedValues, XLAllowedValues.List); - Assert.AreEqual(cell.DataValidation.Value, "$E$1:$E$4"); + Assert.AreEqual(cell.DataValidation.Value, "'Data Validation Issue'!$E$1:$E$4"); Assert.AreEqual(cell.DataValidation.InputTitle, "Title for B2"); @@ -84,7 +84,7 @@ cell.DataValidation.InputMessage = "Message for C2"; Assert.AreEqual(cell.DataValidation.AllowedValues, XLAllowedValues.List); - Assert.AreEqual(cell.DataValidation.Value, "$E$1:$E$4"); + Assert.AreEqual(cell.DataValidation.Value, "'Data Validation Issue'!$E$1:$E$4"); Assert.AreEqual(cell.DataValidation.InputMessage, "Message for C2"); ws.Cell("D1").SetValue("Cell below has Validation with title and message."); @@ -94,7 +94,7 @@ cell.DataValidation.InputMessage = "Message for D2"; Assert.AreEqual(cell.DataValidation.AllowedValues, XLAllowedValues.List); - Assert.AreEqual(cell.DataValidation.Value, "$E$1:$E$4"); + Assert.AreEqual(cell.DataValidation.Value, "'Data Validation Issue'!$E$1:$E$4"); Assert.AreEqual(cell.DataValidation.InputTitle, "Title for D2"); Assert.AreEqual(cell.DataValidation.InputMessage, "Message for D2"); } diff --git a/ClosedXML/ClosedXML/ClosedXML_Tests/ExcelHelperTest.cs b/ClosedXML/ClosedXML/ClosedXML_Tests/ExcelHelperTest.cs index 08212a0..b7f8cd1 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Tests/ExcelHelperTest.cs +++ b/ClosedXML/ClosedXML/ClosedXML_Tests/ExcelHelperTest.cs @@ -4,36 +4,21 @@ namespace ClosedXML_Tests { - - - /// - ///This is a test class for XLHelperTest and is intended - ///to contain all XLHelperTest Unit Tests + /// + /// This is a test class for XLHelperTest and is intended + /// to contain all XLHelperTest Unit Tests /// - [TestClass()] + [TestClass] public class XLHelperTest { - - - private TestContext testContextInstance; - - /// - ///Gets or sets the test context which provides - ///information about and functionality for the current test run. + /// + /// Gets or sets the test context which provides + /// information about and functionality for the current test run. /// - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } + public TestContext TestContext { get; set; } #region Additional test attributes + // //You can use the following additional attributes as you write your tests: // @@ -61,13 +46,13 @@ //{ //} // + #endregion - - /// - ///A test for IsValidColumn + /// + /// A test for IsValidColumn /// - [TestMethod()] + [TestMethod] public void IsValidColumnTest() { Assert.AreEqual(false, XLHelper.IsValidColumn("")); @@ -84,6 +69,89 @@ Assert.AreEqual(false, XLHelper.IsValidColumn("XZA")); Assert.AreEqual(false, XLHelper.IsValidColumn("XFZ")); } - } -} + [TestMethod] + public void ReplaceRelative1() + { + var result = XLHelper.ReplaceRelative("A1", 2, "B"); + Assert.AreEqual("B2", result); + } + + [TestMethod] + public void ReplaceRelative2() + { + var result = XLHelper.ReplaceRelative("$A1", 2, "B"); + Assert.AreEqual("$A2", result); + } + + [TestMethod] + public void ReplaceRelative3() + { + var result = XLHelper.ReplaceRelative("A$1", 2, "B"); + Assert.AreEqual("B$1", result); + } + + [TestMethod] + public void ReplaceRelative4() + { + var result = XLHelper.ReplaceRelative("$A$1", 2, "B"); + Assert.AreEqual("$A$1", result); + } + + [TestMethod] + public void ReplaceRelative5() + { + var result = XLHelper.ReplaceRelative("1:1", 2, "B"); + Assert.AreEqual("2:2", result); + } + + [TestMethod] + public void ReplaceRelative6() + { + var result = XLHelper.ReplaceRelative("$1:1", 2, "B"); + Assert.AreEqual("$1:2", result); + } + + [TestMethod] + public void ReplaceRelative7() + { + var result = XLHelper.ReplaceRelative("1:$1", 2, "B"); + Assert.AreEqual("2:$1", result); + } + + [TestMethod] + public void ReplaceRelative8() + { + var result = XLHelper.ReplaceRelative("$1:$1", 2, "B"); + Assert.AreEqual("$1:$1", result); + } + + [TestMethod] + public void ReplaceRelative9() + { + var result = XLHelper.ReplaceRelative("A:A", 2, "B"); + Assert.AreEqual("B:B", result); + } + + [TestMethod] + public void ReplaceRelativeA() + { + var result = XLHelper.ReplaceRelative("$A:A", 2, "B"); + Assert.AreEqual("$A:B", result); + } + + [TestMethod] + public void ReplaceRelativeB() + { + var result = XLHelper.ReplaceRelative("A:$A", 2, "B"); + Assert.AreEqual("B:$A", result); + } + + [TestMethod] + public void ReplaceRelativeC() + { + var result = XLHelper.ReplaceRelative("$A:$A", 2, "B"); + Assert.AreEqual("$A:$A", result); + } + } +} \ No newline at end of file diff --git a/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFColorScaleLowHigh.xlsx b/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFColorScaleLowHigh.xlsx index 6615729..0081bfd 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFColorScaleLowHigh.xlsx +++ b/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFColorScaleLowHigh.xlsx Binary files differ diff --git a/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFColorScaleLowMidHigh.xlsx b/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFColorScaleLowMidHigh.xlsx index bec8a78..87f8d4f 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFColorScaleLowMidHigh.xlsx +++ b/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFColorScaleLowMidHigh.xlsx Binary files differ diff --git a/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFDataBar.xlsx b/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFDataBar.xlsx index f2f12ea..c6803d4 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFDataBar.xlsx +++ b/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFDataBar.xlsx Binary files differ diff --git a/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFIconSet.xlsx b/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFIconSet.xlsx index 6c15573..8034b13 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFIconSet.xlsx +++ b/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFIconSet.xlsx Binary files differ diff --git a/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/Misc/DataValidation.xlsx b/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/Misc/DataValidation.xlsx index 2cfd482..349758b 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/Misc/DataValidation.xlsx +++ b/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/Misc/DataValidation.xlsx Binary files differ diff --git a/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/Misc/Formulas.xlsx b/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/Misc/Formulas.xlsx index 67a8fc8..04a3383 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/Misc/Formulas.xlsx +++ b/ClosedXML/ClosedXML/ClosedXML_Tests/Resource/Examples/Misc/Formulas.xlsx Binary files differ