DailyByte
일상과 연결되는 AI
DailyByte
일상과 연결되는 AI
← 전체 코드 목록
📖 사용 방법
구글 시트에 있는 데이터를 활용하여 구글 슬라이드 프레젠테이션을 자동으로 만들고, 각 슬라이드에 시트 내용을 채워주는 스크립트입니다.
이런 분께 추천해요
- 반복적인 보고서, 제안서, 명함, 수료증 등을 슬라이드로 만들어야 하는 분
- 데이터를 일일이 복사해서 슬라이드에 붙여넣는 작업이 지겨운 분
- 구글 시트와 구글 슬라이드를 자주 활용하는 분
완성하면 이렇게 됩니다
- 구글 시트의 한 행(row) 데이터가 구글 슬라이드의 한 장(slide)으로 변환됩니다.
- 템플릿 슬라이드에
{{A}},{{B}}와 같은 표시를 해두면, 시트의 A열, B열 데이터가 자동으로 그 자리에 채워집니다. - 데이터가 100개면 100장의 슬라이드가 자동으로 만들어진 새로운 프레젠테이션 파일이 생성됩니다.
준비물
- 구글 시트 파일: 스크립트를 붙여넣을 데이터 시트 파일이 필요합니다.
- 구글 슬라이드 템플릿 파일: 슬라이드를 만들 때 사용할 디자인 템플릿 파일이 필요합니다. 이 템플릿 안에
{{A}},{{B}}와 같이 데이터를 넣을 위치를 미리 표시해 두어야 합니다. - 구글 계정: 당연하겠죠? :)
따라하기
1단계: 스크립트 복사 및 붙여넣기
- 현재 보고 계신 이 코드 스니펫을 모두 복사합니다.
- 구글 시트 파일을 엽니다.
- 상단 메뉴에서
확장 프로그램>Apps Script를 클릭합니다. - 새로운 스크립트 편집기 창이 열리면, 기존에 있던 코드를 모두 지우고 복사한 코드를 붙여넣습니다.
- 상단
저장아이콘(플로피 디스크 모양)을 클릭하여 스크립트를 저장합니다.
2단계: 템플릿 슬라이드 준비 및 설정
- 구글 슬라이드 템플릿 파일을 엽니다.
- 슬라이드 안에 시트 데이터를 넣을 위치에
{{A}},{{B}},{{C}}와 같이 중괄호 두 개로 감싼 대문자 알파벳을 입력합니다. (예: 시트의 A열 데이터가 들어갈 곳에는{{A}}, B열 데이터가 들어갈 곳에는{{B}}) - 템플릿 슬라이드 파일의 URL을 확인합니다.
https://docs.google.com/presentation/d/와/edit사이에 있는 긴 문자열이 템플릿 Slides ID입니다. 이 ID를 복사해 둡니다. - 다시 구글 시트 파일로 돌아와서, 스크립트 코드의
CONFIG부분에서SHEET_NAME을 데이터를 가져올 시트의 이름으로 변경합니다. (기본값은'data'입니다. 시트 이름이 'Sheet1'이면'Sheet1'으로 변경하세요.) HEADER_ROW는 헤더(제목)가 있는 행 번호,DATA_START_ROW는 실제 데이터가 시작되는 행 번호입니다. 시트에 맞게 수정하세요. (예: 1행이 제목이고 2행부터 데이터면 기본값 그대로 두시면 됩니다.)TEMPLATE_SLIDE_INDEX는 템플릿으로 사용할 슬라이드의 위치입니다. 첫 번째 슬라이드(0), 두 번째 슬라이드(1) 식으로 숫자를 입력합니다. (기본값은0으로 첫 슬라이드를 사용합니다.)KEEP_TEMPLATE_SLIDE는false로 두면 템플릿 슬라이드가 최종 결과물에서 삭제되고,true로 두면 표지 등으로 남겨둘 수 있습니다. 필요에 따라true또는false로 설정하세요.
3단계: 스크립트 실행
- 구글 시트 파일로 돌아와서 새로 생긴 메뉴
Slides 자동화를 클릭합니다. 슬라이드 생성(템플릿 복사)를 클릭합니다.- 최초 실행 시, 스크립트가 구글 계정에 접근할 권한을 요청합니다.
권한 검토를 클릭하고 본인의 구글 계정을 선택한 뒤,허용버튼을 눌러 권한을 부여합니다. - 스크립트가 실행되면,
템플릿 Slides ID 입력이라는 창이 나타납니다. 2단계에서 복사해 둔 템플릿 Slides ID를 붙여넣고확인을 누릅니다. - 스크립트가 완료되면, "완료! 생성된 Slides:"라는 메시지와 함께 새로 만들어진 구글 슬라이드 프레젠테이션의 URL이 표시됩니다. 이 URL을 클릭하면 결과물을 확인할 수 있습니다.
자주 막히는 부분
- 권한 요청: 처음 스크립트를 실행할 때 구글 계정 권한을 허용해야 합니다. 이 과정을 건너뛰면 스크립트가 작동하지 않습니다.
- 템플릿 Slides ID 오류: 템플릿 ID를 정확히 입력받지 못하면 오류가 발생합니다. URL에서
/d/와/edit사이의 값만 정확히 복사했는지 확인하세요. 잘못 입력했다면 구글 시트 메뉴에서Slides 자동화>템플릿 ID 다시 설정을 클릭하여 초기화할 수 있습니다. - 시트 이름 또는 데이터 범위 오류:
CONFIG.SHEET_NAME이 실제 시트 이름과 일치하는지,CONFIG.DATA_START_ROW가 데이터가 시작되는 행과 맞는지 확인하세요. - 템플릿 슬라이드 토큰 불일치: 템플릿 슬라이드에
{{A}}라고 입력했는데 시트의 A열에 데이터가 없거나, 반대로 시트에는 데이터가 있는데 템플릿에 해당 토큰이 없으면 원하는 결과가 나오지 않을 수 있습니다.
이렇게도 써보세요 (응용)
- 명함 자동 생성: 시트에 이름, 직책, 연락처 등을 입력하고 템플릿 슬라이드에
{{A}}(이름),{{B}}(직책) 등으로 표시하여 여러 장의 명함을 한 번에 만들 수 있습니다. - 수료증/상장 대량 발급: 시트에 수료자 이름, 과정명, 날짜 등을 입력하고 템플릿에 적용하여 수많은 수료증을 손쉽게 만들 수 있습니다.
- 주간/월간 보고서 자동화: 시트에 각 주의 데이터를 입력하고, 템플릿 슬라이드에 해당 데이터를 표시하여 매주/매월 보고서를 빠르게 생성할 수 있습니다.
한 줄 정리
구글 시트의 데이터를 구글 슬라이드 템플릿에 자동으로 채워 넣어, 반복적인 슬라이드 제작 작업을 획기적으로 줄여주는 똑똑한 스크립트입니다.
💻 코드
/******************************************************
* Google Sheets -> Google Slides (Template Copy 방식)
* - 템플릿 Slides 파일을 복사해서 출력본을 만들고,
* 복사본 내부에서 템플릿 슬라이드를 데이터 행 수만큼 복제(duplicate)한 뒤
* {{A}}, {{B}}, {{C}} ... 토큰을 각 열 값으로 치환합니다.
*
* 장점: 프레젠테이션 간 슬라이드 이동 문제 없이 안정적으로 동작
******************************************************/
const CONFIG = {
SHEET_NAME: 'data', // 데이터 시트 이름
HEADER_ROW: 1, // 헤더 행(권장)
DATA_START_ROW: 2, // 데이터 시작 행
TEMPLATE_SLIDE_INDEX: 0, // 템플릿 슬라이드 위치(0=첫 슬라이드)
OUTPUT_TITLE_PREFIX: '[AUTO] ',
KEEP_TEMPLATE_SLIDE: false, // true면 템플릿 슬라이드를 표지로 남김, false면 삭제
SKIP_EMPTY_ROW: true, // A열이 비면 해당 행은 슬라이드 생성 제외
// 스크립트 속성 키(템플릿 Slides ID 저장)
PROP_TEMPLATE_ID: 'TEMPLATE_PRESENTATION_ID',
};
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('Slides 자동화')
.addItem('슬라이드 생성(템플릿 복사)', 'runCreateByCopy')
.addSeparator()
.addItem('템플릿 ID 다시 설정', 'resetTemplateId')
.addToUi();
}
/**
* 메인 실행: 템플릿 복사 → 데이터 기반 슬라이드 생성
*/
function runCreateByCopy() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sh = ss.getSheetByName(CONFIG.SHEET_NAME);
if (!sh) throw new Error(`시트를 찾을 수 없습니다: ${CONFIG.SHEET_NAME}`);
const values = sh.getDataRange().getValues();
if (values.length < CONFIG.DATA_START_ROW) {
SpreadsheetApp.getUi().alert('데이터가 없습니다. (DATA_START_ROW 이후 행이 필요)');
return;
}
// 데이터행
let rows = values.slice(CONFIG.DATA_START_ROW - 1);
// 빈 행 제외(기본: A열 기준)
if (CONFIG.SKIP_EMPTY_ROW) {
rows = rows.filter(r => String(r[0] ?? '').trim() !== '');
}
if (rows.length === 0) {
SpreadsheetApp.getUi().alert('생성할 데이터 행이 없습니다. (A열이 비어있지 않은 행 필요)');
return;
}
const templateId = getTemplateId_();
const outUrl = createSlidesFromTemplate_(templateId, rows, ss.getName());
SpreadsheetApp.getUi().alert('완료!n생성된 Slides:n' + outUrl);
}
/**
* 템플릿 Slides를 Drive에서 복사해 새 프레젠테이션을 만들고,
* 그 안에서 템플릿 슬라이드를 duplicate하여 데이터 슬라이드를 생성합니다.
*/
function createSlidesFromTemplate_(templateId, rows, baseName) {
const outTitle =
CONFIG.OUTPUT_TITLE_PREFIX +
baseName +
' - ' +
Utilities.formatDate(new Date(), Session.getScriptTimeZone(), 'yyyy-MM-dd HHmm');
// 1) 템플릿 파일 복사(출력본)
const copiedFile = DriveApp.getFileById(templateId).makeCopy(outTitle);
const outPres = SlidesApp.openById(copiedFile.getId());
// 2) 템플릿 슬라이드 확보(복사본 내부)
const slides = outPres.getSlides();
const templateSlide = slides[CONFIG.TEMPLATE_SLIDE_INDEX];
if (!templateSlide) throw new Error('템플릿 슬라이드를 찾지 못했습니다. TEMPLATE_SLIDE_INDEX 확인 필요.');
// 3) 데이터 행마다 슬라이드 생성 + 치환
rows.forEach((row) => {
const newSlide = templateSlide.duplicate();
replaceTokensByColumns_(newSlide, row); // {{A}}~{{Z}} 치환
});
// 4) 템플릿 슬라이드 처리
// - KEEP_TEMPLATE_SLIDE=false면 템플릿 슬라이드를 제거
// - true면 표지로 남겨두는 구조(표지에 토큰이 있으면 그대로 남음)
if (!CONFIG.KEEP_TEMPLATE_SLIDE) {
templateSlide.remove(); // ✅ removeSlide 아님! Slide.remove()가 정답
}
return outPres.getUrl();
}
/**
* {{A}}, {{B}}, {{C}} ... 형태의 토큰을 시트 열 값으로 치환
* - A열: row[0], B열: row[1] ...
* - 기본은 A~Z(26열)까지만 지원
*/
function replaceTokensByColumns_(slide, row) {
const max = Math.min(row.length, 26);
for (let i = 0; i < max; i++) {
const colLetter = String.fromCharCode('A'.charCodeAt(0) + i);
const token = `{{${colLetter}}}`;
const value = row[i] == null ? '' : String(row[i]);
slide.replaceAllText(token, value);
}
}
/**
* 템플릿 Slides ID 가져오기(없으면 1회 입력받아 저장)
* - 템플릿 Slides URL에서 /d/ 와 /edit 사이 값
*/
function getTemplateId_() {
const props = PropertiesService.getDocumentProperties();
let id = props.getProperty(CONFIG.PROP_TEMPLATE_ID);
if (!id) {
const ui = SpreadsheetApp.getUi();
const res = ui.prompt(
'템플릿 Slides ID 입력',
'템플릿 Google Slides URL에서 /d/ 와 /edit 사이 값을 붙여넣으세요.n예) https://docs.google.com/presentation/d/여기/edit',
ui.ButtonSet.OK_CANCEL
);
if (res.getSelectedButton() !== ui.Button.OK) throw new Error('취소됨');
id = (res.getResponseText() || '').trim();
if (!id) throw new Error('템플릿 Slides ID가 비어있습니다.');
props.setProperty(CONFIG.PROP_TEMPLATE_ID, id);
}
return id;
}
/**
* 템플릿 ID 재설정(잘못 넣었을 때)
*/
function resetTemplateId() {
const props = PropertiesService.getDocumentProperties();
props.deleteProperty(CONFIG.PROP_TEMPLATE_ID);
SpreadsheetApp.getUi().alert('템플릿 ID 저장값을 삭제했습니다. 다음 실행 시 다시 입력받습니다.');
}