1

On the 19th January 2022, the CellImageBuilder class was added to the Google Sheets Spreadsheet service.

This class now allows you to import an image into a cell in Google Sheets, previously you could only add an image above the cell.

Ive been trying to use this new class to take a URL link from a Google sheet, and then create an image in the cell next to the URL. This works perfectly fine if I can hard code the URL into the script (example below)

**function insertImageIntoCell()**
    {
    var sheet = SpreadsheetApp.getActiveSheet();  
    
    var url='Google_Docs_Image_URL'
    
    let image = SpreadsheetApp.newCellImage().setSourceUrl(url).setAltTextDescription('TestImage').toBuilder().build();
    
SpreadsheetApp.getActive().getActiveSheet().getRange('C2').setValue(image);
    }

The problem I am having is that once I create an array to iterate through the column the below script creates a valid array and posts it into the correct column and rows, but when it posts it back into the spreadsheet it only returns the URL and does not convert it into an image in a cell

**function insertImageIntoCell()**
{
var sheet = SpreadsheetApp.getActiveSheet();  
var myStringArray = sheet.getRange('B2:B10');
var myStringArray = sheet.getRange('B2:B10').getValues();

//Logger.log(myStringArray)
  
  let image = SpreadsheetApp.newCellImage().setSourceUrl(myStringArray).setAltTextDescription('test').toBuilder().build();

  SpreadsheetApp.getActive().getActiveSheet().getRange('C2:C10').setValues(myStringArray);
}

Im using the followign code to create the initial table of data, this pull the file name and DownloadURL from a Google Drive location and then saves this into a sheet

/* modified from @hubgit and http://stackoverflow.com/questions/30328636/google-apps-script-count-files-in-folder 
for this stackexchange question http://webapps.stackexchange.com/questions/86081/insert-image-from-google-drive-into-google-sheets by @twoodwar
*/
function listFilesInFolder(folderName) {
   var sheet = SpreadsheetApp.getActiveSheet();
   sheet.appendRow(["Name","URL","Image"]);

//change the folder ID below to reflect your folder's ID (look in the URL when you're in your folder)
    var folder = DriveApp.getFolderById("Google_Drive_Folder");
    var contents = folder.getFiles();
    let image=[]; 

    var cnt = 0;
    var file;

    while (contents.hasNext()) {
        var file = contents.next();
        cnt++;
          data = [
                file.getName(),
                file.getDownloadUrl(),
            ];

            sheet.appendRow(data);
            
    };
};

I am looking for the script to refresh the file information from Google Drive into sheets, then to save the image into a cell, it now appears that this functionality exists, but Im not able to get it to take an array of URL's

A.Steer
  • 335
  • 3
  • 14

4 Answers4

1
Update:
  • This issue is filed. Add a star to this issue for Google developers to prioritize fixing this.
Issue:
  • setValues() is NOT working with CellImage, while setValue() does.

If/when it starts working, You need to convert each value to cellImage using map :

function insertImagesIntoCell() {
  const sheet = SpreadsheetApp.getActiveSheet(),
    range = sheet.getRange('B2:B10');
  range.setValues(
    range.getValues().map(url => [
      SpreadsheetApp.newCellImage()
        .setSourceUrl(url[0])
        .build(),
    ])
  );
}
TheMaster
  • 45,448
  • 6
  • 62
  • 85
  • When I use the code as supplied, it overwrites the URL values in Column B with the text "CellImageBuilder", when I add .toBuilder().build(), after .setAltTextDescription('test'), it then only writes the word "CellImage" into the cell. Im struggling to see how to implement this within my code – A.Steer Jan 24 '22 at 15:25
  • 1
    @A.Steer It seems direct setValues is not working currently. See update and other answer. – TheMaster Jan 24 '22 at 19:37
  • @A.Steer If you want to bring it to direct attention of Google devs quickly, you may [file a bug report](https://issuetracker.google.com/issues/new?component=191640&template=823905) with this stackover flow post link. – TheMaster Jan 25 '22 at 11:27
1

Suggestion

Perhaps you can try this sample implementation below.

Sample Tweaked Script

function listFilesInFolder(folderName){
  var sheet = SpreadsheetApp.getActiveSheet();
  sheet.appendRow(["Name","URL","Image"]);

//change the folder ID below to reflect your folder's ID (look in the URL when you're in your folder)
  var folder = DriveApp.getFolderById("DRIVE_FOLDER_ID");
  var contents = folder.getFiles();
  let image=[]; 

  var cnt = 0;
  var file;

  while (contents.hasNext()) {
      var file = contents.next();
      cnt++;
        data = [
              file.getName(),
              file.getDownloadUrl(),
          ];

          sheet.appendRow(data);      
  };
  insertImageIntoCell(); //Insert the images on column C
};

function insertImageIntoCell(){
  var sheet = SpreadsheetApp.getActiveSheet();
  var row = 1;
  sheet.getDataRange().getValues().forEach(url =>{
    if(url[1] == "URL")return row += 1;
      let image = SpreadsheetApp.newCellImage().setSourceUrl(url[1]).setAltTextDescription('TestImage').toBuilder().build();
      SpreadsheetApp.getActive().getActiveSheet().getRange('C'+row).setValue(image);
      row += 1;
  });
}

Sample Drive Folder with sample images

enter image description here

Sample Result:

  • After running the function listFilesInFolder:

enter image description here

SputnikDrunk2
  • 3,398
  • 1
  • 5
  • 17
  • @A.Steer If we answered your question, you may want to click the accept button/up-vote on the left (check icon). By doing so, other people in the community, who may have the same concern as you, will know that theirs can be resolved & they'll easily see this post on their searches. – SputnikDrunk2 Jan 25 '22 at 16:50
  • your answer does answer the question, but as the script iterates through each line it does take a long time to run (8 minutes for 274 images). As The Master mentions as setvalues() dosent work with cell image this is likely the only way to do this at the moment. – A.Steer Jan 31 '22 at 11:08
1

For anyone struggling with importing images from Google Drive you should know that you have to set the "Sharing" setting on every individual file for CellImageBuilder to work properly.

Like this:

const imageFileUrl = imageFolder.getFilesByName(filename).next()
      .setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW)
      .getDownloadUrl();
const cellImage = SpreadsheetApp.newCellImage().setSourceUrl(imageFileUrl).build();

Additionally, there appears to be a rate limit on the drive download URLs, causing the '.build()' function to fail randomly on a valid URL. Retries might be necessary.

Also, the .toBuilder() call on CellImageBuilder is completely redundant.

  • This might be a bug as it's necessary even for a SheetApp and a DriveApp for the same account. It might have something to do with the AppScript being considered a separate entity belonging to the Developer rather than the User. – Viktor Vix Jančík Sep 23 '22 at 06:47
0

I have looked across multiple forums trying to work out how to add a drive image to a cell and finally i have it working!Thanks to viktor Vix!

You have to set the permission on the file before or with the .setSharing() as below and you need the .getDownloadUrl() it that easy! everyone on every forum I know said it cant be done! it can.

file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, 
DriveApp.Permission.VIEW);
var fileDownloadUrl = file.getDownloadUrl();
var cellFormula = "=IMAGE(\"" + fileDownloadUrl + "\")"; 

sheet.appendRow([cellFormula]);