0

我有一个谷歌电子表格脚本,我在定时触发器上运行,并选择在失败时接收通知。如果我手动运行它,它可以正常工作,但是当它触发时,我会收到以下通知:

启动函数错误消息触发器结束 2012 年 9 月 28 日晚上 9:45 plotPortfolioData TypeError:无法调用 null 的方法“getSheetByName”。(第 5 行)基于时间的 9/28/12 晚上 9:45

问题是,第 5 行是空的,第 4 行和第 3 行都没有任何“getSheetByName”函数

function plotPortfolioData() {

  // get the Portfolio Chart sheet, and create it if it doesn't exist
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  var portfolioDataSetT = transpose(GetComprehensivePortfolioData(ss));

  varSheetName = "Charts";

  // IMPORTANT
  var firstIndividualStockColumn = 6; // first column in portfolioDataSetT where the actual individual holdings start

  // loop through every value in the portfolio dataset and replace 0 with a blank string (this has the effect of removing
  // any 0 quantity lines from the stacked charts).
  for (var i = 2; i != portfolioDataSetT.length; i++) // start at i = 2 to skip the header and first row (needed for charting)
  {
    for (ii in portfolioDataSetT[i])
    {
      if (portfolioDataSetT[i][ii] <= 0)
      {
        portfolioDataSetT[i][ii] = '';
      }
    }
  }


  if (!ss.getSheetByName(varSheetName))
  {
    var newSheetCreated = true;
    ss.insertSheet(varSheetName);
    var sheet = ss.getSheetByName(varSheetName);
  }
  else
  {
    var sheet = ss.getSheetByName(varSheetName);

    // remove all charts in this existing sheet
    var charts = sheet.getCharts();
    for (var i in charts)
    {
      sheet.removeChart(charts[i]);
    }
    var sheet = ss.getSheetByName(varSheetName);
  }

  // Build the data into the spreadsheet
  var sheetDataRange = sheet.getRange(1, 1, portfolioDataSetT.length, portfolioDataSetT[0].length);
  sheetDataRange.setValues(portfolioDataSetT);

  // prepare the pie chart data
  // start by listing the individual stock names vertically
  var number_of_custom_rows = 1; // the number of manual rows we will add that are not just stocks
  var pieChartSize = (portfolioDataSetT[0].length + 1 - firstIndividualStockColumn) + number_of_custom_rows; // number of holdings in the pie chart
  var pieChartFirstColumn = portfolioDataSetT[0].length+1; // just start after the data pile

  var pieChartStockTitles = sheet.getRange(1,1,1,portfolioDataSetT[0].length).getValues(); // the range of headers
  var pieChartHoldingsRange = sheet.getRange(portfolioDataSetT.length,1,1,portfolioDataSetT[0].length);
  var pieChartHoldings = pieChartHoldingsRange.getValues(); // range of holdings values

  // set the pie chart holdings range number format
  pieChartHoldingsRange.setNumberFormat("$#,###");

  var pieChartDataSpace = sheet.getRange(1,pieChartFirstColumn,pieChartSize,2); // the space where the pie chart data will be printed for graphing (2 columns for name and holding value for each stock)

  for (var i = 0; i != pieChartSize - number_of_custom_rows; i++)
  {
    pieChartDataSpace.getCell(i+1,1).setValue(pieChartStockTitles[0][firstIndividualStockColumn-1+i]); // add the name of the holding to the first pie chart column
    pieChartDataSpace.getCell(i+1,2).setValue(pieChartHoldings[0][firstIndividualStockColumn-1+i]); // add the value of the holding to the 2nd pie chart column
  }

  // now add the custom rows
  pieChartDataSpace.getCell(pieChartSize,1).setValue(pieChartStockTitles[0][4]); // add the cash header
  pieChartDataSpace.getCell(pieChartSize,2).setValue(pieChartHoldings[0][4]); // add the cash amount

  var chartHeight = 400;
  var chartWidth = 500;
  var offset = 3; // buffer region in pixels between charts and the edge of screen

  // hide the numbers for neatness:
  sheet.hideRows(1,portfolioDataSetT.length);

  // performance chart (top left)
  var performanceChart = sheet.newChart()
      .setOption('title', "Portfolio Measurements")
      .setPosition(portfolioDataSetT.length, 1, offset, offset)
      .setOption('height',chartHeight)
      .setOption('width',chartWidth)
      .setOption('lineWidth',1)
      //.setOption('vAxis.format',"$#,###")
      .setOption('vAxis.gridlines.count',10)
      .setOption('theme','maximized')
      .setChartType(Charts.ChartType.LINE)
      .addRange(sheet.getRange("A:D")) // date,cost base, cash-only,cost-base no cash
      .build();
  sheet.insertChart(performanceChart);

  // performance chart (bottom left)
  var compositionChart = sheet.newChart()
      .setChartType(Charts.ChartType.AREA)
      .setOption('title', "Portfolio Composition")
      .setPosition(portfolioDataSetT.length, 1, offset, 2*offset + chartHeight)
      .setOption('height',chartHeight)
      .setOption('width',chartWidth)
      .setOption('theme','maximized')
      .setOption('vAxis.gridlines.count',10)
      .setOption('isStacked',true)
      .setOption('lineWidth',0)
      .setOption('areaOpacity',0.8)
      //.setOption('vAxis.format',"$#,###")
      .addRange(sheet.getRange("A:A")) // dates
      .addRange(sheet.getRange("E:E")) // cash balance
      .addRange(sheet.getRange(1,firstIndividualStockColumn,portfolioDataSetT.length,portfolioDataSetT[0].length + 1 - firstIndividualStockColumn)) // add the individual stock holdings
      .build();
  sheet.insertChart(compositionChart);

  // pie chart portfolio composition (top right)
  var pieChart = sheet.newChart()
      .setChartType(Charts.ChartType.PIE)
      .setOption('title', "Portfolio Composition")
      .setPosition(portfolioDataSetT.length, 1, 2*offset + chartWidth, offset)
      .setOption('height',chartHeight)
      .setOption('width',chartWidth)
      .setOption('pieSliceText','label')
      .setOption('is3D',true)
      .addRange(sheet.getRange(1,pieChartFirstColumn,pieChartSize,1)) // add the individual stock names
      .addRange(sheet.getRange(1,pieChartFirstColumn+1,pieChartSize,1)) // add the individual holding values
      .build();
  sheet.insertChart(pieChart);

  // fix up number formatting
  var sheetWholeRange = sheet.getDataRange();
  sheetWholeRange.setNumberFormat("$#,###"); // set all numbers to currency
  var sheetDateRange = sheet.getRange("A:A");
  sheetDateRange.setNumberFormat("d-LLL-YYYY"); // set date column formatting
}

那么,发生了什么事,我应该如何调试这个问题?当我运行它时,它工作正常!

4

1 回答 1

1

似乎问题出在以下行

var ss = SpreadsheetApp.getActiveSpreadsheet();

当您手动启动此脚本时,我假设您以电子表格脚本的形式从Spreadsheet Script EditorSpreadsheet Script Manager. 在这种情况下,getActiveSpreadsheet返回现在打开的活动工作表并且ss没有null- 一切都很好。

当您从定时触发器启动相同的脚本时,没有任何活动的电子表格并且getActiveSpreadsheet()返回null. 在那之后,可能在GetComprehensivePortfolioData方法内部的某个地方有一条线ss.getSheetByName('...')。在这一行中抛出异常。

我认为,该GetComprehensivePortfolioData方法在一个单独的gs文件中,第一次getSheetByName调用在第 5 行。

于 2012-09-28T12:07:17.153 回答