4

My objective is to automatize the creation and update of a Google Slides presentation based on Images in a folder:

The Current workflow which is working correctly, but which I want to automatize is follows:

  1. Images are in a Google Drive Folder
  2. I manually add images to each slide using the File Picker Menu (Insert --> Image --> Drive)
  3. Images in folder are periodically updated by an external script, replacing the previous images using the same filename. Images keep the same Google Drive File ID
  4. Images are updated automatically in Slides, with changes visible when reloading the Slides Presentation in the browser

What I try to achieve:

Instead of creating the Slides and inserting the images using the File Picker one by one, use a script that creates the presentation based on the image files in the Drive Folder.

I have used the Tutorial on the Google Developers Pages and the creation of the Slides works fine. However in contrast to the manual insert, the images in the slides created by the script do not update. The script fetches the images just once and seems to use a "copy of the images".

My Test code is:

var NAME = "Dynamic Image Insert Test";
var presentation = SlidesApp.create(NAME);

function addImageSlide(fileID, index) {
    var slide = presentation.appendSlide(SlidesApp.PredefinedLayout.BLANK);    
    var imageurl = DriveApp.getFileById(fileID);
    var image = slide.insertImage(imageurl);
    var imgWidth   = image.getWidth();
    var imgHeight  = image.getHeight();
    var pageWidth  = presentation.getPageWidth();
    var pageHeight = presentation.getPageHeight();
    var newX = pageWidth/2.  - imgWidth/2.;
    var newY = pageHeight/2. - imgHeight/2.;
    image.setLeft(newX).setTop(newY);
}

function main() {
    var images = [
        "Insert ID of a File 1 on Google Drive here",
        "Insert ID of a File 2 on Google Drive here"      
    ];
    var [title, subtitle] = presentation.getSlides()[0].getPageElements();
    title.asShape().getText().setText(NAME);
    subtitle.asShape().getText().setText("Insert Files from Drive using File ID");
    images.forEach(addImageSlide);
}

Furthermore when checking the Object Properties of the Slide Page It seems there are 2 Parameters: contentUrl and sourceUrl:

When Inserting with the File Picker the Image seems to use the sourceUrl, which stays the same and this way updates the Image when the file is updated on Drive. When using the AppScript (or using API - tested also) the Image seems to use the contentUrl, which is generate each time when creating the image and thus does not refer to the file on the drive and therefore not reflecting any change to the file on the drive.

Logger output of the Page Object Properties:

{
  "pageElements": [
    {
      "transform": {
        "scaleX": 171.123,
        "scaleY": 171.123,
        "unit": "EMU",
        "translateY": 1288327.54,
        "translateX": 2375975
      },
      "objectId": "MyImage_01",
      "image": {
        "sourceUrl": "https://lh3.google.com/u/0/d/This-is-the-static-file-id",
        "contentUrl": "https://lh6.googleusercontent.com/This-is-the-id-created-when-creating-the-image-on-the-slide",
        "imageProperties": {
          "shadow": {
            "color": {
              "rgbColor": {}
            },
            "blurRadius": {
              "unit": "EMU"
            },
            "type": "OUTER",
            "transform": {
              "scaleX": 1,
              "scaleY": 1,
              "unit": "EMU"
            },
            "alpha": 1,
            "propertyState": "NOT_RENDERED",
            "rotateWithShape": false,
            "alignment": "BOTTOM_LEFT"
          },
          "outline": {
            "dashStyle": "SOLID",
            "propertyState": "NOT_RENDERED",
            "weight": {
              "unit": "EMU",
              "magnitude": 9525
            },
            "outlineFill": {
              "solidFill": {
                "color": {
                  "themeColor": "DARK2"
                },
                "alpha": 1
              }
            }
          }
        }
      },
      "size": {
        "width": {
          "unit": "EMU",
          "magnitude": 23375
        },
        "height": {
          "unit": "EMU",
          "magnitude": 15000
        }
      }
    }
  ]
}

Also sourceUrl is not documented in the reference of the API.

Any Idea how to use sourceUrl instead of contentUrl when inserting Slides? How can I replicate the same Insert statement and File Reference as the File Picker, using Google app script?

Core Tek
  • 101
  • 2
  • 6
  • Hello, Did you find an acceptable solution to this problem? I encounter the same; But I'm ready to click on "button" in order to launch the update process of the slide. Thx – Fabrice Feb 28 '20 at 13:25

3 Answers3

0

I have used this script to update all images on one slide. I'm currently looking at automating this function when a user loads images via a Google form. Maybe this is something that may help you with your problem.

/////////////////////////////////////////

var deck = SlidesApp.getActivePresentation()
var slide = deck.appendSlide(SlidesApp.PredefinedLayout.BLANK)
function main() {
var folder = DriveApp.getFolderById('your folder id goes here'); // Change the folder  
ID  here
var files = folder.getFiles();
while (files.hasNext()) {
var file = files.next();
Logger.log(file.getName());
var imageUrl = DriveApp.getFileById(file.getId()).getDownloadUrl() + "&access_token=" 
+ ScriptApp.getOAuthToken();
Logger.log(DriveApp.getFileById(file.getId()).getDownloadUrl() + "&access_token=" + 
ScriptApp.getOAuthToken()); 
var image = slide.insertImage(imageUrl);
}}
////////////////////////////////////

Regards Luke

lukeo25
  • 1
  • 2
0

So another thing I have done was use ".replace" to replace the blob to a new URL.

    function rePlace(){
    var IdBox = SlidesApp.getActivePresentation().getSlides()[0].getImages();
    //var L_nk = IdBox[1].
    IdBox[1].select();         
    var userProperties = PropertiesService.getUserProperties();
    var loopCounter = Number(userProperties.getProperty('loopCounter'));       
    IdBox[1].replace("your URL")
    } 
lukeo25
  • 1
  • 2
0

The only way I found (in Python) to make the content_url update base on the SAME source_url where the source image is updated in the drive, is to regenerate the source_url with an access_token

img_url = '%s&access_token=%s' % (
    DRIVE.files().get_media(fileId=rsp['id']).uri, creds.access_token) 

(http://wescpy.blogspot.com/search/label/API)

Read the blog for more details.

Once you manage to get the new url, you can update it with a replace image request

https://developers.google.com/slides/reference/rest/v1/presentations/request#ReplaceImageRequest

the pillow
  • 412
  • 6
  • 14