← 전체 코드 목록

📖 사용 방법

구글 시트에 있는 데이터를 활용하여 구글 슬라이드 프레젠테이션을 자동으로 만들고, 각 슬라이드에 시트 내용을 채워주는 스크립트입니다.

이런 분께 추천해요

  • 반복적인 보고서, 제안서, 명함, 수료증 등을 슬라이드로 만들어야 하는 분
  • 데이터를 일일이 복사해서 슬라이드에 붙여넣는 작업이 지겨운 분
  • 구글 시트와 구글 슬라이드를 자주 활용하는 분

완성하면 이렇게 됩니다

  • 구글 시트의 한 행(row) 데이터가 구글 슬라이드의 한 장(slide)으로 변환됩니다.
  • 템플릿 슬라이드에 {{A}}, {{B}}와 같은 표시를 해두면, 시트의 A열, B열 데이터가 자동으로 그 자리에 채워집니다.
  • 데이터가 100개면 100장의 슬라이드가 자동으로 만들어진 새로운 프레젠테이션 파일이 생성됩니다.

준비물

  • 구글 시트 파일: 스크립트를 붙여넣을 데이터 시트 파일이 필요합니다.
  • 구글 슬라이드 템플릿 파일: 슬라이드를 만들 때 사용할 디자인 템플릿 파일이 필요합니다. 이 템플릿 안에 {{A}}, {{B}}와 같이 데이터를 넣을 위치를 미리 표시해 두어야 합니다.
  • 구글 계정: 당연하겠죠? :)

따라하기

1단계: 스크립트 복사 및 붙여넣기

  1. 현재 보고 계신 이 코드 스니펫을 모두 복사합니다.
  2. 구글 시트 파일을 엽니다.
  3. 상단 메뉴에서 확장 프로그램 > Apps Script를 클릭합니다.
  4. 새로운 스크립트 편집기 창이 열리면, 기존에 있던 코드를 모두 지우고 복사한 코드를 붙여넣습니다.
  5. 상단 저장 아이콘(플로피 디스크 모양)을 클릭하여 스크립트를 저장합니다.

2단계: 템플릿 슬라이드 준비 및 설정

  1. 구글 슬라이드 템플릿 파일을 엽니다.
  2. 슬라이드 안에 시트 데이터를 넣을 위치에 {{A}}, {{B}}, {{C}}와 같이 중괄호 두 개로 감싼 대문자 알파벳을 입력합니다. (예: 시트의 A열 데이터가 들어갈 곳에는 {{A}}, B열 데이터가 들어갈 곳에는 {{B}})
  3. 템플릿 슬라이드 파일의 URL을 확인합니다. https://docs.google.com/presentation/d//edit 사이에 있는 긴 문자열이 템플릿 Slides ID입니다. 이 ID를 복사해 둡니다.
  4. 다시 구글 시트 파일로 돌아와서, 스크립트 코드의 CONFIG 부분에서 SHEET_NAME을 데이터를 가져올 시트의 이름으로 변경합니다. (기본값은 'data'입니다. 시트 이름이 'Sheet1'이면 'Sheet1'으로 변경하세요.)
  5. HEADER_ROW는 헤더(제목)가 있는 행 번호, DATA_START_ROW는 실제 데이터가 시작되는 행 번호입니다. 시트에 맞게 수정하세요. (예: 1행이 제목이고 2행부터 데이터면 기본값 그대로 두시면 됩니다.)
  6. TEMPLATE_SLIDE_INDEX는 템플릿으로 사용할 슬라이드의 위치입니다. 첫 번째 슬라이드(0), 두 번째 슬라이드(1) 식으로 숫자를 입력합니다. (기본값은 0으로 첫 슬라이드를 사용합니다.)
  7. KEEP_TEMPLATE_SLIDEfalse로 두면 템플릿 슬라이드가 최종 결과물에서 삭제되고, true로 두면 표지 등으로 남겨둘 수 있습니다. 필요에 따라 true 또는 false로 설정하세요.

3단계: 스크립트 실행

  1. 구글 시트 파일로 돌아와서 새로 생긴 메뉴 Slides 자동화를 클릭합니다.
  2. 슬라이드 생성(템플릿 복사)를 클릭합니다.
  3. 최초 실행 시, 스크립트가 구글 계정에 접근할 권한을 요청합니다. 권한 검토를 클릭하고 본인의 구글 계정을 선택한 뒤, 허용 버튼을 눌러 권한을 부여합니다.
  4. 스크립트가 실행되면, 템플릿 Slides ID 입력이라는 창이 나타납니다. 2단계에서 복사해 둔 템플릿 Slides ID를 붙여넣고 확인을 누릅니다.
  5. 스크립트가 완료되면, "완료! 생성된 Slides:"라는 메시지와 함께 새로 만들어진 구글 슬라이드 프레젠테이션의 URL이 표시됩니다. 이 URL을 클릭하면 결과물을 확인할 수 있습니다.

자주 막히는 부분

  • 권한 요청: 처음 스크립트를 실행할 때 구글 계정 권한을 허용해야 합니다. 이 과정을 건너뛰면 스크립트가 작동하지 않습니다.
  • 템플릿 Slides ID 오류: 템플릿 ID를 정확히 입력받지 못하면 오류가 발생합니다. URL에서 /d//edit 사이의 값만 정확히 복사했는지 확인하세요. 잘못 입력했다면 구글 시트 메뉴에서 Slides 자동화 > 템플릿 ID 다시 설정을 클릭하여 초기화할 수 있습니다.
  • 시트 이름 또는 데이터 범위 오류: CONFIG.SHEET_NAME이 실제 시트 이름과 일치하는지, CONFIG.DATA_START_ROW가 데이터가 시작되는 행과 맞는지 확인하세요.
  • 템플릿 슬라이드 토큰 불일치: 템플릿 슬라이드에 {{A}}라고 입력했는데 시트의 A열에 데이터가 없거나, 반대로 시트에는 데이터가 있는데 템플릿에 해당 토큰이 없으면 원하는 결과가 나오지 않을 수 있습니다.

이렇게도 써보세요 (응용)

  • 명함 자동 생성: 시트에 이름, 직책, 연락처 등을 입력하고 템플릿 슬라이드에 {{A}}(이름), {{B}}(직책) 등으로 표시하여 여러 장의 명함을 한 번에 만들 수 있습니다.
  • 수료증/상장 대량 발급: 시트에 수료자 이름, 과정명, 날짜 등을 입력하고 템플릿에 적용하여 수많은 수료증을 손쉽게 만들 수 있습니다.
  • 주간/월간 보고서 자동화: 시트에 각 주의 데이터를 입력하고, 템플릿 슬라이드에 해당 데이터를 표시하여 매주/매월 보고서를 빠르게 생성할 수 있습니다.

한 줄 정리

구글 시트의 데이터를 구글 슬라이드 템플릿에 자동으로 채워 넣어, 반복적인 슬라이드 제작 작업을 획기적으로 줄여주는 똑똑한 스크립트입니다.

💻 코드

Code.gs
/******************************************************
 * 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 저장값을 삭제했습니다. 다음 실행 시 다시 입력받습니다.');
}

🎬 관련 영상