슬라이드에 데이터 병합

Slides API는 하나 이상의 데이터 소스의 정보를 템플릿 기반 슬라이드 덱에 병합할 수 있는 매우 유용한 기능을 제공합니다.

메일 병합 개념도

이 접근법은 다음을 포함한 많은 유용성을 제공합니다.

  • 디자이너가 Google Slides 편집기를 사용하여 프레젠테이션 디자인을 쉽게 미세조정할 수 있습니다. 이 방법은 앱에서 매개변수를 조정하는 방법에 비해 렌더링된 슬라이드 디자인을 훨씬 쉽게 조정할 수 있습니다.

  • 프레젠테이션에서 콘텐츠를 분리하는 것은 많은 이점을 가진 잘 알려진 디자인 원칙입니다.

이 페이지에서는 외부 소스에서 데이터를 가져와서 기존 "템플릿" 프레젠테이션에 삽입하는 방법에 대해 간략히 설명합니다. 이 개념은 워드 프로세서와 스프레드시트를 사용하는 메일 병합의 개념과 유사합니다.

기본 레시피

다음은 Slides API를 사용하여 데이터를 프레젠테이션에 병합하는 방법의 예입니다. 전체 단계는 다음과 같습니다.

  1. 디자인을 돕기 위해 더미 콘텐츠를 사용하여 정확히 나타내려는 프레젠테이션을 만듭니다.

  2. 삽입할 각 콘텐츠 요소에 대해 더미 콘텐츠를 태그로 대체합니다. 태그는 단지 고유한 문자열을 가진 텍스트 상자나 도형일 뿐입니다.

  3. 코드에서 Google Drive API를 사용하여 프레젠테이션의 새 복사본을 만듭니다.

  4. 코드에서 Slides API의 batchUpdate 메서드와 replaceAllText 요청 집합을 사용하여 프레젠테이션 전체에서 모든 텍스트 대체를 수행합니다. replaceAllShapesWithImage 요청을 사용하여 프레젠테이션 전체에서 이미지 대체를 수행합니다.

태그를 설정할 때 일반적으로 나타날 확률이 적은 문자열을 사용해야 합니다. 예를 들어, {{account-holder-name}}은 좋은 태그에 해당할 수 있습니다.

태그를 포함하는 덱을 만든 후에는 복사본을 만들고 Slides API를 사용하여 복사본을 조작해야 합니다. Slides API를 사용하여 마스터 "템플릿" 복사본을 조작하지 마십시오!

다음 섹션에 이 과정의 일부를 보여주는 코드 스니펫이 포함되어 있습니다.

텍스트 병합

replaceAllText 요청을 사용하여 프레젠테이션에서 지정된 텍스트 문자열의 모든 인스턴스를 새 텍스트로 대체할 수 있습니다. 병합의 경우 이는 일반적으로 텍스트의 각 인스턴스를 개별적으로 찾아 바꾸는 것보다 훨씬 간단합니다. 이 접근방식이 가장 강력한 한 가지 이유는 특히 공동작업자가 템플릿 프레젠테이션을 미세조정하고 유지 관리할 때 페이지 요소 ID를 예측하기 어렵다는 것입니다.

예시

이 예시에서는 Google Drive API를 사용하여 템플릿 프레젠테이션을 복사하고 프레젠테이션의 새 인스턴스를 만듭니다. 그런 다음 Sheets API를 사용하여 Google Sheets에서 데이터를 읽고, 마지막으로 Slides API를 사용하여 새 프레젠테이션을 업데이트합니다.

이 예시는 스프레드시트에서 명명된 범위의 한 행에 있는 3개의 셀에서 데이터를 취합니다. 그런 다음 문자열 {{customer-name}}, {{case-description}}, 및 {{total-portfolio}}가 나타나는 곳마다 해당 데이터를 프레젠테이션으로 대체합니다.

Java

// Use the Sheets API to load data, one record per row.
String dataRangeNotation = "Customers!A2:M6";
ValueRange sheetsResponse = sheetsService.spreadsheets().values()
        .get(dataSpreadsheetId, dataRangeNotation).execute();
List<List<Object>> values = sheetsResponse.getValues();

// For each record, create a new merged presentation.
for (List<Object> row: values) {
    String customerName = row.get(2).toString();     // name in column 3
    String caseDescription = row.get(5).toString();  // case description in column 6
    String totalPortfolio = row.get(11).toString();  // total portfolio in column 12

    // Duplicate the template presentation using the Drive API.
    String copyTitle = customerName + " presentation";
    File content = new File().setName(copyTitle);
    File presentationFile =
            driveService.files().copy(templatePresentationId, content).execute();
    String presentationId = presentationFile.getId();

    // Create the text merge (replaceAllText) requests for this presentation.
    List<Request> requests = new ArrayList<>();
    requests.add(new Request()
            .setReplaceAllText(new ReplaceAllTextRequest()
                    .setContainsText(new SubstringMatchCriteria()
                            .setText("{{customer-name}}")
                            .setMatchCase(true))
                    .setReplaceText(customerName)));
    requests.add(new Request()
            .setReplaceAllText(new ReplaceAllTextRequest()
                    .setContainsText(new SubstringMatchCriteria()
                            .setText("{{case-description}}")
                            .setMatchCase(true))
                    .setReplaceText(caseDescription)));
    requests.add(new Request()
            .setReplaceAllText(new ReplaceAllTextRequest()
                    .setContainsText(new SubstringMatchCriteria()
                            .setText("{{total-portfolio}}")
                            .setMatchCase(true))
                    .setReplaceText(totalPortfolio)));

    // Execute the requests for this presentation.
    BatchUpdatePresentationRequest body =
            new BatchUpdatePresentationRequest().setRequests(requests);
    BatchUpdatePresentationResponse response =
            slidesService.presentations().batchUpdate(presentationId, body).execute();

Python

# Use the Sheets API to load data, one record per row.
data_range_notation = 'Customers!A2:M6'
sheets_response = sheets_service.spreadsheets().values().get(
    spreadsheetId=data_spreadsheet_id, range=data_range_notation).execute()
values = sheets_response.get('values')

# For each record, create a new merged presentation.
for row in values:
    customer_name = row[2]       # name in column 3
    case_description = row[5]    # case description in column 6
    total_portfolio = row[11]    # total portfolio in column 12

    # Duplicate the template presentation using the Drive API.
    copy_title = customer_name + ' presentation'
    body = {
        'name': copy_title
    }
    drive_response = drive_service.files().copy(
        fileId=template_presentation_id, body=body).execute()
    presentation_copy_id = drive_response.get('id')

    # Create the text merge (replaceAllText) requests for this presentation.
    requests = [
        {
            'replaceAllText': {
                'containsText': {
                    'text': '{{customer-name}}',
                    'matchCase': True
                },
                'replaceText': customer_name
            }
        },
        {
            'replaceAllText': {
                'containsText': {
                    'text': '{{case-description}}',
                    'matchCase': True
                },
                'replaceText': case_description
            }
        },
        {
            'replaceAllText': {
                'containsText': {
                    'text': '{{total-portfolio}}',
                    'matchCase': True
                },
                'replaceText': total_portfolio
            }
        }
    ]

    # Execute the requests for this presentation.
    body = {
        'requests': requests
    }
    response = slides_service.presentations().batchUpdate(
        presentationId=presentation_copy_id, body=body).execute()

PHP

// Use the Sheets API to load data, one record per row.
$dataRangeNotation = 'Customers!A2:M6';
$sheetsResponse =
  $sheetsService->spreadsheets_values->get($dataSpreadsheetId, $dataRangeNotation);
$values = $sheetsResponse['values'];

// For each record, create a new merged presentation.
foreach($values as $row) {
  $customerName = $row[2];     // name in column 3
  $caseDescription = $row[5];  // case description in column 6
  $totalPortfolio = $row[11];  // total portfolio in column 12

  // Duplicate the template presentation using the Drive API.
  $copy = new Google_Service_Drive_DriveFile(array(
    'name' => $customerName . ' presentation'
  ));
  $driveResponse = $driveService->files->copy($templatePresentationId, $copy);
  $presentationCopyId = $driveResponse->id;

  // Create the text merge (replaceAllText) requests for this presentation.
  $requests = array();
  $requests[] = new Google_Service_Slides_Request(array(
    'replaceAllText' => array(
      'containsText' => array(
        'text' => '{{customer-name}}',
        'matchCase' => true
      ),
      'replaceText' => $customerName
    )
  ));
  $requests[] = new Google_Service_Slides_Request(array(
    'replaceAllText' => array(
      'containsText' => array(
        'text' => '{{case-description}}',
        'matchCase' => true
      ),
      'replaceText' => $caseDescription
    )
  ));
  $requests[] = new Google_Service_Slides_Request(array(
    'replaceAllText' => array(
      'containsText' => array(
        'text' => '{{total-portfolio}}',
        'matchCase' => true
      ),
      'replaceText' => $totalPortfolio
    )
  ));

  // Execute the requests for this presentation.
  $batchUpdateRequest = new Google_Service_Slides_BatchUpdatePresentationRequest(array(
    'requests' => $requests
  ));
  $response =
    $slidesService->presentations->batchUpdate($presentationCopyId, $batchUpdateRequest);

이미지 병합

replaceAllShapesWithImage 요청을 사용하여 이미지를 프레젠테이션에 병합할 수도 있습니다. 이 요청은 제공된 텍스트 문자열을 포함하는 모든 도형 인스턴스를 제공된 이미지로 바꿉니다. 이 요청은 이미지의 가로세로 비율을 유지하면서 태그 도형의 테두리 내에 들어가도록 이미지의 위치와 배율을 자동으로 지정합니다.

예시

이 예시에서는 Google Drive API를 사용하여 템플릿 프레젠테이션을 복사하고 프레젠테이션의 새 인스턴스를 만듭니다. 그런 다음 Slides API를 사용하여 {{company-logo}}라는 텍스트가 있는 도형을 찾아 회사 로그 이미지로 바꿉니다. 이 요청은 또한 {{customer-graphic}}라는 텍스트가 있는 도형을 다른 이미지로 바꿉니다.

Java

// Duplicate the template presentation using the Drive API.
String copyTitle = customerName + " presentation";
File content = new File().setName(copyTitle);
File presentationFile =
        driveService.files().copy(templatePresentationId, content).execute();
String presentationId = presentationFile.getId();

// Create the image merge (replaceAllShapesWithImage) requests.
List<Request> requests = new ArrayList<>();
requests.add(new Request()
        .setReplaceAllShapesWithImage(new ReplaceAllShapesWithImageRequest()
                .setImageUrl(logoUrl)
                .setReplaceMethod("CENTER_INSIDE")
                .setContainsText(new SubstringMatchCriteria()
                        .setText("{{company-logo}}")
                        .setMatchCase(true))));
requests.add(new Request()
        .setReplaceAllShapesWithImage(new ReplaceAllShapesWithImageRequest()
                .setImageUrl(customerGraphicUrl)
                .setReplaceMethod("CENTER_INSIDE")
                .setContainsText(new SubstringMatchCriteria()
                        .setText("{{customer-graphic}}")
                        .setMatchCase(true))));

// Execute the requests.
BatchUpdatePresentationRequest body =
        new BatchUpdatePresentationRequest().setRequests(requests);
BatchUpdatePresentationResponse response =
        slidesService.presentations().batchUpdate(presentationId, body).execute();

// Count total number of replacements made.
int numReplacements = 0;
for(Response resp: response.getReplies()) {
    numReplacements += resp.getReplaceAllShapesWithImage().getOccurrencesChanged();
}

System.out.println("Created merged presentation with ID: " + presentationId);
System.out.println("Replaced " + numReplacements + " shapes instances with images.");

Python

# Duplicate the template presentation using the Drive API.
copy_title = customer_name + ' presentation'
drive_response = drive_service.files().copy(
    fileId=template_presentation_id, body={'name': copy_title}).execute()
presentation_copy_id = drive_response.get('id')

# Create the image merge (replaceAllShapesWithImage) requests.
requests = []
requests.append({
    'replaceAllShapesWithImage': {
        'imageUrl': logo_url,
        'replaceMethod': 'CENTER_INSIDE',
        'containsText': {
            'text': '{{company-logo}}',
            'matchCase': True
        }
    }
})
requests.append({
    'replaceAllShapesWithImage': {
        'imageUrl': customer_graphic_url,
        'replaceMethod': 'CENTER_INSIDE',
        'containsText': {
            'text': '{{customer-graphic}}',
            'matchCase': True
        }
    }
})

# Execute the requests.
body = {
    'requests': requests
}
response = slides_service.presentations().batchUpdate(
    presentationId=presentation_copy_id, body=body).execute()

# Count the number of replacements made.
num_replacements = 0
for reply in response.get('replies'):
    num_replacements += reply.get('replaceAllShapesWithImage').get('occurrencesChanged')
print('Created merged presentation with ID: {0}'.format(presentation_copy_id))
print('Replaced %d shapes with images.' % num_replacements)

PHP

// Duplicate the template presentation using the Drive API.
$copy = new Google_Service_Drive_DriveFile(array(
  'name' => $customerName . ' presentation'
));
$driveResponse = $driveService->files->copy($templatePresentationId, $copy);
$presentationCopyId = $driveResponse->id;

// Create the image merge (replaceAllShapesWithImage) requests.
$requests = array();
$requests[] = new Google_Service_Slides_Request(array(
  'replaceAllShapesWithImage' => array(
    'imageUrl' => $logoUrl,
    'replaceMethod' => 'CENTER_INSIDE',
    'containsText' => array(
      'text' => '{{company-logo}}',
      'matchCase' => true
    )
  )
));
$requests[] = new Google_Service_Slides_Request(array(
  'replaceAllShapesWithImage' => array(
    'imageUrl' => $customerGraphicUrl,
    'replaceMethod' => 'CENTER_INSIDE',
    'containsText' => array(
      'text' => '{{customer-graphic}}',
      'matchCase' => true
    )
  )
));

// Execute the requests.
$batchUpdateRequest = new Google_Service_Slides_BatchUpdatePresentationRequest(array(
  'requests' => $requests
));
$response =
  $slidesService->presentations->batchUpdate($presentationCopyId, $batchUpdateRequest);

// Count the total number of replacements made.
$numReplacements = 0;
foreach($response->getReplies() as $reply) {
  $numReplacements += $reply->getReplaceAllShapesWithImage()->getOccurrencesChanged();
}
printf("Created presentation for %s with ID: %s\n", $customerName, $presentationCopyId);
printf("Replaced %d shapes with images.\n", $numReplacements);

특정 텍스트 상자 또는 이미지 인스턴스 바꾸기

replaceAllTextreplaceAllShapesWithImage 요청은 프레젠테이션 전체에서 태그를 바꾸는 데 유용하지만, 특정 슬라이드에 배치와 같은 어떤 기준에 따라 요소를 바꿔야만 하는 경우도 있습니다.

이 경우 바꿀 태그 도형의 ID를 검색해야 합니다. 텍스트 바꾸기의 경우 해당 도형에서 기존 텍스트를 삭제한 다음 새 텍스트를 삽입합니다(지정된 도형에서 텍스트 편집 예시 참조).

이미지 바꾸기는 훨씬 복잡합니다. 이미지에 병합하려면 다음 작업을 수행해야 합니다.

  1. 태그 도형의 ID를 가져옵니다.
  2. 태그에서 크기 및 변환 정보를 복사합니다.
  3. 크기 및 변환 정보를 사용하여 이미지를 페이지에 추가합니다.
  4. 태그 도형을 삭제합니다.

이미지를 원하는 크기로 조정하는 동안 이미지의 가로세로 비율을 유지하려면 다음 단락에 설명된 대로 약간의 주의가 필요할 수 있습니다. 도형 태그를 이미지로 바꾸기 예시를 참조하세요.

가로세로 비율 유지

Slides API를 사용하여 이미지를 만들 때 가로세로 비율 맞춤은 크기 및 변환 데이터가 아니라 이미지 크기만 기반으로 합니다. createImage 요청에서 제공하는 크기 데이터는 원하는 이미지 크기로 간주됩니다. API는 이미지의 가로세로 비율을 이 원하는 크기로 맞춘 후에 제공된 변환을 적용합니다.

태그를 이미지로 바꿀 때 이미지의 크기 및 배율을 다음과 같이 설정하여 이미지의 가로세로 비율을 유지합니다.

  • width: 태그의 widthscaleX의 곱으로 설정
  • height: 태그의 heightscaleY의 곱으로 설정
  • scale_x: 1로 설정
  • scale_y: 1로 설정

이렇게 하면 Slides API가 배율이 조정되지 않은 크기가 아니라 태그의 시각적 크기에 따라 이미지의 가로세로 비율을 맞춥니다(도형 태그를 이미지로 바꾸기 참조). 배율 매개변수를 1로 설정하면 이미지의 배율이 두 번 조정되는 것을 방지합니다.

이 정렬은 이미지의 가로세로 비율을 유지하며 이미지가 태그 도형의 크기를 초과하지 않게 합니다. 이미지가 태그 도형과 동일한 중심점을 갖게 됩니다.

템플릿 관리

애플리케이션이 정의하고 소유한 템플릿 프레젠테이션의 경우, 애플리케이션을 나타내는 전용 계정을 사용하여 템플릿을 만듭니다. 서비스 계정은 탁월한 선택이며 공유를 제한하는 GSuite 정책으로 복잡한 문제를 피합니다.

템플릿에서 프레젠테이션 인스턴스를 만들 때 항상 최종 사용자 인증서를 사용하세요. 그러면 사용자가 최종 프레젠테이션을 완벽히 제어하고 Google Drive에서 사용자별 제한과 관련된 배율 문제를 방지할 수 있습니다.

서비스 계정을 사용하여 템플릿을 만들려면 애플리케이션 인증서를 사용하여 다음 단계를 수행합니다.

  1. Slides API에서 presentation.create을 사용하여 새 프레젠테이션을 만듭니다.
  2. Drive API에서 files.permissions.insert를 사용하여 모든 사람에게 읽기를 허용하도록 권한을 업데이트합니다.
  3. Drive API에서 files.permissions.insert를 사용하여 템플릿 작성자에게 쓰기를 허용하도록 권한을 업데이트합니다.
  4. 필요에 따라 템플릿을 편집합니다.

새 프레젠테이션 인스턴스를 만들려면 사용자 인증서를 사용하여 다음 단계를 수행합니다.

  1. Drive API에서 files.copy를 사용하여 템플릿 복사본을 만듭니다.
  2. Slides API에서 presentation.batchUpdate를 사용하여 값을 바꿉니다.

다음에 대한 의견 보내기...

도움이 필요하시나요? 지원 페이지를 방문하세요.