diff --git a/ClosedXML/Attributes/ColumnOrderAttribute.cs b/ClosedXML/Attributes/ColumnOrderAttribute.cs
new file mode 100644
index 0000000..b85c541
--- /dev/null
+++ b/ClosedXML/Attributes/ColumnOrderAttribute.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace ClosedXML.Attributes
+{
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
+ public class ColumnOrderAttribute : Attribute
+ {
+ public ColumnOrderAttribute(long order)
+ {
+ this.Order = order;
+ }
+
+ public long Order { get; private set; }
+ }
+}
diff --git a/ClosedXML/ClosedXML.csproj b/ClosedXML/ClosedXML.csproj
index 12bf76a..d4073e5 100644
--- a/ClosedXML/ClosedXML.csproj
+++ b/ClosedXML/ClosedXML.csproj
@@ -22,7 +22,7 @@
false
bin\Debug\
DEBUG;TRACE
- NET4
+ NET4;TRACE;DEBUG
prompt
4
1591
@@ -32,7 +32,7 @@
true
bin\Release\
TRACE
- NET4
+ NET4;TRACE
prompt
4
bin\Release\ClosedXML.xml
@@ -61,15 +61,17 @@
+
-
+
+
diff --git a/ClosedXML/Excel/CalcEngine/CalcEngine.cs b/ClosedXML/Excel/CalcEngine/CalcEngine.cs
index b946fa2..9ba60b2 100644
--- a/ClosedXML/Excel/CalcEngine/CalcEngine.cs
+++ b/ClosedXML/Excel/CalcEngine/CalcEngine.cs
@@ -9,8 +9,7 @@
using ClosedXML.Excel.CalcEngine;
using ClosedXML.Excel.CalcEngine.Functions;
-namespace ClosedXML.Excel.CalcEngine
-{
+namespace ClosedXML.Excel.CalcEngine {
///
/// CalcEngine parses strings and returns Expression objects that can
/// be evaluated.
@@ -21,19 +20,18 @@
/// Use the RegisterFunction method to define custom functions.
/// Override the GetExternalObject method to add arbitrary variables to the engine scope.
///
- internal class CalcEngine
- {
- //---------------------------------------------------------------------------
- #region ** fields
+ internal class CalcEngine {
+ //---------------------------------------------------------------------------
+ #region ** fields
- // members
- string _expr; // expression being parsed
- int _len; // length of the expression being parsed
- int _ptr; // current pointer into expression
- string _idChars; // valid characters in identifiers (besides alpha and digits)
- Token _token; // current token being parsed
+ // members
+ string _expr; // expression being parsed
+ int _len; // length of the expression being parsed
+ int _ptr; // current pointer into expression
+ string _idChars; // valid characters in identifiers (besides alpha and digits)
+ Token _token; // current token being parsed
Dictionary
- public bool OptimizeExpressions
- {
+ public bool OptimizeExpressions {
get { return _optimize; }
set { _optimize = value; }
}
@@ -154,8 +142,7 @@
/// additional valid characters such as ':' or '!' (used in Excel range references
/// for example).
///
- public string IdentifierChars
- {
+ public string IdentifierChars {
get { return _idChars; }
set { _idChars = value; }
}
@@ -166,8 +153,7 @@
/// Minimum parameter count.
/// Maximum parameter count.
/// Delegate that evaluates the function.
- public void RegisterFunction(string functionName, int parmMin, int parmMax, CalcEngineFunction fn)
- {
+ public void RegisterFunction(string functionName, int parmMin, int parmMax, CalcEngineFunction fn) {
_fnTbl.Add(functionName, new FunctionDefinition(parmMin, parmMax, fn));
}
///
@@ -176,8 +162,7 @@
/// Function name.
/// Parameter count.
/// Delegate that evaluates the function.
- public void RegisterFunction(string functionName, int parmCount, CalcEngineFunction fn)
- {
+ public void RegisterFunction(string functionName, int parmCount, CalcEngineFunction fn) {
RegisterFunction(functionName, parmCount, parmCount, fn);
}
///
@@ -189,8 +174,7 @@
/// range objects based on identifiers that cannot be enumerated at design time
/// (such as "AB12", "A1:AB12", etc.)
///
- public virtual object GetExternalObject(string identifier)
- {
+ public virtual object GetExternalObject(string identifier) {
return null;
}
///
@@ -201,33 +185,28 @@
/// to the CalcEngine, including sub-properties such as "Address.Street". These may
/// be used with expressions just like any other constant.
///
- public virtual object DataContext
- {
+ public virtual object DataContext {
get { return _dataContext; }
set { _dataContext = value; }
}
///
/// Gets the dictionary that contains function definitions.
///
- public Dictionary Functions
- {
+ public Dictionary Functions {
get { return _fnTbl; }
}
///
/// Gets the dictionary that contains simple variables (not in the DataContext).
///
- public Dictionary Variables
- {
+ public Dictionary Variables {
get { return _vars; }
}
///
/// Gets or sets the to use when parsing numbers and dates.
///
- public CultureInfo CultureInfo
- {
+ public CultureInfo CultureInfo {
get { return _ci; }
- set
- {
+ set {
_ci = value;
var nf = _ci.NumberFormat;
_decimal = nf.NumberDecimalSeparator[0];
@@ -236,16 +215,14 @@
}
}
- #endregion
+ #endregion
//---------------------------------------------------------------------------
#region ** token/keyword tables
// build/get static token table
- Dictionary
+
+ Attributes\ColumnOrderAttribute.cs
+
Excel\AutoFilters\IXLAutoFilter.cs
@@ -109,8 +112,8 @@
Excel\CalcEngine\Functions\DateAndTime.cs
-
- Excel\CalcEngine\Functions\Is.cs
+
+ Excel\CalcEngine\Functions\Information.cs
Excel\CalcEngine\Functions\Logical.cs
@@ -817,6 +820,9 @@
Utils\GraphicsUtils.cs
+
+ Utils\XmlEncoder.cs
+
XLHelper.cs
diff --git a/ClosedXML_Net3.5/Excel/CalcEngine/Functions/Information.cs b/ClosedXML_Net3.5/Excel/CalcEngine/Functions/Information.cs
new file mode 100644
index 0000000..dcb1340
--- /dev/null
+++ b/ClosedXML_Net3.5/Excel/CalcEngine/Functions/Information.cs
@@ -0,0 +1,152 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing.Design;
+
+namespace ClosedXML.Excel.CalcEngine.Functions
+{
+ internal static class Information
+ {
+ public static void Register(CalcEngine ce)
+ {
+ ce.RegisterFunction("ERRORTYPE",1,ErrorType);
+ ce.RegisterFunction("ISBLANK", 1,int.MaxValue, IsBlank);
+ ce.RegisterFunction("ISERR",1, int.MaxValue, IsErr);
+ ce.RegisterFunction("ISERROR",1, int.MaxValue, IsError);
+ ce.RegisterFunction("ISEVEN",1, IsEven);
+ ce.RegisterFunction("ISLOGICAL",1,int.MaxValue,IsLogical);
+ ce.RegisterFunction("ISNA",1, int.MaxValue, IsNa);
+ ce.RegisterFunction("ISNONTEXT",1, int.MaxValue, IsNonText);
+ ce.RegisterFunction("ISNUMBER",1, int.MaxValue, IsNumber);
+ ce.RegisterFunction("ISODD",1,IsOdd);
+ ce.RegisterFunction("ISREF",1, int.MaxValue, IsRef);
+ ce.RegisterFunction("ISTEXT",1, int.MaxValue, IsText);
+ ce.RegisterFunction("N",1,N);
+ ce.RegisterFunction("NA",0,NA);
+ ce.RegisterFunction("TYPE",1,Type);
+ }
+
+ static object ErrorType(List p)
+ {
+ //TODO: Write Code
+ throw new NotSupportedException();;
+ }
+
+ static object IsBlank(List p)
+ {
+ var v = (string) p[0].Evaluate();
+ var isBlank = string.IsNullOrEmpty(v);
+ p.RemoveAt(0);
+
+ if (isBlank && p.Count > 0) {
+ isBlank = (bool)IsBlank(p);
+ }
+
+ return isBlank;
+ }
+
+ //TODO: Support for Error Values
+ static object IsErr(List p)
+ {
+ //TODO: Write Code
+ throw new NotSupportedException();
+ }
+
+ static object IsError(List p)
+ {
+ //TODO: Write Code
+ throw new NotSupportedException();
+ }
+
+ static object IsEven(List p)
+ {
+ var v = p[0].Evaluate();
+ if (v is double)
+ {
+ return Math.Abs((double) v%2) < 0;
+ }
+ throw new ArgumentException("Expression doesn't evaluate to double");
+ }
+
+ static object IsLogical(List p)
+ {
+ var v = p[0].Evaluate();
+ var isLogical = v is bool;
+ p.RemoveAt(0);
+
+ if (isLogical && p.Count > 0)
+ {
+ isLogical = (bool) IsLogical(p);
+ }
+
+ return isLogical;
+ }
+
+ static object IsNa(List p)
+ {
+ //TODO: Write Code
+ throw new NotSupportedException();;
+ }
+
+ static object IsNonText(List p)
+ {
+ return !(bool) IsText(p);
+ }
+
+ static object IsNumber(List p)
+ {
+ var v = p[0].Evaluate();
+ var isNumber = v is double;
+ p.RemoveAt(0);
+
+ if (isNumber && p.Count > 0) {
+ isNumber = (bool)IsNumber(p);
+ }
+
+ return isNumber;
+ }
+
+ static object IsOdd(List p)
+ {
+ return !(bool) IsEven(p);
+ }
+
+ static object IsRef(List p)
+ {
+ //TODO: Write Code
+ throw new NotSupportedException();;
+ }
+
+ static object IsText(List p)
+ {
+ //Evaluate Expressions
+ var isText = !(bool) IsBlank(p);
+ if (isText)
+ {
+ isText = !(bool) IsNumber(p);
+ }
+ if (isText)
+ {
+ isText = !(bool) IsLogical(p);
+ }
+ return isText;
+ }
+
+ static object N(List p)
+ {
+ //TODO: Write Code
+ throw new NotSupportedException();;
+ }
+
+ static object NA(List p)
+ {
+ //TODO: Write Code
+ throw new NotSupportedException();;
+ }
+
+ static object Type(List p)
+ {
+ //TODO: Write Code
+ throw new NotSupportedException();;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ClosedXML_Tests/ClosedXML_Tests.csproj b/ClosedXML_Tests/ClosedXML_Tests.csproj
index d4d5ba6..89a0eff 100644
--- a/ClosedXML_Tests/ClosedXML_Tests.csproj
+++ b/ClosedXML_Tests/ClosedXML_Tests.csproj
@@ -70,12 +70,15 @@
-
+
+
+
+
@@ -138,6 +141,7 @@
+
@@ -229,6 +233,7 @@
+
@@ -245,10 +250,12 @@
-
+
-
+
+
+
diff --git a/ClosedXML_Tests/Examples/ConditionalFormattingTests.cs b/ClosedXML_Tests/Examples/ConditionalFormattingTests.cs
index 823ebeb..1ab8fe2 100644
--- a/ClosedXML_Tests/Examples/ConditionalFormattingTests.cs
+++ b/ClosedXML_Tests/Examples/ConditionalFormattingTests.cs
@@ -19,6 +19,12 @@
}
[Test]
+ public void CFColorScaleMinimumMaximum()
+ {
+ TestHelper.RunTestExample(@"ConditionalFormatting\CFColorScaleMinimumMaximum.xlsx");
+ }
+
+ [Test]
public void CFContains()
{
TestHelper.RunTestExample(@"ConditionalFormatting\CFContains.xlsx");
@@ -107,23 +113,5 @@
{
TestHelper.RunTestExample(@"ConditionalFormatting\CFMultipleConditions.xlsx");
}
-
- //[Test]
- //public void XXX()
- //{
- // TestHelper.RunTestExample(@"ConditionalFormatting\XXX.xlsx");
- //}
- //
- //[Test]
- //public void XXX()
- //{
- // TestHelper.RunTestExample(@"ConditionalFormatting\XXX.xlsx");
- //}
- //
- //[Test]
- //public void XXX()
- //{
- // TestHelper.RunTestExample(@"ConditionalFormatting\XXX.xlsx");
- //}
}
-}
\ No newline at end of file
+}
diff --git a/ClosedXML_Tests/Examples/MiscTests.cs b/ClosedXML_Tests/Examples/MiscTests.cs
index 38f7e8e..eebb483 100644
--- a/ClosedXML_Tests/Examples/MiscTests.cs
+++ b/ClosedXML_Tests/Examples/MiscTests.cs
@@ -26,6 +26,12 @@
}
[Test]
+ public void AdjustToContentsWithAutoFilter()
+ {
+ TestHelper.RunTestExample(@"Misc\AdjustToContentsWithAutoFilter.xlsx");
+ }
+
+ [Test]
public void AutoFilter()
{
TestHelper.RunTestExample(@"Misc\AutoFilter.xlsx");
@@ -152,6 +158,12 @@
}
[Test]
+ public void RightToLeft()
+ {
+ TestHelper.RunTestExample(@"Misc\RightToLeft.xlsx");
+ }
+
+ [Test]
public void SheetProtection()
{
TestHelper.RunTestExample(@"Misc\SheetProtection.xlsx");
@@ -181,4 +193,4 @@
TestHelper.RunTestExample(@"Misc\WorkbookProperties.xlsx");
}
}
-}
\ No newline at end of file
+}
diff --git a/ClosedXML_Tests/Excel/CalcEngine/DateAndTimeTests.cs b/ClosedXML_Tests/Excel/CalcEngine/DateAndTimeTests.cs
index 6213f8c..b6202d9 100644
--- a/ClosedXML_Tests/Excel/CalcEngine/DateAndTimeTests.cs
+++ b/ClosedXML_Tests/Excel/CalcEngine/DateAndTimeTests.cs
@@ -40,6 +40,16 @@
}
[Test]
+ public void Days()
+ {
+ Object actual = XLWorkbook.EvaluateExpr("DAYS(DATE(2016,10,1),DATE(1992,2,29))");
+ Assert.AreEqual(8981, actual);
+
+ actual = XLWorkbook.EvaluateExpr("DAYS(\"2016-10-1\",\"1992-2-29\")");
+ Assert.AreEqual(8981, actual);
+ }
+
+ [Test]
public void DayWithDifferentCulture()
{
CultureInfo ci = new CultureInfo(CultureInfo.InvariantCulture.LCID);
@@ -148,6 +158,16 @@
}
[Test]
+ public void IsoWeekNum()
+ {
+ Object actual = XLWorkbook.EvaluateExpr("ISOWEEKNUM(DATEVALUE(\"2012-3-9\"))");
+ Assert.AreEqual(10, actual);
+
+ actual = XLWorkbook.EvaluateExpr("ISOWEEKNUM(DATE(2012,12,31))");
+ Assert.AreEqual(1, actual);
+ }
+
+ [Test]
public void Networkdays_MultipleHolidaysGiven()
{
var wb = new XLWorkbook();
@@ -473,4 +493,4 @@
Assert.IsTrue(XLHelper.AreEqual(5.24722222222222, (double) actual));
}
}
-}
\ No newline at end of file
+}
diff --git a/ClosedXML_Tests/Excel/CalcEngine/InformationTests.cs b/ClosedXML_Tests/Excel/CalcEngine/InformationTests.cs
new file mode 100644
index 0000000..351ad70
--- /dev/null
+++ b/ClosedXML_Tests/Excel/CalcEngine/InformationTests.cs
@@ -0,0 +1,401 @@
+using ClosedXML.Excel;
+using NUnit.Framework;
+using System;
+using System.Globalization;
+using System.Threading;
+
+namespace ClosedXML_Tests.Excel.CalcEngine
+{
+ [TestFixture]
+ public class InformationTests
+ {
+ [OneTimeSetUp]
+ public void SetCultureInfo()
+ {
+ Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
+ }
+
+ #region IsBlank Tests
+
+ [Test]
+ public void IsBlank_MultipleAllEmpty_true()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+ var actual = ws.Evaluate("=IsBlank(A1:A3)");
+ Assert.AreEqual(true, actual);
+ }
+ }
+
+ [Test]
+ public void IsBlank_MultipleAllFill_false()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+ ws.Cell("A1").Value = "1";
+ ws.Cell("A2").Value = "1";
+ ws.Cell("A3").Value = "1";
+ var actual = ws.Evaluate("=IsBlank(A1:A3)");
+ Assert.AreEqual(false, actual);
+ }
+ }
+
+ [Test]
+ public void IsBlank_MultipleMixedFill_false()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+ ws.Cell("A1").Value = "1";
+ ws.Cell("A3").Value = "1";
+ var actual = ws.Evaluate("=IsBlank(A1:A3)");
+ Assert.AreEqual(false, actual);
+ }
+ }
+
+ [Test]
+ public void IsBlank_Single_false()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+ ws.Cell("A1").Value = " ";
+ var actual = ws.Evaluate("=IsBlank(A1)");
+ Assert.AreEqual(false, actual);
+ }
+ }
+
+ [Test]
+ public void IsBlank_Single_true()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+ var actual = ws.Evaluate("=IsBlank(A1)");
+ Assert.AreEqual(true, actual);
+ }
+ }
+ #endregion IsBlank Tests
+
+ #region IsEven Tests
+
+ [Test]
+ public void IsEven_Single_False()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+
+ ws.Cell("A1").Value = 1;
+ ws.Cell("A2").Value = 1.2;
+ ws.Cell("A3").Value = 3;
+
+ var actual = ws.Evaluate("=IsEven(A1)");
+ Assert.AreEqual(false, actual);
+
+ actual = ws.Evaluate("=IsEven(A2)");
+ Assert.AreEqual(false, actual);
+
+ actual = ws.Evaluate("=IsEven(A3)");
+ Assert.AreEqual(false, actual);
+ }
+ }
+
+ [Test]
+ public void IsEven_Single_True()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+
+ ws.Cell("A1").Value = 4;
+ ws.Cell("A2").Value = 0.2;
+ ws.Cell("A3").Value = 12.2;
+
+ var actual = ws.Evaluate("=IsEven(A1)");
+ Assert.AreEqual(true, actual);
+
+ actual = ws.Evaluate("=IsEven(A2)");
+ Assert.AreEqual(true, actual);
+
+ actual = ws.Evaluate("=IsEven(A3)");
+ Assert.AreEqual(true, actual);
+ }
+ }
+
+ #endregion IsEven Tests
+
+ #region IsLogical Tests
+
+ [Test]
+ public void IsLogical_Simpe_False()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+
+ ws.Cell("A1").Value = 123;
+
+ var actual = ws.Evaluate("=IsLogical(A1)");
+ Assert.AreEqual(false, actual);
+ }
+ }
+
+ [Test]
+ public void IsLogical_Simple_True()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+
+ ws.Cell("A1").Value = true;
+
+ var actual = ws.Evaluate("=IsLogical(A1)");
+ Assert.AreEqual(true, actual);
+ }
+ }
+ #endregion IsLogical Tests
+
+ #region IsNotText Tests
+
+ [Test]
+ public void IsNotText_Simple_false()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+ ws.Cell("A1").Value = "asd";
+ var actual = ws.Evaluate("=IsNonText(A1)");
+ Assert.AreEqual(false, actual);
+ }
+ }
+
+ [Test]
+ public void IsNotText_Simple_true()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+ ws.Cell("A1").Value = "123"; //Double Value
+ ws.Cell("A2").Value = DateTime.Now; //Date Value
+ ws.Cell("A3").Value = "12,235.5"; //Comma Formatting
+ ws.Cell("A4").Value = "$12,235.5"; //Currency Value
+ ws.Cell("A5").Value = true; //Bool Value
+ ws.Cell("A6").Value = "12%"; //Percentage Value
+
+ var actual = ws.Evaluate("=IsNonText(A1)");
+ Assert.AreEqual(true, actual);
+ actual = ws.Evaluate("=IsNonText(A2)");
+ Assert.AreEqual(true, actual);
+ actual = ws.Evaluate("=IsNonText(A3)");
+ Assert.AreEqual(true, actual);
+ actual = ws.Evaluate("=IsNonText(A4)");
+ Assert.AreEqual(true, actual);
+ actual = ws.Evaluate("=IsNonText(A5)");
+ Assert.AreEqual(true, actual);
+ actual = ws.Evaluate("=IsNonText(A6)");
+ Assert.AreEqual(true, actual);
+ }
+ }
+ #endregion IsNotText Tests
+
+ #region IsNumber Tests
+
+ [Test]
+ public void IsNumber_Simple_false()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+ ws.Cell("A1").Value = "asd"; //String Value
+ ws.Cell("A2").Value = true; //Bool Value
+
+ var actual = ws.Evaluate("=IsNumber(A1)");
+ Assert.AreEqual(false, actual);
+ actual = ws.Evaluate("=IsNumber(A2)");
+ Assert.AreEqual(false, actual);
+ }
+ }
+
+ [Test]
+ public void IsNumber_Simple_true()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+ ws.Cell("A1").Value = "123"; //Double Value
+ ws.Cell("A2").Value = DateTime.Now; //Date Value
+ ws.Cell("A3").Value = "12,235.5"; //Coma Formatting
+ ws.Cell("A4").Value = "$12,235.5"; //Currency Value
+ ws.Cell("A5").Value = "12%"; //Percentage Value
+
+ var actual = ws.Evaluate("=IsNumber(A1)");
+ Assert.AreEqual(true, actual);
+ actual = ws.Evaluate("=IsNumber(A2)");
+ Assert.AreEqual(true, actual);
+ actual = ws.Evaluate("=IsNumber(A3)");
+ Assert.AreEqual(true, actual);
+ actual = ws.Evaluate("=IsNumber(A4)");
+ Assert.AreEqual(true, actual);
+ actual = ws.Evaluate("=IsNumber(A5)");
+ Assert.AreEqual(true, actual);
+ }
+ }
+ #endregion IsNumber Tests
+
+ #region IsOdd Test
+
+ [Test]
+ public void IsOdd_Simple_false()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+
+ ws.Cell("A1").Value = 4;
+ ws.Cell("A2").Value = 0.2;
+ ws.Cell("A3").Value = 12.2;
+
+ var actual = ws.Evaluate("=IsOdd(A1)");
+ Assert.AreEqual(false, actual);
+ actual = ws.Evaluate("=IsOdd(A2)");
+ Assert.AreEqual(false, actual);
+ actual = ws.Evaluate("=IsOdd(A3)");
+ Assert.AreEqual(false, actual);
+ }
+ }
+
+ [Test]
+ public void IsOdd_Simple_true()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+
+ ws.Cell("A1").Value = 1;
+ ws.Cell("A2").Value = 1.2;
+ ws.Cell("A3").Value = 3;
+
+ var actual = ws.Evaluate("=IsOdd(A1)");
+ Assert.AreEqual(true, actual);
+ actual = ws.Evaluate("=IsOdd(A2)");
+ Assert.AreEqual(true, actual);
+ actual = ws.Evaluate("=IsOdd(A3)");
+ Assert.AreEqual(true, actual);
+ }
+ }
+ #endregion IsOdd Test
+
+ #region IsText Tests
+
+ [Test]
+ public void IsText_Simple_false()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+ ws.Cell("A1").Value = "123"; //Double Value
+ ws.Cell("A2").Value = DateTime.Now; //Date Value
+ ws.Cell("A3").Value = "12,235.5"; //Comma Formatting
+ ws.Cell("A4").Value = "$12,235.5"; //Currency Value
+ ws.Cell("A5").Value = true; //Bool Value
+ ws.Cell("A6").Value = "12%"; //Percentage Value
+
+ var actual = ws.Evaluate("=IsText(A1)");
+ Assert.AreEqual(false, actual);
+ actual = ws.Evaluate("=IsText(A2)");
+ Assert.AreEqual(false, actual);
+ actual = ws.Evaluate("=IsText(A3)");
+ Assert.AreEqual(false, actual);
+ actual = ws.Evaluate("=IsText(A4)");
+ Assert.AreEqual(false, actual);
+ actual = ws.Evaluate("=IsText(A5)");
+ Assert.AreEqual(false, actual);
+ actual = ws.Evaluate("=IsText(A6)");
+ Assert.AreEqual(false, actual);
+ }
+ }
+
+ [Test]
+ public void IsText_Simple_true()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+
+ ws.Cell("A1").Value = "asd";
+
+ var actual = ws.Evaluate("=IsText(A1)");
+ Assert.AreEqual(true, actual);
+ }
+ }
+ #endregion IsText Tests
+
+ #region N Tests
+
+ [Test]
+ public void N_Date_SerialNumber()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+ var testedDate = DateTime.Now;
+ ws.Cell("A1").Value = testedDate;
+ var actual = ws.Evaluate("=N(A1)");
+ Assert.AreEqual(testedDate.ToOADate(), actual);
+ }
+ }
+
+ [Test]
+ public void N_False_Zero()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+ ws.Cell("A1").Value = false;
+ var actual = ws.Evaluate("=N(A1)");
+ Assert.AreEqual(0, actual);
+ }
+ }
+
+ [Test]
+ public void N_Number_Number()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+ var testedValue = 123;
+ ws.Cell("A1").Value = testedValue;
+ var actual = ws.Evaluate("=N(A1)");
+ Assert.AreEqual(testedValue, actual);
+ }
+ }
+
+ [Test]
+ public void N_String_Zero()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+ ws.Cell("A1").Value = "asd";
+ var actual = ws.Evaluate("=N(A1)");
+ Assert.AreEqual(0, actual);
+ }
+ }
+
+ [Test]
+ public void N_True_One()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+ ws.Cell("A1").Value = true;
+ var actual = ws.Evaluate("=N(A1)");
+ Assert.AreEqual(1, actual);
+ }
+ }
+ #endregion N Tests
+ }
+}
diff --git a/ClosedXML_Tests/Excel/CalcEngine/IsTests.cs b/ClosedXML_Tests/Excel/CalcEngine/IsTests.cs
deleted file mode 100644
index 2d98c68..0000000
--- a/ClosedXML_Tests/Excel/CalcEngine/IsTests.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-using ClosedXML.Excel;
-using NUnit.Framework;
-
-namespace ClosedXML_Tests.Excel.CalcEngine
-{
-
- [TestFixture]
- public class IsTests
- {
- [Test]
- public void IsBlank_true()
- {
- var ws = new XLWorkbook().AddWorksheet("Sheet");
- var actual = ws.Evaluate("=IsBlank(A1)");
- Assert.AreEqual(true, actual);
- }
-
- [Test]
- public void IsBlank_false()
- {
- var ws = new XLWorkbook().AddWorksheet("Sheet");
- ws.Cell("A1").Value = " ";
- var actual = ws.Evaluate("=IsBlank(A1)");
- Assert.AreEqual(false, actual);
- }
- }
-}
\ No newline at end of file
diff --git a/ClosedXML_Tests/Excel/CalcEngine/LogicalTests.cs b/ClosedXML_Tests/Excel/CalcEngine/LogicalTests.cs
index c3aeee4..a78ce97 100644
--- a/ClosedXML_Tests/Excel/CalcEngine/LogicalTests.cs
+++ b/ClosedXML_Tests/Excel/CalcEngine/LogicalTests.cs
@@ -33,5 +33,22 @@
Object actual = XLWorkbook.EvaluateExpr(@"if(1 = 2, ""T"", ""F"")");
Assert.AreEqual("F", actual);
}
+
+ [Test]
+ public void If_Comparing_Against_Empty_String()
+ {
+ Object actual;
+ actual = XLWorkbook.EvaluateExpr(@"if(date(2016, 1, 1) = """", ""A"",""B"")");
+ Assert.AreEqual("B", actual);
+
+ actual = XLWorkbook.EvaluateExpr(@"if("""" = date(2016, 1, 1), ""A"",""B"")");
+ Assert.AreEqual("B", actual);
+
+ actual = XLWorkbook.EvaluateExpr(@"if("""" = 123, ""A"",""B"")");
+ Assert.AreEqual("B", actual);
+
+ actual = XLWorkbook.EvaluateExpr(@"if("""" = """", ""A"",""B"")");
+ Assert.AreEqual("A", actual);
+ }
}
-}
\ No newline at end of file
+}
diff --git a/ClosedXML_Tests/Excel/CalcEngine/LookupTests.cs b/ClosedXML_Tests/Excel/CalcEngine/LookupTests.cs
index 5d232f6..babfab0 100644
--- a/ClosedXML_Tests/Excel/CalcEngine/LookupTests.cs
+++ b/ClosedXML_Tests/Excel/CalcEngine/LookupTests.cs
@@ -17,57 +17,67 @@
workbook = SetupWorkbook();
}
+ [OneTimeTearDown]
+ public void Dispose()
+ {
+ workbook.Dispose();
+ }
+
private XLWorkbook SetupWorkbook()
{
var wb = new XLWorkbook();
var ws = wb.AddWorksheet("Data");
var data = new object[]
{
- new {Id=1,OrderDate = DateTime.Parse("2015-01-06"), Region = "East", Rep = "Jones", Item = "Pencil", Units = 95, UnitCost = 1.99, Total = 189.05 },
- new {Id=2,OrderDate = DateTime.Parse("2015-01-23"), Region = "Central", Rep = "Kivell", Item = "Binder", Units = 50, UnitCost = 19.99, Total = 999.5},
- new {Id=3,OrderDate = DateTime.Parse("2015-02-09"), Region = "Central", Rep = "Jardine", Item = "Pencil", Units = 36, UnitCost = 4.99, Total = 179.64},
- new {Id=4,OrderDate = DateTime.Parse("2015-02-26"), Region = "Central", Rep = "Gill", Item = "Pen", Units = 27, UnitCost = 19.99, Total = 539.73},
- new {Id=5,OrderDate = DateTime.Parse("2015-03-15"), Region = "West", Rep = "Sorvino", Item = "Pencil", Units = 56, UnitCost = 2.99, Total = 167.44},
- new {Id=6,OrderDate = DateTime.Parse("2015-04-01"), Region = "East", Rep = "Jones", Item = "Binder", Units = 60, UnitCost = 4.99, Total = 299.4},
- new {Id=7,OrderDate = DateTime.Parse("2015-04-18"), Region = "Central", Rep = "Andrews", Item = "Pencil", Units = 75, UnitCost = 1.99, Total = 149.25},
- new {Id=8,OrderDate = DateTime.Parse("2015-05-05"), Region = "Central", Rep = "Jardine", Item = "Pencil", Units = 90, UnitCost = 4.99, Total = 449.1},
- new {Id=9,OrderDate = DateTime.Parse("2015-05-22"), Region = "West", Rep = "Thompson", Item = "Pencil", Units = 32, UnitCost = 1.99, Total = 63.68},
- new {Id=10,OrderDate = DateTime.Parse("2015-06-08"), Region = "East", Rep = "Jones", Item = "Binder", Units = 60, UnitCost = 8.99, Total = 539.4},
- new {Id=11,OrderDate = DateTime.Parse("2015-06-25"), Region = "Central", Rep = "Morgan", Item = "Pencil", Units = 90, UnitCost = 4.99, Total = 449.1},
- new {Id=12,OrderDate = DateTime.Parse("2015-07-12"), Region = "East", Rep = "Howard", Item = "Binder", Units = 29, UnitCost = 1.99, Total = 57.71},
- new {Id=13,OrderDate = DateTime.Parse("2015-07-29"), Region = "East", Rep = "Parent", Item = "Binder", Units = 81, UnitCost = 19.99, Total = 1619.19},
- new {Id=14,OrderDate = DateTime.Parse("2015-08-15"), Region = "East", Rep = "Jones", Item = "Pencil", Units = 35, UnitCost = 4.99, Total = 174.65},
- new {Id=15,OrderDate = DateTime.Parse("2015-09-01"), Region = "Central", Rep = "Smith", Item = "Desk", Units = 2, UnitCost = 125, Total = 250},
- new {Id=16,OrderDate = DateTime.Parse("2015-09-18"), Region = "East", Rep = "Jones", Item = "Pen Set", Units = 16, UnitCost = 15.99, Total = 255.84},
- new {Id=17,OrderDate = DateTime.Parse("2015-10-05"), Region = "Central", Rep = "Morgan", Item = "Binder", Units = 28, UnitCost = 8.99, Total = 251.72},
- new {Id=18,OrderDate = DateTime.Parse("2015-10-22"), Region = "East", Rep = "Jones", Item = "Pen", Units = 64, UnitCost = 8.99, Total = 575.36},
- new {Id=19,OrderDate = DateTime.Parse("2015-11-08"), Region = "East", Rep = "Parent", Item = "Pen", Units = 15, UnitCost = 19.99, Total = 299.85},
- new {Id=20,OrderDate = DateTime.Parse("2015-11-25"), Region = "Central", Rep = "Kivell", Item = "Pen Set", Units = 96, UnitCost = 4.99, Total = 479.04},
- new {Id=21,OrderDate = DateTime.Parse("2015-12-12"), Region = "Central", Rep = "Smith", Item = "Pencil", Units = 67, UnitCost = 1.29, Total = 86.43},
- new {Id=22,OrderDate = DateTime.Parse("2015-12-29"), Region = "East", Rep = "Parent", Item = "Pen Set", Units = 74, UnitCost = 15.99, Total = 1183.26},
- new {Id=23,OrderDate = DateTime.Parse("2016-01-15"), Region = "Central", Rep = "Gill", Item = "Binder", Units = 46, UnitCost = 8.99, Total = 413.54},
- new {Id=24,OrderDate = DateTime.Parse("2016-02-01"), Region = "Central", Rep = "Smith", Item = "Binder", Units = 87, UnitCost = 15, Total = 1305},
- new {Id=25,OrderDate = DateTime.Parse("2016-02-18"), Region = "East", Rep = "Jones", Item = "Binder", Units = 4, UnitCost = 4.99, Total = 19.96},
- new {Id=26,OrderDate = DateTime.Parse("2016-03-07"), Region = "West", Rep = "Sorvino", Item = "Binder", Units = 7, UnitCost = 19.99, Total = 139.93},
- new {Id=27,OrderDate = DateTime.Parse("2016-03-24"), Region = "Central", Rep = "Jardine", Item = "Pen Set", Units = 50, UnitCost = 4.99, Total = 249.5},
- new {Id=28,OrderDate = DateTime.Parse("2016-04-10"), Region = "Central", Rep = "Andrews", Item = "Pencil", Units = 66, UnitCost = 1.99, Total = 131.34},
- new {Id=29,OrderDate = DateTime.Parse("2016-04-27"), Region = "East", Rep = "Howard", Item = "Pen", Units = 96, UnitCost = 4.99, Total = 479.04},
- new {Id=30,OrderDate = DateTime.Parse("2016-05-14"), Region = "Central", Rep = "Gill", Item = "Pencil", Units = 53, UnitCost = 1.29, Total = 68.37},
- new {Id=31,OrderDate = DateTime.Parse("2016-05-31"), Region = "Central", Rep = "Gill", Item = "Binder", Units = 80, UnitCost = 8.99, Total = 719.2},
- new {Id=32,OrderDate = DateTime.Parse("2016-06-17"), Region = "Central", Rep = "Kivell", Item = "Desk", Units = 5, UnitCost = 125, Total = 625},
- new {Id=33,OrderDate = DateTime.Parse("2016-07-04"), Region = "East", Rep = "Jones", Item = "Pen Set", Units = 62, UnitCost = 4.99, Total = 309.38},
- new {Id=34,OrderDate = DateTime.Parse("2016-07-21"), Region = "Central", Rep = "Morgan", Item = "Pen Set", Units = 55, UnitCost = 12.49, Total = 686.95},
- new {Id=35,OrderDate = DateTime.Parse("2016-08-07"), Region = "Central", Rep = "Kivell", Item = "Pen Set", Units = 42, UnitCost = 23.95, Total = 1005.9},
- new {Id=36,OrderDate = DateTime.Parse("2016-08-24"), Region = "West", Rep = "Sorvino", Item = "Desk", Units = 3, UnitCost = 275, Total = 825},
- new {Id=37,OrderDate = DateTime.Parse("2016-09-10"), Region = "Central", Rep = "Gill", Item = "Pencil", Units = 7, UnitCost = 1.29, Total = 9.03},
- new {Id=38,OrderDate = DateTime.Parse("2016-09-27"), Region = "West", Rep = "Sorvino", Item = "Pen", Units = 76, UnitCost = 1.99, Total = 151.24},
- new {Id=39,OrderDate = DateTime.Parse("2016-10-14"), Region = "West", Rep = "Thompson", Item = "Binder", Units = 57, UnitCost = 19.99, Total = 1139.43},
- new {Id=40,OrderDate = DateTime.Parse("2016-10-31"), Region = "Central", Rep = "Andrews", Item = "Pencil", Units = 14, UnitCost = 1.29, Total = 18.06},
- new {Id=41,OrderDate = DateTime.Parse("2016-11-17"), Region = "Central", Rep = "Jardine", Item = "Binder", Units = 11, UnitCost = 4.99, Total = 54.89},
- new {Id=42,OrderDate = DateTime.Parse("2016-12-04"), Region = "Central", Rep = "Jardine", Item = "Binder", Units = 94, UnitCost = 19.99, Total = 1879.06},
- new {Id=43,OrderDate = DateTime.Parse("2016-12-21"), Region = "Central", Rep = "Andrews", Item = "Binder", Units = 28, UnitCost = 4.99, Total = 139.72}
+ new {Id=1, OrderDate = DateTime.Parse("2015-01-06"), Region = "East", Rep = "Jones", Item = "Pencil", Units = 95, UnitCost = 1.99, Total = 189.05 },
+ new {Id=2, OrderDate = DateTime.Parse("2015-01-23"), Region = "Central", Rep = "Kivell", Item = "Binder", Units = 50, UnitCost = 19.99, Total = 999.5},
+ new {Id=3, OrderDate = DateTime.Parse("2015-02-09"), Region = "Central", Rep = "Jardine", Item = "Pencil", Units = 36, UnitCost = 4.99, Total = 179.64},
+ new {Id=4, OrderDate = DateTime.Parse("2015-02-26"), Region = "Central", Rep = "Gill", Item = "Pen", Units = 27, UnitCost = 19.99, Total = 539.73},
+ new {Id=5, OrderDate = DateTime.Parse("2015-03-15"), Region = "West", Rep = "Sorvino", Item = "Pencil", Units = 56, UnitCost = 2.99, Total = 167.44},
+ new {Id=6, OrderDate = DateTime.Parse("2015-04-01"), Region = "East", Rep = "Jones", Item = "Binder", Units = 60, UnitCost = 4.99, Total = 299.4},
+ new {Id=7, OrderDate = DateTime.Parse("2015-04-18"), Region = "Central", Rep = "Andrews", Item = "Pencil", Units = 75, UnitCost = 1.99, Total = 149.25},
+ new {Id=8, OrderDate = DateTime.Parse("2015-05-05"), Region = "Central", Rep = "Jardine", Item = "Pencil", Units = 90, UnitCost = 4.99, Total = 449.1},
+ new {Id=9, OrderDate = DateTime.Parse("2015-05-22"), Region = "West", Rep = "Thompson", Item = "Pencil", Units = 32, UnitCost = 1.99, Total = 63.68},
+ new {Id=10, OrderDate = DateTime.Parse("2015-06-08"), Region = "East", Rep = "Jones", Item = "Binder", Units = 60, UnitCost = 8.99, Total = 539.4},
+ new {Id=11, OrderDate = DateTime.Parse("2015-06-25"), Region = "Central", Rep = "Morgan", Item = "Pencil", Units = 90, UnitCost = 4.99, Total = 449.1},
+ new {Id=12, OrderDate = DateTime.Parse("2015-07-12"), Region = "East", Rep = "Howard", Item = "Binder", Units = 29, UnitCost = 1.99, Total = 57.71},
+ new {Id=13, OrderDate = DateTime.Parse("2015-07-29"), Region = "East", Rep = "Parent", Item = "Binder", Units = 81, UnitCost = 19.99, Total = 1619.19},
+ new {Id=14, OrderDate = DateTime.Parse("2015-08-15"), Region = "East", Rep = "Jones", Item = "Pencil", Units = 35, UnitCost = 4.99, Total = 174.65},
+ new {Id=15, OrderDate = DateTime.Parse("2015-09-01"), Region = "Central", Rep = "Smith", Item = "Desk", Units = 2, UnitCost = 125, Total = 250},
+ new {Id=16, OrderDate = DateTime.Parse("2015-09-18"), Region = "East", Rep = "Jones", Item = "Pen Set", Units = 16, UnitCost = 15.99, Total = 255.84},
+ new {Id=17, OrderDate = DateTime.Parse("2015-10-05"), Region = "Central", Rep = "Morgan", Item = "Binder", Units = 28, UnitCost = 8.99, Total = 251.72},
+ new {Id=18, OrderDate = DateTime.Parse("2015-10-22"), Region = "East", Rep = "Jones", Item = "Pen", Units = 64, UnitCost = 8.99, Total = 575.36},
+ new {Id=19, OrderDate = DateTime.Parse("2015-11-08"), Region = "East", Rep = "Parent", Item = "Pen", Units = 15, UnitCost = 19.99, Total = 299.85},
+ new {Id=20, OrderDate = DateTime.Parse("2015-11-25"), Region = "Central", Rep = "Kivell", Item = "Pen Set", Units = 96, UnitCost = 4.99, Total = 479.04},
+ new {Id=21, OrderDate = DateTime.Parse("2015-12-12"), Region = "Central", Rep = "Smith", Item = "Pencil", Units = 67, UnitCost = 1.29, Total = 86.43},
+ new {Id=22, OrderDate = DateTime.Parse("2015-12-29"), Region = "East", Rep = "Parent", Item = "Pen Set", Units = 74, UnitCost = 15.99, Total = 1183.26},
+ new {Id=23, OrderDate = DateTime.Parse("2016-01-15"), Region = "Central", Rep = "Gill", Item = "Binder", Units = 46, UnitCost = 8.99, Total = 413.54},
+ new {Id=24, OrderDate = DateTime.Parse("2016-02-01"), Region = "Central", Rep = "Smith", Item = "Binder", Units = 87, UnitCost = 15, Total = 1305},
+ new {Id=25, OrderDate = DateTime.Parse("2016-02-18"), Region = "East", Rep = "Jones", Item = "Binder", Units = 4, UnitCost = 4.99, Total = 19.96},
+ new {Id=26, OrderDate = DateTime.Parse("2016-03-07"), Region = "West", Rep = "Sorvino", Item = "Binder", Units = 7, UnitCost = 19.99, Total = 139.93},
+ new {Id=27, OrderDate = DateTime.Parse("2016-03-24"), Region = "Central", Rep = "Jardine", Item = "Pen Set", Units = 50, UnitCost = 4.99, Total = 249.5},
+ new {Id=28, OrderDate = DateTime.Parse("2016-04-10"), Region = "Central", Rep = "Andrews", Item = "Pencil", Units = 66, UnitCost = 1.99, Total = 131.34},
+ new {Id=29, OrderDate = DateTime.Parse("2016-04-27"), Region = "East", Rep = "Howard", Item = "Pen", Units = 96, UnitCost = 4.99, Total = 479.04},
+ new {Id=30, OrderDate = DateTime.Parse("2016-05-14"), Region = "Central", Rep = "Gill", Item = "Pencil", Units = 53, UnitCost = 1.29, Total = 68.37},
+ new {Id=31, OrderDate = DateTime.Parse("2016-05-31"), Region = "Central", Rep = "Gill", Item = "Binder", Units = 80, UnitCost = 8.99, Total = 719.2},
+ new {Id=32, OrderDate = DateTime.Parse("2016-06-17"), Region = "Central", Rep = "Kivell", Item = "Desk", Units = 5, UnitCost = 125, Total = 625},
+ new {Id=33, OrderDate = DateTime.Parse("2016-07-04"), Region = "East", Rep = "Jones", Item = "Pen Set", Units = 62, UnitCost = 4.99, Total = 309.38},
+ new {Id=34, OrderDate = DateTime.Parse("2016-07-21"), Region = "Central", Rep = "Morgan", Item = "Pen Set", Units = 55, UnitCost = 12.49, Total = 686.95},
+ new {Id=35, OrderDate = DateTime.Parse("2016-08-07"), Region = "Central", Rep = "Kivell", Item = "Pen Set", Units = 42, UnitCost = 23.95, Total = 1005.9},
+ new {Id=36, OrderDate = DateTime.Parse("2016-08-24"), Region = "West", Rep = "Sorvino", Item = "Desk", Units = 3, UnitCost = 275, Total = 825},
+ new {Id=37, OrderDate = DateTime.Parse("2016-09-10"), Region = "Central", Rep = "Gill", Item = "Pencil", Units = 7, UnitCost = 1.29, Total = 9.03},
+ new {Id=38, OrderDate = DateTime.Parse("2016-09-27"), Region = "West", Rep = "Sorvino", Item = "Pen", Units = 76, UnitCost = 1.99, Total = 151.24},
+ new {Id=39, OrderDate = DateTime.Parse("2016-10-14"), Region = "West", Rep = "Thompson", Item = "Binder", Units = 57, UnitCost = 19.99, Total = 1139.43},
+ new {Id=40, OrderDate = DateTime.Parse("2016-10-31"), Region = "Central", Rep = "Andrews", Item = "Pencil", Units = 14, UnitCost = 1.29, Total = 18.06},
+ new {Id=41, OrderDate = DateTime.Parse("2016-11-17"), Region = "Central", Rep = "Jardine", Item = "Binder", Units = 11, UnitCost = 4.99, Total = 54.89},
+ new {Id=42, OrderDate = DateTime.Parse("2016-12-04"), Region = "Central", Rep = "Jardine", Item = "Binder", Units = 94, UnitCost = 19.99, Total = 1879.06},
+ new {Id=43, OrderDate = DateTime.Parse("2016-12-21"), Region = "Central", Rep = "Andrews", Item = "Binder", Units = 28, UnitCost = 4.99, Total = 139.72}
};
- ws.FirstCell().InsertTable(data);
+ ws.FirstCell()
+ .CellBelow()
+ .CellRight()
+ .InsertTable(data);
+
return wb;
}
@@ -75,7 +85,7 @@
public void Hlookup()
{
// Range lookup false
- var value = workbook.Evaluate(@"=HLOOKUP(""Total"",Data!$A$1:$H$70,4,FALSE)");
+ var value = workbook.Evaluate(@"=HLOOKUP(""Total"",Data!$B$2:$I$71,4,FALSE)");
Assert.AreEqual(179.64, value);
}
@@ -83,34 +93,34 @@
public void Vlookup()
{
// Range lookup false
- var value = workbook.Evaluate("=VLOOKUP(3,Data!$A$1:$H$70,3,FALSE)");
+ var value = workbook.Evaluate("=VLOOKUP(3,Data!$B$2:$I$71,3,FALSE)");
Assert.AreEqual("Central", value);
- value = workbook.Evaluate("=VLOOKUP(DATE(2015,5,22),Data!B:H,7,FALSE)");
+ value = workbook.Evaluate("=VLOOKUP(DATE(2015,5,22),Data!C:I,7,FALSE)");
Assert.AreEqual(63.68, value);
- value = workbook.Evaluate(@"=VLOOKUP(""Central"",Data!C:D,2,FALSE)");
+ value = workbook.Evaluate(@"=VLOOKUP(""Central"",Data!D:E,2,FALSE)");
Assert.AreEqual("Kivell", value);
// Range lookup true
- value = workbook.Evaluate("=VLOOKUP(3,Data!$A$1:$H$70,8,TRUE)");
+ value = workbook.Evaluate("=VLOOKUP(3,Data!$B$2:$I$71,8,TRUE)");
Assert.AreEqual(179.64, value);
- value = workbook.Evaluate("=VLOOKUP(14.5,Data!$A$1:$H$70,8,TRUE)");
+ value = workbook.Evaluate("=VLOOKUP(14.5,Data!$B$2:$I$71,8,TRUE)");
Assert.AreEqual(174.65, value);
- value = workbook.Evaluate("=VLOOKUP(50,Data!$A$1:$H$70,8,TRUE)");
+ value = workbook.Evaluate("=VLOOKUP(50,Data!$B$2:$I$71,8,TRUE)");
Assert.AreEqual(139.72, value);
}
[Test]
public void Vlookup_Exceptions()
{
- Assert.That(() => workbook.Evaluate(@"=VLOOKUP("""",Data!$A$1:$H$70,3,FALSE)"), Throws.Exception);
- Assert.That(() => workbook.Evaluate(@"=VLOOKUP(50,Data!$A$1:$H$70,3,FALSE)"), Throws.Exception);
- Assert.That(() => workbook.Evaluate(@"=VLOOKUP(20,Data!$A$1:$H$70,9,FALSE)"), Throws.Exception);
+ Assert.That(() => workbook.Evaluate(@"=VLOOKUP("""",Data!$B$2:$I$71,3,FALSE)"), Throws.Exception);
+ Assert.That(() => workbook.Evaluate(@"=VLOOKUP(50,Data!$B$2:$I$71,3,FALSE)"), Throws.Exception);
+ Assert.That(() => workbook.Evaluate(@"=VLOOKUP(20,Data!$B$2:$I$71,9,FALSE)"), Throws.Exception);
- Assert.That(() => workbook.Evaluate(@"=VLOOKUP(-1,Data!$A$1:$H$70,9,TRUE)"), Throws.Exception);
+ Assert.That(() => workbook.Evaluate(@"=VLOOKUP(-1,Data!$B$2:$I$71,9,TRUE)"), Throws.Exception);
}
}
-}
\ No newline at end of file
+}
diff --git a/ClosedXML_Tests/Excel/Cells/XLCellTests.cs b/ClosedXML_Tests/Excel/Cells/XLCellTests.cs
index 1415703..750af3a 100644
--- a/ClosedXML_Tests/Excel/Cells/XLCellTests.cs
+++ b/ClosedXML_Tests/Excel/Cells/XLCellTests.cs
@@ -1,10 +1,11 @@
-using System;
+using ClosedXML.Excel;
+using NUnit.Framework;
+using System;
using System.Collections.Generic;
using System.Globalization;
+using System.IO;
using System.Linq;
using System.Threading;
-using ClosedXML.Excel;
-using NUnit.Framework;
namespace ClosedXML_Tests
{
@@ -56,7 +57,7 @@
{
IXLWorksheet ws = new XLWorkbook().Worksheets.Add("Sheet1");
IXLCell cell = ws.Cell("A1");
- var doubleList = new List {1.0/0.0};
+ var doubleList = new List { 1.0 / 0.0 };
cell.Value = doubleList.AsEnumerable();
Assert.AreNotEqual(XLCellValues.Number, cell.DataType);
@@ -67,7 +68,7 @@
{
IXLWorksheet ws = new XLWorkbook().Worksheets.Add("Sheet1");
IXLCell cell = ws.Cell("A1");
- var doubleList = new List {0.0/0.0};
+ var doubleList = new List { 0.0 / 0.0 };
cell.Value = doubleList.AsEnumerable();
Assert.AreNotEqual(XLCellValues.Number, cell.DataType);
@@ -77,7 +78,7 @@
public void InsertData1()
{
IXLWorksheet ws = new XLWorkbook().Worksheets.Add("Sheet1");
- IXLRange range = ws.Cell(2, 2).InsertData(new[] {"a", "b", "c"});
+ IXLRange range = ws.Cell(2, 2).InsertData(new[] { "a", "b", "c" });
Assert.AreEqual("'Sheet1'!B2:B4", range.ToString());
}
@@ -345,5 +346,25 @@
var actual = (DateTime)cell.Value;
Assert.AreEqual(expected, actual);
}
+
+ [Test]
+ public void TestInvalidXmlCharacters()
+ {
+ byte[] data;
+
+ using (var stream = new MemoryStream())
+ {
+ var wb = new XLWorkbook();
+ wb.AddWorksheet("Sheet1").FirstCell().SetValue("\u0018");
+ wb.SaveAs(stream);
+ data = stream.ToArray();
+ }
+
+ using (var stream = new MemoryStream(data))
+ {
+ var wb = new XLWorkbook(stream);
+ Assert.AreEqual("\u0018", wb.Worksheets.First().FirstCell().Value);
+ }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/ClosedXML_Tests/Excel/Columns/ColumnTests.cs b/ClosedXML_Tests/Excel/Columns/ColumnTests.cs
index 0a98c4f..4297a99 100644
--- a/ClosedXML_Tests/Excel/Columns/ColumnTests.cs
+++ b/ClosedXML_Tests/Excel/Columns/ColumnTests.cs
@@ -107,8 +107,8 @@
IXLColumn column3 = ws.Column(3);
IXLColumn columnIns = ws.Column(2).InsertColumnsBefore(1).First();
- string outputPath = Path.Combine(TestHelper.TestsOutputDirectory, @"ForTesting\Sandbox.xlsx");
- wb.SaveAs(outputPath);
+ string outputPath = Path.Combine(TestHelper.TestsOutputDirectory, "ForTesting", "Sandbox.xlsx");
+ wb.SaveAs(outputPath, true);
Assert.AreEqual(XLColor.Red, ws.Column(1).Cell(1).Style.Fill.BackgroundColor);
Assert.AreEqual(XLColor.Red, ws.Column(1).Cell(2).Style.Fill.BackgroundColor);
@@ -237,4 +237,4 @@
Assert.AreEqual(2, lastCoUsed);
}
}
-}
\ No newline at end of file
+}
diff --git a/ClosedXML_Tests/Excel/Loading/LoadingTests.cs b/ClosedXML_Tests/Excel/Loading/LoadingTests.cs
index 5412c0a..3568007 100644
--- a/ClosedXML_Tests/Excel/Loading/LoadingTests.cs
+++ b/ClosedXML_Tests/Excel/Loading/LoadingTests.cs
@@ -8,7 +8,7 @@
namespace ClosedXML_Tests.Excel
{
- // Tests in this fixture test only the successful loading of existing Excel files,
+ // Tests in this fixture test only the successful loading of existing Excel files,
// i.e. we test that ClosedXML doesn't choke on a given input file
// These tests DO NOT test that ClosedXML successfully recognises all the Excel parts or that it can successfully save those parts again.
[TestFixture]
@@ -19,7 +19,8 @@
{
var files = new List()
{
- @"Misc\TableWithCustomTheme.xlsx"
+ @"Misc\TableWithCustomTheme.xlsx",
+ @"Misc\EmptyTable.xlsx"
};
foreach (var file in files)
@@ -27,5 +28,17 @@
TestHelper.LoadFile(file);
}
}
+
+ [Test]
+ public void CanLoadAndManipulateFileWithEmptyTable()
+ {
+ using (var stream = TestHelper.GetStreamFromResource(TestHelper.GetResourcePath(@"Misc\EmptyTable.xlsx")))
+ using (var wb = new XLWorkbook(stream))
+ {
+ var ws = wb.Worksheets.First();
+ var table = ws.Tables.First();
+ table.DataRange.InsertRowsBelow(5);
+ }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/ClosedXML_Tests/Excel/Misc/CopyContentsTests.cs b/ClosedXML_Tests/Excel/Misc/CopyContentsTests.cs
index ce055cc..c9c77f6 100644
--- a/ClosedXML_Tests/Excel/Misc/CopyContentsTests.cs
+++ b/ClosedXML_Tests/Excel/Misc/CopyContentsTests.cs
@@ -113,7 +113,7 @@
copyRowSheet.Cell("G2").Value = "must be removed after copy";
originalRow.CopyTo(destinationRow);
}
- TestHelper.SaveWorkbook(workbook, @"Misc\CopyRowContents.xlsx");
+ TestHelper.SaveWorkbook(workbook, "Misc", "CopyRowContents.xlsx");
}
}
}
\ No newline at end of file
diff --git a/ClosedXML_Tests/Excel/Misc/FormulaTests.cs b/ClosedXML_Tests/Excel/Misc/FormulaTests.cs
index 9d7cc15..d9bb00a 100644
--- a/ClosedXML_Tests/Excel/Misc/FormulaTests.cs
+++ b/ClosedXML_Tests/Excel/Misc/FormulaTests.cs
@@ -1,5 +1,6 @@
using ClosedXML.Excel;
using NUnit.Framework;
+using System;
namespace ClosedXML_Tests.Excel
{
@@ -18,5 +19,65 @@
ws.Cell("A1").CopyTo("A2");
Assert.AreEqual("B2", ws.Cell("A2").FormulaA1);
}
+
+ [Test]
+ public void CopyFormula2()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ IXLWorksheet ws = wb.Worksheets.Add("Sheet1");
+
+ ws.Cell("A1").FormulaA1 = "A2-1";
+ ws.Cell("A1").CopyTo("B1");
+ Assert.AreEqual("R[1]C-1", ws.Cell("A1").FormulaR1C1);
+ Assert.AreEqual("R[1]C-1", ws.Cell("B1").FormulaR1C1);
+ Assert.AreEqual("B2-1", ws.Cell("B1").FormulaA1);
+
+ ws.Cell("A1").FormulaA1 = "B1+1";
+ ws.Cell("A1").CopyTo("A2");
+ Assert.AreEqual("RC[1]+1", ws.Cell("A1").FormulaR1C1);
+ Assert.AreEqual("RC[1]+1", ws.Cell("A2").FormulaR1C1);
+ Assert.AreEqual("B2+1", ws.Cell("A2").FormulaA1);
+ }
+ }
+
+ [Test]
+ public void CopyFormulaWithSheetNameThatResemblesFormula()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ IXLWorksheet ws = wb.Worksheets.Add("S10 Data");
+ ws.Cell("A1").Value = "Some value";
+
+ ws = wb.Worksheets.Add("Summary");
+ ws.Cell("A1").FormulaA1 = "='S10 Data'!A1";
+ Assert.AreEqual("Some value", ws.Cell("A1").Value);
+
+ ws.Cell("A1").CopyTo("A2");
+ Assert.AreEqual("'S10 Data'!A2", ws.Cell("A2").FormulaA1);
+
+ ws.Cell("A1").CopyTo("B1");
+ Assert.AreEqual("'S10 Data'!B1", ws.Cell("B1").FormulaA1);
+ }
+ }
+
+ [Test]
+ public void DateAgainstStringComparison()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet1");
+ ws.Cell("A1").Value = new DateTime(2016, 1, 1);
+ ws.Cell("A1").DataType = XLCellValues.DateTime;
+
+ ws.Cell("A2").FormulaA1 = @"=IF(A1 = """", ""A"", ""B"")";
+ var actual = ws.Cell("A2").Value;
+ Assert.AreEqual(actual, "B");
+
+ ws.Cell("A3").FormulaA1 = @"=IF("""" = A1, ""A"", ""B"")";
+ actual = ws.Cell("A3").Value;
+ Assert.AreEqual(actual, "B");
+ }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/ClosedXML_Tests/Excel/Misc/XmlEncoderTests.cs b/ClosedXML_Tests/Excel/Misc/XmlEncoderTests.cs
new file mode 100644
index 0000000..d6bac0a
--- /dev/null
+++ b/ClosedXML_Tests/Excel/Misc/XmlEncoderTests.cs
@@ -0,0 +1,33 @@
+using ClosedXML.Utils;
+using NUnit.Framework;
+
+namespace ClosedXML_Tests.Excel
+{
+ [TestFixture]
+ public class XmlEncoderTest
+ {
+ [Test]
+ public void TestControlChars()
+ {
+ Assert.AreEqual("_x0001_ _x0002_ _x0003_ _x0004_", XmlEncoder.EncodeString("\u0001 \u0002 \u0003 \u0004"));
+ Assert.AreEqual("_x0005_ _x0006_ _x0007_ _x0008_", XmlEncoder.EncodeString("\u0005 \u0006 \u0007 \u0008"));
+ Assert.AreEqual("\u0001 \u0002 \u0003 \u0004", XmlEncoder.DecodeString("_x0001_ _x0002_ _x0003_ _x0004_"));
+ Assert.AreEqual("\u0005 \u0006 \u0007 \u0008", XmlEncoder.DecodeString("_x0005_ _x0006_ _x0007_ _x0008_"));
+ }
+
+ [Test]
+ public void TestIsXmlChar()
+ {
+ Assert.AreEqual(false, XmlEncoder.IsXmlChar('\u0001'));
+ Assert.AreEqual(false, XmlEncoder.IsXmlChar('\u0005'));
+ Assert.AreEqual(false, XmlEncoder.IsXmlChar('\u0007'));
+ Assert.AreEqual(false, XmlEncoder.IsXmlChar('\u0008'));
+ Assert.AreEqual(true, XmlEncoder.IsXmlChar('J'));
+ Assert.AreEqual(true, XmlEncoder.IsXmlChar('+'));
+ Assert.AreEqual(true, XmlEncoder.IsXmlChar('S'));
+ Assert.AreEqual(true, XmlEncoder.IsXmlChar('4'));
+ Assert.AreEqual(true, XmlEncoder.IsXmlChar('!'));
+ Assert.AreEqual(true, XmlEncoder.IsXmlChar('$'));
+ }
+ }
+}
diff --git a/ClosedXML_Tests/Excel/PageSetup/HeaderFooterTests.cs b/ClosedXML_Tests/Excel/PageSetup/HeaderFooterTests.cs
index d1748a9..18fe221 100644
--- a/ClosedXML_Tests/Excel/PageSetup/HeaderFooterTests.cs
+++ b/ClosedXML_Tests/Excel/PageSetup/HeaderFooterTests.cs
@@ -17,7 +17,7 @@
ws.PageSetup.Header.Center.AddText("Initial page header", XLHFOccurrence.EvenPages);
var ms = new MemoryStream();
- wb.SaveAs(ms);
+ wb.SaveAs(ms, true);
wb = new XLWorkbook(ms);
ws = wb.Worksheets.First();
@@ -25,7 +25,7 @@
ws.PageSetup.Header.Center.Clear();
ws.PageSetup.Header.Center.AddText("Changed header", XLHFOccurrence.EvenPages);
- wb.SaveAs(ms);
+ wb.SaveAs(ms, true);
wb = new XLWorkbook(ms);
ws = wb.Worksheets.First();
@@ -34,4 +34,4 @@
Assert.AreEqual("Changed header", newHeader);
}
}
-}
\ No newline at end of file
+}
diff --git a/ClosedXML_Tests/Excel/PivotTables/XLPivotTableTests.cs b/ClosedXML_Tests/Excel/PivotTables/XLPivotTableTests.cs
index dadb7f9..345daa6 100644
--- a/ClosedXML_Tests/Excel/PivotTables/XLPivotTableTests.cs
+++ b/ClosedXML_Tests/Excel/PivotTables/XLPivotTableTests.cs
@@ -1,16 +1,15 @@
-using NUnit.Framework;
+using ClosedXML_Examples;
+using NUnit.Framework;
namespace ClosedXML_Tests
{
[TestFixture]
public class XLPivotTableTests
{
- //[Test]
- //public void CreateTable()
- //{
- // var ws = new XLWorkbook().Worksheets.Add("Sheet1");
-
-
- //}
+ [Test]
+ public void PivotTables()
+ {
+ TestHelper.RunTestExample(@"PivotTables\PivotTables.xlsx");
+ }
}
-}
\ No newline at end of file
+}
diff --git a/ClosedXML_Tests/Excel/Ranges/UsedAndUnusedCellsTests.cs b/ClosedXML_Tests/Excel/Ranges/UsedAndUnusedCellsTests.cs
new file mode 100644
index 0000000..a096c33
--- /dev/null
+++ b/ClosedXML_Tests/Excel/Ranges/UsedAndUnusedCellsTests.cs
@@ -0,0 +1,133 @@
+using ClosedXML.Excel;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ClosedXML_Tests.Excel.Ranges
+{
+ [TestFixture]
+ public class UsedAndUnusedCellsTests
+ {
+ private XLWorkbook workbook;
+
+ [OneTimeSetUp]
+ public void SetupWorkbook()
+ {
+ workbook = new XLWorkbook();
+ var ws = workbook.AddWorksheet("Sheet1");
+ ws.Cell(1, 1).Value = "A1";
+ ws.Cell(1, 3).Value = "C1";
+ ws.Cell(2, 2).Value = "B2";
+ ws.Cell(4, 1).Value = "A4";
+ ws.Cell(5, 2).Value = "B5";
+ }
+
+ [Test]
+ public void CountUsedCellsInRow()
+ {
+ int i = 0;
+ var row = workbook.Worksheets.First().FirstRow();
+ foreach (var cell in row.Cells()) // Cells() returns UnUsed cells by default
+ {
+ i++;
+ }
+ Assert.AreEqual(2, i);
+
+ i = 0;
+ row = workbook.Worksheets.First().FirstRow().RowBelow();
+ foreach (var cell in row.Cells())
+ {
+ i++;
+ }
+ Assert.AreEqual(1, i);
+ }
+
+ [Test]
+ public void CountAllCellsInRow()
+ {
+ int i = 0;
+ var row = workbook.Worksheets.First().FirstRow();
+ foreach (var cell in row.Cells(false)) // All cells in range between first and last cells used
+ {
+ i++;
+ }
+ Assert.AreEqual(3, i);
+
+ i = 0;
+ row = workbook.Worksheets.First().FirstRow().RowBelow(); //This row has no empty cells BETWEEN used cells
+ foreach (var cell in row.Cells(false))
+ {
+ i++;
+ }
+ Assert.AreEqual(1, i);
+ }
+
+ [Test]
+ public void CountUsedCellsInColumn()
+ {
+ int i = 0;
+ var column = workbook.Worksheets.First().FirstColumn();
+ foreach (var cell in column.Cells()) // Cells() returns UnUsed cells by default
+ {
+ i++;
+ }
+ Assert.AreEqual(2, i);
+
+ i = 0;
+ column = workbook.Worksheets.First().FirstColumn().ColumnRight().ColumnRight();
+ foreach (var cell in column.Cells())
+ {
+ i++;
+ }
+ Assert.AreEqual(1, i);
+ }
+
+ [Test]
+ public void CountAllCellsInColumn()
+ {
+ int i = 0;
+ var column = workbook.Worksheets.First().FirstColumn();
+ foreach (var cell in column.Cells(false)) // All cells in range between first and last cells used
+ {
+ i++;
+ }
+ Assert.AreEqual(4, i);
+
+ i = 0;
+ column = workbook.Worksheets.First().FirstColumn().ColumnRight().ColumnRight(); //This column has no empty cells BETWEEN used cells
+ foreach (var cell in column.Cells(false))
+ {
+ i++;
+ }
+ Assert.AreEqual(1, i);
+ }
+
+ [Test]
+ public void CountUsedCellsInWorksheet()
+ {
+ var ws = workbook.Worksheets.First();
+ int i = 0;
+
+ foreach (var cell in ws.Cells()) // Only used cells in worksheet
+ {
+ i++;
+ }
+ Assert.AreEqual(5, i);
+ }
+
+ [Test]
+ public void CountAllCellsInWorksheet()
+ {
+ var ws = workbook.Worksheets.First();
+ int i = 0;
+
+ foreach (var cell in ws.Cells(false)) // All cells in range between first and last cells used (cartesian product of range)
+ {
+ i++;
+ }
+ Assert.AreEqual(15, i);
+ }
+ }
+}
diff --git a/ClosedXML_Tests/Excel/Ranges/XLRangeBaseTests.cs b/ClosedXML_Tests/Excel/Ranges/XLRangeBaseTests.cs
index c90f624..22bd7c6 100644
--- a/ClosedXML_Tests/Excel/Ranges/XLRangeBaseTests.cs
+++ b/ClosedXML_Tests/Excel/Ranges/XLRangeBaseTests.cs
@@ -178,7 +178,7 @@
// ws.NamedRanges.Add("TestRange", "\"Hello\"");
// using (MemoryStream memoryStream = new MemoryStream())
// {
- // wb.SaveAs(memoryStream);
+ // wb.SaveAs(memoryStream, true);
// var wb2 = new XLWorkbook(memoryStream);
// var text = wb2.Worksheet("Sheet1").NamedRanges.First()
// memoryStream.Close();
@@ -187,4 +187,4 @@
//}
}
-}
\ No newline at end of file
+}
diff --git a/ClosedXML_Tests/Excel/Saving/SavingTests.cs b/ClosedXML_Tests/Excel/Saving/SavingTests.cs
new file mode 100644
index 0000000..22aa34a
--- /dev/null
+++ b/ClosedXML_Tests/Excel/Saving/SavingTests.cs
@@ -0,0 +1,30 @@
+using ClosedXML.Excel;
+using NUnit.Framework;
+using System.IO;
+
+namespace ClosedXML_Tests.Excel.Saving
+{
+ [TestFixture]
+ public class SavingTests
+ {
+ [Test]
+ public void CanSuccessfullySaveFileMultipleTimes()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var sheet = wb.Worksheets.Add("TestSheet");
+ var memoryStream = new MemoryStream();
+ wb.SaveAs(memoryStream, true);
+
+ for (int i = 1; i <= 3; i++)
+ {
+ sheet.Cell(i, 1).Value = "test" + i;
+ wb.SaveAs(memoryStream, true);
+ }
+
+ memoryStream.Close();
+ memoryStream.Dispose();
+ }
+ }
+ }
+}
diff --git a/ClosedXML_Tests/Excel/Tables/TablesTests.cs b/ClosedXML_Tests/Excel/Tables/TablesTests.cs
index 7ebf9bc..ea27d0d 100644
--- a/ClosedXML_Tests/Excel/Tables/TablesTests.cs
+++ b/ClosedXML_Tests/Excel/Tables/TablesTests.cs
@@ -1,10 +1,12 @@
-using System;
+using ClosedXML.Attributes;
+using ClosedXML.Excel;
+using NUnit.Framework;
+using System;
using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
using System.Data;
using System.IO;
using System.Linq;
-using ClosedXML.Excel;
-using NUnit.Framework;
namespace ClosedXML_Tests.Excel
{
@@ -14,12 +16,26 @@
[TestFixture]
public class TablesTests
{
- public class TestObject
+ public class TestObjectWithoutAttributes
{
public String Column1 { get; set; }
public String Column2 { get; set; }
}
+ public class TestObjectWithAttributes
+ {
+ public int UnOrderedColumn { get; set; }
+
+ [Display(Name ="SecondColumn"), ColumnOrder(1)]
+ public String Column1 { get; set; }
+
+ [Display(Name = "FirstColumn"), ColumnOrder(0)]
+ public String Column2 { get; set; }
+
+ [Display(Name = "SomeFieldNotProperty"), ColumnOrder(2)]
+ public int MyField;
+ }
+
[Test]
public void CanSaveTableCreatedFromEmptyDataTable()
{
@@ -31,7 +47,7 @@
wb.AddWorksheet(dt);
using (var ms = new MemoryStream())
- wb.SaveAs(ms);
+ wb.SaveAs(ms, true);
}
[Test]
@@ -43,7 +59,7 @@
ws.Range("A1").CreateTable();
using (var ms = new MemoryStream())
- wb.SaveAs(ms);
+ wb.SaveAs(ms, true);
}
[Test]
@@ -85,7 +101,7 @@
ws.RangeUsed().CreateTable();
using (var ms = new MemoryStream())
{
- wb.SaveAs(ms);
+ wb.SaveAs(ms, true);
var wb2 = new XLWorkbook(ms);
IXLWorksheet ws2 = wb2.Worksheet(1);
IXLTable table2 = ws2.Table(0);
@@ -115,7 +131,7 @@
using (var ms = new MemoryStream())
{
- wb.SaveAs(ms);
+ wb.SaveAs(ms, true);
var wb2 = new XLWorkbook(ms);
IXLWorksheet ws2 = wb2.Worksheet(1);
IXLTable table2 = ws2.Table(0);
@@ -151,7 +167,7 @@
[Test]
public void TableCreatedFromEmptyListOfObject()
{
- var l = new List();
+ var l = new List();
var wb = new XLWorkbook();
IXLWorksheet ws = wb.AddWorksheet("Sheet1");
@@ -160,6 +176,25 @@
}
[Test]
+ public void TableCreatedFromListOfObjectWithPropertyAttributes()
+ {
+ var l = new List()
+ {
+ new TestObjectWithAttributes() { Column1 = "a", Column2 = "b", MyField = 4, UnOrderedColumn = 999 },
+ new TestObjectWithAttributes() { Column1 = "c", Column2 = "d", MyField = 5, UnOrderedColumn = 777 }
+ };
+
+ var wb = new XLWorkbook();
+ IXLWorksheet ws = wb.AddWorksheet("Sheet1");
+ ws.FirstCell().InsertTable(l);
+ Assert.AreEqual(4, ws.Tables.First().ColumnCount());
+ Assert.AreEqual("FirstColumn", ws.FirstCell().Value);
+ Assert.AreEqual("SecondColumn", ws.FirstCell().CellRight().Value);
+ Assert.AreEqual("SomeFieldNotProperty", ws.FirstCell().CellRight().CellRight().Value);
+ Assert.AreEqual("UnOrderedColumn", ws.FirstCell().CellRight().CellRight().CellRight().Value);
+ }
+
+ [Test]
public void TableInsertAboveFromData()
{
var wb = new XLWorkbook();
@@ -177,13 +212,9 @@
row = table.DataRange.InsertRowsAbove(1).First();
row.Field("Value").Value = 1;
- //wb.SaveAs(@"D:\Excel Files\ForTesting\Sandbox.xlsx");
-
Assert.AreEqual(1, ws.Cell(2, 1).GetDouble());
Assert.AreEqual(2, ws.Cell(3, 1).GetDouble());
Assert.AreEqual(3, ws.Cell(4, 1).GetDouble());
-
- //wb.SaveAs(@"D:\Excel Files\ForTesting\Sandbox.xlsx");
}
[Test]
@@ -196,20 +227,17 @@
IXLTable table = ws.Range("A1:A2").CreateTable();
table.SetShowTotalsRow()
.Field(0).TotalsRowFunction = XLTotalsRowFunction.Sum;
- //wb.SaveAs(@"D:\Excel Files\ForTesting\Sandbox1.xlsx");
+
IXLTableRow row = table.DataRange.FirstRow();
row.Field("Value").Value = 3;
row = row.InsertRowsAbove(1).First();
row.Field("Value").Value = 2;
row = row.InsertRowsAbove(1).First();
row.Field("Value").Value = 1;
- //wb.SaveAs(@"D:\Excel Files\ForTesting\Sandbox2.xlsx");
Assert.AreEqual(1, ws.Cell(2, 1).GetDouble());
Assert.AreEqual(2, ws.Cell(3, 1).GetDouble());
Assert.AreEqual(3, ws.Cell(4, 1).GetDouble());
-
- //wb.SaveAs(@"D:\Excel Files\ForTesting\Sandbox.xlsx");
}
[Test]
@@ -230,8 +258,6 @@
row = table.DataRange.InsertRowsBelow(1).First();
row.Field("Value").Value = 3;
- //wb.SaveAs(@"D:\Excel Files\ForTesting\Sandbox.xlsx");
-
Assert.AreEqual(1, ws.Cell(2, 1).GetDouble());
Assert.AreEqual(2, ws.Cell(3, 1).GetDouble());
Assert.AreEqual(3, ws.Cell(4, 1).GetDouble());
@@ -258,8 +284,6 @@
Assert.AreEqual(1, ws.Cell(2, 1).GetDouble());
Assert.AreEqual(2, ws.Cell(3, 1).GetDouble());
Assert.AreEqual(3, ws.Cell(4, 1).GetDouble());
-
- //wb.SaveAs(@"D:\Excel Files\ForTesting\Sandbox.xlsx");
}
[Test]
@@ -272,11 +296,13 @@
.CellBelow().SetValue("B")
.CellBelow().SetValue("C");
- ws.RangeUsed().CreateTable().SetShowHeaderRow(false);
+ IXLTable table = ws.RangeUsed().CreateTable();
- IXLTable table = ws.Tables.First();
+ Assert.AreEqual("Categories", table.Fields.First().Name);
- //wb.SaveAs(@"D:\Excel Files\ForTesting\Sandbox1.xlsx");
+ table.SetShowHeaderRow(false);
+
+ Assert.AreEqual("Categories", table.Fields.First().Name);
Assert.IsTrue(ws.Cell(1, 1).IsEmpty(true));
Assert.AreEqual(null, table.HeadersRow());
@@ -290,15 +316,11 @@
Assert.AreNotEqual(null, headerRow);
Assert.AreEqual("Categories", headerRow.Cell(1).GetString());
-
table.SetShowHeaderRow(false);
ws.FirstCell().SetValue("x");
table.SetShowHeaderRow();
- //wb.SaveAs(@"D:\Excel Files\ForTesting\Sandbox2.xlsx");
-
- //wb.SaveAs(@"D:\Excel Files\ForTesting\Sandbox3.xlsx");
Assert.AreEqual("x", ws.FirstCell().GetString());
Assert.AreEqual("Categories", ws.Cell("A2").GetString());
@@ -331,6 +353,15 @@
Assert.AreEqual("LName", nameBefore);
Assert.AreEqual("LastName", nameAfter);
Assert.AreEqual("LastName", cellValue);
+
+ tbl.ShowHeaderRow = false;
+ tbl.Field(tbl.Fields.Last().Index).Name = "LastNameChanged";
+ nameAfter = tbl.Field(tbl.Fields.Last().Index).Name;
+ Assert.AreEqual("LastNameChanged", nameAfter);
+
+ tbl.SetShowHeaderRow(true);
+ nameAfter = tbl.Cell("B1").Value.ToString();
+ Assert.AreEqual("LastNameChanged", nameAfter);
}
}
-}
\ No newline at end of file
+}
diff --git a/ClosedXML_Tests/ExcelDocsComparerTests.cs b/ClosedXML_Tests/ExcelDocsComparerTests.cs
index 3397f25..ed16735 100644
--- a/ClosedXML_Tests/ExcelDocsComparerTests.cs
+++ b/ClosedXML_Tests/ExcelDocsComparerTests.cs
@@ -17,7 +17,7 @@
new BasicTable().Create(left);
new BasicTable().Create(right);
string message;
- Assert.IsTrue(ExcelDocsComparer.Compare(left, right, out message));
+ Assert.IsTrue(ExcelDocsComparer.Compare(left, right, TestHelper.IsRunningOnUnix, out message));
}
finally
{
@@ -43,7 +43,7 @@
new HelloWorld().Create(right);
string message;
- Assert.IsFalse(ExcelDocsComparer.Compare(left, right, out message));
+ Assert.IsFalse(ExcelDocsComparer.Compare(left, right, TestHelper.IsRunningOnUnix, out message));
}
finally
{
diff --git a/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFColorScaleLowMidHigh.xlsx b/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFColorScaleLowMidHigh.xlsx
index 640d65d..9bc4eb6 100644
--- a/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFColorScaleLowMidHigh.xlsx
+++ b/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFColorScaleLowMidHigh.xlsx
Binary files differ
diff --git a/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFColorScaleMinimumMaximum.xlsx b/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFColorScaleMinimumMaximum.xlsx
new file mode 100644
index 0000000..ef35d8b
--- /dev/null
+++ b/ClosedXML_Tests/Resource/Examples/ConditionalFormatting/CFColorScaleMinimumMaximum.xlsx
Binary files differ
diff --git a/ClosedXML_Tests/Resource/Examples/Misc/AdjustToContentsWithAutoFilter.xlsx b/ClosedXML_Tests/Resource/Examples/Misc/AdjustToContentsWithAutoFilter.xlsx
new file mode 100644
index 0000000..739fe19
--- /dev/null
+++ b/ClosedXML_Tests/Resource/Examples/Misc/AdjustToContentsWithAutoFilter.xlsx
Binary files differ
diff --git a/ClosedXML_Tests/Resource/Examples/Misc/RightToLeft.xlsx b/ClosedXML_Tests/Resource/Examples/Misc/RightToLeft.xlsx
new file mode 100644
index 0000000..1faf041
--- /dev/null
+++ b/ClosedXML_Tests/Resource/Examples/Misc/RightToLeft.xlsx
Binary files differ
diff --git a/ClosedXML_Tests/Resource/Examples/PivotTables/PivotTables.xlsx b/ClosedXML_Tests/Resource/Examples/PivotTables/PivotTables.xlsx
new file mode 100644
index 0000000..c4025e5
--- /dev/null
+++ b/ClosedXML_Tests/Resource/Examples/PivotTables/PivotTables.xlsx
Binary files differ
diff --git a/ClosedXML_Tests/Resource/Examples/Ranges/NamedRanges.xlsx b/ClosedXML_Tests/Resource/Examples/Ranges/NamedRanges.xlsx
index 7087248..27bb627 100644
--- a/ClosedXML_Tests/Resource/Examples/Ranges/NamedRanges.xlsx
+++ b/ClosedXML_Tests/Resource/Examples/Ranges/NamedRanges.xlsx
Binary files differ
diff --git a/ClosedXML_Tests/Resource/Examples/Styles/StyleFont.xlsx b/ClosedXML_Tests/Resource/Examples/Styles/StyleFont.xlsx
index 589c8e5..04267cc 100644
--- a/ClosedXML_Tests/Resource/Examples/Styles/StyleFont.xlsx
+++ b/ClosedXML_Tests/Resource/Examples/Styles/StyleFont.xlsx
Binary files differ
diff --git a/ClosedXML_Tests/Resource/Misc/EmptyTable.xlsx b/ClosedXML_Tests/Resource/Misc/EmptyTable.xlsx
new file mode 100644
index 0000000..e902376
--- /dev/null
+++ b/ClosedXML_Tests/Resource/Misc/EmptyTable.xlsx
Binary files differ
diff --git a/ClosedXML_Tests/TestHelper.cs b/ClosedXML_Tests/TestHelper.cs
index be509a2..477facf 100644
--- a/ClosedXML_Tests/TestHelper.cs
+++ b/ClosedXML_Tests/TestHelper.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections.Generic;
+using System.Linq;
using System.IO;
using System.Threading;
using ClosedXML.Excel;
@@ -19,22 +21,36 @@
//Note: Run example tests parameters
public static string TestsOutputDirectory
{
- get {
- return Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
+ get
+ {
+ return Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
}
}
public const string ActualTestResultPostFix = "";
public static readonly string TestsExampleOutputDirectory = Path.Combine(TestsOutputDirectory, "Examples");
-
+
private const bool CompareWithResources = true;
private static readonly ResourceFileExtractor _extractor = new ResourceFileExtractor(null, ".Resource.Examples.");
- public static void SaveWorkbook(XLWorkbook workbook, string fileName)
+ public static void SaveWorkbook(XLWorkbook workbook, params string[] fileNameParts)
{
- workbook.SaveAs(Path.Combine(TestsOutputDirectory, fileName));
+ workbook.SaveAs(Path.Combine(new string[] { TestsOutputDirectory }.Concat(fileNameParts).ToArray()), true);
+ }
+
+ // Because different fonts are installed on Unix,
+ // the columns widths after AdjustToContents() will
+ // cause the tests to fail.
+ // Therefore we ignore the width attribute when running on Unix
+ public static bool IsRunningOnUnix
+ {
+ get
+ {
+ int p = (int)Environment.OSVersion.Platform;
+ return ((p == 4) || (p == 6) || (p == 128));
+ }
}
public static void RunTestExample(string filePartName)
@@ -44,7 +60,8 @@
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
var example = new T();
- string filePath1 = Path.Combine(TestsExampleOutputDirectory, filePartName);
+ string[] pathParts = filePartName.Split(new char[] {'\\'});
+ string filePath1 = Path.Combine(new List() { TestsExampleOutputDirectory }.Concat(pathParts).ToArray());
var extension = Path.GetExtension(filePath1);
var directory = Path.GetDirectoryName(filePath1);
@@ -57,7 +74,7 @@
var filePath2 = Path.Combine(directory, fileName);
//Run test
example.Create(filePath1);
- new XLWorkbook(filePath1).SaveAs(filePath2);
+ new XLWorkbook(filePath1).SaveAs(filePath2, true);
bool success = true;
#pragma warning disable 162
try
@@ -73,7 +90,7 @@
using (var streamActual = File.OpenRead(filePath2))
{
string message;
- success = ExcelDocsComparer.Compare(streamActual, streamExpected, out message);
+ success = ExcelDocsComparer.Compare(streamActual, streamExpected, TestHelper.IsRunningOnUnix, out message);
var formattedMessage =
String.Format(
"Actual file '{0}' is different than the expected file '{1}'. The difference is: '{2}'",
@@ -90,16 +107,24 @@
#pragma warning restore 162
}
- public static void LoadFile(string filePartName)
+ public static string GetResourcePath(string filePartName)
+ {
+ return filePartName.Replace('\\', '.').TrimStart('.');
+ }
+
+ public static Stream GetStreamFromResource(string resourcePath)
{
var extractor = new ResourceFileExtractor(null, ".Resource.");
+ return extractor.ReadFileFromResToStream(resourcePath);
+ }
- string resourcePath = filePartName.Replace('\\', '.').TrimStart('.');
- using (var stream = extractor.ReadFileFromResToStream(resourcePath))
+ public static void LoadFile(string filePartName)
+ {
+ using (var stream = GetStreamFromResource(GetResourcePath(filePartName)))
{
var wb = new XLWorkbook(stream);
wb.Dispose();
}
}
}
-}
\ No newline at end of file
+}
diff --git a/ClosedXML_Tests/Utils/ExcelDocsComparer.cs b/ClosedXML_Tests/Utils/ExcelDocsComparer.cs
index 25dc07f..0bbeafd 100644
--- a/ClosedXML_Tests/Utils/ExcelDocsComparer.cs
+++ b/ClosedXML_Tests/Utils/ExcelDocsComparer.cs
@@ -6,24 +6,24 @@
{
internal static class ExcelDocsComparer
{
- public static bool Compare(string left, string right, out string message)
+ public static bool Compare(string left, string right, bool stripColumnWidths, out string message)
{
using (FileStream leftStream = File.OpenRead(left))
{
using (FileStream rightStream = File.OpenRead(right))
{
- return Compare(leftStream, rightStream, out message);
+ return Compare(leftStream, rightStream, stripColumnWidths, out message);
}
}
}
- public static bool Compare(Stream left, Stream right, out string message)
+ public static bool Compare(Stream left, Stream right, bool stripColumnWidths, out string message)
{
using (Package leftPackage = Package.Open(left))
{
using (Package rightPackage = Package.Open(right))
{
- return PackageHelper.Compare(leftPackage, rightPackage, false, ExcludeMethod, out message);
+ return PackageHelper.Compare(leftPackage, rightPackage, false, ExcludeMethod, stripColumnWidths, out message);
}
}
}
diff --git a/ClosedXML_Tests/Utils/PackageHelper.cs b/ClosedXML_Tests/Utils/PackageHelper.cs
index ec92716..33ba3e4 100644
--- a/ClosedXML_Tests/Utils/PackageHelper.cs
+++ b/ClosedXML_Tests/Utils/PackageHelper.cs
@@ -273,9 +273,9 @@
///
///
///
- public static bool Compare(Package left, Package right, bool compareToFirstDifference, out string message)
+ public static bool Compare(Package left, Package right, bool compareToFirstDifference, bool stripColumnWidths, out string message)
{
- return Compare(left, right, compareToFirstDifference, null, out message);
+ return Compare(left, right, compareToFirstDifference, null, stripColumnWidths, out message);
}
///
@@ -288,7 +288,7 @@
///
///
public static bool Compare(Package left, Package right, bool compareToFirstDifference,
- Func excludeMethod, out string message)
+ Func excludeMethod, bool stripColumnWidths, out string message)
{
#region Check
@@ -344,10 +344,16 @@
{
continue;
}
- using (Stream oneStream = left.GetPart(pair.Uri).GetStream(FileMode.Open, FileAccess.Read))
- using (Stream otherStream = right.GetPart(pair.Uri).GetStream(FileMode.Open, FileAccess.Read))
+ var leftPart = left.GetPart(pair.Uri);
+ var rightPart = right.GetPart(pair.Uri);
+ using (Stream oneStream = leftPart.GetStream(FileMode.Open, FileAccess.Read))
+ using (Stream otherStream = rightPart.GetStream(FileMode.Open, FileAccess.Read))
{
- if (!StreamHelper.Compare(oneStream, otherStream))
+ bool stripColumnWidthsFromSheet = stripColumnWidths &&
+ leftPart.ContentType == @"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" &&
+ rightPart.ContentType == @"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml";
+
+ if (!StreamHelper.Compare(oneStream, otherStream, stripColumnWidthsFromSheet))
{
pair.Status = CompareStatus.NonEqual;
if (compareToFirstDifference)
diff --git a/ClosedXML_Tests/Utils/StreamHelper.cs b/ClosedXML_Tests/Utils/StreamHelper.cs
index 30b8d08..05a057e 100644
--- a/ClosedXML_Tests/Utils/StreamHelper.cs
+++ b/ClosedXML_Tests/Utils/StreamHelper.cs
@@ -1,5 +1,8 @@
using System;
+using System.Collections.Generic;
using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
namespace ClosedXML_Tests
{
@@ -19,7 +22,7 @@
var bytes = new byte[iLength];
for (int i = 0; i < iLength; i++)
{
- bytes[i] = (byte) pStream.ReadByte();
+ bytes[i] = (byte)pStream.ReadByte();
}
pStream.Close();
return bytes;
@@ -98,7 +101,7 @@
long rest = length;
while (rest > 0)
{
- int len1 = streamIn.Read(buf, 0, rest >= 512 ? 512 : (int) rest);
+ int len1 = streamIn.Read(buf, 0, rest >= 512 ? 512 : (int)rest);
streamToWrite.Write(buf, 0, len1);
rest -= len1;
}
@@ -109,8 +112,9 @@
///
///
///
+ /// ///
///
- public static bool Compare(Stream one, Stream other)
+ public static bool Compare(Stream one, Stream other, bool stripColumnWidths)
{
#region Check
@@ -133,9 +137,35 @@
#endregion
- var stringOne = new StreamReader(one).ReadToEnd();
- var stringOther = new StreamReader(other).ReadToEnd();
+ var stringOne = new StreamReader(one).ReadToEnd().StripColumnWidths(stripColumnWidths);
+ var stringOther = new StreamReader(other).ReadToEnd().StripColumnWidths(stripColumnWidths);
return stringOne == stringOther;
}
+
+ private static Regex columnRegex = new Regex("", RegexOptions.Compiled);
+ private static Regex widthRegex = new Regex("width=\"\\d+(\\.\\d+)?\"\\s+", RegexOptions.Compiled);
+
+ private static string StripColumnWidths(this string s, bool stripIt)
+ {
+ if (!stripIt)
+ return s;
+ else
+ {
+ var replacements = new Dictionary();
+
+ foreach (var m in columnRegex.Matches(s).OfType())
+ {
+ var original = m.Groups[0].Value;
+ var replacement = widthRegex.Replace(original, "");
+ replacements.Add(original, replacement);
+ }
+
+ foreach (var r in replacements)
+ {
+ s = s.Replace(r.Key, r.Value);
+ }
+ return s;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/README.md b/README.md
index bd0789c..5d195da 100644
--- a/README.md
+++ b/README.md
@@ -2,18 +2,27 @@
# ClosedXML
[](https://ci.appveyor.com/project/Pyropace/closedxml)
- we are in process of moving the project from codeplex to github
- Documentations to follow
+ClosedXML makes it easier for developers to create Excel 2007/2010/2013 files. It provides a nice object oriented way to manipulate the files (similar to VBA) without dealing with the hassles of XML Documents. It can be used by any .NET language like C# and Visual Basic (VB).
-ClosedXML makes it easier for developers to create Excel 2007/2010 files. It provides a nice object oriented way to manipulate the files (similar to VBA) without dealing with the hassles of XML Documents. It can be used by any .NET language like C# and Visual Basic (VB).
+### Install ClosedXML via NuGet
+
+If you want to include ClosedXML in your project, you can [install it directly from NuGet](https://www.nuget.org/packages/ClosedXML)
+
+To install ClosedXML, run the following command in the Package Manager Console
+
+```
+PM> Install-Package ClosedXML
+```
### What can you do with this?
-ClosedXML allows you to create Excel 2007/2010 files without the Excel application. The typical example is creating Excel reports on a web server.
+ClosedXML allows you to create Excel 2007/2010/2013 files without the Excel application. The typical example is creating Excel reports on a web server.
If you've ever used the Microsoft Open XML Format SDK you know just how much code you have to write to get the same results as the following 4 lines of code.
- var workbook = new XLWorkbook();
- var worksheet = workbook.Worksheets.Add("Sample Sheet");
- worksheet.Cell("A1").Value = "Hello World!";
- workbook.SaveAs("HelloWorld.xlsx");
+```c#
+var workbook = new XLWorkbook();
+var worksheet = workbook.Worksheets.Add("Sample Sheet");
+worksheet.Cell("A1").Value = "Hello World!";
+workbook.SaveAs("HelloWorld.xlsx");
+```