自定义筛选行为

SpreadJS 支持通过继承筛选器基类来自定义筛选行为。开发者可以在筛选执行前后插入自定义逻辑,例如自动选中筛选结果、更新状态提示等,实现完全受代码控制的筛选交互。

概述 本 Demo 展示了如何创建自定义筛选器,通过继承 RowFilterBase 类并重写 onFilter 方法来实现筛选行为的自定义。Demo 中实现了一个 SelectionFilter 筛选器,在执行筛选时自动选中符合条件的行,并在取消筛选时重置选择状态。 实现思路 创建学生成绩数据表,包含姓名和分数两列 定义 SelectionFilter 类继承自 RowFilterBase 重写 onFilter 方法,在筛选时自动选中符合条件的行 设置筛选器并隐藏筛选按钮,通过代码完全控制筛选流程 通过按钮点击事件添加筛选条件并执行筛选 代码解析 创建自定义筛选器类 这段代码定义了 SelectionFilter 类,通过原型继承扩展 RowFilterBase。构造函数接收一个 range 参数,指定筛选器的作用范围。 重写 onFilter 方法实现自定义行为 onFilter 方法在筛选执行后自动调用,参数 args 包含: sheet:当前工作表 range:筛选的列范围 filteredRows:被筛选出的行索引数组 action:操作类型,FilterActionType.filter 表示筛选,FilterActionType.unfilter 表示取消筛选 当筛选时,代码遍历所有被筛选的行,使用 setSelection 和 addSelection 方法将这些行选中;取消筛选时,重置选择到第一行。 设置筛选器并隐藏筛选按钮 创建筛选器实例,指定筛选范围为第 2-7 行、第 1 列,然后将其设置给工作表。通过 filterButtonVisible(false) 隐藏筛选按钮,由代码完全控制筛选流程。 通过按钮触发筛选 这段代码通过按钮点击事件触发筛选: 从输入框获取筛选值 使用 removeFilterItems(col) 清除该列的旧筛选条件 创建数字条件,筛选分数小于指定值的行 使用 addFilterItem(col, condition) 添加筛选条件 调用 filter() 执行筛选 清除筛选 点击清除按钮时,调用 removeFilterItems(1) 移除第 1 列的筛选条件,恢复显示所有行。 运行效果 表格中显示学生姓名和分数数据 点击"应用过滤"按钮,筛选分数小于输入值的行,被筛选出的行会自动选中 筛选状态区域显示 "Select the filtered items" 提示 点击"清除过滤"按钮,移除筛选条件,所有行恢复显示,选择重置到第一行 筛选按钮被隐藏,所有筛选操作通过按钮代码控制 API 参考 RowFilterBase 类 筛选器基类,可以通过继承该类创建自定义筛选器。 onFilter 方法 当筛选执行后自动调用,可用于插入自定义逻辑。 参数 args 包含: sheet:当前工作表 range:筛选范围 filteredRows:被筛选出的行索引数组 action:操作类型(filter 或 unfilter) filterButtonVisible 方法 获取或设置筛选按钮的显示状态。 无参数:获取是否显示筛选按钮 一个参数(数字):获取指定列的筛选按钮是否显示 一个参数(布尔):设置所有筛选按钮是否显示 两个参数:设置指定列的筛选按钮是否显示 addFilterItem 方法 向筛选器添加筛选条件。 col:列索引 condition:筛选条件对象 filter 方法 执行筛选操作。 col:可选,指定要筛选的列索引 removeFilterItems 方法 移除指定列的筛选条件。 col:列索引 Condition 类 创建筛选条件。 conditionType:条件类型,如 numberCondition(数字条件) options.compareType:比较运算符,如 lessThan(小于)、greaterThan(大于) options.expected:比较值
var spreadNS = GC.Spread.Sheets; window.onload = function () { var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss")); initSpread(spread); }; function initSpread(spread) { var sheet = spread.getSheet(0); sheet.suspendPaint(); sheet.setColumnWidth(0, 100); sheet.setColumnWidth(1, 200); sheet.setValue(1, 0, "Name"); sheet.setValue(1, 1, "Score"); var score = [ { name: "Simon", score: 59 }, { name: "Jack", score: 70 }, { name: "Lily", score: 86 }, { name: "Bob", score: 54 }, { name: "Lucy", score: 84 }, { name: "John", score: 99 } ]; for (var i = 0, len = score.length; i < len; i++) { var student = score[i]; sheet.setValue(i + 2, 0, student.name); sheet.setValue(i + 2, 1, student.score); } function SelectionFilter(range) { spreadNS.Filter.RowFilterBase.call(this, range); } SelectionFilter.prototype = new spreadNS.Filter.RowFilterBase(); SelectionFilter.prototype.onFilter = function (args) { var sheet = args.sheet, range = args.range, filterRows = args.filteredRows, action = args.action, doFilter = action === spreadNS.Filter.FilterActionType.filter; if (doFilter) { if (range.col < 0) { range.col = 0; range.colCount = sheet.getColumnCount(); } var activeCellSet; for (var i = 0, len = filterRows.length; i < len; i++) { var r = filterRows[i]; for (var c = range.col, len1 = range.col + range.colCount; c < len1; c++) { if (!activeCellSet) { activeCellSet = true; sheet.setSelection(r, c, 1, 1); } else { sheet.addSelection(r, c, 1, 1); } } } sheet.setValue(9, 1, "Select the filtered items"); } else { sheet.setSelection(0, 0, 1, 1); sheet.setValue(9, 1, "No filtered items"); } spread.focus(); }; var actionFilter = new SelectionFilter(new spreadNS.Range(2, 1, 6, 1)); sheet.rowFilter(actionFilter); actionFilter.filterButtonVisible(false); sheet.resumePaint(); document.getElementById("btnFilter").addEventListener('click',function () { var sheet = spread.getActiveSheet(), filter = sheet.rowFilter(), value = parseInt(document.getElementById("filterValue").value, 10), col = 1; if (filter && !isNaN(value)) { filter.removeFilterItems(col); var condition = new spreadNS.ConditionalFormatting.Condition(spreadNS.ConditionalFormatting.ConditionType.numberCondition, { compareType: spreadNS.ConditionalFormatting.GeneralComparisonOperators.lessThan, expected: value }); filter.addFilterItem(col, condition); filter.filter(); sheet.invalidateLayout(); sheet.repaint(); } }); document.getElementById("btnClearFilter").addEventListener('click',function () { var sheet = spread.getActiveSheet(), filter = sheet.rowFilter(); if (filter) { filter.removeFilterItems(1); } }); }
<!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"> <div class="option-row"> <label for="filterValue">分数小于:</label> <input id="filterValue" placeholder="输入过滤分数值" type="text" value="60" /> <input type="button" id="btnFilter" value="应用过滤" title="使用过滤操作过滤分数列。" /> <input type="button" id="btnClearFilter" value="清除过滤" title="清除分数列的过滤。" /> </div> </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; padding: 12px; height: 100%; box-sizing: border-box; background: #fbfbfb; overflow: auto; } .option-row { font-size: 14px; padding: 5px; margin-top: 10px; } input { padding: 4px 6px; } label { display: block; margin-bottom: 6px; } input[type=button] { margin-top: 6px; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }