20

In google apps Script you can insert an image into Google Spreadsheets using the insertImage function (https://developers.google.com/apps-script/reference/spreadsheet/sheet#insertimageblob-column-row).

But I'm not using appscript. I'm using the Google Sheets API (https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets) and I can't seem to find a way to do this. Is there any possible implementation?

3 Answers 3

23

The V4 API doesn't have the ability to insert an image blob like Apps Script does (where the image is an overlay on the sheet, not associated with any cell). You may be able to workaround this using the =IMAGE function. We know of the gap in functionality and are looking into adding support for image blobs.

Sign up to request clarification or add additional context in comments.

8 Comments

Yup, I wrote the Sheets V4 API.
@SamBerlin Any idea when this functionality could be implemented?
I have the same need. I have a blob data. I need to insert the blob in google sheet using Google Sheet API v4. You mention a workaround using =IMAGE function. How do we do this? I don't want to convert the blob into an image that can be accessed via URL
@SamBerlin can you please guide me, in V4 API functionality implemented?
+1 i'd also be interested in if/when the API functionality to insert images into G sheets will be implemented @SamBerlin.
|
8

Set the formula with script like this:

function showImage() {
 var ss=SpreadsheetApp.getActiveSpreadsheet() 
 var formulaSheet = ss.getSheetByName("Sheet1");
 var formulaCell = formulaSheet.getRange("B5");
 formulaCell.setFormula('=IMAGE("http://finviz.com/fut_chart.ashx?t=ES&p&p=m5&s=m",4,100,200)')
}

3 Comments

He Nelson, Thank you so much for the snippet of code. It's so valueable... if you have a website where you share google sheets contents. Let me know... This is great!!!
This image formula will not be exported to XLS format. It's better to use Google Apps Script Web App gateway.
Unfortunately this only supports images hosted in the web which is usually not what you want when using the Google Sheets API. It does not support BLOB and also no data URLs.
6

In the interim, this Google Apps Script Web App will do it (I recommend hosting your own rather than using this one, for privacy and security).

This works with either JSON or application/x-www-form-urlencoded, and whether the URL passed is a link or an actual base64 encoded image url like you might get from https://www.base64-image.de/.

function doGet(e) {
  return ContentService.createTextOutput("Authorization: Bearer " + ScriptApp.getOAuthToken())
}

//
// Example curl command to insert an image:
// 
// curl -L -d '{ "spreadsheetid": "1xNDWJXOekpBBV2hPseQwCRR8Qs4LcLOcSLDadVqDA0E","sheetname": "Sheet1", "imageurl": "https://www.google.com/images/srpr/logo3w.png", "column": 1, "row": 1 }' \
// -H "Authorization: Bearer <INSERT TOKEN RETURNED FROM GET HERE>" \
// -H 'Content-Type: application/json' \
// https://script.google.com/a/tillerhq.com/macros/s/AKfycbzjFgIrgCfZTvOHImuX54G90VuAgmyfz2cmaKjrsNFrTzcLpNk0/exec
//

var REQUIRED_PARAMS = [
  'spreadsheetid', // example: "1xNDWJXOekpBBV2hPseQwCRR8Qs4LcLOcSLDadVqDA0E"
  'sheetname',     // Case-sensitive; example: "Sheet1"
  'imageurl',      // Can be an url such as "https://www.google.com/images/srpr/logo3w.png"
                   // or alternately "data:image/png;base64,iVBOR...<snip>...gg=="
  'column', // 1-based (i.e. top left corner is column 1)
  'row'     // 1-based (i.e. top left corner is row 1)
];

function doPost(e) {

  var result = {
    status: "ok",
    defaultMessage: "Image inserted."
  }

  try {
    var params = (e.postData && e.postData.type == "application/x-www-form-urlencoded") ? e.parameter
    : (e.postData && e.postData.type == "application/json") ? JSON.parse(e.postData.contents)
    : undefined;


    if (!params) throw new Error('Unsupported content-type, must be either application/x-www-form-urlencoded or application/json.');

    REQUIRED_PARAMS.forEach(function(requiredParam) {
      if (!params[requiredParam]) throw new Error('Missing required parameter ' + requiredParam);
    });

    SpreadsheetApp.openById(params.spreadsheetid).getSheetByName(params.sheetname).insertImage(params.imageurl, params.column, params.row);  

  } catch(e) {

    console.error(e); 

    result.status = "error";
    result.error = e;
    result.defaultMessage = e.message;

  }  

  return ContentService.createTextOutput(JSON.stringify(result))
    .setMimeType(ContentService.MimeType.JSON)  
}

Two puzzling things I never figured out:

It worked great all along from within Postman (presumably authed with a cookie) after visiting the URL for the web app and accepting permissions. Unfortunately, I wasn't able to get it working from curl with the Oauth token returned in ScriptApp.getOAuthToken() until I manually added https://www.googleapis.com/auth/drive in the manifest -- which is still a bit of a head scratcher for me.

Here's my resulting manifest:

{
  "timeZone": "America/Los_Angeles",
  "dependencies": {
  },
  "webapp": {
    "access": "ANYONE",
    "executeAs": "USER_ACCESSING"
  },
  "exceptionLogging": "STACKDRIVER",
  "oauthScopes": ["https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/drive"]
}

I was also never able to get it to work converting to a Blob and passing that in to insertImage(), but the URL flavor of insertImage works great with full Base 64 encoded image URLs, so that's a bit annoying but this seems reasonably workable until the Sheets API gets the functionality.

The script (source) itself is shared read-only with the world here:

https://script.google.com/d/1JvFwemL45x3orxFiJf_Gye-JWXaFlzA_MysJsQx06LsH8M2psa9i1H99/edit?usp=sharing

And it's also publicly deployed here, wo if you want to test it out without deploying your own, have at it:

https://script.google.com/a/tillerhq.com/macros/s/AKfycbzjFgIrgCfZTvOHImuX54G90VuAgmyfz2cmaKjrsNFrTzcLpNk0/exec

  • Tim

5 Comments

One more note here -- if you do deploy your own rather than just using this one, it is absolutely critically imperative to keep the executeAs "USER_ACCESSING" -- otherwise that doGet route is a handy-dandy provider of YOUR access tokens, with access to most of the Drive and Sheets APIs.
How to display datepicker by double click on specific column using rest API? What is the custom validation rule for this?
When we send a blob for the imageURL we are getting the following error - result : 200 content : {"status":"error","defaultMessage":"Error retrieving image from URL or bad URL: data:image/png;base64,
dropoff_signature = "ZGF0YT <clip > WVhSaA==" web_app_url = "script.google.com/macros/s/A < clip > y/exec" image_data = "data:image/png;base64," + dropoff_signature data_to_post = { 'spreadsheetid' : spreadsheet_Id, 'sheetname' : 'Sheet1', 'imageurl' : image_data, 'column' : 5, 'row' : 5 } encoded_data = urllib.urlencode(data_to_post) # Send encoded data to application-2 url_result = urlfetch.fetch(web_app_url, encoded_data, method='POST') This is how we are calling our webapp scripts
Can the do post method be called by a service account? how to call it? what are the necessary credentials/permissions etc?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.