You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过PropertiesService传递表格数据至客户端并规避冲突?

问题与优化需求

我现有函数能正常运行,但不确定是否符合最佳实践——担心其他地方用PropertiesService存储数据时会出现冲突。

原流程

  • 用户勾选某行末尾的复选框
  • 事件触发函数将该行数据存入脚本的PropertiesService
  • 打开模态对话框,调用另一函数获取PropertiesService中的首个属性并清空所有数据

希望改成通过key获取数据,且无需多次调用服务器的方案。

安装型触发器触发的函数

function ajustarParcela() {
  const crSht = ss.getSheetByName(crShtName);
  let row = 0;
  let dados = crSht.getRange(6, 1, crSht.getLastRow(), crSht.getLastColumn()).getValues();
  const headers = dados[0];

  dados = dados.filter((e, i) => {
    if (e[18] === true) {
      row = i + 6;
      return e;
    }
  });
  if (row < 7) {
    Browser.msgBox('请选择一笔分期进行调整。');
    return;
  }
  if (dados.length > 1) {
    Browser.msgBox('无法同时调整多笔分期。');
    return;
  }
  dados.unshift(headers);

  // HTML弹窗
  const ui = SpreadsheetApp.getUi();
  const htmlWindow = HtmlService.createTemplateFromFile("Pagina_Baixar");
  htmlWindow.dados = JSON.stringify(dados);

  const htmlOutput = htmlWindow.evaluate().setWidth(450).setHeight(570);
  ui.showModalDialog(htmlOutput, "核销分期");
  crSht.getRange(row, 19).clearContent();
}

客户端函数

<script>
  const getDadosParcela = () => {
    const dadosParcela = <?!= dados ?>; // 预期dadosParcela是数组格式
    console.log(dadosParcela);
  }

  getDadosParcela(); // 测试用
</script>

JS文件引入方式

...
<head>
  <meta charset="utf-8">
  <base target="_top">
  <?!= HtmlService.createHtmlOutputFromFile('Pagina_Baixar_css').getContent(); ?>
  <?!= HtmlService.createHtmlOutputFromFile('Pagina_Baixar_js').getContent(); ?>
</head>
...

尝试后的报错

出现语法错误:Uncaught SyntaxError: Unexpected token '<'

错误截图


解决方案

1. 修复模板语法报错问题

Google Apps Script的模板语法<?!= ... ?>仅在被createTemplateFromFile加载的主HTML文件中生效,单独引入的JS/CSS文件不会被解析模板标签,这就是你看到<符号报错的原因。

解决办法:

  • 将需要接收模板数据的逻辑移到主HTML文件的<script>标签中
  • 或者在主HTML里把数据挂载到全局对象,再让外部JS文件读取

示例:
主HTML文件(Pagina_Baixar.html):

...
<head>
  <meta charset="utf-8">
  <base target="_top">
  <?!= HtmlService.createHtmlOutputFromFile('Pagina_Baixar_css').getContent(); ?>
  <script>
    // 将模板数据挂载到全局对象
    window.parcelaDados = <?!= dados ?>;
  </script>
  <?!= HtmlService.createHtmlOutputFromFile('Pagina_Baixar_js').getContent(); ?>
</head>
...

外部JS文件(Pagina_Baixar_js.html):

const getDadosParcela = () => {
  const dadosParcela = window.parcelaDados;
  console.log(dadosParcela);
}

getDadosParcela();

2. 无冲突的替代PropertiesService方案

通过模板直接传递数据的方式,完全不需要依赖PropertiesService,从根源上避免了数据冲突问题——数据在服务器渲染HTML时直接注入,一次请求完成,无需二次调用服务器拉取数据。

如果后续需要区分多组数据,只需在模板中传递带key的对象即可:

// 服务器端
htmlWindow.appData = JSON.stringify({
  parcela: dados,
  otherBizData: otherValue
});

// 主HTML
window.globalAppData = <?!= appData ?>;

// 外部JS
const parcelaDados = window.globalAppData.parcela;
const otherData = window.globalAppData.otherBizData;

内容的提问来源于stack exchange,提问作者onit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 22:20:47