Sur cette page
Un tableur suffit souvent à un journal local, un site de mairie, un ciné-club ou un média étudiant : le programme du cinéma d’à côté, mis à jour tout seul, que toute l’équipe peut filtrer, trier ou publier. Ce tutoriel met les séances de la semaine d’un cinéma dans une feuille Google Sheets avec environ 80 lignes d’Apps Script, collées une fois. Aucun serveur, aucun déploiement, et une requête par jour, que le forfait gratuit couvre très largement.
Date Heure Film Durée Version Format Réservation
2026-11-06 11:50 Sourires d'une nuit d'été 1 h 49 VOST 2D https://www.cinema-lechampo.com/…
2026-11-06 11:55 Le Septième Sceau 1 h 36 VOST 2D https://www.cinema-lechampo.com/…
2026-11-06 13:45 Affreux, sales et méchants 1 h 55 VOST 2D https://www.cinema-lechampo.com/…Ce qu’il vous faut
- Un compte Google et une nouvelle feuille Google Sheets.
- Une clé API Cinéma : créez un compte gratuit, confirmez votre adresse e-mail, puis créez une clé depuis le tableau de bord. Le forfait gratuit donne 100 requêtes par semaine ; cette feuille en consomme une par jour.
- Le
slugdu cinéma. Cherchez-le par son nom :
curl "https://api.api-cinema.com/v1/cinemas?q=champo" -H "Authorization: Bearer ac_live_…"La réponse donne "slug": "le-champo-paris-5e-arrondissement". N’importe quel cinéma de l’API, en France, aux États-Unis ou en Australie, marche pareil.
Le script
Dans la feuille, ouvrez Extensions › Apps Script, remplacez le contenu de Code.gs par le script ci-dessous et enregistrez (l’icône disquette, ou Ctrl+S). Rechargez ensuite la feuille : un menu Cinéma apparaît à côté d’Aide.
// Une feuille Google Sheets qui se remplit avec les séances d’un cinéma, depuis API Cinéma.
// Menu « Cinéma » : enregistrer la clé une fois, mettre à jour maintenant, ou chaque matin.
const API = 'https://api.api-cinema.com/v1'
const HEADER = ['Date', 'Heure', 'Film', 'Durée', 'Version', 'Format', 'Réservation']
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('Cinéma')
.addItem('Mettre à jour les séances', 'updateShowtimes')
.addItem('Mettre à jour chaque matin', 'installDailyTrigger')
.addSeparator()
.addItem('Enregistrer la clé API…', 'setApiKey')
.addToUi()
}
/** La clé vit dans les propriétés du script : jamais dans une cellule, jamais dans le code. */
function setApiKey() {
const ui = SpreadsheetApp.getUi()
const answer = ui.prompt('Clé API Cinéma', 'Collez votre clé (ac_live_…).', ui.ButtonSet.OK_CANCEL)
if (answer.getSelectedButton() !== ui.Button.OK)
return
PropertiesService.getScriptProperties().setProperty('API_CINEMA_KEY', answer.getResponseText().trim())
}
function updateShowtimes() {
const key = PropertiesService.getScriptProperties().getProperty('API_CINEMA_KEY')
if (!key)
throw new Error('Pas encore de clé API : Cinéma › Enregistrer la clé API…')
const ss = SpreadsheetApp.getActiveSpreadsheet()
const config = configSheet(ss)
const slug = String(config.getRange('B1').getValue()).trim()
const days = Math.max(1, Math.min(14, Number(config.getRange('B2').getValue()) || 7))
if (!slug)
throw new Error('Mettez le slug du cinéma dans Config!B1')
const rows = fetchShowtimes(key, slug, days).map(s => [
s.startsAt.slice(0, 10), // date et heure locales du cinéma, telles que l’API les donne
s.startsAt.slice(11, 16),
s.movie.title,
s.movie.durationMin ? `${Math.floor(s.movie.durationMin / 60)} h ${String(s.movie.durationMin % 60).padStart(2, '0')}` : '',
s.version,
s.format,
s.bookingUrl || '',
])
const sheet = ss.getSheetByName('Séances') || ss.insertSheet('Séances')
sheet.clearContents()
sheet.getRange(1, 1, 1, HEADER.length).setValues([HEADER]).setFontWeight('bold')
if (rows.length)
sheet.getRange(2, 1, rows.length, HEADER.length).setValues(rows)
sheet.setFrozenRows(1)
sheet.autoResizeColumns(1, HEADER.length)
config.getRange('B3').setValue(new Date())
}
/** Toutes les séances du cinéma de maintenant à `days` jours, page par page. */
function fetchShowtimes(key, slug, days) {
const to = new Date()
to.setDate(to.getDate() + days - 1) // `to` est un jour entier : 7 jours = aujourd’hui et les 6 suivants
const params = { to: Utilities.formatDate(to, Session.getScriptTimeZone(), 'yyyy-MM-dd'), include: 'movie', limit: 1000 }
const all = []
let cursor
do {
const query = Object.entries({ ...params, cursor })
.filter(([, v]) => v !== undefined)
.map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
.join('&')
const res = UrlFetchApp.fetch(`${API}/cinemas/${encodeURIComponent(slug)}/showtimes?${query}`, {
headers: { Authorization: `Bearer ${key}` },
muteHttpExceptions: true,
})
if (res.getResponseCode() !== 200) {
throw new Error(`API Cinéma a répondu ${res.getResponseCode()} : ${res.getContentText().slice(0, 200)}`)
}
const body = JSON.parse(res.getContentText())
all.push(...body.data)
cursor = body.meta && body.meta.nextCursor
} while (cursor)
return all
}
/** La feuille Config, créée avec des valeurs par défaut la première fois. */
function configSheet(ss) {
let sheet = ss.getSheetByName('Config')
if (!sheet) {
sheet = ss.insertSheet('Config')
sheet.getRange('A1:B3').setValues([
['Slug du cinéma', 'le-champo-paris-5e-arrondissement'],
['Jours', 7],
['Dernière mise à jour', ''],
])
sheet.autoResizeColumns(1, 2)
}
return sheet
}
/** Une mise à jour par jour, vers 6 h du matin, dans le fuseau de la feuille. */
function installDailyTrigger() {
ScriptApp.getProjectTriggers()
.filter(t => t.getHandlerFunction() === 'updateShowtimes')
.forEach(t => ScriptApp.deleteTrigger(t))
ScriptApp.newTrigger('updateShowtimes').timeBased().everyDays(1).atHour(6).create()
SpreadsheetApp.getUi().alert('La feuille Séances se mettra à jour chaque matin.')
}Enregistrer la clé
Cinéma › Enregistrer la clé API… demande la clé et la range dans les propriétés du script : elle n’apparaît jamais dans une cellule, la feuille peut donc être partagée ou publiée sans la donner. Une chose à savoir : quiconque peut modifier la feuille peut ouvrir le script et lire ses propriétés. Partagez la feuille en Lecteur avec le public, gardez la modification pour les personnes de confiance, et révoquez la clé depuis le tableau de bord au moindre doute.
À la première exécution, Google vous demande d’autoriser le script : Vérifier les autorisations, choisissez votre compte, puis, le script étant le vôtre et non vérifié par Google, Paramètres avancés › Accéder à … (non sécurisé) › Autoriser. Il a besoin de deux choses : vos feuilles de calcul, et la connexion à un service externe (l’API).
Remplir la feuille
Cinéma › Mettre à jour les séances crée deux feuilles. Config contient le slug du cinéma (B1, Le Champo par défaut) et le nombre de jours (B2, 7, jusqu’à 14) ; Séances reçoit une ligne par séance, date, heure, film, durée, version, format et lien de réservation du cinéma, en-tête figé, colonnes ajustées. Changez le slug ou les jours dans Config, relancez : la feuille est réécrite.
Les horaires sont l’heure locale du cinéma, telle que l’API la renvoie : un cinéma de New York affiche l’heure de New York. Les séances déjà commencées sont laissées de côté, la liste part de maintenant. La durée et le lien de réservation viennent avec include=movie et les autres champs ; la documentation les liste tous.
Chaque matin
Cinéma › Mettre à jour chaque matin installe un déclencheur horaire : la feuille se met à jour vers 6 h, dans son fuseau, sans que personne ne l’ouvre. Cela fait une requête par jour pour une semaine de programme (un multiplexe sur 14 jours peut prendre deux ou trois pages, une requête chacune) : quelques requêtes par semaine sur un forfait qui en permet 150. Le déclencheur tourne avec votre compte ; si vous quittez l’organisation, confiez la feuille à quelqu’un d’autre et laissez-le le réinstaller.
La publier
- Partager ou intégrer. Fichier › Partager › Publier sur le Web donne une page publique ou un
<iframe>pour un site, mis à jour après chaque exécution. - Filtrer sur aujourd’hui. Dans une autre feuille,
=FILTER(Séances!A2:G; Séances!A2:A = TEXT(AUJOURDHUI(); "yyyy-mm-dd"))garde les lignes du jour ;=QUERY(Séances!A:G; "select C, count(B) group by C")compte les séances par film. - Une autre feuille, un autre cinéma.
=IMPORTRANGEdepuis une seconde feuille, ou des lignes en plus dans Config et une boucle dessus dansupdateShowtimes: une requête par cinéma.
Pour aller plus loin
- La VO seulement. Ajoutez
version: 'VOST'(ouVO) àparams: l’API filtre avant de répondre. - Les affiches.
s.movie.posterUrlest dans la réponse ;=IMAGE(H2)l’affiche dans une cellule. - Une ville plutôt qu’un cinéma.
GET /v1/showtimes?city=Lyon&include=movie,cinemaliste toutes les séances d’une ville, avec le cinéma sur chaque ligne : le même script avec une autre URL et une colonne de plus.
Les mêmes données alimentent le tutoriel Python (CSV et pandas, pour de plus gros exports) et le widget pour site web quand une page en a besoin en direct. Pour une newsletter ou un post chaque soir sans code, voyez le tutoriel n8n.