Cannot call method “getEditResponseUrl” of undefin

2019-09-17 23:51发布

I have this function which works but it gets all responses.

function setEditUrl(ss, createDateColumn)
{
  var formURL = 'https://docs.google.com/forms/d/101bMiRw9TQaGbdDc4U_tLAD0QzicqejM9qXOEwJPQKU/viewform';
  var urlColumn = createDateColumn-2;
  var data = ss.getDataRange().getValues();
  var form = FormApp.openByUrl(formURL);
  for(var i = 2; i < data.length; i++) 
  {
    if(data[i][0] != '' && data[i][urlColumn-1] == '') 
    {
      var timestamp = data[i][0];
      var formSubmitted = form.getResponses(timestamp);
      if(formSubmitted.length < 1) continue;
      var editResponseUrl = formSubmitted[0].getEditResponseUrl();
      ss.getRange(i+1, urlColumn).setValue(editResponseUrl);
    }//end of if
  }//end of for
  return;
}// This is the end of the setEditUrl function

As the spreadsheet gets larger I am concerned with performance lag so I want to streamline it and replace the function with one like the one below which just gets the editURL for the last response and only if the sheet cell is empty

function setGoogleFormURL(ss, lastRowInx, createDateColumn)
{
  var urlColumn = createDateColumn-2;

  if (ss.getRange(lastRowInx, urlColumn).getValue() == "") // so that subsequent edits to Google Form don't overwrite editResponseURL
  {
    var form = FormApp.openById('101bMiRw9TQaGbdDc4U_tLAD0QzicqejM9qXOEwJPQKU');
    var formResponses = form.getResponses();
    var lastResponseIndex = form.getResponses.length-1;
    var lastResponse = formResponses[lastResponseIndex];
    var editResponseUrl = lastResponse.getEditResponseUrl();
    var createEditResponseUrl = ss.getRange(lastRowInx, urlColumn);
    createEditResponseUrl.setValue(editResponseUrl);  
  }
  else{} //do nothing

however this seems to break on the getEditResponseUrl. I am getting the following error TypeError: Cannot call method "getEditResponseUrl" of undefined. (line 100, file "Code").

I used @SandyGood 's answer to this post as a reference. I wonder though if her observation about the event trigger is why this is borking. This is the onFormSubmit function I am using to call this and other fucntions.

    function onFormSubmit(e) 
{
 var ss = SpreadsheetApp.getActiveSheet();
 var lastRowInx = ss.getLastRow(); // Get the row number of the last row with content
 var createDateColumn = ss.getMaxColumns(); //CreateDateColumn is currently in AX (Column 50) which is the last/max column position

 var createDate = setCreateDate(ss, lastRowInx, createDateColumn);
 var trackingNumber = setTrackingNumber(ss, lastRowInx, createDateColumn);
 //var editURL = setEditUrl(ss, createDateColumn);
 var editResponseURL = setGoogleFormURL(ss, lastRowInx, createDateColumn);

 }//This is the end of onFormSubmit

I also found a whole bunch of sources 234where they were looking use the URL to append to an email, were more complex than my use case, or were unanswered. I also found some solutions for getting the EditURL by binding the script to the form but since I want to store the value on the sheet it needs to be bound to the sheet rather than the form.

UPDATE: Okay so I tried to bind my script to the form instead of the sheet which allowed me to see the URL but now I have the problem in reverse where the form can't find the spreadsheet methods like .getMaxColumns TypeError: Cannot find function getMaxColumns in object Spreadsheet. (line 40, file "Code") AND .getActiveRange Cannot find method getActiveRange(number). (line 48, file "Code").

Here is the code on the form side

function onFormSubmit(e)
{
  var form = FormApp.getActiveForm();
  var activeFormUrl = form.getEditUrl();
  var ss = SpreadsheetApp.openById(form.getDestinationId());
  var createDateColumn = ss.getMaxColumns(); //CreateDateColumn is currently in AY (Column 51) which is the last/max column position
  var urlColumn = createDateColumn-1; //urlColumn is currently in AX (Column 50) Calculating using it's relative position to createDateColumn Position

  Logger.log(activeFormUrl, createDateColumn, urlColumn);
  var checkLog1 = Logger.getLog();
  Logger.clear();

  if (ss.getActiveRange(urlColumn).getValue() == "") // so that subsequent edits to Google Form don't overwrite editResponseURL
  {
    var editResponseURL = setGoogleFormEditUrl(ss, createDateColumn, activeFormUrl);
    var createEditResponseUrl = ss.getActiveRange(urlColumn);
    createEditResponseUrl.setValue(activeFormUrl);  
  }
  else
  {
    if (ss.getActiveRange(urlColumn).getValue() != activeFormUrl)
    { 
      Logger.log("Something went wrong - URL doesn't match")
      Logger.log(ss.getActiveRange(urlColumn).getValue());
      var checkLog2 = Logger.getLog();
    }
  else {}//do nothing
  }   
}//This is the end of the onFormSubmit function

So I am wondering how I can pass a variable between the form and the sheet. Can I somehow read the form log programmically from the sheet? Can I append the value to the form response array (This would mean a few other edits to the referenced columns but could work). Thoughts @Gerneio , @SandyGood , Anyone else?

UPDATE 2: There seemed to be a conflict with using both the methods from the FormApp and the SpreadsheetApp within the same function.

The solution that worked for me was to modularize the spreadsheet functions out (except the getActiveSheet) and to leave the getEditResponseURL method within the onFormSubmit Function.

The code snippet can be found posted here.

2条回答
ゆ 、 Hurt°
2楼-- · 2019-09-18 00:41

I'd suggest trying to use the onFormSubmit(e) on the form side.

function onFormSubmit(e)
{
  var form = e.source;
  var response = e.response;
  var sheet = SpreadsheetApp.openById(form.getDestinationId());
  var editUrl = response.getEditResponseUrl();
  Logger.log(editUrl); // check the logger to see what results you are getting now
  // Then do whatever operations you need to do...
}

Update:

I'm not so sure why you are having so many problems with this, but I can tell you for sure that it can be done from either side, the Form or Spreadsheet. I just put together a working example with code written on the Spreadsheet side, none what-so-ever on the Form side. Check it out:

function onFormSubmit(e) 
{
  var rng = e.range;
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  var fUrl = ss.getFormUrl();
  var f = FormApp.openByUrl(fUrl);

  var rs = f.getResponses();  
  var r = rs[rs.length - 1]; // Get last response made

  var c = getCellRngByCol(rng, 'Edit Response URL');  
  c.setValue(r.getEditResponseUrl());
}

// Specific for a form submit trigger
// Pass e.range and the name of the column
// to return a single cell
function getCellRngByCol(rng, col)
{
  var aRng = SpreadsheetApp.getActiveSheet().getDataRange();
  var hRng = aRng.offset(0, 0, 1, aRng.getNumColumns()).getValues();
  var colIndex = hRng[0].indexOf(col);

  return SpreadsheetApp.getActiveSheet().getRange(rng.getRow(), colIndex + 1);
}

There were a few small hiccups that I ran into. Firstly, make sure to setup the trigger accordingly. I highly recommend setting up immediate notifications of failures. Secondly, even though the function will rely on the event that is passed, manually run the onFormSubmit(e) method at least once before submitting a form. It will check to see if your script needs any authorization and will request if needed. I'd also recommend that you open up a new form, link a fresh new spreadsheet, and test this code to make sure it works. Then mold the above code to fit your needs.

If you can't get it, then I'll share a working example.

查看更多
We Are One
3楼-- · 2019-09-18 00:45

There seemed to be a conflict with using both the methods from the FormApp and the SpreadsheetApp within the same function.

The solution that worked for me was to modularize the spreadsheet functions out (except the getActiveSheet) and to leave the getEditResponseURL method within the onFormSubmit Function.

The code snippet can be found posted here.

查看更多
登录 后发表回答