跳到主要内容

上手开发

准备工作

前置知识

在进行任务前,我们假定你已经对 JavaScript 比较熟悉了,当然如果你对 JavaScript 还没有足够的了解可以参考 附录:JavaScript 上手指南,其中有对 JavaScript 语法知识进行简单的说明,并且列举了一些入门教程网站。

另外,本篇脚本也会用到 脚本 API,利用这些 API 你就可以用 JavaScrip 对表格进行操作:

  • Space API 空间站级别的 API,可以获取空间站下的表格,并做后续操作
  • Datasheet API 可以获取表格信息,并支持对表格中的视图、字段、记录进行操作
  • View API 能够获取视图信息和指定视图下的记录
  • Field API 能够获取表格中的字段列信息
  • Record API 能够获取每条行记录的具体信息
  • UI 相关的 API 比较特殊,能够渲染出可以交互的标准化 UI 组件,例如:文本输入框、字段选择器等,同时还支持渲染指定的内容(文本、表格等)

如果你对 API 还不太熟悉也没有关系,后续实操中我们会大量地使用到它们,所以之后可以在实践中学习并掌握这些 API。

目标

接下来,我们将用 JavaScript 在「脚本」小程序中开发一个查找替换小程序,该功能在很多场景下都特别有用,比如说针对一个专有名词的错误拼写进行批量替换等等。

在开始之前,我们需要对这个任务进行一下具体工作的拆解,我们主要需要实现以下这些步骤:

  1. 需要用户输入想要查找和替换那些数据

    • 查找值
    • 替换值
    • 要在哪个字段进行查找替换
  2. 提取表格内所有数据,然后找到要所有要查找的数据并替换

    • 循环查找 表格内每一条记录,提取记录中指定字段的数据
    • 判断 这些数据是否含有查找值,如果是的话则需要使用替换值替换,将替换后的数据保存为一个 数组
    • 最后将保存的数据一一替换表格里的需替换数据
  3. 输出最终结果

    • 替换成功
    • 替换失败

下面我们一起开始编写这个小程序吧!示例代码运行方式可以参考 这里

开始编写

利用 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.updateRecordsAsyncfinalData 中的新数据替换旧数据即可:

// 判断 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 等待你进行探索,发掘出更多的用法。