-
Notifications
You must be signed in to change notification settings - Fork 304
Dynamic arrayformulas
EPPlus supports dynamic array formulas and spill ranges from version 7. A dynamic array formula is a formula that returns multiple values — the results automatically spill into adjacent cells, just as they do in modern Excel.
Note: Dynamic array formulas must be calculated by EPPlus to appear correctly when the file is opened in Excel or other spreadsheet applications.
A formula that returns an array of values will automatically spill its results into the cells below or to the right of the formula cell.
sheet.Cells["A1"].Value = 1;
sheet.Cells["A2"].Value = 2;
sheet.Cells["A3"].Value = 3;
// This formula returns an array of boolean values — {FALSE, TRUE, TRUE}
// The results spill into A5:A7
sheet.Cells["A5"].Formula = "A1:A3 > 1";
sheet.Calculate();Functions that return arrays work the same way. The example below uses SORTBY to sort a range by a separate column and spill the sorted result starting at A4.
sheet.Cells["A1"].Value = "Bob"; sheet.Cells["B1"].Value = "Street 1"; sheet.Cells["C1"].Value = 25;
sheet.Cells["A2"].Value = "Steve"; sheet.Cells["B2"].Value = "Street 2"; sheet.Cells["C2"].Value = 23;
sheet.Cells["A3"].Value = "Phil"; sheet.Cells["B3"].Value = "Street 3"; sheet.Cells["C3"].Value = 21;
// Sort A1:B3 by the values in C1:C3 ascending
sheet.Cells["A4"].Formula = "SORTBY(A1:B3, C1:C3, 1)";
sheet.Calculate();
Assert.AreEqual("Phil", sheet.Cells["A4"].Value); // age 21
Assert.AreEqual("Steve", sheet.Cells["A5"].Value); // age 23
Assert.AreEqual("Bob", sheet.Cells["A6"].Value); // age 25In the Excel UI you can use the # operator to reference the full spill range of a dynamic array formula — for example SUM(B3#). This operator is not part of the OOXML standard. In EPPlus you use the ANCHORARRAY function instead:
// Excel UI: SUM(B3#)
// EPPlus: SUM(ANCHORARRAY(B3))
sheet.Cells["B3"].Formula = "UNIQUE(A1:A10)";
sheet.Cells["D1"].Formula = "SUM(ANCHORARRAY(B3))";
sheet.Calculate();Note that ANCHORARRAY is not an EPPlus-specific function — it is the function Excel itself uses internally when saving # references to the file format.
From EPPlus 7, you can use ExcelRangeBase.FormulaRange to get the spill range of a calculated dynamic array formula and use it as a chart data source.
sheet.Cells[2, 2].Formula = "RANDARRAY(5,5)";
sheet.Calculate(); // Must be calculated first to determine the spill range
var chart = sheet.Drawings.AddBarChart("Dynamic Chart", eBarChartType.ColumnClustered);
var range = sheet.Cells[2, 2].FormulaRange;
for (var c = range.Start.Column; c <= range.End.Column; c++)
{
chart.Series.Add(range.TakeSingleColumn(c));
}
chart.StyleManager.SetChartStyle(ePresetChartStyle.ColumnChartStyle9);
chart.SetPosition(1, 0, 10, 0);You can also use ExcelWorksheet.GetFormulaRange(int row, int col) as an alternative. The Take and Skip functions are useful when building chart series from spill ranges.
Implicit intersection means that when a formula expects a single value but receives a range, it picks the value in the same row or column as the formula cell. In the Excel UI this is expressed with the @ operator. Since @ is not part of the OOXML standard, EPPlus uses different approaches depending on the context.
Read more about implicit intersection here (Microsoft, external link).
Use the SINGLE function to apply implicit intersection to a range argument inside a function.
// Excel UI: SUM(@A1:A5)
// EPPlus: SUM(SINGLE(A1:A5))
sheet.Cells["B1"].Formula = "SUM(SINGLE(A1:A5))";
sheet.Calculate();To apply implicit intersection to the output of a formula in a single cell, set UseImplicitIntersection = true on the cell after assigning the formula.
// Excel UI: @A1:A5 (in both B1 and B2)
sheet.Cells["B1"].Formula = "A1:A5";
sheet.Cells["B2"].Formula = "A1:A5";
// Must be set AFTER the formula has been assigned
sheet.Cells["B1:B2"].UseImplicitIntersection = true;
sheet.Calculate();
// Without UseImplicitIntersection, EPPlus treats the formula
// as a dynamic array formula and spills the results instead.When a formula is assigned to a multi-cell range (a shared formula), implicit intersection is always applied automatically — each cell in the range picks the value from its own row or column.
// Each cell in B1:B5 resolves to the value in the corresponding row of A1:A5
sheet.Cells["B1:B5"].Formula = "A1:A5";
sheet.Calculate();Many functions that previously only accepted single values can from EPPlus 7 take an array as input and return an array as output. This works both with legacy array formulas and dynamic array formulas.
// Legacy array formula — result is written to B1:B3
sheet.Cells["B1:B3"].CreateArrayFormula("YEAR(A1:A3)");
// Dynamic array formula — result spills from D1 downward
sheet.Cells["D1"].Formula = "YEAR(A1:A3)";
sheet.Calculate();EPPlus Software AB - https://epplussoftware.com
- What is new in EPPlus 5+
- Breaking Changes in EPPlus 5
- Breaking Changes in EPPlus 6
- Breaking Changes in EPPlus 7
- Breaking Changes in EPPlus 8
- Addressing a worksheet
- Dimension/Used range
- Copying ranges/sheets
- Insert/Delete
- Filling ranges
- Sorting ranges
- Taking and skipping columns/rows
- Data validation
- Comments
- Freeze and Split Panes
- Header and Footer
- Hyperlinks
- Autofit columns
- Grouping and Ungrouping Rows and Columns
- Formatting and styling
- The ExcelRange.Text property
- Conditional formatting
- Using Themes
- Working with custom named table- or slicer- styles