diff --git a/ClosedXML/ClosedXML.csproj b/ClosedXML/ClosedXML.csproj
index 455e38c..4bc2ce0 100644
--- a/ClosedXML/ClosedXML.csproj
+++ b/ClosedXML/ClosedXML.csproj
@@ -68,6 +68,7 @@
+
diff --git a/ClosedXML/Excel/CalcEngine/CalcEngine.cs b/ClosedXML/Excel/CalcEngine/CalcEngine.cs
index 71e3d72..8cc752e 100644
--- a/ClosedXML/Excel/CalcEngine/CalcEngine.cs
+++ b/ClosedXML/Excel/CalcEngine/CalcEngine.cs
@@ -77,18 +77,20 @@
// skip leading equals sign
if (_len > 0 && _expr[0] == '=')
- {
_ptr++;
- }
+
+ // skip leading +'s
+ while (_len > _ptr && _expr[_ptr] == '+')
+ _ptr++;
// parse the expression
var expr = ParseExpression();
// check for errors
- if (_token.ID != TKID.END)
- {
- Throw();
- }
+ if (_token.ID == TKID.OPEN)
+ Throw("Unknown function: " + expr.LastParseItem);
+ else if (_token.ID != TKID.END)
+ Throw("Expected end of expression");
// optimize expression
if (_optimize)
@@ -113,10 +115,9 @@
///
public object Evaluate(string expression)
{
- var x = //Parse(expression);
- _cache != null
- ? _cache[expression]
- : Parse(expression);
+ var x = _cache != null
+ ? _cache[expression]
+ : Parse(expression);
return x.Evaluate();
}
@@ -413,11 +414,11 @@
var pCnt = p == null ? 0 : p.Count;
if (fnDef.ParmMin != -1 && pCnt < fnDef.ParmMin)
{
- Throw("Too few parameters.");
+ Throw(string.Format("Too few parameters for function '{0}'. Expected a minimum of {1} and a maximum of {2}.", id, fnDef.ParmMin, fnDef.ParmMax));
}
if (fnDef.ParmMax != -1 && pCnt > fnDef.ParmMax)
{
- Throw("Too many parameters.");
+ Throw(string.Format("Too many parameters for function '{0}'.Expected a minimum of {1} and a maximum of {2}.", id, fnDef.ParmMin, fnDef.ParmMax));
}
x = new FunctionExpression(fnDef, p);
break;
@@ -713,7 +714,7 @@
if (isEnclosed && disallowedSymbols.Contains(c))
break;
- var allowedSymbols = new List() { '_' };
+ var allowedSymbols = new List() { '_', '.' };
if (!isLetter && !isDigit
&& !(isEnclosed || allowedSymbols.Contains(c))
@@ -771,10 +772,10 @@
}
// make sure the list was closed correctly
- if (_token.ID != TKID.CLOSE)
- {
- Throw();
- }
+ if (_token.ID == TKID.OPEN)
+ Throw("Unknown function: " + expr.LastParseItem);
+ else if (_token.ID != TKID.CLOSE)
+ Throw("Syntax error: expected ')'");
// done
return parms;
@@ -816,7 +817,7 @@
private static void Throw(string msg)
{
- throw new Exception(msg);
+ throw new ExpressionParseException(msg);
}
#endregion ** static helpers
diff --git a/ClosedXML/Excel/CalcEngine/Expression.cs b/ClosedXML/Excel/CalcEngine/Expression.cs
index dcac3c0..9dfdf28 100644
--- a/ClosedXML/Excel/CalcEngine/Expression.cs
+++ b/ClosedXML/Excel/CalcEngine/Expression.cs
@@ -1,11 +1,17 @@
using System;
-using System.Threading;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
+using System.Linq;
+using System.Threading;
namespace ClosedXML.Excel.CalcEngine
{
+ internal abstract class ExpressionBase
+ {
+ public abstract string LastParseItem { get; }
+ }
+
///
/// Base class that represents parsed expressions.
///
@@ -16,34 +22,39 @@
/// object val = expr.Evaluate();
///
///
- internal class Expression : IComparable
+ internal class Expression : ExpressionBase, IComparable
{
//---------------------------------------------------------------------------
+
#region ** fields
- internal Token _token;
+ internal readonly Token _token;
- #endregion
+ #endregion ** fields
//---------------------------------------------------------------------------
+
#region ** ctors
internal Expression()
{
_token = new Token(null, TKID.ATOM, TKTYPE.IDENTIFIER);
}
+
internal Expression(object value)
{
_token = new Token(value, TKID.ATOM, TKTYPE.LITERAL);
}
+
internal Expression(Token tk)
{
_token = tk;
}
- #endregion
+ #endregion ** ctors
//---------------------------------------------------------------------------
+
#region ** object model
public virtual object Evaluate()
@@ -54,14 +65,16 @@
}
return _token.Value;
}
+
public virtual Expression Optimize()
{
return this;
}
- #endregion
+ #endregion ** object model
//---------------------------------------------------------------------------
+
#region ** implicit converters
public static implicit operator string(Expression x)
@@ -69,6 +82,7 @@
var v = x.Evaluate();
return v == null ? string.Empty : v.ToString();
}
+
public static implicit operator double(Expression x)
{
// evaluate
@@ -102,6 +116,7 @@
CultureInfo _ci = Thread.CurrentThread.CurrentCulture;
return (double)Convert.ChangeType(v, typeof(double), _ci);
}
+
public static implicit operator bool(Expression x)
{
// evaluate
@@ -128,6 +143,7 @@
// handle everything else
return (double)x == 0 ? false : true;
}
+
public static implicit operator DateTime(Expression x)
{
// evaluate
@@ -150,9 +166,10 @@
return (DateTime)Convert.ChangeType(v, typeof(DateTime), _ci);
}
- #endregion
+ #endregion ** implicit converters
//---------------------------------------------------------------------------
+
#region ** IComparable
public int CompareTo(Expression other)
@@ -197,15 +214,27 @@
return c1.CompareTo(c2);
}
- #endregion
+ #endregion ** IComparable
+
+ //---------------------------------------------------------------------------
+
+ #region ** ExpressionBase
+
+ public override string LastParseItem
+ {
+ get { return _token?.Value?.ToString() ?? "Unknown value"; }
+ }
+
+ #endregion ** ExpressionBase
}
+
///
/// Unary expression, e.g. +123
///
- class UnaryExpression : Expression
+ internal class UnaryExpression : Expression
{
// ** fields
- Expression _expr;
+ private Expression _expr;
// ** ctor
public UnaryExpression(Token tk, Expression expr) : base(tk)
@@ -220,11 +249,13 @@
{
case TKID.ADD:
return +(double)_expr;
+
case TKID.SUB:
return -(double)_expr;
}
throw new ArgumentException("Bad expression.");
}
+
public override Expression Optimize()
{
_expr = _expr.Optimize();
@@ -232,20 +263,27 @@
? new Expression(this.Evaluate())
: this;
}
+
+ public override string LastParseItem
+ {
+ get { return _expr.LastParseItem; }
+ }
}
+
///
/// Binary expression, e.g. 1+2
///
- class BinaryExpression : Expression
+ internal class BinaryExpression : Expression
{
// ** fields
- Expression _lft;
- Expression _rgt;
+ private Expression _lft;
+
+ private Expression _rgt;
// ** ctor
public BinaryExpression(Token tk, Expression exprLeft, Expression exprRight) : base(tk)
{
- _lft = exprLeft;
+ _lft = exprLeft;
_rgt = exprRight;
}
@@ -272,18 +310,25 @@
{
case TKID.CONCAT:
return (string)_lft + (string)_rgt;
+
case TKID.ADD:
return (double)_lft + (double)_rgt;
+
case TKID.SUB:
return (double)_lft - (double)_rgt;
+
case TKID.MUL:
return (double)_lft * (double)_rgt;
+
case TKID.DIV:
return (double)_lft / (double)_rgt;
+
case TKID.DIVINT:
return (double)(int)((double)_lft / (double)_rgt);
+
case TKID.MOD:
return (double)(int)((double)_lft % (double)_rgt);
+
case TKID.POWER:
var a = (double)_lft;
var b = (double)_rgt;
@@ -297,6 +342,7 @@
}
throw new ArgumentException("Bad expression.");
}
+
public override Expression Optimize()
{
_lft = _lft.Optimize();
@@ -305,20 +351,27 @@
? new Expression(this.Evaluate())
: this;
}
+
+ public override string LastParseItem
+ {
+ get { return _rgt.LastParseItem; }
+ }
}
+
///
/// Function call expression, e.g. sin(0.5)
///
- class FunctionExpression : Expression
+ internal class FunctionExpression : Expression
{
// ** fields
- FunctionDefinition _fn;
- List _parms;
+ private readonly FunctionDefinition _fn;
+
+ private readonly List _parms;
// ** ctor
internal FunctionExpression()
- {
- }
+ { }
+
public FunctionExpression(FunctionDefinition function, List parms)
{
_fn = function;
@@ -330,6 +383,7 @@
{
return _fn.Function(_parms);
}
+
public override Expression Optimize()
{
bool allLits = true;
@@ -349,33 +403,46 @@
? new Expression(this.Evaluate())
: this;
}
+
+ public override string LastParseItem
+ {
+ get { return _parms.Last().LastParseItem; }
+ }
}
+
///
/// Simple variable reference.
///
- class VariableExpression : Expression
+ internal class VariableExpression : Expression
{
- Dictionary _dct;
- string _name;
+ private readonly Dictionary _dct;
+ private readonly string _name;
public VariableExpression(Dictionary dct, string name)
{
_dct = dct;
_name = name;
}
+
public override object Evaluate()
{
return _dct[_name];
}
+
+ public override string LastParseItem
+ {
+ get { return _name; }
+ }
}
+
///
/// Expression that represents an external object.
///
- class XObjectExpression :
+ internal class XObjectExpression :
Expression,
IEnumerable
{
- object _value;
+ private readonly object _value;
// ** ctor
internal XObjectExpression(object value)
@@ -398,18 +465,29 @@
// return raw object
return _value;
}
+
public IEnumerator GetEnumerator()
{
return (_value as IEnumerable).GetEnumerator();
}
+
+ public override string LastParseItem
+ {
+ get { return Value.ToString(); }
+ }
}
///
/// Expression that represents an omitted parameter.
///
- class EmptyValueExpression : Expression
+ internal class EmptyValueExpression : Expression
{
internal EmptyValueExpression() { }
+
+ public override string LastParseItem
+ {
+ get { return ""; }
+ }
}
///
diff --git a/ClosedXML/Excel/CalcEngine/ExpressionParseException.cs b/ClosedXML/Excel/CalcEngine/ExpressionParseException.cs
new file mode 100644
index 0000000..2de2293
--- /dev/null
+++ b/ClosedXML/Excel/CalcEngine/ExpressionParseException.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Text;
+
+namespace ClosedXML.Excel.CalcEngine
+{
+ ///
+ /// The exception that is thrown when the strings to be parsed to an expression is invalid.
+ ///
+ public class ExpressionParseException : Exception
+ {
+ ///
+ /// Initializes a new instance of the ExpressionParseException class with a
+ /// specified error message.
+ ///
+ /// The message that describes the error.
+ public ExpressionParseException(string message)
+ : base(message)
+ {
+ }
+ }
+}
diff --git a/ClosedXML/Excel/CalcEngine/Functions/Lookup.cs b/ClosedXML/Excel/CalcEngine/Functions/Lookup.cs
index 8a9ac19..964e72b 100644
--- a/ClosedXML/Excel/CalcEngine/Functions/Lookup.cs
+++ b/ClosedXML/Excel/CalcEngine/Functions/Lookup.cs
@@ -15,7 +15,7 @@
//ce.RegisterFunction("COLUMNS", , Columns); // Returns the number of columns in a reference
//ce.RegisterFunction("FORMULATEXT", , Formulatext); // Returns the formula at the given reference as text
//ce.RegisterFunction("GETPIVOTDATA", , Getpivotdata); // Returns data stored in a PivotTable report
- ce.RegisterFunction("HLOOKUP", 4, Hlookup); // Looks in the top row of an array and returns the value of the indicated cell
+ ce.RegisterFunction("HLOOKUP", 3, 4, Hlookup); // Looks in the top row of an array and returns the value of the indicated cell
//ce.RegisterFunction("HYPERLINK", , Hyperlink); // Creates a shortcut or jump that opens a document stored on a network server, an intranet, or the Internet
//ce.RegisterFunction("INDEX", , Index); // Uses an index to choose a value from a reference or array
//ce.RegisterFunction("INDIRECT", , Indirect); // Returns a reference indicated by a text value
@@ -26,7 +26,7 @@
//ce.RegisterFunction("ROWS", , Rows); // Returns the number of rows in a reference
//ce.RegisterFunction("RTD", , Rtd); // Retrieves real-time data from a program that supports COM automation
//ce.RegisterFunction("TRANSPOSE", , Transpose); // Returns the transpose of an array
- ce.RegisterFunction("VLOOKUP", 4, Vlookup); // Looks in the first column of an array and moves across the row to return the value of a cell
+ ce.RegisterFunction("VLOOKUP", 3, 4, Vlookup); // Looks in the first column of an array and moves across the row to return the value of a cell
}
private static object Hlookup(List p)
@@ -34,20 +34,25 @@
var lookup_value = p[0];
var table_array = p[1] as XObjectExpression;
+ if (table_array == null)
+ throw new ArgumentException("table_array has to be a range");
+
var range_reference = table_array.Value as CellRangeReference;
+ if (range_reference == null)
+ throw new ArgumentException("table_array has to be a range");
+
var range = range_reference.Range;
var row_index_num = (int)(p[2]);
- var range_lookup = p.Count < 4 || (bool)(p[3]);
-
- if (table_array == null || range_reference == null)
- throw new ApplicationException("table_array has to be a range");
+ var range_lookup = p.Count < 4
+ || p[3] is EmptyValueExpression
+ || (bool)(p[3]);
if (row_index_num < 1)
- throw new ApplicationException("col_index_num has to be positive");
+ throw new ArgumentOutOfRangeException("Row index", "row_index_num has to be positive");
if (row_index_num > range.RowCount())
- throw new ApplicationException("col_index_num must be smaller or equal to the number of rows in the table array");
+ throw new ArgumentOutOfRangeException("Row index", "row_index_num has to be positive");
IXLRangeColumn matching_column;
matching_column = range.FindColumn(c => !c.Cell(1).IsEmpty() && new Expression(c.Cell(1).Value).CompareTo(lookup_value) == 0);
@@ -67,7 +72,7 @@
}
if (matching_column == null)
- throw new ApplicationException("No matches found.");
+ throw new ArgumentException("No matches found.");
return matching_column
.Cell(row_index_num)
@@ -79,20 +84,25 @@
var lookup_value = p[0];
var table_array = p[1] as XObjectExpression;
+ if (table_array == null)
+ throw new ArgumentException("table_array has to be a range");
+
var range_reference = table_array.Value as CellRangeReference;
+ if (range_reference == null)
+ throw new ArgumentException("table_array has to be a range");
+
var range = range_reference.Range;
var col_index_num = (int)(p[2]);
- var range_lookup = p.Count < 4 || (bool)(p[3]);
-
- if (table_array == null || range_reference == null)
- throw new ApplicationException("table_array has to be a range");
+ var range_lookup = p.Count < 4
+ || p[3] is EmptyValueExpression
+ || (bool)(p[3]);
if (col_index_num < 1)
- throw new ApplicationException("col_index_num has to be positive");
+ throw new ArgumentOutOfRangeException("Column index", "col_index_num has to be positive");
if (col_index_num > range.ColumnCount())
- throw new ApplicationException("col_index_num must be smaller or equal to the number of columns in the table array");
+ throw new ArgumentOutOfRangeException("Column index", "col_index_num must be smaller or equal to the number of columns in the table array");
IXLRangeRow matching_row;
matching_row = range.FindRow(r => !r.Cell(1).IsEmpty() && new Expression(r.Cell(1).Value).CompareTo(lookup_value) == 0);
@@ -112,7 +122,7 @@
}
if (matching_row == null)
- throw new ApplicationException("No matches found.");
+ throw new ArgumentException("No matches found.");
return matching_row
.Cell(col_index_num)
diff --git a/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs b/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs
index c4e86ca..12e0995 100644
--- a/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs
+++ b/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs
@@ -1,8 +1,8 @@
+using ClosedXML.Excel.CalcEngine.Functions;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
-using ClosedXML.Excel.CalcEngine.Functions;
namespace ClosedXML.Excel.CalcEngine
{
@@ -29,7 +29,8 @@
ce.RegisterFunction("EXP", 1, Exp);
ce.RegisterFunction("FACT", 1, Fact);
ce.RegisterFunction("FACTDOUBLE", 1, FactDouble);
- ce.RegisterFunction("FLOOR", 1, Floor);
+ ce.RegisterFunction("FLOOR", 1, 2, Floor);
+ ce.RegisterFunction("FLOOR.MATH", 1, 3, FloorMath);
ce.RegisterFunction("GCD", 1, 255, Gcd);
ce.RegisterFunction("INT", 1, Int);
ce.RegisterFunction("LCM", 1, 255, Lcm);
@@ -120,12 +121,44 @@
private static object Floor(List p)
{
- return Math.Floor(p[0]);
+ double number = p[0];
+ double significance = 1;
+ if (p.Count > 1)
+ significance = p[1];
+
+ if (significance < 0)
+ {
+ number = -number;
+ significance = -significance;
+
+ return -Math.Floor(number / significance) * significance;
+ }
+ else if (significance == 1)
+ return Math.Floor(number);
+ else
+ return Math.Floor(number / significance) * significance;
+ }
+
+ private static object FloorMath(List p)
+ {
+ double number = p[0];
+ double significance = 1;
+ if (p.Count > 1) significance = p[1];
+
+ double mode = 0;
+ if (p.Count > 2) mode = p[2];
+
+ if (number >= 0)
+ return Math.Floor(number / Math.Abs(significance)) * Math.Abs(significance);
+ else if (mode >= 0)
+ return Math.Floor(number / Math.Abs(significance)) * Math.Abs(significance);
+ else
+ return -Math.Floor(-number / Math.Abs(significance)) * Math.Abs(significance);
}
private static object Int(List p)
{
- return (int) ((double) p[0]);
+ return (int)((double)p[0]);
}
private static object Ln(List p)
@@ -135,7 +168,7 @@
private static object Log(List p)
{
- var lbase = p.Count > 1 ? (double) p[1] : 10;
+ var lbase = p.Count > 1 ? (double)p[1] : 10;
return Math.Log(p[0], lbase);
}
@@ -161,7 +194,7 @@
private static object RandBetween(List p)
{
- return _rnd.Next((int) (double) p[0], (int) (double) p[1]);
+ return _rnd.Next((int)(double)p[0], (int)(double)p[1]);
}
private static object Sign(List p)
@@ -240,42 +273,42 @@
private static object Trunc(List p)
{
- return (double) (int) ((double) p[0]);
+ return (double)(int)((double)p[0]);
}
public static double DegreesToRadians(double degrees)
{
- return (Math.PI/180.0)*degrees;
+ return (Math.PI / 180.0) * degrees;
}
public static double RadiansToDegrees(double radians)
{
- return (180.0/Math.PI)*radians;
+ return (180.0 / Math.PI) * radians;
}
public static double GradsToRadians(double grads)
{
- return (grads/200.0)*Math.PI;
+ return (grads / 200.0) * Math.PI;
}
public static double RadiansToGrads(double radians)
{
- return (radians/Math.PI)*200.0;
+ return (radians / Math.PI) * 200.0;
}
public static double DegreesToGrads(double degrees)
{
- return (degrees/9.0)*10.0;
+ return (degrees / 9.0) * 10.0;
}
public static double GradsToDegrees(double grads)
{
- return (grads/10.0)*9.0;
+ return (grads / 10.0) * 9.0;
}
public static double ASinh(double x)
{
- return (Math.Log(x + Math.Sqrt(x*x + 1.0)));
+ return (Math.Log(x + Math.Sqrt(x * x + 1.0)));
}
private static object Acosh(List p)
@@ -295,8 +328,8 @@
private static object Combin(List p)
{
- Int32 n = (int) p[0];
- Int32 k = (int) p[1];
+ Int32 n = (int)p[0];
+ Int32 k = (int)p[1];
return XLMath.Combin(n, k);
}
@@ -305,8 +338,6 @@
return p[0] * (180.0 / Math.PI);
}
-
-
private static object Fact(List p)
{
var num = Math.Floor(p[0]);
@@ -348,15 +379,15 @@
private static int Lcm(int a, int b)
{
if (a == 0 || b == 0) return 0;
- return a * ( b / Gcd(a, b));
+ 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;
+ double number = p[0];
+ double divisor = p[1];
+
+ return number - Math.Floor(number / divisor) * divisor;
}
private static object MRound(List p)
@@ -479,7 +510,6 @@
temp = Math.Round(temp, 0, MidpointRounding.AwayFromZero);
return temp * Math.Pow(10, digits);
}
-
}
private static object RoundDown(List p)
@@ -512,7 +542,7 @@
var obj = p[3] as XObjectExpression;
if (obj == null)
- return p[3] * Math.Pow(x , n);
+ return p[3] * Math.Pow(x, n);
Double total = 0;
Int32 i = 0;
@@ -540,26 +570,37 @@
{
case 1:
return tally.Average();
+
case 2:
return tally.Count(true);
+
case 3:
return tally.Count(false);
+
case 4:
return tally.Max();
+
case 5:
return tally.Min();
+
case 6:
return tally.Product();
+
case 7:
return tally.Std();
+
case 8:
return tally.StdP();
+
case 9:
return tally.Sum();
+
case 10:
return tally.Var();
+
case 11:
return tally.VarP();
+
default:
throw new ArgumentException("Function not supported.");
}
@@ -591,19 +632,18 @@
}
}
-
return C;
}
private static double[,] GetArray(Expression expression)
{
var oExp1 = expression as XObjectExpression;
- if (oExp1 == null) return new [,]{{(Double)expression}};
+ if (oExp1 == null) return new[,] { { (Double)expression } };
var range = (oExp1.Value as CellRangeReference).Range;
var rowCount = range.RowCount();
var columnCount = range.ColumnCount();
- var arr = new double[rowCount,columnCount];
+ var arr = new double[rowCount, columnCount];
for (int row = 0; row < rowCount; row++)
{
diff --git a/ClosedXML/Excel/CalcEngine/Functions/Text.cs b/ClosedXML/Excel/CalcEngine/Functions/Text.cs
index cb66322..6046455 100644
--- a/ClosedXML/Excel/CalcEngine/Functions/Text.cs
+++ b/ClosedXML/Excel/CalcEngine/Functions/Text.cs
@@ -76,7 +76,7 @@
}
var index = text.IndexOf(srch, start, StringComparison.Ordinal);
if (index == -1)
- throw new Exception("String not found.");
+ throw new ArgumentException("String not found.");
else
return index + 1;
}
@@ -192,7 +192,7 @@
var search = WildcardToRegex((string)p[0]);
var text = (string)p[1];
- if ("" == text) throw new Exception("Invalid input string.");
+ if ("" == text) throw new ArgumentException("Invalid input string.");
var start = 0;
if (p.Count > 2)
@@ -203,12 +203,12 @@
Regex r = new Regex(search, RegexOptions.Compiled | RegexOptions.IgnoreCase);
var match = r.Match(text.Substring(start));
if (!match.Success)
- throw new Exception("Search failed.");
+ throw new ArgumentException("Search failed.");
else
return match.Index + start + 1;
//var index = text.IndexOf(search, start, StringComparison.OrdinalIgnoreCase);
//if (index == -1)
- // throw new Exception("String not found.");
+ // throw new ArgumentException("String not found.");
//else
// return index + 1;
}
@@ -233,7 +233,7 @@
int index = (int)p[3];
if (index < 1)
{
- throw new Exception("Invalid index in Substitute.");
+ throw new ArgumentException("Invalid index in Substitute.");
}
int pos = text.IndexOf(oldText);
while (pos > -1 && index > 1)
diff --git a/ClosedXML/Excel/CalcEngine/Functions/XLMatrix.cs b/ClosedXML/Excel/CalcEngine/Functions/XLMatrix.cs
index 80d2663..79d6a70 100644
--- a/ClosedXML/Excel/CalcEngine/Functions/XLMatrix.cs
+++ b/ClosedXML/Excel/CalcEngine/Functions/XLMatrix.cs
@@ -59,7 +59,7 @@
public void MakeLU() // Function for LU decomposition
{
- if (!IsSquare()) throw new Exception("The matrix is not square!");
+ if (!IsSquare()) throw new InvalidOperationException("The matrix is not square!");
L = IdentityMatrix(rows, cols);
U = Duplicate();
@@ -79,8 +79,8 @@
k0 = i;
}
}
- if (p == 0)
- throw new Exception("The matrix is singular!");
+ if (p == 0)
+ throw new InvalidOperationException("The matrix is singular!");
var pom1 = pi[k];
pi[k] = pi[k0];
@@ -115,8 +115,8 @@
public XLMatrix SolveWith(XLMatrix v) // Function solves Ax = v in confirmity with solution vector "v"
{
- if (rows != cols) throw new Exception("The matrix is not square!");
- if (rows != v.rows) throw new Exception("Wrong number of results in solution vector!");
+ if (rows != cols) throw new InvalidOperationException("The matrix is not square!");
+ if (rows != v.rows) throw new ArgumentException("Wrong number of results in solution vector!");
if (L == null) MakeLU();
var b = new XLMatrix(rows, 1);
@@ -242,9 +242,9 @@
for (var j = 0; j < nums.Length; j++) matrix[i, j] = double.Parse(nums[j]);
}
}
- catch (FormatException)
+ catch (FormatException fe)
{
- throw new Exception("Wrong input format!");
+ throw new FormatException("Wrong input format!", fe);
}
return matrix;
}
@@ -345,7 +345,7 @@
private static XLMatrix StrassenMultiply(XLMatrix A, XLMatrix B) // Smart matrix multiplication
{
- if (A.cols != B.rows) throw new Exception("Wrong dimension of matrix!");
+ if (A.cols != B.rows) throw new ArgumentException("Wrong dimension of matrix!");
XLMatrix R;
@@ -513,7 +513,7 @@
public static XLMatrix StupidMultiply(XLMatrix m1, XLMatrix m2) // Stupid matrix multiplication
{
- if (m1.cols != m2.rows) throw new Exception("Wrong dimensions of matrix!");
+ if (m1.cols != m2.rows) throw new ArgumentException("Wrong dimensions of matrix!");
var result = ZeroMatrix(m1.rows, m2.cols);
for (var i = 0; i < result.rows; i++)
@@ -535,7 +535,7 @@
private static XLMatrix Add(XLMatrix m1, XLMatrix m2)
{
if (m1.rows != m2.rows || m1.cols != m2.cols)
- throw new Exception("Matrices must have the same dimensions!");
+ throw new ArgumentException("Matrices must have the same dimensions!");
var r = new XLMatrix(m1.rows, m1.cols);
for (var i = 0; i < r.rows; i++)
for (var j = 0; j < r.cols; j++)
diff --git a/ClosedXML/Excel/CalcEngine/XLCalcEngine.cs b/ClosedXML/Excel/CalcEngine/XLCalcEngine.cs
index 6d5dc53..108ea40 100644
--- a/ClosedXML/Excel/CalcEngine/XLCalcEngine.cs
+++ b/ClosedXML/Excel/CalcEngine/XLCalcEngine.cs
@@ -92,7 +92,7 @@
{
if (_evaluating)
{
- throw new Exception("Circular Reference");
+ throw new InvalidOperationException("Circular Reference");
}
try
{
diff --git a/ClosedXML/Excel/Cells/IXLCell.cs b/ClosedXML/Excel/Cells/IXLCell.cs
index d3efb2e..8df2759 100644
--- a/ClosedXML/Excel/Cells/IXLCell.cs
+++ b/ClosedXML/Excel/Cells/IXLCell.cs
@@ -173,6 +173,14 @@
IXLRange InsertData(IEnumerable data);
///
+ /// Inserts the IEnumerable data elements and returns the range it occupies.
+ ///
+ /// The IEnumerable data.
+ /// if set to true the data will be transposed before inserting.
+ ///
+ IXLRange InsertData(IEnumerable data, Boolean tranpose);
+
+ ///
/// Inserts the IEnumerable data elements as a table and returns it.
/// The new table will receive a generic name: Table#
///
diff --git a/ClosedXML/Excel/Cells/XLCell.cs b/ClosedXML/Excel/Cells/XLCell.cs
index 5815958..f5e9084 100644
--- a/ClosedXML/Excel/Cells/XLCell.cs
+++ b/ClosedXML/Excel/Cells/XLCell.cs
@@ -1,4 +1,4 @@
-using FastMember;
+using FastMember;
using System;
using System.Collections;
using System.Collections.Generic;
@@ -221,6 +221,9 @@
public IXLCell SetValue(T value)
{
+ if (value == null)
+ return this.Clear(XLClearOptions.Contents);
+
FormulaA1 = String.Empty;
_richText = null;
var style = GetStyleForRead();
@@ -281,7 +284,7 @@
if (TryGetValue(out retVal))
return retVal;
- throw new Exception("Cannot convert cell value to " + typeof(T));
+ throw new FormatException("Cannot convert cell value to " + typeof(T));
}
public string GetString()
@@ -438,6 +441,8 @@
if (value as XLCells != null) throw new ArgumentException("Cannot assign IXLCells object to the cell value.");
+ if (SetTableHeader(value)) return;
+
if (SetRangeRows(value)) return;
if (SetRangeColumns(value)) return;
@@ -470,7 +475,7 @@
public IXLTable InsertTable(IEnumerable data, string tableName, bool createTable)
{
- if (data != null && data.GetType() != typeof(String))
+ if (data != null && !(data is String))
{
var ro = Address.RowNumber + 1;
var fRo = Address.RowNumber;
@@ -713,10 +718,18 @@
public IXLRange InsertData(IEnumerable data)
{
- if (data != null && data.GetType() != typeof(String))
+ return InsertData(data, false);
+ }
+
+ public IXLRange InsertData(IEnumerable data, Boolean transpose)
+ {
+ if (data != null && !(data is String))
{
- var ro = Address.RowNumber;
- var maxCo = 0;
+ var rowNumber = Address.RowNumber;
+ var columnNumber = Address.ColumnNumber;
+
+ var maxColumnNumber = 0;
+ var maxRowNumber = 0;
var isDataTable = false;
var isDataReader = false;
@@ -745,20 +758,31 @@
members = memberCache[itemType];
accessor = accessorCache[itemType];
- var co = Address.ColumnNumber;
+ if (transpose)
+ rowNumber = Address.RowNumber;
+ else
+ columnNumber = Address.ColumnNumber;
+
if (itemType.IsPrimitive || itemType == typeof(String) || itemType == typeof(DateTime) || itemType.IsNumber())
{
- SetValue(m, ro, co);
- co++;
+ SetValue(m, rowNumber, columnNumber);
+
+ if (transpose)
+ rowNumber++;
+ else
+ columnNumber++;
}
else if (itemType.IsArray)
{
- // dynamic arr = m;
foreach (var item in (Array)m)
{
- SetValue(item, ro, co);
- co++;
+ SetValue(item, rowNumber, columnNumber);
+
+ if (transpose)
+ rowNumber++;
+ else
+ columnNumber++;
}
}
else if (isDataTable || m is DataRow)
@@ -768,8 +792,12 @@
foreach (var item in (m as DataRow).ItemArray)
{
- SetValue(item, ro, co);
- co++;
+ SetValue(item, rowNumber, columnNumber);
+
+ if (transpose)
+ rowNumber++;
+ else
+ columnNumber++;
}
}
else if (isDataReader || m is IDataRecord)
@@ -782,31 +810,45 @@
var fieldCount = record.FieldCount;
for (var i = 0; i < fieldCount; i++)
{
- SetValue(record[i], ro, co);
- co++;
+ SetValue(record[i], rowNumber, columnNumber);
+
+ if (transpose)
+ rowNumber++;
+ else
+ columnNumber++;
}
}
else
{
foreach (var mi in members)
{
- SetValue(accessor[m, mi.Name], ro, co);
- co++;
+ SetValue(accessor[m, mi.Name], rowNumber, columnNumber);
+
+ if (transpose)
+ rowNumber++;
+ else
+ columnNumber++;
}
}
- if (co > maxCo)
- maxCo = co;
+ if (transpose)
+ columnNumber++;
+ else
+ rowNumber++;
- ro++;
+ if (columnNumber > maxColumnNumber)
+ maxColumnNumber = columnNumber;
+
+ if (rowNumber > maxRowNumber)
+ maxRowNumber = rowNumber;
}
ClearMerged();
return _worksheet.Range(
Address.RowNumber,
Address.ColumnNumber,
- ro - 1,
- maxCo - 1);
+ maxRowNumber - 1,
+ maxColumnNumber - 1);
}
return null;
@@ -1450,6 +1492,23 @@
#endregion IXLStylized Members
+ private bool SetTableHeader(object value)
+ {
+ foreach (var table in Worksheet.Tables.Where(t => t.ShowHeaderRow))
+ {
+ var cells = table.HeadersRow().CellsUsed(c => c.Address.Equals(this.Address));
+ if (cells.Any())
+ {
+ var oldName = cells.First().GetString();
+ var field = table.Field(oldName);
+ field.Name = value.ToString();
+ return true;
+ }
+ }
+
+ return false;
+ }
+
private bool SetRangeColumns(object value)
{
var columns = value as XLRangeColumns;
@@ -1620,7 +1679,7 @@
private bool SetEnumerable(object collectionObject)
{
// IXLRichText implements IEnumerable, but we don't want to handle this here.
- if ((collectionObject as IXLRichText) != null) return false;
+ if (collectionObject is IXLRichText) return false;
var asEnumerable = collectionObject as IEnumerable;
return InsertData(asEnumerable) != null;
@@ -1639,13 +1698,10 @@
{
if (value == null)
_worksheet.Cell(ro, co).SetValue(String.Empty);
+ else if (value is IConvertible)
+ _worksheet.Cell(ro, co).SetValue((T)Convert.ChangeType(value, typeof(T)));
else
- {
- if (value is IConvertible)
- _worksheet.Cell(ro, co).SetValue((T)Convert.ChangeType(value, typeof(T)));
- else
- _worksheet.Cell(ro, co).SetValue(value);
- }
+ _worksheet.Cell(ro, co).SetValue(value);
}
private void SetValue(object value)
diff --git a/ClosedXML/Excel/Columns/XLColumn.cs b/ClosedXML/Excel/Columns/XLColumn.cs
index b8036d4..ff70d31 100644
--- a/ClosedXML/Excel/Columns/XLColumn.cs
+++ b/ClosedXML/Excel/Columns/XLColumn.cs
@@ -774,17 +774,27 @@
#endregion
- public new Boolean IsEmpty()
+ public override Boolean IsEmpty()
{
return IsEmpty(false);
}
- public new Boolean IsEmpty(Boolean includeFormats)
+ public override Boolean IsEmpty(Boolean includeFormats)
{
if (includeFormats && !Style.Equals(Worksheet.Style))
return false;
return base.IsEmpty(includeFormats);
}
+
+ public override Boolean IsEntireRow()
+ {
+ return false;
+ }
+
+ public override Boolean IsEntireColumn()
+ {
+ return true;
+ }
}
}
diff --git a/ClosedXML/Excel/ConditionalFormats/Save/XLCFDataBarConverter.cs b/ClosedXML/Excel/ConditionalFormats/Save/XLCFDataBarConverter.cs
index f0bd151..ff2d3c0 100644
--- a/ClosedXML/Excel/ConditionalFormats/Save/XLCFDataBarConverter.cs
+++ b/ClosedXML/Excel/ConditionalFormats/Save/XLCFDataBarConverter.cs
@@ -7,20 +7,32 @@
namespace ClosedXML.Excel
{
- internal class XLCFDataBarConverter:IXLCFConverter
+ internal class XLCFDataBarConverter : IXLCFConverter
{
public ConditionalFormattingRule Convert(IXLConditionalFormat cf, Int32 priority, XLWorkbook.SaveContext context)
{
var conditionalFormattingRule = new ConditionalFormattingRule { Type = cf.ConditionalFormatType.ToOpenXml(), Priority = priority };
- var dataBar = new DataBar {ShowValue = !cf.ShowBarOnly};
- var conditionalFormatValueObject1 = new ConditionalFormatValueObject { Type = cf.ContentTypes[1].ToOpenXml()};
- if (cf.Values.Count >= 1) conditionalFormatValueObject1.Val = cf.Values[1].Value;
+ var dataBar = new DataBar { ShowValue = !cf.ShowBarOnly };
+ var conditionalFormatValueObject1 = new ConditionalFormatValueObject { Type = cf.ContentTypes[1].ToOpenXml() };
+ if (cf.Values.Any() && cf.Values[1]?.Value != null) conditionalFormatValueObject1.Val = cf.Values[1].Value;
- var conditionalFormatValueObject2 = new ConditionalFormatValueObject { Type = cf.ContentTypes[2].ToOpenXml()};
- if (cf.Values.Count >= 2) conditionalFormatValueObject2.Val = cf.Values[2].Value;
+ var conditionalFormatValueObject2 = new ConditionalFormatValueObject { Type = cf.ContentTypes[2].ToOpenXml() };
+ if (cf.Values.Count >= 2 && cf.Values[2]?.Value != null) conditionalFormatValueObject2.Val = cf.Values[2].Value;
- var color = new Color { Rgb = cf.Colors[1].Color.ToHex() };
+ var color = new Color();
+ switch (cf.Colors[1].ColorType)
+ {
+ case XLColorType.Color:
+ color.Rgb = cf.Colors[1].Color.ToHex();
+ break;
+ case XLColorType.Theme:
+ color.Theme = System.Convert.ToUInt32(cf.Colors[1].ThemeColor);
+ break;
+ case XLColorType.Indexed:
+ color.Indexed = System.Convert.ToUInt32(cf.Colors[1].Indexed);
+ break;
+ }
dataBar.Append(conditionalFormatValueObject1);
dataBar.Append(conditionalFormatValueObject2);
diff --git a/ClosedXML/Excel/Drawings/IXLPicture.cs b/ClosedXML/Excel/Drawings/IXLPicture.cs
index 2c2f750..cf167d2 100644
--- a/ClosedXML/Excel/Drawings/IXLPicture.cs
+++ b/ClosedXML/Excel/Drawings/IXLPicture.cs
@@ -16,6 +16,8 @@
Int32 Height { get; set; }
+ Int32 Id { get; }
+
MemoryStream ImageStream { get; }
Int32 Left { get; set; }
diff --git a/ClosedXML/Excel/Drawings/XLPicture.cs b/ClosedXML/Excel/Drawings/XLPicture.cs
index 422336d..9266215 100644
--- a/ClosedXML/Excel/Drawings/XLPicture.cs
+++ b/ClosedXML/Excel/Drawings/XLPicture.cs
@@ -16,6 +16,7 @@
private static IDictionary FormatMap;
private readonly IXLWorksheet _worksheet;
private Int32 height;
+ private Int32 id;
private String name = string.Empty;
private Int32 width;
@@ -32,7 +33,7 @@
}
internal XLPicture(IXLWorksheet worksheet, Stream stream)
- : this(worksheet)
+ : this(worksheet)
{
if (stream == null) throw new ArgumentNullException(nameof(stream));
@@ -67,11 +68,8 @@
using (var bitmap = new Bitmap(ImageStream))
{
- if (FormatMap.ContainsKey(this.Format))
- {
- if (FormatMap[this.Format].Guid != bitmap.RawFormat.Guid)
- throw new ArgumentException("The picture format in the stream and the parameter don't match");
- }
+ if (FormatMap.ContainsKey(this.Format) && FormatMap[this.Format].Guid != bitmap.RawFormat.Guid)
+ throw new ArgumentException("The picture format in the stream and the parameter don't match");
DeduceDimensionsFromBitmap(bitmap);
}
@@ -105,6 +103,13 @@
[XLMarkerPosition.TopLeft] = null,
[XLMarkerPosition.BottomRight] = null
};
+
+ // Calculate default picture ID
+ var allPictures = worksheet.Workbook.Worksheets.SelectMany(ws => ws.Pictures);
+ if (allPictures.Any())
+ this.id = allPictures.Max(p => p.Id) + 1;
+ else
+ this.id = 1;
}
public IXLAddress BottomRightCellAddress
@@ -135,6 +140,16 @@
}
}
+ public Int32 Id
+ {
+ get { return id; }
+ internal set
+ {
+ if ((_worksheet.Pictures.FirstOrDefault(p => p.Id.Equals(value)) ?? this) != this)
+ throw new ArgumentException($"The picture ID '{value}' already exists.");
+ }
+ }
+
public MemoryStream ImageStream { get; private set; }
public Int32 Left
@@ -156,19 +171,10 @@
{
if (name == value) return;
- if (value.IndexOfAny(InvalidNameChars.ToCharArray()) != -1)
- throw new ArgumentException($"Picture names cannot contain any of the following characters: {InvalidNameChars}");
-
- if (String.IsNullOrWhiteSpace(value))
- throw new ArgumentException("Picture names cannot be empty");
-
- if (value.Length > 31)
- throw new ArgumentException("Picture names cannot be more than 31 characters");
-
if ((_worksheet.Pictures.FirstOrDefault(p => p.Name.Equals(value, StringComparison.OrdinalIgnoreCase)) ?? this) != this)
throw new ArgumentException($"The picture name '{value}' already exists.");
- name = value;
+ SetName(value);
}
}
@@ -323,6 +329,20 @@
return this;
}
+ internal void SetName(string value)
+ {
+ if (value.IndexOfAny(InvalidNameChars.ToCharArray()) != -1)
+ throw new ArgumentException($"Picture names cannot contain any of the following characters: {InvalidNameChars}");
+
+ if (String.IsNullOrWhiteSpace(value))
+ throw new ArgumentException("Picture names cannot be empty");
+
+ if (value.Length > 31)
+ throw new ArgumentException("Picture names cannot be more than 31 characters");
+
+ name = value;
+ }
+
private static ImageFormat FromMimeType(string mimeType)
{
var guid = ImageCodecInfo.GetImageDecoders().FirstOrDefault(c => c.MimeType.Equals(mimeType, StringComparison.OrdinalIgnoreCase))?.FormatID;
diff --git a/ClosedXML/Excel/Drawings/XLPictures.cs b/ClosedXML/Excel/Drawings/XLPictures.cs
index 3381309..6a102dd 100644
--- a/ClosedXML/Excel/Drawings/XLPictures.cs
+++ b/ClosedXML/Excel/Drawings/XLPictures.cs
@@ -39,7 +39,7 @@
return picture;
}
- public Drawings.IXLPicture Add(Stream stream, XLPictureFormat format)
+ public IXLPicture Add(Stream stream, XLPictureFormat format)
{
var picture = new XLPicture(_worksheet, stream, format);
_pictures.Add(picture);
@@ -127,13 +127,21 @@
var matches = _pictures.Where(p => p.Name.Equals(pictureName, StringComparison.OrdinalIgnoreCase));
if (matches.Any())
{
- picture = matches.Single();
+ picture = matches.First();
return true;
}
picture = null;
return false;
}
+ internal IXLPicture Add(Stream stream, string name, int Id)
+ {
+ var picture = Add(stream) as XLPicture;
+ picture.SetName(name);
+ picture.Id = Id;
+ return picture;
+ }
+
private String GetNextPictureName()
{
var pictureNumber = this.Count;
diff --git a/ClosedXML/Excel/NamedRanges/XLNamedRanges.cs b/ClosedXML/Excel/NamedRanges/XLNamedRanges.cs
index a7b191f..f3f7304 100644
--- a/ClosedXML/Excel/NamedRanges/XLNamedRanges.cs
+++ b/ClosedXML/Excel/NamedRanges/XLNamedRanges.cs
@@ -69,10 +69,16 @@
if (!match.Success)
{
- if (Worksheet == null || !XLHelper.NamedRangeReferenceRegex.Match(Worksheet.Range(rangeAddress).ToString()).Success)
- throw new ArgumentException("For named ranges in the workbook scope, specify the sheet name in the reference.");
+ var range = Worksheet?.Range(rangeAddress) ?? Workbook.Range(rangeAddress);
+ if (range == null)
+ throw new ArgumentException(string.Format("The range address '{0}' for the named range '{1}' is not a valid range.", rangeAddress, rangeName));
else
- rangeAddress = Worksheet.Range(rangeAddress).ToString();
+ {
+ if (Worksheet == null || !XLHelper.NamedRangeReferenceRegex.Match(range.ToString()).Success)
+ throw new ArgumentException("For named ranges in the workbook scope, specify the sheet name in the reference.");
+ else
+ rangeAddress = Worksheet.Range(rangeAddress).ToString();
+ }
}
}
diff --git a/ClosedXML/Excel/Ranges/IXLRange.cs b/ClosedXML/Excel/Ranges/IXLRange.cs
index fbbe958..992ebf9 100644
--- a/ClosedXML/Excel/Ranges/IXLRange.cs
+++ b/ClosedXML/Excel/Ranges/IXLRange.cs
@@ -1,12 +1,14 @@
using System;
-
namespace ClosedXML.Excel
{
public enum XLShiftDeletedCells { ShiftCellsUp, ShiftCellsLeft }
+
public enum XLTransposeOptions { MoveCells, ReplaceCells }
+
public enum XLSearchContents { Values, Formulas, ValuesAndFormulas }
- public interface IXLRange: IXLRangeBase
+
+ public interface IXLRange : IXLRangeBase
{
///
/// Gets the cell at the specified row and column.
@@ -28,6 +30,7 @@
/// The cell's row.
/// The cell's column.
IXLCell Cell(int row, string column);
+
/// Gets the cell at the specified address.
/// The cell address is relative to the parent range.
/// The cell address in the parent range.
@@ -36,79 +39,100 @@
///
/// Gets the specified column of the range.
///
- /// The range column.
- IXLRangeColumn Column(int column);
+ /// The column number.
+ ///
+ IXLRangeColumn Column(int columnNumber);
+
///
/// Gets the specified column of the range.
///
- /// The range column.
- IXLRangeColumn Column(string column);
+ /// Column letter.
+ IXLRangeColumn Column(string columnLetter);
+
///
/// Gets the first column of the range.
///
IXLRangeColumn FirstColumn(Func predicate = null);
+
///
/// Gets the first column of the range that contains a cell with a value.
///
IXLRangeColumn FirstColumnUsed(Boolean includeFormats, Func predicate = null);
+
IXLRangeColumn FirstColumnUsed(Func predicate = null);
+
///
/// Gets the last column of the range.
///
IXLRangeColumn LastColumn(Func predicate = null);
+
///
/// Gets the last column of the range that contains a cell with a value.
///
IXLRangeColumn LastColumnUsed(Boolean includeFormats, Func predicate = null);
+
IXLRangeColumn LastColumnUsed(Func predicate = null);
+
///
/// Gets a collection of all columns in this range.
///
IXLRangeColumns Columns(Func predicate = null);
+
///
/// Gets a collection of the specified columns in this range.
///
/// The first column to return.
/// The last column to return.
IXLRangeColumns Columns(int firstColumn, int lastColumn);
+
///
/// Gets a collection of the specified columns in this range.
///
/// The first column to return.
/// The last column to return.
IXLRangeColumns Columns(string firstColumn, string lastColumn);
+
///
/// Gets a collection of the specified columns in this range, separated by commas.
/// e.g. Columns("G:H"), Columns("10:11,13:14"), Columns("P:Q,S:T"), Columns("V")
///
/// The columns to return.
IXLRangeColumns Columns(string columns);
+
///
/// Returns the first row that matches the given predicate
///
IXLRangeColumn FindColumn(Func predicate);
+
///
/// Returns the first row that matches the given predicate
///
IXLRangeRow FindRow(Func predicate);
+
///
/// Gets the first row of the range.
///
IXLRangeRow FirstRow(Func predicate = null);
+
///
/// Gets the first row of the range that contains a cell with a value.
///
IXLRangeRow FirstRowUsed(Boolean includeFormats, Func predicate = null);
+
IXLRangeRow FirstRowUsed(Func predicate = null);
+
///
/// Gets the last row of the range.
///
IXLRangeRow LastRow(Func predicate = null);
+
///
/// Gets the last row of the range that contains a cell with a value.
///
IXLRangeRow LastRowUsed(Boolean includeFormats, Func predicate = null);
+
IXLRangeRow LastRowUsed(Func predicate = null);
+
///
/// Gets the specified row of the range.
///
@@ -124,6 +148,7 @@
/// The last row to return.
///
IXLRangeRows Rows(int firstRow, int lastRow);
+
///
/// Gets a collection of the specified rows in this range, separated by commas.
/// e.g. Rows("4:5"), Rows("7:8,10:11"), Rows("13")
@@ -182,27 +207,34 @@
///
/// Number of columns to insert.
IXLRangeColumns InsertColumnsAfter(int numberOfColumns);
+
IXLRangeColumns InsertColumnsAfter(int numberOfColumns, Boolean expandRange);
+
///
/// Inserts X number of columns to the left of this range.
/// This range and all cells to the right of this range will be shifted X number of columns.
///
/// Number of columns to insert.
IXLRangeColumns InsertColumnsBefore(int numberOfColumns);
+
IXLRangeColumns InsertColumnsBefore(int numberOfColumns, Boolean expandRange);
+
///
/// Inserts X number of rows on top of this range.
/// This range and all cells below this range will be shifted X number of rows.
///
/// Number of rows to insert.
IXLRangeRows InsertRowsAbove(int numberOfRows);
+
IXLRangeRows InsertRowsAbove(int numberOfRows, Boolean expandRange);
+
///
/// Inserts X number of rows below this range.
/// All cells below this range will be shifted X number of rows.
///
/// Number of rows to insert.
IXLRangeRows InsertRowsBelow(int numberOfRows);
+
IXLRangeRows InsertRowsBelow(int numberOfRows, Boolean expandRange);
///
@@ -218,13 +250,17 @@
void Transpose(XLTransposeOptions transposeOption);
IXLTable AsTable();
+
IXLTable AsTable(String name);
+
IXLTable CreateTable();
+
IXLTable CreateTable(String name);
IXLRange RangeUsed();
IXLRange CopyTo(IXLCell target);
+
IXLRange CopyTo(IXLRangeBase target);
IXLSortElements SortRows { get; }
@@ -233,9 +269,10 @@
IXLRange Sort();
IXLRange Sort(String columnsToSortBy, XLSortOrder sortOrder = XLSortOrder.Ascending, Boolean matchCase = false, Boolean ignoreBlanks = true);
+
IXLRange Sort(Int32 columnToSortBy, XLSortOrder sortOrder = XLSortOrder.Ascending, Boolean matchCase = false, Boolean ignoreBlanks = true);
+
IXLRange SortLeftToRight(XLSortOrder sortOrder = XLSortOrder.Ascending, Boolean matchCase = false, Boolean ignoreBlanks = true);
-
IXLRange SetDataType(XLCellValues dataType);
@@ -246,9 +283,11 @@
new IXLRange Clear(XLClearOptions clearOptions = XLClearOptions.ContentsAndFormats);
IXLRangeRows RowsUsed(Boolean includeFormats, Func predicate = null);
+
IXLRangeRows RowsUsed(Func predicate = null);
+
IXLRangeColumns ColumnsUsed(Boolean includeFormats, Func predicate = null);
+
IXLRangeColumns ColumnsUsed(Func predicate = null);
}
}
-
diff --git a/ClosedXML/Excel/Ranges/IXLRangeBase.cs b/ClosedXML/Excel/Ranges/IXLRangeBase.cs
index 76902d0..064d975 100644
--- a/ClosedXML/Excel/Ranges/IXLRangeBase.cs
+++ b/ClosedXML/Excel/Ranges/IXLRangeBase.cs
@@ -1,4 +1,5 @@
using System;
+using System.Globalization;
namespace ClosedXML.Excel
{
@@ -8,7 +9,7 @@
Worksheet
}
- public interface IXLRangeBase: IDisposable
+ public interface IXLRangeBase : IDisposable
{
IXLWorksheet Worksheet { get; }
@@ -64,7 +65,6 @@
IXLHyperlinks Hyperlinks { get; }
-
///
/// Returns the collection of cells.
///
@@ -94,6 +94,15 @@
IXLCells CellsUsed(Boolean includeFormats, Func predicate);
///
+ /// Searches the cells' contents for a given piece of text
+ ///
+ /// The search text.
+ /// The compare options.
+ /// if set to true search formulae instead of cell values.
+ ///
+ IXLCells Search(String searchText, CompareOptions compareOptions = CompareOptions.Ordinal, Boolean searchFormulae = false);
+
+ ///
/// Returns the first cell of this range.
///
IXLCell FirstCell();
@@ -236,15 +245,19 @@
IXLRange AsRange();
Boolean IsMerged();
+
Boolean IsEmpty();
+
Boolean IsEmpty(Boolean includeFormats);
+ Boolean IsEntireRow();
+
+ Boolean IsEntireColumn();
IXLPivotTable CreatePivotTable(IXLCell targetCell);
+
IXLPivotTable CreatePivotTable(IXLCell targetCell, String name);
-
-
//IXLChart CreateChart(Int32 firstRow, Int32 firstColumn, Int32 lastRow, Int32 lastColumn);
IXLAutoFilter SetAutoFilter();
diff --git a/ClosedXML/Excel/Ranges/XLRange.cs b/ClosedXML/Excel/Ranges/XLRange.cs
index 94d53e3..1991c89 100644
--- a/ClosedXML/Excel/Ranges/XLRange.cs
+++ b/ClosedXML/Excel/Ranges/XLRange.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
-
namespace ClosedXML.Excel
{
internal class XLRange : XLRangeBase, IXLRange
@@ -23,29 +22,28 @@
SetStyle(xlRangeParameters.DefaultStyle);
}
- #endregion
+ #endregion Constructor
public XLRangeParameters RangeParameters { get; private set; }
#region IXLRange Members
-
IXLRangeRow IXLRange.Row(Int32 row)
{
return Row(row);
}
- IXLRangeColumn IXLRange.Column(Int32 column)
+ IXLRangeColumn IXLRange.Column(Int32 columnNumber)
{
- return Column(column);
+ return Column(columnNumber);
}
- IXLRangeColumn IXLRange.Column(String column)
+ IXLRangeColumn IXLRange.Column(String columnLetter)
{
- return Column(column);
+ return Column(columnLetter);
}
- public IXLRangeColumns Columns(Func predicate = null)
+ public virtual IXLRangeColumns Columns(Func predicate = null)
{
var retVal = new XLRangeColumns();
Int32 columnCount = ColumnCount();
@@ -69,13 +67,13 @@
return retVal;
}
- public IXLRangeColumns Columns(String firstColumn, String lastColumn)
+ public virtual IXLRangeColumns Columns(String firstColumn, String lastColumn)
{
return Columns(XLHelper.GetColumnNumberFromLetter(firstColumn),
XLHelper.GetColumnNumberFromLetter(lastColumn));
}
- public IXLRangeColumns Columns(String columns)
+ public virtual IXLRangeColumns Columns(String columns)
{
var retVal = new XLRangeColumns();
var columnPairs = columns.Split(',');
@@ -274,6 +272,7 @@
{
return CreateTable();
}
+
public XLTable CreateTable()
{
return new XLTable(this, true, true);
@@ -283,6 +282,7 @@
{
return CreateTable(name);
}
+
public XLTable CreateTable(String name)
{
return new XLTable(this, name, true, true);
@@ -333,27 +333,27 @@
return this;
}
-
public new IXLRange Sort()
{
return base.Sort().AsRange();
}
-
+
public new IXLRange Sort(String columnsToSortBy, XLSortOrder sortOrder = XLSortOrder.Ascending, Boolean matchCase = false, Boolean ignoreBlanks = true)
{
return base.Sort(columnsToSortBy, sortOrder, matchCase, ignoreBlanks).AsRange();
}
+
public new IXLRange Sort(Int32 columnToSortBy, XLSortOrder sortOrder = XLSortOrder.Ascending, Boolean matchCase = false, Boolean ignoreBlanks = true)
{
return base.Sort(columnToSortBy, sortOrder, matchCase, ignoreBlanks).AsRange();
}
+
public new IXLRange SortLeftToRight(XLSortOrder sortOrder = XLSortOrder.Ascending, Boolean matchCase = false, Boolean ignoreBlanks = true)
{
return base.SortLeftToRight(sortOrder, matchCase, ignoreBlanks).AsRange();
}
-
- #endregion
+ #endregion IXLRange Members
private void WorksheetRangeShiftedColumns(XLRange range, int columnsShifted)
{
@@ -362,13 +362,14 @@
private void WorksheetRangeShiftedRows(XLRange range, int rowsShifted)
{
- ShiftRows(RangeAddress, range, rowsShifted);
+ ShiftRows(RangeAddress, range, rowsShifted);
}
IXLRangeColumn IXLRange.FirstColumn(Func predicate)
{
return FirstColumn(predicate);
}
+
public XLRangeColumn FirstColumn(Func predicate = null)
{
if (predicate == null)
@@ -390,6 +391,7 @@
{
return LastColumn(predicate);
}
+
public XLRangeColumn LastColumn(Func predicate = null)
{
Int32 columnCount = ColumnCount();
@@ -407,10 +409,11 @@
return null;
}
- IXLRangeColumn IXLRange.FirstColumnUsed(Func predicate )
+ IXLRangeColumn IXLRange.FirstColumnUsed(Func predicate)
{
return FirstColumnUsed(false, predicate);
}
+
public XLRangeColumn FirstColumnUsed(Func predicate = null)
{
return FirstColumnUsed(false, predicate);
@@ -420,6 +423,7 @@
{
return FirstColumnUsed(includeFormats, predicate);
}
+
public XLRangeColumn FirstColumnUsed(Boolean includeFormats, Func predicate = null)
{
if (predicate == null)
@@ -450,6 +454,7 @@
{
return LastColumnUsed(false, predicate);
}
+
public XLRangeColumn LastColumnUsed(Func predicate = null)
{
return LastColumnUsed(false, predicate);
@@ -459,6 +464,7 @@
{
return LastColumnUsed(includeFormats, predicate);
}
+
public XLRangeColumn LastColumnUsed(Boolean includeFormats, Func predicate = null)
{
if (predicate == null)
@@ -489,6 +495,7 @@
{
return FirstRow(predicate);
}
+
public XLRangeRow FirstRow(Func predicate = null)
{
if (predicate == null)
@@ -510,6 +517,7 @@
{
return LastRow(predicate);
}
+
public XLRangeRow LastRow(Func predicate = null)
{
Int32 rowCount = RowCount();
@@ -531,6 +539,7 @@
{
return FirstRowUsed(false, predicate);
}
+
public XLRangeRow FirstRowUsed(Func predicate = null)
{
return FirstRowUsed(false, predicate);
@@ -540,6 +549,7 @@
{
return FirstRowUsed(includeFormats, predicate);
}
+
public XLRangeRow FirstRowUsed(Boolean includeFormats, Func predicate = null)
{
if (predicate == null)
@@ -572,6 +582,7 @@
{
return LastRowUsed(false, predicate);
}
+
public XLRangeRow LastRowUsed(Func predicate = null)
{
return LastRowUsed(false, predicate);
@@ -581,6 +592,7 @@
{
return LastRowUsed(includeFormats, predicate);
}
+
public XLRangeRow LastRowUsed(Boolean includeFormats, Func predicate = null)
{
if (predicate == null)
@@ -607,11 +619,11 @@
return null;
}
-
IXLRangeRows IXLRange.RowsUsed(Boolean includeFormats, Func predicate)
{
return RowsUsed(includeFormats, predicate);
}
+
public XLRangeRows RowsUsed(Boolean includeFormats, Func predicate = null)
{
XLRangeRows rows = new XLRangeRows();
@@ -627,19 +639,23 @@
}
return rows;
}
+
IXLRangeRows IXLRange.RowsUsed(Func predicate)
{
return RowsUsed(predicate);
}
+
public XLRangeRows RowsUsed(Func predicate = null)
{
return RowsUsed(false, predicate);
}
+
IXLRangeColumns IXLRange.ColumnsUsed(Boolean includeFormats, Func predicate)
{
return ColumnsUsed(includeFormats, predicate);
}
- public XLRangeColumns ColumnsUsed(Boolean includeFormats, Func predicate = null)
+
+ public virtual XLRangeColumns ColumnsUsed(Boolean includeFormats, Func predicate = null)
{
XLRangeColumns columns = new XLRangeColumns();
Int32 columnCount = ColumnCount();
@@ -654,11 +670,13 @@
}
return columns;
}
+
IXLRangeColumns IXLRange.ColumnsUsed(Func predicate)
{
return ColumnsUsed(predicate);
}
- public XLRangeColumns ColumnsUsed(Func predicate = null)
+
+ public virtual XLRangeColumns ColumnsUsed(Func predicate = null)
{
return ColumnsUsed(false, predicate);
}
@@ -682,34 +700,30 @@
new XLRangeParameters(new XLRangeAddress(firstCellAddress, lastCellAddress), Worksheet.Style), false);
}
-
-
- public XLRangeColumn Column(Int32 column)
+ public virtual XLRangeColumn Column(Int32 columnNumber)
{
- if (column <= 0 || column > XLHelper.MaxColumnNumber)
+ if (columnNumber <= 0 || columnNumber > XLHelper.MaxColumnNumber)
throw new IndexOutOfRangeException(String.Format("Column number must be between 1 and {0}", XLHelper.MaxColumnNumber));
var firstCellAddress = new XLAddress(Worksheet,
RangeAddress.FirstAddress.RowNumber,
- RangeAddress.FirstAddress.ColumnNumber + column - 1,
+ RangeAddress.FirstAddress.ColumnNumber + columnNumber - 1,
false,
false);
var lastCellAddress = new XLAddress(Worksheet,
RangeAddress.LastAddress.RowNumber,
- RangeAddress.FirstAddress.ColumnNumber + column - 1,
+ RangeAddress.FirstAddress.ColumnNumber + columnNumber - 1,
false,
false);
return new XLRangeColumn(
new XLRangeParameters(new XLRangeAddress(firstCellAddress, lastCellAddress), Worksheet.Style), false);
}
- public XLRangeColumn Column(String column)
+ public virtual XLRangeColumn Column(String columnLetter)
{
- return Column(XLHelper.GetColumnNumberFromLetter(column));
+ return Column(XLHelper.GetColumnNumberFromLetter(columnLetter));
}
-
-
private void TransposeRange(int squareSide)
{
var cellsToInsert = new Dictionary();
@@ -728,7 +742,7 @@
{
var oldCell = rngToTranspose.Cell(ro, co);
var newKey = rngToTranspose.Cell(co, ro).Address;
- // new XLAddress(Worksheet, c.Address.ColumnNumber, c.Address.RowNumber);
+ // new XLAddress(Worksheet, c.Address.ColumnNumber, c.Address.RowNumber);
var newCell = new XLCell(Worksheet, newKey, oldCell.GetStyleId());
newCell.CopyFrom(oldCell, true);
cellsToInsert.Add(new XLSheetPoint(newKey.RowNumber, newKey.ColumnNumber), newCell);
diff --git a/ClosedXML/Excel/Ranges/XLRangeAddress.cs b/ClosedXML/Excel/Ranges/XLRangeAddress.cs
index df631ec..fbe5135 100644
--- a/ClosedXML/Excel/Ranges/XLRangeAddress.cs
+++ b/ClosedXML/Excel/Ranges/XLRangeAddress.cs
@@ -84,7 +84,7 @@
get
{
if (IsInvalid)
- throw new Exception("Range is invalid.");
+ throw new InvalidOperationException("Range is invalid.");
return _firstAddress;
}
@@ -96,7 +96,7 @@
get
{
if (IsInvalid)
- throw new Exception("Range is an invalid state.");
+ throw new InvalidOperationException("Range is an invalid state.");
return _lastAddress;
}
diff --git a/ClosedXML/Excel/Ranges/XLRangeBase.cs b/ClosedXML/Excel/Ranges/XLRangeBase.cs
index 9e9b20e..0534107 100644
--- a/ClosedXML/Excel/Ranges/XLRangeBase.cs
+++ b/ClosedXML/Excel/Ranges/XLRangeBase.cs
@@ -2,36 +2,39 @@
using ClosedXML.Extensions;
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
-
-
namespace ClosedXML.Excel
{
internal abstract class XLRangeBase : IXLRangeBase, IXLStylized
{
public Boolean StyleChanged { get; set; }
+
#region Fields
private IXLStyle _style;
private XLSortElements _sortRows;
private XLSortElements _sortColumns;
- #endregion
+ #endregion Fields
private Int32 _styleCacheId;
+
protected void SetStyle(IXLStyle styleToUse)
{
_styleCacheId = Worksheet.Workbook.GetStyleId(styleToUse);
_style = null;
StyleChanged = false;
}
+
protected void SetStyle(Int32 styleId)
{
_styleCacheId = styleId;
_style = null;
StyleChanged = false;
}
+
public Int32 GetStyleId()
{
if (StyleChanged)
@@ -39,6 +42,7 @@
return _styleCacheId;
}
+
protected IXLStyle GetStyle()
{
return _style ?? (_style = new XLStyle(this, Worksheet.Workbook.GetStyleById(_styleCacheId)));
@@ -46,18 +50,17 @@
#region Constructor
- static Int32 IdCounter = 0;
- readonly Int32 Id;
+ private static Int32 IdCounter = 0;
+ private readonly Int32 Id;
protected XLRangeBase(XLRangeAddress rangeAddress)
{
-
Id = ++IdCounter;
RangeAddress = new XLRangeAddress(rangeAddress);
}
- #endregion
+ #endregion Constructor
private XLCallbackAction _shiftedRowsAction;
@@ -71,6 +74,7 @@
}
private XLCallbackAction _shiftedColumnsAction;
+
protected void SubscribeToShiftedColumns(Action action)
{
if (Worksheet == null || !Worksheet.EventTrackingEnabled) return;
@@ -82,9 +86,8 @@
#region Public properties
- //public XLRangeAddress RangeAddress { get; protected set; }
-
private XLRangeAddress _rangeAddress;
+
public XLRangeAddress RangeAddress
{
get { return _rangeAddress; }
@@ -243,8 +246,6 @@
}
}
-
-
public Object Value
{
set { Cells().ForEach(c => c.Value = value); }
@@ -255,7 +256,7 @@
set { Cells().ForEach(c => c.DataType = value); }
}
- #endregion
+ #endregion IXLRangeBase Members
#region IXLStylized Members
@@ -268,9 +269,9 @@
}
}
- #endregion
+ #endregion IXLStylized Members
- #endregion
+ #endregion Public properties
#region IXLRangeBase Members
@@ -457,17 +458,17 @@
get { return GetStyle(); }
set { Cells().ForEach(c => c.Style = value); }
}
+
IXLRange IXLRangeBase.AsRange()
{
return AsRange();
}
+
public virtual XLRange AsRange()
{
return Worksheet.Range(RangeAddress.FirstAddress, RangeAddress.LastAddress);
}
-
-
public IXLRange AddToNamed(String rangeName)
{
return AddToNamed(rangeName, XLScope.Workbook);
@@ -505,18 +506,30 @@
return Cells().Any(c => c.IsMerged());
}
- public Boolean IsEmpty()
+ public virtual Boolean IsEmpty()
{
return !CellsUsed().Any() || CellsUsed().Any(c => c.IsEmpty());
}
- public Boolean IsEmpty(Boolean includeFormats)
+ public virtual Boolean IsEmpty(Boolean includeFormats)
{
return !CellsUsed(includeFormats).Cast().Any() ||
CellsUsed(includeFormats).Cast().Any(c => c.IsEmpty(includeFormats));
}
- #endregion
+ public virtual Boolean IsEntireRow()
+ {
+ return RangeAddress.FirstAddress.ColumnNumber == 1
+ && RangeAddress.LastAddress.ColumnNumber == XLHelper.MaxColumnNumber;
+ }
+
+ public virtual Boolean IsEntireColumn()
+ {
+ return RangeAddress.FirstAddress.RowNumber == 1
+ && RangeAddress.LastAddress.RowNumber == XLHelper.MaxRowNumber;
+ }
+
+ #endregion IXLRangeBase Members
#region IXLStylized Members
@@ -539,7 +552,28 @@
set { SetStyle(value); }
}
- #endregion
+ #endregion IXLStylized Members
+
+ public IXLCells Search(String searchText, CompareOptions compareOptions = CompareOptions.Ordinal, Boolean searchFormulae = false)
+ {
+ var culture = CultureInfo.CurrentCulture;
+ return this.CellsUsed(false, c =>
+ {
+ try
+ {
+ if (searchFormulae)
+ return c.HasFormula
+ && culture.CompareInfo.IndexOf(c.FormulaA1, searchText, compareOptions) >= 0
+ || culture.CompareInfo.IndexOf(c.Value.ToString(), searchText, compareOptions) >= 0;
+ else
+ return culture.CompareInfo.IndexOf(c.GetFormattedString(), searchText, compareOptions) >= 0;
+ }
+ catch
+ {
+ return false;
+ }
+ });
+ }
public XLCell FirstCell()
{
@@ -642,7 +676,6 @@
}
}
-
if (sp.Row > 0)
return Worksheet.Cell(sp.Row, sp.Column);
@@ -734,7 +767,6 @@
}
}
-
if (sp.Row > 0)
return Worksheet.Cell(sp.Row, sp.Column);
@@ -748,7 +780,6 @@
public XLCell Cell(String cellAddressInRange)
{
-
if (XLHelper.IsValidA1Address(cellAddressInRange))
return Cell(XLAddress.Create(Worksheet, cellAddressInRange));
@@ -810,7 +841,7 @@
Int32 newCellStyleId = styleId;
- // If the default style for this range base is empty, but the worksheet
+ // If the default style for this range base is empty, but the worksheet
// has a default style, use the worksheet's default style
if (styleId == 0 && worksheetStyleId != 0)
newCellStyleId = worksheetStyleId;
@@ -904,7 +935,6 @@
public XLRange Range(IXLRangeAddress rangeAddress)
{
-
var newFirstCellAddress = new XLAddress((XLWorksheet)rangeAddress.FirstAddress.Worksheet,
rangeAddress.FirstAddress.RowNumber + RangeAddress.FirstAddress.RowNumber - 1,
rangeAddress.FirstAddress.ColumnNumber + RangeAddress.FirstAddress.ColumnNumber - 1,
@@ -1077,7 +1107,6 @@
cell.ShiftFormulaColumns(asRange, numberOfColumns);
}
-
var cellsDataValidations = new Dictionary();
var cellsToInsert = new Dictionary();
var cellsToDelete = new List();
@@ -1092,10 +1121,10 @@
{
for (int co = lastColumn; co >= firstColumn; co--)
{
+ int newColumn = co + numberOfColumns;
for (int ro = lastRow; ro >= firstRow; ro--)
{
var oldKey = new XLAddress(Worksheet, ro, co, false, false);
- int newColumn = co + numberOfColumns;
var newKey = new XLAddress(Worksheet, ro, newColumn, false, false);
var oldCell = Worksheet.Internals.CellsCollection.GetCell(ro, co) ??
Worksheet.Cell(oldKey);
@@ -1106,6 +1135,11 @@
cellsToInsert.Add(newKey, newCell);
cellsToDelete.Add(oldKey);
}
+
+ if (this.IsEntireColumn())
+ {
+ Worksheet.Column(newColumn).Width = Worksheet.Column(co).Width;
+ }
}
}
}
@@ -1193,7 +1227,6 @@
: Worksheet.Style;
rangeToReturn.Row(ro).Style = styleToUse;
}
-
}
}
@@ -1284,15 +1317,17 @@
return retVal;
}
- struct DataValidationToCopy
+ private struct DataValidationToCopy
{
public XLAddress SourceAddress;
public XLDataValidation DataValidation;
}
+
public void InsertRowsAboveVoid(Boolean onlyUsedCells, Int32 numberOfRows, Boolean formatFromAbove = true)
{
InsertRowsAboveInternal(onlyUsedCells, numberOfRows, formatFromAbove, nullReturn: true);
}
+
public IXLRangeRows InsertRowsAbove(Boolean onlyUsedCells, Int32 numberOfRows, Boolean formatFromAbove = true)
{
return InsertRowsAboveInternal(onlyUsedCells, numberOfRows, formatFromAbove, nullReturn: false);
@@ -1323,10 +1358,11 @@
{
for (int ro = lastRow; ro >= firstRow; ro--)
{
+ int newRow = ro + numberOfRows;
+
for (int co = lastColumn; co >= firstColumn; co--)
{
var oldKey = new XLAddress(Worksheet, ro, co, false, false);
- int newRow = ro + numberOfRows;
var newKey = new XLAddress(Worksheet, newRow, co, false, false);
var oldCell = Worksheet.Internals.CellsCollection.GetCell(ro, co);
if (oldCell != null)
@@ -1338,6 +1374,10 @@
cellsToDelete.Add(oldKey);
}
}
+ if (this.IsEntireRow())
+ {
+ Worksheet.Row(newRow).Height = Worksheet.Row(ro).Height;
+ }
}
}
}
@@ -1363,7 +1403,6 @@
newCell.FormulaA1 = c.FormulaA1;
cellsToInsert.Add(newKey, newCell);
cellsToDelete.Add(c.Address);
-
}
}
@@ -1381,7 +1420,6 @@
cellsToDelete.ForEach(c => Worksheet.Internals.CellsCollection.Remove(c.RowNumber, c.ColumnNumber));
cellsToInsert.ForEach(c => Worksheet.Internals.CellsCollection.Add(c.Key.RowNumber, c.Key.ColumnNumber, c.Value));
-
Int32 firstRowReturn = RangeAddress.FirstAddress.RowNumber;
Int32 lastRowReturn = RangeAddress.FirstAddress.RowNumber + numberOfRows - 1;
Int32 firstColumnReturn = RangeAddress.FirstAddress.ColumnNumber;
@@ -1472,7 +1510,6 @@
RangeAddress.LastAddress.RowNumber,
RangeAddress.LastAddress.ColumnNumber);
-
foreach (
XLCell cell in
Worksheet.Workbook.Worksheets.Cast().SelectMany(
@@ -1501,7 +1538,6 @@
Worksheet.Internals.CellsCollection.MaxRowUsed,
RangeAddress.LastAddress.ColumnNumber);
-
int columnModifier = shiftDeleteCells == XLShiftDeletedCells.ShiftCellsLeft ? ColumnCount() : 0;
int rowModifier = shiftDeleteCells == XLShiftDeletedCells.ShiftCellsUp ? RowCount() : 0;
var cellsQuery = shiftDeleteCells == XLShiftDeletedCells.ShiftCellsLeft ? shiftLeftQuery : shiftUpQuery;
@@ -1523,7 +1559,6 @@
cellsToInsert.Add(newKey, newCell);
}
-
cellsToDelete.ForEach(c => Worksheet.Internals.CellsCollection.Remove(c.RowNumber, c.ColumnNumber));
cellsToInsert.ForEach(
c => Worksheet.Internals.CellsCollection.Add(c.Key.RowNumber, c.Key.ColumnNumber, c.Value));
@@ -1698,17 +1733,16 @@
// return chart;
//}
-
IXLPivotTable IXLRangeBase.CreatePivotTable(IXLCell targetCell)
{
return CreatePivotTable(targetCell);
}
+
IXLPivotTable IXLRangeBase.CreatePivotTable(IXLCell targetCell, String name)
{
return CreatePivotTable(targetCell, name);
}
-
public XLPivotTable CreatePivotTable(IXLCell targetCell)
{
return CreatePivotTable(targetCell, Guid.NewGuid().ToString());
@@ -1821,7 +1855,6 @@
return this;
}
-
#region Sort Rows
private void SortRangeRows()
@@ -1886,7 +1919,7 @@
SortingRangeRows(pivot + 1, end);
}
- #endregion
+ #endregion Sort Rows
#region Sort Columns
@@ -1951,9 +1984,9 @@
SortingRangeColumns(pivot + 1, end);
}
- #endregion
+ #endregion Sort Columns
- #endregion
+ #endregion Sort
public XLRangeColumn ColumnQuick(Int32 column)
{
@@ -2017,7 +2050,6 @@
}
}
-
internal IXLConditionalFormat AddConditionalFormat(IXLConditionalFormat source)
{
using (var asRange = AsRange())
diff --git a/ClosedXML/Excel/Ranges/XLRangeColumn.cs b/ClosedXML/Excel/Ranges/XLRangeColumn.cs
index 7449d3c..34710ea 100644
--- a/ClosedXML/Excel/Ranges/XLRangeColumn.cs
+++ b/ClosedXML/Excel/Ranges/XLRangeColumn.cs
@@ -1,9 +1,8 @@
+using System;
+using System.Linq;
+
namespace ClosedXML.Excel
{
- using System;
- using System.Linq;
-
-
internal class XLRangeColumn : XLRangeBase, IXLRangeColumn
{
#region Constructor
@@ -13,18 +12,24 @@
{
if (quickLoad) return;
- SubscribeToShiftedRows((range, rowsShifted) => this.WorksheetRangeShiftedRows(range, rowsShifted));
- SubscribeToShiftedColumns((range, columnsShifted) => this.WorksheetRangeShiftedColumns(range, columnsShifted));
+ SubscribeToShiftedRows((range, rowsShifted) => this.WorksheetRangeShiftedRows(range, rowsShifted));
+ SubscribeToShiftedColumns((range, columnsShifted) => this.WorksheetRangeShiftedColumns(range, columnsShifted));
SetStyle(rangeParameters.DefaultStyle);
}
- #endregion
+ public XLRangeColumn(XLRangeParameters rangeParameters, bool quickLoad, IXLTable table)
+ : this(rangeParameters, quickLoad)
+ {
+ this.Table = table;
+ }
+
+ #endregion Constructor
#region IXLRangeColumn Members
- IXLCell IXLRangeColumn.Cell(int row)
+ IXLCell IXLRangeColumn.Cell(int rowNumber)
{
- return Cell(row);
+ return Cell(rowNumber);
}
public new IXLCells Cells(string cellsInColumn)
@@ -43,6 +48,22 @@
public void Delete()
{
+ Delete(true);
+ }
+
+ internal void Delete(Boolean deleteTableField)
+ {
+ if (deleteTableField && IsTableColumn())
+ {
+ var table = Table as XLTable;
+ var firstCellValue = Cell(1).Value.ToString();
+ if (!table.FieldNames.ContainsKey(firstCellValue))
+ throw new ArgumentException(string.Format("Field {0} not found.", firstCellValue));
+
+ var field = table.Fields.Cast().Single(f => f.Name == firstCellValue);
+ field.Delete(false);
+ }
+
Delete(XLShiftDeletedCells.ShiftCellsLeft);
}
@@ -77,7 +98,6 @@
return this;
}
-
public new IXLRangeColumn CopyTo(IXLCell target)
{
base.CopyTo(target);
@@ -166,7 +186,7 @@
return Worksheet.Column(RangeAddress.FirstAddress.ColumnNumber);
}
- #endregion
+ #endregion IXLRangeColumn Members
public XLCell Cell(int row)
{
@@ -289,7 +309,7 @@
return ColumnShift(step * -1);
}
- #endregion
+ #endregion XLRangeColumn Left
#region XLRangeColumn Right
@@ -313,29 +333,40 @@
return ColumnShift(step);
}
- #endregion
-
+ #endregion XLRangeColumn Right
public IXLTable AsTable()
{
+ if (IsTableColumn())
+ throw new InvalidOperationException("This column is already part of a table.");
+
using (var asRange = AsRange())
- return asRange.AsTable();
+ return asRange.AsTable();
}
public IXLTable AsTable(string name)
{
+ if (IsTableColumn())
+ throw new InvalidOperationException("This column is already part of a table.");
+
using (var asRange = AsRange())
return asRange.AsTable(name);
}
public IXLTable CreateTable()
{
+ if (IsTableColumn())
+ throw new InvalidOperationException("This column is already part of a table.");
+
using (var asRange = AsRange())
return asRange.CreateTable();
}
public IXLTable CreateTable(string name)
{
+ if (IsTableColumn())
+ throw new InvalidOperationException("This column is already part of a table.");
+
using (var asRange = AsRange())
return asRange.CreateTable(name);
}
@@ -351,5 +382,11 @@
return Column(FirstCellUsed(includeFormats), LastCellUsed(includeFormats));
}
+ internal IXLTable Table { get; set; }
+
+ public Boolean IsTableColumn()
+ {
+ return Table != null;
+ }
}
}
diff --git a/ClosedXML/Excel/Rows/IXLRow.cs b/ClosedXML/Excel/Rows/IXLRow.cs
index 3bec732..70816fb 100644
--- a/ClosedXML/Excel/Rows/IXLRow.cs
+++ b/ClosedXML/Excel/Rows/IXLRow.cs
@@ -15,6 +15,11 @@
Double Height { get; set; }
///
+ /// Clears the height for the row and defaults it to the spreadsheet row height.
+ ///
+ void ClearHeight();
+
+ ///
/// Deletes this row and shifts the rows below this one accordingly.
///
void Delete();
diff --git a/ClosedXML/Excel/Rows/XLRow.cs b/ClosedXML/Excel/Rows/XLRow.cs
index 944cb17..a847178 100644
--- a/ClosedXML/Excel/Rows/XLRow.cs
+++ b/ClosedXML/Excel/Rows/XLRow.cs
@@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using System.Drawing;
-
+using System.Linq;
namespace ClosedXML.Excel
{
@@ -15,7 +14,7 @@
private Boolean _isHidden;
private Int32 _outlineLevel;
- #endregion
+ #endregion Private fields
#region Constructor
@@ -44,7 +43,7 @@
_height = row._height;
IsReference = row.IsReference;
if (IsReference)
- SubscribeToShiftedRows((range, rowShifted) => this.WorksheetRangeShiftedRows(range, rowShifted));
+ SubscribeToShiftedRows((range, rowShifted) => this.WorksheetRangeShiftedRows(range, rowShifted));
_collapsed = row._collapsed;
_isHidden = row._isHidden;
@@ -53,7 +52,7 @@
SetStyle(row.GetStyleId());
}
- #endregion
+ #endregion Constructor
public Boolean IsReference { get; private set; }
@@ -108,6 +107,7 @@
#region IXLRow Members
private Boolean _loading;
+
public Boolean Loading
{
get { return IsReference ? Worksheet.Internals.RowsCollection[RowNumber()].Loading : _loading; }
@@ -121,6 +121,7 @@
}
public Boolean HeightChanged { get; private set; }
+
public Double Height
{
get { return IsReference ? Worksheet.Internals.RowsCollection[RowNumber()].Height : _height; }
@@ -136,6 +137,12 @@
}
}
+ public void ClearHeight()
+ {
+ Height = Worksheet.RowHeight;
+ HeightChanged = false;
+ }
+
public void Delete()
{
int rowNumber = RowNumber();
@@ -291,7 +298,7 @@
foreach (IXLRichString rt in c.RichText)
{
String formattedString = rt.Text;
- var arr = formattedString.Split(new[] {Environment.NewLine}, StringSplitOptions.None);
+ var arr = formattedString.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
Int32 arrCount = arr.Count();
for (Int32 i = 0; i < arrCount; i++)
{
@@ -305,7 +312,7 @@
else
{
String formattedString = c.GetFormattedString();
- var arr = formattedString.Split(new[] {Environment.NewLine}, StringSplitOptions.None);
+ var arr = formattedString.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
Int32 arrCount = arr.Count();
for (Int32 i = 0; i < arrCount; i++)
{
@@ -338,7 +345,7 @@
}
}
else
- thisHeight = c.Style.Font.GetHeight( fontCache);
+ thisHeight = c.Style.Font.GetHeight(fontCache);
if (thisHeight >= maxHeight)
{
@@ -520,15 +527,15 @@
IXLRangeRow IXLRow.CopyTo(IXLCell target)
{
using (var asRange = AsRange())
- using (var copy = asRange.CopyTo(target))
- return copy.Row(1);
+ using (var copy = asRange.CopyTo(target))
+ return copy.Row(1);
}
IXLRangeRow IXLRow.CopyTo(IXLRangeBase target)
{
using (var asRange = AsRange())
- using (var copy = asRange.CopyTo(target))
- return copy.Row(1);
+ using (var copy = asRange.CopyTo(target))
+ return copy.Row(1);
}
public IXLRow CopyTo(IXLRow row)
@@ -581,7 +588,7 @@
return Row(FirstCellUsed(includeFormats), LastCellUsed(includeFormats));
}
- #endregion
+ #endregion IXLRow Members
public override XLRange AsRange()
{
@@ -676,7 +683,7 @@
return RowShift(step * -1);
}
- #endregion
+ #endregion XLRow Above
#region XLRow Below
@@ -700,14 +707,14 @@
return RowShift(step);
}
- #endregion
+ #endregion XLRow Below
- public new Boolean IsEmpty()
+ public override Boolean IsEmpty()
{
return IsEmpty(false);
}
- public new Boolean IsEmpty(Boolean includeFormats)
+ public override Boolean IsEmpty(Boolean includeFormats)
{
if (includeFormats && !Style.Equals(Worksheet.Style))
return false;
@@ -715,6 +722,14 @@
return base.IsEmpty(includeFormats);
}
+ public override Boolean IsEntireRow()
+ {
+ return true;
+ }
+ public override Boolean IsEntireColumn()
+ {
+ return false;
+ }
}
}
diff --git a/ClosedXML/Excel/Style/Colors/XLColor_Public.cs b/ClosedXML/Excel/Style/Colors/XLColor_Public.cs
index 6feefe3..4d0d9d3 100644
--- a/ClosedXML/Excel/Style/Colors/XLColor_Public.cs
+++ b/ClosedXML/Excel/Style/Colors/XLColor_Public.cs
@@ -55,7 +55,7 @@
get
{
if (_colorType == XLColorType.Theme)
- throw new Exception("Cannot convert theme color to Color.");
+ throw new InvalidOperationException("Cannot convert theme color to Color.");
if (_colorType == XLColorType.Indexed)
if (_indexed == TOOLTIPCOLORINDEX)
@@ -72,12 +72,12 @@
get
{
if (ColorType == XLColorType.Theme)
- throw new Exception("Cannot convert theme color to indexed color.");
+ throw new InvalidOperationException("Cannot convert theme color to indexed color.");
if (ColorType == XLColorType.Indexed)
return _indexed;
- throw new Exception("Cannot convert Color to indexed color.");
+ throw new InvalidOperationException("Cannot convert Color to indexed color.");
}
}
@@ -89,9 +89,9 @@
return _themeColor;
if (ColorType == XLColorType.Indexed)
- throw new Exception("Cannot convert indexed color to theme color.");
+ throw new InvalidOperationException("Cannot convert indexed color to theme color.");
- throw new Exception("Cannot convert Color to theme color.");
+ throw new InvalidOperationException("Cannot convert Color to theme color.");
}
}
@@ -103,7 +103,7 @@
return _themeTint;
if (ColorType == XLColorType.Indexed)
- throw new Exception("Cannot extract theme tint from an indexed color.");
+ throw new InvalidOperationException("Cannot extract theme tint from an indexed color.");
return _color.A/255.0;
}
diff --git a/ClosedXML/Excel/Tables/IXLTableField.cs b/ClosedXML/Excel/Tables/IXLTableField.cs
index 5bc695c..91ba4e8 100644
--- a/ClosedXML/Excel/Tables/IXLTableField.cs
+++ b/ClosedXML/Excel/Tables/IXLTableField.cs
@@ -18,11 +18,14 @@
public interface IXLTableField
{
+ IXLRangeColumn Column { get; }
Int32 Index { get; }
String Name { get; set; }
- String TotalsRowLabel { get; set; }
String TotalsRowFormulaA1 { get; set; }
String TotalsRowFormulaR1C1 { get; set; }
XLTotalsRowFunction TotalsRowFunction { get; set; }
+ String TotalsRowLabel { get; set; }
+
+ void Delete();
}
}
diff --git a/ClosedXML/Excel/Tables/XLTable.cs b/ClosedXML/Excel/Tables/XLTable.cs
index 61f8063..6048e33 100644
--- a/ClosedXML/Excel/Tables/XLTable.cs
+++ b/ClosedXML/Excel/Tables/XLTable.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -13,12 +13,12 @@
internal bool _showTotalsRow;
internal HashSet _uniqueNames;
- #endregion
+ #endregion Private fields
#region Constructor
public XLTable(XLRange range, Boolean addToTables, Boolean setAutofilter = true)
- : base(new XLRangeParameters(range.RangeAddress, range.Style ))
+ : base(new XLRangeParameters(range.RangeAddress, range.Style))
{
InitializeValues(setAutofilter);
@@ -45,10 +45,11 @@
AddToTables(range, addToTables);
}
- #endregion
+ #endregion Constructor
private IXLRangeAddress _lastRangeAddress;
private Dictionary _fieldNames = null;
+
public Dictionary FieldNames
{
get
@@ -73,13 +74,11 @@
if (_fieldNames.ContainsKey(name))
throw new ArgumentException("The header row contains more than one field name '" + name + "'.");
- _fieldNames.Add(name, new XLTableField(this, name) {Index = cellPos++ });
+ _fieldNames.Add(name, new XLTableField(this, name) { Index = cellPos++ });
}
}
else
{
- if (_fieldNames == null) _fieldNames = new Dictionary();
-
Int32 colCount = ColumnCount();
for (Int32 i = 1; i <= colCount; i++)
{
@@ -87,7 +86,7 @@
{
var name = "Column" + i;
- _fieldNames.Add(name, new XLTableField(this, name) {Index = i - 1 });
+ _fieldNames.Add(name, new XLTableField(this, name) { Index = i - 1 });
}
}
}
@@ -100,12 +99,21 @@
_fieldNames = new Dictionary();
Int32 cellPos = 0;
- foreach(var name in fieldNames)
+ foreach (var name in fieldNames)
{
_fieldNames.Add(name, new XLTableField(this, name) { Index = cellPos++ });
}
}
+ internal void RenameField(String oldName, String newName)
+ {
+ if (!_fieldNames.ContainsKey(oldName))
+ throw new ArgumentException("The field does not exist in this table", "oldName");
+
+ var field = _fieldNames[oldName];
+ _fieldNames.Remove(oldName);
+ _fieldNames.Add(newName, field);
+ }
internal String RelId { get; set; }
@@ -121,7 +129,7 @@
if (_showHeaderRow)
{
range = _showTotalsRow
- ? Range(2, 1,RowCount() - 1,ColumnCount())
+ ? Range(2, 1, RowCount() - 1, ColumnCount())
: Range(2, 1, RowCount(), ColumnCount());
}
else
@@ -136,6 +144,7 @@
}
private XLAutoFilter _autoFilter;
+
public XLAutoFilter AutoFilter
{
get
@@ -164,10 +173,13 @@
public Boolean ShowColumnStripes { get; set; }
private Boolean _showAutoFilter;
- public Boolean ShowAutoFilter {
+
+ public Boolean ShowAutoFilter
+ {
get { return _showHeaderRow && _showAutoFilter; }
set { _showAutoFilter = value; }
- }
+ }
+
public XLTableTheme Theme { get; set; }
public String Name
@@ -364,9 +376,7 @@
base.Dispose();
}
- #endregion
-
-
+ #endregion IXLTable Members
private void InitializeValues(Boolean setAutofilter)
{
@@ -403,7 +413,6 @@
Worksheet.Tables.Add(this);
}
-
private String GetUniqueName(String originalName)
{
String name = originalName;
@@ -424,6 +433,10 @@
public Int32 GetFieldIndex(String name)
{
+ // There is a discrepancy in the way headers with line breaks are stored.
+ // The entry in the table definition will contain \r\n
+ // but the shared string value of the actual cell will contain only \n
+ name = name.Replace("\r\n", "\n");
if (FieldNames.ContainsKey(name))
return FieldNames[name].Index;
@@ -431,6 +444,7 @@
}
internal Boolean _showHeaderRow;
+
public Boolean ShowHeaderRow
{
get { return _showHeaderRow; }
@@ -461,59 +475,59 @@
}
else
{
- using(var asRange = Worksheet.Range(
- RangeAddress.FirstAddress.RowNumber - 1 ,
+ using (var asRange = Worksheet.Range(
+ RangeAddress.FirstAddress.RowNumber - 1,
RangeAddress.FirstAddress.ColumnNumber,
RangeAddress.LastAddress.RowNumber,
RangeAddress.LastAddress.ColumnNumber
))
- using (var firstRow = asRange.FirstRow())
- {
- IXLRangeRow rangeRow;
- if (firstRow.IsEmpty(true))
- {
- rangeRow = firstRow;
- RangeAddress.FirstAddress = new XLAddress(Worksheet,
- RangeAddress.FirstAddress.RowNumber - 1,
- RangeAddress.FirstAddress.ColumnNumber,
- RangeAddress.FirstAddress.FixedRow,
- RangeAddress.FirstAddress.FixedColumn);
- }
- else
- {
- var fAddress = RangeAddress.FirstAddress;
- var lAddress = RangeAddress.LastAddress;
+ using (var firstRow = asRange.FirstRow())
+ {
+ IXLRangeRow rangeRow;
+ if (firstRow.IsEmpty(true))
+ {
+ rangeRow = firstRow;
+ RangeAddress.FirstAddress = new XLAddress(Worksheet,
+ RangeAddress.FirstAddress.RowNumber - 1,
+ RangeAddress.FirstAddress.ColumnNumber,
+ RangeAddress.FirstAddress.FixedRow,
+ RangeAddress.FirstAddress.FixedColumn);
+ }
+ else
+ {
+ var fAddress = RangeAddress.FirstAddress;
+ var lAddress = RangeAddress.LastAddress;
- rangeRow = firstRow.InsertRowsBelow(1, false).First();
+ rangeRow = firstRow.InsertRowsBelow(1, false).First();
+ RangeAddress.FirstAddress = new XLAddress(Worksheet, fAddress.RowNumber,
+ fAddress.ColumnNumber,
+ fAddress.FixedRow,
+ fAddress.FixedColumn);
- RangeAddress.FirstAddress = new XLAddress(Worksheet, fAddress.RowNumber,
- fAddress.ColumnNumber,
- fAddress.FixedRow,
- fAddress.FixedColumn);
+ RangeAddress.LastAddress = new XLAddress(Worksheet, lAddress.RowNumber + 1,
+ lAddress.ColumnNumber,
+ lAddress.FixedRow,
+ lAddress.FixedColumn);
+ }
- RangeAddress.LastAddress = new XLAddress(Worksheet, lAddress.RowNumber + 1,
- lAddress.ColumnNumber,
- lAddress.FixedRow,
- lAddress.FixedColumn);
- }
-
- Int32 co = 1;
- foreach (var name in FieldNames.Values.Select(f => f.Name))
- {
- rangeRow.Cell(co).SetValue(name);
- co++;
- }
-
- }
+ Int32 co = 1;
+ foreach (var name in FieldNames.Values.Select(f => f.Name))
+ {
+ rangeRow.Cell(co).SetValue(name);
+ co++;
+ }
+ }
}
_showHeaderRow = value;
}
}
+
public IXLTable SetShowHeaderRow()
{
return SetShowHeaderRow(true);
}
+
public IXLTable SetShowHeaderRow(Boolean value)
{
ShowHeaderRow = value;
@@ -528,5 +542,60 @@
RangeAddress.LastAddress.FixedColumn);
}
+ public override XLRangeColumn Column(int columnNumber)
+ {
+ var column = base.Column(columnNumber);
+ column.Table = this;
+ return column;
+ }
+
+ public override XLRangeColumn Column(string columnName)
+ {
+ var column = base.Column(columnName);
+ column.Table = this;
+ return column;
+ }
+
+ public override IXLRangeColumns Columns(int firstColumn, int lastColumn)
+ {
+ var columns = base.Columns(firstColumn, lastColumn);
+ columns.Cast().ForEach(column => column.Table = this);
+ return columns;
+ }
+
+ public override IXLRangeColumns Columns(Func predicate = null)
+ {
+ var columns = base.Columns(predicate);
+ columns.Cast().ForEach(column => column.Table = this);
+ return columns;
+ }
+
+ public override IXLRangeColumns Columns(string columns)
+ {
+ var cols = base.Columns(columns);
+ cols.Cast().ForEach(column => column.Table = this);
+ return cols;
+ }
+
+ public override IXLRangeColumns Columns(string firstColumn, string lastColumn)
+ {
+ var columns = base.Columns(firstColumn, lastColumn);
+ columns.Cast().ForEach(column => column.Table = this);
+ return columns;
+ }
+
+ public override XLRangeColumns ColumnsUsed(bool includeFormats, Func predicate = null)
+ {
+ var columns = base.ColumnsUsed(includeFormats, predicate);
+ columns.Cast().ForEach(column => column.Table = this);
+ return columns;
+ }
+
+ public override XLRangeColumns ColumnsUsed(Func predicate = null)
+ {
+ var columns = base.ColumnsUsed(predicate);
+ columns.Cast().ForEach(column => column.Table = this);
+ return columns;
+ }
}
}
diff --git a/ClosedXML/Excel/Tables/XLTableField.cs b/ClosedXML/Excel/Tables/XLTableField.cs
index 744700f..528d7d2 100644
--- a/ClosedXML/Excel/Tables/XLTableField.cs
+++ b/ClosedXML/Excel/Tables/XLTableField.cs
@@ -1,19 +1,30 @@
-using System;
+using System;
+using System.Diagnostics;
+using System.Linq;
namespace ClosedXML.Excel
{
- internal class XLTableField: IXLTableField
+ [DebuggerDisplay("{Name}")]
+ internal class XLTableField : IXLTableField
{
- private XLTable table;
+ internal XLTotalsRowFunction totalsRowFunction;
+ internal String totalsRowLabel;
+ private readonly XLTable table;
+
+ private String name;
+
public XLTableField(XLTable table, String name)
{
this.table = table;
this.name = name;
}
- public Int32 Index { get; internal set; }
+ public IXLRangeColumn Column
+ {
+ get { return table.Column(this.Index); }
+ }
- private String name;
+ public Int32 Index { get; internal set; }
public String Name
{
@@ -26,22 +37,11 @@
if (table.ShowHeaderRow)
table.HeadersRow().Cell(Index + 1).SetValue(value);
+ table.RenameField(name, value);
name = value;
}
}
- internal String totalsRowLabel;
- public String TotalsRowLabel
- {
- get { return totalsRowLabel; }
- set
- {
- totalsRowFunction = XLTotalsRowFunction.None;
- table.TotalsRow().Cell(Index + 1).SetValue(value);
- totalsRowLabel = value;
- }
- }
-
public String TotalsRowFormulaA1
{
get { return table.TotalsRow().Cell(Index + 1).FormulaA1; }
@@ -51,6 +51,7 @@
table.TotalsRow().Cell(Index + 1).FormulaA1 = value;
}
}
+
public String TotalsRowFormulaR1C1
{
get { return table.TotalsRow().Cell(Index + 1).FormulaR1C1; }
@@ -61,7 +62,6 @@
}
}
- internal XLTotalsRowFunction totalsRowFunction;
public XLTotalsRowFunction TotalsRowFunction
{
get { return totalsRowFunction; }
@@ -94,5 +94,31 @@
totalsRowFunction = value;
}
}
+
+ public String TotalsRowLabel
+ {
+ get { return totalsRowLabel; }
+ set
+ {
+ totalsRowFunction = XLTotalsRowFunction.None;
+ table.TotalsRow().Cell(Index + 1).SetValue(value);
+ totalsRowLabel = value;
+ }
+ }
+
+ public void Delete()
+ {
+ Delete(true);
+ }
+
+ internal void Delete(Boolean deleteUnderlyingRangeColumn)
+ {
+ var fields = table.Fields.Cast();
+ fields.Where(f => f.Index > this.Index).ForEach(f => f.Index--);
+ table.FieldNames.Remove(this.Name);
+
+ if (deleteUnderlyingRangeColumn)
+ (this.Column as XLRangeColumn).Delete(false);
+ }
}
}
diff --git a/ClosedXML/Excel/XLWorkbook.cs b/ClosedXML/Excel/XLWorkbook.cs
index 370836e..bdcc86c 100644
--- a/ClosedXML/Excel/XLWorkbook.cs
+++ b/ClosedXML/Excel/XLWorkbook.cs
@@ -4,13 +4,14 @@
using System;
using System.Collections.Generic;
using System.Data;
+using System.Globalization;
using System.IO;
using System.Linq;
namespace ClosedXML.Excel
{
-
public enum XLEventTracking { Enabled, Disabled }
+
public enum XLCalculateMode
{
Auto,
@@ -58,14 +59,11 @@
Italic = false,
Underline = XLFontUnderlineValues.None,
Strikethrough = false,
- VerticalAlignment =
- XLFontVerticalTextAlignmentValues.
- Baseline,
+ VerticalAlignment = XLFontVerticalTextAlignmentValues.Baseline,
FontSize = 11,
FontColor = XLColor.FromArgb(0, 0, 0),
FontName = "Calibri",
- FontFamilyNumbering =
- XLFontFamilyNumberingValues.Swiss
+ FontFamilyNumbering = XLFontFamilyNumberingValues.Swiss
},
Fill = new XLFill(null)
{
@@ -75,10 +73,8 @@
},
Border = new XLBorder(null, null)
{
- BottomBorder =
- XLBorderStyleValues.None,
- DiagonalBorder =
- XLBorderStyleValues.None,
+ BottomBorder = XLBorderStyleValues.None,
+ DiagonalBorder = XLBorderStyleValues.None,
DiagonalDown = false,
DiagonalUp = false,
LeftBorder = XLBorderStyleValues.None,
@@ -90,24 +86,17 @@
RightBorderColor = XLColor.Black,
TopBorderColor = XLColor.Black
},
- NumberFormat =
- new XLNumberFormat(null, null) {NumberFormatId = 0},
+ NumberFormat = new XLNumberFormat(null, null) { NumberFormatId = 0 },
Alignment = new XLAlignment(null)
{
Indent = 0,
- Horizontal =
- XLAlignmentHorizontalValues.
- General,
+ Horizontal = XLAlignmentHorizontalValues.General,
JustifyLastLine = false,
- ReadingOrder =
- XLAlignmentReadingOrderValues.
- ContextDependent,
+ ReadingOrder = XLAlignmentReadingOrderValues.ContextDependent,
RelativeIndent = 0,
ShrinkToFit = false,
TextRotation = 0,
- Vertical =
- XLAlignmentVerticalValues.
- Bottom,
+ Vertical = XLAlignmentVerticalValues.Bottom,
WrapText = false
},
Protection = new XLProtection(null)
@@ -166,7 +155,12 @@
///
public static XLCellSetValueBehavior CellSetValueBehavior { get; set; }
- #endregion
+ public static XLWorkbook OpenFromTemplate(String path)
+ {
+ return new XLWorkbook(path, true);
+ }
+
+ #endregion Static
internal readonly List UnsupportedSheets =
new List();
@@ -203,7 +197,7 @@
Stream
};
- #endregion
+ #endregion Nested Type: XLLoadSource
internal XLWorksheets WorksheetsInternal { get; private set; }
@@ -265,7 +259,6 @@
///
public XLCalculateMode CalculateMode { get; set; }
-
public Boolean CalculationOnSave { get; set; }
public Boolean ForceFullCalculation { get; set; }
public Boolean FullCalculationOnLoad { get; set; }
@@ -352,24 +345,34 @@
{
case XLThemeColor.Text1:
return Theme.Text1;
+
case XLThemeColor.Background1:
return Theme.Background1;
+
case XLThemeColor.Text2:
return Theme.Text2;
+
case XLThemeColor.Background2:
return Theme.Background2;
+
case XLThemeColor.Accent1:
return Theme.Accent1;
+
case XLThemeColor.Accent2:
return Theme.Accent2;
+
case XLThemeColor.Accent3:
return Theme.Accent3;
+
case XLThemeColor.Accent4:
return Theme.Accent4;
+
case XLThemeColor.Accent5:
return Theme.Accent5;
+
case XLThemeColor.Accent6:
return Theme.Accent6;
+
default:
throw new ArgumentException("Invalid theme color");
}
@@ -422,7 +425,6 @@
return null;
}
-
///
/// Saves the current workbook.
///
@@ -452,7 +454,7 @@
{
checkForWorksheetsPresent();
if (_loadSource == XLLoadSource.New)
- throw new Exception("This is a new file. Please use one of the 'SaveAs' methods.");
+ throw new InvalidOperationException("This is a new file. Please use one of the 'SaveAs' methods.");
if (_loadSource == XLLoadSource.Stream)
{
@@ -521,7 +523,8 @@
private static SpreadsheetDocumentType GetSpreadsheetDocumentType(string filePath)
{
var extension = Path.GetExtension(filePath);
- if (extension == null) throw new Exception("Empty extension is not supported.");
+
+ if (extension == null) throw new ArgumentException("Empty extension is not supported.");
extension = extension.Substring(1).ToLowerInvariant();
switch (extension)
@@ -529,19 +532,20 @@
case "xlsm":
case "xltm":
return SpreadsheetDocumentType.MacroEnabledWorkbook;
+
case "xlsx":
case "xltx":
return SpreadsheetDocumentType.Workbook;
+
default:
throw new ArgumentException(String.Format("Extension '{0}' is not supported. Supported extensions are '.xlsx', '.xslm', '.xltx' and '.xltm'.", extension));
-
}
}
private void checkForWorksheetsPresent()
{
if (Worksheets.Count() == 0)
- throw new Exception("Workbooks need at least one worksheet.");
+ throw new InvalidOperationException("Workbooks need at least one worksheet.");
}
///
@@ -625,7 +629,6 @@
output.Write(buffer, 0, len);
// dm 20130422, and flushing the output after write
output.Flush();
-
}
public IXLWorksheet Worksheet(String name)
@@ -679,24 +682,44 @@
return columns;
}
+ ///
+ /// Searches the cells' contents for a given piece of text
+ ///
+ /// The search text.
+ /// The compare options.
+ /// if set to true search formulae instead of cell values.
+ ///
+ public IEnumerable Search(String searchText, CompareOptions compareOptions = CompareOptions.Ordinal, Boolean searchFormulae = false)
+ {
+ foreach (var ws in WorksheetsInternal)
+ {
+ foreach (var cell in ws.Search(searchText, compareOptions, searchFormulae))
+ yield return cell;
+ }
+ }
+
#region Fields
private readonly XLLoadSource _loadSource = XLLoadSource.New;
private readonly String _originalFile;
private readonly Stream _originalStream;
-#endregion
+ #endregion Fields
#region Constructor
-
///
/// Creates a new Excel workbook.
///
public XLWorkbook()
:this(XLEventTracking.Enabled)
{
+ }
+ internal XLWorkbook(String file, Boolean asTemplate)
+ : this(XLEventTracking.Enabled)
+ {
+ LoadSheetsFromTemplate(file);
}
public XLWorkbook(XLEventTracking eventTracking)
@@ -735,7 +758,6 @@
public XLWorkbook(String file)
: this(file, XLEventTracking.Enabled)
{
-
}
public XLWorkbook(String file, XLEventTracking eventTracking)
@@ -747,15 +769,12 @@
Load(file);
}
-
-
///
/// Opens an existing workbook from a stream.
///
/// The stream to open.
public XLWorkbook(Stream stream):this(stream, XLEventTracking.Enabled)
{
-
}
public XLWorkbook(Stream stream, XLEventTracking eventTracking)
@@ -766,7 +785,7 @@
Load(stream);
}
-#endregion
+ #endregion Constructor
#region Nested type: UnsupportedSheet
@@ -777,7 +796,7 @@
public Int32 Position;
}
-#endregion
+ #endregion Nested type: UnsupportedSheet
public IXLCell Cell(String namedCell)
{
@@ -819,13 +838,13 @@
internal XLIdManager ShapeIdManager { get; private set; }
-
public void Dispose()
{
Worksheets.ForEach(w => w.Dispose());
}
public Boolean Use1904DateSystem { get; set; }
+
public XLWorkbook SetUse1904DateSystem()
{
return SetUse1904DateSystem(true);
@@ -846,10 +865,12 @@
{
return Worksheets.Add(sheetName, position);
}
+
public IXLWorksheet AddWorksheet(DataTable dataTable)
{
return Worksheets.Add(dataTable);
}
+
public void AddWorksheet(DataSet dataSet)
{
Worksheets.Add(dataSet);
@@ -866,10 +887,12 @@
}
private XLCalcEngine _calcEngine;
+
private XLCalcEngine CalcEngine
{
get { return _calcEngine ?? (_calcEngine = new XLCalcEngine(this)); }
}
+
public Object Evaluate(String expression)
{
return CalcEngine.Evaluate(expression);
@@ -882,6 +905,7 @@
{
get { return _calcEngineExpr ?? (_calcEngineExpr = new XLCalcEngine()); }
}
+
public static Object EvaluateExpr(String expression)
{
return CalcEngineExpr.Evaluate(expression);
@@ -890,9 +914,13 @@
public String Author { get; set; }
public Boolean LockStructure { get; set; }
+
public XLWorkbook SetLockStructure(Boolean value) { LockStructure = value; return this; }
+
public Boolean LockWindows { get; set; }
+
public XLWorkbook SetLockWindows(Boolean value) { LockWindows = value; return this; }
+
internal HexBinaryValue LockPassword { get; set; }
public Boolean IsPasswordProtected { get { return LockPassword != null; } }
@@ -915,7 +943,6 @@
LockPassword = null;
}
-
if (!IsPasswordProtected && hashPassword != null && (lockStructure || lockWindows))
{
//Protect workbook using password.
diff --git a/ClosedXML/Excel/XLWorkbook_ImageHandling.cs b/ClosedXML/Excel/XLWorkbook_ImageHandling.cs
index 37e85da..9dbaf3e 100644
--- a/ClosedXML/Excel/XLWorkbook_ImageHandling.cs
+++ b/ClosedXML/Excel/XLWorkbook_ImageHandling.cs
@@ -43,7 +43,13 @@
if (!IsAllowedAnchor(anchor))
return null;
- return anchor
+ var picture = anchor
+ .Descendants()
+ .FirstOrDefault();
+
+ if (picture == null) return null;
+
+ return picture
.Descendants()
.FirstOrDefault();
}
diff --git a/ClosedXML/Excel/XLWorkbook_Load.cs b/ClosedXML/Excel/XLWorkbook_Load.cs
index e29185f..be0d818 100644
--- a/ClosedXML/Excel/XLWorkbook_Load.cs
+++ b/ClosedXML/Excel/XLWorkbook_Load.cs
@@ -55,11 +55,17 @@
LoadSpreadsheetDocument(dSpreadsheet);
}
+ private void LoadSheetsFromTemplate(String fileName)
+ {
+ using (var dSpreadsheet = SpreadsheetDocument.CreateFromTemplate(fileName))
+ LoadSpreadsheetDocument(dSpreadsheet);
+ }
+
private void LoadSpreadsheetDocument(SpreadsheetDocument dSpreadsheet)
{
ShapeIdManager = new XLIdManager();
SetProperties(dSpreadsheet);
- //var sharedStrings = dSpreadsheet.WorkbookPart.SharedStringTablePart.SharedStringTable.Elements();
+
SharedStringItem[] sharedStrings = null;
if (dSpreadsheet.WorkbookPart.GetPartsOfType().Count() > 0)
{
@@ -265,11 +271,15 @@
#region LoadTables
- foreach (TableDefinitionPart tablePart in wsPart.TableDefinitionParts)
+ foreach (var tablePart in wsPart.TableDefinitionParts)
{
var dTable = tablePart.Table;
- string reference = dTable.Reference.Value;
- XLTable xlTable = ws.Range(reference).CreateTable(dTable.Name, false) as XLTable;
+ String reference = dTable.Reference.Value;
+ String tableName = dTable?.Name ?? dTable.DisplayName ?? string.Empty;
+ if (String.IsNullOrWhiteSpace(tableName))
+ throw new InvalidDataException("The table name is missing.");
+
+ XLTable xlTable = ws.Range(reference).CreateTable(tableName, false) as XLTable;
if (dTable.HeaderRowCount != null && dTable.HeaderRowCount == 0)
{
xlTable._showHeaderRow = false;
@@ -500,6 +510,14 @@
if (pivotTableDefinition.ShowError != null && pivotTableDefinition.ErrorCaption != null)
pt.ErrorValueReplacement = pivotTableDefinition.ErrorCaption.Value;
+ // Subtotal configuration
+ if (pivotTableDefinition.PivotFields.Cast().All(pf => pf.SubtotalTop != null && pf.SubtotalTop.HasValue && pf.SubtotalTop.Value))
+ pt.SetSubtotals(XLPivotSubtotals.AtTop);
+ else if (pivotTableDefinition.PivotFields.Cast().All(pf => pf.SubtotalTop != null && pf.SubtotalTop.HasValue && !pf.SubtotalTop.Value))
+ pt.SetSubtotals(XLPivotSubtotals.AtBottom);
+ else
+ pt.SetSubtotals(XLPivotSubtotals.DoNotShow);
+
// Row labels
if (pivotTableDefinition.RowFields != null)
{
@@ -640,7 +658,7 @@
{
var vsdp = GetPropertiesFromAnchor(anchor);
- var picture = ws.AddPicture(stream, vsdp.Name) as XLPicture;
+ var picture = (ws as XLWorksheet).AddPicture(stream, vsdp.Name, Convert.ToInt32(vsdp.Id.Value)) as XLPicture;
picture.RelId = imgId;
Xdr.ShapeProperties spPr = anchor.Descendants().First();
@@ -725,7 +743,7 @@
if (shape != null) break;
}
- if (xdoc == null) throw new Exception("Could not load comments file");
+ if (xdoc == null) throw new ArgumentException("Could not load comments file");
return xdoc;
}
@@ -1062,7 +1080,7 @@
else
{
if (!Worksheet(Int32.Parse(localSheetId) + 1).NamedRanges.Any(nr => nr.Name == name))
- Worksheet(Int32.Parse(localSheetId) + 1).NamedRanges.Add(name, text, comment).Visible = visible;
+ (Worksheet(Int32.Parse(localSheetId) + 1).NamedRanges as XLNamedRanges).Add(name, text, comment, true).Visible = visible;
}
}
}
@@ -1073,7 +1091,6 @@
private IEnumerable validateDefinedNames(IEnumerable definedNames)
{
- var fixedNames = new List();
var sb = new StringBuilder();
foreach (string testName in definedNames)
{
diff --git a/ClosedXML/Excel/XLWorkbook_Save.cs b/ClosedXML/Excel/XLWorkbook_Save.cs
index 3c9b741..57edc21 100644
--- a/ClosedXML/Excel/XLWorkbook_Save.cs
+++ b/ClosedXML/Excel/XLWorkbook_Save.cs
@@ -87,7 +87,7 @@
}
}
- private bool Validate(SpreadsheetDocument package)
+ private Boolean Validate(SpreadsheetDocument package)
{
var backupCulture = Thread.CurrentThread.CurrentCulture;
@@ -142,9 +142,10 @@
private void DeleteSheetAndDependencies(WorkbookPart wbPart, string sheetId)
{
//Get the SheetToDelete from workbook.xml
- Sheet worksheet = wbPart.Workbook.Descendants().Where(s => s.Id == sheetId).FirstOrDefault();
+ Sheet worksheet = wbPart.Workbook.Descendants().FirstOrDefault(s => s.Id == sheetId);
if (worksheet == null)
- { }
+ return;
+
string sheetName = worksheet.Name;
// Get the pivot Table Parts
@@ -154,8 +155,8 @@
{
PivotCacheDefinition pvtCacheDef = Item.PivotCacheDefinition;
//Check if this CacheSource is linked to SheetToDelete
- var pvtCahce = pvtCacheDef.Descendants().Where(s => s.WorksheetSource.Sheet == sheetName);
- if (pvtCahce.Count() > 0)
+ var pvtCache = pvtCacheDef.Descendants().Where(s => s.WorksheetSource.Sheet == sheetName);
+ if (pvtCache.Any())
{
pvtTableCacheDefinationPart.Add(Item, Item.ToString());
}
@@ -178,7 +179,7 @@
{
List defNamesToDelete = new List();
- foreach (DefinedName Item in definedNames)
+ foreach (var Item in definedNames.OfType())
{
// This condition checks to delete only those names which are part of Sheet in question
if (Item.Text.Contains(worksheet.Name + "!"))
@@ -201,19 +202,15 @@
var calChainEntries = calChainPart.CalculationChain.Descendants().Where(c => c.SheetId == sheetId);
List calcsToDelete = new List();
foreach (CalculationCell Item in calChainEntries)
- {
calcsToDelete.Add(Item);
- }
+
foreach (CalculationCell Item in calcsToDelete)
- {
Item.Remove();
- }
- if (calChainPart.CalculationChain.Count() == 0)
- {
+
+ if (!calChainPart.CalculationChain.Any())
wbPart.DeletePart(calChainPart);
- }
}
}
@@ -353,6 +350,9 @@
GenerateCustomFilePropertiesPartContent(customFilePropertiesPart);
}
SetPackageProperties(document);
+
+ // Clear list of deleted worksheets to prevent errors on multiple saves
+ worksheets.Deleted.Clear();
}
private void DeleteComments(WorksheetPart worksheetPart, XLWorksheet worksheet, SaveContext context)
@@ -2145,6 +2145,21 @@
IXLPivotField labelField = null;
var pf = new PivotField { ShowAll = false, Name = xlpf.CustomName };
+ switch (pt.Subtotals)
+ {
+ case XLPivotSubtotals.DoNotShow:
+ pf.DefaultSubtotal = false;
+ break;
+ case XLPivotSubtotals.AtBottom:
+ pf.DefaultSubtotal = true;
+ pf.SubtotalTop = false;
+ break;
+ case XLPivotSubtotals.AtTop:
+ pf.DefaultSubtotal = true;
+ pf.SubtotalTop = true;
+ break;
+ }
+
if (pt.RowLabels.Any(p => p.SourceName == xlpf.SourceName))
{
labelField = pt.RowLabels.Single(p => p.SourceName == xlpf.SourceName);
@@ -2168,7 +2183,7 @@
var fieldItems = new Items();
- if (xlpf.SharedStrings.Count > 0)
+ if (xlpf.SharedStrings.Any())
{
for (uint i = 0; i < xlpf.SharedStrings.Count; i++)
{
@@ -2179,7 +2194,7 @@
}
}
- if (xlpf.Subtotals.Count > 0)
+ if (xlpf.Subtotals.Any())
{
foreach (var subtotal in xlpf.Subtotals)
{
@@ -2244,13 +2259,17 @@
fieldItems.AppendChild(itemSubtotal);
}
}
- else
+ // If the field itself doesn't have subtotals, but the pivot table is set to show pivot tables, add the default item
+ else if (pt.Subtotals != XLPivotSubtotals.DoNotShow)
{
fieldItems.AppendChild(new Item { ItemType = ItemValues.Default });
}
- fieldItems.Count = Convert.ToUInt32(fieldItems.Count());
- pf.AppendChild(fieldItems);
+ if (fieldItems.Any())
+ {
+ fieldItems.Count = Convert.ToUInt32(fieldItems.Count());
+ pf.AppendChild(fieldItems);
+ }
pivotFields.AppendChild(pf);
}
diff --git a/ClosedXML/Excel/XLWorksheet.cs b/ClosedXML/Excel/XLWorksheet.cs
index e4669c8..c40ad1b 100644
--- a/ClosedXML/Excel/XLWorksheet.cs
+++ b/ClosedXML/Excel/XLWorksheet.cs
@@ -606,11 +606,18 @@
}
}
- foreach (IXLNamedRange r in NamedRanges)
+ foreach (var nr in NamedRanges)
{
var ranges = new XLRanges();
- r.Ranges.ForEach(ranges.Add);
- targetSheet.NamedRanges.Add(r.Name, ranges);
+ foreach (var r in nr.Ranges)
+ {
+ if (this == r.Worksheet)
+ // Named ranges on the source worksheet have to point to the new destination sheet
+ ranges.Add(targetSheet.Range(r.RangeAddress.FirstAddress.RowNumber, r.RangeAddress.FirstAddress.ColumnNumber, r.RangeAddress.LastAddress.RowNumber, r.RangeAddress.LastAddress.ColumnNumber));
+ else
+ ranges.Add(r);
+ }
+ targetSheet.NamedRanges.Add(nr.Name, ranges);
}
foreach (XLTable t in Tables.Cast())
@@ -1545,7 +1552,12 @@
return Pictures.Add(stream, name);
}
- public Drawings.IXLPicture AddPicture(Stream stream, XLPictureFormat format)
+ internal IXLPicture AddPicture(Stream stream, string name, int Id)
+ {
+ return (Pictures as XLPictures).Add(stream, name, Id);
+ }
+
+ public IXLPicture AddPicture(Stream stream, XLPictureFormat format)
{
return Pictures.Add(stream, format);
}
@@ -1574,5 +1586,14 @@
{
return Pictures.Add(imageFile, name);
}
+ public override Boolean IsEntireRow()
+ {
+ return true;
+ }
+
+ public override Boolean IsEntireColumn()
+ {
+ return true;
+ }
}
}
diff --git a/ClosedXML/Excel/XLWorksheets.cs b/ClosedXML/Excel/XLWorksheets.cs
index c7b15d4..9061e1d 100644
--- a/ClosedXML/Excel/XLWorksheets.cs
+++ b/ClosedXML/Excel/XLWorksheets.cs
@@ -77,18 +77,18 @@
if (wss.Any())
return wss.First().Value;
- throw new Exception("There isn't a worksheet named '" + sheetName + "'.");
+ throw new ArgumentException("There isn't a worksheet named '" + sheetName + "'.");
}
public IXLWorksheet Worksheet(Int32 position)
{
int wsCount = _worksheets.Values.Count(w => w.Position == position);
if (wsCount == 0)
- throw new Exception("There isn't a worksheet associated with that position.");
+ throw new ArgumentException("There isn't a worksheet associated with that position.");
if (wsCount > 1)
{
- throw new Exception(
+ throw new ArgumentException(
"Can't retrieve a worksheet because there are multiple worksheets associated with that position.");
}
@@ -130,10 +130,10 @@
{
int wsCount = _worksheets.Values.Count(w => w.Position == position);
if (wsCount == 0)
- throw new Exception("There isn't a worksheet associated with that index.");
+ throw new ArgumentException("There isn't a worksheet associated with that index.");
if (wsCount > 1)
- throw new Exception(
+ throw new ArgumentException(
"Can't delete the worksheet because there are multiple worksheets associated with that index.");
var ws = _worksheets.Values.Single(w => w.Position == position);
@@ -180,7 +180,8 @@
{
if (String.IsNullOrWhiteSpace(oldSheetName) || !_worksheets.ContainsKey(oldSheetName)) return;
- if (_worksheets.Any(ws1 => ws1.Key.Equals(newSheetName, StringComparison.OrdinalIgnoreCase)))
+ if (!oldSheetName.Equals(newSheetName, StringComparison.OrdinalIgnoreCase)
+ && _worksheets.Any(ws1 => ws1.Key.Equals(newSheetName, StringComparison.OrdinalIgnoreCase)))
throw new ArgumentException(String.Format("A worksheet with the same name ({0}) has already been added.", newSheetName), nameof(newSheetName));
var ws = _worksheets[oldSheetName];
diff --git a/ClosedXML_Examples/Misc/InsertingData.cs b/ClosedXML_Examples/Misc/InsertingData.cs
index d0ade19..d1035d5 100644
--- a/ClosedXML_Examples/Misc/InsertingData.cs
+++ b/ClosedXML_Examples/Misc/InsertingData.cs
@@ -13,59 +13,65 @@
// Public
public void Create(String filePath)
{
- var wb = new XLWorkbook();
- var ws = wb.Worksheets.Add("Inserting Data");
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.Worksheets.Add("Inserting Data");
- // From a list of strings
- var listOfStrings = new List();
- listOfStrings.Add("House");
- listOfStrings.Add("001");
- ws.Cell(1, 1).Value = "From Strings";
- ws.Cell(1, 1).AsRange().AddToNamed("Titles");
- ws.Cell(2, 1).InsertData(listOfStrings);
+ // From a list of strings
+ var listOfStrings = new List();
+ listOfStrings.Add("House");
+ listOfStrings.Add("001");
+ ws.Cell(1, 1).Value = "From Strings";
+ ws.Cell(1, 1).AsRange().AddToNamed("Titles");
+ ws.Cell(2, 1).InsertData(listOfStrings);
- // From a list of arrays
- var listOfArr = new List();
- listOfArr.Add(new Int32[] { 1, 2, 3 });
- listOfArr.Add(new Int32[] { 1 });
- listOfArr.Add(new Int32[] { 1, 2, 3, 4, 5, 6 });
- ws.Cell(1, 3).Value = "From Arrays";
- ws.Range(1, 3, 1, 8).Merge().AddToNamed("Titles");
- ws.Cell(2, 3).InsertData(listOfArr);
+ // From a list of arrays
+ var listOfArr = new List();
+ listOfArr.Add(new Int32[] { 1, 2, 3 });
+ listOfArr.Add(new Int32[] { 1 });
+ listOfArr.Add(new Int32[] { 1, 2, 3, 4, 5, 6 });
+ ws.Cell(1, 3).Value = "From Arrays";
+ ws.Range(1, 3, 1, 8).Merge().AddToNamed("Titles");
+ ws.Cell(2, 3).InsertData(listOfArr);
- // From a DataTable
- var dataTable = GetTable();
- ws.Cell(6, 1).Value = "From DataTable";
- ws.Range(6, 1, 6, 4).Merge().AddToNamed("Titles");
- ws.Cell(7, 1).InsertData(dataTable.AsEnumerable());
+ // From a DataTable
+ var dataTable = GetTable();
+ ws.Cell(6, 1).Value = "From DataTable";
+ ws.Range(6, 1, 6, 4).Merge().AddToNamed("Titles");
+ ws.Cell(7, 1).InsertData(dataTable.AsEnumerable());
- // From a query
- var list = new List();
- list.Add(new Person() { Name = "John", Age = 30, House = "On Elm St." });
- list.Add(new Person() { Name = "Mary", Age = 15, House = "On Main St." });
- list.Add(new Person() { Name = "Luis", Age = 21, House = "On 23rd St." });
- list.Add(new Person() { Name = "Henry", Age = 45, House = "On 5th Ave." });
+ // From a query
+ var list = new List();
+ list.Add(new Person() { Name = "John", Age = 30, House = "On Elm St." });
+ list.Add(new Person() { Name = "Mary", Age = 15, House = "On Main St." });
+ list.Add(new Person() { Name = "Luis", Age = 21, House = "On 23rd St." });
+ list.Add(new Person() { Name = "Henry", Age = 45, House = "On 5th Ave." });
- var people = from p in list
- where p.Age >= 21
- select new { p.Name, p.House, p.Age };
+ var people = from p in list
+ where p.Age >= 21
+ select new { p.Name, p.House, p.Age };
- ws.Cell(6, 6).Value = "From Query";
- ws.Range(6, 6, 6, 8).Merge().AddToNamed("Titles");
- ws.Cell(7, 6).InsertData(people.AsEnumerable());
+ ws.Cell(6, 6).Value = "From Query";
+ ws.Range(6, 6, 6, 8).Merge().AddToNamed("Titles");
+ ws.Cell(7, 6).InsertData(people.AsEnumerable());
- // Prepare the style for the titles
- var titlesStyle = wb.Style;
- titlesStyle.Font.Bold = true;
- titlesStyle.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
- titlesStyle.Fill.BackgroundColor = XLColor.Cyan;
-
- // Format all titles in one shot
- wb.NamedRanges.NamedRange("Titles").Ranges.Style = titlesStyle;
+ ws.Cell("F13").Value = "Transposed";
+ ws.Range(13, 6, 13, 8).Merge().AddToNamed("Titles");
+ ws.Cell("F14").InsertData(people.AsEnumerable(), true);
- ws.Columns().AdjustToContents();
+ // Prepare the style for the titles
+ var titlesStyle = wb.Style;
+ titlesStyle.Font.Bold = true;
+ titlesStyle.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
+ titlesStyle.Fill.BackgroundColor = XLColor.Cyan;
- wb.SaveAs(filePath);
+ // Format all titles in one shot
+ wb.NamedRanges.NamedRange("Titles").Ranges.Style = titlesStyle;
+
+ ws.Columns().AdjustToContents();
+
+ wb.SaveAs(filePath);
+ }
}
class Person
diff --git a/ClosedXML_Examples/PivotTables/PivotTables.cs b/ClosedXML_Examples/PivotTables/PivotTables.cs
index 9eb24ea..fa479da 100644
--- a/ClosedXML_Examples/PivotTables/PivotTables.cs
+++ b/ClosedXML_Examples/PivotTables/PivotTables.cs
@@ -60,6 +60,8 @@
IXLWorksheet ptSheet;
IXLPivotTable pt;
+ #region Pivots
+
for (int i = 1; i <= 3; i++)
{
// Add a new sheet for our pivot table
@@ -95,7 +97,10 @@
ptSheet.Columns().AdjustToContents();
}
- // Different kind of pivot
+ #endregion Pivots
+
+ #region Different kind of pivot
+
ptSheet = wb.Worksheets.Add("pvtNoColumnLabels");
pt = ptSheet.PivotTables.AddNew("pvtNoColumnLabels", ptSheet.Cell(1, 1), dataRange);
@@ -105,8 +110,10 @@
pt.Values.Add("NumberOfOrders").SetSummaryFormula(XLPivotSummary.Sum);
pt.Values.Add("Quality").SetSummaryFormula(XLPivotSummary.Sum);
+ #endregion Different kind of pivot
- // Pivot table with collapsed fields
+ #region Pivot table with collapsed fields
+
ptSheet = wb.Worksheets.Add("pvtCollapsedFields");
pt = ptSheet.PivotTables.AddNew("pvtCollapsedFields", ptSheet.Cell(1, 1), dataRange);
@@ -116,8 +123,10 @@
pt.Values.Add("NumberOfOrders").SetSummaryFormula(XLPivotSummary.Sum);
pt.Values.Add("Quality").SetSummaryFormula(XLPivotSummary.Sum);
+ #endregion Pivot table with collapsed fields
- // Pivot table with a field both as a value and as a row/column/filter label
+ #region Pivot table with a field both as a value and as a row/column/filter label
+
ptSheet = wb.Worksheets.Add("pvtFieldAsValueAndLabel");
pt = ptSheet.PivotTables.AddNew("pvtFieldAsValueAndLabel", ptSheet.Cell(1, 1), dataRange);
@@ -126,6 +135,37 @@
pt.Values.Add("Name").SetSummaryFormula(XLPivotSummary.Count);//.NumberFormat.Format = "#0.00";
+ #endregion Pivot table with a field both as a value and as a row/column/filter label
+
+ #region Pivot table with subtotals disabled
+
+ ptSheet = wb.Worksheets.Add("pvtHideSubTotals");
+
+ // Create the pivot table, using the data from the "PastrySalesData" table
+ pt = ptSheet.PivotTables.AddNew("pvtHidesubTotals", ptSheet.Cell(1, 1), dataRange);
+
+ // The rows in our pivot table will be the names of the pastries
+ pt.RowLabels.Add(XLConstants.PivotTableValuesSentinalLabel);
+
+ // The columns will be the months
+ pt.ColumnLabels.Add("Month");
+ pt.ColumnLabels.Add("Name");
+
+ // The values in our table will come from the "NumberOfOrders" field
+ // The default calculation setting is a total of each row/column
+ pt.Values.Add("NumberOfOrders", "NumberOfOrdersPercentageOfBearclaw")
+ .ShowAsPercentageFrom("Name").And("Bearclaw")
+ .NumberFormat.Format = "0%";
+
+ pt.Values.Add("Quality", "Sum of Quality")
+ .NumberFormat.SetFormat("#,##0.00");
+
+ pt.Subtotals = XLPivotSubtotals.DoNotShow;
+
+ ptSheet.Columns().AdjustToContents();
+
+ #endregion Pivot table with subtotals disabled
+
wb.SaveAs(filePath);
}
}
diff --git a/ClosedXML_Tests/ClosedXML_Tests.csproj b/ClosedXML_Tests/ClosedXML_Tests.csproj
index 487ea3a..8059cad 100644
--- a/ClosedXML_Tests/ClosedXML_Tests.csproj
+++ b/ClosedXML_Tests/ClosedXML_Tests.csproj
@@ -80,10 +80,12 @@
+
+
@@ -91,6 +93,7 @@
+
@@ -285,6 +288,9 @@
+
+
+
diff --git a/ClosedXML_Tests/Excel/CalcEngine/FunctionsTests.cs b/ClosedXML_Tests/Excel/CalcEngine/FunctionsTests.cs
index 3fca48e..3ad7f8e 100644
--- a/ClosedXML_Tests/Excel/CalcEngine/FunctionsTests.cs
+++ b/ClosedXML_Tests/Excel/CalcEngine/FunctionsTests.cs
@@ -620,7 +620,7 @@
Assert.AreEqual(0, cell.Value);
cell = wb.Worksheet(1).Cell(3, 1).SetFormulaA1("=SUM(D1,D2)");
Assert.AreEqual(0, cell.Value);
- Assert.That(() => wb.Worksheet(1).Cell(3, 1).SetFormulaA1("=AVERAGE(D1,D2)").Value, Throws.Exception);
+ Assert.That(() => wb.Worksheet(1).Cell(3, 1).SetFormulaA1("=AVERAGE(D1,D2)").Value, Throws.TypeOf());
}
[Test]
diff --git a/ClosedXML_Tests/Excel/CalcEngine/LookupTests.cs b/ClosedXML_Tests/Excel/CalcEngine/LookupTests.cs
index a112f3d..f416784 100644
--- a/ClosedXML_Tests/Excel/CalcEngine/LookupTests.cs
+++ b/ClosedXML_Tests/Excel/CalcEngine/LookupTests.cs
@@ -106,6 +106,12 @@
value = workbook.Evaluate("=VLOOKUP(3,Data!$B$2:$I$71,8,TRUE)");
Assert.AreEqual(179.64, value);
+ value = workbook.Evaluate("=VLOOKUP(3,Data!$B$2:$I$71,8)");
+ Assert.AreEqual(179.64, value);
+
+ value = workbook.Evaluate("=VLOOKUP(3,Data!$B$2:$I$71,8,)");
+ Assert.AreEqual(179.64, value);
+
value = workbook.Evaluate("=VLOOKUP(14.5,Data!$B$2:$I$71,8,TRUE)");
Assert.AreEqual(174.65, value);
@@ -116,11 +122,11 @@
[Test]
public void Vlookup_Exceptions()
{
- 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("""",Data!$B$2:$I$71,3,FALSE)"), Throws.TypeOf());
+ Assert.That(() => workbook.Evaluate(@"=VLOOKUP(50,Data!$B$2:$I$71,3,FALSE)"), Throws.TypeOf());
+ Assert.That(() => workbook.Evaluate(@"=VLOOKUP(20,Data!$B$2:$I$71,9,FALSE)"), Throws.TypeOf());
- Assert.That(() => workbook.Evaluate(@"=VLOOKUP(-1,Data!$B$2:$I$71,9,TRUE)"), Throws.Exception);
+ Assert.That(() => workbook.Evaluate(@"=VLOOKUP(-1,Data!$B$2:$I$71,9,TRUE)"), Throws.TypeOf());
}
}
}
diff --git a/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs b/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs
new file mode 100644
index 0000000..5012bb5
--- /dev/null
+++ b/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs
@@ -0,0 +1,123 @@
+using ClosedXML.Excel;
+using NUnit.Framework;
+using System;
+
+namespace ClosedXML_Tests.Excel.CalcEngine
+{
+ [TestFixture]
+ public class MathTrigTests
+ {
+ private readonly double tolerance = 1e-10;
+
+ [Test]
+ public void Floor()
+ {
+ Object actual;
+
+ actual = XLWorkbook.EvaluateExpr(@"FLOOR(1.2)");
+ Assert.AreEqual(1, actual);
+
+ actual = XLWorkbook.EvaluateExpr(@"FLOOR(1.7)");
+ Assert.AreEqual(1, actual);
+
+ actual = XLWorkbook.EvaluateExpr(@"FLOOR(-1.7)");
+ Assert.AreEqual(-2, actual);
+
+ actual = XLWorkbook.EvaluateExpr(@"FLOOR(1.2, 1)");
+ Assert.AreEqual(1, actual);
+
+ actual = XLWorkbook.EvaluateExpr(@"FLOOR(1.7, 1)");
+ Assert.AreEqual(1, actual);
+
+ actual = XLWorkbook.EvaluateExpr(@"FLOOR(-1.7, 1)");
+ Assert.AreEqual(-2, actual);
+
+ actual = XLWorkbook.EvaluateExpr(@"FLOOR(0.4, 2)");
+ Assert.AreEqual(0, actual);
+
+ actual = XLWorkbook.EvaluateExpr(@"FLOOR(2.7, 2)");
+ Assert.AreEqual(2, actual);
+
+ actual = XLWorkbook.EvaluateExpr(@"FLOOR(7.8, 2)");
+ Assert.AreEqual(6, actual);
+
+ actual = XLWorkbook.EvaluateExpr(@"FLOOR(-5.5, -2)");
+ Assert.AreEqual(-4, actual);
+ }
+
+ [Test]
+ // Functions have to support a period first before we can implement this
+ public void FloorMath()
+ {
+ double actual;
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"FLOOR.MATH(24.3, 5)");
+ Assert.AreEqual(20, actual, tolerance);
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"FLOOR.MATH(6.7)");
+ Assert.AreEqual(6, actual, tolerance);
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"FLOOR.MATH(-8.1, 2)");
+ Assert.AreEqual(-10, actual, tolerance);
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"FLOOR.MATH(5.5, 2.1, 0)");
+ Assert.AreEqual(4.2, actual, tolerance);
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"FLOOR.MATH(5.5, -2.1, 0)");
+ Assert.AreEqual(4.2, actual, tolerance);
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"FLOOR.MATH(5.5, 2.1, -1)");
+ Assert.AreEqual(4.2, actual, tolerance);
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"FLOOR.MATH(5.5, -2.1, -1)");
+ Assert.AreEqual(4.2, actual, tolerance);
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"FLOOR.MATH(-5.5, 2.1, 0)");
+ Assert.AreEqual(-6.3, actual, tolerance);
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"FLOOR.MATH(-5.5, -2.1, 0)");
+ Assert.AreEqual(-6.3, actual, tolerance);
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"FLOOR.MATH(-5.5, 2.1, -1)");
+ Assert.AreEqual(-4.2, actual, tolerance);
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"FLOOR.MATH(-5.5, -2.1, -1)");
+ Assert.AreEqual(-4.2, actual, tolerance);
+ }
+
+ [Test]
+ public void Mod()
+ {
+ double actual;
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"MOD(1.5, 1)");
+ Assert.AreEqual(0.5, actual, tolerance);
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"MOD(3, 2)");
+ Assert.AreEqual(1, actual, tolerance);
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"MOD(-3, 2)");
+ Assert.AreEqual(1, actual, tolerance);
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"MOD(3, -2)");
+ Assert.AreEqual(-1, actual, tolerance);
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"MOD(-3, -2)");
+ Assert.AreEqual(-1, actual, tolerance);
+
+ //////
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"MOD(-4.3, -0.5)");
+ Assert.AreEqual(-0.3, actual, tolerance);
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"MOD(6.9, -0.2)");
+ Assert.AreEqual(-0.1, actual, tolerance);
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"MOD(0.7, 0.6)");
+ Assert.AreEqual(0.1, actual, tolerance);
+
+ actual = (double)XLWorkbook.EvaluateExpr(@"MOD(6.2, 1.1)");
+ Assert.AreEqual(0.7, actual, tolerance);
+ }
+ }
+}
diff --git a/ClosedXML_Tests/Excel/CalcEngine/StatisticalTests.cs b/ClosedXML_Tests/Excel/CalcEngine/StatisticalTests.cs
index c59e34d..2550868 100644
--- a/ClosedXML_Tests/Excel/CalcEngine/StatisticalTests.cs
+++ b/ClosedXML_Tests/Excel/CalcEngine/StatisticalTests.cs
@@ -22,7 +22,7 @@
value = ws.Evaluate("AVERAGE(G3:G45)").CastTo();
Assert.AreEqual(49.3255814, value, tolerance);
- Assert.That(() => ws.Evaluate("AVERAGE(D3:D45)"), Throws.Exception);
+ Assert.That(() => ws.Evaluate("AVERAGE(D3:D45)"), Throws.TypeOf());
}
[Test]
@@ -146,7 +146,7 @@
{
var ws = workbook.Worksheets.First();
double value;
- Assert.That(() => ws.Evaluate(@"=STDEV(D3:D45)"), Throws.Exception);
+ Assert.That(() => ws.Evaluate(@"=STDEV(D3:D45)"), Throws.TypeOf());
value = ws.Evaluate(@"=STDEV(H3:H45)").CastTo();
Assert.AreEqual(47.34511769, value, tolerance);
@@ -163,7 +163,7 @@
{
var ws = workbook.Worksheets.First();
double value;
- Assert.That(() => ws.Evaluate(@"=STDEVP(D3:D45)"), Throws.Exception);
+ Assert.That(() => ws.Evaluate(@"=STDEVP(D3:D45)"), Throws.InvalidOperationException);
value = ws.Evaluate(@"=STDEVP(H3:H45)").CastTo();
Assert.AreEqual(46.79135458, value, tolerance);
@@ -180,7 +180,7 @@
{
var ws = workbook.Worksheets.First();
double value;
- Assert.That(() => ws.Evaluate(@"=VAR(D3:D45)"), Throws.Exception);
+ Assert.That(() => ws.Evaluate(@"=VAR(D3:D45)"), Throws.InvalidOperationException);
value = ws.Evaluate(@"=VAR(H3:H45)").CastTo();
Assert.AreEqual(2241.560169, value, tolerance);
@@ -197,7 +197,7 @@
{
var ws = workbook.Worksheets.First();
double value;
- Assert.That(() => ws.Evaluate(@"=VARP(D3:D45)"), Throws.Exception);
+ Assert.That(() => ws.Evaluate(@"=VARP(D3:D45)"), Throws.InvalidOperationException);
value = ws.Evaluate(@"=VARP(H3:H45)").CastTo();
Assert.AreEqual(2189.430863, value, tolerance);
diff --git a/ClosedXML_Tests/Excel/CalcEngine/TextTests.cs b/ClosedXML_Tests/Excel/CalcEngine/TextTests.cs
index 3a89de2..efb58d3 100644
--- a/ClosedXML_Tests/Excel/CalcEngine/TextTests.cs
+++ b/ClosedXML_Tests/Excel/CalcEngine/TextTests.cs
@@ -1,4 +1,5 @@
using ClosedXML.Excel;
+using ClosedXML.Excel.CalcEngine;
using NUnit.Framework;
using System;
using System.Globalization;
@@ -19,13 +20,13 @@
[Test]
public void Char_Empty_Input_String()
{
- Assert.That(() => XLWorkbook.EvaluateExpr(@"Char("""")"), Throws.Exception);
+ Assert.That(() => XLWorkbook.EvaluateExpr(@"Char("""")"), Throws.TypeOf());
}
[Test]
public void Char_Input_Too_Large()
{
- Assert.That(() => XLWorkbook.EvaluateExpr(@"Char(9797)"), Throws.Exception);
+ Assert.That(() => XLWorkbook.EvaluateExpr(@"Char(9797)"), Throws.TypeOf());
}
[Test]
@@ -56,7 +57,7 @@
public void Code_Empty_Input_String()
{
// Todo: more specific exception - ValueException?
- Assert.That(() => XLWorkbook.EvaluateExpr(@"Code("""")"), Throws.Exception);
+ Assert.That(() => XLWorkbook.EvaluateExpr(@"Code("""")"), Throws.TypeOf());
}
[Test]
@@ -82,7 +83,7 @@
[Test]
public void Dollar_Empty_Input_String()
{
- Assert.That(() => XLWorkbook.EvaluateExpr(@"Dollar("", 3)"), Throws.Exception);
+ Assert.That(() => XLWorkbook.EvaluateExpr(@"Dollar("", 3)"), Throws.TypeOf());
}
[Test]
@@ -121,26 +122,26 @@
[Test]
public void Find_Start_Position_Too_Large()
{
- Assert.That(() => XLWorkbook.EvaluateExpr(@"Find(""abc"", ""abcdef"", 10)"), Throws.Exception);
+ Assert.That(() => XLWorkbook.EvaluateExpr(@"Find(""abc"", ""abcdef"", 10)"), Throws.TypeOf());
}
[Test]
public void Find_String_In_Another_Empty_String()
{
- Assert.That(() => XLWorkbook.EvaluateExpr(@"Find(""abc"", """")"), Throws.Exception);
+ Assert.That(() => XLWorkbook.EvaluateExpr(@"Find(""abc"", """")"), Throws.TypeOf());
}
[Test]
public void Find_String_Not_Found()
{
- Assert.That(() => XLWorkbook.EvaluateExpr(@"Find(""123"", ""asdf"")"), Throws.Exception);
+ Assert.That(() => XLWorkbook.EvaluateExpr(@"Find(""123"", ""asdf"")"), Throws.TypeOf());
}
[Test]
public void Find_Case_Sensitive_String_Not_Found()
{
// Find is case-sensitive
- Assert.That(() => XLWorkbook.EvaluateExpr(@"Find(""excel"", ""Microsoft Excel 2010"")"), Throws.Exception);
+ Assert.That(() => XLWorkbook.EvaluateExpr(@"Find(""excel"", ""Microsoft Excel 2010"")"), Throws.TypeOf());
}
[Test]
@@ -159,7 +160,7 @@
[Test]
public void Fixed_Input_Is_String()
{
- Assert.That(() => XLWorkbook.EvaluateExpr(@"Fixed(""asdf"")"), Throws.Exception);
+ Assert.That(() => XLWorkbook.EvaluateExpr(@"Fixed(""asdf"")"), Throws.TypeOf());
}
[Test]
@@ -297,7 +298,7 @@
[Test]
public void Rept_Start_Is_Negative()
{
- Assert.That(() => XLWorkbook.EvaluateExpr(@"Rept(""Francois"", -1)"), Throws.Exception);
+ Assert.That(() => XLWorkbook.EvaluateExpr(@"Rept(""Francois"", -1)"), Throws.TypeOf());
}
[Test]
@@ -344,7 +345,7 @@
[Test]
public void Search_No_Parameters_With_Values()
{
- Assert.That(() => XLWorkbook.EvaluateExpr(@"Search("""", """")"), Throws.Exception);
+ Assert.That(() => XLWorkbook.EvaluateExpr(@"Search("""", """")"), Throws.TypeOf());
}
[Test]
@@ -357,31 +358,31 @@
[Test]
public void Search_Start_Position_Too_Large()
{
- Assert.That(() => XLWorkbook.EvaluateExpr(@"Search(""abc"", ""abcdef"", 10)"), Throws.Exception);
+ Assert.That(() => XLWorkbook.EvaluateExpr(@"Search(""abc"", ""abcdef"", 10)"), Throws.TypeOf());
}
[Test]
public void Search_Empty_Input_String()
{
- Assert.That(() => XLWorkbook.EvaluateExpr(@"Search(""abc"", """")"), Throws.Exception);
+ Assert.That(() => XLWorkbook.EvaluateExpr(@"Search(""abc"", """")"), Throws.TypeOf());
}
[Test]
public void Search_String_Not_Found()
{
- Assert.That(() => XLWorkbook.EvaluateExpr(@"Search(""123"", ""asdf"")"), Throws.Exception);
+ Assert.That(() => XLWorkbook.EvaluateExpr(@"Search(""123"", ""asdf"")"), Throws.TypeOf());
}
[Test]
public void Search_Wildcard_String_Not_Found()
{
- Assert.That(() => XLWorkbook.EvaluateExpr(@"Search(""soft?2010"", ""Microsoft Excel 2010"")"), Throws.Exception);
+ Assert.That(() => XLWorkbook.EvaluateExpr(@"Search(""soft?2010"", ""Microsoft Excel 2010"")"), Throws.TypeOf());
}
[Test]
public void Search_Start_Position_Too_Large2()
{
- Assert.That(() => XLWorkbook.EvaluateExpr(@"Search(""text"", ""This is some text"", 15)"), Throws.Exception);
+ Assert.That(() => XLWorkbook.EvaluateExpr(@"Search(""text"", ""This is some text"", 15)"), Throws.TypeOf());
}
// http://www.excel-easy.com/examples/find-vs-search.html
@@ -517,7 +518,7 @@
[Test]
public void Value_Input_String_Is_Not_A_Number()
{
- Assert.That(() => XLWorkbook.EvaluateExpr(@"Value(""asdf"")"), Throws.Exception);
+ Assert.That(() => XLWorkbook.EvaluateExpr(@"Value(""asdf"")"), Throws.TypeOf());
}
[Test]
diff --git a/ClosedXML_Tests/Excel/Cells/XLCellTests.cs b/ClosedXML_Tests/Excel/Cells/XLCellTests.cs
index 31e66f9..2fb6166 100644
--- a/ClosedXML_Tests/Excel/Cells/XLCellTests.cs
+++ b/ClosedXML_Tests/Excel/Cells/XLCellTests.cs
@@ -83,6 +83,22 @@
}
[Test]
+ public void InsertData2()
+ {
+ IXLWorksheet ws = new XLWorkbook().Worksheets.Add("Sheet1");
+ IXLRange range = ws.Cell(2, 2).InsertData(new[] { "a", "b", "c" }, false);
+ Assert.AreEqual("Sheet1!B2:B4", range.ToString());
+ }
+
+ [Test]
+ public void InsertData3()
+ {
+ IXLWorksheet ws = new XLWorkbook().Worksheets.Add("Sheet1");
+ IXLRange range = ws.Cell(2, 2).InsertData(new[] { "a", "b", "c" }, true);
+ Assert.AreEqual("Sheet1!B2:D2", range.ToString());
+ }
+
+ [Test]
public void IsEmpty1()
{
IXLWorksheet ws = new XLWorkbook().Worksheets.Add("Sheet1");
@@ -388,5 +404,27 @@
Assert.AreEqual("\u0018", wb.Worksheets.First().FirstCell().Value);
}
}
+
+ [Test]
+ public void CanClearCellValueBySettingNullValue()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet1");
+ var cell = ws.FirstCell();
+
+ cell.Value = "Test";
+ Assert.AreEqual("Test", cell.Value);
+ Assert.AreEqual(XLCellValues.Text, cell.DataType);
+
+ string s = null;
+ cell.SetValue(s);
+ Assert.AreEqual(string.Empty, cell.Value);
+
+ cell.Value = "Test";
+ cell.Value = null;
+ Assert.AreEqual(string.Empty, cell.Value);
+ }
+ }
}
}
diff --git a/ClosedXML_Tests/Excel/ImageHandling/PictureTests.cs b/ClosedXML_Tests/Excel/ImageHandling/PictureTests.cs
index b0ba0d6..a06902e 100644
--- a/ClosedXML_Tests/Excel/ImageHandling/PictureTests.cs
+++ b/ClosedXML_Tests/Excel/ImageHandling/PictureTests.cs
@@ -145,6 +145,35 @@
}
[Test]
+ public void TestDefaultIds()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet1");
+
+ using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ClosedXML_Tests.Resource.Images.ImageHandling.png"))
+ {
+ ws.AddPicture(stream, XLPictureFormat.Png);
+ stream.Position = 0;
+
+ ws.AddPicture(stream, XLPictureFormat.Png);
+ stream.Position = 0;
+
+ ws.AddPicture(stream, XLPictureFormat.Png).Name = "Picture 4";
+ stream.Position = 0;
+
+ ws.AddPicture(stream, XLPictureFormat.Png);
+ stream.Position = 0;
+ }
+
+ Assert.AreEqual(1, ws.Pictures.Skip(0).First().Id);
+ Assert.AreEqual(2, ws.Pictures.Skip(1).First().Id);
+ Assert.AreEqual(3, ws.Pictures.Skip(2).First().Id);
+ Assert.AreEqual(4, ws.Pictures.Skip(3).First().Id);
+ }
+ }
+
+ [Test]
public void XLMarkerTests()
{
IXLWorksheet ws = new XLWorkbook().Worksheets.Add("Sheet1");
diff --git a/ClosedXML_Tests/Excel/Loading/LoadingTests.cs b/ClosedXML_Tests/Excel/Loading/LoadingTests.cs
index 218ae90..5b1fc42 100644
--- a/ClosedXML_Tests/Excel/Loading/LoadingTests.cs
+++ b/ClosedXML_Tests/Excel/Loading/LoadingTests.cs
@@ -1,6 +1,8 @@
using ClosedXML.Excel;
using ClosedXML.Excel.Drawings;
+using ClosedXML_Tests.Utils;
using NUnit.Framework;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -27,7 +29,10 @@
@"Misc\InvalidPrintTitles.xlsx",
@"Misc\ExcelProducedWorkbookWithImages.xlsx",
@"Misc\EmptyCellValue.xlsx",
- @"Misc\AllShapes.xlsx"
+ @"Misc\AllShapes.xlsx",
+ @"Misc\TableHeadersWithLineBreaks.xlsx",
+ @"Misc\TableWithNameNull.xlsx",
+ @"Misc\DuplicateImageNames.xlsx"
};
foreach (var file in files)
@@ -178,5 +183,26 @@
wb.SaveAs(ms, true);
}
}
+
+ [Test]
+ public void CanLoadFromTemplate()
+ {
+ using (var tf1 = new TemporaryFile())
+ using (var tf2 = new TemporaryFile())
+ {
+ using (var stream = TestHelper.GetStreamFromResource(TestHelper.GetResourcePath(@"Misc\AllShapes.xlsx")))
+ using (var wb = new XLWorkbook(stream))
+ {
+ // Save as temporary file
+ wb.SaveAs(tf1.Path);
+ }
+
+ var workbook = XLWorkbook.OpenFromTemplate(tf1.Path);
+ Assert.True(workbook.Worksheets.Any());
+ Assert.Throws(() => workbook.Save());
+
+ workbook.SaveAs(tf2.Path);
+ }
+ }
}
}
diff --git a/ClosedXML_Tests/Excel/Misc/FormulaTests.cs b/ClosedXML_Tests/Excel/Misc/FormulaTests.cs
index 8d2d470..16ac2a1 100644
--- a/ClosedXML_Tests/Excel/Misc/FormulaTests.cs
+++ b/ClosedXML_Tests/Excel/Misc/FormulaTests.cs
@@ -156,5 +156,22 @@
Assert.AreEqual(6, actual);
}
}
+
+ [Test]
+ public void FormulaThatStartsWithEqualsAndPlus()
+ {
+ object actual;
+ actual = XLWorkbook.EvaluateExpr("=MID(\"This is a test\", 6, 2)");
+ Assert.AreEqual("is", actual);
+
+ actual = XLWorkbook.EvaluateExpr("=+MID(\"This is a test\", 6, 2)");
+ Assert.AreEqual("is", actual);
+
+ actual = XLWorkbook.EvaluateExpr("=+++++MID(\"This is a test\", 6, 2)");
+ Assert.AreEqual("is", actual);
+
+ actual = XLWorkbook.EvaluateExpr("+MID(\"This is a test\", 6, 2)");
+ Assert.AreEqual("is", actual);
+ }
}
}
diff --git a/ClosedXML_Tests/Excel/Misc/SearchTests.cs b/ClosedXML_Tests/Excel/Misc/SearchTests.cs
new file mode 100644
index 0000000..21e299d
--- /dev/null
+++ b/ClosedXML_Tests/Excel/Misc/SearchTests.cs
@@ -0,0 +1,78 @@
+using ClosedXML.Excel;
+using NUnit.Framework;
+using System.Globalization;
+using System.Linq;
+
+namespace ClosedXML_Tests.Excel.Misc
+{
+ [TestFixture]
+ public class SearchTests
+ {
+ [Test]
+ public void TestSearch()
+ {
+ using (var stream = TestHelper.GetStreamFromResource(TestHelper.GetResourcePath(@"Examples\Misc\CellValues.xlsx")))
+ using (var wb = new XLWorkbook(stream))
+ {
+ var ws = wb.Worksheets.First();
+
+ IXLCells foundCells;
+
+ foundCells = ws.Search("Initial Value");
+ Assert.AreEqual(1, foundCells.Count());
+ Assert.AreEqual("B2", foundCells.Single().Address.ToString());
+ Assert.AreEqual("Initial Value", foundCells.Single().GetString());
+
+ foundCells = ws.Search("Using");
+ Assert.AreEqual(2, foundCells.Count());
+ Assert.AreEqual("D2", foundCells.First().Address.ToString());
+ Assert.AreEqual("Using Get...()", foundCells.First().GetString());
+ Assert.AreEqual(2, foundCells.Count());
+ Assert.AreEqual("E2", foundCells.Last().Address.ToString());
+ Assert.AreEqual("Using GetValue()", foundCells.Last().GetString());
+
+ foundCells = ws.Search("1234");
+ Assert.AreEqual(4, foundCells.Count());
+ Assert.AreEqual("C5,D5,E5,F5", string.Join(",", foundCells.Select(c => c.Address.ToString()).ToArray()));
+
+ foundCells = ws.Search("Sep");
+ Assert.AreEqual(2, foundCells.Count());
+ Assert.AreEqual("B3,G3", string.Join(",", foundCells.Select(c => c.Address.ToString()).ToArray()));
+
+ foundCells = ws.Search("1234", CompareOptions.Ordinal, true);
+ Assert.AreEqual(5, foundCells.Count());
+ Assert.AreEqual("B5,C5,D5,E5,F5", string.Join(",", foundCells.Select(c => c.Address.ToString()).ToArray()));
+
+ foundCells = ws.Search("test case", CompareOptions.Ordinal);
+ Assert.AreEqual(0, foundCells.Count());
+
+ foundCells = ws.Search("test case", CompareOptions.OrdinalIgnoreCase);
+ Assert.AreEqual(6, foundCells.Count());
+ }
+ }
+
+ [Test]
+ public void TestSearch2()
+ {
+ using (var stream = TestHelper.GetStreamFromResource(TestHelper.GetResourcePath(@"Examples\Misc\Formulas.xlsx")))
+ using (var wb = new XLWorkbook(stream))
+ {
+ var ws = wb.Worksheets.First();
+
+ IXLCells foundCells;
+
+ foundCells = ws.Search("3", CompareOptions.Ordinal);
+ Assert.AreEqual(10, foundCells.Count());
+ Assert.AreEqual("C2", foundCells.First().Address.ToString());
+
+ foundCells = ws.Search("A2", CompareOptions.Ordinal, true);
+ Assert.AreEqual(6, foundCells.Count());
+ Assert.AreEqual("C2,D2,B6,C6,D6,A11", string.Join(",", foundCells.Select(c => c.Address.ToString()).ToArray()));
+
+ foundCells = ws.Search("RC", CompareOptions.Ordinal, true);
+ Assert.AreEqual(3, foundCells.Count());
+ Assert.AreEqual("E2,E3,E4", string.Join(",", foundCells.Select(c => c.Address.ToString()).ToArray()));
+ }
+ }
+ }
+}
diff --git a/ClosedXML_Tests/Excel/NamedRanges/NamedRangesTests.cs b/ClosedXML_Tests/Excel/NamedRanges/NamedRangesTests.cs
index 907bc96..afe5c7b 100644
--- a/ClosedXML_Tests/Excel/NamedRanges/NamedRangesTests.cs
+++ b/ClosedXML_Tests/Excel/NamedRanges/NamedRangesTests.cs
@@ -140,5 +140,38 @@
Assert.Throws(() => wb.NamedRanges.Add("MyRange", "A1:C1"));
}
}
+
+ [Test]
+ public void NamedRangesWhenCopyingWorksheets()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws1 = wb.AddWorksheet("Sheet1");
+ ws1.FirstCell().Value = Enumerable.Range(1, 10);
+ wb.NamedRanges.Add("wbNamedRange", ws1.Range("A1:A10"));
+ ws1.NamedRanges.Add("wsNamedRange", ws1.Range("A3"));
+
+ var ws2 = wb.AddWorksheet("Sheet2");
+ ws2.FirstCell().Value = Enumerable.Range(101, 10);
+ ws1.NamedRanges.Add("wsNamedRangeAcrossSheets", ws2.Range("A4"));
+
+ ws1.Cell("C1").FormulaA1 = "=wbNamedRange";
+ ws1.Cell("C2").FormulaA1 = "=wsNamedRange";
+ ws1.Cell("C3").FormulaA1 = "=wsNamedRangeAcrossSheets";
+
+ Assert.AreEqual(1, ws1.Cell("C1").Value);
+ Assert.AreEqual(3, ws1.Cell("C2").Value);
+ Assert.AreEqual(104, ws1.Cell("C3").Value);
+
+ var wsCopy = ws1.CopyTo("Copy");
+ Assert.AreEqual(1, wsCopy.Cell("C1").Value);
+ Assert.AreEqual(3, wsCopy.Cell("C2").Value);
+ Assert.AreEqual(104, wsCopy.Cell("C3").Value);
+
+ Assert.AreEqual("Sheet1!A1:A10", wb.NamedRange("wbNamedRange").Ranges.First().RangeAddress.ToStringRelative(true));
+ Assert.AreEqual("Copy!A3:A3", wsCopy.NamedRange("wsNamedRange").Ranges.First().RangeAddress.ToStringRelative(true));
+ Assert.AreEqual("Sheet2!A4:A4", wsCopy.NamedRange("wsNamedRangeAcrossSheets").Ranges.First().RangeAddress.ToStringRelative(true));
+ }
+ }
}
}
diff --git a/ClosedXML_Tests/Excel/Rows/RowTests.cs b/ClosedXML_Tests/Excel/Rows/RowTests.cs
index 17cddeb..bb74d4f 100644
--- a/ClosedXML_Tests/Excel/Rows/RowTests.cs
+++ b/ClosedXML_Tests/Excel/Rows/RowTests.cs
@@ -185,6 +185,36 @@
}
[Test]
+ public void InsertingRowsAbove4()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.Worksheets.Add("Sheet1");
+
+ ws.Row(2).Height = 15;
+ ws.Row(3).Height = 20;
+ ws.Row(4).Height = 25;
+ ws.Row(5).Height = 35;
+
+ ws.Row(2).FirstCell().SetValue("Row height: 15");
+ ws.Row(3).FirstCell().SetValue("Row height: 20");
+ ws.Row(4).FirstCell().SetValue("Row height: 25");
+ ws.Row(5).FirstCell().SetValue("Row height: 35");
+
+ ws.Range("3:3").InsertRowsAbove(1);
+
+ Assert.AreEqual(15, ws.Row(2).Height);
+ Assert.AreEqual(20, ws.Row(4).Height);
+ Assert.AreEqual(25, ws.Row(5).Height);
+ Assert.AreEqual(35, ws.Row(6).Height);
+
+ Assert.AreEqual(20, ws.Row(3).Height);
+ ws.Row(3).ClearHeight();
+ Assert.AreEqual(ws.RowHeight, ws.Row(3).Height);
+ }
+ }
+
+ [Test]
public void NoRowsUsed()
{
var wb = new XLWorkbook();
@@ -224,4 +254,4 @@
ws.Rows(1, 2).Ungroup(true);
}
}
-}
\ No newline at end of file
+}
diff --git a/ClosedXML_Tests/Excel/Saving/SavingTests.cs b/ClosedXML_Tests/Excel/Saving/SavingTests.cs
index ca2fd98..60a1d7a 100644
--- a/ClosedXML_Tests/Excel/Saving/SavingTests.cs
+++ b/ClosedXML_Tests/Excel/Saving/SavingTests.cs
@@ -34,6 +34,35 @@
}
[Test]
+ public void CanSaveFileMultipleTimesAfterDeletingWorksheet()
+ {
+ // https://github.com/ClosedXML/ClosedXML/issues/435
+
+
+ using (var ms = new MemoryStream())
+ {
+ using (XLWorkbook book1 = new XLWorkbook())
+ {
+ book1.AddWorksheet("sheet1");
+ book1.AddWorksheet("sheet2");
+
+ book1.SaveAs(ms);
+ }
+ ms.Position = 0;
+
+ using (XLWorkbook book2 = new XLWorkbook(ms))
+ {
+ var ws = book2.Worksheet(1);
+ Assert.AreEqual("sheet1", ws.Name);
+ ws.Delete();
+ book2.Save();
+ book2.Save();
+ }
+ }
+ }
+
+
+ [Test]
public void CanSaveAndValidateFileInAnotherCulture()
{
string[] cultures = new string[] { "it", "de-AT" };
diff --git a/ClosedXML_Tests/Excel/Styles/NumberFormatTests.cs b/ClosedXML_Tests/Excel/Styles/NumberFormatTests.cs
index 3c94664..326340b 100644
--- a/ClosedXML_Tests/Excel/Styles/NumberFormatTests.cs
+++ b/ClosedXML_Tests/Excel/Styles/NumberFormatTests.cs
@@ -14,7 +14,6 @@
using (var wb = new XLWorkbook())
{
var ws = wb.AddWorksheet("Sheet1");
- ws.Column(1).Style.NumberFormat.Format = "yy-MM-dd";
var table = new DataTable();
table.Columns.Add("Date", typeof(DateTime));
@@ -24,9 +23,13 @@
table.Rows.Add(new DateTime(2017, 1, 1).AddMonths(i));
}
+ ws.Column(1).Style.NumberFormat.Format = "yy-MM-dd";
ws.Cell("A1").InsertData(table.AsEnumerable());
-
Assert.AreEqual("yy-MM-dd", ws.Cell("A5").Style.DateFormat.Format);
+
+ ws.Row(1).Style.NumberFormat.Format = "yy-MM-dd";
+ ws.Cell("A1").InsertData(table.AsEnumerable(), true);
+ Assert.AreEqual("yy-MM-dd", ws.Cell("E1").Style.DateFormat.Format);
}
}
}
diff --git a/ClosedXML_Tests/Excel/Tables/TablesTests.cs b/ClosedXML_Tests/Excel/Tables/TablesTests.cs
index ddc7b84..1a35952 100644
--- a/ClosedXML_Tests/Excel/Tables/TablesTests.cs
+++ b/ClosedXML_Tests/Excel/Tables/TablesTests.cs
@@ -1,4 +1,4 @@
-using ClosedXML.Attributes;
+using ClosedXML.Attributes;
using ClosedXML.Excel;
using NUnit.Framework;
using System;
@@ -42,100 +42,112 @@
dt.Columns.Add("col1", typeof(string));
dt.Columns.Add("col2", typeof(double));
- var wb = new XLWorkbook();
- wb.AddWorksheet(dt);
+ using (var wb = new XLWorkbook())
+ {
+ wb.AddWorksheet(dt);
- using (var ms = new MemoryStream())
- wb.SaveAs(ms, true);
+ using (var ms = new MemoryStream())
+ wb.SaveAs(ms, true);
+ }
}
[Test]
public void CanSaveTableCreatedFromSingleRow()
{
- var wb = new XLWorkbook();
- IXLWorksheet ws = wb.AddWorksheet("Sheet1");
- ws.FirstCell().SetValue("Title");
- ws.Range("A1").CreateTable();
+ using (var wb = new XLWorkbook())
+ {
+ IXLWorksheet ws = wb.AddWorksheet("Sheet1");
+ ws.FirstCell().SetValue("Title");
+ ws.Range("A1").CreateTable();
- using (var ms = new MemoryStream())
- wb.SaveAs(ms, true);
+ using (var ms = new MemoryStream())
+ wb.SaveAs(ms, true);
+ }
}
[Test]
public void CreatingATableFromHeadersPushCellsBelow()
{
- var wb = new XLWorkbook();
- IXLWorksheet ws = wb.AddWorksheet("Sheet1");
- ws.FirstCell().SetValue("Title")
- .CellBelow().SetValue("X");
- ws.Range("A1").CreateTable();
+ using (var wb = new XLWorkbook())
+ {
+ IXLWorksheet ws = wb.AddWorksheet("Sheet1");
+ ws.FirstCell().SetValue("Title")
+ .CellBelow().SetValue("X");
+ ws.Range("A1").CreateTable();
- Assert.AreEqual(ws.Cell("A2").GetString(), String.Empty);
- Assert.AreEqual(ws.Cell("A3").GetString(), "X");
+ Assert.AreEqual(ws.Cell("A2").GetString(), String.Empty);
+ Assert.AreEqual(ws.Cell("A3").GetString(), "X");
+ }
}
[Test]
public void Inserting_Column_Sets_Header()
{
- var wb = new XLWorkbook();
- IXLWorksheet ws = wb.AddWorksheet("Sheet1");
- ws.FirstCell().SetValue("Categories")
- .CellBelow().SetValue("A")
- .CellBelow().SetValue("B")
- .CellBelow().SetValue("C");
+ using (var wb = new XLWorkbook())
+ {
+ IXLWorksheet ws = wb.AddWorksheet("Sheet1");
+ ws.FirstCell().SetValue("Categories")
+ .CellBelow().SetValue("A")
+ .CellBelow().SetValue("B")
+ .CellBelow().SetValue("C");
- IXLTable table = ws.RangeUsed().CreateTable();
- table.InsertColumnsAfter(1);
- Assert.AreEqual("Column2", table.HeadersRow().LastCell().GetString());
+ IXLTable table = ws.RangeUsed().CreateTable();
+ table.InsertColumnsAfter(1);
+ Assert.AreEqual("Column2", table.HeadersRow().LastCell().GetString());
+ }
}
[Test]
public void SavingLoadingTableWithNewLineInHeader()
{
- var wb = new XLWorkbook();
- IXLWorksheet ws = wb.AddWorksheet("Sheet1");
- string columnName = "Line1" + Environment.NewLine + "Line2";
- ws.FirstCell().SetValue(columnName)
- .CellBelow().SetValue("A");
- ws.RangeUsed().CreateTable();
- using (var ms = new MemoryStream())
+ using (var wb = new XLWorkbook())
{
- wb.SaveAs(ms, true);
- var wb2 = new XLWorkbook(ms);
- IXLWorksheet ws2 = wb2.Worksheet(1);
- IXLTable table2 = ws2.Table(0);
- string fieldName = table2.Field(0).Name;
- Assert.AreEqual("Line1\nLine2", fieldName);
+ IXLWorksheet ws = wb.AddWorksheet("Sheet1");
+ string columnName = "Line1" + Environment.NewLine + "Line2";
+ ws.FirstCell().SetValue(columnName)
+ .CellBelow().SetValue("A");
+ ws.RangeUsed().CreateTable();
+ using (var ms = new MemoryStream())
+ {
+ wb.SaveAs(ms, true);
+ var wb2 = new XLWorkbook(ms);
+ IXLWorksheet ws2 = wb2.Worksheet(1);
+ IXLTable table2 = ws2.Table(0);
+ string fieldName = table2.Field(0).Name;
+ Assert.AreEqual("Line1\nLine2", fieldName);
+ }
}
}
[Test]
public void SavingLoadingTableWithNewLineInHeader2()
{
- var wb = new XLWorkbook();
- IXLWorksheet ws = wb.Worksheets.Add("Test");
-
- var dt = new DataTable();
- string columnName = "Line1" + Environment.NewLine + "Line2";
- dt.Columns.Add(columnName);
-
- DataRow dr = dt.NewRow();
- dr[columnName] = "some text";
- dt.Rows.Add(dr);
- ws.Cell(1, 1).InsertTable(dt.AsEnumerable());
-
- IXLTable table1 = ws.Table(0);
- string fieldName1 = table1.Field(0).Name;
- Assert.AreEqual(columnName, fieldName1);
-
- using (var ms = new MemoryStream())
+ using (var wb = new XLWorkbook())
{
- wb.SaveAs(ms, true);
- var wb2 = new XLWorkbook(ms);
- IXLWorksheet ws2 = wb2.Worksheet(1);
- IXLTable table2 = ws2.Table(0);
- string fieldName2 = table2.Field(0).Name;
- Assert.AreEqual("Line1\nLine2", fieldName2);
+ IXLWorksheet ws = wb.Worksheets.Add("Test");
+
+ var dt = new DataTable();
+ string columnName = "Line1" + Environment.NewLine + "Line2";
+ dt.Columns.Add(columnName);
+
+ DataRow dr = dt.NewRow();
+ dr[columnName] = "some text";
+ dt.Rows.Add(dr);
+ ws.Cell(1, 1).InsertTable(dt.AsEnumerable());
+
+ IXLTable table1 = ws.Table(0);
+ string fieldName1 = table1.Field(0).Name;
+ Assert.AreEqual(columnName, fieldName1);
+
+ using (var ms = new MemoryStream())
+ {
+ wb.SaveAs(ms, true);
+ var wb2 = new XLWorkbook(ms);
+ IXLWorksheet ws2 = wb2.Worksheet(1);
+ IXLTable table2 = ws2.Table(0);
+ string fieldName2 = table2.Field(0).Name;
+ Assert.AreEqual("Line1\nLine2", fieldName2);
+ }
}
}
@@ -146,10 +158,12 @@
dt.Columns.Add("col1", typeof(string));
dt.Columns.Add("col2", typeof(double));
- var wb = new XLWorkbook();
- IXLWorksheet ws = wb.AddWorksheet("Sheet1");
- ws.FirstCell().InsertTable(dt);
- Assert.AreEqual(2, ws.Tables.First().ColumnCount());
+ using (var wb = new XLWorkbook())
+ {
+ IXLWorksheet ws = wb.AddWorksheet("Sheet1");
+ ws.FirstCell().InsertTable(dt);
+ Assert.AreEqual(2, ws.Tables.First().ColumnCount());
+ }
}
[Test]
@@ -157,10 +171,12 @@
{
var l = new List();
- var wb = new XLWorkbook();
- IXLWorksheet ws = wb.AddWorksheet("Sheet1");
- ws.FirstCell().InsertTable(l);
- Assert.AreEqual(1, ws.Tables.First().ColumnCount());
+ using (var wb = new XLWorkbook())
+ {
+ IXLWorksheet ws = wb.AddWorksheet("Sheet1");
+ ws.FirstCell().InsertTable(l);
+ Assert.AreEqual(1, ws.Tables.First().ColumnCount());
+ }
}
[Test]
@@ -168,10 +184,12 @@
{
var l = new List();
- var wb = new XLWorkbook();
- IXLWorksheet ws = wb.AddWorksheet("Sheet1");
- ws.FirstCell().InsertTable(l);
- Assert.AreEqual(2, ws.Tables.First().ColumnCount());
+ using (var wb = new XLWorkbook())
+ {
+ IXLWorksheet ws = wb.AddWorksheet("Sheet1");
+ ws.FirstCell().InsertTable(l);
+ Assert.AreEqual(2, ws.Tables.First().ColumnCount());
+ }
}
[Test]
@@ -183,184 +201,255 @@
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);
+ using (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();
- IXLWorksheet ws = wb.AddWorksheet("Sheet1");
- ws.FirstCell().SetValue("Value");
+ using (var wb = new XLWorkbook())
+ {
+ IXLWorksheet ws = wb.AddWorksheet("Sheet1");
+ ws.FirstCell().SetValue("Value");
- IXLTable table = ws.Range("A1:A2").CreateTable();
- table.SetShowTotalsRow()
- .Field(0).TotalsRowFunction = XLTotalsRowFunction.Sum;
+ IXLTable table = ws.Range("A1:A2").CreateTable();
+ table.SetShowTotalsRow()
+ .Field(0).TotalsRowFunction = XLTotalsRowFunction.Sum;
- IXLTableRow row = table.DataRange.FirstRow();
- row.Field("Value").Value = 3;
- row = table.DataRange.InsertRowsAbove(1).First();
- row.Field("Value").Value = 2;
- row = table.DataRange.InsertRowsAbove(1).First();
- row.Field("Value").Value = 1;
+ IXLTableRow row = table.DataRange.FirstRow();
+ row.Field("Value").Value = 3;
+ row = table.DataRange.InsertRowsAbove(1).First();
+ row.Field("Value").Value = 2;
+ row = table.DataRange.InsertRowsAbove(1).First();
+ row.Field("Value").Value = 1;
- Assert.AreEqual(1, ws.Cell(2, 1).GetDouble());
- Assert.AreEqual(2, ws.Cell(3, 1).GetDouble());
- Assert.AreEqual(3, ws.Cell(4, 1).GetDouble());
+ Assert.AreEqual(1, ws.Cell(2, 1).GetDouble());
+ Assert.AreEqual(2, ws.Cell(3, 1).GetDouble());
+ Assert.AreEqual(3, ws.Cell(4, 1).GetDouble());
+ }
}
[Test]
public void TableInsertAboveFromRows()
{
- var wb = new XLWorkbook();
- IXLWorksheet ws = wb.AddWorksheet("Sheet1");
- ws.FirstCell().SetValue("Value");
+ using (var wb = new XLWorkbook())
+ {
+ IXLWorksheet ws = wb.AddWorksheet("Sheet1");
+ ws.FirstCell().SetValue("Value");
- IXLTable table = ws.Range("A1:A2").CreateTable();
- table.SetShowTotalsRow()
- .Field(0).TotalsRowFunction = XLTotalsRowFunction.Sum;
+ IXLTable table = ws.Range("A1:A2").CreateTable();
+ table.SetShowTotalsRow()
+ .Field(0).TotalsRowFunction = XLTotalsRowFunction.Sum;
- 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;
+ 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;
- Assert.AreEqual(1, ws.Cell(2, 1).GetDouble());
- Assert.AreEqual(2, ws.Cell(3, 1).GetDouble());
- Assert.AreEqual(3, ws.Cell(4, 1).GetDouble());
+ Assert.AreEqual(1, ws.Cell(2, 1).GetDouble());
+ Assert.AreEqual(2, ws.Cell(3, 1).GetDouble());
+ Assert.AreEqual(3, ws.Cell(4, 1).GetDouble());
+ }
}
[Test]
public void TableInsertBelowFromData()
{
- var wb = new XLWorkbook();
- IXLWorksheet ws = wb.AddWorksheet("Sheet1");
- ws.FirstCell().SetValue("Value");
+ using (var wb = new XLWorkbook())
+ {
+ IXLWorksheet ws = wb.AddWorksheet("Sheet1");
+ ws.FirstCell().SetValue("Value");
- IXLTable table = ws.Range("A1:A2").CreateTable();
- table.SetShowTotalsRow()
- .Field(0).TotalsRowFunction = XLTotalsRowFunction.Sum;
+ IXLTable table = ws.Range("A1:A2").CreateTable();
+ table.SetShowTotalsRow()
+ .Field(0).TotalsRowFunction = XLTotalsRowFunction.Sum;
- IXLTableRow row = table.DataRange.FirstRow();
- row.Field("Value").Value = 1;
- row = table.DataRange.InsertRowsBelow(1).First();
- row.Field("Value").Value = 2;
- row = table.DataRange.InsertRowsBelow(1).First();
- row.Field("Value").Value = 3;
+ IXLTableRow row = table.DataRange.FirstRow();
+ row.Field("Value").Value = 1;
+ row = table.DataRange.InsertRowsBelow(1).First();
+ row.Field("Value").Value = 2;
+ row = table.DataRange.InsertRowsBelow(1).First();
+ row.Field("Value").Value = 3;
- Assert.AreEqual(1, ws.Cell(2, 1).GetDouble());
- Assert.AreEqual(2, ws.Cell(3, 1).GetDouble());
- Assert.AreEqual(3, ws.Cell(4, 1).GetDouble());
+ Assert.AreEqual(1, ws.Cell(2, 1).GetDouble());
+ Assert.AreEqual(2, ws.Cell(3, 1).GetDouble());
+ Assert.AreEqual(3, ws.Cell(4, 1).GetDouble());
+ }
}
[Test]
public void TableInsertBelowFromRows()
{
- var wb = new XLWorkbook();
- IXLWorksheet ws = wb.AddWorksheet("Sheet1");
- ws.FirstCell().SetValue("Value");
+ using (var wb = new XLWorkbook())
+ {
+ IXLWorksheet ws = wb.AddWorksheet("Sheet1");
+ ws.FirstCell().SetValue("Value");
- IXLTable table = ws.Range("A1:A2").CreateTable();
- table.SetShowTotalsRow()
- .Field(0).TotalsRowFunction = XLTotalsRowFunction.Sum;
+ IXLTable table = ws.Range("A1:A2").CreateTable();
+ table.SetShowTotalsRow()
+ .Field(0).TotalsRowFunction = XLTotalsRowFunction.Sum;
- IXLTableRow row = table.DataRange.FirstRow();
- row.Field("Value").Value = 1;
- row = row.InsertRowsBelow(1).First();
- row.Field("Value").Value = 2;
- row = row.InsertRowsBelow(1).First();
- row.Field("Value").Value = 3;
+ IXLTableRow row = table.DataRange.FirstRow();
+ row.Field("Value").Value = 1;
+ row = row.InsertRowsBelow(1).First();
+ row.Field("Value").Value = 2;
+ row = row.InsertRowsBelow(1).First();
+ row.Field("Value").Value = 3;
- Assert.AreEqual(1, ws.Cell(2, 1).GetDouble());
- Assert.AreEqual(2, ws.Cell(3, 1).GetDouble());
- Assert.AreEqual(3, ws.Cell(4, 1).GetDouble());
+ Assert.AreEqual(1, ws.Cell(2, 1).GetDouble());
+ Assert.AreEqual(2, ws.Cell(3, 1).GetDouble());
+ Assert.AreEqual(3, ws.Cell(4, 1).GetDouble());
+ }
}
[Test]
public void TableShowHeader()
{
- var wb = new XLWorkbook();
- IXLWorksheet ws = wb.AddWorksheet("Sheet1");
- ws.FirstCell().SetValue("Categories")
- .CellBelow().SetValue("A")
- .CellBelow().SetValue("B")
- .CellBelow().SetValue("C");
+ using (var wb = new XLWorkbook())
+ {
+ IXLWorksheet ws = wb.AddWorksheet("Sheet1");
+ ws.FirstCell().SetValue("Categories")
+ .CellBelow().SetValue("A")
+ .CellBelow().SetValue("B")
+ .CellBelow().SetValue("C");
- IXLTable table = ws.RangeUsed().CreateTable();
+ IXLTable table = ws.RangeUsed().CreateTable();
- Assert.AreEqual("Categories", table.Fields.First().Name);
+ Assert.AreEqual("Categories", table.Fields.First().Name);
- table.SetShowHeaderRow(false);
+ table.SetShowHeaderRow(false);
- Assert.AreEqual("Categories", table.Fields.First().Name);
+ Assert.AreEqual("Categories", table.Fields.First().Name);
- Assert.IsTrue(ws.Cell(1, 1).IsEmpty(true));
- Assert.AreEqual(null, table.HeadersRow());
- Assert.AreEqual("A", table.DataRange.FirstRow().Field("Categories").GetString());
- Assert.AreEqual("C", table.DataRange.LastRow().Field("Categories").GetString());
- Assert.AreEqual("A", table.DataRange.FirstCell().GetString());
- Assert.AreEqual("C", table.DataRange.LastCell().GetString());
+ Assert.IsTrue(ws.Cell(1, 1).IsEmpty(true));
+ Assert.AreEqual(null, table.HeadersRow());
+ Assert.AreEqual("A", table.DataRange.FirstRow().Field("Categories").GetString());
+ Assert.AreEqual("C", table.DataRange.LastRow().Field("Categories").GetString());
+ Assert.AreEqual("A", table.DataRange.FirstCell().GetString());
+ Assert.AreEqual("C", table.DataRange.LastCell().GetString());
- table.SetShowHeaderRow();
- IXLRangeRow headerRow = table.HeadersRow();
- Assert.AreNotEqual(null, headerRow);
- Assert.AreEqual("Categories", headerRow.Cell(1).GetString());
+ table.SetShowHeaderRow();
+ IXLRangeRow headerRow = table.HeadersRow();
+ Assert.AreNotEqual(null, headerRow);
+ Assert.AreEqual("Categories", headerRow.Cell(1).GetString());
- table.SetShowHeaderRow(false);
+ table.SetShowHeaderRow(false);
- ws.FirstCell().SetValue("x");
+ ws.FirstCell().SetValue("x");
- table.SetShowHeaderRow();
+ table.SetShowHeaderRow();
- Assert.AreEqual("x", ws.FirstCell().GetString());
- Assert.AreEqual("Categories", ws.Cell("A2").GetString());
- Assert.AreNotEqual(null, headerRow);
- Assert.AreEqual("A", table.DataRange.FirstRow().Field("Categories").GetString());
- Assert.AreEqual("C", table.DataRange.LastRow().Field("Categories").GetString());
- Assert.AreEqual("A", table.DataRange.FirstCell().GetString());
- Assert.AreEqual("C", table.DataRange.LastCell().GetString());
+ Assert.AreEqual("x", ws.FirstCell().GetString());
+ Assert.AreEqual("Categories", ws.Cell("A2").GetString());
+ Assert.AreNotEqual(null, headerRow);
+ Assert.AreEqual("A", table.DataRange.FirstRow().Field("Categories").GetString());
+ Assert.AreEqual("C", table.DataRange.LastRow().Field("Categories").GetString());
+ Assert.AreEqual("A", table.DataRange.FirstCell().GetString());
+ Assert.AreEqual("C", table.DataRange.LastCell().GetString());
+ }
}
[Test]
public void ChangeFieldName()
{
- XLWorkbook wb = new XLWorkbook();
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet");
+ ws.Cell("A1").SetValue("FName")
+ .CellBelow().SetValue("John");
- var ws = wb.AddWorksheet("Sheet");
- ws.Cell("A1").SetValue("FName")
- .CellBelow().SetValue("John");
+ ws.Cell("B1").SetValue("LName")
+ .CellBelow().SetValue("Doe");
- ws.Cell("B1").SetValue("LName")
- .CellBelow().SetValue("Doe");
+ var tbl = ws.RangeUsed().CreateTable();
+ var nameBefore = tbl.Field(tbl.Fields.Last().Index).Name;
+ tbl.Field(tbl.Fields.Last().Index).Name = "LastName";
+ var nameAfter = tbl.Field(tbl.Fields.Last().Index).Name;
- var tbl = ws.RangeUsed().CreateTable();
- var nameBefore = tbl.Field(tbl.Fields.Last().Index).Name;
- tbl.Field(tbl.Fields.Last().Index).Name = "LastName";
- var nameAfter = tbl.Field(tbl.Fields.Last().Index).Name;
+ var cellValue = ws.Cell("B1").GetString();
- var cellValue = ws.Cell("B1").GetString();
+ Assert.AreEqual("LName", nameBefore);
+ Assert.AreEqual("LastName", nameAfter);
+ Assert.AreEqual("LastName", cellValue);
- 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.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);
- tbl.SetShowHeaderRow(true);
- nameAfter = tbl.Cell("B1").Value.ToString();
- Assert.AreEqual("LastNameChanged", nameAfter);
+ var field = tbl.Field("LastNameChanged");
+ Assert.AreEqual("LastNameChanged", field.Name);
+
+ tbl.Cell(1, 1).Value = "FirstName";
+ Assert.AreEqual("FirstName", tbl.Field(0).Name);
+ }
+ }
+
+ [Test]
+ public void CanDeleteTableColumn()
+ {
+ var l = new List()
+ {
+ new TestObjectWithAttributes() { Column1 = "a", Column2 = "b", MyField = 4, UnOrderedColumn = 999 },
+ new TestObjectWithAttributes() { Column1 = "c", Column2 = "d", MyField = 5, UnOrderedColumn = 777 }
+ };
+
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet1");
+ var table = ws.FirstCell().InsertTable(l);
+
+ table.Column("C").Delete();
+
+ Assert.AreEqual(3, table.Fields.Count());
+
+ Assert.AreEqual("FirstColumn", table.Fields.First().Name);
+ Assert.AreEqual(0, table.Fields.First().Index);
+
+ Assert.AreEqual("UnOrderedColumn", table.Fields.Last().Name);
+ Assert.AreEqual(2, table.Fields.Last().Index);
+ }
+ }
+
+ [Test]
+ public void CanDeleteTableField()
+ {
+ var l = new List()
+ {
+ new TestObjectWithAttributes() { Column1 = "a", Column2 = "b", MyField = 4, UnOrderedColumn = 999 },
+ new TestObjectWithAttributes() { Column1 = "c", Column2 = "d", MyField = 5, UnOrderedColumn = 777 }
+ };
+
+ using (var wb = new XLWorkbook())
+ {
+ var ws = wb.AddWorksheet("Sheet1");
+ var table = ws.FirstCell().InsertTable(l);
+
+ table.Field("SomeFieldNotProperty").Delete();
+
+ Assert.AreEqual(3, table.Fields.Count());
+
+ Assert.AreEqual("FirstColumn", table.Fields.First().Name);
+ Assert.AreEqual(0, table.Fields.First().Index);
+
+ Assert.AreEqual("UnOrderedColumn", table.Fields.Last().Name);
+ Assert.AreEqual(2, table.Fields.Last().Index);
+ }
}
}
}
diff --git a/ClosedXML_Tests/Excel/Worksheets/XLWorksheetTests.cs b/ClosedXML_Tests/Excel/Worksheets/XLWorksheetTests.cs
index f679187..0918e5a 100644
--- a/ClosedXML_Tests/Excel/Worksheets/XLWorksheetTests.cs
+++ b/ClosedXML_Tests/Excel/Worksheets/XLWorksheetTests.cs
@@ -140,5 +140,25 @@
Assert.AreEqual(6, value);
}
}
+
+ [Test]
+ public void CanRenameWorksheet()
+ {
+ using (var wb = new XLWorkbook())
+ {
+ var ws1 = wb.AddWorksheet("Sheet1");
+ var ws2 = wb.AddWorksheet("Sheet2");
+
+ ws1.Name = "New sheet name";
+ Assert.AreEqual("New sheet name", ws1.Name);
+
+ ws2.Name = "sheet2";
+ Assert.AreEqual("sheet2", ws2.Name);
+
+ Assert.Throws(() => ws1.Name = "SHEET2");
+
+
+ }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/ClosedXML_Tests/OleDb/OleDbTests.cs b/ClosedXML_Tests/OleDb/OleDbTests.cs
index e502614..2aa897c 100644
--- a/ClosedXML_Tests/OleDb/OleDbTests.cs
+++ b/ClosedXML_Tests/OleDb/OleDbTests.cs
@@ -1,4 +1,5 @@
using ClosedXML.Excel;
+using ClosedXML_Tests.Utils;
using NUnit.Framework;
using System;
using System.Collections.Generic;
@@ -16,7 +17,7 @@
[Test]
public void TestOleDbValues()
{
- using (var tf = new TestFile(CreateTestFile()))
+ using (var tf = new TemporaryFile(CreateTestFile()))
{
Console.Write("Using temporary file\t{0}", tf.Path);
var connectionString = string.Format(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 12.0 Xml;HDR=YES;IMEX=1';", tf.Path);
@@ -115,32 +116,5 @@
return path;
}
}
-
- internal class TestFile : IDisposable
- {
- internal TestFile(string path)
- : this(path, false)
- { }
-
- internal TestFile(string path, bool preserve)
- {
- this.Path = path;
- this.Preserve = preserve;
- }
-
- public string Path { get; private set; }
- public bool Preserve { get; private set; }
-
- public void Dispose()
- {
- if (!Preserve)
- File.Delete(Path);
- }
-
- public override string ToString()
- {
- return this.Path;
- }
- }
}
}
diff --git a/ClosedXML_Tests/Resource/Examples/Misc/InsertingData.xlsx b/ClosedXML_Tests/Resource/Examples/Misc/InsertingData.xlsx
index 9e9d20f..c8ae77a 100644
--- a/ClosedXML_Tests/Resource/Examples/Misc/InsertingData.xlsx
+++ b/ClosedXML_Tests/Resource/Examples/Misc/InsertingData.xlsx
Binary files differ
diff --git a/ClosedXML_Tests/Resource/Examples/PivotTables/PivotTables.xlsx b/ClosedXML_Tests/Resource/Examples/PivotTables/PivotTables.xlsx
index 6e3156d..7c0b68e 100644
--- a/ClosedXML_Tests/Resource/Examples/PivotTables/PivotTables.xlsx
+++ b/ClosedXML_Tests/Resource/Examples/PivotTables/PivotTables.xlsx
Binary files differ
diff --git a/ClosedXML_Tests/Resource/Misc/DuplicateImageNames.xlsx b/ClosedXML_Tests/Resource/Misc/DuplicateImageNames.xlsx
new file mode 100644
index 0000000..29df50b
--- /dev/null
+++ b/ClosedXML_Tests/Resource/Misc/DuplicateImageNames.xlsx
Binary files differ
diff --git a/ClosedXML_Tests/Resource/Misc/TableHeadersWithLineBreaks.xlsx b/ClosedXML_Tests/Resource/Misc/TableHeadersWithLineBreaks.xlsx
new file mode 100644
index 0000000..8e7dbdc
--- /dev/null
+++ b/ClosedXML_Tests/Resource/Misc/TableHeadersWithLineBreaks.xlsx
Binary files differ
diff --git a/ClosedXML_Tests/Resource/Misc/TableWithNameNull.xlsx b/ClosedXML_Tests/Resource/Misc/TableWithNameNull.xlsx
new file mode 100644
index 0000000..0a5a8de
--- /dev/null
+++ b/ClosedXML_Tests/Resource/Misc/TableWithNameNull.xlsx
Binary files differ
diff --git a/ClosedXML_Tests/Utils/TemporaryFile.cs b/ClosedXML_Tests/Utils/TemporaryFile.cs
new file mode 100644
index 0000000..6d95b1f
--- /dev/null
+++ b/ClosedXML_Tests/Utils/TemporaryFile.cs
@@ -0,0 +1,37 @@
+using System;
+using System.IO;
+
+namespace ClosedXML_Tests.Utils
+{
+ internal class TemporaryFile : IDisposable
+ {
+ internal TemporaryFile()
+ : this(System.IO.Path.ChangeExtension(System.IO.Path.GetTempFileName(), "xlsx"))
+ { }
+
+ internal TemporaryFile(string path)
+ : this(path, false)
+ { }
+
+ internal TemporaryFile(String path, bool preserve)
+ {
+ this.Path = path;
+ this.Preserve = preserve;
+ }
+
+
+ public string Path { get; private set; }
+ public bool Preserve { get; private set; }
+
+ public void Dispose()
+ {
+ if (!Preserve)
+ File.Delete(Path);
+ }
+
+ public override string ToString()
+ {
+ return this.Path;
+ }
+ }
+}
diff --git a/ClosedXML_Tests/packages.config b/ClosedXML_Tests/packages.config
index c32aa84..5e0ab7c 100644
--- a/ClosedXML_Tests/packages.config
+++ b/ClosedXML_Tests/packages.config
@@ -1,5 +1,5 @@
-
-
-
-
+
+
+
+
\ No newline at end of file