I've got a stand-alone script deployed as a Web App. My code is working exactly as it should as a Web App. However, my goal is to use that code in a Spreadsheet Project.
I copied and pasted the code into a Spreadsheet Script and made a few alterations to make it work in a pop-up Modal dialog window, but it does not work as it does as a deployed web app. The code seems to not return any data to Code.gs. After running alerts at various points along the code path I have discovered the point of failure but am not sure how to address it.
Code from the working WebApp (2 files: Code.gs & form.html):
## Code.gs file ##
function doGet() {
return HtmlService.createHtmlOutputFromFile('form')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function uploadFileToDrive(base64Data, fileName, totalFiles, finalCount) {
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 dropbox = "stuff"; // Folder Name
var folder, folders = DriveApp.getFoldersByName(dropbox); // Get folders by name
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var file = folder.createFile(ss);
// BEGIN LOGGING FILE NAMES AND IDs
var dropboxId = "SOME_FOLDER_ID_HERE" // Folder ID
var theFolder = DriveApp.getFolderById(dropboxId); // Get folder by ID
var list = [];
var theBlobs = [];
if (totalFiles == finalCount) {
var files = theFolder.getFiles();
while (files.hasNext()) {
var theFile = files.next();
list.push(theFile.getId());
}
for (var i = 0; i < list.length; i++) {
Logger.log(DriveApp.getFileById(list[i]).getName() + " : " + list[i]);
theBlobs.push(DriveApp.getFileById(list[i]).getBlob());
}
Logger.log(theBlobs);
// END LOGGING FILE NAMES AND IDs
// BEGIN ZIPPING UP FILES
var newZip = theFolder.createFile(Utilities.zip(theBlobs, 'zippedFiles.zip'));
var zipId = newZip.getId();
Logger.log("Zip Id: " + zipId);
// END ZIPPING UP FILES
// BEGIN TRASHING UPLOADED FILES
for (var i = 0; i < list.length; i++) {
DriveApp.getFileById(list[i]).setTrashed(true);
}
// END TRASHING UPLOADED FILES
}
return file.getName();
}catch(e){
return 'Error: ' + e.toString();
}
}
## form.html ##
<body>
<div id="formcontainer">
<form id="myForm">
<label for="myFile">Upload File(s):</label><br />
<input type="file" name="filename" id="myFile" multiple />
<input type="button" class="blue" value="Submit" onclick="iteratorFileUpload()" /><br /><br />
</form>
</div>
<div id="output"></div>
<div id="progressbar">
<div class="progress-label"></div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<link rel="stylesheet" href="https://googledrive.com/host/0By0COpjNTZPnZTBvVGZOSFRhREE/add-ons.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script>
var numUploads = {};
numUploads.done = 0 ;
numUploads.total = 0 ;
// Upload the files into a folder in drive...set to send them all to one folder (specificed in the .gs file)
function iteratorFileUpload() {
var allFiles = document.getElementById('myFile').files;
if (allFiles.length == 0) {
alert('No file selected!');
} else { // Show Progress Bar
var myCount = 0; // Begin count to compare loops through
numUploads.total = allFiles.length;
$('#progressbar').progressbar({
value : false
});
$(".progress-label").html('Preparing files..');
// Send a file at a time
for (var i = 0; i < allFiles.length; i++) {
myCount++; // Increment count each time before sending the file to drive
sendFileToDrive(allFiles[i], allFiles.length, myCount);
}
}
}
function sendFileToDrive(file, totalFiles, newCount) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, totalFiles, newCount);
}
reader.readAsDataURL(file);
}
function updateProgressbar( 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;
};
}
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
body {
max-width: 400px;
padding: 20px;
margin: auto;
}
input {
display: inline-block;
width: 100%;
padding: 5px 0px 5px 5px;
margin-bottom: 10px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
select {
margin: 5px 0px 15px 0px;
}
input[type="submit"] {
width: auto !important;
display: block !important;
}
input[type="file"] {
padding: 5px 0px 15px 0px !important;
}
#progressbar{
width: 100%;
text-align: center;
overflow: hidden;
position: relative;
vertical-align: middle;
}
.progress-label {
float: left;
margin-top: 5px;
font-weight: bold;
text-shadow: 1px 1px 0 #fff;
width: 100%;
height: 100%;
position: absolute;
vertical-align: middle;
}
</style>
</body>
When deploying as a Spreadsheet container bound app the code is as follows (2 files: Code.gs & form.html):
## Code.gs ##
function uploadFiles() {
function doGet() {
return SpreadsheetApp.getUi().showModalDialog(HtmlService.createHtmlOutputFromFile('form').setSandboxMode(HtmlService.SandboxMode.IFRAME), "Upload Files");
}
doGet();
function uploadFileToDrive(base64Data, fileName, totalFiles, finalCount) {
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 dropbox = "stuff"; // Folder Name
var folder, folders = DriveApp.getFoldersByName(dropbox); // Get folders by name
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var file = folder.createFile(ss);
// BEGIN LOGGING FILE NAMES AND IDs
var dropboxId = "SOME_FOLDER_ID_HERE" // Folder ID
var theFolder = DriveApp.getFolderById(dropboxId); // Get folder by ID
var list = [];
var theBlobs = [];
if (totalFiles == finalCount) {
var files = theFolder.getFiles();
while (files.hasNext()) {
var theFile = files.next();
list.push(theFile.getId());
}
for (var i = 0; i < list.length; i++) {
Logger.log(DriveApp.getFileById(list[i]).getName() + " : " + list[i]);
theBlobs.push(DriveApp.getFileById(list[i]).getBlob());
}
Logger.log(theBlobs);
// END LOGGING FILE NAMES AND IDs
// BEGIN ZIPPING UP FILES
var newZip = theFolder.createFile(Utilities.zip(theBlobs, 'zippedFiles.zip'));
var zipId = newZip.getId();
Logger.log("Zip Id: " + zipId);
// END ZIPPING UP FILES
// BEGIN TRASHING UPLOADED FILES
for (var i = 0; i < list.length; i++) {
DriveApp.getFileById(list[i]).setTrashed(true);
}
// END TRASHING UPLOADED FILES
}
return file.getName();
}catch(e){
return 'Error: ' + e.toString();
}
}
}
## form.html ##
<body>
<div id="formcontainer">
<form id="myForm">
<label for="myFile">Upload File(s):</label><br />
<input type="file" name="filename" id="myFile" multiple />
<input type="button" class="blue" value="Submit" onclick="iteratorFileUpload()" /><br /><br />
</form>
</div>
<div id="output"></div>
<div id="progressbar">
<div class="progress-label"></div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<link rel="stylesheet" href="https://googledrive.com/host/0By0COpjNTZPnZTBvVGZOSFRhREE/add-ons.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script>
var numUploads = {};
numUploads.done = 0 ;
numUploads.total = 0 ;
// Upload the files into a folder in drive...set to send them all to one folder (specificed in the .gs file)
function iteratorFileUpload() {
var allFiles = document.getElementById('myFile').files;
if (allFiles.length == 0) {
alert('No file selected!');
} else { // Show Progress Bar
var myCount = 0; // Begin count to compare loops through
numUploads.total = allFiles.length;
$('#progressbar').progressbar({
value : false
});
$(".progress-label").html('Preparing files..');
// Send a file at a time
for (var i = 0; i < allFiles.length; i++) {
myCount++; // Increment count each time before sending the file to drive
sendFileToDrive(allFiles[i], allFiles.length, myCount);
}
}
}
function sendFileToDrive(file, totalFiles, newCount) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, totalFiles, newCount);
}
reader.readAsDataURL(file);
}
function updateProgressbar( 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;
};
}
/*
function updateProgressbar( 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;
};
}
*/
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
body {
max-width: 400px;
padding: 20px;
margin: auto;
}
input {
display: inline-block;
width: 100%;
padding: 5px 0px 5px 5px;
margin-bottom: 10px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
select {
margin: 5px 0px 15px 0px;
}
input[type="submit"] {
width: auto !important;
display: block !important;
}
input[type="file"] {
padding: 5px 0px 15px 0px !important;
}
#progressbar{
width: 100%;
text-align: center;
overflow: hidden;
position: relative;
vertical-align: middle;
}
.progress-label {
float: left;
margin-top: 5px;
font-weight: bold;
text-shadow: 1px 1px 0 #fff;
width: 100%;
height: 100%;
position: absolute;
vertical-align: middle;
}
</style>
</body>
The non-working code stops at this point:
google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, totalFiles, newCount);
.
Up to that point everything moves along nicely and info is passed from function to function.
In the Spreadsheet script the files never get uploaded to Drive and the counter for the files that displays on the html page never increments...it just stalls.
The closest articles I've come across that may aid in resolving this are: how to use google.script.run as if it was a function that was originally proposed as a solution to this question Google Apps Script HTML Service: Passing variables and Returning a value using Date picker in HTMLService / Google Apps Script.
Thank you for your help in advance!!