Can I use google utilities unzip in JavaScript on the browser client? - javascript

I'm trying to figure out the flow of using google's scripts to copy images from a user's hard drive to a public folder on their Google Drive. (see https://developers.google.com/apps-script/reference/utilities/utilities#unzip%28BlobSource%29 ) Question is, do I have to write a google script that I publish as a web app from script.google.com, or can I have the script inside the javascript on the client's browser? Google has a sample of uploading images one at a time: "developers.google.com/drive/web/quickstart/quickstart-js"
I would like to upload one zipped file of images, unzip them and then reduce the size before they are stored in the user's Google Drive.
Here is some code that unzips files, but it looks like they are running this from script.google.com; it does not work: (http://webcache.googleusercontent.com/search?q=cache:NsTvlj17H4MJ:ctrlq.org/code/19506-google-drive-hosting&client=firefox-a&hs=ZEF&hl=en&gl=us&strip=1)

This is a script that I modified for another user that allows for multiple files (validation could probably limit file types to images) to be uploaded from the user's hard drive to a specific folder. The folder would be set to share publicly. You would simply change the folderID string to the string that matches the folder where you wanted to files to arrive. Put this script in a Google Sites page, and change the id in the doPost(e) function, and it should do what you want it to do. I'm not sure about the zipping and unzipping. You would publish the script in a google site as a public webapp widget.
You can see the UiApp interface here, but if you try to upload something, you will get an error because I've removed the folderId link to my drive since I put this answer live. If you need more explanation about how or why it works, let me know. Use the + and - buttons to add more files to the upload, or remove a file that you don't want to include. The files can be zips or any file type, but there isn't code included to unzip anything after it's uploaded.
//modified from script found here http://www.googleappsscript.org/miscellaneous/creating-form-elements-dynamically-using-google-apps-script-gas
//additional help from Serge to fix an error in my original code.
function doGet() {
var app = UiApp.createApplication();
var panel = app.createVerticalPanel();
var formPanel = app.createFormPanel();
var instructionsLabel = app.createLabel('Put your instructions here');
var filesLabel = app.createLabel('Add Files to Upload');
var table = app.createFlexTable().setId('table').setTag('0'); //Here tag will count the number of files
//Write the header for the table
var header = app.createLabel('File(s)');
table.setWidget(0, 0, header);
//Add the first row of files
addFirstRow(app);
var hidden = app.createHidden().setId('hiddenRowHolder').setName('hidden').setValue(table.getTag());
//Add a button to submit the info
var button = app.createSubmitButton('Upload File(s)');
panel.add(instructionsLabel).add(filesLabel).add(table).add(hidden).add(button);
formPanel.add(panel);
app.add(formPanel);
return app;
}
function addFirstRow(app){
var table = app.getElementById('table');
var tag = parseInt(table.getTag());
Logger.log(tag);
var numRows = tag+1;
if(numRows >1){
table.removeCell(numRows-1, 5);
table.removeCell(numRows-1, 4);
}
Logger.log(numRows);
var uploadWidget = app.createFileUpload();
table.setWidget(numRows, 0, uploadWidget);
table.setTag(numRows.toString());
addButtons(app);
}
function addButtons(app){
var table = app.getElementById('table');
var numRows = parseInt(table.getTag());
//Create handler to add/remove row
var addRemoveRowHandler = app.createServerHandler('addRemoveRow');
addRemoveRowHandler.addCallbackElement(table);
//Add row button and handler
var addRowBtn = app.createButton('+').setId('addOne').setTitle('Add row');
table.setWidget(numRows, 4, addRowBtn);
addRowBtn.addMouseUpHandler(addRemoveRowHandler);
//remove row button and handler
var removeRowBtn = app.createButton('-').setId('removeOne').setTitle('Remove row');
table.setWidget(numRows, 5, removeRowBtn);
removeRowBtn.addMouseUpHandler(addRemoveRowHandler);
}
function addRemoveRow(e){
Logger.log(e.parameter.source);
var app = UiApp.getActiveApplication();
var table = app.getElementById('table');
var tag = parseInt(e.parameter.table_tag);
var hidden = app.getElementById('hiddenRowHolder');
var source = e.parameter.source;
//Logger.log(tag);
if(source == 'addOne'){
table.setTag(tag.toString());
hidden.setValue(tag+1);
addFirstRow(app);
}
else if(source == 'removeOne'){
if(tag > 1){
//Dcrement the tag by one
var numRows = tag-1;
table.removeRow(tag);
//Set the new tag of the table
table.setTag(numRows);
hidden.setValue(numRows);
//Add buttons in previous row
addButtons(app);
}
}
return app;
}
function doPost(e) {
var numFiles = Number(e.parameter.hidden);
Logger.log(numFiles);
for (var i = 1; i<=numFiles; i++){
var fileBlob = e.parameter['file'+i];
var newFile = DocsList.getFolderById("YOUR FILE FOLDER ID").createFile(fileBlob);//replace string with folder id where you want to place your files
}
var app = UiApp.getActiveApplication();
var label = app.createLabel(numFiles +' file(s) uploaded successfully');
app.add(label);
return app;
}

Related

After I set dataUrl to text area as value, browser and my site stop responding

I am now trying to set the dataUrl of JSZip to textarea using document.getElementById('fileContent').value = fileData; . But Once I did that, the site and browser became no response without any error. Does anyone have any idea what is wrong? Please really need help, and thanks for reading my question.
Every Thing goes well except after document.getElementById('fileContent').value = fileData;
Even I copy the DataURL and paste it into the textarea by myself, my site and browser stopped eventually.
I want to set the value inside a form element with action to send data by input value.
<textarea placeholder="Example Text" id="fileContent" name="fileContent" data-name="fileContent" class="w-input" spellcheck="false"></textarea>
<script>
function getfile() {
var zip = new JSZip();
for(let i = 0; i < file.length; i++){
var caltor = i+1;
var aFileName = "image"+caltor+".jpg";
var aContent = dataURItoBlob(file[i]);
zip.folder("Image_folder").file(aFileName, aContent)
}
zip.generateAsync({type:"base64"})
.then(function (content) {
fileData = "data:application/zip;base64,"+content;
document.getElementById('fileContent').value = fileData;
});
}
</script>

Button Action to retrieve data from spreadsheet using google app script

How to retrieve a complete row from a spreadsheet based on a filter on an action such as a click of a button.
I read that GAS is server-side scripting and it is complex to gain access to a spreadsheet.
Is that so. Please guide me.
I have done till this:
$("#form-action")
.button()
.click(function() {
var ss = SpreadsheetApp.openById("");
var sheet = SpreadsheetApp.getActiveSpreadsheet();
SpreadsheetApp.setActiveSheet(sheet.getSheetByName('Test'));
SpreadsheetApp.getActiveSheet().getRange("D1").setFormula('Query(A:C,"SELECT A,B,C WHERE B="' + "mydata'" + ',1)');
SpreadsheetApp.getActiveSheet().getRange("E:J").getValues();
});
Gaining access to the spreadsheet is not difficult at all. You have to remember that while Google Apps Script runs on Google servers, the client-side code (e.g. HTML and JavaScript code you use in your UI templates) will be sent to your browser for rendering, so you can't really mix the two and write jQuery code in GAS(.gs) files or vice versa.
To clarify, commands like
var ss = SpreadsheetApp.openById("");
must be kept in .gs files. To use client-side HTML and JavaScript, you must create separate HTML files in your project (go to File - New - HTML file). Here's more information on serving HTML in GAS https://developers.google.com/apps-script/guides/html/
Luckily, Google provides the API that allows you to communicate between client and server sides by calling 'google.script.run.' followed by the name of the function in '.gs' file.
Example function in '.gs' file
function addRow() {
var sheet = SpreadsheetApp.getActive()
.getSheets()[0];
sheet.appendRow(['Calling', 'server', 'function']);
}
In your HTML template file, here's how you would call this function
<script>
google.script.run.addRow();
</script>
Consider the example that is more relevant to your situation. In my spreadsheet, the QUERY formula changes dynamically based on the value entered by the user. The form with input field is displayed in the sidebar.
Project structure
Code for 'sidebar.html' is below. Note that using the 'name' attribute of the <input> element is mandatory. On form submit, the value of the attribute ('filterBy') will be transformed into propetry of the form object that we can reference in our server function to get user input.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
</script>
</head>
<body>
<form id="myForm">
<input type="text" name="filterBy">
<input type="submit" value="submit">
</form>
<table id="myTable"></table>
<script>
$('document').ready(function(){
var form = $('#myForm');
var table = $('#myTable');
var runner = google.script.run;
form.on('submit', function(event){
event.preventDefault(); //prevents <form> redirecting to another page on submit
table.empty(); // clear the table
runner.withSuccessHandler(function(array){ //this callback function will be invoked after the 'retriveValues()' function below
for (var i = 0; i < array.length; i++) {
var item = '<tr><td>' + array[i] +'</td></tr>';
table.append(item);
}
})
.retrieveValues(this); //the function that will be called first. Here, 'this' refers to the form element
});
});
</script>
</body>
</html>
Code in '.gs' file:
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheets()[0];
function onOpen() {
var ui = SpreadsheetApp.getUi();
var htmlOutput = HtmlService.createTemplateFromFile('sidebar')
.evaluate();
ui.showSidebar(htmlOutput);
}
function retrieveValues(req) {
var res = [];
var filterBy = req.filterBy; //getting the value of the input field.
sheet.getRange(1, 2, 1, 1)
.setFormula("QUERY(A1:A, \"SELECT A WHERE A > " + filterBy + "\")");
sheet.getRange(1, 2, sheet.getLastRow(), 1)
.getValues()
.map(function(value){
if (value[0] != "") res = res.concat(value[0]); // get only the values that are not empty strings.
});
return res;
}
Here's the result of entering the value and submitting the form. The server-side function returns the array of values greater than 5. The callback function that we passed as parameter to 'withSuccessHandler' then receives this array and populates the table in the sidebar.
Finally, I'm not sure why you are using the QUERY formula. Instead of modifying 'SELECT' statement, you could simply take the values from the target range an filter them in GAS.

how to covert visualization table of app script to spread sheet google app script code

I have HTML web app where I have converted a spreadsheet to a HTML table. Now I would like to convert this HTML Table to a spreadsheet. Is it possible to convert it back to a spreadsheet?
You can say that I can directly make use of the spreadsheet but the problem is that I have applied some filters. Now whenever I apply a filter to a specific column, it will be displayed so now I want that column to be moved to the new spreadsheet using google app script
Here is my table, how can convert this table to spreadsheet using Google App Script
I use two sheets for this example one sheet is named sht2tbl and the other sheet is named tbl2sht. You need to have both ready to go when you run the code.
Here's sheet2table and table2sheet.gs:
function sheetToTable()//This produces a modeless dialog
{
var s='';
s+='<table width="100%">';
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sht=ss.getSheetByName('sht2tbl');
var rng=sht.getDataRange();
var rngA=rng.getValues();
for(var i=0;i<rngA.length;i++)
{
s+='<tr>';
for(var j=0;j<rngA[0].length;j++)
{
if(i==0)
{
s+='<th id="cell' + i + j + '">' + rngA[i][j] + '</th>';//put ids in each th
}
else
{
s+='<td id="cell' + i + j + '">' + rngA[i][j] + '</td>';//put ids in each td
}
}
s+='</tr>';
}
s+=' </body></html>'
var html=HtmlService.createHtmlOutputFromFile('html2body');//create output from file
html.append(s);//and append s for the rest
SpreadsheetApp.getUi().showModelessDialog(html, 'Sheet to Table')
}
function getParams()//this gives the client side array dimensions
{
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sht=ss.getSheetByName('sht2tbl');
var rng=sht.getDataRange();
var A=[];
A.push(rng.getWidth());
A.push(rng.getHeight());
return (A);//range width and height in an array
}
function putData(data)//this gets cell contents from the client side and displays them on another sheet named 'tbl2sht'
{
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sht=ss.getSheetByName('tbl2sht');
var h=data.length;
var w=data[0].length;
var rng=sht.getRange(1,1,h,w);//create a range properly dimensioned
rng.setValues(data);//use setValues to load sheet
}
This is the file htmltobody.html. It's a lot easier to create javascript this way. But I like to integrate the data creation with server side google script.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
$(function() {
google.script.run
.withSuccessHandler(getCellValues)//returns to get values from client side
.getParams();//get width and height of data array
});
function getCellValues(A)
{
var w=A[0];
var h=A[1];
var data=[];
for(var i=0;i<h;i++)
{
data[i]=[];
for(var j=0;j<w;j++)
{
var s='#cell' + Number(i) + Number(j);
data[i][j]=$(s).text();//use jquery text to get th and td values
}
}
google.script.run
.putData(data);//send data to server side to load data in tbl2sht
}
console.log('My Code');//helps me to find code in chrome console
</script>
</head>
<body>
This is the sht2tbl which was use to create the modeless dialog:
This is the dialog that gets created:
And this is the data from the dialog displayed on a sheet named tbl2sht:

Google App Script Bounded to Spreadsheet

what I' trying to accomplish is a Google Spreadsheet for a project management. I've got lots of cells in a grid where a user should select either the item was completed or not. Now this spreadsheet would be available only to a Project Manager. The way I imagined the process would work was that Project Manager selects particular cells and assigns them to a technician's email address. Script would then generate mobile friendly html UI and send it to the technician (I thought of Google forms but I want to create more customized UI). Technician would then select a checkbox after completing a task which would at the same time update the spreadsheet. Next time technician would open the UI it would populate all the checkboxes that previously were selected.
The only way I've found that I could make it work was a google script web app bounded to a spreadsheet. I've created a test HTML file and .gs file:
.html file
<head>
<base target="_top">
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
</head>
<body>
<h1> Web App Test </h1>
<input type="button" value="Click Me" id="buttonclicked" onclick="getSomeData()"/>
<div id="output" class="current">output</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<script>
function getSomeData()
{
google.script.run
.withSuccessHandler(onSuccess)
.withFailureHandler(showError)
.testForWebApp();
myLog("in WebAppTest.html getSomeData()");
}
function onSuccess(testParam)
{
var div = document.getElementById('output');
if (sectionName == null)
div.innerHTML = "<p style='color:red;'>You didn't hit the script</p>";
else
div.innerHTML = "<p style='color:white;'>" + testParam + "</p>";
}
function showError()
{
var div = document.getElementById('output');
div.innerHTML = "<p style='color:red;'>You didn't hit the script</p>";
}
</script>
</body>
and .gs file:
function doGet()
{
return HtmlService.createHtmlOutputFromFile('WebAppTest')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function testForWebApp()
{
myLog("In testForWebApp()");
var msg = "Yep you hit the script!";
return msg;
}
function myLog(log)
{
//log = 'test';
Logger.log(log);
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getSheetByName('log');
var lastRow = sheet.getLastRow();
sheet.insertRowBefore(1);
var newLogDateRange = sheet.getRange(1, 1);
var newLogTextRange = sheet.getRange(1, 2);
var now = new Date();
newLogDateRange.setValue(now);
newLogTextRange.setValue(log)
}
When I published the app and followed the generated link I saw my html page with a Click Me button. The click event ran the getSomeData() function which called google.script.run function. The server side .testForWebApp() gotten executed because I've gotten a log entry from myLog() but the .withSuccessHandler or .withFailureHandler were never called. At the same time the myLog() that should be executed after google.script.run never run either.
I definitely don't understand how it works and suspect that if I publish a script as a web app the HTML is not bounded to the script anymore, but I couldn't find any information about it online.
Thanks for your help.
Firstly, you cannot call server-side myLog() function from your client side javascript unless you call it using google.script.run.myLog() Therefore
myLog("in WebAppTest.html getSomeData()");
in your getSomeData() doesnt log anything in your google sheet
Secondly, this code in function onSuccess(testParam)
if (sectionName == null)
is causing your function to terminate prematurely, since there is no variable called sectionName defined.
Note: You can monitor all these errors in the console of your web browser.
Below is the modified code that should work as you intend it to
Final code:
Web App Test
output
function getSomeData()
{
google.script.run
.withSuccessHandler(onSuccess)
.withFailureHandler(showError)
.testForWebApp();
console.log("in WebAppTest.html getSomeData()"); //Log it on the browser console
}
function onSuccess(testParam)
{
var div = document.getElementById('output');
if (testParam == null) // Changed it to testParam from sectionName, to check the value returned from testWebApp()
div.innerHTML = "<p style='color:red;'>You didn't hit the script</p>";
else
div.innerHTML = "<p style='color:black;'>Success:" + testParam + "</p>";
}
function showError()
{
var div = document.getElementById('output');
div.innerHTML = "<p style='color:red;'>You didn't hit the script</p>";
}
Edit
One last note, the below code would make the return text invisible as the text and background color would be the same color (white):
div.innerHTML = "<p style='color:white;'>Success:" + testParam + "</p>";
hence changed the text color to black in the final code
Hope that helps!
Try redeploying the web app, but under a new project version.

Reading the name of a File with Javascript/jQuery

Currently I am making a program in which works as a text editor. I have a section where you can rename the title, and when you save, it takes that document.getElementById('title').innerHTML and makes it the .txt name.
For example:
If the title div had the innerHTML of "Document", the file would be called "Document.txt".
My problem is that I want it to also upload a file and take its file name.
For example:
I uploaded a file called "Document.txt", and the function makes the title "Document". (I am using a .replace('.txt','') to make it not show in the title and a += '.txt' to make the file actually a .txt when saved.
Anyone know how to make the file name of the uploaded document using an <input type='file'> a string to be used elsewhere?
Here is some code to put it in perspective:
var id = function(id){return document.getElementById(id)};
function readText(that)
{
var reader = new FileReader();
reader.onload = function(e)
{
var output = e.target.result,
name = FILENAMEFIND();
id('page').innerHTML = output;
id('title').innerHTML = name;
}
reader.readAsText(that.files[0]);
}
Ok, I figured it out myself:
var id = function(id){return document.getElementById(id)},
input = id("upfile"),
file = input.value.split("\\"),
fileName = file[file.length-1]; // Take purely the file name
id('title').innerHTML = fileName; // Outputted to title div

Categories

Resources