繁体   English   中英

使用谷歌表格数据的自定义图表

[英]custom chart using google sheets data

我是新手,所以请多多包涵:)

我有一个带有列的谷歌表:'姓名,A-Score,T-Score,R-Score,P-Score'

分数是从 0 到 20 的数值。这些数据需要转换为一个特殊但非常简单的图表,我认为在现有的图表选项中不可用。 我试图编写一些代码(即从许多堆栈溢出答案组装)来构建我需要的图形:

我的学习风格图

myCodePenDraft

问题:

  1. 我是否错过了现有图表选项中的一些基本内容,可以让我以这种方式绘制图表?

    ...如果不是,这可以在带有 google-scripts 或扩展的工作表中完成吗?

  2. 我怎么能有效地为几百行创建单独的图表(导出到 png)? 也许通过某种方式重用我到目前为止的代码。

非常感谢!

//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}

这种类型没有谷歌图表,但你可以用你建议的方法来实现你的目标。

不幸的是,谷歌目前没有此类图表的选项。 尽管您的代码看起来画得很好! 要使用工作表进行此操作,您需要使用HtmlService来呈现客户端 HTML 和 JavaScript。 然后要在客户端和服务器之间进行通信(应用脚本与您的工作表和驱动器交互),您将使用google.script.run... ,请参阅客户端服务器通信

这是最有效的方法吗? 可能不是。 然而,这是完全在 Apps Script 中执行此操作的一种相当简洁的方式。

我会用 10 行,然后是 20 行,然后是 50 行等来测试它。以防它被太多的东西淹没。

工作样本

您的 Apps 脚本项目中需要两个文件:

图.html

<!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>

代码.gs

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);
}

电子表格如下所示:

在此处输入图像描述

脚本的操作顺序

  1. 通过从Code.gs运行main来启动脚本并对其进行授权。
  2. 创建一个 HTML output,如上图所示使用客户端 JS 完成。
  3. 在工作表的侧边栏中加载 HTML SpreadsheetApp.getUi().showSidebar(html);
  4. 客户端 HTML 然后向主 Apps 脚本 ( google.script.run ) 发送异步请求,以从电子表格中获取所有数据,它将以二维数组的形式接收。
  5. 数据返回后,客户端JS将go遍历每一行,绘制图表,将其保存为dataURL字符串,并向Apps Script发送另一个异步请求,将dataURL转换为png blob,将其保存在Drive中,并返回一条消息说它已完成。

笔记

  • 尝试将其从客户端作为 blob 发送,但我遇到了奇怪的错误,因此默认使用 dataURL。
  • 必须添加ctx.resetTransform(); 并在绘图 function 的末尾正确重置 ctx。
  • 列的索引号是硬编码的,因此请注意,只有当您的电子表格格式完全相同时,此脚本才能按原样工作。

结果

出现侧栏和图表。 这么少的图纸,我只看到了从白色到最终图的go。 之后,在图表下方,开始出现完成消息:

在此处输入图像描述

然后,如果您将 go 到您的主驱动器文件夹,您应该会看到 PNG 文件!

参考

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM