上手开发
准备工作
前置知识
在进行任务前,我们假定你已经对 JavaScript 比较熟悉了,当然如果你对 JavaScript 还没有足够的了解可以参考 附录:JavaScript 上手指南,其中有对 JavaScript 语法知识进行简单的说明,并且列举了一些入门教程网站。
另外,本篇脚本也会用到 脚本 API,利用这些 API 你就可以用 JavaScrip 对表格进行操作:
- Space API 空间站级别的 API,可以获取空间站下的表格,并做后续操作
- Datasheet API 可以获取表格信息,并支持对表格中的视图、字段、记录进行操作
- View API 能够获取视图信息和指定视图下的记录
- Field API 能够获取表格中的字段列信息
- Record API 能够获取每条行记录的具体信息
- UI 相关的 API 比较特殊,能够渲染出可以交互的标准化 UI 组件,例如:文本输入框、字段选择器等,同时还支持渲染指定的内容(文本、表格等)
如果你对 API 还不太熟悉也没有关系,后续实操中我们会大量地使用到它们,所以之后可以在实践中学习并掌握这些 API。
目标
接下来,我们将用 JavaScript 在「脚本」小程序中开发一个查找替换小程序,该功能在很多场景下都特别有用,比如说针对一个专有名词的错误拼写进行批量替换等等。
在开始之前,我们需要对这个任务进行一下具体工作的拆解,我们主要需要实现以下这些步骤:
需要用户输入想要查找和替换那些数据
- 查找值
- 替换值
- 要在哪个字段进行查找替换
提取表格内所有数据,然后找到要所有要查找的数据并替换
输出最终结果
- 替换成功
- 替换失败
下面我们一起开始编写这个小程序吧!示例代码运行方式可以参考 这里
开始编写
利用 Input API 输入数据
Input API 能够要求用户输入内容,方便进行后续的交互。因此,我们可以利用这个 API 要求用户填写必要信息:
const findText = await input.textAsync('请输入想查找的文本:');
const replaceText = await input.textAsync('想替换查找文本为:');
运行效果如下所示:
在上面一步做完之后,我们就可以得到用户想要查找替换的文本了,下一步我们需要让用户指定一个字段,方便我们查找数据,在这里可以使用 input.fieldAsync 来完成:
// 需要通过 Space API 获取当前激活的表格,并作为一个参数传入到 input.fieldAsync
const datasheet = await space.getActiveDatasheetAsync();
const field = await input.fieldAsync("请选择想要查找的维格列名", datasheet);
最终运行效果如下所示:
在表格内匹配数据
在上面一步做完之后,已经完成了所有必要信息的获取,此时我们应该就需要撰写最主要的逻辑部分了。这一部分主要用到的是 JavaScript 的知识。
首先我们需要获取想要查找的维格列的 id
,此时可以根据上面获取到的 field
参数进行获取,如下所示:
// 获取维格列的 id
const fieldId = field.id;
然后再通过 datasheet.getRecordsAsync 获取当前表格所有的记录,同时新建一个数组用于存放需要替换的数据:
// 通过 datasheet API 获取所有的记录对象
const records = await datasheet.getRecordsAsync();
const finalData = [];
此时基本的变量定义已经完成了,下面需要针对 records
进行循环遍历查找,并利用 record.getCellValueString 查找其中指定的 fieldId
数据:
// 遍历 records
for (let record of records) {
const recordId = record.id;
// 获取 record 中指定 field 的数据为 cellValue
const cellValue = record.getCellValueString(fieldId);
}
然后需要用到 JavaScript 中 <String>.replaceAll(findText, replaceText)
来查找替换数据,这个方法可以做到用 replaceText
替换 String 里的所有 findText
。但是由于这个方法只适用于字符串类型,因此需要在使用前判断一下 cellValue
是否为空,如果为空则代表无需查找替换,可直接用 continue 执行下一次循环:
for (let record of records) {
……
// 如果获取的数据为空,则跳出此次循环,直接执行下一次
if (cellValue == null) continue;
// 替换 cellValue 中的 findText 为 replaceText,并使用新的变量——newCellValue
const newCellValue = cellValue.replace(findText, replaceText);
}
最后,我们需要需要 条件语句 判断 newCellValue
是否和 cellValue
相等,如果相等则代表该数据不含 findText
,无需替换;如果不相等,则代表该数据含有 findText
,需要用 newCellValue
替换 cellValue
,这时候就需要新数据到之前定义的 finalData
中。保存的数据格式需要参考 Datasheet API 中的 updateRecordsAsync 参数:
for (let record of records) {
……
// 判断替换前的数据是否和替换后的数据一致
if (cellValue !== newCellValue) {
// 不一致则代表表格内对应记录需要用 newCellValue 替换 cellValue,需要将数据加入到 finalData 数组中
finalData.push({
id: recordId,
valuesMap: { [fieldId]: newCellValue }
})
}
}
最终完整的循环遍历查找代码如下:
// 遍历 records
for (let record of records) {
const recordId = record.id;
// 获取 record 指定 field 的数据为 cellValue
const cellValue = record.getCellValueString(fieldId);
// 如果获取的数据为空,则跳出此次循环,直接执行下一次
if (cellValue == null) continue;
// 替换 cellValue 中的 findText 为 replaceText,并使用新的变量——newCellValue
const newCellValue = cellValue.replaceAll(findText, replaceText);
// 判断替换前的数据是否和替换后的数据一致
if (cellValue !== newCellValue) {
// 不一致则代表表格内对应记录需要用 newCellValue 替换 cellValue,需要将数据加入到 finalData 数组中
finalData.push({
id: recordId,
valuesMap: { [fieldId]: newCellValue }
})
}
}
到此处,我们已经可以找到所有需要替换的数据了,此时只需要用 datasheet.updateRecordsAsync 将 finalData
中的新数据替换旧数据即可:
// 判断 finalData 里面是否有数据,没有数据则无需替换
if (finalData.length) {
await datasheet.updateRecordsAsync(finalData);
}
利用 Output API 输出数据
脚本除了支持 Input API 让用户输入数据,同样也支持 Output API 来让开发者输出数据展示给用户。
在查找替换这个例子中,我们就可以增加替换完成的提示给用户,让体验更加完整:
// 判断 finalData 里面是否有数据,没有数据则无需替换
if (finalData.length) {
await datasheet.updateRecordsAsync(finalData);
output.text('替换完成!')
} else {
output.text('没有找到需要替换的数据')
}
最终效果和完整代码
const findText = await input.textAsync('请输入想查找的文本:');
const replaceText = await input.textAsync('想替换查找文本为:');
// 需要通过 Space API 获取当前激活的表格,并作为一个参数传入到 input.fieldAsync
const datasheet = await space.getActiveDatasheetAsync();
const field = await input.fieldAsync("请选择想要查找的维格列名", datasheet);
// 获取维格列的 id
const fieldId = field.id;
const records = await datasheet.getRecordsAsync();
const finalData = [];
// 遍历 records
for (let record of records) {
const recordId = record.id;
// 获取 record 指定 field 的数据为 cellValue
const cellValue = record.getCellValueString(fieldId);
// 如果获取的数据为空,则跳出此次循环,直接执行下一次
if (cellValue == null) continue;
// 替换 cellValue 中的 findText 为 replaceText,并使用新的变量——newCellValue
const newCellValue = cellValue.replaceAll(findText, replaceText);
// 判断替换前的数据是否和替换后的数据一致
if (cellValue !== newCellValue) {
// 不一致则代表表格内对应记录需要用 newCellValue 替换 cellValue,需要将数据加入到 finalData 数组中
finalData.push({
id: recordId,
valuesMap: { [fieldId]: newCellValue }
})
}
}
// 判断 finalData 里面是否有数据,没有数据则无需替换
if (finalData.length) {
await datasheet.updateRecordsAsync(finalData);
output.text('替换完成!')
} else {
output.text('没有找到需要替换的数据')
}
总结
恭喜你通过「脚本」小程序用不超过 30 行的代码就实现了一个「查找替换」小程序。另外我们还准备了更多 示例 方便你进一步了解「脚本」的用途和更多写法。
通过这篇教程相信你已经了解到了部分 API 的用法,同时这里还有更多 API 等待你进行探索,发掘出更多的用法。