WPS JS宏编程实战:从VBA迁移到现代JavaScript自动化

📅 2026/8/5 13:40:33
WPS JS宏编程实战:从VBA迁移到现代JavaScript自动化
1. 从VBA到JS为什么WPS宏的脚本语言变了如果你和我一样是个在Office和WPS之间反复横跳的老用户最近打开WPS的宏编辑器时可能会有点懵。那个熟悉的、带着点“上古”气息的VBAVisual Basic for Applications界面不见了取而代之的是一个写着“JS宏”的新玩意儿。这感觉就像你常去的早餐店突然把油条豆浆换成了贝果拿铁东西是好东西但得重新适应。这个变化背后其实是金山办公一个挺有远见的决策。VBA作为微软Office的“亲儿子”虽然功能强大生态成熟但它本质上是一个相对封闭、陈旧的体系。它的语法是几十年前的学习曲线对新手不友好更重要的是它在跨平台尤其是Web和移动端方面有着天生的短板。而WPS选择拥抱JavaScriptJS看中的正是JS的现代、开放与无处不在。JS是Web的通用语言从浏览器到服务器Node.js再到现在的桌面应用Electron等它几乎无处不在。用JS来写宏意味着你学会的这套技能不再局限于WPS表格或文档里它可以直接迁移到网页开发、自动化脚本甚至小程序中技能的通用性大大提升。对于咱们普通用户来说这个切换有好有坏。好处是如果你本来就会一点前端开发或者Node.js那么上手WPS JS宏几乎零门槛甚至有种“降维打击”的快感。坏处是对于习惯了VBA那套对象模型比如Range,Worksheet的老手需要重新学习一套基于WPS Office对象模型的JS API。不过别担心WPS提供的这套API设计上借鉴了VBA和现代JS的优点逻辑是相通的只是写法变了。从“录制宏”这个经典功能你就能看出端倪WPS现在录制出来的是JS代码这本身就是最好的学习资料。2. 你的第一个JS宏从“Hello World”到自动格式化理论说再多不如动手敲一行代码。我们从一个最经典的“Hello World”开始但这次我们让它干点表格里的实事。2.1 环境准备与编辑器初探首先确保你的WPS是最新版本个人版/专业版均可教育版可能功能受限。打开一个空白的WPS表格你会看到顶部菜单栏多了一个“开发工具”选项卡。如果没找到需要去“文件”-“选项”-“自定义功能区”里勾选上。点击“开发工具”-“JS宏”就打开了WPS宏编辑器。这个编辑器界面比较简洁左边是项目浏览器显示你所有的宏模块中间是代码编辑区支持基本的语法高亮和提示右边暂时空着。我们先新建一个模块在项目浏览器右键点击“模块”-“插入”-“模块”然后双击打开它。现在我们来写第一个宏。删除默认的代码输入以下内容function HelloWorld() { let sheet Application.ActiveSheet; let cell sheet.Range(A1); cell.Value2 你好WPS JS宏; cell.Font.Bold true; cell.Font.Size 14; cell.Interior.Color 0xFFC000; // 设置单元格背景为橙色 }写完代码直接点击编辑器顶部的“运行”按钮那个绿色的三角形。然后切回表格窗口你会发现A1单元格已经被填上了加粗的橙色大字。代码解读与避坑点function关键字在WPS JS宏中每一个可执行的宏都是一个JavaScript函数。函数名这里是HelloWorld就是将来你在宏列表里看到的名字。Application对象这是入口相当于VBA里的Application。Application.ActiveSheet获取当前活动的工作表。Range对象和VBA一样用于表示单元格区域。这里我们选中了A1单元格。属性赋值Value2是单元格的值Font和Interior是格式对象。注意颜色值0xFFC000这是一个十六进制的BGR蓝-绿-红值和HTML/CSS里常用的RGB顺序是反的。这是从VBA/COM体系继承过来的“历史包袱”刚开始很容易搞错。WPS的API文档里通常会有颜色常量比如Constants.wdColorOrange但表格里有时直接写数字更直接。你可以用在线RGB到BGR转换工具或者记住常用颜色代码。运行与调试运行后如果没反应首先检查代码是否有语法错误编辑器会有红色波浪线提示。其次确认你选中的是正确的工作表。一个常见的坑是你的代码可能操作的是Sheet1但你当前激活的是Sheet2。2.2 进阶制作一个智能数据格式化宏只会问好可不够我们来点实用的。假设你经常收到一些从系统导出的数据数字没有千位分隔符日期格式混乱你需要快速美化它。function FormatMyData() { let sheet Application.ActiveSheet; let usedRange sheet.UsedRange; // 获取已使用的区域 // 遍历已使用区域的每一行假设第一行是标题 for (let i 2; i usedRange.Rows.Count; i) { let rowRange usedRange.Rows(i); // 假设B列是金额格式化为会计格式千位分隔符两位小数 let amountCell sheet.Cells(i, 2); if (!isNaN(amountCell.Value2) amountCell.Value2 ! ) { amountCell.NumberFormat #,##0.00; // 如果是负数标为红色 if (amountCell.Value2 0) { amountCell.Font.Color 0xFF0000; // 红色 } } // 假设C列是日期统一格式化为“YYYY-MM-DD” let dateCell sheet.Cells(i, 3); let dateValue new Date(dateCell.Value2); if (dateValue instanceof Date !isNaN(dateValue)) { dateCell.NumberFormat yyyy-mm-dd; dateCell.Value2 dateValue; // 重新赋值以确保格式生效 } // 为整行添加细边框 rowRange.Borders.LineStyle 1; // 1代表连续细线 } // 自动调整列宽 usedRange.Columns.AutoFit(); // 冻结首行 sheet.Application.ActiveWindow.SplitRow 1; sheet.Application.ActiveWindow.FreezePanes true; }实操心得UsedRange的妙用与坑UsedRange能快速定位有内容的区域非常方便。但要注意如果之前有单元格被设置过格式然后又清空了内容这个区域可能会比实际数据区域大。更稳妥的做法是结合UsedRange和判断单元格值是否为空来精确控制范围。日期处理的陷阱JS的Date对象对输入字符串的解析能力很强但也因此很不稳定。比如“03/04/2023”在美国是3月4日在欧洲是4月3日。最可靠的方式是如果源数据日期格式固定就用字符串方法如.split(/)拆解后构造Date对象。上述代码中new Date(dateCell.Value2)是一种简单处理对于规整的日期字符串有效。性能优化如果你要处理上万行数据在循环里频繁操作单元格Cells(i, j)会非常慢。WPS JS宏提供了Range.Value2属性可以一次性读取或写入一个二维数组处理完再写回去这是提升性能的关键技巧我们后面会详细讲。AutoFit的副作用自动调整列宽很方便但如果某列有很长的文本可能会把表格撑得非常宽。一个折中的办法是设定一个最大列宽usedRange.Columns.AutoFit();之后再遍历列如果ColumnWidth 50则设置ColumnWidth 50。3. 深入WPS JS对象模型像操作DOM一样操作表格理解了基础操作后我们需要更系统地认识WPS JS宏背后的对象模型。它和VBA对象模型一脉相承但通过JS来调用感觉更像在操作一个特殊的“文档对象模型(DOM)”。3.1 核心对象层级整个模型是一个层次结构最顶层是ApplicationWPS应用本身。Application: 包含所有打开的文档Workbooks、插件、设置等。Workbook: 一个WPS表格文件。关键属性有Worksheets工作表集合、Names定义名称集合。Worksheet: 一个工作表。我们大部分操作在这里进行核心是Range单元格区域。Range: 这是灵魂对象可以是一个单元格也可以是一片区域。几乎所有数据读写、格式设置都通过它。一个关键技巧如何高效地获取和操作Range直接通过Cells(row, column)或Range(A1:B10)获取区域是最常见的。但当你需要基于条件动态确定区域时UsedRange、CurrentRegion当前区域类似VBA中围绕活动单元格的连续数据区域和Find方法就非常有用。function FindAndHighlight() { let sheet Application.ActiveSheet; let searchRange sheet.UsedRange; let foundCell searchRange.Find(目标关键词); if (foundCell) { // 找到后高亮该单元格所在整行 let targetRow foundCell.Row; let entireRow sheet.Rows(targetRow); entireRow.Interior.Color 0xFFFF00; // 黄色高亮 // 进一步可以获取这个“当前区域”假设数据是表格形式 let dataBlock foundCell.CurrentRegion; console.log(找到的数据块有 ${dataBlock.Rows.Count} 行${dataBlock.Columns.Count} 列); } else { Application.Alert(未找到关键词); } }注意WPS JS宏中的Find方法和VBA类似但参数略有不同。它返回一个Range对象如果没找到则返回null。CurrentRegion属性非常智能它能自动识别被空行空列包围的连续数据区域是处理结构化表格的利器。3.2 属性、方法与事件属性Properties描述对象的状态。比如Range.Value2值、Range.Formula公式、Worksheet.Name工作表名。赋值用等号获取值直接引用。方法Methods让对象执行某个动作。比如Range.Copy()复制、Worksheet.Delete()删除、Workbook.Save()保存。调用要加括号有时需要参数。事件Events对象状态改变时触发的动作。例如工作表被激活Worksheet.Activate、单元格内容被改变Worksheet.Change。在JS宏中可以通过Application.WorksheetEvents等对象来绑定事件处理函数实现自动化响应。事件绑定示例实现输入自动大写假设你想让某一列比如A列输入的内容自动转为大写。// 这个函数需要被事件调用 function AutoUppercase() { let sheet Application.ActiveSheet; // 获取刚刚改变的单元格 let target Application.ActiveCell; // 判断是否在A列且不是空值 if (target.Column 1 target.Value2 ! null target.Value2 ! ) { // 将值转为大写 target.Value2 target.Value2.toString().toUpperCase(); } } // 如何绑定事件需要在工作簿打开时执行 function Workbook_Open() { let sheet Application.ThisWorkbook.Worksheets(1); // 获取第一个工作表 // 注意WPS JS宏的事件绑定语法可能与VBA不同这里是一种常见模拟方式 // 更可靠的做法是使用WPS提供的特定事件接口或通过“工作表变化”事件全局监控 // 此处为概念演示实际应用需查阅最新API文档 console.log(工作簿已打开事件监听已设置概念上); }重要提醒WPS JS宏的事件模型可能仍在完善中与VBA的Worksheet_Change事件直接写在工作表代码模块中的方式不同。通常需要在Workbook_Open宏里使用Application.WorksheetEvents.add_Change(yourEventHandlerFunction)这类方式进行绑定。具体语法请务必以WPS官方最新文档为准这是目前最容易踩坑的地方之一。4. 性能优化实战告别卡顿处理万级数据当你尝试用循环处理几千行数据时可能会发现WPS变得“未响应”。这是因为每次读写单元格都是一次跨进程的COM调用可以理解为WPS程序内部的一次远程通信开销巨大。解决方案是批量操作。4.1 读写优化使用数组作为缓冲区核心思想是把Range的数据一次性读入一个JS二维数组在内存中对这个数组进行高速处理然后再一次性写回Range。function ProcessDataInBatch() { let sheet Application.ActiveSheet; let lastRow sheet.Cells(sheet.Rows.Count, 1).End(-4162).Row; // xlUp找到A列最后一行 let lastCol sheet.Cells(1, sheet.Columns.Count).End(-4159).Column; // xlToLeft找到第一行最后一列 if (lastRow 2 || lastCol 1) return; // 无数据 let dataRange sheet.Range(sheet.Cells(1, 1), sheet.Cells(lastRow, lastCol)); // 一次性读取所有数据到数组 let dataArray dataRange.Value2; // 这是一个二维数组dataArray[row][col]索引从1开始 console.log(读取了 ${dataArray.length} 行 ${dataArray[0].length} 列数据); // 在内存中处理数据示例为第3列索引2的数值乘以1.1 for (let i 1; i dataArray.length; i) { // i从1开始跳过标题行 let originalValue dataArray[i][2]; // 第三列 if (typeof originalValue number) { dataArray[i][2] originalValue * 1.1; // 可以在数组里直接标记比如负数标红这里先记下写回时处理 if (dataArray[i][2] 0) { dataArray[i][2] [dataArray[i][2], RED]; // 用数组存储值和颜色标记 } } } // 一次性写回数据 dataRange.Value2 dataArray; // 单独处理格式比如标红这又是一次批量操作 // 我们可以先收集需要标红的单元格地址然后一次性设置格式 // 但更高效的是在写回数据后基于条件格式或再次遍历数组设置 // 这里演示遍历设置对于万行数据格式设置仍可能慢可考虑条件格式 for (let i 1; i dataArray.length; i) { if (Array.isArray(dataArray[i][2]) dataArray[i][2][1] RED) { sheet.Cells(i 1, 3).Font.Color 0xFF0000; // 注意数组索引和行号的转换 } } }关键点与避坑指南数组索引从1开始Value2返回的二维数组行和列索引都是从1开始这与JS常规数组从0开始不同极易导致“off-by-one”错误。dataArray[1][1]对应的是A1单元格。End()方法的方向参数代码中的-4162(xlUp) 和-4159(xlToLeft) 是VBA中的常量值在WPS JS宏中通常可以直接使用这些数值或者查找WPS JS API中是否定义了对应的常量如Constants.xlUp。数据类型保持从Value2读出的数据数字是number文本是string空单元格是null或undefined需测试确认。写回时数组中的null通常会导致单元格被清空。格式与值分离Value2属性只读写值不包含格式。批量修改格式如字体颜色无法通过Value2数组实现需要额外的操作。对于大量单元格的格式设置使用条件格式是性能最好的选择。4.2 利用条件格式替代循环对于像“负数标红”这样的简单规则完全可以用条件格式在瞬间完成无需任何脚本循环。function ApplyConditionalFormatting() { let sheet Application.ActiveSheet; let lastRow sheet.Cells(sheet.Rows.Count, 3).End(-4162).Row; // C列 if (lastRow 2) return; let targetRange sheet.Range(C2:C lastRow); // 清除可能已有的条件格式 targetRange.FormatConditions.Clear(); // 添加新的条件格式当单元格值小于0时字体变红 let condition targetRange.FormatConditions.Add( 2, // Type: xlCellValue (值为2代表基于单元格值) 1, // Operator: xlLess (值为1代表小于) 0 // Formula1: 比较值0 ); condition.Font.Color 0xFF0000; }这比用JS循环遍历设置Font.Color快几个数量级尤其是数据量大的时候。WPS JS宏的FormatConditions对象用法和VBA高度相似。5. 常用脚本模式与实战案例拆解掌握了核心API和性能技巧我们就可以组装一些实用的脚本了。下面分享几个我工作中最常用的模式。5.1 数据清洗与整理模板场景从数据库或网页导出的CSV数据混杂需要清洗。function CleanseImportData() { let sheet Application.ActiveSheet; let usedRange sheet.UsedRange; let data usedRange.Value2; for (let i 1; i data.length; i) { // i1是标题行 for (let j 1; j data[i].length; j) { let val data[i][j]; if (val null || val ) continue; // 1. 去除首尾空格字符串 if (typeof val string) { data[i][j] val.trim(); // 2. 处理数字字符串中的千位分隔符如“1,234” - 1234 if (/^-?\d{1,3}(,\d{3})*(\.\d)?$/.test(data[i][j])) { data[i][j] parseFloat(data[i][j].replace(/,/g, )); } // 3. 将“N/A”、“NULL”等统一转为空 if (data[i][j].toUpperCase() N/A || data[i][j].toUpperCase() NULL) { data[i][j] null; } } // 4. 日期统一化假设原格式为MM/DD/YYYY // 这里逻辑较复杂可根据实际情况编写或调用外部库 } } usedRange.Value2 data; // 5. 删除完全空白的行可选性能要求高时慎用 for (let r usedRange.Rows.Count; r 1; r--) { let rowRange usedRange.Rows(r); let rowVals rowRange.Value2[0]; // 取二维数组的第一行 let isEmpty rowVals.every(cell cell null || cell ); if (isEmpty) { rowRange.Delete(); } } }5.2 自动生成报表与图表场景每月底需要将原始数据表汇总生成带图表的数据透视表和摘要。function GenerateMonthlyReport() { let wb Application.ThisWorkbook; let sourceSheet wb.Worksheets(原始数据); let reportSheet wb.Worksheets.Add(undefined, wb.Worksheets(wb.Worksheets.Count)); // 在最后添加新表 reportSheet.Name 月度报告_ new Date().toISOString().slice(0, 7); // 用年月命名 // 1. 复制数据透视表模板假设有一个隐藏的模板工作表 let templateSheet wb.Worksheets(PivotTemplate); templateSheet.UsedRange.Copy(); reportSheet.Range(A1).PasteSpecial(-4104); // xlPasteAll Application.CutCopyMode false; // 2. 刷新数据透视表的数据源假设透视表在报告表的A1 let pivotTable reportSheet.PivotTables(1); // 获取第一个数据透视表 if (pivotTable) { pivotTable.ChangePivotCache(wb.PivotCaches.Create( 1, // SourceType: xlDatabase sourceSheet.UsedRange, // SourceData 1 // Version: xlPivotTableVersion14 (根据WPS版本调整) )); pivotTable.RefreshTable(); } // 3. 在数据透视表下方生成摘要假设汇总数据在特定位置 let summaryRow pivotTable.TableRange2.Row pivotTable.TableRange2.Rows.Count 2; reportSheet.Cells(summaryRow, 1).Value2 本月总计; // 假设我们需要从透视表结果中计算总和例如求和字段在“总计”列 // 这里需要根据实际透视表布局来定位数据逻辑可能较复杂 // let totalRange ... ; // reportSheet.Cells(summaryRow, 2).Value2 Application.WorksheetFunction.Sum(totalRange); // 4. 基于摘要数据生成一个迷你图或图表 let chartRange reportSheet.Range(reportSheet.Cells(summaryRow - 5, 2), reportSheet.Cells(summaryRow - 1, 2)); // 假设取前5个月的数据 let newChart reportSheet.Shapes.AddChart2(240, 73).Chart; // 添加柱形图参数为样式索引 newChart.SetSourceData(chartRange); newChart.Parent.Left reportSheet.Cells(summaryRow 1, 1).Left; newChart.Parent.Top reportSheet.Cells(summaryRow 1, 1).Top; // 5. 美化调整列宽设置标题样式 reportSheet.UsedRange.Columns.AutoFit(); reportSheet.Cells(1, 1).Font.Size 16; reportSheet.Cells(1, 1).Font.Bold true; }5.3 与外部数据交互读取本地文件WPS JS宏虽然主要操作Office对象但通过一些技巧也能有限度地与外部系统交互。例如读取同目录下的一个JSON配置文件。function ReadConfigFromFile() { // 注意WPS JS宏默认运行在沙盒环境中不能直接访问文件系统。 // 但可以通过“对话框”让用户选择文件或者利用WPS提供的特定API如果存在。 // 以下是一个概念性示例假设未来API支持或通过其他方式实现。 // 假设我们有一个自定义函数 ReadTextFile (这需要WPS提供相应扩展或通过ActiveX等复杂方式目前可能不支持) // let filePath Application.ThisWorkbook.Path \\config.json; // let configText ReadTextFile(filePath); // 伪代码 // let config JSON.parse(configText); // 更现实的方案将配置存储在表格的隐藏工作表或特定单元格中。 let configSheet Application.ThisWorkbook.Worksheets(Config); let serverUrl configSheet.Range(B1).Value2; let apiKey configSheet.Range(B2).Value2; console.log(使用配置服务器 - ${serverUrl}, API密钥 - ${apiKey}); // 然后可以使用这些配置去调用Web API等需要WPS支持网络请求 }重要说明与VBA可以通过Scripting.FileSystemObject自由操作文件不同WPS JS宏出于安全性考虑对本地文件系统的直接访问权限可能受限。更常见的模式是将配置内嵌在文档内隐藏一个工作表存放配置。使用对话框用Application.FileDialog让用户选择文件然后读取其内容对于文本文件如CSV可能支持。调用Web服务如果WPS JS宏环境支持XMLHTTPRequest或FetchAPI则可以与网络API交互实现更动态的数据获取。这需要你确认当前WPS版本的支持情况是另一个需要重点测试的领域。6. 调试、错误处理与代码管理写代码没有不出错的。良好的调试和错误处理习惯能节省你大量抓狂的时间。6.1 调试三板斧console.log()是你的好朋友这是输出信息到WPS宏编辑器“立即窗口”或类似面板的最简单方法。打印变量值、函数执行到哪一步了。let rng sheet.Range(A1); console.log(单元格地址${rng.Address}值${rng.Value2});善用断点在WPS宏编辑器的代码行号左侧点击可以设置断点通常是一个红点。运行宏时执行到断点处会暂停你可以将鼠标悬停在变量上查看当前值也可以使用“监视”窗口添加要监控的变量。Debugger关键字在代码中插入debugger;语句当运行到这行时如果调试器已附加通常F5运行时会自动进入调试模式代码也会中断。这在条件触发时调试非常有用。6.2 健壮的错误处理使用try...catch...finally块来捕获和处理运行时错误避免脚本突然崩溃给用户一个友好的提示。function SafeDataProcess() { try { let sheet Application.ActiveSheet; // 假设这里有一个可能出错的操作比如除零 let result 100 / sheet.Range(B1).Value2; // 如果B1是0或空会出错 sheet.Range(C1).Value2 result; } catch (error) { // 捕获到错误 console.error(处理数据时发生错误, error.message); Application.Alert(操作失败${error.message}\n请检查B1单元格是否有有效数值。, 0, 错误); // 0代表vbOKOnly // 可以选择恢复现场或清理 Application.ThisWorkbook.Saved false; // 标记文档未保存防止数据丢失 } finally { // 无论是否出错都会执行的代码比如关闭打开的资源如果有 console.log(数据处理流程结束。); } }6.3 代码组织与管理当宏越来越多你需要考虑代码结构。模块化将通用的功能封装成独立的函数放在单独的模块文件中。例如创建一个“utils.jsm”模块存放数据验证、格式转换等工具函数。在WPS宏编辑器中你可以通过“项目浏览器”管理多个模块。注释与文档为每个函数写清楚注释说明其目的、参数和返回值。复杂的逻辑在关键步骤旁添加行内注释。版本备份WPS宏是保存在文档内部的。定期将重要的宏代码复制到外部的.js或.txt文件中备份防止文档损坏导致代码丢失。你可以写一个简单的导出函数function BackupAllMacros() { let fso new ActiveXObject(Scripting.FileSystemObject); // 注意此方法在WPS JS宏中可能不可用仅为VBA思路 // ... 遍历ThisWorkbook.VBProject.VBComponents ... // 更实际的做法手动在编辑器中全选代码复制到外部编辑器保存。 }更务实的方法是养成手动备份的习惯或者探索WPS是否提供了宏的导入导出功能。7. 从热词看生态常见问题与资源指北最后结合你提供的那些热搜词聊聊WPS JS宏生态的现状和资源获取。“wps宏编辑器代码大全” / “wps-excel办公js宏编程教程”这反映了大家强烈的学习需求。目前系统的、成体系的WPS JS宏中文教程还不多远不如VBA丰富。最佳学习路径是官方文档首要资源。在WPS宏编辑器中按F1或访问金山办公开发者网站查找“JS宏 API 参考”。这是最权威的。VBA知识迁移因为对象模型相似很多VBA的逻辑和思路可以直接借鉴。遇到一个VBA功能去查对应的JS API即可。录制宏这是学习具体操作对应什么代码的最快方式。社区与论坛在金山办公相关的社区、知乎、CSDN等平台搜索具体问题通常能找到片段代码或思路。“js宏编写函数”这很具体。编写自定义函数UDFUser Defined Function是宏的高级用法可以让你的函数像SUM、VLOOKUP一样在单元格公式里使用。在WPS JS宏中你需要将函数定义为function MyUDF(arg1, arg2) { ... }并确保它被放置在标准模块中而非工作表或工作簿事件模块中。然后就可以在单元格中输入MyUDF(A1, B1)来调用了。“打工工作薄提示包含一个或多个4.0宏” / “microsoft已阻止宏运行”这是兼容性和安全性问题。WPS JS宏.JSM和VBA宏.BAS是两种不同的格式。用WPS创建的JS宏文件在微软Excel中可能无法识别或会被安全警告因为Excel默认只信任VBA宏。反过来包含VBA宏的Excel文件在WPS中打开如果WPS安装了VBA组件通常可以运行。最佳实践是如果协作环境不确定尽量使用JS宏代表未来或者明确告知协作者文件包含的宏类型。“wps破解版免费永久使用” / “银河麒麟wps强制删除”这类词与技术无关但提醒我们务必使用正版软件。破解版不仅法律风险高更可能携带病毒、导致宏功能不稳定或无法使用。WPS个人版对大部分用户免费已包含JS宏功能完全足够学习和一般办公使用。我个人从VBA转向WPS JS宏的过程感觉像是从一条熟悉的乡间小路开上了一条更宽阔、但指示牌还不太多的新高速。一开始需要适应但一旦熟悉了JS的语法和这套API的脾气开发效率其实更高特别是结合现代JS的数组方法、异步思维如果未来支持Promise来处理数据。最大的体会是多利用“录制宏”功能来探索未知对象的属性和方法多把复杂操作拆解成小函数并测试遇到性能瓶颈首先想到批量读写和条件格式。这个生态还在成长一起探索的过程本身就是乐趣所在。