XMATCH 函数

XMATCH 函数用于在数组或单元格区域中搜索指定项,并返回该项的相对位置。作为 MATCH 函数的增强版本,XMATCH 支持精确匹配、近似匹配、通配符匹配以及反向搜索。在实际应用中,XMATCH 常与 XLOOKUP 函数配合使用,实现灵活的数据查询和计算。

概述 本 Demo 展示了 XMATCH 函数的多种用法,包括基本精确匹配、近似匹配、查找多个值以及与 XLOOKUP 配合使用的实际业务场景。Demo 通过 4 个工作表分别演示了这些功能特性:员工佣金计算、基本精确匹配、基本近似匹配以及查找多个值。 实现思路 创建工作簿并启用动态数组支持(XMATCH 需要此功能) 定义命名样式(标题样式、公式样式、表格样式等) 创建 4 个工作表,分别展示不同用法: Sheet1:实际业务场景(员工佣金计算) Sheet2:基本精确匹配 Sheet3:基本近似匹配 Sheet4:查找多个值 为每个工作表设置数据、样式和 XMATCH 公式 代码解析 启用动态数组支持 XMATCH 函数需要启用动态数组功能才能正常工作。 实际业务场景:员工佣金计算 这段代码展示了 XMATCH 与 XLOOKUP 配合使用的实际场景。XMATCH 根据员工收入在佣金表中查找对应的类别(使用近似匹配,返回不超过收入的最大销售额对应的类别),然后 XLOOKUP 根据类别查找佣金百分比,最后计算佣金金额。 基本精确匹配 在电影列表中查找"玩具总动员"的位置。省略 match_mode 参数时,默认使用精确匹配(match_mode = 0)。 基本近似匹配 在销售额列中查找 400 的位置。match_mode 参数为 1,表示如果找不到精确匹配,返回下一个最大的项。 查找多个值 同时查找排名 5、4、1 在排名列中的位置。XMATCH 支持传入数组 {5,4,1} 作为查找值,返回多个匹配结果。 运行效果 第一个工作表展示了员工佣金计算场景,表格自动根据收入计算佣金类别、百分比和金额 第二个工作表演示精确匹配,输入"玩具总动员"后显示其在电影列表中的位置(第 4 行) 第三个工作表演示近似匹配,输入销售额 400 后返回最接近且大于它的位置(第 3 行,销售额 673) 第四个工作表演示多值查找,同时查找排名 5、4、1 的位置,返回多个结果 API 参考 XMATCH 函数语法 lookup_value:查找值,可以是单个值或数组 lookup_array:要搜索的数组或区域 match_mode(可选): 0 - 精确匹配(默认值),找不到则返回 #N/A -1 - 精确匹配或下一个最小项 1 - 精确匹配或下一个最大项 2 - 通配符匹配 search_mode(可选): 1 - 从第一项开始搜索(默认值) -1 - 从最后一项开始反向搜索 2 - 升序二分查找 -2 - 降序二分查找
window.onload = function() { var spread = new GC.Spread.Sheets.Workbook(_getElementById("ss")); spread.options.allowDynamicArray = true; initStyles(spread); initSpread(spread); }; function initSpread(spread) { spread.setSheetCount(4); spread.suspendPaint(); spread.suspendCalcService(); initSheet1(spread.getSheet(0)); initSheet2(spread.getSheet(1)); initSheet3(spread.getSheet(2)); initSheet4(spread.getSheet(3)); spread.resumeCalcService(); spread.resumePaint(); } function initStyles(spread) { var introStyle = new GC.Spread.Sheets.Style(); introStyle.name = 'intro'; introStyle.font = 'normal bold 16px Segoe UI'; introStyle.foreColor = "#172b4d"; spread.addNamedStyle(introStyle); var introStyle1 = new GC.Spread.Sheets.Style(); introStyle1.name = 'intro1'; introStyle1.font = 'normal bold 14px Calibri'; introStyle1.hAlign = 0; introStyle1.vAlign = 1; introStyle1.foreColor = "#172b4d"; spread.addNamedStyle(introStyle1); var formulaStyle = new GC.Spread.Sheets.Style(); formulaStyle.name = 'formula'; formulaStyle.font = 'normal bold 12px Consolas'; formulaStyle.foreColor = "#c00000"; introStyle1.vAlign = 1; spread.addNamedStyle(formulaStyle); var tableHeaderStyle = new GC.Spread.Sheets.Style(); tableHeaderStyle.name = 'tableHeader'; tableHeaderStyle.font = "normal bold 14.7px Calibri"; tableHeaderStyle.hAlign = 1; tableHeaderStyle.backColor = "#d9e1f2"; spread.addNamedStyle(tableHeaderStyle); var tableContentStyle = new GC.Spread.Sheets.Style(); tableContentStyle.name = 'tableContent'; tableContentStyle.font = "normal normal 14.7px Calibri"; tableContentStyle.hAlign = 1; spread.addNamedStyle(tableContentStyle); var sourceStyle = new GC.Spread.Sheets.Style(); sourceStyle.name = 'source'; sourceStyle.hAlign = 0; sourceStyle.backColor = "#fce8ce"; spread.addNamedStyle(sourceStyle); var resultStyle = new GC.Spread.Sheets.Style(); resultStyle.name = 'result'; resultStyle.hAlign = 0; resultStyle.backColor = "#e2efda"; spread.addNamedStyle(resultStyle); } function initSheet1(sheet) { sheet.name('使用案例'); var table1Source = { name: '员工季度佣金', data: [ { salesRap: 'Jim', quarter: 'Q1', revenue: 351 }, { salesRap: 'Jim', quarter: 'Q2', revenue: 210 }, { salesRap: 'Kevin', quarter: 'Q1', revenue: 687 }, { salesRap: 'Sarah', quarter: 'Q1', revenue: 300 }, { salesRap: 'Sarah', quarter: 'Q2', revenue: 809 }, { salesRap: 'Kevin', quarter: 'Q2', revenue: 285 }, { salesRap: 'Bob', quarter: 'Q1', revenue: 110 } ] }; sheet.addSpan(1, 1, 1, 6); sheet.setValue(1, 1, table1Source.name); sheet.getCell(1, 1).hAlign(1).font("normal bold 15px Calibri"); sheet.setColumnWidth(1, 83); sheet.setColumnWidth(2, 73); sheet.setColumnWidth(3, 77); sheet.setColumnWidth(4, 122); sheet.setColumnWidth(5, 134); sheet.setColumnWidth(6, 98); var table1 = sheet.tables.add('Table1', 2, 1, 7, 6); table1.style(GC.Spread.Sheets.Tables.TableThemes.medium2); var table1Column1 = new GC.Spread.Sheets.Tables.TableColumn(1, "salesRap", "销售代表"); var table1Column2 = new GC.Spread.Sheets.Tables.TableColumn(2, "quarter", "季度"); var table1Column3 = new GC.Spread.Sheets.Tables.TableColumn(3, "revenue", "收入"); var table1Column4 = new GC.Spread.Sheets.Tables.TableColumn(4, null, "佣金类别"); var table1Column5 = new GC.Spread.Sheets.Tables.TableColumn(5, null, "佣金百分比", "0%"); var table1Column6 = new GC.Spread.Sheets.Tables.TableColumn(6, null, "佣金"); table1.autoGenerateColumns(false); table1.bind([table1Column1, table1Column2, table1Column3, table1Column4, table1Column5, table1Column6], 'data', table1Source); var table2Source = { name: "佣金表", data: [ { category: 1, sales: 100, percentage: 0.05 }, { category: 2, sales: 200, percentage: 0.1 }, { category: 3, sales: 400, percentage: 0.15 }, { category: 4, sales: 800, percentage: 0.20 } ] }; sheet.addSpan(1, 8, 1, 3); sheet.setValue(1, 8, table2Source.name); sheet.getCell(1, 8).hAlign(1).font("normal bold 15px Calibri"); sheet.setColumnWidth(8, 88); sheet.setColumnWidth(9, 57); sheet.setColumnWidth(10, 91); var table2 = sheet.tables.add('Table2', 2, 8, 4, 3); table2.style(GC.Spread.Sheets.Tables.TableThemes.medium2); var table2Column1 = new GC.Spread.Sheets.Tables.TableColumn(1, "category", "类别"); var table2Column2 = new GC.Spread.Sheets.Tables.TableColumn(2, "sales", "销售额"); var table2Column3 = new GC.Spread.Sheets.Tables.TableColumn(3, "percentage", "百分比", "0%"); table2.autoGenerateColumns(false); table2.bind([table2Column1, table2Column2, table2Column3 ], 'data', table2Source); table1.setColumnDataFormula(3, '=XMATCH([@收入],Table2[销售额],-1,1)'); table1.setColumnDataFormula(4, '=XLOOKUP([@[佣金类别]],Table2[类别],Table2[百分比],0,0,1)'); table1.setColumnDataFormula(5, '=[@收入]*[@[佣金百分比]]'); } function initSheet2(sheet) { sheet.name('基本精确匹配'); var intro = '#1 - 基本精确匹配'; var formula = '=XMATCH(H5,B6:B10)'; sheet.setValue(1, 1, intro); sheet.setStyle(1, 1, 'intro'); sheet.setValue(2, 1, formula); sheet.setStyle(2, 1, 'formula'); var data = [ ["电影", "年份", "排名", "销售额"], ["冰血暴", 1996, 5, 61], ["洛城机密", 1997, 4, 126], ["灵异第六感", 1999, 1, 673], ["玩具总动员", 1995, 2, 362], ["不可饶恕", 1992, 3, 159] ]; sheet.setArray(4, 1, data); for (var i = 0; i < data.length; i++) { for (var j = 0; j < data[i].length; j ++) { var styleName; if (i === 0) { styleName = 'tableHeader'; } else { styleName = 'tableContent'; } sheet.setStyle(4 + i, 1 + j, styleName); } } sheet.setColumnWidth(1, 126); sheet.setValue(4, 6, '电影'); sheet.setStyle(4, 6, 'source'); sheet.setValue(5, 6, '位置'); sheet.setStyle(5, 6, 'result'); sheet.setValue(4, 7, '玩具总动员'); sheet.setFormula(5, 7, formula); } function initSheet3(sheet) { sheet.name('基本近似匹配'); var intro = '#2 - 基本近似匹配'; var formula = '=XMATCH(H5,E6:E10,1)'; sheet.setValue(1, 1, intro); sheet.setStyle(1, 1, 'intro'); sheet.setValue(2, 1, formula); sheet.setStyle(2, 1, 'formula'); var data = [ ["电影", "年份", "排名", "销售额"], ["冰血暴", 1996, 5, 61], ["洛城机密", 1997, 4, 126], ["灵异第六感", 1999, 1, 673], ["玩具总动员", 1995, 2, 362], ["不可饶恕", 1992, 3, 159] ]; sheet.setArray(4, 1, data); for (var i = 0; i < data.length; i++) { for (var j = 0; j < data[i].length; j ++) { var styleName; if (i === 0) { styleName = 'tableHeader'; } else { styleName = 'tableContent'; } sheet.setStyle(4 + i, 1 + j, styleName); } } sheet.setColumnWidth(1, 126); sheet.setValue(4, 6, '销售额'); sheet.setStyle(4, 6, 'source'); sheet.setValue(5, 6, '位置'); sheet.setStyle(5, 6, 'result'); sheet.setValue(4, 7, 400); sheet.setFormula(5, 7, formula); } function initSheet4(sheet) { sheet.name('多个值'); var intro = '#3 - 多个值'; var formula = '=XMATCH({5,4,1},D6:D10)'; sheet.setValue(1, 1, intro); sheet.setStyle(1, 1, 'intro'); sheet.setValue(2, 1, formula); sheet.setStyle(2, 1, 'formula'); var data = [ ["电影", "年份", "排名", "销售额"], ["冰血暴", 1996, 5, 61], ["洛城机密", 1997, 4, 126], ["灵异第六感", 1999, 1, 673], ["玩具总动员", 1995, 2, 362], ["不可饶恕", 1992, 3, 159] ]; sheet.setArray(4, 1, data); for (var i = 0; i < data.length; i++) { for (var j = 0; j < data[i].length; j ++) { var styleName; if (i === 0) { styleName = 'tableHeader'; } else { styleName = 'tableContent'; } sheet.setStyle(4 + i, 1 + j, styleName); } } sheet.setColumnWidth(1, 126); sheet.setValue(4, 6, '排名'); sheet.setStyle(4, 6, 'source'); sheet.setValue(5, 6, '位置'); sheet.setStyle(5, 6, 'result'); sheet.setValue(4, 7, '{5,4,1}'); sheet.setFormula(5, 7, formula); } function _getElementById(id) { return document.getElementById(id); }
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta name="spreadjs culture" content="zh-cn" /> <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$/spread/source/js/license.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="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> </body> </html>
input[type="text"] { width: 200px; margin-right: 20px; } label { display: inline-block; width: 110px; } .sample-tutorial { position: relative; height: 100%; overflow: hidden; } .sample-spreadsheets { width: 100%; height: 100%; overflow: hidden; float: left; } label { display: block; margin-bottom: 6px; } input { padding: 4px 6px; } input[type=button] { margin-top: 6px; display: block; width:216px; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; } code { border: 1px solid #000; }