Google表格脚本中的距离未定义错误

时间:2014-07-11 16:33:01

标签: javascript google-maps google-maps-api-3 google-apps-script google-sheets

好的,所以我试图制作一个程序,通过一个分包商及其数据列表,然后制作一个填充了附近的分包商的新表。

我遇到的问题是,当为转包商提供的位置与作业位置相同时,会返回错误。 Sprecifically:' TypeError:无法设置属性" 0.0"未定义到""。'在脚本编辑器的执行脚本中,我在代码失败之前就收到了这个错误。

[14-07-11 12:20:29:418 EDT] Maps.newDirectionFinder() [0 seconds]
[14-07-11 12:20:29:418 EDT] DirectionFinder.setOrigin([Louisville, KY]) [0 seconds]
[14-07-11 12:20:29:419 EDT] DirectionFinder.setDestination([3515 Newburg rd, Louisville, KY]) [0 seconds]
[14-07-11 12:20:29:476 EDT] DirectionFinder.getDirections() [0.057 seconds]
[14-07-11 12:20:30:043 EDT] Execution failed: TypeError: Cannot set property "0.0" of undefined to "". (line 99, file "Code") [6.364 seconds total runtime]

在这种情况下,有什么方法可以让我处理这个错误并让它通过吗?我尝试制作一个dist变量,然后如果返回的距离未定义则将其设置为0,但我仍然收到此错误。

我的程序的完整代码如下。

/**
 * A shared helper function used to obtain the full set of directions
 * information between two addresses. Uses the Apps Script Maps Service.
 *
 * @param {String} origin The starting address.
 * @param {String} destination The ending address.
 * @return {Object} The directions response object.
 */
function getDirections_(origin, destination) {
  var directionFinder = Maps.newDirectionFinder();
  directionFinder.setOrigin(origin);
  directionFinder.setDestination(destination);
  var directions = directionFinder.getDirections();
  if (typeof directions.routes[0] != 'undefined'){
  var dist = directions.routes[0].legs[0].distance.value
  }
  if (dist == 0 && origin == ', ') {
    dist = 100000;
  }
  return directions;
}

/**
 * A special function that runs when the spreadsheet is open, used to add a
 * custom menu to the spreadsheet.
 */
function onOpen() {
  var spreadsheet = SpreadsheetApp.getActive();
  var menuItems = [
    {name: 'Find Local Subs', functionName: 'getSubInfo'}
  ];
  spreadsheet.addMenu('Subcontractors', menuItems);
}

/**
 * A custom function that converts meters to miles.
 *
 * @param {Number} meters The distance in meters.
 * @return {Number} The distance in miles.
 */
function metersToMiles(meters) {
  if (typeof meters != 'number') {
    return null;
  }
  return meters / 1000 * 0.621371;
}

/**
 * A custom function that gets the driving distance between two addresses.
 *
 * @param {String} origin The starting address.
 * @param {String} destination The ending address.
 * @return {Number} The distance in meters.
 */
function drivingDistance(origin, destination) {
  var directions = getDirections_(origin, destination);
  return directions.routes[0].legs[0].distance.value;
}

function drivingDistanceMiles(origin,destination){
  var distMeters = drivingDistance(origin,destination);
  return metersToMiles(distMeters);
}

//start the program and ask for location
function getSubInfo(){
  var job = Browser.inputBox('Job',
                             'Please enter the job name' +
                             ' (for example, "Hamilton WWTP"):',
                             Browser.Buttons.OK_CANCEL);
  if (job == 'cancel') {
    return;
  }  
  var jobLocation = Browser.inputBox('Job Site Location',
                                     'Please enter the address of the job site as accurately as possible' +
                                     ' (for example, "2 Rosewood dr, Wilder, Kentucky"):',
                                     Browser.Buttons.OK_CANCEL);
  if (jobLocation == 'cancel') {
    return;
  } 
  var maxDistance = Browser.inputBox('Max Distance',
                                     'Please enter a maximum allowable distance from a job site that a sub can be' +
                                     '(for example, "50")',
                                     Browser.Buttons.OK_CANCEL);
  if(maxDistance == 'cancel'){
    return
  }
  findSubs(job,jobLocation,maxDistance);
}

function findSubs(job,jobLocation,maxDistance){
  var data = SpreadsheetApp.getActiveSheet().getDataRange().getValues();
  var filteredData = new Array;
  var numFiltered = 0;
  for (row = 0, len = SpreadsheetApp.getActiveSheet().getLastRow(); row < len; row++) {
    var subLocation = data[row][26] + ", " + data[row][27];
      if (drivingDistanceMiles(subLocation,jobLocation) < maxDistance){
        for(currentCol = 0; currentCol < 32; currentCol++){
          filteredData[numFiltered][currentCol] = data[row][currentCol];
        }
        numFiltered++;
      }
  }
  buildSubSheet(job,jobLocation,filteredData,numFiltered);
}

function buildSubSheet(job,jobLocation,filteredData,numFiltered){
  var ss = SpreadsheetApp.getActive();
  var infoSheet = spreadsheet.getSheetByName('2012');
  infoSheet.activate();
  var sheetName = job + " Subs";
  var subsSheet = spreadsheet.getSheetByName(sheetName);
  if (directionsSheet) {
    directionsSheet.clear();
    directionsSheet.activate();
  } else {
    directionsSheet =
        spreadsheet.insertSheet(sheetName, spreadsheet.getNumSheets());
  }
  var sheetTitle = "Subcontractors for " + job;
//  var headers = [
//    [sheetTitle, '', ''],
//    ['Step', 'Distance (Meters)', 'Distance (Miles)']
//  ];
  subsSheet.activate();
  range = subSheet.getRange(2,1,numFiltered,33);
  range.setValues(filteredData);
}

谢谢, 射线

1 个答案:

答案 0 :(得分:0)

查看第99行,报告错误:

      filteredData[numFiltered][currentCol] = data[row][currentCol];

您正在为数组数组(也称为二维数组)分配值。在第93行,您定义了:

  var filteredData = new Array;

所以你有一个阵列可以开始,很好。但是,在为子阵列分配值之前,需要首先以某种方式定义IT。一种方法是在你的循环中 - 但是由于你要按currentCol索引,你应该在currentCol增加的范围内进行索引。类似的东西:

  for (row = 0, len = SpreadsheetApp.getActiveSheet().getLastRow(); row < len; row++) {
    var subLocation = data[row][26] + ", " + data[row][27];
      if (drivingDistanceMiles(subLocation,jobLocation) < maxDistance){
        filteredData[numFiltered] = new Array;
        ...

这将消除你得到的错误。

  

我尝试制作一个dist变量,然后将其设置为等于0   距离返回undefined ...

由于这个bug在别处,你可能不需要担心这个。但即便如此,我希望你不介意一些观察。

if (typeof directions.routes[0] != 'undefined'){

您正在检查未定义(可以检查if (directions.length == 0),这更符合逻辑),但是您实际上并未设置dist = 0,因此{}可能会{{1} }将在第二个dist语句中未定义。由于ifundefined不相等,因此会评估0。没有错误,但它可能没有做你认为应该做的事情。

最好先设置默认值,然后让计算继续进行:

false

如果有路线,则语句 var dist = 0; // set the default value first if (typeof directions.routes[0] != 'undefined'){ dist = directions.routes[0].legs[0].distance.value // no 'var' here } 将更改dist = 100000;,这将获得directions.routes[0].legs[0].distance.value。这是有道理的,因为你试图取消承包商将工地作为他们的地址的情况。但是,如果没有路线),设置return无论如何都不会对返回的dist = 0产生任何影响。相反,您可以嵌套决策,而不必担心它们之外的directions

dist = 0