I´m learning how to use the Google Scripts, I saw a video on the youtube and I wrote this code based on the video. It will be a dashboard, but the problem I have is: In this spreadsheet, I have more than one Sheet. How can I "tell" the code which sheet it would have to check? In my case the Sheet ID is 8.
I think this would be the only "mistake" in the code!
Thanks for helping!
function doGet() {
// Identify the spreadsheet where the data is stored.
var ss = SpreadsheetApp.openById('0AjizIuAuEzaydFlsRDRrTkZSekROaWNZNV9QbjRDdUE')
var data = ss.getDataRange();
// Create all the filters
var clienteFilter = Charts.newNumberRangeFilter().setFilterColumnIndex(1).build();
var pedidoFilter = Charts.newNumberRangeFilter().setFilterColumnIndex(2).build();
var necessidadeFilter = Charts.newCategoryFilter().setFilterColumnIndex(3).build();
var entregaFilter = Charts.newCategoryFilter().setFilterColumnIndex(4).build();
var notaconsultorFilter = Charts.newNumberRangeFilter().setFilterColumnIndex(5).build();
var notaentregadorFilter = Charts.newNumberRangeFilter().setFilterColumnIndex(6).build();
var recomendariaFilter = Charts.newCategoryFilter().setFilterColumnIndex(8).build();
var atencaoFilter = Charts.newCategoryFilter().setFilterColumnIndex(9).build();
var servicosFilter = Charts.newCategoryFilter().setFilterColumnIndex(10).build();
var entregadorFilter = Charts.newCategoryFilter().setFilterColumnIndex(11).build();
// Create all the charts
var pieChart = Charts.newPieChart()
.setDataViewDefinition(Charts.newDataViewDefinition().setColumns([11,6]))
.build();
// Create the dashboard
var dashboard = Charts.newDashboardPanel().setDataTable(data)
.bind([clienteFilter, pedidoFilter, necessidadeFilter, entregaFilter, notaconsultorFilter, notaentregadorFilter, recomendariaFilter, atencaoFilter, servicosFilter, entregadorFilter],[pieChart])
.build();
// Create the webapp and bind together the filters and charts
var app = UiApp.createApplication();
var filterPanel = app.createVerticalPanel();
var chartPanel = app.createHorizontalPanel();
filterPanel.add(clienteFilter).add(pedidoFilter).add(necessidadeFilter).add(entregaFilter).add(notaconsultorFilter).add(notaentregadorFilter).add(recomendariaFilter).add(atencaoFilter).add(servicosFilter).add(entregadorFilter).setSpacing(10);
chartPanel.add(pieChart).setSpacing(10);
// Format the dashboard layout
dashboard.add(app.createVerticalPanel().add(filterPanel).add(chartPanel));
app.add(dashboard);
return app;
}
in your code , ss comes for a spreadSheet object, which is -way of speaking - the "parent" of the included sheets.
This class (spreadsheet object) has a couple of methods to get sheets that are described in the documentation, for example getSheetByName('name of the sheet') or getSheets() which returns an array of sheet objects. In this case you can chose which one you use with getSheets()[number]
Related
I've been struggling to build a specific weekly stock system reports. So to give you a basic overview, I have a mastersheet that I want to generate reports from, triggered by an UI button. The first step however is to create a folder for that week to place the PDF's in. I can create the folder, and I can generate the PDF in my root Google Drive folder, but I can't seem to move the PDF anywhere after that. I have attempted to use .moveTo() but I can't get that to work. Does anyone have any advise?
function onOpen(e)
{
SpreadsheetApp.getUi()
.createMenu('Physical')
.addItem('New folder','newFolder')
.addItem('Generate PDF','generatePDF')
.addToUi();
}
function newFolder(){
var today = new Date();
var week = Utilities.formatDate(today, "Europe/Amsterdam", "w"); //need to find a way to minus 1 for the current week
var spreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId(); //time to create a new folder
var spreadsheetFile = DriveApp.getFileById(spreadsheetId);
var folderId = spreadsheetFile.getParents().next().getId();
var parFolder = DriveApp.getFolderById(folderId)
var destFolder = parFolder.createFolder('Week ' + week);
}
function generatePDF(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var speadsheetFile = ss.getId();
var file = DriveApp.getFileById(speadsheetFile);
var folderId = file.getParents().next().getId();
var pdf = DriveApp.createFile(ss.getBlob())
pdf.moveTo(folderId); //find way to move file either to destination folder or to parent folder
}
Description
These types of situations are hard to test because the circumstances are specific to the OP questioner. However, I believe this will work.
Using the PropertyService Script Properties, store the newly created folderId and then get that id from Script Properties to move the file.
A note of caution, I didn't check for the case if the week changes and a new folder is not created, the pdf will go to the previous week folder.
Regarding creating a button and linking a function to the button see this article Buttons in Google Sheets
Script
function newFolder(){
var today = new Date();
var week = Utilities.formatDate(today, "Europe/Amsterdam", "w"); //need to find a way to minus 1 for the current week
var spreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId(); //time to create a new folder
var spreadsheetFile = DriveApp.getFileById(spreadsheetId);
var folderId = spreadsheetFile.getParents().next().getId();
var parFolder = DriveApp.getFolderById(folderId);
var folderName = 'Week '+week;
// check if folder already exists
var subFolders = parFolder.getFoldersByName(folderName);
var destFolder = null;
if( subFolders.hasNext() ) {
SpreadsheetApp.getUi().alert("Folder "+folderName+" already exists");
destFolder = subFolders.next();
}
else {
destFolder = parFolder.createFolder(folderName);
}
// store folder id to Script Properties
var props = PropertiesService.getScriptProperties();
props.setProperty("foldeId",destFolder.getId());
}
function generatePDF(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
// get folder id from Script Properties
var folderId = PropertiesService.getScriptProperties("folderId");
if( !folderId ) {
SpreadsheetApp.getUi().alert("Property folderId not found");
return;
}
var pdf = DriveApp.createFile(ss.getBlob())
pdf.moveTo(folderId); //find way to move file either to destination folder or to parent folder
}
Reference
SpreadsheetApp.getUi().alert()
PropetiesService
I have an API response that I'm trying to place in my spreadsheet.
I managed to figure out how to call it using the following code but it all goes to the first cell. How do I make each value go to a different cell?
function callCandles() {
var response = UrlFetchApp.fetch("https://api-pub.bitfinex.com/v2/candles/trade:1D:tBTCUSD/hist?limit=1000&start=1577841154000&end=1606785154000&sort=-1");
Logger.log(response.getContentText());
var fact = response.getContentText();
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(1,1).setValue([fact])
}
This is the correct way to set the values in a sheet. Avoid using for loops with appendRow. It can be extremely slow for a relatively small amount of data.
Suggested solution:
function myFunction() {
var response = UrlFetchApp.fetch("https://api-pub.bitfinex.com/v2/candles/trade:1D:tBTCUSD/hist?limit=1000&start=1577841154000&end=1606785154000&sort=-1");
var fact = JSON.parse(response.getContentText());
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(sheet.getLastRow()+1,1,fact.length,fact[0].length).setValues(fact);
}
Try something like this,
var response = UrlFetchApp.fetch("https://api-pub.bitfinex.com/v2/candles/trade:1D:tBTCUSD/hist?limit=1000&start=1577841154000&end=1606785154000&sort=-1");
Logger.log(response.getContentText());
var fact = JSON.parse(response.getContentText());
var sheet = SpreadsheetApp.getActiveSheet();
fact.forEach(row => {
sheet.appendRow(row);
});
Hope you got some idea.
I want to write a app which generates a spreadsheet in my google-drive with the user input data with google-app scripts.
For doing so I have several JavaScript-functions I want to execute one after the other:
function createSpreadsheet(name){
var ss=SpreadsheetApp.create(name);
var ssID = ss.getID()
}
function writeData(data){
var s = ss.getSheets()[0];
s.getRange('A1').setValue(data);
}
which are called by the frond-end script via:
<script>
function parse_to_backend(){
var name = document.getElementById("user_name").value;
var data = document.getElementById("user_data").value;
google.script.run.createSpreadsheet(name);
google.script.run.writeData(data);
};
</script>
how can I achieve that the writeData knows ssID the ID of the spreadsheet (I can not return values to the frontend with google.script.run and parse it as an argument)?
You want to create new Spreadsheet from HTML side.
You want to put the value to the created Spreadsheet from HTML side.
In your situation, you don't want to put writeData() in createSpreadsheet(). Namely, you want to individually use both functions.
If my understanding is correct, how about this answer? Please think of this as just one of several answers.
At first, the modification point is as follows.
Modification point:
When you run the script as follows,
google.script.run.createSpreadsheet(name);
google.script.run.writeData(data);
Function of writeData() is run before the function of createSpreadsheet() is finished, because google.script.run works by the asynchronous process. In order to avoid this, in this sample script, withSuccessHandler() is used.
About the modified script, I introduce 2 patterns. Please select one of them.
Pattern 1:
In this pattern, file ID is returned from createSpreadsheet() and the value is put to the created Spreadsheet using the file ID.
Code.gs: Google Apps Script
function createSpreadsheet(name){
var ss = SpreadsheetApp.create(name);
var ssID = ss.getId();
return ssID;
}
function writeData(id, data){
var ss = SpreadsheetApp.openById(id);
var s = ss.getSheets()[0];
s.getRange('A1').setValue(data);
}
index.html: HTML and Javascript
<script>
function parse_to_backend(){
var name = document.getElementById("user_name").value;
var data = document.getElementById("user_data").value;
google.script.run.withSuccessHandler((id) => {
google.script.run.writeData(id, data);
}).createSpreadsheet(name);
};
</script>
Pattern 2:
In this pattern, file ID is saved by PropertiesService and the value is put to the created Spreadsheet using the file ID got from PropertiesService. In this case, the file ID is saved to PropertiesService. So the created Spreadsheet can be also used by other action of Javascript using the file ID got from PropertiesService.
Code.gs: Google Apps Script
function createSpreadsheet(name){
var ss = SpreadsheetApp.create(name);
var ssID = ss.getId();
PropertiesService.getScriptProperties().setProperty("ssID", ssID);
}
function writeData(data){
var id = PropertiesService.getScriptProperties().getProperty("ssID");
var ss = SpreadsheetApp.openById(id);
var s = ss.getSheets()[0];
s.getRange('A1').setValue(data);
}
index.html: HTML and Javascript
<script>
function parse_to_backend(){
var name = document.getElementById("user_name").value;
var data = document.getElementById("user_data").value;
google.script.run.withSuccessHandler(() => {
google.script.run.writeData(data);
}).createSpreadsheet(name);
};
</script>
References:
Class google.script.run
withSuccessHandler()
Class PropertiesService
If I misunderstood your question and this answer was not what you want, I apologize.
I'm currently trying to develope a JavaScript Compiler with the help of an Antlr4 Visitor. I've got this already implemented with Java but cannot figure out how to do this in JavaScript. Probably somebody can answer me a few questions?
1: In Java there is a Visitor.visit function. If im right this isn't possibile with Javascript. Is there a work around for this?
2: My Javascript Visitor got all the generated visiting functions but when I use console.log(ctx) the context is undefined. Any idea why?
Extract from the SimpleVisitor.js:
// Visit a parse tree produced by SimpleParser#parse.
SimpleVisitor.prototype.visitParse = function(ctx) {
console.log(ctx);
};
Main js file:
var antlr4 = require('lib/antlr4/index');
var SimpleLexer = require('antlr4/SimpleLexer');
var SimpleParser = require('antlr4/SimpleParser');
var SimpleVisitor = require('antlr4/SimpleVisitor');
var input = "double hallo = 1;";
var chars = new antlr4.InputStream(input);
var lexer = new SimpleLexer.SimpleLexer(chars);
var tokens = new antlr4.CommonTokenStream(lexer);
var parser = new SimpleParser.SimpleParser(tokens);
var visitor = new SimpleVisitor.SimpleVisitor();
parser.buildParseTrees = true;
var tree = parser.parse();
visitor.visitParse();
This is probably enough to start with ...
Bruno
Edit:
Probably the context is undefined because I call the function without arguments but where do I get the "starting"-context?
Edit2:
So I think I get the idea how this should work out. One Question remaining how do I determine which rule to call next inside each visitor function?
The basic idea behind the visitor is that you have to handle all the logic by yourself. To do this I generated the visitor using antlr. My own visitor overrides all functions that I need to implement my logic.
create lexer, tokens, ...
var antlr4 = require('antlr4/index');
var SimpleJavaLexer = require('generated/GrammarLexer');
var SimpleJavaParser = require('generated/GrammarParser');
var SimpleJavaVisitor = require('generated/GrammarVisitor');
var Visitor = require('./Visitor');
var input = "TestInput";
var chars = new antlr4.InputStream(input);
var lexer = new GrammarLexer.GrammarLexer(chars);
var tokens = new antlr4.CommonTokenStream(lexer);
var parser = new GrammarParser.GrammarParser(tokens);
var visitor = new Visitor.Visitor();
parser.buildParseTrees = true;
var tree = parser.parse();
and call your entry function
visitor.visitTest(tree);
inside your new visitor you need to implement your new logic to determine which function to call next (the right context as argument is important)
var GrammarVisitor = require('generated/GrammarVisitor').GrammarVisitor;
function Visitor () {
SimpleJavaVisitor.call(this);
return this;
};
Visitor.prototype = Object.create(GrammarVisitor.prototype);
Visitor.prototype.constructor = Visitor;
Visitor.prototype.visitTest = function(ctx) {
// implement logic to determine which function to visit
// then call next function and with the right context
this.visitBlock(ctx.block());
};
I hope you can understand my basic idea. If anybody got any questions just comment.
I followed the documentation
var workbook = createAndFillWorkbook();
and I get this
error Object # has no method 'createAndFillWorkbook'
even if I required exceljs already
var Excel = require("exceljs");
What I wanted to do was to create a report but I am somehow confused on the documentation because it does not say here how to use the createAndFillWorkbook() method it just says here to use it right away.
I referred here in the documentation: https://github.com/guyonroche/exceljs#writing-xlsx
createAndFillWorkbook(); does not mean a function.(maybe pseudo function)
You must create some workbook then fill content.
See below.
// create workbook by api.
var workbook = new Excel.Workbook();
// must create one more sheet.
var sheet = workbook.addWorksheet("My Sheet");
// you can create xlsx file now.
workbook.xlsx.writeFile("C:\\somepath\\some.xlsx").then(function() {
console.log("xls file is written.");
});
var excel = require("exceljs");
var workbook1 = new excel.Workbook();
workbook1.creator = 'Me';
workbook1.lastModifiedBy = 'Me';
workbook1.created = new Date();
workbook1.modified = new Date();
var sheet1 = workbook1.addWorksheet('Sheet1');
var reColumns=[
{header:'FirstName',key:'firstname'},
{header:'LastName',key:'lastname'},
{header:'Other Name',key:'othername'}
];
sheet1.columns = reColumns;
workbook1.xlsx.writeFile("./uploads/error.xlsx").then(function() {
console.log("xlsx file is written.");
});
This is my sample code which works for me.