Search code examples
google-apps-scriptgoogle-sheetsgoogle-slides

Unable to add downloaded images to google slides


I am trying to create a script that reads 2 columns from a google sheets tab, one column containing image links that are on my google drive, and another column containing boolean values to decide whether to include the image at each line or not in a google slides presentation. Then, add 4 images to a single slide and create a new slide and repeat until all the images are added. So, I created this function:

function createSlidesFromImages() {
  // set the relevant column names
  const IMAGE_LINK_COLUMN_NAME = "Image link";
  const INCLUDE_IMAGE_COLUMN_NAME = "Include image";

  // Access the Google Sheet and the "today_sheet" tab
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = spreadsheet.getSheetByName("today_sheet");
  const data = sheet.getDataRange().getValues();

  // Get the column indexes by column names
  const headerRow = data[0];
  const IMAGE_LINK_COLUMN = headerRow.indexOf(IMAGE_LINK_COLUMN_NAME);
  const INCLUDE_IMAGE_COLUMN = headerRow.indexOf(INCLUDE_IMAGE_COLUMN_NAME);

  // Get the ID of the folder containing the Google Sheets file
  const file = DriveApp.getFileById(spreadsheet.getId());
  const folder = file.getParents().next();
  const folderId = folder.getId();

  // Create a new Google Slides presentation
  const presentation = SlidesApp.create("Generated Slides");
  const presentationId = presentation.getId();
  DriveApp.getFileById(presentationId).moveTo(folder);

  // Initializes variables for slide creation
  let slide, images = [];

  // Iterate through the rows in the sheet (starting from the second row)
  for (let i=1; i < data.length; i++){
    const includeImage = data[i][INCLUDE_IMAGE_COLUMN];
    const imageUrl = data[i][IMAGE_LINK_COLUMN];

    if (includeImage === true){
      // Download the image
      const imageBlob = UrlFetchApp.fetch(imageUrl).getBlob();
      
      // Add the image to the images array
      images.push(imageBlob);

      // If there are 4 images, create a new slide and add the images
      if (images.length === 4){
        slide = presentation.appendSlide(SlidesApp.PredefinedLayout.BLANK);
        for (let j = 0; j < images.length; j++){
          slide.insertImage(images[j]);
        }
      // Reset the images array
      images = [];
      }
    }
  }

  // If there are remaining images, crfeate a new slide and add them
  if (images.length > 0){
    slide = presentation.appendSlide(SlidesApp.PredefinedLayout.BLANK);
    for (let j = 0; j < images.length; j++){
      slide.insertImage(images[j]);
    }
  }
}

When I run the script, I get the error : "Exception: The image you are trying to use is invalid or corrupt." The error occurs at the line where the images are being added to the google slide:

slide.insertImage(images[j]);

And for the moment, all my URLs in the sheet are just duplicates to the same image link, which is: https://drive.google.com/file/d/1Ga3vQ2IyWzY4B5jvZjtXGY_4HRucmw7V/view?usp=sharing

Also, I made sure that the image is accessible to anyone with the link in the "manage access" section and that it can be edited. Does anyone know what I am doing wrong ?

Thanks for the help.


Solution

  • From your following situation,

    When I run the script, I get the error : "Exception: The image you are trying to use is invalid or corrupt." The error occurs at the line where the images are being added to the google slide:

    And for the moment, all my URLs in the sheet are just duplicates to the same image link, which is: https://drive.google.com/file/d/1Ga3vQ2IyWzY4B5jvZjtXGY_4HRucmw7V/view?usp=sharing

    Also, I made sure that the image is accessible to anyone with the link in the "manage access" section and that it can be edited.

    I guessed that the reason for your current issue might be due to the endpoint of https://drive.google.com/file/d/1Ga3vQ2IyWzY4B5jvZjtXGY_4HRucmw7V/view?usp=sharing. When const imageBlob = UrlFetchApp.fetch(imageUrl).getBlob(); is run with the URL of https://drive.google.com/file/d/1Ga3vQ2IyWzY4B5jvZjtXGY_4HRucmw7V/view?usp=sharing, unfortunately, the image blob cannot be retrieved. In this case, how about the following modification?

    In this modification, the file ID is retrieved from the URL https://drive.google.com/file/d/1Ga3vQ2IyWzY4B5jvZjtXGY_4HRucmw7V/view?usp=sharing like Ga3vQ2IyWzY4B5jvZjtXGY_4HRucmw7V. And, the image blob is retrieved from the file ID. Please modify your showing script as follows.

    From:

    // Iterate through the rows in the sheet (starting from the second row)
    for (let i=1; i < data.length; i++){
      const includeImage = data[i][INCLUDE_IMAGE_COLUMN];
      const imageUrl = data[i][IMAGE_LINK_COLUMN];
    
      if (includeImage === true){
        // Download the image
        const imageBlob = UrlFetchApp.fetch(imageUrl).getBlob();
        
        // Add the image to the images array
        images.push(imageBlob);
    
        // If there are 4 images, create a new slide and add the images
        if (images.length === 4){
          slide = presentation.appendSlide(SlidesApp.PredefinedLayout.BLANK);
          for (let j = 0; j < images.length; j++){
            slide.insertImage(images[j]);
          }
        // Reset the images array
        images = [];
        }
      }
    }
    

    To:

    for (let i = 1; i < data.length; i++) {
      const includeImage = data[i][INCLUDE_IMAGE_COLUMN];
      const fileId = data[i][IMAGE_LINK_COLUMN].split("/")[5];
      if (includeImage === true) {
        const imageBlob = DriveApp.getFileById(fileId).getBlob();
        images.push(imageBlob);
        if (images.length === 4) {
          slide = presentation.appendSlide(SlidesApp.PredefinedLayout.BLANK);
          for (let j = 0; j < images.length; j++) {
            slide.insertImage(images[j]);
          }
          images = [];
        }
      }
    }
    

    Or, when your all image files are publicly shared, the following modification might be able to be used.

    for (let i = 1; i < data.length; i++) {
      const includeImage = data[i][INCLUDE_IMAGE_COLUMN];
      const fileId = data[i][IMAGE_LINK_COLUMN].split("/")[5];
      if (includeImage === true) {
        const imageUrl = `https://drive.google.com/thumbnail?sz=w1000&id=${fileId}`; // Ref: https://stackoverflow.com/a/31504086
        images.push(imageUrl);
        if (images.length === 4) {
          slide = presentation.appendSlide(SlidesApp.PredefinedLayout.BLANK);
          for (let j = 0; j < images.length; j++) {
            slide.insertImage(images[j]);
          }
          images = [];
        }
      }
    }
    

    Note:

    • In this modification, from all my URLs in the sheet are just duplicates to the same image link, which is:, it supposes that your all URLs are like https://drive.google.com/file/d/{fileId}/view?usp=sharing. If other URLs are included, an error might occur. Please be careful about this.

    • Also, in this modification, it supposes that you have permission to access the file. Please be careful about this.

    Reference: