This answer is about INSERTING in-cell images. I haven't been able to find a way to actually extract image data so Panos's answer is the best option for reading in-cell image data.
There are a few different ways to do this, some of them use some undocumented APIs.
The =IMAGE
is a standard function which displays in image within a cell. It does almost the exact same thing as manually inserting an in-cell image.
2. Copied-by-value =IMAGE
Once you have an =IMAGE
image you can copy it and paste it by-value which will duplicate the image without the formula (if you want that for some reason). You can do this in a script using the copyTo
function:
srcImageRange.copyTo(dstRange, { contentsOnly: true })
This formula-less IMAGE is only distinguishable from a true in-cell image in that when you right-click on it is missing the "Alt text" and "Put image over cells" context menu options. Those options only show up on real in-cell images.
3. The undocumented CellImage
APIs
When you call getValue()
on a in-cell image (both formula and manually inserted) you get a CellImage
instance.
CellImage
Prop/method |
(Return) Type |
Description |
---|
toString() |
string |
returns "CellImage" . |
getContentUrl() |
? |
always throws an error? |
toBuilder() |
CellImageBuilder |
Convert this into an writable CellImageBuilder instance. |
getAltTextDescription() |
string |
Returns the alt text description. |
getAltTextTitle() |
string |
Returns the alt text title. |
getUrl() |
? |
Doesn't seem to work, always returns undefined. :( |
valueType |
? |
Same as SpreadsheetApp.ValueType , doesn't seem meaningful. |
CellImageBuilder
Has all the same properties and methods as CellImage
with these additional ones:
Prop/method |
(Return) Type |
Description |
---|
toString() |
string |
returns "CellImageBuilder" . |
build() |
CellImage |
Convert into a (read-only) CellImage instance. |
setSourceUrl(string) |
void |
Update the image by supplying a web or data URL. |
setAltTextTitle(string) |
void |
Sets the alt text title. |
setAltTextDescription(string) |
void |
Sets the alt text description. |
The major benefit I see with using this over IMAGE()
is that it supports data URLs and therefore indirectly supports blobs.
Working Example Code
Keep in mind the undocumented APIs might change without notice.
Link to Example Spreadhseet
// 1 (or just use IMAGE in formula directly)
function insertImageFormula(range, httpUrl) {
range.setFormula(`=IMAGE("${httpUrl}")`);
}
// 2
function insertImageValue(range, httpUrl) {
range.setFormula(`=IMAGE("${httpUrl}")`);
SpreadsheetApp.flush(); // Flush needed for image to load.
range.copyTo(range, { contentsOnly: true }); // Copy value onto itself, removing the formula.
}
// 3
function insertCellImage(range, sourceUrl) {
range.setFormula('=IMAGE("http")'); // Set blank image to get CellImageBuilder handle.
const builder = range.getValue().toBuilder();
builder.setSourceUrl(sourceUrl);
builder.setAltTextDescription(sourceUrl); // Put url in description for later identification, for example.
range.setValue(builder.build());
}
const DATA_URI = "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7///"
+ "/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAos"
+ "J6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7";
function test() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
sheet.clear();
sheet.getRange(1, 1).setValue("IMAGE formula");
insertImageFormula(sheet.getRange(2, 1), "https://www.google.com/images/icons/illustrations/paper_pencil-y128.png");
sheet.getRange(1, 2).setValue("Copied-by-value IMAGE");
insertImageValue(sheet.getRange(2, 2), "https://www.google.com/images/icons/illustrations/paper_pencil-y128.png");
sheet.getRange(1, 3).setValue("In-Cell Image (Http URL)");
insertCellImage(sheet.getRange(2, 3), "https://www.google.com/images/icons/illustrations/paper_pencil-y128.png");
sheet.getRange(1, 4).setValue("In-Cell Image (DATA URI)");
insertCellImage(sheet.getRange(2, 4), DATA_URI);
sheet.getRange(1, 5).setValue("In-Cell Image (Blob DATA URI)");
const blob = UrlFetchApp.fetch("https://www.gstatic.com/script/apps_script_1x_24dp.png").getBlob();
insertCellImage(sheet.getRange(2, 5), blobToDataUrl(blob));
}
function blobToDataUrl(blob) {
return `data:${blob.getContentType()};base64,${Utilities.base64Encode(blob.getBytes())}`
}
=IMAGE(URL)
, the image can be retrieved from the URL as a blob. – Tanaike