Skip to content

Instantly share code, notes, and snippets.

@mhawksey
Last active March 23, 2021 10:54
Show Gist options
  • Save mhawksey/b5e3e2b60f1927c6994f9071922fc77c to your computer and use it in GitHub Desktop.
Save mhawksey/b5e3e2b60f1927c6994f9071922fc77c to your computer and use it in GitHub Desktop.
Port of Wesley Chun's 'Using the Google Slides API with Python' to Google Apps Script. Read more at https://mashe.hawksey.info/?p=17385
// Port of Slides API demo by Wesley Chun to Google Apps Script
// Source: http://wescpy.blogspot.co.uk/2016/11/using-google-slides-api-with-python.html
function slides_template() {
/*
from apiclient import discovery
from httplib2 import Http
from oauth2client import file, client, tools
*/
/* DIFF
No comand line imports but some setup required.
1. Resources > Advance Services and enable the Slides API
[Also change the identifier in the Libraries dialog to SLIDES to make it easy to compare to Wesley's code
2. Resources > Developer Console Project click on the project link and enable Slides API
*/
var IMG_FILE = 'logo_slides_128px.png' // use your own or copy https://goo.gl/hJwcoa !
var TMPLFILE = 'Google Slides API template DEMO' // use your own or use https://goo.gl/FdQ9AH !
/*
SCOPES = (
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/presentations',
)
store = file.Storage('storage.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
creds = tools.run_flow(flow, store)
HTTP = creds.authorize(Http())
DRIVE = discovery.build('drive', 'v3', http=HTTP)
SLIDES = discovery.build('slides', 'v1', http=HTTP)
*/
/* DIFF
Tip by Romain Vialard that if you use DriveApp you can use the project token
Running the function also automatically triggers any authorization required
https://plus.google.com/u/0/+MartinHawksey/posts/aPEdvRiFV9Y
*/
// SLIDES.setTokenService(function(){return ScriptApp.getOAuthToken()});
/*
rsp = DRIVE.files().list(q="name='%s'" % TMPLFILE).execute().get('files')[0]
DATA = {'name': 'Google Slides API template DEMO'}
print('** Copying template %r as %r' % (rsp['name'], DATA['name']))
DECK_ID = DRIVE.files().copy(body=DATA, fileId=rsp['id']).execute().get('id')
*/
/* DIFF
As Google Apps Script has built-in DriveApp service we can use this to get out template
and copy it
*/
Logger.log('** Copying template **');
var DECK_ID = DriveApp.getFilesByName(TMPLFILE).next().makeCopy().getId();
/*
print('** Get slide objects, search for image placeholder')
slide = SLIDES.presentations().get(presentationId=DECK_ID,
fields='slides').execute().get('slides')[0]
obj = None
for obj in slide['pageElements']:
if obj['shape']['shapeType'] == 'RECTANGLE':
break
*/
/* DIFF
None really other than a slighlty difference call and port from py to js
*/
Logger.log('** Get slide objects, search for image placeholder');
// var slide = SLIDES.presentationsGet(DECK_ID).slides[0];
var slide = SLIDES.Presentations.get(DECK_ID).slides[0];
var obj
for (var i in slide['pageElements']){
var obj = slide['pageElements'][i];
if (obj['shape']['shapeType'] == 'RECTANGLE'){
break;
}
}
/*
print('** Searching for icon file')
rsp = DRIVE.files().list(q="name='%s'" % IMG_FILE).execute().get('files')[0]
print(' - Found image %r' % rsp['name'])
img_url = '%s&access_token=%s' % (
DRIVE.files().get_media(fileId=rsp['id']).uri, creds.access_token)
*/
/* DIFF
Using built-in DriveApp. The 'https://drive.google.com/uc?id=XXX' tip
thanks to Romain Vialard https://plus.google.com/+MartinHawksey/posts/aaMshWDR1PZ
*/
Logger.log('** Searching for icon file');
var rsp = DriveApp.getFilesByName(IMG_FILE).next();
Logger.log(Utilities.formatString(' - Found image %s', rsp.getId()));
// var img_url = 'https://drive.google.com/uc?id='+rsp.getId(); // requires share access
var img_url = rsp.getDownloadUrl()+"&access_token="+ScriptApp.getOAuthToken();
/*
print('** Replacing placeholder text and icon')
reqs = [
{'replaceAllText': {
'containsText': {'text': '{{NAME}}'},
'replaceText': 'Hello World!'
}},
{'createImage': {
'url': img_url,
'elementProperties': {
'pageObjectId': slide['objectId'],
'size': obj['size'],
'transform': obj['transform'],
}
}},
{'deleteObject': {'objectId': obj['objectId']}},
]
*/
/* DIFF
None other than Logger
*/
Logger.log('** Replacing placeholder text and icon');
var reqs = [
{'replaceAllText': {
'containsText': {'text': '{{NAME}}'},
'replaceText': 'Hello World!'
}},
{'createImage': {
'url': img_url,
'elementProperties': {
'pageObjectId': slide['objectId'],
'size': obj['size'],
'transform': obj['transform'],
}
}},
{'deleteObject': {'objectId': obj['objectId']}},
];
/*
SLIDES.presentations().batchUpdate(body={'requests': reqs},
presentationId=DECK_ID).execute()
*/
/* DIFF
Slightly different call presentationsBatchUpdate(presentationId,BatchUpdatePresentationRequestResource,options)
*/
// SLIDES.presentationsBatchUpdate(DECK_ID, {'requests': reqs});
SLIDES.Presentations.batchUpdate({'requests': reqs}, DECK_ID);
Logger.log('DONE ');
}
@amullins65
Copy link

Thank you for this! I was having a hard time getting started on the slides API. I do have a question though. When I run this with my own slide template and photo it seems as though the photo ends up being skewed and smaller than the original shape. Is there a way to have it center crop the photo into the shape? I've been messing with the transform parameter a bit but don't seem to understand how it works.

@amullins65
Copy link

Figured out I could use this instead

`var reqs = [

{"replaceAllShapesWithImage": {

"imageUrl": img_url,
"replaceMethod": "CENTER_CROP",
"containsText": {
"text": "Main_Image",
"matchCase": "True",
}
},},`

@schlos
Copy link

schlos commented Oct 14, 2020

ReferenceError: "SLIDES" is not defined.
    at slides_template(Playground:95)

it should be written as "Slides" instead of "SLIDES", e.g.
SLIDES.Presentations.batchUpdate({'requests': reqs}, DECK_ID);
-> correct:
Slides.Presentations.batchUpdate({'requests': reqs}, DECK_ID);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment