I'm trying to send table charts on a daily basis to my slack channel from my google spreadsheet. The automation works when I am creating some normal charts - e.g. column charts or line charts - but it shows an error if I try the same thing with a table chart. Should I change any of my code to have this running?
function myFunction(){
var sheetUrl2 = "https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxxxxx/edit#gid=xxxxx"
var ss2 = SpreadsheetApp.openByUrl(sheetUrl2);
var sheet2 = ss2.getSheetByName("MyDailySheet");
var charts2 = sheet2.getCharts();
var chartImage2 = charts2[0].getBlob().getAs('image/jpeg').setName("graph.png");
sendSlack(chartImage2);
}
function sendSlack(chart){
var url = 'https://slack.com/api/files.upload';
var token = 'xoxp-xxxxxxxxxxxxxxxxxxxxxxxxxx';
var channel = '#general';
var payload = {
'token' : token,
'channels' : channel,
'file' : chart,
'filename' : 'DailyUsers - Last 30 Days'
};
var params = {
'method' : 'post',
'payload' : payload
};
var response = UrlFetchApp.fetch(url, params);
}
Error message:
Exception: Service Spreadsheets failed while accessing document with id xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
myFunction # DailyChart02.gs:7
This code works perfectly and sends a chart to my slack channel.
My slack app has these token scopes authorized: (bot) chat:write chat:write.public files:write (User) chat:write files:write
My table chart looks something like this. It shows perfectly on my spreadsheet file.
Issue and workaround:
I have had the same situation with you. In the current stage, it seems that the table chart cannot be directly retrieved as the image blob. This might be the current specification. So as a current workaround, I would like to propose the following flow. In this workaround, Google Slides is used as a wrapper. By the way, in your script, getAs('image/jpeg') is used. But it seems that setName("graph.png") is used. So in this modification, the mimeType uses image/png from the filename.
Retrieve the table chart from Google Spreadsheet.
Create new Google Slides as a temporal file.
Insert the table chart from Google Spreadsheet to Google Slides.
Retrieve the inserted chart on Google Slides as an image blob.
Remove the temporal Google Slides.
Use the blob to the Slack API.
By this flow, the table chart can be retrieved as the image blob. When your script is modified, it becomes as follows.
Modified script:
Please modify myFunction() as follows.
function myFunction(){
var sheetUrl2 = "https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxxxxx/edit#gid=xxxxx"
var ss2 = SpreadsheetApp.openByUrl(sheetUrl2);
var sheet2 = ss2.getSheetByName("MyDailySheet");
var charts2 = sheet2.getCharts();
// --- I added below script.
var s = SlidesApp.create("temporalSlides");
var chartImage2 = s.getSlides()[0].insertSheetsChartAsImage(charts2[0]).getBlob().setName("graph.png");
DriveApp.getFileById(s.getId()).setTrashed(true);
// ---
sendSlack(chartImage2);
}
Note:
In this case, how about reporting it to Google issue tracker as the future request? Ref
Reference:
insertSheetsChartAsImage(sourceChart)
Related
I am trying to make a google script which i want to use in Google sheets.
I followed a tutorial video on youtube and i had the idea that my script was working well.
But then two strange things happen, and i can't figure out why.
Below is my code, this code is exactly doing what i want.
It is showing the EPS of IBM in the google sheets and also in the log.
However the moment i change the APIkey from "demo" to my own APIkey it is not working anymore.
At that moment it is still showing the EPS in the LOG, but i will get an empty cell in Google Sheets.
I have no idea why that happens.
/**
* Imports api data from alphavantage
* #customfunction
*/
function apiav(a) {
var res = UrlFetchApp.fetch(
'https://www.alphavantage.co/query?function=OVERVIEW&symbol=IBM&apikey=demo'
);
var content = res.getContentText();
var json = JSON.parse(content);
var overviewvalue = json['EPS'];
Logger.log(overviewvalue);
return overviewvalue;
}
Try adding {validateHttpsCertificates: false} to your UrlFetchApp.fetch() to ignores any invalid certificates for HTTPS requests.
Your code should look like this:
function apiav(a) {
var res = UrlFetchApp.fetch('https://www.alphavantage.co/query?function=OVERVIEW&symbol=IBM&apikey=ABCDEFGH', {validateHttpsCertificates: false});
var content = res.getContentText();
var json = JSON.parse(content);
var overviewvalue = json['EPS'];
Logger.log(overviewvalue);
return overviewvalue;
}
Output:
Reference:
UrlFetchApp
So I have a google app script where I search a mail based on subject line and then take that csv and update it in an google sheet. This worked fine the first time. But going forward when I got emails with the same subject line it still pick the content of the first email and not the latest .How can I fetch data from the latest mail.
function importCSVFromGmail() {
var threads = GmailApp.search("email subject);
var message = threads[0].getMessages().slice(-1);
Log.logger(message);
var attachment = message.getAttachments()[0];
Log.logger(message.getAttachments()) ;
// Is the attachment a CSV file
if (attachment.getContentType() === "text/csv") {
var sheet = SpreadsheetApp.getActiveSheet();
var csvData = Utilities.parseCsv(attachment.getDataAsString(), ",");
// Remember to clear the content of the sheet before importing new data
sheet.clearContents().clearFormats();
sheet.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
}
}
You should be able to get the last or most recent message like that :
var message = threads[0].getMessages().slice(-1)
I have created a script in google scripts, to take a spreadsheet and fill out multiple google docs successfully. I am trying to apply this logic to filling out an HTML form, basically, we need user-generated info (in our google sheet) to fill out an HTML form on a web page.
How would I get the following function to not only open but write in the data?
This is where I am at (just using an example webpage):
function testNew(){
var js = " \
<script> \
window.open('https://colorlib.com/etc/cf/ContactFrom_v1/index.html', '_blank', 'width=800, height=600'); \
google.script.host.close(); \
</script> \
";
var html = HtmlService.createHtmlOutput(js)
.setHeight(10)
.setWidth(100);
SpreadsheetApp.getUi().showModalDialog(html, 'Now loading.'); // If you use this on Spreadsheet
// DocumentApp.getUi().showModalDialog(html, 'Now loading.'); // If you use this on Document
// SlidesApp.getUi().showModalDialog(html, 'Now loading.'); // If you use this on Slides
}
This is an example of what I did with the google docs, trying to replicate in forms:
function myFunction() {
var data = Sheets.Spreadsheets.Values.get('google sheet ID HERE', 'A2:R300');
// google doc template id, already got deal memo
var templateId = 'google doc ID HERE';
// loop through the values "i" is looping the rows, "#" is the column example: 0=a,1=b
for (var i = 0; i < data.values.length; i++) {
var date = data.values[i][0];
var email = data.values[i][1];
// grab the google doc template, create a copy, and generate the new id
var documentId = DriveApp.getFileById(templateId).makeCopy().getId();
// change the name of the new file
DriveApp.getFileById(documentId).setName(companyName+ '-' + projectName+ '-' + 'Insurance Report');
// get the document body as a variable
var body = DocumentApp.openById(documentId).getBody();
// replace values with google sheet data
body.replaceText('##Date##', date);
body.replaceText('##Email##', email);
I have many functions that I have written that interact with a lot of third party forms and websites. Don't let it fool you that all that a form is, is a human-readable way to "POST" to a url. The easier way to do this is to use the UrlFetchApp.fetch(url, options) function in Google Apps script.
I use Chrome but other browsers have this functionality as well:
open Chrome, navigate to the form and then press F12 to open up the developers window.
Click on 'Network'
fill out the form manually and then review the traffic in the 'Network' window and find the POST that your browser sent to the site,
With that highlighted, you will see a couple other tabs for 'Headers','Preview','Response'
In the 'Headers' tab, scroll to the bottom and it will show you what the request looked like. Screen shot this and send these variables through the UrlFetchApp.fetch() to the website as the 'payload' and formatted like the function below.
Look at the 'Request URL' at the top of that same 'Headers' tab and you will use that as the URL below:
function senddatatoform() {
var url = 'http://theurlthattheformpoststohere.com'; // this is the 'request url' as shown in your browser (not always the url of the form).
var payload = {
datapoint1: datapoint1value,
datapoint2: datapoint2value,
... //continue with all required post data
}
var options = {
method: "POST",
payload: payload
}
var response = UrlFetchApp.fetch(url,options);
/*this is where what you need to do next might vary -- if you're looking for a 'success' page, you might write some code here to verify that the http response is correct based on your needs.
*/
}
I am thinking of creating a google slides to Figma exporter using Google App Script. Starting out I would first like to route the shapes created in from google Slides to figma. How would I go about setting up my file? And I don't know how to set up the Oauth api communication between Google and Figma or if it's even possible.
I believe that I can start with:
References
Figma reference
https://github.com/figma/plugin-samples/blob/master/react/src/code.ts
google app script reference
https://github.com/gsuitedevs/apps-script-samples/blob/master/slides/style/style.gs#L30
Get Figma Shape
var file=projectid.key()
var=figma rectangle= file()
await figma.loadFontAsync({ family: "Roboto", style: "Regular" })
name;
var figmaShape = {
figma.ui.onmessage = msg => {
if (msg.type === 'create-rectangles') {
const nodes = []
for (let i = 0; i < msg.count; i++) {
const rect = figma.createRectangle()
rect.x = i * 150
rect.fills = [{type: 'SOLID', color: {r: 1, g: 0.5, b: 0}}]
figma.currentPage.appendChild(rect)
nodes.push(rect)
}
figma.currentPage.selection = nodes
figma.viewport.scrollAndZoomIntoView(nodes)
}
figma.closePlugin()
}
};
Get Google Docs File Shape
var powerpointfile = driveApp.getFileById = ("### Slide file ID ###")
function powerPointShape = () {
var slide = SlidesApp.getActivePresentation().getSlides()[0];
var shape = slide.insertShape(SlidesApp.ShapeType.TEXT_BOX, 100, 200, 300,
getObjectId.element(SHAPE);
};
Create new Figma file#
file.getSlides.shape = (powerPointShape, ) => {
this.powerPointShape.getRigh()=this.figmaShape(rect.x);
this.powerPointShape.getleft()=this.figmaShape(rect.y);
}
But from there would I also want to get the file id from google app script to a Figma File?
and after looking at: https://github.com/alyssaxuu/figma-to-google-slides/blob/master/Chrome%20Extension/background.js I wonder if I would have to create a chrome extension or a google Slides plugin.
How about this answer?
Issue and workaround:
Unfortunately, it seems that the shapes of Google Slides cannot be put to the page of Figma file. Because it seems that there are no methods of API for putting the shapes. But it was found that that the pages of Figma file can be retrieved as the image using Figma API.
In this answer, I would like to propose the sample script that the pages of Figma file can be put to the Google Slides as the image using Figma API with the access token. So you can directly use Figma API with Google Apps Script.
Usage:
1. Retrieve access token
You can see the method for retrieving the access token at here. Although there is also OAuth2 for retrieving the access token, in your situation, I thought that the method for directly generating the access token on the site might be suitable. So in this answer, the generated access token on the site is used. Please retrieve the access token as follows.
Generate a personal access token
Login to your Figma account.
Head to the Account Settings from the top-left menu inside Figma.
Find the Personal Access Tokens section.
Click Create new token.
A token will be generated. This will be your only chance to copy the token, so make sure you keep a copy of this in a secure place.
The access token is like #####-########-####-####-####-############. At Google Apps Script, the authorization is done by headers: {"X-Figma-Token": accessToken}.
2. Retrieve file key
In order to retrieve the Figma file using Figma API, the file key is required. You can retrieve the file key from the URL of the file.
The URL of the file is like https://www.figma.com/file/###/sampleFilename. In this case, ### is the file key.
3. Run script
The sample script is as follows. Before you run the script, please set the variables of accessToken and fileKey.
function myFunction() {
var accessToken = "###"; // Please set your access token.
var fileKey = "###"; // Please set the file key.
var baseUrl = "https://api.figma.com/v1";
var params = {
method: "get",
headers: {"X-Figma-Token": accessToken},
muteHttpExceptions: true,
};
var fileInfo = JSON.parse(UrlFetchApp.fetch(baseUrl + "/files/" + fileKey, params));
var children = JSON.parse(UrlFetchApp.fetch(baseUrl + "/images/" + fileKey + "?format=jpg&scale=3&ids=" + fileInfo.document.children.map(function(c) {return c.id}).join(","), params));
if (!children.err) {
var s = SlidesApp.create("sampleSlide");
var slide = s.getSlides()[0];
var keys = Object.keys(children.images);
keys.forEach(function(c, i) {
slide.insertImage(children.images[c]);
if (i != keys.length - 1) slide = s.insertSlide(i + 1);
})
} else {
throw new Error(children);
}
}
When myFunction() is run, at first, the file information is retrieved with the file key fileKey. Then, all pages are retrieved from the retrieved file information, and the retrieved pages are put to each slide of new Google Slides.
I think that the action of this script is similar to the script which is shown at the bottom of your question.
Note:
This is a sample script. So please modify it for your actual situation.
References:
Figma API
Class UrlFetchApp
Class SlidesApp
If I misunderstood your question and this was not the direction you want, I apologize.
I am writing a google script on top of a spreadsheet.
I want to deploy it as a web app.
It shows some values.
Unfortunately, with my current code, google reminds me:
TypeError: Cannot call method "getSheetByName" of null.
I have no idea where the mistake is.
Here's the code
function doGet(e) {
var app = UiApp.createApplication().setTitle('Details');
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var dataFromCell = ss.getRange("B4").getValue();
var mypanel = app.createVerticalPanel();
var label = app.createLabel(dataFromCell);
app.add(mypanel);
app.add(label);
return app;
}
In standalone webapps you cannot use getActiveSpreadsheet because no one is using it actively...
Use SpreadsheetApp.openById('ID') instead, you can get the ID in the url of your spreadsheet like in this example :
https://docs.google.com/spreadsheet/ccc?key=0AnqSFd3iikE3d-------nZIV0JQQ0c1a3dWX1dQbGc#gid=0
between key= and #, ie 0AnqSFd3iikE3d-------nZIV0JQQ0c1a3dWX1dQbGc
Not need to use ID , just try this code ( change mygooglelocation with your Spreadsheet name and range of cells. Working very well for me with google maps...
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('mygooglelocation');
var ss = SpreadsheetApp.getActive();
var mylocationInfo = ss.getRange("A2:B4").getValues();