AI 函数

SpreadJS 提供三种内置 AI 函数,可在单元格中直接调用 AI 能力。SJS.AI.TEXTSENTIMENT 自动分析文本情感倾向并返回分类结果,SJS.AI.TRANSLATE 支持将表格内容翻译为目标语言,SJS.AI.QUERY 通过自然语言描述从数据中提取洞察。这些函数让电子表格具备智能处理能力,适用于客户评论分析、多语言报表生成、智能数据查询等场景。

概述 本 Demo 展示了 SpreadJS 的三种 AI 函数的使用方式,包括文本情感分析、内容翻译和智能查询。Demo 中加载了餐厅评论数据和国家列表数据,通过 AI 函数公式实现情感分类、语言翻译和根据提示查询首都的功能。 实现思路 创建 Spread 工作簿实例,根据运行环境自动切换设计器模式或纯表格模式 通过 injectAI 方法注入服务器回调函数,将 AI 请求转发到后端服务 启用动态数组功能 (allowDynamicArray = true),因为 AI 函数返回动态数组结果 初始化表格数据,包括餐厅评论数据和国家列表数据 设置 AI 函数公式,分别演示三种 AI 功能的应用 代码解析 注入 AI 服务回调 这段代码通过 injectAI 方法将 AI 请求转发到后端服务器。回调函数接收 requestBody 参数,包含 AI 模型需要的请求信息。当服务器返回 429 状态码时,提示用户稍后重试。 文本情感分析 SJS.AI.TEXTSENTIMENT 函数分析 B2:B9 单元格中的餐厅评论,根据情感倾向返回对应标签:正面评论返回 "Positive",负面评论返回 "Negative",中性评论返回 "Neutral"。 内容翻译 SJS.AI.TRANSLATE 函数将 A1:B9 区域的英文内容翻译为简体中文。函数会自动识别源语言,只需指定目标语言代码 "zh-cn"。 智能查询 SJS.AI.QUERY 函数根据 B25 单元格中的提示文本("请给出该国家的首都"),从 A26:A35 区域的国家列表中提取对应的首都信息。 运行效果 表格加载后,C 列自动显示 B 列餐厅评论的情感分析结果(Positive/Negative/Neutral) 第 13 行开始显示将餐厅评论翻译为中文的结果 B26 单元格及下方自动显示各国首都名称,由 AI 根据 A 列国家列表和 B25 的提示生成 所有 AI 函数结果均为动态数组,自动填充到相应区域 AI 函数执行期间会显示 #BUSY! 状态,完成后返回结果 API 参考 injectAI 方法 callbackOrEnv: 可以是环境对象(包含 model、key、basePath)或回调函数 回调函数签名: async (requestBody) => Response 用于配置 AI 服务连接,支持直接配置或通过服务器代理 SJS.AI.TEXTSENTIMENT 函数 array: 要分析的文本区域 positive: 情感为正面时的返回值 negative: 情感为负面时的返回值 neutral: 情感为中性时的返回值(可选) 返回动态数组结果 SJS.AI.TRANSLATE 函数 array: 要翻译的文本区域 language: 目标语言(如 "zh-cn"、"en-us" 或 "中文"、"English") 返回动态数组结果 SJS.AI.QUERY 函数 prompt: 自然语言描述的操作指令 array: 要处理的数据区域 返回动态数组结果 注意: 所有 AI 函数都是异步公式,执行期间返回 #BUSY!,需要启用动态数组功能 (spread.options.allowDynamicArray = true)
let spreadNS = GC.Spread.Sheets; let config = GC.Spread.Sheets.Designer.DefaultConfig; window.onload = function () { const spread = createSpreadAndDesigner(); injectAI(spread); initSpread(spread); }; function createSpreadAndDesigner() { const demoHost = document.getElementById("demo-host"); if (window !== top) { const spread = new GC.Spread.Sheets.Workbook(demoHost, { sheetCount: 2 }); return spread; } else { const designer = new GC.Spread.Sheets.Designer.Designer( demoHost, undefined, undefined, { sheetCount: 2 } ); return designer.getWorkbook(); } } function initSpread(spread) { spread.options.allowDynamicArray = true; var sheet = spread.getActiveSheet(); spread.suspendPaint(); spread.suspendCalcService(); const restaurantReviews = [ ["Username", "Review"], [ "Miss Zhang", "The restaurant offers a beautiful ambiance and attentive service, perfect for family gatherings.", ], [ "Mr. Li", "The food is delicious, but the prices are slightly high, which affects the overall value.", ], [ "Mr. Wang", "It was noisy with poor service and slow food delivery, making for a disappointing experience.", ], [ "Emily", "Loved the unique dishes and inviting atmosphere! Definitely planning to come back.", ], [ "Ms. Chen", "Great flavors and a cozy setting, although the waiting time was a bit too long.", ], [ "Mr. Zhao", "A varied menu with mixed results; some dishes were outstanding while others were just average.", ], [ "George", "The service was extremely poor and the food quality subpar, leaving a very negative impression.", ], [ "Miss Liu", "The food was ordinary and the restaurant was too noisy, which detracted from the overall experience.", ], ]; sheet.setArray(0, 0, restaurantReviews); sheet.setColumnWidth(0, 95) sheet.setColumnWidth(1, 700); sheet.setColumnWidth(2, 160); sheet.setColumnWidth(3, 480); sheet.setValue(0, 2, "TEXTSENTIMENT"); sheet.setFormula(1, 2, '=SJS.AI.TEXTSENTIMENT(B2:B9, "Positive", "Negative", "Neutral")'); sheet.setFormula(0, 3, '="The Formula Is " & FORMULATEXT(C2)'); sheet.setFormula(11, 0, '="The Formula Is " & FORMULATEXT(A13)'); sheet.setFormula(12, 0, '=SJS.AI.TRANSLATE(A1:B9, "zh-cn")'); const countries = [ ["Country", "Please give me the capital of the country"], ["China"], ["India"], ["United States"], ["Indonesia"], ["Pakistan"], ["Brazil"], ["Nigeria"], ["Bangladesh"], ["Russia"], ["Japan"], ]; sheet.setFormula(23, 0, '="The Formula Is " & FORMULATEXT(B26)'); sheet.setArray(24, 0, countries); sheet.setFormula(25, 1, "=SJS.AI.QUERY(B25, A26:A35)"); spread.resumeCalcService(); spread.resumePaint(); } function _getElementById(id) { return document.getElementById(id); } function injectAI(spread) { const serverCallback = async (requestBody) => { const response = await fetch(getAIApiUrl(), { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestBody) }); if (response.status === 429) { alert('The server is busy, please try again later.'); return; } if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response; }; spread.injectAI(serverCallback); } function getAIApiUrl() { return window.location.href.match(/http.+spreadjs\/SpreadJSTutorial\//)[0] + 'server/api/queryAI'; }
<!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"> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-designer/styles/gc.spread.sheets.designer.light.min.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-shapes/dist/gc.spread.sheets.shapes.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-charts/dist/gc.spread.sheets.charts.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-print/dist/gc.spread.sheets.print.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-barcode/dist/gc.spread.sheets.barcode.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-pivot-addon/dist/gc.spread.pivot.pivottables.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-slicers/dist/gc.spread.sheets.slicers.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-formula-panel/dist/gc.spread.sheets.formulapanel.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-io/dist/gc.spread.sheets.io.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-ai-addon/dist/gc.spread.sheets.ai.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$/zh/purejs/node_modules/@grapecity-software/spread-sheets-designer-resources-cn/dist/gc.spread.sheets.designer.resource.cn.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-designer/dist/gc.spread.sheets.designer.all.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/designer/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="demo-host"></div> </div> </body> </html>
body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; } .sample-tutorial { position: relative; height: 100%; overflow: hidden; display: flex; flex-direction: row; } #demo-host { width: 100%; height: 100%; }