Using Array Formulas

Use an array formula to make your worksheet more powerful and simplify it at the same time. The following examples illustrate how you might use array formulas.

Description
app.vue
index.html
Copy to CodeMine

An array formula can do calculations on rows and columns of cells where you might otherwise need to use several formulas. For example:

    // Calculate everyone's total score
    sheet.setArrayFormula(1, 5, 6, 1, 
           '=SUBTOTAL(9,OFFSET($B$2,ROW($A$1:$A$6)-ROW($A$1),,1,3))')

You can use an array formula to help search range items. For example:

    // Find the first value in B1:B5 that does not contain data in A1:A9
    sheet.setArrayFormula(2, 5, 1, 1, 
           '=INDEX(B1:B5,MATCH(TRUE,ISNA(MATCH(B1:B5,A1:A9,0)),0))')

An array formula can help collect statistics information from related range items. For example:

    // Summing Sales: Faxes Sold By Brown
    sheet.setArrayFormula(2, 5, 1, 1, 
           '=SUM((A2:A10="Fax")*(B2:B10="Brown")*(C2:C10))');
    // Logical AND (Faxes And Brown)
    sheet.setArrayFormula(5, 5, 1, 1, 
           '=SUM((A2:A10="Fax")*(B2:B10="Brown"))');
An array formula can do calculations on rows and columns of cells where you might otherwise need to use several formulas. For example: You can use an array formula to help search range items. For example: An array formula can help collect statistics information from related range items. For example:
<template> <div class="sample-tutorial"> <gc-spread-sheets class="sample-spreadsheets" @workbookInitialized="initSpread"> <gc-worksheet> </gc-worksheet> <gc-worksheet> </gc-worksheet> <gc-worksheet> </gc-worksheet> </gc-spread-sheets> <div class="options-container"> <textarea id="formulaBar" rows="10" readonly="readonly"></textarea> </div> </div> </template> <script setup> import GC from "@mescius/spread-sheets"; const spreadNS = GC.Spread.Sheets; function initSpread (spread) { var fbx = new spreadNS.FormulaTextBox.FormulaTextBox(document.getElementById('formulaBar')); fbx.workbook(spread); var oldArrayRange; var arrayFormulaStyle = new spreadNS.Style(); arrayFormulaStyle.backColor = "#E0E0FF"; for (var i = 0; i < spread.sheets.length; i++) { (function (sheet1) { sheet1.bind(spreadNS.Events.SelectionChanged, null, function (args) { sheet1.suspendPaint(); var formulaBar = document.getElementById("formulaBar"); var formulaInfo = sheet1.getFormulaInformation(sheet1.getActiveRowIndex(), sheet1.getActiveColumnIndex()); if (oldArrayRange && (!formulaInfo || !formulaInfo.isArrayFormula || !formulaInfo.baseRange.equals(oldArrayRange))) { for (var r = oldArrayRange.row; r < oldArrayRange.row + oldArrayRange.rowCount; r++) { for (var c = oldArrayRange.col; c < oldArrayRange.col + oldArrayRange.colCount; c++) { sheet1.setStyle(r, c, null); } } oldArrayRange = null; } if (formulaInfo && formulaInfo.hasFormula) { var formula = "=" + formulaInfo.formula; formula = formulaInfo.isArrayFormula ? "{" + formula + "}" : formula; formulaBar.value=formula; if (formulaInfo.isArrayFormula && !formulaInfo.baseRange.equals(oldArrayRange)) { oldArrayRange = formulaInfo.baseRange; for (var r = oldArrayRange.row; r < oldArrayRange.row + oldArrayRange.rowCount; r++) { for (var c = oldArrayRange.col; c < oldArrayRange.col + oldArrayRange.colCount; c++) { sheet1.setStyle(r, c, arrayFormulaStyle); } } } } else { formulaBar.value=sheet1.getValue(sheet1.getActiveRowIndex(), sheet1.getActiveColumnIndex()); } sheet1.resumePaint(); }); })(spread.sheets[i]); } setCalculation(spread.sheets[0]); setSearch(spread.sheets[1]); setStatistics(spread.sheets[2]); } function setCalculation (sheet) { sheet.name("Calculation"); sheet.setArray(0, 0, [ ["", "Match", "Physical", "Chemistry"], ["Alice", 97, 61, 53], ["Jon", 65, 76, 65], ["Bob", 55, 70, 64], ["Jack", 89, 77, 73], ["Tom", 83, 62, 78], ["Robert", 86, 98, 57] ]); sheet.addSpan(0, 5, 1, 4); sheet.setValue(0, 5, "Calculate every body's total score"); sheet.setArrayFormula(1, 5, 6, 1, "=SUBTOTAL(9,OFFSET($B$2,ROW($A$1:$A$6)-ROW($A$1),,1,3))"); } function setSearch (sheet) { sheet.name("Search"); sheet.setArray(0, 0, [ ["apple", "apple"], ["banana", "strawberry"], ["pea", "potato"], ["tomato", "potato"], ["potato", "dumpling"], ["cake"], ["noodle"], ["rice"], ["soup"] ]); sheet.addSpan(0, 3, 1, 8); sheet.setValue(0, 3, "Find out the first value on B1:B5 that does not contains on A1:A9"); sheet.setColumnWidth(3, 80); sheet.addSpan(2, 3, 1, 2); sheet.setValue(2, 3, "ArrayFormula Result:"); sheet.setArrayFormula(2, 5, 1, 1, "=INDEX(B1:B5,MATCH(TRUE,ISNA(MATCH(B1:B5,A1:A9,0)),0))"); sheet.getCell(2, 5).backColor("Accent 5 80"); sheet.addSpan(3, 3, 1, 2); sheet.setValue(3, 3, "NormalFormula Result:"); sheet.setFormula(3, 5, "=INDEX(B1:B5,MATCH(TRUE,ISNA(MATCH(B1:B5,A1:A9,0)),0))"); sheet.getCell(3, 5).backColor("Accent 6 80"); } function setStatistics (sheet) { sheet.name("Statistics"); sheet.options.allowCellOverflow = true; sheet.setArray(0, 0, [ ["Product", "Salesman", "Units Sold"], ["Fax", "Brown", 1], ["Phone", "Smith", 10], ["Fax", "Jones", 20], ["Fax", "Smith", 30], ["Phone", "Jones", 40], ["PC", "Smith", 50], ["Fax", "Brown", 60], ["Phone", "Davis", 70], ["PC", "Jones", 80] ]); sheet.setValue(1, 5, "Summing Sales: Faxes Sold By Brown"); sheet.setArrayFormula(2, 5, 1, 1, "=SUM((A2:A10=\"Fax\")*(B2:B10=\"Brown\")*(C2:C10))"); sheet.setValue(4, 5, "Logical AND (Faxes And Brown)"); sheet.setArrayFormula(5, 5, 1, 1, "=SUM((A2:A10=\"Fax\")*(B2:B10=\"Brown\"))"); sheet.setValue(7, 5, "Logical OR (Faxes Or Jones)"); sheet.setArrayFormula(8, 5, 1, 1, "=SUM(IF((A2:A10=\"Fax\")+(B2:B10=\"Jones\"),1,0))"); sheet.setValue(10, 5, "Logical XOR (Fax Or Jones but not both)"); sheet.setArrayFormula(11, 5, 1, 1, "=SUM(IF(MOD((A2:A10=\"Fax\")+(B2:B10=\"Jones\"),2),1,0))"); sheet.setValue(13, 5, "Logical AND (All Sales Except Fax And Jones)"); sheet.setArrayFormula(14, 5, 1, 1, "=SUM(IF((A2:A10=\"Fax\")+(B2:B10=\"Jones\")<>2,1,0))"); } </script> <style scoped> #app { height: 100%; } .sample-tutorial { position: relative; height: 100%; overflow: hidden; } .sample-spreadsheets { width: calc(100% - 280px); height: 100%; overflow: hidden; float: left; } .options-container { float: right; width: 280px; padding: 12px; height: 100%; box-sizing: border-box; background: #fbfbfb; overflow: auto; } textarea { width: 100%; box-sizing: border-box; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; } </style>
<!DOCTYPE html> <html lang="en" style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <title>SpreadJS VUE</title> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/vue3/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <script src="$DEMOROOT$/en/vue3/node_modules/systemjs/dist/system.src.js"></script> <script src="./systemjs.config.js"></script> <script src="./compiler.js" type="module"></script> <script> var System = SystemJS; System.import("./src/app.js"); System.import('$DEMOROOT$/en/lib/vue3/license.js'); </script> </head> <body> <div id="app"></div> </body> </html>
(function (global) { SystemJS.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, packageConfigPaths: [ './node_modules/*/package.json', "./node_modules/@mescius/*/package.json", "./node_modules/@babel/*/package.json", "./node_modules/@vue/*/package.json" ], map: { '@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js', '@mescius/spread-sheets-vue': 'npm:@mescius/spread-sheets-vue/index.js', 'vue': "npm:vue/dist/vue.esm-browser.js", 'tiny-emitter': 'npm:tiny-emitter/index.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', "systemjs-babel-build": "npm:systemjs-plugin-babel/systemjs-babel-browser.js", }, meta: { '*.css': { loader: 'systemjs-plugin-css' }, '*.vue': { loader: "../plugin-vue/index.js" } } }); })(this);