將資料合併至簡報

Google Slides API 的其中一項實用用途是合併 製作範本簡報

本頁面概述如何從外部來源擷取資料 並插入現有範本簡報中概念是 與使用文書處理程式和試算表合併郵件的功能類似。

這種方法很實用有以下幾個原因:

  • 設計人員可以使用 使用 Google 簡報編輯器比起在實際工作環境中 設定轉譯的投影片設計。

  • 從簡報中區隔內容是一項著名的設計 開發原則有許多好處

合併作業的概念圖。

基本食譜

以下範例說明如何使用 Slides API 將資料合併成簡報:

  1. 建立簡報的顯示方式 預留位置內容協助您設計

  2. 針對您要插入的每個內容元素,將預留位置替換成 標記內容標記是含有不重複字串的文字方塊或形狀。請務必使用不太可能發生的字串。例如: 「{{account-holder-name}}」可能是個不錯的標記。

  3. 在程式碼中,使用 Google Drive API 建立 簡報

  4. 在程式碼中,使用 Slides API 的 batchUpdate敬上 方法,其中包含一組 replaceAllText 執行所有文字替代要求,執行整份簡報中的所有文字替代作業。 使用 replaceAllShapesWithImage 要求執行圖片替代

建立含有標記的簡報後,請務必複製一份 以及使用 Slides API 操控本副本。不要使用 Slides API 藉此操控主要「範本」複製!

以下各節包含程式碼片段來說明其中一部分 上傳資料集之後,您可以運用 AutoML 自動完成部分資料準備工作您也可以觀看上方影片 查看完整範例 (Python) 結合了以下個別章節的幾個概念。

合併文字

您可以使用 replaceAllText 要求,用來在 顯示新文字的簡報合併時,這樣的做法比 可以個別尋找並取代每個文字例項其中一個原因是 最複雜的做法是網頁元素 ID 難以預測 特別是當協作者修正和維護範本時 簡報

範例

這個範例使用 Drive API 複製一份範本簡報, 接著請建立新的簡報執行個體然後使用 Google Sheets API 讀取資料 ,最後使用 Slides API 更新 新版簡報

這個範例會擷取 試算表。然後將這些資料替換成簡報中 字串 {{customer-name}}{{case-description}},或 發生 {{total-portfolio}} 次。

Apps Script

slides/api/Snippets.gs
/**
 * Use the Sheets API to load data, one record per row.
 * @param {string} templatePresentationId
 * @param {string} dataSpreadsheetId
 * @returns {*[]}
 */
function textMerging(templatePresentationId, dataSpreadsheetId) {
  let responses = [];
  const dataRangeNotation = 'Customers!A2:M6';
  try {
    let values = SpreadsheetApp.openById(dataSpreadsheetId).getRange(dataRangeNotation).getValues();

    // For each record, create a new merged presentation.
    for (let i = 0; i < values.length; ++i) {
      const row = values[i];
      const customerName = row[2]; // name in column 3
      const caseDescription = row[5]; // case description in column 6
      const totalPortfolio = row[11]; // total portfolio in column 12

      // Duplicate the template presentation using the Drive API.
      const copyTitle = customerName + ' presentation';
      let copyFile = {
        title: copyTitle,
        parents: [{id: 'root'}]
      };
      copyFile = Drive.Files.copy(copyFile, templatePresentationId);
      const presentationCopyId = copyFile.id;

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

      // Execute the requests for this presentation.
      const result = Slides.Presentations.batchUpdate({
        requests: requests
      }, presentationCopyId);
      // Count the total number of replacements made.
      let numReplacements = 0;
      result.replies.forEach(function(reply) {
        numReplacements += reply.replaceAllText.occurrencesChanged;
      });
      console.log('Created presentation for %s with ID: %s', customerName, presentationCopyId);
      console.log('Replaced %s text instances', numReplacements);
    }
  } catch (err) {
    // TODO (Developer) - Handle exception
    console.log('Failed with error: %s', err.error);
  }
};

Go

slides/snippets/presentations.go
// Use the Sheets API to load data, one record per row.
dataRangeNotation := "Customers!A2:M6"
sheetsResponse, _ := sheetsService.Spreadsheets.Values.Get(dataSpreadsheetId, dataRangeNotation).Do()
values := sheetsResponse.Values

// For each record, create a new merged presentation.
for _, row := range values {
	customerName := row[2].(string)
	caseDescription := row[5].(string)
	totalPortfolio := row[11].(string)

	// Duplicate the template presentation using the Drive API.
	copyTitle := customerName + " presentation"
	file := drive.File{
		Title: copyTitle,
	}
	presentationFile, _ := driveService.Files.Copy(templatePresentationId, &file).Do()
	presentationId := presentationFile.Id

	// Create the text merge (replaceAllText) requests for this presentation.
	requests := []*slides.Request{{
		ReplaceAllText: &slides.ReplaceAllTextRequest{
			ContainsText: &slides.SubstringMatchCriteria{
				Text:      "{{customer-name}}",
				MatchCase: true,
			},
			ReplaceText: customerName,
		},
	}, {
		ReplaceAllText: &slides.ReplaceAllTextRequest{
			ContainsText: &slides.SubstringMatchCriteria{
				Text:      "{{case-description}}",
				MatchCase: true,
			},
			ReplaceText: caseDescription,
		},
	}, {
		ReplaceAllText: &slides.ReplaceAllTextRequest{
			ContainsText: &slides.SubstringMatchCriteria{
				Text:      "{{total-portfolio}}",
				MatchCase: true,
			},
			ReplaceText: totalPortfolio,
		},
	}}

	// Execute the requests for this presentation.
	body := &slides.BatchUpdatePresentationRequest{
		Requests: requests,
	}
	response, _ := slidesService.Presentations.BatchUpdate(presentationId, body).Do()

Java

slides/snippets/src/main/java/TextMerging.java
import com.google.api.client.googleapis.json.GoogleJsonError;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.model.File;
import com.google.api.services.sheets.v4.Sheets;
import com.google.api.services.sheets.v4.model.ValueRange;
import com.google.api.services.slides.v1.Slides;
import com.google.api.services.slides.v1.SlidesScopes;
import com.google.api.services.slides.v1.model.BatchUpdatePresentationRequest;
import com.google.api.services.slides.v1.model.BatchUpdatePresentationResponse;
import com.google.api.services.slides.v1.model.ReplaceAllTextRequest;
import com.google.api.services.slides.v1.model.Request;
import com.google.api.services.slides.v1.model.Response;
import com.google.api.services.slides.v1.model.SubstringMatchCriteria;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/* Class to demonstrate the use of Slides Text Merging API */
public class TextMerging {
  /**
   * Changes specified texts with data from spreadsheet.
   *
   * @param templatePresentationId - id of the presentation.
   * @param dataSpreadsheetId      - id of the spreadsheet containing data.
   * @return merged presentation id
   * @throws IOException - if credentials file not found.
   */
  public static List<BatchUpdatePresentationResponse> textMerging(
      String templatePresentationId, String dataSpreadsheetId) throws IOException {
        /* Load pre-authorized user credentials from the environment.
           TODO(developer) - See https://developers.google.com/identity for
            guides on implementing OAuth2 for your application. */
    GoogleCredentials credentials = GoogleCredentials.getApplicationDefault()
        .createScoped(Arrays.asList(SlidesScopes.PRESENTATIONS,
            SlidesScopes.DRIVE, SlidesScopes.SPREADSHEETS));
    HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(
        credentials);

    // Create the slides API client
    Slides service = new Slides.Builder(new NetHttpTransport(),
        GsonFactory.getDefaultInstance(),
        requestInitializer)
        .setApplicationName("Slides samples")
        .build();

    // Create the drive API client
    Drive driveService = new Drive.Builder(new NetHttpTransport(),
        GsonFactory.getDefaultInstance(),
        requestInitializer)
        .setApplicationName("Slides samples")
        .build();

    // Create the sheets API client
    Sheets sheetsService = new Sheets.Builder(new NetHttpTransport(),
        GsonFactory.getDefaultInstance(),
        requestInitializer)
        .setApplicationName("Slides samples")
        .build();

    List<BatchUpdatePresentationResponse> responses = new ArrayList<>(5);
    // 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();

    try {
      // 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 =
            service.presentations().batchUpdate(presentationId, body).execute();

        // Count total number of replacements made.
        int numReplacements = 0;
        for (Response resp : response.getReplies()) {
          numReplacements += resp.getReplaceAllText().getOccurrencesChanged();
        }
        // Prints the merged presentation id and count of replacements.
        System.out.println("Created merged presentation for " +
            customerName + " with ID: " + presentationId);
        System.out.println("Replaced " + numReplacements + " text instances.");
      }
    } catch (NullPointerException ne) {
      System.out.println("Text not found to replace with image.");
    } catch (GoogleJsonResponseException e) {
      // TODO(developer) - handle error appropriately
      GoogleJsonError error = e.getDetails();
      if (error.getCode() == 404) {
        System.out.printf("Presentation not found with id '%s'.\n", templatePresentationId);
      } else {
        throw e;
      }
    }
    return responses;
  }
}

JavaScript

slides/snippets/slides_text_merging.js
function textMerging(templatePresentationId, dataSpreadsheetId, callback) {
  // Use the Sheets API to load data, one record per row.
  const responses = [];
  const dataRangeNotation = 'Customers!A2:M6';
  try {
    gapi.client.sheets.spreadsheets.values.get({
      spreadsheetId: dataSpreadsheetId,
      range: dataRangeNotation,
    }).then((sheetsResponse) => {
      const values = sheetsResponse.result.values;
      // For each record, create a new merged presentation.
      for (let i = 0; i < values.length; ++i) {
        const row = values[i];
        const customerName = row[2]; // name in column 3
        const caseDescription = row[5]; // case description in column 6
        const totalPortfolio = row[11]; // total portfolio in column 12

        // Duplicate the template presentation using the Drive API.
        const copyTitle = customerName + ' presentation';
        const request = {
          name: copyTitle,
        };
        gapi.client.drive.files.copy({
          fileId: templatePresentationId,
          requests: request,
        }).then((driveResponse) => {
          const presentationCopyId = driveResponse.result.id;

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

          // Execute the requests for this presentation.
          gapi.client.slides.presentations.batchUpdate({
            presentationId: presentationCopyId,
            requests: requests,
          }).then((batchUpdateResponse) => {
            const result = batchUpdateResponse.result;
            responses.push(result.replies);
            // Count the total number of replacements made.
            let numReplacements = 0;
            for (let i = 0; i < result.replies.length; ++i) {
              numReplacements += result.replies[i].replaceAllText.occurrencesChanged;
            }
            console.log(`Created presentation for ${customerName} with ID: ${presentationCopyId}`);
            console.log(`Replaced ${numReplacements} text instances`);
            if (responses.length === values.length) { // callback for the last value
              if (callback) callback(responses);
            }
          });
        });
      }
    });
  } catch (err) {
    document.getElementById('content').innerText = err.message;
    return;
  }
}

Node.js

slides/snippets/slides_text_merging.js
/**
 * Adds data from a spreadsheet to a template presentation.
 * @param {string} templatePresentationId The template presentation ID.
 * @param {string} dataSpreadsheetId  The data spreadsheet ID.
 */
async function textMerging(templatePresentationId, dataSpreadsheetId) {
  const {GoogleAuth} = require('google-auth-library');
  const {google} = require('googleapis');

  const auth = new GoogleAuth({
    scopes: [
      'https://www.googleapis.com/auth/presentations',
      'https://www.googleapis.com/auth/drive',
      'https://www.googleapis.com/auth/spreadsheets',
    ],
  });

  const slidesService = google.slides({version: 'v1', auth});
  const sheetsService = google.sheets({version: 'v4', auth});
  const driveService = google.drive({version: 'v2', auth});

  // Use the Sheets API to load data, one record per row.
  const responses = [];
  const dataRangeNotation = 'A2:M6';

  try {
    const sheetsResponse = await sheetsService.spreadsheets.values.get({
      spreadsheetId: dataSpreadsheetId,
      range: dataRangeNotation,
    });
    const values = sheetsResponse.data.values;

    // For each record, create a new merged presentation.
    for (let i = 0; i < values.length; ++i) {
      const row = values[i];
      const customerName = row[2]; // name in column 3
      const caseDescription = row[5]; // case description in column 6
      const totalPortfolio = row[11]; // total portfolio in column 12

      // Duplicate the template presentation using the Drive API.
      const copyTitle = customerName + ' presentation';
      let requests = {
        name: copyTitle,
      };

      const driveResponse = await driveService.files.copy({
        fileId: templatePresentationId,
        requests,
      });

      const presentationCopyId = driveResponse.data.id;
      // Create the text merge (replaceAllText) requests for this presentation.
      requests = [
        {
          replaceAllText: {
            containsText: {
              text: '{{customer-name}}',
              matchCase: true,
            },
            replaceText: customerName,
          },
        },
        {
          replaceAllText: {
            containsText: {
              text: '{{case-description}}',
              matchCase: true,
            },
            replaceText: caseDescription,
          },
        },
        {
          replaceAllText: {
            containsText: {
              text: '{{total-portfolio}}',
              matchCase: true,
            },
            replaceText: totalPortfolio,
          },
        },
      ];
      // Execute the requests for this presentation.
      const batchUpdateResponse = await slidesService.presentations.batchUpdate(
          {
            presentationId: presentationCopyId,
            resource: {
              requests,
            },
          },
      );
      const result = batchUpdateResponse.data;
      // Count the total number of replacements made.
      let numReplacements = 0;
      for (let i = 0; i < result.replies.length; ++i) {
        numReplacements += result.replies[i].replaceAllText.occurrencesChanged;
      }
      console.log(
          `Created presentation for ${customerName} with ID: ` +
          presentationCopyId,
      );
      console.log(`Replaced ${numReplacements} text instances`);
      return result;
    }
  } catch (err) {
    // TODO (developer) - Handle exception
    throw err;
  }
}

PHP

slides/snippets/src/SlidesTextMerging.php
use Google\Client;
use Google\Service\Drive;
use Google\Service\Slides;
use Google\Service\Slides\Request;

function textMerging($templatePresentationId, $dataSpreadsheetId)
{

    /* Load pre-authorized user credentials from the environment.
       TODO(developer) - See https://developers.google.com/identity for
        guides on implementing OAuth2 for your application. */
    $client = new Google\Client();
    $client->useApplicationDefaultCredentials();
    $client->addScope(Google\Service\Drive::DRIVE);
    $slidesService = new Google_Service_Slides($client);
    $driveService = new Google_Service_Drive($client);
    $sheetsService = new Google_Service_Sheets($client);
    try {
        $responses = array();
        // 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);
            $responses[] = $response;
            // Count the total number of replacements made.
            $numReplacements = 0;
            foreach ($response->getReplies() as $reply) {
                $numReplacements += $reply->getReplaceAllText()->getOccurrencesChanged();
            }
            printf("Created presentation for %s with ID: %s\n", $customerName, $presentationCopyId);
            printf("Replaced %d text instances.\n", $numReplacements);
        }
        return $responses;
    } catch (Exception $e) {
        echo 'Message: ' . $e->getMessage();
    }
}

Python

slides/snippets/slides_text_merging.py
import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def text_merging(template_presentation_id, data_spreadsheet_id):
  """
  Run Text merging the user has access to.
  Load pre-authorized user credentials from the environment.
  TODO(developer) - See https://developers.google.com/identity
  for guides on implementing OAuth2 for the application.
  """
  creds, _ = google.auth.default()
  # pylint: disable=maybe-no-member

  try:
    service = build("slides", "v1", credentials=creds)
    sheets_service = build("sheets", "v4", credentials=creds)
    drive_service = build("drive", "v3", credentials=creds)
    # 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 = (
          service.presentations()
          .batchUpdate(presentationId=presentation_copy_id, body=body)
          .execute()
      )

      # Count the total number of replacements made.
      num_replacements = 0
      for reply in response.get("replies"):
        if reply.get("occurrencesChanged") is not None:
          num_replacements += reply.get("replaceAllText").get(
              "occurrencesChanged"
          )
      print(
          "Created presentation for "
          f"{customer_name} with ID: {presentation_copy_id}"
      )
      print(f"Replaced {num_replacements} text instances")

  except HttpError as error:
    print(f"An error occurred: {error}")
    return error


if __name__ == "__main__":
  # Put the template_presentation_id, data_spreadsheet_id
  # of slides

  text_merging(
      "10QnVUx1X2qHsL17WUidGpPh_SQhXYx40CgIxaKk8jU4",
      "17eqFZl_WK4WVixX8PjvjfLD77DraoFwMDXeiHB3dvuM",
  )

小茹

slides/snippets/lib/file_snippets.rb
# Use the Sheets API to load data, one record per row.
data_range_notation = 'Customers!A2:M6'
sheets_response = sheets_service.get_spreadsheet_values(
  data_spreadsheet_id,
  data_range_notation
)
values = sheets_response.values

# For each record, create a new merged presentation.
values.each do |row|
  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 = Google::Apis::SlidesV1::Presentation.new
  body.title = copy_title
  drive_response = drive_service.copy_file(template_presentation_id, body)
  presentation_copy_id = drive_response.id

  # Create the text merge (replace_all_text) requests for this presentation.
  requests = [] << {
    replace_all_text: {
      contains_text: {
        text:       '{{customer-name}}',
        match_case: true
      },
      replace_text:  customer_name
    }
  } << {
    replace_all_text: {
      contains_text: {
        text:       '{{case-description}}',
        match_case: true
      },
      replace_text:  case_description
    }
  } << {
    replace_all_text: {
      contains_text: {
        text:       '{{total-portfolio}}',
        match_case: true
      },
      replace_text:  total_portfolio
    }
  }

  # Execute the requests for this presentation.
  req = Google::Apis::SlidesV1::BatchUpdatePresentationRequest.new(requests: requests)
  response = slides_service.batch_update_presentation(
    presentation_copy_id,
    req
  )

合併圖片

您也可以使用 replaceAllShapesWithImage敬上 請求。這項要求會取代所有包含 帶有提供圖片的文字字串。自動要求 放置並縮放圖片以符合標記形狀的邊界, 保留圖片的長寬比。

範例

這個範例使用 Google Drive API 複製一份範本簡報, 接著請建立新的簡報執行個體接著再使用 Slides API 搜尋 任何含有文字「{{company-logo}}」的形狀 並替換為公司標誌圖片請求也會取代任何 含有文字「{{customer-graphic}}」的形狀 並使用不同的圖片

Apps Script

slides/api/Snippets.gs
/**
 * Duplicate the template presentation using the Drive API.
 * @param {string} templatePresentationId
 * @param {string} imageUrl
 * @param {string} customerName
 * @returns {*}
 */
function imageMerging(templatePresentationId, imageUrl, customerName) {
  const logoUrl = imageUrl;
  const customerGraphicUrl = imageUrl;

  const copyTitle = customerName + ' presentation';
  let copyFile = {
    title: copyTitle,
    parents: [{id: 'root'}]
  };

  try {
    copyFile = Drive.Files.copy(copyFile, templatePresentationId);
    const presentationCopyId = copyFile.id;

    // Create the image merge (replaceAllShapesWithImage) requests.
    const requests = [{
      replaceAllShapesWithImage: {
        imageUrl: logoUrl,
        imageReplaceMethod: 'CENTER_INSIDE',
        containsText: {
          text: '{{company-logo}}',
          matchCase: true
        }
      }
    }, {
      replaceAllShapesWithImage: {
        imageUrl: customerGraphicUrl,
        imageReplaceMethod: 'CENTER_INSIDE',
        containsText: {
          text: '{{customer-graphic}}',
          matchCase: true
        }
      }
    }];

    // Execute the requests for this presentation.
    let batchUpdateResponse = Slides.Presentations.batchUpdate({
      requests: requests
    }, presentationCopyId);
    let numReplacements = 0;
    batchUpdateResponse.replies.forEach(function(reply) {
      numReplacements += reply.replaceAllShapesWithImage.occurrencesChanged;
    });
    console.log('Created merged presentation with ID: %s', presentationCopyId);
    console.log('Replaced %s shapes with images.', numReplacements);

    return batchUpdateResponse;
  } catch (err) {
    // TODO (Developer) - Handle exception
    console.log('Failed with error: %s', err.error);
  }
};

Go

slides/snippets/presentations.go
// Duplicate the template presentation using the Drive API.
copyTitle := customerName + " presentation"
file := drive.File{
	Title: copyTitle,
}
presentationFile, _ := driveService.Files.Copy(templatePresentationId, &file).Do()
presentationId := presentationFile.Id

// Create the image merge (replaceAllShapesWithImage) requests.
requests := []*slides.Request{{
	ReplaceAllShapesWithImage: &slides.ReplaceAllShapesWithImageRequest{
		ImageUrl:      logoURL,
		ReplaceMethod: "CENTER_INSIDE",
		ContainsText: &slides.SubstringMatchCriteria{
			Text:      "{{company-logo}}",
			MatchCase: true,
		},
	},
}, {
	ReplaceAllShapesWithImage: &slides.ReplaceAllShapesWithImageRequest{
		ImageUrl:      customerGraphicURL,
		ReplaceMethod: "CENTER_INSIDE",
		ContainsText: &slides.SubstringMatchCriteria{
			Text:      "{{customer-graphic}}",
			MatchCase: true,
		},
	},
}}

// Execute the requests for this presentation.
body := &slides.BatchUpdatePresentationRequest{Requests: requests}
response, _ := slidesService.Presentations.BatchUpdate(presentationId, body).Do()

// Count total number of replacements made.
var numReplacements int64 = 0
for _, resp := range response.Replies {
	numReplacements += resp.ReplaceAllShapesWithImage.OccurrencesChanged
}
fmt.Printf("Created merged presentation with ID %s\n", presentationId)
fmt.Printf("Replaced %d shapes instances with images.\n", numReplacements)

Java

slides/snippets/src/main/java/ImageMerging.java
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.model.File;
import com.google.api.services.slides.v1.Slides;
import com.google.api.services.slides.v1.SlidesScopes;
import com.google.api.services.slides.v1.model.BatchUpdatePresentationRequest;
import com.google.api.services.slides.v1.model.BatchUpdatePresentationResponse;
import com.google.api.services.slides.v1.model.Request;
import com.google.api.services.slides.v1.model.Response;
import com.google.api.services.slides.v1.model.ReplaceAllShapesWithImageRequest;
import com.google.api.services.slides.v1.model.SubstringMatchCriteria;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/* Class to demonstrate the use of Slides Image Merging API */
public class ImageMerging {
  /**
   * Changes specified texts into images.
   *
   * @param templatePresentationId - id of the presentation.
   * @param imageUrl               - Url of the image.
   * @param customerName           - Name of the customer.
   * @return merged presentation id
   * @throws IOException - if credentials file not found.
   */
  public static BatchUpdatePresentationResponse imageMerging(String templatePresentationId,
                                                             String imageUrl,
                                                             String customerName)
      throws IOException {
        /* Load pre-authorized user credentials from the environment.
           TODO(developer) - See https://developers.google.com/identity for
            guides on implementing OAuth2 for your application. */
    GoogleCredentials credentials = GoogleCredentials.getApplicationDefault()
        .createScoped(Arrays.asList(SlidesScopes.PRESENTATIONS,
            SlidesScopes.DRIVE));
    HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(
        credentials);

    // Create the slides API client
    Slides service = new Slides.Builder(new NetHttpTransport(),
        GsonFactory.getDefaultInstance(),
        requestInitializer)
        .setApplicationName("Slides samples")
        .build();

    // Create the drive API client
    Drive driveService = new Drive.Builder(new NetHttpTransport(),
        GsonFactory.getDefaultInstance(),
        requestInitializer)
        .setApplicationName("Slides samples")
        .build();

    // 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(imageUrl)
            .setImageReplaceMethod("CENTER_INSIDE")
            .setContainsText(new SubstringMatchCriteria()
                .setText("{{company-logo}}")
                .setMatchCase(true))));

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

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

      // Prints the merged presentation id and count of replacements.
      System.out.println("Created merged presentation with ID: " + presentationId);
      System.out.println("Replaced " + numReplacements + " shapes instances with images.");
    } catch (NullPointerException ne) {
      System.out.println("Text not found to replace with image.");
    }
    return response;
  }
}

JavaScript

slides/snippets/slides_image_merging.js
function imageMerging(
    templatePresentationId,
    imageUrl,
    customerName,
    callback,
) {
  const logoUrl = imageUrl;
  const customerGraphicUrl = imageUrl;

  // Duplicate the template presentation using the Drive API.
  const copyTitle = customerName + ' presentation';
  try {
    gapi.client.drive.files
        .copy({
          fileId: templatePresentationId,
          resource: {
            name: copyTitle,
          },
        })
        .then((driveResponse) => {
          const presentationCopyId = driveResponse.result.id;

          // Create the image merge (replaceAllShapesWithImage) requests.
          const requests = [
            {
              replaceAllShapesWithImage: {
                imageUrl: logoUrl,
                replaceMethod: 'CENTER_INSIDE',
                containsText: {
                  text: '{{company-logo}}',
                  matchCase: true,
                },
              },
            },
            {
              replaceAllShapesWithImage: {
                imageUrl: customerGraphicUrl,
                replaceMethod: 'CENTER_INSIDE',
                containsText: {
                  text: '{{customer-graphic}}',
                  matchCase: true,
                },
              },
            },
          ];
          // Execute the requests for this presentation.
          gapi.client.slides.presentations
              .batchUpdate({
                presentationId: presentationCopyId,
                requests: requests,
              })
              .then((batchUpdateResponse) => {
                let numReplacements = 0;
                for (
                  let i = 0;
                  i < batchUpdateResponse.result.replies.length;
                  ++i
                ) {
                  numReplacements +=
                batchUpdateResponse.result.replies[i].replaceAllShapesWithImage
                    .occurrencesChanged;
                }
                console.log(
                    `Created merged presentation with ID: ${presentationCopyId}`,
                );
                console.log(`Replaced ${numReplacements} shapes with images.`);
                if (callback) callback(batchUpdateResponse.result);
              });
        });
  } catch (err) {
    document.getElementById('content').innerText = err.message;
    return;
  }
}

Node.js

slides/snippets/slides_image_merging.js
/**
 * Add an image to a template presentation.
 * @param {string} templatePresentationId The template presentation ID.
 * @param {string} imageUrl The image URL
 * @param {string} customerName A customer name used for the title
 */
async function imageMerging(templatePresentationId, imageUrl, customerName) {
  const {GoogleAuth} = require('google-auth-library');
  const {google} = require('googleapis');

  const auth = new GoogleAuth({
    scopes: [
      'https://www.googleapis.com/auth/presentations',
      'https://www.googleapis.com/auth/drive',
    ],
  });

  const slidesService = google.slides({version: 'v1', auth});
  const driveService = google.drive({version: 'v2', auth});
  const logoUrl = imageUrl;
  const customerGraphicUrl = imageUrl;

  // Duplicate the template presentation using the Drive API.
  const copyTitle = customerName + ' presentation';
  try {
    const driveResponse = await driveService.files.copy({
      fileId: templatePresentationId,
      resource: {
        name: copyTitle,
      },
    });
    const presentationCopyId = driveResponse.data.id;

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

    // Execute the requests for this presentation.
    const batchUpdateResponse = await slidesService.presentations.batchUpdate({
      presentationId: presentationCopyId,
      resource: {
        requests,
      },
    });
    let numReplacements = 0;
    for (let i = 0; i < batchUpdateResponse.data.replies.length; ++i) {
      numReplacements +=
        batchUpdateResponse.data.replies[i].replaceAllShapesWithImage
            .occurrencesChanged;
    }
    console.log(`Created merged presentation with ID: ${presentationCopyId}`);
    console.log(`Replaced ${numReplacements} shapes with images.`);
    return batchUpdateResponse.data;
  } catch (err) {
    // TODO (developer) - Handle exception
    throw err;
  }
}

PHP

slides/snippets/src/SlidesImageMerging.php
use Google\Client;
use Google\Service\Drive;
use Google\Service\Slides;
use Google\Service\DriveFile;
use Google\Service\Slides\Request;


function imageMerging($templatePresentationId, $imageUrl, $customerName)
{
    /* Load pre-authorized user credentials from the environment.
       TODO(developer) - See https://developers.google.com/identity for
        guides on implementing OAuth2 for your application. */
    $client = new Google\Client();
    $client->useApplicationDefaultCredentials();
    $client->addScope(Google\Service\Drive::DRIVE);
    $slidesService = new Google_Service_Slides($client);
    $driveService = new Google_Service_Drive($client);
    // Duplicate the template presentation using the Drive API.
    $copy = new Google_Service_Drive_DriveFile([
        'name' => $customerName . ' presentation'
    ]);

    $driveResponse = $driveService->files->copy($templatePresentationId, $copy);
    $presentationCopyId = $driveResponse->id;

    // Create the image merge (replaceAllShapesWithImage) requests.

    $requests[] = new Google_Service_Slides_Request([
        'replaceAllShapesWithImage' => [
            'imageUrl' => $imageUrl,
            'replaceMethod' => 'CENTER_INSIDE',
            'containsText' => [
                'text' => '{{company-logo}}',
                'matchCase' => true
            ]
        ]
    ]);
    $requests[] = new Google_Service_Slides_Request([
        'replaceAllShapesWithImage' => [
            'imageUrl' => $imageUrl,
            'replaceMethod' => 'CENTER_INSIDE',
            'containsText' => [
                'text' => '{{customer-graphic}}',
                'matchCase' => true
            ]
        ]
    ]);

    // Execute the requests.
    $batchUpdateRequest = new Google_Service_Slides_BatchUpdatePresentationRequest([
        '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);
    return $response;
}

Python

slides/snippets/slides_image_merging.py
import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def image_merging(template_presentation_id, image_url, customer_name):
  """image_merging require template_presentation_id,
  image_url and customer_name
  Load pre-authorized user credentials from the environment.
  TODO(developer) - See https://developers.google.com/identity
  for guides on implementing OAuth2 for the application.
  """
  creds, _ = google.auth.default()
  # pylint: disable=maybe-no-member
  try:
    slides_service = build("slides", "v1", credentials=creds)
    drive_service = build("drive", "v3", credentials=creds)
    logo_url = image_url

    customer_graphic_url = image_url

    # 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"):
      # add below line

      if reply.get("occurrencesChanged") is not None:
        # end tag
        num_replacements += reply.get("replaceAllShapesWithImage").get(
            "occurrencesChanged"
        )

    print(f"Created merged presentation with ID:{presentation_copy_id}")
    print(f"Replaced {num_replacements} shapes with images")
  except HttpError as error:
    print(f"An error occurred: {error}")
    print("Images is not merged")
    return error

  return response


if __name__ == "__main__":
  # Put the template_presentation_id, image_url and customer_name

  image_merging(
      "10QnVUx1X2qHsL17WUidGpPh_SQhXYx40CgIxaKk8jU4",
      "https://www.google.com/images/branding/"
      "googlelogo/2x/googlelogo_color_272x92dp.png",
      "Fake Customer",
  )

小茹

slides/snippets/lib/file_snippets.rb
# Duplicate the template presentation using the Drive API.
copy_title = customer_name + ' presentation'
body = Google::Apis::SlidesV1::Presentation.new
body.title = copy_title
drive_response = drive_service.copy_file(template_presentation_id, body)
presentation_copy_id = drive_response.id

# Create the image merge (replace_all_shapes_with_image) requests.
requests = [] << {
  replace_all_shapes_with_image: {
    image_url:      logo_url,
    replace_method: 'CENTER_INSIDE',
    contains_text:  {
      text:       '{{company-logo}}',
      match_case: true
    }
  }
} << {
  replace_all_shapes_with_image: {
    image_url:      customer_graphic_url,
    replace_method: 'CENTER_INSIDE',
    contains_text:  {
      text:       '{{customer-graphic}}',
      match_case: true
    }
  }
}

# Execute the requests.
req = Google::Apis::SlidesV1::BatchUpdatePresentationRequest.new(requests: requests)
response = slides_service.batch_update_presentation(
  presentation_copy_id,
  req
)

# Count the number of replacements made.
num_replacements = 0
response.replies.each do |reply|
  num_replacements += reply.replace_all_shapes_with_image.occurrences_changed
end
puts "Created presentation for #{customer_name} with ID: #{presentation_copy_id}"
puts "Replaced #{num_replacements} shapes with images"

取代特定文字方塊或映像檔執行個體

replaceAllTextreplaceAllShapesWithImage 「要求」十分實用,可取代簡報中的標記 有時候,您只需要根據其他條件替換元素, 會排在特定投影片中

在這些情況下,您必須擷取標記形狀的 ID 做為替代物件如果是取代文字,您可以刪除 然後再插入這些圖案中的文字 (請參閱範例) 編輯特定形狀中的文字)。

替換圖片則比較複雜。如要合併圖片,您需要:

  1. 取得代碼形狀的 ID。
  2. 從標記複製大小和轉換資訊。
  3. 按照大小和轉換資訊將圖片加入頁面。
  4. 刪除標記形狀。

縮放到您想要的大小時,保留圖片的顯示比例,可能會 因此在處理下請更加謹慎。另請參閱此範例: 將形狀標記替換成圖片

保留顯示比例

使用 Slides API 建立圖片時,長寬比只會依照 而非尺寸和轉換資料。您提供的資料大小 createImage 要求視為所需的圖片大小這個 API 符合 圖片長寬比與此所需大小,然後套用提供的轉換值。

以圖片取代標記時,可保留圖片的長寬比 ,方法是設定圖片大小和縮放比例:

  • width:設為標記 widthscaleX 的乘積
  • height:設為代碼 heightscaleY 的乘積
  • scale_x:設為 1
  • scale_y:設為 1

如此一來,Slide API 就會根據 廣告代碼的視覺大小,而非未縮放的大小 (詳情請參閱 將形狀標記替換成圖片)。 將縮放參數設為 1 可防止縮放圖片 兩次。

這種排列方式可確保能保留圖片的顯示比例,並且避免 導致圖片超出標記形狀的大小映像檔有 和標記形狀相同的中心點

管理範本

如果是應用程式定義和擁有的範本簡報,請建立 使用代表應用程式的專屬帳戶建立範本 服務帳戶 會是不錯的選擇,避免使用 Google Workspace 政策 分享。

使用範本建立簡報執行個體時,一律使用 建立使用者憑證這樣一來,使用者就能完全掌控 產生的簡報,並避免發生與每位使用者相關的資源調度問題 Google 雲端硬碟的數量上限。

如要使用服務帳戶建立範本,請執行下列步驟: 應用程式憑證:

  1. 在 Slides API 中使用 presentations.create 建立簡報。
  2. 更新權限,允許簡報收件者使用 permissions.create
  3. 更新權限,允許範本作者使用 寫入 permissions.create
  4. 視需要編輯範本。

如要建立簡報執行個體,請執行下列步驟: 包含使用者憑證:

  1. 使用 files.copy
  2. 在 Slides API 中使用 presentation.batchUpdate 取代值。