工作表公式引用集算表

SpreadJS 支持在工作表中使用结构化引用方式引用集算表(TableSheet)数据。您可以使用集算表名称和列标题,像引用表格一样在公式中访问集算表的数据,实现跨表数据汇总和报表分析。

此外,还可以通过 QUERY 函数直接从 DataManager 表中查询数据,支持按条件筛选、按主键查询等灵活的数据访问方式。

概述 本 Demo 展示了如何在普通工作表中使用公式引用集算表(TableSheet)的数据。Demo 创建了一个产品集算表(TableSheet1),然后在普通工作表中通过结构化引用和 QUERY 函数两种方式访问集算表数据,实现了产品统计、分类汇总、缺货筛选等多种数据分析功能。 实现思路 初始化 DataManager,添加产品表和类别表,并建立表关系 创建集算表 TableSheet1,绑定产品数据视图 在普通工作表中使用结构化引用(如 TableSheet1[Category])引用集算表数据 使用 COUNTA、SUM、UNIQUE、COUNTIF、MAXIFS、FILTER 等函数进行数据统计和分析 使用 QUERY 函数从 DataManager 表中按条件查询数据 代码解析 初始化 DataManager 和表关系 这段代码创建了两个数据表并建立了关系。addRelationship 方法将产品表的 CategoryId 字段与类别表的 Id 字段关联,使得产品视图可以访问类别信息。 创建集算表并绑定视图 视图定义了集算表的列结构,其中 Total Amount 和 Total Price 是计算列。[@UnitsInStock] 表示引用当前行的库存数量。 使用结构化引用引用集算表 结构化引用的格式为 TableSheetName[ColumnName],与 Excel 表格引用方式一致。A5# 表示引用动态数组的溢出区域。 使用 FILTER 函数筛选数据 FILTER 函数根据条件筛选集算表数据,返回动态数组结果。 使用 QUERY 函数查询 DataManager 表 QUERY 函数直接从 DataManager 表中查询数据。格式为 QUERY("tableName?filter", columns),其中 ?CategoryName="&B14 表示按类别名称筛选,A16:C16 指定返回的列。 运行效果 集算表 TableSheet1 显示产品数据,包含库存、订单数量和计算的总金额、总价格 普通工作表显示多个数据汇总区域: 产品总数和总价的统计 按类别汇总的产品数量、订单成本、最高单价等信息 缺货产品的筛选列表 点击类别下拉框选择类别后,QUERY 函数自动查询并显示该类别的产品信息 所有数据随集算表数据变化自动更新 API 参考 addRelationship 方法 sourceTable:源表对象 sourceFieldName:源表关联字段名 sourceRelationshipName:源表中关系名称 targetTable:目标表对象 targetFieldName:目标表关联字段名 targetRelationshipName:目标表中关系名称 QUERY 函数 tableAndRows:表名和筛选条件,格式为 "tableName?field=value" columns:可选,指定返回的列名或单元格区域 常用查询格式: 查询整个表:QUERY("table1") 按行索引查询:QUERY("table1#1") 按主键查询:QUERY("customer/abc@gmail.com") 按条件筛选:QUERY("order?status=success")
/*REPLACE_MARKER*/ /*DO NOT DELETE THESE COMMENTS*/ window.onload = function() { var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 1 }); initSpread(spread); }; function initSpread(spread) { spread.suspendPaint(); spread.options.autoFitType = GC.Spread.Sheets.AutoFitType.cellWithHeader; spread.options.allowDynamicArray = true; //init a data manager var baseApiUrl = getBaseApiUrl(); var dataManager = spread.dataManager(); //add product table var productTable = dataManager.addTable("productTable", { remote: { read: { url: baseApiUrl + "/Product" } } }); //add category table var categoryTable = dataManager.addTable("categoryTable", { remote: { read: { url: baseApiUrl + "/Category" } } }); //add relation ship dataManager.addRelationship(productTable, "CategoryId", "category", categoryTable, "Id", "products"); //init a table sheet var sheet = spread.addSheetTab(0, "TableSheet1", GC.Spread.Sheets.SheetType.tableSheet); sheet.options.allowAddNew = false; //hide new row sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader); //bind a view to the table sheet var myView = productTable.addView("myView", [ { value: "Id", caption: "ID" }, { value: "category.CategoryName", caption: "Category", width: 120 }, { value: "ProductName", caption: "Product Name", width: 200 }, { value: "UnitPrice", caption: "Unit Price", width: 120 }, { value: "UnitsInStock", caption: "Units In Stock", width: 120 }, { value: "UnitsOnOrder", caption: "Units On Order", width: 130 }, { value: "=SUM([@UnitsInStock], [@UnitsOnOrder])", caption: "Total Amount", width: 130 }, { value: "=[@UnitPrice] * SUM([@UnitsInStock], [@UnitsOnOrder])", caption: "Total Price", width: 120 } ]); myView.fetch().then(function() { spread.suspendPaint(); sheet.setDataView(myView); var sheet1 = spread.getSheet(0); sheet1.setColumnWidth(0, 170); sheet1.setColumnWidth(1, 95); sheet1.setColumnWidth(2, 95); sheet1.setColumnWidth(3, 120); sheet1.setColumnWidth(4, 170); sheet1.setColumnWidth(6, 110); sheet1.setColumnWidth(7, 170); sheet1.setValue(0, 0, "Product Count:") sheet1.setFormula(0, 1, "=COUNTA(TableSheet1[ID])"); sheet1.setValue(0, 3, 'Total Price:') sheet1.setFormula(0, 4, '=SUM(TableSheet1[Total Price])'); //Category Summary applyTableStyleForRange(sheet1, 3, 0, 9, 5); sheet1.setValue(2, 0, "Category Summary:") sheet1.setArray(3, 0, [ ["Category", "Product No", "On Order Cost", "Highest Unit Price", "Highest Price Product"] ]); sheet1.setFormula(4, 0, '=UNIQUE(TableSheet1[Category])'); sheet1.setFormula(4, 1, '=COUNTIF(TableSheet1[Category], A5#)'); sheet1.setFormula(4, 3, '=MAXIFS(TableSheet1[Unit Price], TableSheet1[Category], A5#)'); for (var i = 5; i <= 12; i++) { sheet1.setFormula(i - 1, 2, '=SUMPRODUCT((TableSheet1[Category]=A' + i + ')*TableSheet1[Units On Order],TableSheet1[Unit Price])'); sheet1.setFormula(i - 1, 4, '=XLOOKUP(D' + i + ', IF(TableSheet1[Category] = A' + i + ', TableSheet1[Unit Price], -1), TableSheet1[Product Name])'); } //Out of Stock sheet1.setValue(2, 6, "Out of Stock:") applyTableStyleForRange(sheet1, 3, 6, 6, 2); sheet1.setArray(3, 6, [ ["Category", "Product"] ]); sheet1.setFormula(4, 6, '=FILTER(TableSheet1[Category]:TableSheet1[Product Name], TableSheet1[Units In Stock] = 0)'); //Filters sheet1.setValue(13, 0, "Category:"); sheet1.setFormula(13, 1, "=A5"); var dv2 = GC.Spread.Sheets.DataValidation.createFormulaListValidator('=$A$5#'); sheet1.setDataValidator(13, 1, dv2); sheet1.setValue(13, 3, "Category ID:"); sheet1.setFormula(13, 4, '=QUERY("categoryTable?CategoryName="&B14, "Id")'); sheet1.comments.add(13, 4, 'Query the category id.'); applyTableStyleForRange(sheet1, 15, 0, 14, 3); sheet1.setArray(15, 0, [ ["ProductName", "UnitPrice", "UnitsInStock"] ]); sheet1.setFormula(16, 0, '=QUERY("productTable?CategoryId="&E14, A16:C16)'); sheet1.comments.add(16, 0, 'Use the QUERY function to get data from DataManager.'); spread.setActiveSheetIndex(0); spread.resumePaint(); }); spread.resumePaint(); } function getBaseApiUrl() { return window.location.href.match(/http.+spreadjs\/SpreadJSTutorial\//)[0] + 'server/api'; } function applyTableStyleForRange(sheet, row, col, rowCount, colCount, options) { var tableName = "tmpTable"; var TableThemes = GC.Spread.Sheets.Tables.TableThemes; // use table to help set style then remove like convert table to range in Excel sheet.tables.add(tableName, row, col, rowCount, colCount, TableThemes.light2, options); sheet.tables.remove(tableName, 2 /* keep style */ ); }
<!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"> <!-- Promise Polyfill for IE, https://www.npmjs.com/package/promise-polyfill --> <script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script> <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-tablesheet/dist/gc.spread.sheets.tablesheet.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 id="optionContainer" class="optionContainer"> </div> </div> </html>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; } .sample-spreadsheets { width: 100%; height: 100%; overflow: hidden; float: left; }