Bugfix Praveen
diff --git a/EPPlus/ExcelNamedRangeCollection.cs b/EPPlus/ExcelNamedRangeCollection.cs index 8ea6462..3f6a493 100644 --- a/EPPlus/ExcelNamedRangeCollection.cs +++ b/EPPlus/ExcelNamedRangeCollection.cs
@@ -81,6 +81,22 @@ private void AddName(string Name, ExcelNamedRange item) { + // Is 'Name' already present + if (_dic.ContainsKey(Name)) + { + int index = _dic[Name]; + if ((0 <= index) && (index < _list.Count)) + { + ExcelNamedRange listItem = _list[index]; + if ((listItem != null) && (listItem.FullAddress == item.FullAddress)) + return; + + throw new Exception(string.Format("Name '{0}' is defined in the worksheet more than once. First as '{1}' and second as '{2}'.", Name, listItem.FullAddress, item.FullAddress)); + } + + throw new Exception(string.Format("Name '{0}' is defined in the worksheet more than once.", Name)); + } + _dic.Add(Name, _list.Count); _list.Add(item); }
diff --git a/EPPlus/FormulaParsing/CalculateExtentions.cs b/EPPlus/FormulaParsing/CalculateExtentions.cs index 6763f3b..1ec584a 100644 --- a/EPPlus/FormulaParsing/CalculateExtentions.cs +++ b/EPPlus/FormulaParsing/CalculateExtentions.cs
@@ -153,6 +153,11 @@ } Thread.Sleep(0); } + catch (OfficeOpenXml.FormulaParsing.Excel.Functions.FunctionException functionex) + { + // Excel function is not supported by EPPlus + throw (functionex); + } catch (FormatException fe) { throw (fe);
diff --git a/EPPlus/FormulaParsing/Excel/Functions/FunctionRepository.cs b/EPPlus/FormulaParsing/Excel/Functions/FunctionRepository.cs index ca4a769..4b90546 100644 --- a/EPPlus/FormulaParsing/Excel/Functions/FunctionRepository.cs +++ b/EPPlus/FormulaParsing/Excel/Functions/FunctionRepository.cs
@@ -33,6 +33,29 @@ namespace OfficeOpenXml.FormulaParsing.Excel.Functions { + // Used to report the names of Excel functions that are not supported by EPPlus + public class FunctionException : SystemException + { + // Summary: + // Initializes a new instance of the System.FunctionException class. + public FunctionException() + : base() + { + } + // + // Summary: + // Initializes a new instance of the System.FunctionException class with a specified + // error message. + // + // Parameters: + // message: + // The message that describes the error. + public FunctionException(string message) + : base(message) + { + } + } + /// <summary> /// This class provides methods for accessing/modifying VBA Functions. /// </summary> @@ -69,6 +92,9 @@ { if(!_functions.ContainsKey(name.ToLower(CultureInfo.InvariantCulture))) { + // Report that Excel function is not supported by EPPlus + throw new FunctionException(string.Format("Excel function '{0}' is not supported in formulas.", name)); + //throw new InvalidOperationException("Non supported function: " + name); //throw new ExcelErrorValueException("Non supported function: " + name, ExcelErrorValue.Create(eErrorType.Name)); return null;
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/CompileResult.cs b/EPPlus/FormulaParsing/ExpressionGraph/CompileResult.cs index 8074af0..d1959c6 100644 --- a/EPPlus/FormulaParsing/ExpressionGraph/CompileResult.cs +++ b/EPPlus/FormulaParsing/ExpressionGraph/CompileResult.cs
@@ -102,7 +102,14 @@ } else if (IsNumericString) { - return double.Parse(Result.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture); + try + { + return double.Parse(Result.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture); + } + catch (Exception ex) + { + return 0; + } } else if (Result is ExcelDataProvider.IRangeInfo) {
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/DecimalExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/DecimalExpression.cs index 1182d2d..6e3ba50 100644 --- a/EPPlus/FormulaParsing/ExpressionGraph/DecimalExpression.cs +++ b/EPPlus/FormulaParsing/ExpressionGraph/DecimalExpression.cs
@@ -65,5 +65,11 @@ result = _negate ? result * -1 : result; return new CompileResult(result, DataType.Decimal); } + + public bool IsNegated + { + get { return _negate; } + } + } }
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/ExcelAddressExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/ExcelAddressExpression.cs index c034117..186c726 100644 --- a/EPPlus/FormulaParsing/ExpressionGraph/ExcelAddressExpression.cs +++ b/EPPlus/FormulaParsing/ExpressionGraph/ExcelAddressExpression.cs
@@ -118,5 +118,11 @@ compileResult.IsHiddenCell = cell.IsHiddenRow; return compileResult; } + + public bool IsNegated + { + get { return _negate; } + } + } }
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/Expression.cs b/EPPlus/FormulaParsing/ExpressionGraph/Expression.cs index 61ab6b3..277b78a 100644 --- a/EPPlus/FormulaParsing/ExpressionGraph/Expression.cs +++ b/EPPlus/FormulaParsing/ExpressionGraph/Expression.cs
@@ -39,7 +39,7 @@ { public abstract class Expression { - protected string ExpressionString { get; private set; } + public string ExpressionString { get; private set; } private readonly List<Expression> _children = new List<Expression>(); public IEnumerable<Expression> Children { get { return _children; } } public Expression Next { get; set; }
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/GroupExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/GroupExpression.cs index cad1339..e8dba20 100644 --- a/EPPlus/FormulaParsing/ExpressionGraph/GroupExpression.cs +++ b/EPPlus/FormulaParsing/ExpressionGraph/GroupExpression.cs
@@ -67,5 +67,11 @@ { get { return true; } } + + public bool IsNegated + { + get { return _isNegated; } + } + } }
diff --git a/EPPlus/FormulaParsing/ExpressionGraph/IntegerExpression.cs b/EPPlus/FormulaParsing/ExpressionGraph/IntegerExpression.cs index 6178660..4e57168 100644 --- a/EPPlus/FormulaParsing/ExpressionGraph/IntegerExpression.cs +++ b/EPPlus/FormulaParsing/ExpressionGraph/IntegerExpression.cs
@@ -65,5 +65,11 @@ result = _negate ? result*-1 : result; return new CompileResult(result, DataType.Integer); } + + public bool IsNegated + { + get { return _negate; } + } + } }
diff --git a/EPPlus/FormulaParsing/FormulaParser.cs b/EPPlus/FormulaParsing/FormulaParser.cs index 64dd6cc..e025114 100644 --- a/EPPlus/FormulaParsing/FormulaParser.cs +++ b/EPPlus/FormulaParsing/FormulaParser.cs
@@ -218,6 +218,17 @@ } } + // Praveen's Formula Parser + public ExpressionGraph.ExpressionGraph ParseToGraph(string formula) + { + using (var scope = _parsingContext.Scopes.NewScope(RangeAddress.Empty)) + { + var tokens = _lexer.Tokenize(formula); + var graph = _graphBuilder.Build(tokens); + return graph; + } + } + public IFormulaParserLogger Logger { get { return _parsingContext.Configuration.Logger; }
diff --git a/EPPlus/FormulaParsing/FormulaParserManager.cs b/EPPlus/FormulaParsing/FormulaParserManager.cs index 7137b99..aa9658b 100644 --- a/EPPlus/FormulaParsing/FormulaParserManager.cs +++ b/EPPlus/FormulaParsing/FormulaParserManager.cs
@@ -97,6 +97,12 @@ return _parser.Parse(formula); } + // Praveen's Parser Support + public ExpressionGraph.ExpressionGraph ParseToGraph(string formula) + { + return _parser.ParseToGraph(formula); + } + /// <summary> /// Attaches a logger to the <see cref="FormulaParser"/>. /// </summary>
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/SourceCodeTokenizer.cs b/EPPlus/FormulaParsing/LexicalAnalysis/SourceCodeTokenizer.cs index 60b9e9c..a0d5d47 100644 --- a/EPPlus/FormulaParsing/LexicalAnalysis/SourceCodeTokenizer.cs +++ b/EPPlus/FormulaParsing/LexicalAnalysis/SourceCodeTokenizer.cs
@@ -71,6 +71,8 @@ // MA 1401: Ignore leading plus in formula. input = input.TrimStart('+'); var context = new TokenizerContext(input); + + bool isSingleQuoteString = false; for (int i = 0; i<context.FormulaChars.Length;i++) { var c = context.FormulaChars[i]; @@ -90,6 +92,12 @@ context.AppendToCurrentToken(c); continue; } + // CHANGE 2 + if ((isSingleQuoteString && c != '\'') || (!isSingleQuoteString && c != '"')) + { + context.AppendToCurrentToken(c); + continue; + } } if (tokenSeparator.TokenType == TokenType.OpeningBracket) { @@ -119,9 +127,11 @@ } if (tokenSeparator.TokenType == TokenType.String) { + // CHANGE3 : + isSingleQuoteString = (c == '\''); if (context.LastToken != null && context.LastToken.TokenType == TokenType.OpeningEnumerable) { - context.AppendToCurrentToken(c); + // context.AppendToCurrentToken(c); // Praveen's change of 10/28/2015 context.ToggleIsInString(); continue; }
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorProvider.cs b/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorProvider.cs index 61df09a..d11ccd6 100644 --- a/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorProvider.cs +++ b/EPPlus/FormulaParsing/LexicalAnalysis/TokenSeparatorProvider.cs
@@ -59,7 +59,7 @@ _tokens.Add(")", new Token(")", TokenType.ClosingParenthesis)); _tokens.Add("{", new Token("{", TokenType.OpeningEnumerable)); _tokens.Add("}", new Token("}", TokenType.ClosingEnumerable)); - _tokens.Add("'", new Token("'", TokenType.String)); + _tokens.Add("'", new Token("'", TokenType.String)); _tokens.Add("\"", new Token("\"", TokenType.String)); _tokens.Add(",", new Token(",", TokenType.Comma)); _tokens.Add(";", new Token(";", TokenType.SemiColon));
diff --git a/EPPlus/FormulaParsing/LexicalAnalysis/TokenizerContext.cs b/EPPlus/FormulaParsing/LexicalAnalysis/TokenizerContext.cs index 5518a5c..6a28142 100644 --- a/EPPlus/FormulaParsing/LexicalAnalysis/TokenizerContext.cs +++ b/EPPlus/FormulaParsing/LexicalAnalysis/TokenizerContext.cs
@@ -85,7 +85,7 @@ public bool CurrentTokenHasValue { - get { return !string.IsNullOrEmpty(CurrentToken.Trim()); } + get { return !string.IsNullOrEmpty(this.IsInString ? CurrentToken : CurrentToken.Trim()); } } public void NewToken()