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

GAS Web应用图表渲染报错及HTML样式引用问题求助

Google Apps Script Web应用:解决下拉筛选图表的"Cannot read properties of undefined (reading 'length')"报错

问题场景

基于Google Apps Script开发Web应用,目标实现带下拉筛选的图表功能:下拉选项包含All、North、South,页面加载默认渲染All对应数据,选择选项点击按钮后筛选图表。目前遇到两个核心问题:

  1. 报错Cannot read properties of undefined (reading 'length'),导致开发停滞;
  2. 移除<?!= include('page_style'); ?>标签后图表可正常渲染,但CSS样式失效;重新添加该标签则样式正常,但报错重现。

报错原因分析

  1. 模板变量与DOM元素ID冲突:HTML中<select>元素的ID设为dg,和模板中传入的下拉选项数组变量dg重名。模板渲染循环<? for(var i=0; i< dg.length;i++){ ?>时,dg被解析为DOM元素而非模板变量,因此读取length属性时触发undefined报错。
  2. 缺失关键函数:get_dg函数中调用了return_array.filter(uniquelists),但未提供uniquelists去重函数的实现,导致返回数组异常,间接引发模板变量赋值错误。
  3. doPost方法变量覆盖:doPost函数中先声明var dg = e.parameters.dg.toString();,之后又重新声明var dg = get_dg();,虽不直接引发当前报错,但属于不良编码习惯,可能导致后续逻辑问题。

修复方案

1. 解决变量名冲突

修改HTML中<select>的ID,避免与模板变量dg重名,例如改为select_dg。

2. 补充缺失的去重函数

在GAS脚本中添加uniquelists函数,确保get_dg返回正确的唯一值数组。

3. 修复doPost变量覆盖问题

将doPost中接收请求参数的变量名改为selectedDg,避免覆盖后续获取的下拉选项数组。

4. 完善图表筛选逻辑

修改draw_linechart函数,使其接收筛选参数,返回对应的数据;同时在HTML中绑定按钮点击事件,触发图表重新渲染。

完整修正代码

GAS脚本

function doGet(e){
  var html = HtmlService.createTemplateFromFile('pages');            
  var dg = get_dg();
  html.dg = dg;  
  return html.evaluate();       
}

function doPost(e){  
  var selectedDg = e.parameters.s_d; // 对应HTML中select的name属性s_d
  var html = HtmlService.createTemplateFromFile('pages');             
  var dg = get_dg();  
  html.dg = dg;
  html.selectedDg = selectedDg; // 将选中的筛选值传入模板
  return html.evaluate();
}

function getUrl() {
 return ScriptApp.getService().getUrl(); 
}

function include(filename) {
  return HtmlService.createHtmlOutputFromFile(filename)
      .getContent();
}

// 补充去重函数,实现数组去重
function uniquelists(value, index, self) {
  return self.indexOf(value) === index;
}

function get_dg(){
  var d_useremail = Session.getActiveUser().getEmail();  
  var ss = SpreadsheetApp.openById('XXXXXXXXX');
  var metrics_sheet = ss.getSheetByName('sheet');
  var getlastrow = metrics_sheet.getLastRow();  
  var return_array = [];  
  for(var i = 2; i <= getlastrow; i++)
  {
      if(metrics_sheet.getRange(i, 1).getValue() === d_useremail) {                
        return_array.push(metrics_sheet.getRange(i, 2).getValue());
      }
  }
  Logger.log(return_array);
  return return_array.filter(uniquelists);
}

// 修改为接收筛选参数的图表数据获取函数
function draw_linechart(filterValue = 'All'){
  var ss = SpreadsheetApp.openById('XXXXXXXXXXXXXXX');
  var metrics_sheet = ss.getSheetByName('test_chart');
  var c_data = metrics_sheet.getRange("A1:B").getValues();
  
  // 根据筛选值过滤数据(假设第一列为区域标识,第二列为数值,可根据实际结构调整)
  if(filterValue !== 'All'){
    c_data = c_data.filter(row => row[0] === filterValue);
    // 若无匹配数据,保留表头避免图表报错
    if(c_data.length === 0){
      c_data = [c_data[0]];
    }
  }
  
  var c_data1 = JSON.stringify(c_data);   
  return c_data1;
}

page_style CSS

.c_line_chart{
  display:flex;
  width:90%;
  height:90px;
  margin-left:35px;    
}

pages HTML

<!DOCTYPE html>
<html>  
  <head>
    <base target="_top">    
    <?!= include('page_style'); ?>
    <script src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">   
      google.charts.load('current',{'packages':['corechart']});
      // 获取页面加载时的筛选值,默认All
      var initialFilter = "<?= selectedDg || 'All' ?>";
      google.charts.setOnLoadCallback(() => drawchart(initialFilter));

      function drawchart(filterValue){
        google.script.run.withSuccessHandler(displaychart).draw_linechart(filterValue);
      }

      function displaychart(c_data1){
        var chartdata = new google.visualization.arrayToDataTable(JSON.parse(c_data1));
        console.log(chartdata);        

        var options={
          title: 'Checking the Charts',
          is3D: true
        }

        var chart = new google.visualization.LineChart(document.getElementById('line_chart'));
        chart.draw(chartdata,options);
      }

      // 绑定按钮点击事件,触发图表筛选渲染
      document.addEventListener('DOMContentLoaded', function() {
        document.getElementById('btn').addEventListener('click', function() {
          var selectedValue = document.getElementById('select_dg').value;
          drawchart(selectedValue);
        });
      });
      </script>
  </head>
<body>
<?var url = getUrl(); ?>
<form method="post" action="<?= url ?>" >
<div class="filter_container">
      <br><br>
      <div class="box1">      
        <label class="label_"> DGraph </label> <br>
        <!-- 修改select的ID为select_dg,避免和模板变量dg冲突 -->
        <select name="s_d" id="select_dg" class="cselect">
        <option value="All" <?= selectedDg === 'All' || !selectedDg ? 'selected' : '' ?>>All</option>
        <? for(var i=0; i< dg.length;i++){ ?>
        <option value="<?= dg[i] ?>" <?= selectedDg === dg[i] ? 'selected' : '' ?>><?= dg[i] ?></option>
        <? } ?>
        </select><br><br>
      </div>
<button id ="btn" type="button">Click!</button>
</div>
<div id ="line_chart" class="c_line_chart"></div>
</form>
</body>
</html>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 17:44:53