Bugfix ArrayFormula
diff --git a/EPPlus/ExcelRangeBase.cs b/EPPlus/ExcelRangeBase.cs
index f1f206c..288ad58 100644
--- a/EPPlus/ExcelRangeBase.cs
+++ b/EPPlus/ExcelRangeBase.cs
@@ -128,7 +128,7 @@
 		}
         ~ExcelRangeBase()
         {
-            this.AddressChange -= new EventHandler(ExcelRangeBase_AddressChange);
+            //this.AddressChange -= new EventHandler(ExcelRangeBase_AddressChange);
         }
 		#endregion
 		#region Set Value Delegates
@@ -328,7 +328,11 @@
                 _worksheet._values.SetValue(row, col, (Uri)null);
             }
         }
-		private void Set_IsRichText(object value, int row, int col)
+        private void Set_IsArrayFormula(object value, int row, int col)
+        {
+            _worksheet._flags.SetFlagValue(row, col, (bool)value, CellFlags.ArrayFormula);
+        }
+        private void Set_IsRichText(object value, int row, int col)
 		{
 			//_worksheet.Cell(row, col).IsRichText = (bool)value;
             _worksheet._flags.SetFlagValue(row, col, (bool)value, CellFlags.RichText);
@@ -1162,10 +1166,18 @@
 				}
 			}
 		}
-		/// <summary>
-		/// Set the hyperlink property for a range of cells
-		/// </summary>
-		public Uri Hyperlink
+        public string ArrayFormulaAddress
+        {
+            get
+            {
+                IsRangeValid("FormulaR1C1");
+                return _worksheet.GetArrayFormulaAddress(_fromRow, _fromCol);
+            }
+        }
+        /// <summary>
+        /// Set the hyperlink property for a range of cells
+        /// </summary>
+        public Uri Hyperlink
 		{
 			get
 			{
@@ -1321,7 +1333,11 @@
 				IsRangeValid("arrayformulas");
                 return _worksheet._flags.GetFlagValue(_fromRow, _fromCol, CellFlags.ArrayFormula);
 			}
-		}
+            set
+            {
+                _changePropMethod(Set_IsArrayFormula, value);
+            }
+        }
 		ExcelRichTextCollection _rtc = null;
 		/// <summary>
 		/// Cell value is richtext formatted. 
diff --git a/EPPlus/ExcelWorksheet.cs b/EPPlus/ExcelWorksheet.cs
index e79d163..995febe 100644
--- a/EPPlus/ExcelWorksheet.cs
+++ b/EPPlus/ExcelWorksheet.cs
@@ -120,7 +120,37 @@
                 _tokenizer = tokenizer;
             }
 
-            private ISourceCodeTokenizer _tokenizer;
+            public static string RemoveDummyFunction(string formula)
+            {
+                const string DummyFunctionPrefix = "IFERROR(__xludf.DUMMYFUNCTION(\"";
+                const string DummyFunctionSuffix = "\"),\"";
+
+                if (string.IsNullOrEmpty(formula))
+                    return formula;
+
+                // Look for Prefix
+                if (!formula.StartsWith(DummyFunctionPrefix))
+                    return formula;
+
+                // Look for Suffix
+                int index = formula.LastIndexOf(DummyFunctionSuffix);
+                if (index < 0)
+                    return formula;
+
+                // Trim Suffix
+                formula = formula.Substring(0, index);
+
+                // Trim Prefix
+                formula = formula.Replace(DummyFunctionPrefix, "");
+
+                // Replace doubled quotes with single quote
+                formula = formula.Replace("\"\"", "\"");
+
+                // Return formula
+                return formula;
+            }
+			
+           private ISourceCodeTokenizer _tokenizer;
             internal int Index { get; set; }
             internal string Address { get; set; }
             internal bool IsArray { get; set; }
@@ -129,17 +159,18 @@
             public int StartCol { get; set; }
 
             private IEnumerable<Token> Tokens {get; set;}
+           
 
             internal string GetFormula(int row, int column, string worksheet)
             {
-                if (StartRow == row && StartCol == column)
+                if ((StartRow == row && StartCol == column) || IsArray)
                 {
-                    return Formula;
+                    return RemoveDummyFunction(Formula);
                 }
 
                 if (Tokens == null)
                 {
-                    Tokens = _tokenizer.Tokenize(Formula, worksheet);
+                    Tokens = _tokenizer.Tokenize(RemoveDummyFunction(Formula), worksheet);
                 }
                 
                 string f = "";
@@ -1255,11 +1286,37 @@
                     else if (t == "array") //TODO: Array functions are not support yet. Read the formula for the start cell only.
                     {
                         string aAddress = xr.GetAttribute("ref");
+                        ExcelRange addressRange = new ExcelRange(this, aAddress);                      
                         string formula = xr.ReadElementContentAsString();
-                        var afIndex = GetMaxShareFunctionIndex(true);
-                        _formulas.SetValue(address._fromRow, address._fromCol, afIndex);
-                        _values.SetValue(address._fromRow, address._fromCol, null);
-                        _sharedFormulas.Add(afIndex, new Formulas(SourceCodeTokenizer.Default) { Index = afIndex, Formula = formula, Address = aAddress, StartRow = address._fromRow, StartCol = address._fromCol, IsArray = true });
+                        bool isIndexMatchFormula = Regex.IsMatch(formula, @"INDEX\(", RegexOptions.IgnoreCase) && Regex.IsMatch(formula, @"MATCH\(", RegexOptions.IgnoreCase) && !aAddress.Contains(":");
+                        if (isIndexMatchFormula)
+                        {
+                            addressRange.IsArrayFormula = false;
+                            for (int colIndex = addressRange.Start.Column; colIndex <= addressRange.End.Column; colIndex++)
+                            {
+                                for (int rowIndex = addressRange.Start.Row; rowIndex <= addressRange.End.Row; rowIndex++)
+                                {
+                                    var afIndex = GetMaxShareFunctionIndex(true);
+                                    _formulas.SetValue(rowIndex, colIndex, afIndex);
+                                    _values.SetValue(rowIndex, colIndex, null);
+                                    _sharedFormulas.Add(afIndex, new Formulas(SourceCodeTokenizer.Default) { Index = afIndex, Formula = formula, Address = aAddress, StartRow = address._fromRow, StartCol = address._fromCol, IsArray = false });
+                                }
+                            }
+                        }
+                        else
+                        {
+                            addressRange.IsArrayFormula = true;
+                            var afIndex = GetMaxShareFunctionIndex(true);
+                            for (int colIndex = addressRange.Start.Column; colIndex <= addressRange.End.Column; colIndex++)
+                            {
+                                for (int rowIndex = addressRange.Start.Row; rowIndex <= addressRange.End.Row; rowIndex++)
+                                {
+                                    _formulas.SetValue(rowIndex, colIndex, afIndex);
+                                    _values.SetValue(rowIndex, colIndex, null);
+                                }
+                            }
+                            _sharedFormulas.Add(afIndex, new Formulas(SourceCodeTokenizer.Default) { Index = afIndex, Formula = formula, Address = aAddress, StartRow = address._fromRow, StartCol = address._fromCol, IsArray = true });
+                        }
                     }
                     else // ??? some other type
                     {
@@ -1365,6 +1422,18 @@
             };
         }
 
+        private DateTime DurationFromOADate(double value)
+        {
+            // Convert the Duration value into the corresponding DateTime value.
+            // The Duration value is passed in as a fractional Office Automation double values where the 
+            // whole portion is the number of days and the fractional portion of the number is the hours.
+            // For example, the Duration value -1.5 represents a negative duration of one day and 12 hours.
+            // We use this technique rather than calling the 'DateTime.FromOADate()' method, because
+            // this technique works for both positive and negative duration values. unlike 'DateTime.FromOADate()'
+            // which yields the wrong result for negative Duration values.
+            return new DateTime(1899, 12, 30) + TimeSpan.FromDays(value);
+        }
+
         private void SetValueFromXml(XmlTextReader xr, string type, int styleID, int row, int col)
         {
             //XmlNode vnode = colNode.SelectSingleNode("d:v", NameSpaceManager);
@@ -1372,6 +1441,17 @@
             if (type == "s")
             {
                 int ix = xr.ReadElementContentAsInt();
+
+                // Temporary debugging code to locate intermittent 'Index was out of range' exception.
+                if (ix < 0)
+                {
+                    throw new Exception(string.Format("ReadElementContentAsInt returned value '{0}' which is less than zero.", ix));
+                }
+                if (ix >= _package.Workbook._sharedStringsList.Count)
+                {
+                    throw new Exception(string.Format("ReadElementContentAsInt returned index value '{0}' which is greater than _sharedStringsList count of {1}.", ix, _package.Workbook._sharedStringsList.Count));
+                }
+
                 _values.SetValue(row, col, _package.Workbook._sharedStringsList[ix].Text);
                 if (_package.Workbook._sharedStringsList[ix].isRichText)
                 {
@@ -1394,7 +1474,31 @@
             {
                 string v = xr.ReadElementContentAsString();
                 var nf = Workbook.Styles.CellXfs[styleID].NumberFormatId;
-                if ((nf >= 14 && nf <= 22) || (nf >= 45 && nf <= 47))
+                if ((nf >= 20 && nf <= 21) || (nf >= 45 && nf <= 47))  // Duration
+                {
+                    double res;
+                    if (double.TryParse(v, NumberStyles.Any, CultureInfo.InvariantCulture, out res))
+                    {
+                        if (Workbook.Date1904)
+                        {
+                            res += ExcelWorkbook.date1904Offset;
+                        }
+                        if (res >= -657435.0 && res < 2958465.9999999)
+                        {
+                            // Get the Duration value expressed as a DateTime.
+                            _values.SetValue(row, col, DurationFromOADate(res));
+                        }
+                        else
+                        {
+                            _values.SetValue(row, col, "");
+                        } 
+                    }
+                    else
+                    {
+                        _values.SetValue(row, col, "");
+                    }
+                }
+                else if ((nf >= 14 && nf <= 19) || (nf == 22))   // DateTime
                 {
                     double res;
                     if (double.TryParse(v, NumberStyles.Any, CultureInfo.InvariantCulture, out res))
@@ -1410,7 +1514,7 @@
                         else
                         {
                             _values.SetValue(row, col, "");
-                        } 
+                        }
                     }
                     else
                     {
@@ -4095,7 +4199,7 @@
             if (v is int)
             {
                 var sf = _sharedFormulas[(int)v];
-                return ExcelCellBase.TranslateToR1C1(sf.Formula, sf.StartRow, sf.StartCol);
+                return ExcelCellBase.TranslateToR1C1(Formulas.RemoveDummyFunction(sf.Formula), sf.StartRow, sf.StartCol);
             }
             else if (v != null)
             {
@@ -4106,6 +4210,18 @@
                 return "";
             }
         }
+        internal string GetArrayFormulaAddress(int row, int col)
+        {
+            var v = _formulas.GetValue(row, col);
+            if ((v is int) && (_sharedFormulas[(int)v].IsArray))
+            {
+                return _sharedFormulas[(int)v].Address;
+            }
+            else
+            {
+                return "";
+            }
+        }
 
         private void DisposeInternal(IDisposable candidateDisposable)
         {