Getting image url in google script - google-apps-script

Trying to get image url in google script.
couldn’t find any function that is able to get the url from images that are not in a specific cell, images are located above the grid.
any ideas?

Issue and workaround:
On October 30, 2018, in order to manage the images on the cells in Spreadsheet, a new Class of OverGridImage has been added. Ref By this, the images on the cells got to be able to be managed. This class has the method of getUrl. The official document of this method says as follows.
Gets the image's source URL; returns null if the URL is unavailable. If the image was inserted by URL using an API, this method returns the URL provided during image insertion.
Namely, for example, when the following script is run, the URL of the image can be retrieved.
function sample1() {
const sheet = SpreadsheetApp.getActiveSheet();
// Put image from URL.
sheet.insertImage("https://stackoverflow.design/assets/img/logos/so/logo-stackoverflow.png", 1, 1);
// Retrieve image URL.
const images = sheet.getImages();
const url = images[0].getUrl();
console.log(url)
}
In your actual situation, if your images are put on the cells using the above script, the URLs can be retrieved by the above simple script. But, here, there is an important point. After the image was put using this script, when you manually move the image, the URL cannot be retrieved. I think that this is a bug.
And also, if you had manually put the images from the URL and your drive, unfortunately, the URL of the images cannot be retrieved. About this, it has already been reported to the Google issue tracker. Ref
If you had manually put the images from the URL and your drive, and when you want to retrieve the URLs of the images, it is required to use a workaround. In this case, I would like to propose to use this method of this answer. In this answer, my created Google Apps Script library is used.
Usage:
1. Install Google Apps Script library.
You can see the method for installing this library at here.
2. Enable Drive API.
In this case, Drive API is used. So, please enable Drive API at Advanced Google services.
3. Sample script.
function sample2() {
const sheetName = "Sheet1"; // Please set the sheet name.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName(sheetName);
const images = sheet.getImages();
const obj = images.reduce((o, e) => {
const u = e.getUrl();
if (u) o[e.getAnchorCell().getA1Notation()] = u;
return o;
}, {});
const res = DocsServiceApp.openBySpreadsheetId(ss.getId()).getSheetByName(sheetName).getImages();
if (res.length == 0) return;
const urls = res.map(({ image, range }, i) => {
if (obj[range.a1Notation]) return obj[range.a1Notation];
const o = Drive.Files.insert({ title: `sample${i + 1}` }, image.blob);
const url = o.thumbnailLink.replace(/\=s\d+/, "=s1000");
DriveApp.getFileById(o.id).setTrashed(true);
return url;
});
console.log(urls)
}
4. Testing.
When the above script is run, the images are retrieved from "Sheet1" and retrieve the URLs of the images. For example, when there are images put with the image URL using the script, the URL can be retrieved.
Note:
In this workaround, in order to retrieve the URL of the image, the thumbnail link is used. This link is not permanent. Please be careful about this. If you are required to retrieve the permanent link, please create the retrieved image file blob as the file, and please publicly share them, and then, please retrieve the WebContentLink. By this, you can retrieve the permanent link of the image.
References:
DocsServiceApp
Related thread
How to access new 'in-cell-image' from google apps script?

Related

Issue getting full page Screenshot of website using PageSpeedApi and Google Apps Script

I am trying to get the screenshot from this link to Google Drive using Google Apps Script. For that, I found this source to make it work. I tried to modify the script but the result is not exactly what I am looking to achieve. Here is the script:
function getScreenShot(){
const apiKey = "###";
const url1 = "http://www.amafruits.com";
const apiEndpoint = `https://www.googleapis.com/pagespeedonline/v5/runPagespeed?key=${apiKey}&url=${encodeURIComponent(url1)}&category=performance&strategy=mobile`;
const res = UrlFetchApp.fetch(apiEndpoint)
const obj = JSON.parse(res.getContentText());
const base64 = obj["lighthouseResult"]["audits"]["final-screenshot"][
"details"
]["data"]
.split(",")
.pop();
const blob = Utilities.newBlob(
Utilities.base64Decode(base64),
"image/jpeg",
"sample1.jpg"
);
const id = DriveApp.createFile(blob).getId();
console.log(id);
}
However, it gives the following output:
Ideally, I want to get the following screenshot from the website:
How do I get the full page screenshot instead of just one small portion? Any guidance would be much appreciated. Thank you for your time.
In your situation, how about the following sample script?
Sample script:
In this sample script, I retrieved the screenshot from https://pagespeed.web.dev/report?url=http%3A%2F%2Fwww.amafruits.com%2F using Charts Service.
function myFunction() {
const url = "https://pagespeed.web.dev/report?url=http%3A%2F%2Fwww.amafruits.com%2F"; // This URL is from your question.
const blob = Charts
.newTableChart()
.setDataTable(Charts.newDataTable().addColumn(Charts.ColumnType.STRING, "").addRow([`<meta http-equiv="refresh" content="0; URL='${url}'">`]).build())
.setOption('allowHtml', true)
.setDimensions(1000, 2000)
.build()
.getBlob();
DriveApp.createFile(blob.setName("sample.png"));
}
When this script is run, the whole page is retrieved as a PNG file. That image includes your expected situation. Unfortunately, if you want to retrieve only your showing image, it is required to edit the exported image.
Note:
In this case, when the image size is smaller than the HTML page, please adjust .setDimensions(1000, 2000), and test it again.
In this sample, it seems that all URLs cannot be used. Please be careful about this.
Reference:
Charts Service

Insert Image from Google Sheets cell into Google Slides [duplicate]

The new function Insert > Image > Image in Cell in Google sheets inserts an image in a cell and not as an OverGridImage.
I would like to insert the image in this manner and then access the image from Google Apps Script. Is this possible?
After inserting the image the formula of the cell is blank when the cell is selected. I tried searching the GAS reference, but I could not find any information on this relatively new feature.
There is information on the over grid images. I would expect the in-cell image to have similar functions.
I've tried things like this:
// See what information is available on a cell with inserted image:
var image = sheet.getRange(1, 1).getFormula();
Logger.log(image);
The logs shows up empty.
I tried several: .getImage() (does not exist), .getValue(), .getFormula()
I would expect to be able to access the image URL or Blob in some way.
Answer:
This is a new feature and unfortunately at current there isn’t a method to be able to get an image inserted into a Cell this way using Google Apps Script, nor using the Sheets API.
More Information:
Attempting to get the data in a cell using the spreadsheets.get method with the following parameters
spreadsheetId: "ID of private spreadsheet created in Drive"
includeGridData: True
ranges: D7
fields: sheets/data/rowData/values
Will return a 200 response, however the image data is not returned:
{
"sheets": [
{
"data": [
{
"rowData": [
{
"values": [
{
"userEnteredValue": {},
"effectiveValue": {},
"effectiveFormat": {
"backgroundColor": {
"red": 1,
"green": 1,
"blue": 1
},
"padding": {
"top": 2,
"right": 3,
"bottom": 2,
"left": 3
},
"horizontalAlignment": "LEFT",
"verticalAlignment": "BOTTOM",
"wrapStrategy": "OVERFLOW_CELL",
"textFormat": {
"foregroundColor": {},
"fontFamily": "Arial",
"fontSize": 10,
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false
},
"hyperlinkDisplayType": "PLAIN_TEXT"
}
}
]
}
]
}
]
}
]
}
Feature Request:
There is however a Feature request for this on Google’s Issue Tracker which you can find here. If you head over to the feature request page and click the star in the top left, you can let Google know that you also would like this feature, and will automatically get updates about its progress.
I believe your goal as follows.
You want to retrieve the image in the cell of Google Spreadsheet using Google Apps Script.
Issue and workaround:
Unfortunately, in the current stage, there are no methods for retrieving the images in the cell on Spreadsheet in Spreadsheet service and Sheets API. This has already been mentioned by Rafa Guillermo's answer. So in this answer, I would like to propose a workaround for retrieving the images in the cells using Google Apps Script.
In this workaround, I use Microsoft Excel Data converted from Google Spreadsheet. Even when Google Spreadsheet is converted to Microsoft Excel Data, the images in the cells are not removed. I use this. Of course, the images can be also retrieved from HTML data converted from Spreadsheet. But in this case, the parse of HTML data is a bit complicated than that of Excel data. So here, I would like to propose to retrieve the images from Excel Data converted from Spreadsheet. The flow of this workaround is as follows.
Convert Google Spreadsheet to Microsoft Excel (XLSX data) using Drive API.
Parse XLSX data using Google Apps Script.
When the converted XLSX data is unzipped, the data can be analyzed as the XML data. Fortunately, at Microsoft Docs, the detail specification is published as Open XML. So in this case, Microsoft Docs like XLSX, DOCX and PPTX can be analyzed using XmlService of Google Apps Script. I think that this method will be also useful for other situations.
Retrieve images from XLSX data.
Pattern 1:
In this pattern, I would like to introduce a simple method.
Sample script:
function myFunction() {
const spreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
const url = "https://docs.google.com/spreadsheets/export?exportFormat=xlsx&id=" + spreadsheetId;
const blob = UrlFetchApp.fetch(url, {headers: {authorization: `Bearer ${ScriptApp.getOAuthToken()}`}}).getBlob().setContentType(MimeType.ZIP);
const xlsx = Utilities.unzip(blob);
xlsx.forEach(b => {
const name = b.getName().match(/xl\/media\/(.+)/);
if (name) DriveApp.createFile(b.setName(name[1]));
});
}
In this sample script, all images in the Spreadsheet are exported as the files. So in this case, both images in the cells and over the cells from all sheets in the Spreadsheet are retrieved. And also, it cannot retrieve the cell coordinate that the image is in the cell.
In the current stage, there are no methods for retrieving the images in Google Spreadsheet as the blob. In this sample script, this can be achieved.
This sample script cannot export the drawings. Please be careful this.
When setContentType(MimeType.ZIP) is not used, an error occurs at Utilities.unzip(blob). Please be careful this.
Pattern 2:
In this pattern, the images are retrieved with the sheet name and cell coordinate from Spreadsheet. In this case, the script becomes a bit complicated. So here, I would like to introduce the sample script using a Google Apps Script library. Ref Of course, you can see the whole script there.
Sample script:
Before you use this script, please install DocsServiceApp (The author of this GAS library is tanaike.) of the Google Apps Script library. Ref And run the function of myFunction.
function myFunction() {
const cell = "A1";
const sheetName = "Sheet1";
const spreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
const obj = DocsServiceApp.openBySpreadsheetId(spreadsheetId).getSheetByName(sheetName).getImages();
console.log(obj)
const blobs = obj.filter(({range, image}) => range.a1Notation == cell && image.innerCell);
console.log(blobs.length)
if (blobs.length > 0) DriveApp.createFile(blobs[0].image.blob);
}
In this sample, the image in the cell "A1" of "Sheet1" in the active Spreadsheet is retrieved, and the retrieved blob is created to the root folder as an image file.
Note:
In the current stage, when an image is inserted to Google Spreadsheet and the Spreadsheet is converted to XLSX data, the image including the XLSX data has the filename of image1, image2,,, which are not the original filename. So it seems that this is the current specification.
When the images are retrieved from XLSX data, it seems that the image is a bit different from the original one. The image format is the same. But the data size is smaller than that of the original. When the image size is more than 2048 pixels and 72 dpi, the image is modified to 2048 pixels and 72 dpi. Even when the image size is less than 2048 pixels and 72 dpi, the file size becomes smaller than that of original one. So I think that the image might be compressed. Please be careful this.
In the current stage, the drawings cannot be directly retrieved.
References:
Understanding the Open XML file formats
XML Service
DocsServiceApp
Now available as of January 2022 (release notes):
The following classes have been added to the Spreadsheet Service to let you add images to cells:
CellImageBuilder: This builder creates the image value needed to add an image to a >cell.
CellImage: Represents an image to add to a cell.
To add an image to a cell, you must create a new image value for the image using SpreadsheetApp.newCellImage() and CellImageBuilder. Then, use Range.setValue(value) or Range.setValues(values) to add the image value to the cell.
Example:
function insertImageIntoCell()
{
let image = SpreadsheetApp.newCellImage().setSourceUrl('https://www.gstatic.com/images/branding/product/2x/apps_script_48dp.png').setAltTextDescription('Google Apps Script logo').toBuilder().build();
SpreadsheetApp.getActive().getActiveSheet().getRange('A1').setValue(image);
}
Result:
function getImageFromCell()
{
let value = SpreadsheetApp.getActive().getActiveSheet().getRange('A1').getValue();
console.log(value.getAltTextDescription());
console.log(value.getUrl());
}
Result:
Note: getUrl returns null for this particular example, which seems to be due some internal API unavailability, from docs:
Gets the image's source URL; returns null if the URL is unavailable. If the image was inserted by URL using an API, this method returns the URL provided during image insertion.
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.
1. =IMAGE(<http url>)
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())}`
}
Both Rafa Guillermo and Tanaike requested that I make an answer based on my comment to Tanaike’s post. I do so below, but it falls into the category of a workaround rather than an "answer". A true answer would address the exact question in the original post.
As I said in my comment, I’ve used this method for simple cases, and I’ve also done some tests which suggest it preserves image resolution. Since I've only used this for simple cases like the one below, I don't know how generally it will work.
The steps I provide below are (to the best of my ability) what I remember going through as I did one specific example. Here are the first dozen rows of the final result after using this method:
This example had a total of 7100+ rows
Column 1 contained 430+ images or blank cells, most of which repeated
multiple times
Column 2 contained unique IDs for each image
Column 3 are the file names which were tied to each ID using the
method below
Steps to extract images from google sheet cells:
Resize column and rows containing images to something large (eg, 300)
Use File>Publish to Web & paste generated link into a new tab
In Chrome, use File>Save Page As…>Webpage, Complete
Images will be found in an html folder ending with _files
If needed, rename files to use image extension and list in order*
To key downloaded image file names to image cells in the sheet:
Duplicate sheet since the following will remove original data
Select columns containing images and IDs and use Data>Remove Duplicates
Add a new column next to the IDs containing the file names**
Use VLOOKUP function to transfer all file names to original sheet based on the unique IDs***
*In my example the images all had names like p.txt, p(1).txt, p(2).txt, etc… In Mac OS Finder, I selected all files and used right click>Rename files… and then the replace option to replace .txt with .jpg, (1) with (001), etc…
**file name listing can be obtained, for example, using the Terminal ls -l command
***for example, I used: =vlookup(B2,unique!$B$2:$C$430,2,false)
This question is a little old, but since I faced today this problem, please allow me to share my experience.
I realized that the getValue() of the cell, returns an object that its text is "CellImage". This allows me to understand that there is an embedded image in this cell. This objects seems to be similar to (or the same) with the OverGridImage object. At least, you can use the getAltTextTitle and the getAltTextDescription methods.
By combining all these features, my workaround is:
Add specific AltText to the image in the cell.
Get the value of the cell in an object.
Check if this is equals to "CellImage".
If it is CellImage, get the AltText.
Based on the value of this AltText do whatever you like.
The sample code follows:
/*-------------------------------------------------------------------------
Custom event handler triggered when a single cell is selected in the spreadsheet.
#param {Event} e The onSelectionChange event.
-------------------------------------------------------------------------*/
function onSingleCellSelected(e) {
var cell = e.range.getCell(1, 1);
var v = cell.getValue();
if(v == "CellImage") {
var altText = v.getAltTextTitle();
Logger.log(v.getAltTextDescription());
if(altText == "#action(recordTime)"){
cell.setBackground("cyan");
}
}
}
I just tried something pretty basic and it worked. Maybe doesn't work in all cases, depends if you added the images previously through a formula...
Add image through Google Apps Script :
var ss = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
var sheet = ss.getSheetByName(SHEET_NAME);
sheet.getRange('A1').setFormula('=IMAGE("https://developers.google.com/google-ads/scripts/images/reports.png")');
Worked (it's in the cell and will work auto fit on resizing) :
Then to retrieve the image url from cell :
var imgVal = sheet.getRange('A1').getFormula();
var regEx = /"(.*)"/gm;
var url = regEx.exec(imgVal)[1];
Logger.log(url);
Logs will be :

How can I get an image FROM A CELL in a Google Sheet and insert it into a Google Doc [duplicate]

I have a script that creates a document during runtime and attach it to a variable.
I need to insert images to it using a script.
Here is my code:
var modulo = "foo";
var nomeDoc = "bar";
let doc = DocumentApp.create("Validação escopo ("+ modulo +") cliente: " + nomeDoc);
var body = doc.getBody();
var imgPDF = body.appendImage(blob);
How do i pass an image as "blob" inside the variable: imgPDF?
Important: The image is in the Spreadsheet that calls this function.
On January 19, 2022, 2 Classes for using the inner cell image were added to the Spreadsheet service. Ref But, in the current stage, the image can be put into a cell. But, unfortunately, the image in the cell cannot be retrieved. I think that this might be a bug. And also, these Classes cannot retrieve the images on a cell as the blob and the image URL. I think that this is the specification.
So, as the current workaround, I thought that in your situation, in the current stage, this method can be used. Ref
In this workaround, a Google Apps Script library might be able to be used. Ref This library can retrieve both the image in a cell and the image on a cell.
Usage:
1. Install Google Apps Script library.
You can see the method for installing this library at here.
2. Enable Drive API.
In this case, Drive API is used. So, please enable Drive API at Advanced Google services.
3. Sample script.
const spreadsheetId = "###"; // Google Spreadsheet ID
const res = DocsServiceApp.openBySpreadsheetId(spreadsheetId).getSheetByName("Sheet1").getImages();
console.log(res); // You can check the retrieved images at the log.
if (res.length == 0) return;
const blob = res[0].image.blob; // Here, 1st image of Sheet1 is retrieved. Of course, you can choose the image on the sheet.
let doc = DocumentApp.create("Validação escopo (" + modulo + ") cliente: " + nomeDoc);
var body = doc.getBody();
var imgPDF = body.appendImage(blob);
In this case, please declare modulo and nomeDoc.
4. Testing.
When the above script is run, the images are retrieved from "Sheet1" and put the 1st image to the created Document body.
References:
DocsServiceApp
Related thread
How to access new 'in-cell-image' from google apps script?

How do get GIF from Google Docs using Apps Script?

I want to get the gif image from google docs. Using Apps Script, gif images are got as
InlineImage. But it's only static without animating.
My code
var doc = DocumentApp.openByUrl('url');
Logger.log(doc.getBody().getImages()[0]);
var encoded = Utilities.base64Encode(doc.getBody().getImages()[0].getBlob().getBytes());
Logger.log(encoded);
You want to retrieve the original images from Google Document.
In your case, you want to retrieve an animation GIF from Google Document.
You want to achieve this using Google Apps Script.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Unfortunately, it seems that the original images cannot be directly retrieved using getImages(). So in this answer, I use the method of documents.get in Google Docs API.
Flow:
The flow of this sample script is as follows.
Retrieve the object from Google Document using the method of documents.get in Google Docs API.
Retrieve the source information from the retrieved object.
The embeded original images can be retrieved from the property of inlineObjects.
Create the original images from the retrieved source information.
Sample script:
Before you use this script, please enable Google Docs API at Advanced Google services.
function myFunction() {
var documentId = "###"; // Please set Google Document ID.
// Retrieve the object from Google Document using the method of documents.get in Google Docs API.
var obj = Docs.Documents.get(documentId);
// Retrieve the source information from the retrieved object.
var inlineObjects = Object.keys(obj.inlineObjects).reduce(function(ar, e, i) {
var o = obj.inlineObjects[e].inlineObjectProperties.embeddedObject;
if (o.hasOwnProperty("imageProperties")) {
var res = UrlFetchApp.fetch(o.imageProperties.contentUri, {headers: {Authorization: "Baerer " + ScriptApp.getOAuthToken()}, muteHttpExceptions: true});
if (res.getResponseCode() == 200) ar.push(res.getBlob().setName("image" + (i + 1)));
}
return ar;
}, []);
// Create the original images from the retrieved source information.
inlineObjects.forEach(function(blob) {
var id = DriveApp.createFile(blob).getId();
Logger.log(id)
})
}
When you run the script, the image files are created to the root folder. And you can see the file IDs of them at the log. The filename is "image1", "image2",,, as the sample.
References:
Advanced Google services
Method: documents.get
InlineObject
If I misunderstood your question and this was not the direction you want, I apologize.

How to access new 'in-cell-image' from google apps script?

The new function Insert > Image > Image in Cell in Google sheets inserts an image in a cell and not as an OverGridImage.
I would like to insert the image in this manner and then access the image from Google Apps Script. Is this possible?
After inserting the image the formula of the cell is blank when the cell is selected. I tried searching the GAS reference, but I could not find any information on this relatively new feature.
There is information on the over grid images. I would expect the in-cell image to have similar functions.
I've tried things like this:
// See what information is available on a cell with inserted image:
var image = sheet.getRange(1, 1).getFormula();
Logger.log(image);
The logs shows up empty.
I tried several: .getImage() (does not exist), .getValue(), .getFormula()
I would expect to be able to access the image URL or Blob in some way.
Answer:
This is a new feature and unfortunately at current there isn’t a method to be able to get an image inserted into a Cell this way using Google Apps Script, nor using the Sheets API.
More Information:
Attempting to get the data in a cell using the spreadsheets.get method with the following parameters
spreadsheetId: "ID of private spreadsheet created in Drive"
includeGridData: True
ranges: D7
fields: sheets/data/rowData/values
Will return a 200 response, however the image data is not returned:
{
"sheets": [
{
"data": [
{
"rowData": [
{
"values": [
{
"userEnteredValue": {},
"effectiveValue": {},
"effectiveFormat": {
"backgroundColor": {
"red": 1,
"green": 1,
"blue": 1
},
"padding": {
"top": 2,
"right": 3,
"bottom": 2,
"left": 3
},
"horizontalAlignment": "LEFT",
"verticalAlignment": "BOTTOM",
"wrapStrategy": "OVERFLOW_CELL",
"textFormat": {
"foregroundColor": {},
"fontFamily": "Arial",
"fontSize": 10,
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false
},
"hyperlinkDisplayType": "PLAIN_TEXT"
}
}
]
}
]
}
]
}
]
}
Feature Request:
There is however a Feature request for this on Google’s Issue Tracker which you can find here. If you head over to the feature request page and click the star in the top left, you can let Google know that you also would like this feature, and will automatically get updates about its progress.
I believe your goal as follows.
You want to retrieve the image in the cell of Google Spreadsheet using Google Apps Script.
Issue and workaround:
Unfortunately, in the current stage, there are no methods for retrieving the images in the cell on Spreadsheet in Spreadsheet service and Sheets API. This has already been mentioned by Rafa Guillermo's answer. So in this answer, I would like to propose a workaround for retrieving the images in the cells using Google Apps Script.
In this workaround, I use Microsoft Excel Data converted from Google Spreadsheet. Even when Google Spreadsheet is converted to Microsoft Excel Data, the images in the cells are not removed. I use this. Of course, the images can be also retrieved from HTML data converted from Spreadsheet. But in this case, the parse of HTML data is a bit complicated than that of Excel data. So here, I would like to propose to retrieve the images from Excel Data converted from Spreadsheet. The flow of this workaround is as follows.
Convert Google Spreadsheet to Microsoft Excel (XLSX data) using Drive API.
Parse XLSX data using Google Apps Script.
When the converted XLSX data is unzipped, the data can be analyzed as the XML data. Fortunately, at Microsoft Docs, the detail specification is published as Open XML. So in this case, Microsoft Docs like XLSX, DOCX and PPTX can be analyzed using XmlService of Google Apps Script. I think that this method will be also useful for other situations.
Retrieve images from XLSX data.
Pattern 1:
In this pattern, I would like to introduce a simple method.
Sample script:
function myFunction() {
const spreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
const url = "https://docs.google.com/spreadsheets/export?exportFormat=xlsx&id=" + spreadsheetId;
const blob = UrlFetchApp.fetch(url, {headers: {authorization: `Bearer ${ScriptApp.getOAuthToken()}`}}).getBlob().setContentType(MimeType.ZIP);
const xlsx = Utilities.unzip(blob);
xlsx.forEach(b => {
const name = b.getName().match(/xl\/media\/(.+)/);
if (name) DriveApp.createFile(b.setName(name[1]));
});
}
In this sample script, all images in the Spreadsheet are exported as the files. So in this case, both images in the cells and over the cells from all sheets in the Spreadsheet are retrieved. And also, it cannot retrieve the cell coordinate that the image is in the cell.
In the current stage, there are no methods for retrieving the images in Google Spreadsheet as the blob. In this sample script, this can be achieved.
This sample script cannot export the drawings. Please be careful this.
When setContentType(MimeType.ZIP) is not used, an error occurs at Utilities.unzip(blob). Please be careful this.
Pattern 2:
In this pattern, the images are retrieved with the sheet name and cell coordinate from Spreadsheet. In this case, the script becomes a bit complicated. So here, I would like to introduce the sample script using a Google Apps Script library. Ref Of course, you can see the whole script there.
Sample script:
Before you use this script, please install DocsServiceApp (The author of this GAS library is tanaike.) of the Google Apps Script library. Ref And run the function of myFunction.
function myFunction() {
const cell = "A1";
const sheetName = "Sheet1";
const spreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
const obj = DocsServiceApp.openBySpreadsheetId(spreadsheetId).getSheetByName(sheetName).getImages();
console.log(obj)
const blobs = obj.filter(({range, image}) => range.a1Notation == cell && image.innerCell);
console.log(blobs.length)
if (blobs.length > 0) DriveApp.createFile(blobs[0].image.blob);
}
In this sample, the image in the cell "A1" of "Sheet1" in the active Spreadsheet is retrieved, and the retrieved blob is created to the root folder as an image file.
Note:
In the current stage, when an image is inserted to Google Spreadsheet and the Spreadsheet is converted to XLSX data, the image including the XLSX data has the filename of image1, image2,,, which are not the original filename. So it seems that this is the current specification.
When the images are retrieved from XLSX data, it seems that the image is a bit different from the original one. The image format is the same. But the data size is smaller than that of the original. When the image size is more than 2048 pixels and 72 dpi, the image is modified to 2048 pixels and 72 dpi. Even when the image size is less than 2048 pixels and 72 dpi, the file size becomes smaller than that of original one. So I think that the image might be compressed. Please be careful this.
In the current stage, the drawings cannot be directly retrieved.
References:
Understanding the Open XML file formats
XML Service
DocsServiceApp
Now available as of January 2022 (release notes):
The following classes have been added to the Spreadsheet Service to let you add images to cells:
CellImageBuilder: This builder creates the image value needed to add an image to a >cell.
CellImage: Represents an image to add to a cell.
To add an image to a cell, you must create a new image value for the image using SpreadsheetApp.newCellImage() and CellImageBuilder. Then, use Range.setValue(value) or Range.setValues(values) to add the image value to the cell.
Example:
function insertImageIntoCell()
{
let image = SpreadsheetApp.newCellImage().setSourceUrl('https://www.gstatic.com/images/branding/product/2x/apps_script_48dp.png').setAltTextDescription('Google Apps Script logo').toBuilder().build();
SpreadsheetApp.getActive().getActiveSheet().getRange('A1').setValue(image);
}
Result:
function getImageFromCell()
{
let value = SpreadsheetApp.getActive().getActiveSheet().getRange('A1').getValue();
console.log(value.getAltTextDescription());
console.log(value.getUrl());
}
Result:
Note: getUrl returns null for this particular example, which seems to be due some internal API unavailability, from docs:
Gets the image's source URL; returns null if the URL is unavailable. If the image was inserted by URL using an API, this method returns the URL provided during image insertion.
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.
1. =IMAGE(<http url>)
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())}`
}
Both Rafa Guillermo and Tanaike requested that I make an answer based on my comment to Tanaike’s post. I do so below, but it falls into the category of a workaround rather than an "answer". A true answer would address the exact question in the original post.
As I said in my comment, I’ve used this method for simple cases, and I’ve also done some tests which suggest it preserves image resolution. Since I've only used this for simple cases like the one below, I don't know how generally it will work.
The steps I provide below are (to the best of my ability) what I remember going through as I did one specific example. Here are the first dozen rows of the final result after using this method:
This example had a total of 7100+ rows
Column 1 contained 430+ images or blank cells, most of which repeated
multiple times
Column 2 contained unique IDs for each image
Column 3 are the file names which were tied to each ID using the
method below
Steps to extract images from google sheet cells:
Resize column and rows containing images to something large (eg, 300)
Use File>Publish to Web & paste generated link into a new tab
In Chrome, use File>Save Page As…>Webpage, Complete
Images will be found in an html folder ending with _files
If needed, rename files to use image extension and list in order*
To key downloaded image file names to image cells in the sheet:
Duplicate sheet since the following will remove original data
Select columns containing images and IDs and use Data>Remove Duplicates
Add a new column next to the IDs containing the file names**
Use VLOOKUP function to transfer all file names to original sheet based on the unique IDs***
*In my example the images all had names like p.txt, p(1).txt, p(2).txt, etc… In Mac OS Finder, I selected all files and used right click>Rename files… and then the replace option to replace .txt with .jpg, (1) with (001), etc…
**file name listing can be obtained, for example, using the Terminal ls -l command
***for example, I used: =vlookup(B2,unique!$B$2:$C$430,2,false)
This question is a little old, but since I faced today this problem, please allow me to share my experience.
I realized that the getValue() of the cell, returns an object that its text is "CellImage". This allows me to understand that there is an embedded image in this cell. This objects seems to be similar to (or the same) with the OverGridImage object. At least, you can use the getAltTextTitle and the getAltTextDescription methods.
By combining all these features, my workaround is:
Add specific AltText to the image in the cell.
Get the value of the cell in an object.
Check if this is equals to "CellImage".
If it is CellImage, get the AltText.
Based on the value of this AltText do whatever you like.
The sample code follows:
/*-------------------------------------------------------------------------
Custom event handler triggered when a single cell is selected in the spreadsheet.
#param {Event} e The onSelectionChange event.
-------------------------------------------------------------------------*/
function onSingleCellSelected(e) {
var cell = e.range.getCell(1, 1);
var v = cell.getValue();
if(v == "CellImage") {
var altText = v.getAltTextTitle();
Logger.log(v.getAltTextDescription());
if(altText == "#action(recordTime)"){
cell.setBackground("cyan");
}
}
}
I just tried something pretty basic and it worked. Maybe doesn't work in all cases, depends if you added the images previously through a formula...
Add image through Google Apps Script :
var ss = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
var sheet = ss.getSheetByName(SHEET_NAME);
sheet.getRange('A1').setFormula('=IMAGE("https://developers.google.com/google-ads/scripts/images/reports.png")');
Worked (it's in the cell and will work auto fit on resizing) :
Then to retrieve the image url from cell :
var imgVal = sheet.getRange('A1').getFormula();
var regEx = /"(.*)"/gm;
var url = regEx.exec(imgVal)[1];
Logger.log(url);
Logs will be :