[英]custom chart using google sheets data
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'我有一个带有列的谷歌表:'姓名,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.分数是从 0 到 20 的数值。这些数据需要转换为一个特殊但非常简单的图表,我认为在现有的图表选项中不可用。 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? ...如果不是,这可以在带有 google-scripts 或扩展的工作表中完成吗?
How could i go about efficiently creating individual charts (export to pngs) for a few hundred rows;我怎么能有效地为几百行创建单独的图表(导出到 png)? 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.要使用工作表进行此操作,您需要使用HtmlService来呈现客户端 HTML 和 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 .然后要在客户端和服务器之间进行通信(应用脚本与您的工作表和驱动器交互),您将使用google.script.run...
,请参阅客户端服务器通信。
Is this the most efficient way?这是最有效的方法吗? Probably not.可能不是。 Yet this is a reasonably concise way of doing it totally within Apps Script.然而,这是完全在 Apps Script 中执行此操作的一种相当简洁的方式。
I would test this with 10 rows, then 20, then 50 etc. In case it gets overwhelmed with too many.我会用 10 行,然后是 20 行,然后是 50 行等来测试它。以防它被太多的东西淹没。
You need two files in your Apps Script project:您的 Apps 脚本项目中需要两个文件:
<!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.通过从Code.gs
运行main
来启动脚本并对其进行授权。SpreadsheetApp.getUi().showSidebar(html);
在工作表的侧边栏中加载 HTML SpreadsheetApp.getUi().showSidebar(html);
google.script.run
) to get all the data from the spreadsheet, which it will receive as a two dimensional array.客户端 HTML 然后向主 Apps 脚本 ( google.script.run
) 发送异步请求,以从电子表格中获取所有数据,它将以二维数组的形式接收。ctx.resetTransform();
必须添加ctx.resetTransform();
and the end of the drawing function to reset the ctx properly.并在绘图 function 的末尾正确重置 ctx。The side bar appears and a chart.出现侧栏和图表。 For so few drawings, I only saw it go from white to the final chart.这么少的图纸,我只看到了从白色到最终图的go。 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!然后,如果您将 go 到您的主驱动器文件夹,您应该会看到 PNG 文件!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.