2

For the organisation of a large scout camp, I am currently trying to build a web form where requests for services (security, infrastructure, materials, etc.) can be made. For this I would like the following:

  • upload (multiple) files to a google drive folder

  • write the remaining input (text, names, etc.) to a google spreadsheet

  • If possible, write the url of the file location to that same spreadsheet

So far, I have been utterly unsuccesful in combining the first two functions. Over the course I have tried combining the methods as described in:

https://script.google.com/d/1x3p9ZAv-SafEK06r_Vr7fVuUNtEfBg1SGhmSYWjQ0kuPTk-y55a7Nink/edit?usp=sharing

Uploading Multiple Files to Google Drive with Google App Script

HTML form file upload to Google Drive and save URL to google sheet

Google Forms: Send data to spreadsheet

Google Forms file upload complete example

https://gist.github.com/xtman/060edd76c27b7fcb343dfb8e08252693

As per request, I am trying to achieve this the following way: Code to make two functions both happen:

frm.submit(function () {
    allFiles = document.getElementById('supportingFiles').files;
    if (!frm.checkValidity || frm.checkValidity()) {
      if (allFiles.length == 0) {
        alert('Error: Please choose at least 1 file to upload.');
        google.script.run.record_Data(frm);
        return false;
      } else {
        frm.hide();
        alert('Step 1');
        var subfolderName = document.getElementById('requesterSubject').value;

        $.ajax({
          url: '',//URL of webhook endpoint for sending a Slack notification
          data: {
            title: subfolderName + ' is uploading screenshots',
            message: ''
          }
        });
        alert('Step 2');
        //google.script.run.withSuccesHandler(record_Data(transformedData).transformData('myForm');
        google.script.run.withSuccessHandler(afterSubfolderCreated).createSubfolder(subfolderName);
        alert('Step 3');
        return false;
      }
    } else {
      alert('Invalid form');
      return false;
    }
});

This is where the error occurs. It is able to run the code as-is, but when I try to also run the recordData function, it doesn't do anything.

The code of the functions is as follows:
Submit the data

function dataTransform(form){
  var transformedData = JSON.stringify( $(form).serializeArray() ); //  <-----------
  console.log( data );
  return transformedData; //don't submit
}

function recordData(e) {
  Logger.log(JSON.stringify(e)); // log the POST data in case we need to debug it
  try {
    var doc     = SpreadsheetApp.openById('some id');
    var sheet   = doc.getSheetByName('responses'); // select the responses sheet
    var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
    var nextRow = sheet.getLastRow()+1; // get next row
    var row     = [ new Date() ]; // first element in the row should always be a timestamp
    // loop through the header columns
    for (var i = 1; i < headers.length; i++) { // start at 1 to avoid Timestamp column
      if(headers[i].length > 0) {
        row.push(e.parameter[headers[i]]); // add data to row
      }
    }
    // more efficient to set values as [][] array than individually
    sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
  }
  catch(error) {
    Logger.log(e);
  }
  finally {
    return;
  }
}

Submit the files

function uploadFileToDrive(base64Data, fileName, subfolderId) {
  Logger.log(subfolderId);
  try{
    var splitBase = base64Data.split(','),
        type = splitBase[0].split(';')[0].replace('data:','');

    var byteCharacters = Utilities.base64Decode(splitBase[1]);
    var ss = Utilities.newBlob(byteCharacters, type);
    ss.setName(fileName);
    var subfolder = DriveApp.getFolderById(subfolderId);
    var file = subfolder.createFile(ss);
    Logger.log(file);
    return file.getName() + ' at ' + file.getUrl();
  } catch(e) {
    return 'createFile Error: ' + e.toString();
  }
}

function createSubfolder(subfolderName) {
  var dropbox = Utilities.formatDate(new Date(), "Europe/Amsterdam", "yyyy-MM-dd_hh.mm_") + subfolderName ;
  Logger.log(dropbox);
  var parentFolderId = "some folder id";
  var parentFolder = DriveApp.getFolderById(parentFolderId);
  var folder;
  try {
      folder = parentFolder.getFoldersByName(dropbox).next();      
  }
  catch(e) {
      folder = parentFolder.createFolder(dropbox);
  }
  Logger.log(folder);
  return folder.getId();
}
function afterSubfolderCreated(subfolderId) {
  console.log(subfolderId);
  console.log(allFiles);
  numUploads.total = allFiles.length;
  $('#progressbar').progressbar({ value: false });
  $(".progress-label").html('Preparing files for upload');
  for (var i = 0; i < allFiles.length; i++) {
    console.log(i);
    sendFileToDrive(allFiles[i], subfolderId);
  }
}

function sendFileToDrive(file, subfolderId) {
  var reader = new FileReader();
  reader.onload = function (e) {
    var content = reader.result;
    console.log('Sending ' + file.name);
    google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, subfolderId);
  }
  reader.readAsDataURL(file);
}

function updateProgressbar(idUpdate) {
  console.log('Received: ' + idUpdate);
  numUploads.done++;
  var porc = Math.ceil((numUploads.done / numUploads.total) * 100);
  $("#progressbar").progressbar({value: porc});
  $(".progress-label").text(numUploads.done + '/' + numUploads.total);
  if (numUploads.done == numUploads.total) {                        
    numUploads.done = 0;
    $(".progress-label").text($(".progress-label").text() + ': FINISHED!');
    $("#progressbar").after('(Optional) Refresh this page if you want to fill out another request.');
    //<a href="javascript:window.top.location.href=window.top.location.href"> does not work
  }
}

function fileUploaded(status) {
  document.getElementById('myForm').style.display = 'none';
  document.getElementById('output').innerHTML = status;
}
tehhowch
  • 9,645
  • 4
  • 24
  • 42
Jeff
  • 21
  • 3
  • _"For now I won't bother you with the code"_ Can you include the code that you have tried at the Question. See https://stackoverflow.com/help/how-to-ask, https://stackoverflow.com/help/mcve – guest271314 Oct 18 '17 at 18:38
  • Include the code so we can better help you. the whole proccess just involves using HTMLService to get the form to the "server side" and then using DriveApp to upload the files (the form gives them to you as blobs), get the links from them and finally use SpreadsheetApp to put it all in your google sheet. – Imme Oct 18 '17 at 19:26
  • 1
    I disagree with the need for the HTMLService here: it can all be accomplished with Google Forms & Google Sheets. Incidentally, Forms already does all of this for you (handle upload of multiple files, write submitted data to a spreadsheet, write file URLs to the same spreadsheet): what do you need to implement that's not provided there? – Dean Ransevycz Oct 18 '17 at 22:17
  • Fair enough, the above can roughly be accomplished with Google forms, but for me the issue is that it requires a google account. I have also included parts of the code above, but since I am very new to this all, please correct me if anything is missing. – Jeff Oct 24 '17 at 12:02
  • A common way to organize code in your question for webapps is to explicitly indicate which scripts are in .gs code files (which are run server-side only), and which are within ` – tehhowch Sep 18 '18 at 14:53

1 Answers1

0

I don't know about the code, not competent enough. However, when you enter your data in a spreadsheet through a Google Form, you can use the Autocrat add-on to generate a google doc of pdf file which will be sent by e-mail and saved to a single folder. You can also use the dynamic reference folder ID to save the file to several folders at once. All you have to do is enter the Google Drive files reference in you spreadsheet. If you have hundreds of folders to link, it can be strenuous, but I do it with a hundred students or so for assessments and it works perfectly. Hope that helps...