I'm new to this, so please bear with me:)
I have a google sheet with columns: 'Name, A-Score,T-Score, R-Score, P-Score'
Scores are numerical values from 0 to 20. This data needs to be converted to a special, but very simple graph which i don't think is available in the existing sheets charting options. I've tried to write some code (ie assembled from many stack overflow answers) to construct the graph i need:
Question:
Have i missed something basic in the existing chart options that would let me graph this way?
...if not, is this possible to do in sheets with google-scripts or extensions?
How could i go about efficiently creating individual charts (export to pngs) for a few hundred rows; perhaps by somehow reusing the code i've got so far.
Thanks so much!
//javascript
//data from sheets
var Name = "santayan";
var Activist = 12;
var Theorist = 9;
var Reflector = 14;
var Pragmatist = 12;
//set up canvas
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
//set up click target
var link = document.getElementById("link");
//reset coordinates and white bg
ctx.translate(200, 200);
ctx.beginPath();
ctx.rect(-200, -200, 400, 400);
ctx.fillStyle = "white";
ctx.fill();
//plot main graph
ctx.lineCap = "round";
ctx.lineWidth = 5;
ctx.strokeStyle = "#806";
ctx.beginPath();
ctx.moveTo(Theorist * 10, 0);
ctx.lineTo(0, Reflector * 10);
ctx.lineTo(Activist * -10, 0);
ctx.lineTo(0, Pragmatist * -10);
ctx.closePath();
ctx.stroke();
//plot axes and labels
ctx.strokeStyle = "#d3d3d3";
ctx.lineWidth = 1;
ctx.moveTo(-200, 0);
ctx.lineTo(200, 0);
ctx.moveTo(0, -200);
ctx.lineTo(0, 200);
ctx.stroke();
ctx.font = "1em Helvetica";
ctx.textAlign = "right";
ctx.fillStyle = "#806";
ctx.fillText(Name, 195, -185);
ctx.font = ".5em Helvetica";
ctx.fillText("LEARNING STYLE", 195, -170);
ctx.fillStyle = "#000";
ctx.textAlign = "center";
ctx.fillText("ACTIVIST", -170, 12);
ctx.fillText("THEORIST", 170, -5);
ctx.rotate(Math.PI / 2);
ctx.fillText("PRAGMATIST", -165, 12);
ctx.fillText("REFLECTOR", 170, -5);
//click handler
function downloadImage() {
link.setAttribute("download", Name + " LearningStyle.png");
link.setAttribute(
"href",
canvas.toDataURL("image/png").replace("image/png", "image/octet-stream")
);
}
//html
<div class="container"> <a id="link" OnClick=downloadImage()><canvas id="myCanvas" width="400" height="400" </canvas></a> click on the image to download</div>
//css
a{cursor:pointer}body{font-family:Helvetica,Sans;font-size:.8em;text-align:right;background-color:#888;margin:0}.container{width:440px;height:460px;display:block;background-color:#aaa;margin:0 auto;padding:10px}canvas{box-sizing:border-box;background:#fff;padding:20px;margin:0 auto;border:1px solid grey;border-box:inner}
Unfortunately there is no option for this type of chart in Google at the moment. Though your code looks like it draws it fine! To get this working with a sheet you would need to use the HtmlService to render client side HTML and JavaScript. Then to communicate between the client and server (Apps Script to interface with your sheet and drive), you would use google.script.run...
, see Client Server Communications .
Is this the most efficient way? Probably not. Yet this is a reasonably concise way of doing it totally within Apps Script.
I would test this with 10 rows, then 20, then 50 etc. In case it gets overwhelmed with too many.
You need two files in your Apps Script project:
<!DOCTYPE html>
<html>
<head>
<style>
a {cursor:pointer;}body{font-family:Helvetica,Sans;font-size:.8em;text-align:right;background-color:#888;margin:0}.container{width:440px;height:460px;display:block;background-color:#aaa;margin:0 auto;padding:10px}canvas{box-sizing:border-box;background:#fff;padding:20px;margin:0 auto;border:1px solid grey;border-box:inner}
</style>
</head>
<body>
<div class="container">
<canvas id="myCanvas" width="400" height="400"></canvas>
</div>
</body>
<script>
// Your drawing code wrapped in a function
function drawChart(Name, Activist, Theorist, Reflector, Pragmatist){
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
//reset coordinates and white bg
ctx.translate(200, 200);
ctx.beginPath();
ctx.rect(-200, -200, 400, 400);
ctx.fillStyle = "white";
ctx.fill();
//plot main graph
ctx.lineCap = "round";
ctx.lineWidth = 5;
ctx.strokeStyle = "#806";
ctx.beginPath();
ctx.moveTo(Theorist * 10, 0);
ctx.lineTo(0, Reflector * 10);
ctx.lineTo(Activist * -10, 0);
ctx.lineTo(0, Pragmatist * -10);
ctx.closePath();
ctx.stroke();
//plot axes and labels
ctx.strokeStyle = "#d3d3d3";
ctx.lineWidth = 1;
ctx.moveTo(-200, 0);
ctx.lineTo(200, 0);
ctx.moveTo(0, -200);
ctx.lineTo(0, 200);
ctx.stroke();
ctx.font = "1em Helvetica";
ctx.textAlign = "right";
ctx.fillStyle = "#806";
ctx.fillText(Name, 195, -185);
ctx.font = ".5em Helvetica";
ctx.fillText("LEARNING STYLE", 195, -170);
ctx.fillStyle = "#000";
ctx.textAlign = "center";
ctx.fillText("ACTIVIST", -170, 12);
ctx.fillText("THEORIST", 170, -5);
ctx.rotate(Math.PI / 2);
ctx.fillText("PRAGMATIST", -165, 12);
ctx.fillText("REFLECTOR", 170, -5);
// Had to add this to reset the canvas properly
ctx.resetTransform();
}
function getImage(Name) {
var canvas = document.getElementById("myCanvas");
var dataURL = canvas.toDataURL("image/png");
return dataURL;
}
function notification(msg){
let message = document.createElement("p");
message.textContent = msg
document.body.appendChild(message)
}
function main(data){
// data is 2D array
data.forEach(row => {
drawChart(row[0], row[1], row[2], row[3], row[4]);
let png = getImage();
google.script.run.withSuccessHandler(notification).saveToDrive(row[0], png)
})
}
google.script.run.withSuccessHandler(main).getData();
</script>
</html>
function getData() {
let file = SpreadsheetApp.getActive();
let sheet = file.getSheetByName("Sheet1");
let range = sheet.getDataRange();
let values = range.getValues();
// Get rid of headers
values.shift()
return values;
}
function saveToDrive(name, dataURL){
// https://stackoverflow.com/questions/56092146/convert-data-uri-using-google-apps-script-blob
var type = (dataURL.split(";")[0]).replace('data:','');
var imageUpload = Utilities.base64Decode(dataURL.split(",")[1]);
var blob = Utilities.newBlob(imageUpload, type, name + ".png");
let newFile = DriveApp.createFile(blob);
newFile.setName(name)
return name + "'s chart saved!"
}
function main(){
let html = HtmlService.createHtmlOutputFromFile("chart.html");
SpreadsheetApp.getUi().showSidebar(html);
}
Spreadsheet looks like this:
main
from Code.gs
and authorize it.SpreadsheetApp.getUi().showSidebar(html);
google.script.run
) to get all the data from the spreadsheet, which it will receive as a two dimensional array.ctx.resetTransform();
and the end of the drawing function to reset the ctx properly.The side bar appears and a chart. For so few drawings, I only saw it go from white to the final chart. Afterwards, below the chart, the completion messages start to appear:
Then if you go to your main Drive folder, you should see the PNG files!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.