Let’s say that you have an Add-on which creates something in Canvas (or SVG), and you want to now embed that in a Sheet or document. Here’s how.

As an aside, the code samples here will be using the techniques in More client-server code sharing and Namespaces in libraries and scripts, which allows me to share code between Gas and HTML service and also manage the code in the Apps Script IDE as if it were regular GS code, so you may want to take a look at those for some background on the styles here.

Server code

Let’s start with Image.gs, which runs on the server and whose job it is to decide where to embed the canvas image. Calling Image.place() will insert a PNG image blob at the current cell in a Sheet.

// responsible for placing a png image on a sheet
var Image = (function(image) {
  'use strict';

  // insert an image at row / column in the sheet
  image.insert = function ( range, png) {
    range.getSheet().insertImage ( png ,  range.getColumn(), range.getRow());

  };

  // place an image
  image.place = function (png) {
    return image.insert ( SpreadsheetApp.getActiveRange() , png);
  };

  return image;

}) (Image || {});

Converting the canvas to a PNG blob

Assuming you already have your canvas plotted, all you need to do is this. Note that we don’t need to use Utilities.newBlob() back on the server, because toDataUrl() creates a blob.

Client.insertImage(canvas.toDataURL("image/png"));

Passing it off to the Server

I usually centralize all my calls to the server in a script called Client.gs. Here’s where we call the server to write the image

/**
* client stuff that's specific to the type server
*/
var Client = (function(client) {

  client.insertImage = function (png) {

    google.script.run
      .withFailureHandler(function(error) {
        App.showNotification ("Failed to insert image", error);
      })
      .withSuccessHandler(function (result) {
       
      })
      .insertImage(png);
  };

  return client;

})(Client || {});

Finally back on the server we need a global function that’s seeable by the client.

function insertImage(png) {
  return Image.place(png);
  }

embed SVG images

SVG Mime type is not supported by Sheet.insertImage(), but if SVG is your thing , you can still do this by going via Canvas. All the code above is the same, except that we need to include a couple of external JS libraries.


I’ve created a new script CanvasConvert.gs, which will run on the client.

var CanvasConvert = (function(canvasConvert) {
  'use strict';

  canvasConvert.svgToPng = function (svg) {


    // create a canvas to use, no need to actually assign it to a parent
    var canvas = document.createElement("canvas");

    // plot it on a canvas
    canvg ( canvas , svg);


    // return it as png
    return canvas.toDataURL("image/png");

  }

  return canvasConvert;

})(CanvasConvert || {});

This time, converting to a blob and passing over to the Server becomes this, where svgCode is the innerHTML of your SVG element.

Client.insertImage(CanvasConvert.svgToPng(svgCode));

HTML5

We’re using HTML5 here, so it’s not going to work on some older browsers, but if you’re using Canvas, you’re probably already got past that anyway.

For more like this see Google Apps Scripts Snippets
Why not join our cummunity,follow the blog or follow me on Twitter