Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot call Google Script API Functions from Web App (TypeError: Cannot read property 'run' of undefined)

I had a google apps script working fine for months and it suddenly stopped working. I'm wondering if Google deprecated some part of my code or something.

This is the link to the file: Click here to view Google Spreadsheet File

The google script code is apparently failing when trying to call a google script function from an HTML file. This is the line of code that fails.

google.script.run.importCSVData(id);

The lines fails and catches the following error:

TypeError: Cannot read property 'run' of undefined

Like I said, I had this code working fine for months and it suddenly stopped working.

(FYI... The purpose of this code is to upload a CSV file into the tab "Archivo Plano ADN". To run this code, one must simply select "Importar Archivo CSV" --> "Importar Archivo..." from the upper menu. When prompted to select file, select any .csv file. The csv file must be separated by ;)


My Google Spreadsheet File has three code files ("Code.gs", "CodeImport.gs" and "Picker.html")

Let me give you the code of each:

Code.gs:

function onOpen() {

  var me = Session.getEffectiveUser();
  if (me.getEmail() == "[email protected]") {
    var ui = SpreadsheetApp.getUi();
    ui.createMenu('Protected Ranges')
    .addItem('Remove Protection', 'menuItem1')
    .addItem('Copy Protected Ranges To Another Sheet', 'menuItem2')
    .addItem('Copy SM Protected Ranges to all SA sheets', 'menuItem3')
    .addToUi();

    ui.createMenu('Importar Archivo CSV')
      .addItem('Importar Archivo...', 'showPicker')
      .addToUi();

    ui.cre
  } else {
    SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
      .createMenu('Importar Archivo CSV')
      .addItem('Importar Archivo...', 'showPicker')
      .addToUi();
  }

}

CodeImport.gs:

function importCSVData(id) {
try {  
    var file = DriveApp.getFileById(id);
    var csvData = Utilities.parseCsv(file.getBlob().getDataAsString("ISO-8859-1"),";");
    var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Archivo Plano ADN");
    sheet.getRange("A:U").clear();
    sheet.getRange("G:G").setNumberFormat('@STRING@');
    Logger.log("yes");

    sheet.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);

    file.setTrashed(true);

    SpreadsheetApp.getUi().alert("Archivo Importado con éxito");

  } catch (e) {
    MailApp.sendEmail(Session.getEffectiveUser().getEmail(), "Error report jaja - sonríele a la vida!", 
      "\r\nMessage: " + e.message
      + "\r\nFile: " + e.fileName
      + "\r\nLine: " + e.lineNumber);
  }
}

function showPicker() {
  var html = HtmlService.createHtmlOutputFromFile('Picker.html')
      .setWidth(600)
      .setHeight(425)
      .setSandboxMode(HtmlService.SandboxMode.IFRAME);
  SpreadsheetApp.getUi().showModalDialog(html, 'Select File');
}

function getOAuthToken() {
  DriveApp.getRootFolder();
  return ScriptApp.getOAuthToken();
}

function finishedImport() {
  SpreadsheetApp.getUi().alert("Archivo importado exitosamente");
}

 function senderror(e) {
   MailApp.sendEmail(Session.getEffectiveUser().getEmail(), "Error report jaja - sonríele a la vida!", 
      "\r\nMessage: " + e.message
      + "\r\nFile: " + e.fileName
      + "\r\nLine: " + e.lineNumber);
 }

And finally, Picker.html file:

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
  <script type="text/javascript">
    var DIALOG_DIMENSIONS = {
        width: 600,
        height: 425
    };
    var pickerApiLoaded = false;

    function onApiLoad() {
        gapi.load('picker', {
            'callback': function() {
                pickerApiLoaded = true;
            }
        });
        google.script.run.withSuccessHandler(createPicker)
            .withFailureHandler(showError).getOAuthToken();
    }

    function createPicker(token) {

        if (pickerApiLoaded && token) {

            //var docsView = new google.picker.DocsView()
                //.setIncludeFolders(true)
                //.setMimeTypes('application/vnd.google-apps.folder')
                //.setSelectFolderEnabled(true);

            var uploadDocsView = new google.picker.DocsUploadView()
                .setIncludeFolders(true)
                //.setMimeTypes('application/vnd.google-apps.folder')
                //.setSelectFolderEnabled(true);

            var picker = new google.picker.PickerBuilder()
                //.addView(docsView)
                .addView(uploadDocsView)
                //.setAppId("AIzaSyCZDa4JKKIOv2AF3QyrG8DnVOXmz27054o")
                .enableFeature(google.picker.Feature.NAV_HIDDEN)
                .hideTitleBar()
                .setSize(DIALOG_DIMENSIONS.width - 2, DIALOG_DIMENSIONS.height - 2)
                .setOAuthToken(token)
                .setCallback(pickerCallback)
                .setOrigin('https://docs.google.com')
                .build();

            picker.setVisible(true);

        } else {
            showError('Unable to load the file picker.');
        }
    }

    /**
     * A callback function that extracts the chosen document's metadata from the
     * response object. For details on the response object, see
     * https://developers.google.com/picker/docs/result
     *
     * @param {object} data The response object.
     */
    function pickerCallback(data) {
    try {
        var action = data[google.picker.Response.ACTION];
        if (action == google.picker.Action.PICKED) {
            var doc = data[google.picker.Response.DOCUMENTS][0];
            var id = doc[google.picker.Document.ID];
            // Show the ID of the Google Drive folder
            //document.getElementById('result').innerHTML = id;
            document.getElementById('result').innerHTML = "Importando..."
            google.script.run.importCSVData(id);
            //google.script.run.deleteImportedFile(id);
            google.script.host.close();
        } else if (action == google.picker.Action.CANCEL) {
        //document.getElementById('result').innerHTML = "Cerrando1..."
           google.script.host.close();
        //document.getElementById('result').innerHTML = "Cerrando2..."

        }
        } catch (e) {
          document.getElementById('result').innerHTML = e;
          google.script.run.senderror(e);
        }
    }

    function showError(message) {
        document.getElementById('result').innerHTML = 'Error: ' + message;
    }
  </script>
</head>

<body>
    <div>
        <p id='result'></p>
    </div>
    <script type="text/javascript" src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
</body>
</html>
like image 300
Alejandro Sardi Avatar asked Apr 07 '17 08:04

Alejandro Sardi


1 Answers

You need to load the Google File Picker using the Google API Loader library.

Replace:

<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>

with:

<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script>google.load("picker", "1", {callback:function(){pickerApiLoaded =!0}});</script>

Remember to publish a new version of the web app after making this change.

Update: Erik from the Google Apps Script team says " the cause of the problem is that when the Picker API loads into google.picker, it is currently overwriting google.script, so google.script.run() calls start failing."

They have posted an alternate solution - manually preserve and restore google.script when loading the Picker API:

window.script = google.script;
gapi.load('picker', '1', {callback: function() {
  google.script = window.script;
  // ...
}});
like image 81
Amit Agarwal Avatar answered Nov 15 '22 07:11

Amit Agarwal