Google app script: upload a csv file from html service

人盡茶涼 提交于 2020-06-17 09:09:28

问题


I'm trying to upload a csv file from an html service in google sheets, and after some research I found some code which seemed to be working at the time:

html service call:

function importAnalysis() {
  var html = HtmlService.createHtmlOutputFromFile('Import')
      .setWidth(1524)
      .setHeight(800);
  SpreadsheetApp.getUi()
      .showModalDialog(html, 'Import d\'analyse');
}

html template:

<!DOCTYPE html>
  <html>
    <body>
      <form>
        <input type="file" name="analysisCsv" accept=".csv">
        <input type="button" onclick="google.script.run.processForm(this.parentNode);">
      </form>
    </body>
  </html>

gs file (I commented further code to isolate the source of the problem):

function processForm(form) {
  let fileBlob=form.analysisCsv;
//  sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Table_Analysis");
//  let lastRow = sheet.getLastRow();
//  let values = []
//  let rows = fileBlob.contents.split('\n');
//  for(let r=0; r<rows.length; ++r){
//    values.push( rows[r].split(';') );
//  }
//  for (var i = 0; i < values.length; i++) {
//    sheet.getRange(lastRow+i+1, 1, 1, values[i].length).setValues(new Array(values[i]));
//  }  
}

Problem is I get an error 400 on processForm function: "Failed to load resource: the server responded with a status of 400 ()"

Do you know what's wrong with my code, or another way to upload csv content in my sheet? Thanks in advance.


回答1:


So to sum it up, I had to force Legacy runtime: Select Run > Disable new Apps Script runtime powered by V8. Then edit all the V8 syntax:replace "let" by "var" mainly. Now it's working, thanks to all.

See https://developers.google.com/apps-script/guides/v8-runtime/migration https://developers.google.com/apps-script/guides/v8-runtime#enabling_the_v8_runtime




回答2:


You can't provide doPost() with a parameter. From the documentation:

When a user visits an app or a program sends the app an HTTP GET request, Apps Script runs the function doGet(e). When a program sends the app an HTTP POST request, Apps Script runs doPost(e) instead. In both cases, the e argument represents an event parameter that can contain information about any request parameters. The structure of the event object is shown in the table below: And here's a link to that

As I stated in my comment above a simple way of passing a form to the server is:

google.script.run.proccessForm(this.parentNode)

And this is explained here and partly here

Well I finally ran your code myself and sure enough it's not working in V8.

So I moved to the old version and this is the code I used:

GS:

function runThree() {
  var html = HtmlService.createHtmlOutputFromFile('ah3').setWidth(400).setHeight(400);
  SpreadsheetApp.getUi().showModelessDialog(html, 'Title');
}

function processForm(form) {
  Logger.log(JSON.stringify(form));
  var fileBlob=form.analysisCsv;
  var folder=DriveApp.getFolderById(getGlobal('TestFolderId'));
  var file=folder.createFile(fileBlob);
  var csv=Utilities.parseCsv(file.getBlob().getDataAsString());
  var sh=SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet10");
  var rg=sh.getRange(sh.getLastRow()+1,1,csv.length,csv[0].length).setValues(csv);
  return "I've got it";
}

HTML:

<!DOCTYPE html>
  <html>
    <head>
    <base target="_top">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    </head>
    <body>
      <form>
        <input type="file" name="analysisCsv" accept=".csv">
        <input type="button" value="Save" onclick="intermediate(this.parentNode);">
        <div id="msg"></div>
      </form>
      <script>
        function intermediate(obj) {
          google.script.run
          .withSuccessHandler(function(msg){$('#msg').html(msg);google.script.host.close();})
          .processForm(obj);
        }
        console.log('My Code');
      </script>
    </body>
  </html>

I just created a csv file and upload to a folder and then using Utilites.parseCsv() which converts it to a 2D array that can be inserted into a spreadsheet with setValues();




回答3:


Here is my solution using client-side FileReader API:

code.gs:

function doSomething(csvstr) {
  Logger.log('doSomething', csvstr);

  const csvarr = Utilities.parseCsv(csvstr);

  return csvarr; // now an array !
}

index.html:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">

  </head>
  <body>
    <input type="file">

    <script>
    const $input = document.querySelector('input')

    $input.onchange = function (e) {
      // File
      const file = e.target.files[0]

      //
      // FileReader
      //
      // see: https://web.dev/read-files/#read-content
      //

      const reader = new FileReader();

      reader.onerror = event => {
        console.error('error while reading CSV file', event)
        reader.abort()
      }

      reader.onload = event => {
        const content = event.target.result // result
        console.log(content)

        // https://developers.google.com/apps-script/guides/html/reference/run
        google.script.run
          .withFailureHandler(err => {
            console.error('oh noes', err)
          })
          .withSuccessHandler(val => {
            console.log('yay!', val)

            google.script.host.close() // https://developers.google.com/apps-script/guides/html/reference/host#close
          })
          .doSomething(content)
      }
      reader.readAsText(file);
    }
    </script>
  </body>
</html>


来源:https://stackoverflow.com/questions/60416575/google-app-script-upload-a-csv-file-from-html-service

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!