google sheets UiApi to htmlservice script file upload - google-apps-script

I got the problem since google isnt supporting UIapi anymore i cant use the code below. Could someone help me with it and re-edit to html service? I have no clue about any of those stuff. Code was copied from other site long time ago. Tryed to find a solution for the last 2 days and nothing. Would be really greatfull.
regards
// upload document into google spreadsheet
// and put link to it into current cell
function onOpen(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var menuEntries = [];
menuEntries.push({name: "", functionName: "doGet"});
ss.addMenu("", menuEntries);
}
function doGet(e) {
var app = UiApp.createApplication().setTitle("");
SpreadsheetApp.getActiveSpreadsheet().show(app);
var form = app.createFormPanel().setId('frm').setEncoding('multipart/form-data');
var formContent = app.createVerticalPanel();
form.add(formContent);
formContent.add(app.createFileUpload().setName('thefile'));
// these parameters need to be passed by form
// in doPost() these cannot be found out anymore
formContent.add(app.createHidden("activeCell", SpreadsheetApp.getActiveRange().getA1Notation()));
formContent.add(app.createHidden("activeSheet", SpreadsheetApp.getActiveSheet().getName()));
formContent.add(app.createHidden("activeSpreadsheet", SpreadsheetApp.getActiveSpreadsheet().getId()));
formContent.add(app.createSubmitButton(''));
app.add(form);
SpreadsheetApp.getActiveSpreadsheet().show(app);
return app;
}
function doPost(e) {
var app = UiApp.getActiveApplication();
app.createLabel('');
var fileBlob = e.parameter.thefile;
var doc = DriveApp.getFolderById('0BzI2pkyLXZ5maWo5b2Uyb3JWdzQ').createFile(fileBlob);
var label = app.createLabel('');
// write value into current cell
var value = 'hyperlink("' + doc.getUrl() + '";"' + doc.getName() + '")'
var activeSpreadsheet = e.parameter.activeSpreadsheet;
var activeSheet = e.parameter.activeSheet;
var activeCell = e.parameter.activeCell;
var label = app.createLabel('');
app.add(label);
SpreadsheetApp.openById(activeSpreadsheet).getSheetByName(activeSheet).getRange(activeCell).setFormula(value);
app.close();
return app;
}

Related

Can not run standalone Google App Script from a Google Spreadsheet

I have a google spreadsheet shared with co-workers to keep track of task status. And I want to set a function through a menu to block some ranges in which the tasks were completed. The protective permissions are set to only allow me (owner) to edit it.
I've built a standalone script to run as me for this shared spreadsheet by using UrlFetch. I've tried many kinds of codes but it didn't work. The below are 3 versions I tried.
And, of course, I set "Who has access to the app: Anyone, even anonymous" in the standalone script.
Photo 1: Standalone script setting
Thanks so much!
1st version: Without using Content Service
//In standalone script
function doGet(e){
var taskRange = e.parameter.taskRange;
var ss = SpreadsheetApp.openById('SHARING_SPREADSHEET_ID');
var sh = ss.getSheetByName('Sheet1');
var protection = sh.getRange(taskRange).protect().setDescription('Completed Task')
var result = protection.removeEditors(protection.getEditors())
return result
}
//In sharing spreadsheet script
var url = "https://script.google.com/macros/s/STANDALONE_SCRIPT_ID/exec"
function onOpen(){
SpreadsheetApp.getUi().createMenu('TASK')
.addItem('Protect Task', 'protectTask')
.addToUi();
}
function protectTask(){
var taskRange = SpreadsheetApp.getActiveSheet().getActiveRange()
var response = UrlFetchApp.fetch(url+"?taskRange="+taskRange);
Logger.log(response);
}
2nd version: Using Content Service
//In standalone script
function doGet(e){
var taskRange = e.parameter.taskRange;
var ss = SpreadsheetApp.openById('SHARING_SPREADSHEET_ID');
var sh = ss.getSheetByName('Sheet1');
var protection = sh.getRange(taskRange).protect().setDescription('Completed Task')
var result = protection.removeEditors(protection.getEditors())
return ContentService.createTextOutput(result)
}
//In sharing spreadsheet script
var url = "https://script.google.com/macros/s/STANDALONE_SCRIPT_ID/exec"
function onOpen(){
SpreadsheetApp.getUi().createMenu('TASK')
.addItem('Protect Task', 'protectTask')
.addToUi();
}
function protectTask(){
var taskRange = SpreadsheetApp.getActiveSheet().getActiveRange()
var response = UrlFetchApp.fetch(url+"?taskRange="+taskRange).getContentText();
Logger.log(response);
}
3rd version: Using Content Service with JSON
//In standalone script
function doGet(e){
var taskRange = e.parameter.taskRange;
var ss = SpreadsheetApp.openById('SHARING_SPREADSHEET_ID');
var sh = ss.getSheetByName('Sheet1');
var protection = sh.getRange(taskRange).protect().setDescription('Completed Task')
var result = protection.removeEditors(protection.getEditors())
return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JSON)
}
//In sharing spreadsheet script
var url = "https://script.google.com/macros/s/STANDALONE_SCRIPT_ID/exec"
function onOpen(){
SpreadsheetApp.getUi().createMenu('TASK')
.addItem('Protect Task', 'protectTask')
.addToUi();
}
function protectTask(){
var taskRange = SpreadsheetApp.getActiveSheet().getActiveRange()
var response = UrlFetchApp.fetch(url+"?taskRange="+taskRange).getContentText();
var result = JSON.Parse(response)
Logger.log(result);
}
One problem is this line:
var taskRange = SpreadsheetApp.getActiveSheet().getActiveRange()
Should be:
var taskRange = SpreadsheetApp.getActiveSheet().getActiveRange().getA1Notation();
Currently, the variable taskRange is a "class" It's not a string. You need to send a string.
FINALLY IT WORKS. I think the script was not running properly because I modified many times with many kinds of code. Therefore, I've created a new one and used the "stringified" log as #SandyGood suggested.
Many thanks to you all, specially, #SandyGood.
FINAL SCRIPTS
//In standalone script
function doGet(e){
var taskRange = e.parameter.taskRange;
var ss = SpreadsheetApp.openById('SHARING_SPREADSHEET_ID');
var sh = ss.getSheetByName('Sheet1');
var protection = sh.getRange(taskRange).protect().setDescription('Completed Task');
var result = protection.removeEditors(protection.getEditors());
var resultStr = JSON.stringify(result);
Logger.log('resultStr: ' + resultStr);
}
//In sharing spreadsheet script
var url = "https://script.google.com/macros/s/STANDALONE_SCRIPT_ID/exec"
function onOpen(){
SpreadsheetApp.getUi().createMenu('TASK')
.addItem('Protect Task', 'protectTask')
.addToUi();
}
function protectTask(){
var taskRange = SpreadsheetApp.getActiveSheet().getActiveRange().getA1Notation();
var response = UrlFetchApp.fetch(url+"?taskRange="+taskRange).getContentText();
Logger.log(response);
}

Copy single worksheet to multiple workbooks within Google Drive

I am trying to copy a single worksheet to multiple workbooks within Google Drive. Just over a month ago, this code worked fine but now it doesn't because I'm thinking that the DocsList command within the code has been deprecated by Google (see https://developers.google.com/apps-script/sunset). I've heard that the new command is DriveApp but I'm not too sure. I'm a total newbie when it comes to writing code so I'm hoping someone can please fix this code?
function onOpen(){
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [];
menuEntries.push({name: "Copy Active Sheet to Other Spreadsheets", functionName: "doGet"});
spreadsheet.addMenu("Copy Sheet", menuEntries);
}
function doGet()
{
var app = UiApp.createApplication();
app.setTitle("Kishan - Copy Sheet in Multiple Spreadsheets");
var form = app.createFormPanel();
var flow = app.createFlowPanel();
var label = app.createLabel("Select Spreadsheet where you want to copy the current sheet:").setId('selectLabel');
flow.add(label);
var allfiles = DocsList.getAllFiles();
var verticalPanel = app.createVerticalPanel().setId('verticalPanel');
for(var i=0;i<allfiles.length;i++)
{
var temp = app.createCheckBox(allfiles[i].getName()).setName('cb'+i).setId('cb'+i);
var tempvalue = app.createHidden('cbvalue'+i, allfiles[i].getId());
verticalPanel.add(temp);
verticalPanel.add(tempvalue);
}
var scrollPanel = app.createScrollPanel().setId('scrollPanel');
scrollPanel.add(verticalPanel);
scrollPanel.setSize("400", "250")
flow.add(scrollPanel);
var buttonsubmit = app.createSubmitButton("Copy");
flow.add(buttonsubmit);
form.add(flow);
app.add(form);
SpreadsheetApp.getActiveSpreadsheet().show(app);
}
function doPost(eventInfo) {
var app = UiApp.getActiveApplication();
var allfiles = DocsList.getAllFiles();
var tempSsId = "";
for(var i=0;i<allfiles.length;i++)
{
var temp = eventInfo.parameter['cb'+i];
if(temp == 'on')
{
tempSsId = eventInfo.parameter['cbvalue'+i];
var activeSheet = SpreadsheetApp.getActiveSheet().copyTo(SpreadsheetApp.openById(tempSsId));
activeSheet.setName(SpreadsheetApp.getActiveSheet().getSheetName());
}
}
var label = app.createLabel('statusLabel');
label.setText("Copied Active sheet in all selected Spreadsheets...");
label.setVisible(true);
app.add(label);
return app;
}
This is the original code from [http://igoogledrive.blogspot.ca/2012/10/Google-Spreadsheet-Script-to-Copy-Sheet-to-multiple-Spreadsheets-at-a-time.html][1] that was working fine for me before but now isn't. Can anyone help?
Try this
function doGet()
{
var app = UiApp.createApplication();
app.setTitle("Kishan - Copy Sheet in Multiple Spreadsheets");
var form = app.createFormPanel();
var flow = app.createFlowPanel();
var label = app.createLabel("Select Spreadsheet where you want to copy the current sheet:").setId('selectLabel');
flow.add(label);
var allfiles = DriveApp.getFiles();
var verticalPanel = app.createVerticalPanel().setId('verticalPanel');
var i = 0;
while (allfiles.hasNext())
{
var file = allfiles.next();
var temp = app.createCheckBox(file.getName()).setName('cb'+i).setId('cb'+i);
var tempvalue = app.createHidden('cbvalue'+i, file.getId());
verticalPanel.add(temp);
verticalPanel.add(tempvalue);
i++;
}
var scrollPanel = app.createScrollPanel().setId('scrollPanel');
scrollPanel.add(verticalPanel);
scrollPanel.setSize("400", "250")
flow.add(scrollPanel);
var buttonsubmit = app.createSubmitButton("Copy");
flow.add(buttonsubmit);
form.add(flow);
app.add(form);
SpreadsheetApp.getActiveSpreadsheet().show(app);
}
function doPost(eventInfo) {
var app = UiApp.getActiveApplication();
var allfiles = DriveApp.getFiles();
var tempSsId = "";
var i = 0;
while (allfiles.hasNext())
{
var temp = eventInfo.parameter['cb'+i];
if(temp == 'on')
{
tempSsId = eventInfo.parameter['cbvalue'+i];
var activeSheet = SpreadsheetApp.getActiveSheet().copyTo(SpreadsheetApp.openById(tempSsId));
activeSheet.setName(SpreadsheetApp.getActiveSheet().getSheetName());
}
i++;
}
var label = app.createLabel('statusLabel');
label.setText("Copied Active sheet in all selected Spreadsheets...");
label.setVisible(true);
app.add(label);
return app;
}

Not replacing e.parameter

I created this script to be able to send an email after a grid has been filled with information. Before the email is sent, another display comes in an warns the user to continue only if the information is correct. At the end the script sends an email to me, with the info entered by the user. The problem is here, when I received the email, the fields that the script is suppose to replace are shown as undefined and no info is there. Any ideas on what is wrong here??
Thank you!
function runmyapp() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
var app = UiApp.createApplication().setTitle('Title 1');
var grid = app.createGrid(4, 5);
grid.setWidget(0, 0, app.createLabel('Time '));
grid.setWidget(0, 1, app.createTextBox().setName('Time'));
grid.setWidget(1, 0, app.createLabel('Minutes'));
grid.setWidget(1, 1, app.createTextBox().setName('Minutes'));
grid.setWidget(2, 0, app.createLabel('Enter Name'));
grid.setWidget(2, 1, app.createTextBox().setName('Name'));
grid.setWidget(3, 0, app.createLabel('Email'));
grid.setWidget(3, 1, app.createTextBox().setName('email'));
var panel = app.createVerticalPanel();
panel.add(grid);
var button = app.createButton('Submit').setId("button");
var handler2 = app.createServerHandler('dis');
handler2.addCallbackElement(grid);
button.addClickHandler(handler2);
var handler = app.createServerHandler('disc');
handler.addCallbackElement(grid);
button.addClickHandler(handler);
// Add the button to the panel and the panel to the application, then display the application app
panel.add(button);
app.add(panel);
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.show(app);
}
function dis(e){
var app = UiApp.getActiveApplication();
app.getElementById("button").setText("Request is in process, please wait!").setEnabled(false);
return app;
};
function disc(e){
var app = UiApp.getActiveApplication();
var html1 = app.add(app.createHTML("<p><p>Hello Expert,</p>"+
"<p>By clicking OK you agree that your information is correct</p>");
var button = app.createButton('Ok').setId("button");
app.add(button);
var handler2 = app.createServerHandler('gsnot');
button.addClickHandler(handler2);
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.show(app);
return app;}
function gsnot(e) {
var advancedArgs = {bcc:e.parameter.email};
var emailSubject = "Subject";
var address ="albdominguez25#gmail.com";
var emailTemplate =SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Templates").getRange("A1").getValue( ) ;
emailTemplate = emailTemplate.replace("TIME", e.parameter.Times).replace("MIN", e.parameter.Minutes).replace("EXP", e.parameter.Name);
MailApp.sendEmail(address, emailSubject, emailTemplate, advancedArgs);
Browser.msgBox("Your Email has been sent!");
var app = UiApp.getActiveApplication();
app.close();
// The following line is REQUIRED for the widget to actually close.
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.show(app);
}
To make a widget value show on your e.parameter you need to add it (or a parent panel) as a callback element on the handler. Like this:
function runmyapp() {
//...
var grid = app.createGrid(4, 5).setId('grid');
//...
}
function disc(e){
//...
var grid = app.getElementById('grid');
var handler2 = app.createServerHandler('gsnot').addCallbackElement(grid);
//...
}
Keep Henrique's answer as best one please.
You can try to change your disc(e) function like this :
function disc(e){
var app = UiApp.getActiveApplication();
var html1 = app.add(app.createHTML("<p><p>Hello Expert,</p>"+
"<p>By clicking OK you agree that your information is correct</p>"));
var grid = app.getElementById('grid')
var button = app.createButton('Ok').setId("button");
app.add(button);
var handler3 = app.createServerHandler('gsnot');// use a different name to avoid confusion
handler3.addCallbackElement(grid);
button.addClickHandler(handler3);
return app;}
And, also, there is a typo in your code in this line :
emailTemplate = emailTemplate.replace("TIME", e.parameter.Times).replace("MIN", e.parameter.Minutes).replace("EXP", e.parameter.Name);
Time has no 's' at the end in the original name ! ;)
and, last point, if I where you I wouldn't call show(app) in disc so the UI would keep the data validation while confirming... (but that's a matter of choice ;-)

Cannot read property "parameter" from undefined error with Logger.log

I am getting "TypeError: Cannot read property "parameter" from undefined." when trying to log e.parameter properties. (I inserted the following lines in the contactMe() function)
Logger.log(e.parameter.textBox);
Logger.log(e.parameter);
The script otherwise works fine, any idea?
function doGet() {
var app = UiApp.createApplication();
var mainPanel = app.createVerticalPanel().setId('mainPanel');
app.add(mainPanel);
mainPanel.add(app.createLabel('Enter your email to sign up'));
var form = app.createHorizontalPanel();
mainPanel.add(form);
var email = app.createTextBox().setName('textBox').setId('textBox');
form.add(email);
var button = app.createButton('Sign up');
form.add(button);
var info = app.createLabel().setVisible(true).setId('info');
mainPanel.add(info);
//handler
var handler = app.createServerHandler('contactMe').addCallbackElement(mainPanel);
button.addClickHandler(handler);
return app;
}
function contactMe(e){
var app = UiApp.getActiveApplication();
Logger.log("testing");
Logger.log(e.parameter);
Logger.log(e.parameter.textBox);
app.getElementById('textBox').setValue('').setStyleAttribute("color", "black");
app.getElementById('info').setText('Thank you!').setStyleAttribute("color", "black");
var ss = SpreadsheetApp.openById('0AqKSxC6f0Cc7dF9aT1lUeXFEcnR2eUFYRGs4Y1NiVVE')
.getSheets()[0];
var range = ss.getRange(ss.getLastRow()+1, 1, 1, 2);
var values = [[new Date(),e.parameter.textBox]];
range.setValues(values);
return app;
}
I just tested your exact code (except the sheet stuff) and it works nicely... except that the logger doesn't show anything when called from a handler function but that's a known issue...
I used the label to check the e.parameter value like this :
app.getElementById('info').setText(e.parameter.textBox).setStyleAttribute("color", "black");
A bit out of the box but i think it should work:
function doGet() {
var app = UiApp.createApplication();
var mainPanel = app.createFormPanel;
app.add(mainPanel);
mainPanel.add(app.createLabel('Enter your email to sign up'));
var form = app.createHorizontalPanel();
mainPanel.add(form);
var email = app.createTextBox().setName('textBox').setId('textBox');
form.add(email);
var button = app.createSubmitButton('Sign up');
form.add(button);
var info = app.createLabel().setVisible(true).setId('info');
mainPanel.add(info);
return app;
}
function doPost(e){
var app = UiApp.getActiveApplication();
//Logger wont work in uiApps
//in Form panels the UI is cleared so you want to write a thank you note
app.add(app.createLabel("Thanks"));
var ss = SpreadsheetApp.openById('0AqKSxC6f0Cc7dF9aT1lUeXFEcnR2eUFYRGs4Y1NiVVE')
.getSheets()[0];
var range = ss.getRange(ss.getLastRow()+1, 1, 1, 2);
var values = [[new Date(),e.parameter.textBox]];
range.setValues(values);
return app;
With kind regards,
Thomas van Latum
I just copy pasted your complete code made a spreadsheet and ran it.
It works just perfectly dont forget your } at the end.....

Google apps script : drop a document in My drive from a form in google site

I use the following code to create a kind of dropbox for my students. The form is embedded on a google site page . When the file is sent in the "dropbox" folder, it is automatically converted in a text file. I did try with a .doc, .xls and .pdf...
Should it be possible to avoid this problem ?
Thanks a lot
Jean-Paul
var folderName = "Assignments-Spring-2011";
function doGet() {
var app = UiApp.createApplication().setTitle("Upload Assignment");
app.setHeight(180);
var form = app.createFormPanel().setId('frm').setEncoding('multipart/form-data');
var formContent = app.createGrid().resize(6,2);
form.add(formContent);
formContent.setWidget(1, 0, app.createLabel('Assignment Number:'));
var assignmentNumberList = app.createListBox();
assignmentNumberList.addItem("Assignment 1");
assignmentNumberList.addItem("Assignment 2");
assignmentNumberList.addItem("Assignment 3");
assignmentNumberList.addItem("Assignment 4");
assignmentNumberList.addItem("Assignment 5");
assignmentNumberList.addItem("Assignment 6");
assignmentNumberList.addItem("Assignment 7");
assignmentNumberList.addItem("Assignment 8");
formContent.setWidget(1, 1, assignmentNumberList.setName('assignmentNumber'));
formContent.setWidget(3, 0, app.createLabel('Assignment File:'));
formContent.setWidget(3, 1, app.createFileUpload().setName('thefile'));
formContent.setWidget(5, 0, app.createSubmitButton('Submit Assignment!'));
// thank you panel
var panel = app.createSimplePanel().setVisible(false).setId("thankyouPanel");
var label = app.createLabel("Thank you for submitting the Assignment").setStyleAttribute("fontSize", "16px");
panel.add(label);
app.add(panel);
app.add(form);
return app;
}
function doPost(e) {
var doc = SpreadsheetApp.getActiveSpreadsheet();
var name = Session.getActiveUser().getUserLoginId();
var assignmentFile = e.parameter.file;
var uploadBlob = Utilities.newBlob (assignmentFile, "text/plain",e.parameter.assignmentNumber+"-"+name+"-"+e.parameter.thefile.name );
var doc = DocsList.createFile(uploadBlob);
// get assignment folder
var folder = DocsList.getFolder(folderName);
doc.addToFolder(folder);
var app = UiApp.getActiveApplication();
var form = app.getElementById("frm").setVisible(false);
var panel = app.getElementById("thankyouPanel").setVisible(true);
app.close();
return app;
}
It looks as thought he code you've used is intentionally restricting it to text:
var uploadBlob = Utilities.newBlob (assignmentFile, "text/plain",e.parameter.assignmentNumber+"-"+name+"-"+e.parameter.thefile.name );
Simply eliminate that line and redirect your variables like so
var uploadBlob = e.parameter.file;
Should set you straight.