数组公式基础

数组公式是一种特殊的公式类型,可以在数组的一项或多项上执行多个计算,并返回一个或多个结果。SpreadJS 支持使用数组常量、区域引用和函数组合等多种方式创建数组公式,适用于批量计算、矩阵运算等复杂计算场景。

概述 本 Demo 展示了数组公式的基本用法,包括使用数组常量、区域引用和函数组合的多种示例。Demo 还实现了公式栏显示和数组公式区域高亮功能,帮助用户直观理解数组公式的工作方式。 实现思路 设置基础数据,准备用于数组公式计算的单元格值 演示多种数组公式的使用方式:数组常量、区域引用、函数组合等 通过 SelectionChanged 事件监听单元格选择变化 使用 getFormulaInformation 获取当前单元格的公式信息 在公式栏中显示公式内容,数组公式用大括号包裹 为数组公式区域设置高亮背景色,提升可视化效果 代码解析 设置数组公式 setArrayFormula 方法的参数依次为:起始行、起始列、行数、列数、公式字符串。数组公式会自动填充到指定区域的每个单元格中。 获取公式信息并高亮显示 getFormulaInformation 返回一个包含公式详细信息的对象,包括 hasFormula(是否有公式)、isArrayFormula(是否为数组公式)、formula(公式字符串)和 baseRange(数组公式的基础范围)等属性。 运行效果 工作表展示了 6 种不同的数组公式示例,包括数组常量、区域引用、函数组合等 点击任意单元格,右侧公式栏会显示该单元格的公式内容 数组公式会自动用大括号 {} 包裹显示 选中数组公式区域的任一单元格,整个数组公式区域会以浅蓝色背景高亮显示 切换单元格时,之前的高亮会自动清除,新选中的数组公式区域会重新高亮 API 参考 setArrayFormula 方法 row:起始行索引 col:起始列索引 rowCount:区域的行数 colCount:区域的列数 value:公式字符串(以 = 开头) sheetArea:可选,指定工作表区域 getFormulaInformation 方法 返回 IFormulaInfo 对象,包含以下属性: hasFormula:布尔值,指示单元格是否有公式 isArrayFormula:布尔值,指示公式是否为数组公式 formula:公式字符串(不包含 = 符号) formulaWithCulture:带区域设置的公式字符串 baseRange:数组公式的基础范围对象 isDynamicArray:布尔值,指示是否为动态数组公式
var spreadNS = GC.Spread.Sheets; window.onload = function () { var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 1 }); initSpread(spread); }; function initSpread(spread) { spread.suspendPaint(); 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]); } setBasic(spread.sheets[0]); spread.resumePaint(); } function setBasic(sheet) { sheet.name("简单示例"); sheet.setArray(0, 0, [[1, 2, 3, 4, 5, 6], [4, 5, 6], [7, 8, 9], [10, 11, 12]]); sheet.addSpan(0, 7, 4, 3); sheet.setValue(0, 7, "设置数组公式的方法:\n 1. 选择单元格/区域;\n 2. 输入公式;\n 最后按 Ctrl+Shift+Enter。"); setDescriptionStyle(sheet.getCell(0, 7)); sheet.setRowHeight(5, 40); sheet.addSpan(5, 0, 1, 3); sheet.setValue(5, 0, "使用常量的数组公式\n 示例:={1,2,3}*{4;5;6}"); setDescriptionStyle(sheet.getCell(5, 0)); sheet.setArrayFormula(6, 0, 3, 3, "={1,2,3}*{4;5;6}"); sheet.addSpan(5, 4, 1, 3); sheet.setValue(5, 4, "使用区域的数组公式\n 示例:=A1:A4*A1:C1"); setDescriptionStyle(sheet.getCell(5, 4)); sheet.setArrayFormula(6, 4, 4, 3, "=A1:A4*A1:C1"); sheet.addSpan(5, 8, 1, 4); sheet.setValue(5, 8, "使用区域和函数的数组公式\n 示例:=SUM(A1:A4*A1:C1)"); setDescriptionStyle(sheet.getCell(5, 8)); sheet.setArrayFormula(6, 8, 4, 2, "=SUM(A1:A4*A1:C1)"); sheet.setRowHeight(11, 40); sheet.addSpan(11, 0, 1, 4); sheet.setValue(11, 0, "复制列区域的数组公式\n 示例:=A1:A2"); setDescriptionStyle(sheet.getCell(11, 0)); sheet.setArrayFormula(12, 0, 2, 3, "=A1:A2"); sheet.addSpan(11, 5, 1, 3); sheet.setValue(11, 5, "复制行区域的数组公式\n 示例:=A1:B1"); setDescriptionStyle(sheet.getCell(11, 5)); sheet.setArrayFormula(12, 5, 4, 2, "=A1:B1"); sheet.setRowHeight(17, 40); sheet.addSpan(17, 0, 1, 4); sheet.setValue(17, 0, "数组公式超出范围的值为 #N/A:\n 示例:={1,2,3}*{4;5;6}"); setDescriptionStyle(sheet.getCell(17, 0)); sheet.setArrayFormula(18, 0, 4, 4, "={1,2,3}*{4;5;6}"); } function setDescriptionStyle(cell) { cell.wordWrap(true).backColor("Accent 5 80").vAlign(spreadNS.VerticalAlign.center); }
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta name="spreadjs culture" content="zh-cn" /> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-resources-zh/dist/gc.spread.sheets.resources.zh.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script> <script src="app.js" type="text/javascript"></script> <link rel="stylesheet" type="text/css" href="styles.css"> </head> <body> <div class="sample-tutorial"> <div id="ss" class="sample-spreadsheets"></div> <div class="options-container"> <textarea id="formulaBar" rows="10" readonly="readonly"></textarea> </div> </div> </body> </html>
.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; height: 100%; overflow: auto; padding: 12px; box-sizing: border-box; background: #fbfbfb; } textarea { width: 100%; box-sizing: border-box; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }