数据科学家可以使用许多工具来执行大数据分析,但最终,您是否仍然需要向管理层证明这些结果的合理性?纸上或数据库中的大量数字很难向主要利益相关者展示。这个中级 Google Apps 脚本 Codelab 利用 G Suite 和 Google Cloud Platform (GCP) 这两个 Google 开发者平台,帮助您完成最后一步。
借助 Google Cloud 的开发者工具,您可以执行深入的数据分析,然后将这些结果放入电子表格中,并使用这些数据生成幻灯片演示文稿,从而为向管理层展示结果提供更合适的平台。此 Codelab 介绍了 GCP 的 BigQuery API(作为 Apps 脚本高级服务)以及 Google 表格和 Google 幻灯片的内置 Apps 脚本服务。
动机/在先技术
此 Codelab 中的示例应用灵感来源于以下其他代码示例...
- Google Apps 脚本 BigQuery 服务示例应用和 GitHub 上的开源应用
- 根据电子表格数据生成幻灯片开发者视频中展示的示例应用,已发布在这篇博文中
- Google Slides API Codelab 中介绍的示例应用
虽然 Slides API Codelab 示例应用也包含 BigQuery 和 Slides,但它与此 Codelab 的示例应用在以下几个方面有所不同:
- Node.js 应用与 Apps 脚本应用
- 使用 REST API,而我们使用 Apps 脚本服务
- 使用 Google 云端硬盘但不使用 Google 表格,而此应用使用 Google 表格但不使用 Google 云端硬盘
在此 Codelab 中,我们希望将尽可能多的技术整合到一个应用中,同时以更贴近实际应用场景的方式展示 Google Cloud 中的功能和 API。目的是激发您的想象力,并考虑利用 GCP 和 G Suite 来解决组织或客户面临的难题。
学习内容
- 如何将 Google Apps 脚本与多项 Google (GCP & G Suite) 服务搭配使用
- 如何使用 Google BigQuery 执行大数据分析
- 如何创建 Google 表格并向其中填充数据
- 如何在 Google 表格中创建新图表
- 如何将图表和数据从 Google 表格转移到 Google 幻灯片演示文稿中
所需条件
- 可连接到互联网的设备和网络浏览器
- Google 账号(G Suite 账号可能需要获得管理员批准)
- 具备基本的 JavaScript 技能
- 了解 Apps 脚本开发可能有助于您完成相关学习,但并非必须
您将如何使用本 Codelab/教程?
您如何评价自己在 G Suite 开发者工具和 API 方面的经验水平?
您如何评价自己使用 Apps 脚本的体验?
您如何评价自己在 GCP 开发者工具和 API 方面的经验水平?
现在,您已经了解了本 Codelab 的内容,接下来您将具体做些什么?
- 获取现有的 Apps 脚本-BigQuery 示例并使其正常运行
- 通过该示例,了解如何向 BigQuery 发送查询并获取查询结果
- 创建 Google 表格并将 BigQuery 中的结果填充到其中
- 稍微修改代码,以略微更改返回并添加到工作表中的数据
- 使用 Apps 脚本中的表格服务为 BigQuery 中的数据创建图表
- 使用幻灯片服务创建新的幻灯片演示文稿
- 为所有新演示文稿自动创建的默认标题幻灯片添加标题和副标题
- 创建包含数据表的新幻灯片,然后将 Google 表格的数据单元格导入其中
- 添加另一张新幻灯片,并将电子表格图表添加到其中
我们先来了解一些关于 Apps 脚本、BigQuery、Google 表格和 Google 幻灯片的基本信息。
Google Apps 脚本和 BigQuery
Google Apps 脚本是一个 G Suite 开发平台,其运作方式比使用 Google REST API 更高级别。它是一个无服务器开发和应用托管环境,适合各种技能水平的开发者。用一句话概括:“Apps 脚本是一种无服务器 JavaScript 运行时环境,可用于实现 G Suite 自动化、扩展和集成。”
它是服务器端 JavaScript,类似于 Node.js,但侧重于与 G Suite 和其他 Google 服务紧密集成,而不是快速的异步事件驱动型应用托管。它还提供了一个可能与您习惯的开发环境完全不同的开发环境。借助 Apps 脚本,您可以:
- 在基于浏览器的代码编辑器中开发,但如果使用
clasp
(Apps 脚本的命令行部署工具),则可以选择在本地开发 - 使用专门的 JavaScript 版本中的代码,该版本经过自定义,可访问 G Suite 以及其他 Google 或外部服务(通过 Apps 脚本
URLfetch
或Jdbc
服务) - 无需编写授权代码,因为 Apps 脚本会为您代劳
- 无需托管应用,应用可在云端 Google 服务器上运行
注意:本 Codelab 的主要目的不是教您学习 Apps 脚本。网上有很多资源可以帮助您完成此操作。官方文档还提供包含快速入门、教程和视频的概览。最后,别忘了“Apps 脚本简介”Codelab,您应该先完成该 Codelab,然后再开始学习本 Codelab。
Apps 脚本通过两种不同的方式与其他 Google 技术进行交互:
- 内置/原生服务
- 高级服务
内置服务提供高级方法,您可以使用这些方法来访问 G Suite 或 Google 产品数据,或者使用其他实用程序方法。高级服务只是 G Suite 或 Google REST API 的一个精简封装容器。高级服务可全面覆盖 REST API,并且通常比内置服务的功能更强大,但需要更复杂的代码(不过仍比 REST API 本身更易于使用)。在使用高级服务之前,还必须为脚本项目启用这些服务。
如果可以,开发者应首选内置服务,因为它们比高级服务更易于使用,并且可以处理更多繁重任务。不过,某些 Google API 没有内置服务,因此高级服务可能是唯一选择。Google BigQuery 就是一个这样的示例…没有内置服务,但BigQuery 高级服务 确实存在。(总比没有服务要好,对吧?)如果您是 BigQuery 新手,那么您需要了解的是,BigQuery 是一项 GCP 服务,可让您对非常庞大的数据语料库(例如,数 TB 级)执行简单(或复杂)的查询,但仍可在几秒钟内提供结果。
通过 Apps 脚本访问 Google 表格和 Google 幻灯片
与 BigQuery 不同,Google 表格和 Google 幻灯片都具有内置服务(以及高级服务,您只会使用高级服务来访问仅在 API 中提供的功能)。在开始编写代码之前,请先参阅内置 Google 表格和 Google 幻灯片服务的文档。当然,高级服务也有文档;以下分别是 Google 表格和 Google 幻灯片的文档。
简介
我们将通过第一个任务来完成此 Codelab 的大部分内容。事实上,完成此步骤后,您将完成整个 Codelab 的一半。本部分分为几个小节,您将完成以下所有操作:
- 启动新的 Google Apps 脚本项目
- 启用对 BigQuery 高级服务的访问权限
- 前往开发编辑器,然后输入应用源代码
- 完成应用授权流程 (OAuth2)
- 运行向 BigQuery 发送请求的应用
- 查看使用 BigQuery 中的结果创建的全新 Google 表格
设置
- a) 前往
script.google.com
,创建一个新的 Apps 脚本项目。G Suite 产品线有多种,您创建新项目的方式可能会因所用版本而异。如果您仅使用 Gmail 账号,并且是项目开发新手,则会看到一个空白屏幕,其中包含一个用于创建第一个项目的按钮:
b) 否则,您可能会在左上角看到所有项目和一个大的 + 新建 按钮,请点击该按钮。
c) 如果上述两种情况都不是,您的屏幕可能如下所示。如果是,请在左上角找到汉堡菜单图标,然后选择 + 新脚本。
d) 对于喜欢使用命令行界面的用户。您的工具是 clasp
,具体来说,您将运行 clasp create
命令。
e) 创建新脚本项目的最后一种方法是直接访问快捷链接:https://script.google.com/create。
- 无论您使用哪种技术来启动新项目,最终都应该进入 Apps 脚本代码编辑器,该界面如下所示:
- 依次点击 File > Save,然后为项目命名。
- 接下来,您需要创建 Google Cloud 控制台项目,才能运行 BigQuery 查询。
- 创建新项目,为其命名,选择结算账号,然后点击创建。
- 项目创建完成后,页面右上角会显示一则通知。点击“创建项目:<项目名称>”条目,打开项目。
- 点击左上角的菜单图标
,然后依次前往 API 和服务 > 凭据。点击 OAuth 同意屏幕标签页(直接链接)。
- 在应用名称字段中,输入“Big Data Codelab”,然后点击底部的保存按钮。
- 点击右上角的三点状图标
以展开菜单,然后选择项目设置 (直接链接)。
- 复制项目编号下列出的值。(还有一个单独的字段 Product ID,我们将在 Codelab 的后续部分中使用。)
- 返回到 App 脚本编辑器,然后依次点击资源 > Cloud Platform 项目。
- 在文本框中输入项目编号,然后点击设置项目。出现提示时,点击确认。
- 完成后,点击关闭按钮以关闭对话框。
- 现在,您已设置好新项目,接下来需要启用 BigQuery 高级服务,因此请下拉资源 -> 高级 Google 服务,然后将 BigQuery API 的位翻转为开启。
- 底部的注释指出,“这些服务还必须在‘Google Cloud Platform API 信息中心’内启用”,因此请点击该链接,这会打开另一个浏览器标签页,其中显示开发者控制台(简称“devconsole”)。
- 在开发者控制台中,点击顶部的 +启用 API 和服务按钮,搜索“bigquery”,选择 BigQuery API(而非 BigQuery Data Transfer API),然后点击启用以将其开启。保持此浏览器标签页处于打开状态。
注意:启用 API 后,您可能会在此页面上看到类似“如需使用此 API,您需要创建凭据…”的注释,但暂时不必担心,Apps 脚本会为您处理此步骤。 - 返回代码编辑器浏览器标签页,您仍处于“高级 Google 服务”菜单中,因此点击确定关闭对话框,然后您会回到代码编辑器中。点击顶部的项目名称,然后将其命名为任意名称,例如“BigQuery 演示”或类似名称 - 我们将其命名为“final mile”。
现在,您已准备好输入应用代码、完成授权流程,并让此应用的第一个版本正常运行。
上传应用并运行
- 复制下方框中的代码,并将其粘贴到代码编辑器中,以替换其中的所有内容:
// Filename for data results
var QUERY_NAME = "Most common words in all of Shakespeare's works";
// Replace this value with your Google Cloud API project ID
var PROJECT_ID = '';
if (!PROJECT_ID) throw Error('Project ID is required in setup');
/**
* Runs a BigQuery query; puts results into Sheet. You must enable
* the BigQuery advanced service before you can run this code.
* @see http://developers.google.com/apps-script/advanced/bigquery#run_query
* @see http://github.com/googleworkspace/apps-script-samples/blob/main/advanced/bigquery.gs
*
* @returns {Spreadsheet} Returns a spreadsheet with BigQuery results
* @see http://developers.google.com/apps-script/reference/spreadsheet/spreadsheet
*/
function runQuery() {
// Replace sample with your own BigQuery query.
var request = {
query:
'SELECT ' +
'LOWER(word) AS word, ' +
'SUM(word_count) AS count ' +
'FROM [bigquery-public-data:samples.shakespeare] ' +
'GROUP BY word ' +
'ORDER BY count ' +
'DESC LIMIT 10'
};
var queryResults = BigQuery.Jobs.query(request, PROJECT_ID);
var jobId = queryResults.jobReference.jobId;
// Wait for BQ job completion (with exponential backoff).
var sleepTimeMs = 500;
while (!queryResults.jobComplete) {
Utilities.sleep(sleepTimeMs);
sleepTimeMs *= 2;
queryResults = BigQuery.Jobs.getQueryResults(PROJECT_ID, jobId);
}
// Get all results from BigQuery.
var rows = queryResults.rows;
while (queryResults.pageToken) {
queryResults = BigQuery.Jobs.getQueryResults(PROJECT_ID, jobId, {
pageToken: queryResults.pageToken
});
rows = rows.concat(queryResults.rows);
}
// Return null if no data returned.
if (!rows) {
return Logger.log('No rows returned.');
}
// Create the new results spreadsheet.
var spreadsheet = SpreadsheetApp.create(QUERY_NAME);
var sheet = spreadsheet.getActiveSheet();
// Add headers to Sheet.
var headers = queryResults.schema.fields.map(function(field) {
return field.name.toUpperCase();
});
sheet.appendRow(headers);
// Append the results.
var data = new Array(rows.length);
for (var i = 0; i < rows.length; i++) {
var cols = rows[i].f;
data[i] = new Array(cols.length);
for (var j = 0; j < cols.length; j++) {
data[i][j] = cols[j].v;
}
}
// Start storing data in row 2, col 1
var START_ROW = 2; // skip header row
var START_COL = 1;
sheet.getRange(START_ROW, START_COL, rows.length, headers.length).setValues(data);
Logger.log('Results spreadsheet created: %s', spreadsheet.getUrl());
}
现在,保存您刚刚创建的文件,但将其从 Code.gs
重命名为 bq-sheets-slides.js
。那么,此代码的作用是什么?我们已经告诉您,它会查询 BigQuery 并将结果写入新的 Google 表格,但此查询是什么?您可以在 runQuery()
的顶部附近看到它:
SELECT
LOWER(word) AS word,
SUM(word_count) AS count
FROM [bigquery-public-data:samples.shakespeare]
GROUP BY word
ORDER BY count
DESC LIMIT 10
此查询会浏览莎士比亚的作品(属于 BigQuery 的公开数据集),并生成其所有作品中出现频率最高的前 10 个字词,按受欢迎程度降序排序。想象一下手动执行此操作会有多(不)有趣,您应该就能大致了解 BigQuery 的实用性了。
- 我们已接近完成准备工作,但尚未完全准备就绪。如您在此代码段顶部附近所见,需要提供有效的项目 ID,因此我们需要将您的项目 ID 添加到应用代码中。如需获取此信息,请返回包含开发者控制台页面的浏览器窗口或标签页。(我们曾建议您保持打开状态,还记得吗?)
- 在 Google 账号头像左上角,有一个下拉菜单选择器 (
)。点击该选择器,然后选择项目设置。您会看到项目名称、ID 和编号。复制项目 ID,并将
bq-sheets-slides.js
顶部的PROJECT_ID
变量设置为从开发者控制台获取的值。注意:如果菜单选择器卡住且无法操作,请重新加载页面。 if
语句用于防止应用在没有项目 ID 的情况下继续运行。添加完您的权限后,保存文件,然后前往菜单栏并依次选择 Run > Run function > runQuery 来运行代码,点击查看权限对话框“此应用未经验证”,以下是动画 GIF(适用于其他应用),展示了接下来的几个步骤:- 请求查看权限后,系统会显示一个新对话框,如上图所示。选择将运行脚本的正确 Google 账号,选择高级,向下滚动,然后点击“前往 <YOUR PROJECT NAME>(不安全)”,进入 OAuth2 应用授权界面。(如需详细了解验证流程,请参阅相关文档,了解为何此界面会显示在您与下方的 OAuth2 授权对话框之间。)
注意:授权应用后,您无需在每次执行时重复此流程。在本教程中,您需要完成任务 3 才能再次看到此对话框界面,该界面会要求用户授予创建和管理 Google 幻灯片演示的权限。 - 在 OAuth2 对话框窗口中点击允许后,脚本开始运行…您会在顶部看到一个淡黄色对话框。它运行得相当快,因此您可能不会注意到它正在运行或已完成执行。
- 该对话框会在完成后消失,因此如果您没有看到它,则可能表示脚本已完成运行。接下来,前往 Google 云端硬盘 (
drive.google.com
),查找名为“Most common words in all of Shakespeare's works”(莎士比亚所有作品中最常用的字词)的新 Google 表格,或者查找您为QUERY_NAME
变量分配的任何名称: - 打开电子表格,您应该会看到 10 行字词及其总数(按降序排序):
任务 1 摘要
了解刚刚发生了什么...您运行了一些代码,这些代码查询了莎士比亚的所有作品(数据量不算巨大,但肯定比您自己轻松浏览的文本量要多得多,您需要查看每部戏剧中的每个字词,统计这些字词的出现次数,然后按出现次数降序对它们进行排序。您不仅要求 BigQuery 代表您执行此操作,还能够使用 Google 表格中的 Apps 脚本内置服务将这些数据放入其中,以便轻松使用。
您在上面粘贴的 bq-sheets-slides.js
(我们选择的文件名)的代码(除了 PROJECT_ID
,它应具有实际的项目 ID)也可以在 github.com/googlecodelabs/bigquery-sheets-slides 上此 Codelab 的 GitHub 代码库中的step1
文件夹中找到。此代码的灵感来自 BigQuery 高级服务页面中的原始示例,该示例运行的查询略有不同,目的是找出莎士比亚使用的最热门的字词(长度为 10 个或更多字符)。您还可以在其 GitHub 代码库中查看该示例。
如果您对可以针对莎士比亚作品或其他公开数据表尝试的其他查询感兴趣,请查看此网页以及此网页。无论使用什么查询,您始终可以在 BigQuery 控制台中测试查询,然后再在 Apps 脚本中运行该查询。开发者可以通过 bigquery.cloud.google.com 访问 BigQuery 的界面。例如,以下是使用 BigQuery 界面运行查询的示例:
虽然上述步骤利用了 Apps 脚本的代码编辑器,但您也可以选择通过命令行在本地进行开发。如果您愿意,可以创建一个名为 bq-sheets-slides.js
的脚本,将上述代码粘贴到其中,然后使用 clasp push
命令上传到 Google。(如果您之前错过了,这里再次提供 clasp
的链接以及使用方法。)
runQuery()
的目的是与 BigQuery 对话,并将结果发送到 Google 表格中。现在,我们需要使用这些数据制作图表。我们来创建一个名为 createColumnChart()
的新函数,该函数会调用工作表的 newChart()
方法来执行此操作。
- 创建图表。将下方
createColumnChart()
的正文添加到runQuery()
之后的bq-sheets-slides.js
中。它会获取包含数据的工作表,并请求包含所有数据的柱状图。数据范围从单元格 A2 开始,因为第一行包含列标题,而不是数据。
/**
* Uses spreadsheet data to create columnar chart.
* @param {Spreadsheet} Spreadsheet containing results data
* @returns {EmbeddedChart} visualizing the results
* @see http://developers.google.com/apps-script/reference/spreadsheet/embedded-chart
*/
function createColumnChart(spreadsheet) {
// Retrieve the populated (first and only) Sheet.
var sheet = spreadsheet.getSheets()[0];
// Data range in Sheet is from cell A2 to B11
var START_CELL = 'A2'; // skip header row
var END_CELL = 'B11';
// Place chart on Sheet starting on cell E5.
var START_ROW = 5; // row 5
var START_COL = 5; // col E
var OFFSET = 0;
// Create & place chart on the Sheet using above params.
var chart = sheet.newChart()
.setChartType(Charts.ChartType.COLUMN)
.addRange(sheet.getRange(START_CELL + ':' + END_CELL))
.setPosition(START_ROW, START_COL, OFFSET, OFFSET)
.build();
sheet.insertChart(chart);
}
- 退回电子表格。在上面的示例中,
createColumnChart()
需要电子表格对象,因此我们需要更新runQuery()
以返回spreadsheet
对象,以便我们可以将其传递给createColumnChart()
。在记录 Google 表格成功创建后,在runQuery()
的末尾(紧跟在日志行之后)返回spreadsheet
对象:
Logger.log('Results spreadsheet created: %s', spreadsheet.getUrl());
// NEW: Return the spreadsheet object for later use.
return spreadsheet;
}
- 驾驶
createBigQueryPresentation()
功能。从逻辑上分离 BigQuery 和图表创建功能是个好主意。现在,我们来创建一个createBigQueryPresentation()
函数来驱动应用,同时调用runQuery()
和createColumnChart()
。您添加的代码应如下所示:
/**
* Runs a BigQuery query, adds data and a chart in a Sheet.
*/
function createBigQueryPresentation() {
var spreadsheet = runQuery();
createColumnChart(spreadsheet);
}
- 提高代码的可重用性。您在上面执行了两个重要步骤:返回电子表格对象和创建驱动函数。如果同事想要重复使用
runQuery()
,但不希望系统记录该网址,该怎么办?为了让runQuery()
更易于理解,我们需要移动该日志行。最适合将该文件移到哪里?如果您猜的是createBigQueryPresentation()
,那就猜对了!移动日志行后,它应如下所示:
/**
* Runs a BigQuery query, adds data and a chart in a Sheet.
*/
function createBigQueryPresentation() {
var spreadsheet = runQuery();
Logger.log('Results spreadsheet created: %s', spreadsheet.getUrl()); // MOVED HERE
createColumnChart(spreadsheet);
}
完成上述这些更改(PROJECT_ID
除外)后,您的 bq-sheets-slides.js
现在应如下所示(也可在 GitHub 代码库的 step2
文件夹中找到):
// Filename for data results
var QUERY_NAME = "Most common words in all of Shakespeare's works";
// Replace this value with your Google Cloud API project ID
var PROJECT_ID = '';
if (!PROJECT_ID) throw Error('Project ID is required in setup');
/**
* Runs a BigQuery query; puts results into Sheet. You must enable
* the BigQuery advanced service before you can run this code.
* @see http://developers.google.com/apps-script/advanced/bigquery#run_query
* @see http://github.com/googleworkspace/apps-script-samples/blob/main/advanced/bigquery.gs
*
* @returns {Sheet} Returns a sheet with results
* @see http://developers.google.com/apps-script/reference/spreadsheet/sheet
*/
function runQuery() {
// Replace sample with your own BigQuery query.
var request = {
query:
'SELECT ' +
'LOWER(word) AS word, ' +
'SUM(word_count) AS count ' +
'FROM [bigquery-public-data:samples.shakespeare] ' +
'GROUP BY word ' +
'ORDER BY count ' +
'DESC LIMIT 10'
};
var queryResults = BigQuery.Jobs.query(request, PROJECT_ID);
var jobId = queryResults.jobReference.jobId;
// Wait for BQ job completion (with exponential backoff).
var sleepTimeMs = 500;
while (!queryResults.jobComplete) {
Utilities.sleep(sleepTimeMs);
sleepTimeMs *= 2;
queryResults = BigQuery.Jobs.getQueryResults(PROJECT_ID, jobId);
}
// Get all results from BigQuery.
var rows = queryResults.rows;
while (queryResults.pageToken) {
queryResults = BigQuery.Jobs.getQueryResults(PROJECT_ID, jobId, {
pageToken: queryResults.pageToken
});
rows = rows.concat(queryResults.rows);
}
// Return null if no data returned.
if (!rows) {
return Logger.log('No rows returned.');
}
// Create the new results spreadsheet.
var spreadsheet = SpreadsheetApp.create(QUERY_NAME);
var sheet = spreadsheet.getActiveSheet();
// Add headers to Sheet.
var headers = queryResults.schema.fields.map(function(field) {
return field.name.toUpperCase();
});
sheet.appendRow(headers);
// Append the results.
var data = new Array(rows.length);
for (var i = 0; i < rows.length; i++) {
var cols = rows[i].f;
data[i] = new Array(cols.length);
for (var j = 0; j < cols.length; j++) {
data[i][j] = cols[j].v;
}
}
// Start storing data in row 2, col 1
var START_ROW = 2; // skip header row
var START_COL = 1;
sheet.getRange(START_ROW, START_COL, rows.length, headers.length).setValues(data);
// Return the spreadsheet object for later use.
return spreadsheet;
}
/**
* Uses spreadsheet data to create columnar chart.
* @param {Spreadsheet} Spreadsheet containing results data
* @returns {EmbeddedChart} visualizing the results
* @see http://developers.google.com/apps-script/reference/spreadsheet/embedded-chart
*/
function createColumnChart(spreadsheet) {
// Retrieve the populated (first and only) Sheet.
var sheet = spreadsheet.getSheets()[0];
// Data range in Sheet is from cell A2 to B11
var START_CELL = 'A2'; // skip header row
var END_CELL = 'B11';
// Place chart on Sheet starting on cell E5.
var START_ROW = 5; // row 5
var START_COL = 5; // col E
var OFFSET = 0;
// Create & place chart on the Sheet using above params.
var chart = sheet.newChart()
.setChartType(Charts.ChartType.COLUMN)
.addRange(sheet.getRange(START_CELL + ':' + END_CELL))
.setPosition(START_ROW, START_COL, OFFSET, OFFSET)
.build();
sheet.insertChart(chart);
}
/**
* Runs a BigQuery query, adds data and a chart in a Sheet.
*/
function createBigQueryPresentation() {
var spreadsheet = runQuery();
Logger.log('Results spreadsheet created: %s', spreadsheet.getUrl());
createColumnChart(spreadsheet);
}
保存文件,然后前往代码编辑器顶部,将执行模式切换为 createBigQueryPresentation()
而不是 runQuery()
。运行后,您会获得另一个 Google 表格,但这次,表格中会在数据旁边显示图表:
此 Codelab 的最后一部分涉及创建新的 Google 幻灯片演示,在标题幻灯片上填写标题和副标题,然后添加 2 张新幻灯片,一张用于每个数据单元格,另一张用于图表。
- 创建幻灯片组。幻灯片演示中的所有工作都将在
createSlidePresentation()
中进行,我们将把createSlidePresentation()
添加到bq-sheets-slides.js
中的createColumnChart()
之后。我们先创建一个新的幻灯片组,然后向所有新演示文稿中默认包含的标题幻灯片添加标题和副标题。
/**
* Create presentation with spreadsheet data & chart
* @param {Spreadsheet} Spreadsheet with results data
* @param {EmbeddedChart} Sheets chart to embed on slide
* @returns {Presentation} Slide deck with results
*/
function createSlidePresentation(spreadsheet, chart) {
// Create the new presentation.
var deck = SlidesApp.create(QUERY_NAME);
// Populate the title slide.
var [title, subtitle] = deck.getSlides()[0].getPageElements();
title.asShape().getText().setText(QUERY_NAME);
subtitle.asShape().getText().setText('via GCP and G Suite APIs:\n' +
'Google Apps Script, BigQuery, Sheets, Slides');
- 添加数据表。
createSlidePresentation()
中的下一步是将 Google 表格中的单元格数据导入到新演示文稿中。此代码段,因此请将其添加到函数中:
// Data range to copy is from cell A1 to B11
var START_CELL = 'A1'; // include header row
var END_CELL = 'B11';
// Add the table slide and insert an empty table on it of
// the dimensions of the data range; fails if Sheet empty.
var tableSlide = deck.appendSlide(SlidesApp.PredefinedLayout.BLANK);
var sheetValues = spreadsheet.getSheets()[0].getRange(
START_CELL + ':' + END_CELL).getValues();
var table = tableSlide.insertTable(sheetValues.length, sheetValues[0].length);
// Populate the table with spreadsheet data.
for (var i = 0; i < sheetValues.length; i++) {
for (var j = 0; j < sheetValues[0].length; j++) {
table.getCell(i, j).getText().setText(String(sheetValues[i][j]));
}
}
- 导入图表。
createSlidePresentation()
中的最后一步是再创建一个幻灯片,从电子表格中导入图表,然后返回Presentation
对象。将以下最后一段代码添加到函数中:
// Add a chart slide and insert the chart on it.
var chartSlide = deck.appendSlide(SlidesApp.PredefinedLayout.BLANK);
chartSlide.insertSheetsChart(chart);
// Return the presentation object for later use.
return deck;
}
- 回报图表。现在,我们的最终函数已完成,请再次查看其签名。是的,
createSlidePresentation()
需要同时包含电子表格对象和图表对象。我们已调整runQuery()
以返回Spreadsheet
对象,但现在我们需要对createColumnChart()
进行类似更改,以返回图表 (EmbeddedChart
) 对象。返回应用中的代码,在createColumnChart()
的末尾添加最后一行代码:
// NEW: Return chart object for later use
return chart;
}
- 更新
createBigQueryPresentation()
。由于createColumnChart()
会返回图表,因此我们需要将该图表保存到变量中,然后将电子表格和图表都传递给createSlidePresentation()
。由于我们会记录新创建的电子表格的网址,因此也记录新幻灯片演示的网址。更新createBigQueryPresentation()
,使其如下所示:
/**
* Runs a BigQuery query, adds data and a chart in a Sheet,
* and adds the data and chart to a new slide presentation.
*/
function createBigQueryPresentation() {
var spreadsheet = runQuery();
Logger.log('Results spreadsheet created: %s', spreadsheet.getUrl());
var chart = createColumnChart(spreadsheet); // UPDATED
var deck = createSlidePresentation(spreadsheet, chart); // NEW
Logger.log('Results slide deck created: %s', deck.getUrl()); // NEW
}
- 保存并再次运行
createBigQueryPresentation()
。不过,在执行之前,请注意您的应用现在需要用户授予另一组权限,才能查看和管理 Google 幻灯片演示。您授予此权限后,该应用将像以前一样运行。 - 现在,除了创建的工作表之外,您还应获得一个包含 3 张幻灯片(标题、数据表、数据图表)的新 Google 幻灯片演示文稿,如下所示:
恭喜!您现在已创建一个应用,该应用通过执行 Google BigQuery 请求来查询其某个公共数据集,创建新的 Google 表格来存储结果,根据刚刚检索到的数据添加图表,最后创建 Google 幻灯片演示文稿,其中包含结果以及电子表格中的图表,从而充分利用 Google Cloud 的两方面功能。
从技术上讲,您就是这样做的。从广义上讲,您通过代码将大数据分析转化为可向利益相关者展示的内容,整个过程都是自动化的。希望此示例能为您带来启发,让您能根据自己的项目进行自定义。在此 Codelab 结束时,我们将提供一些建议,帮助您进一步增强此示例应用。
完成最终任务中的上述更改后(PROJECT_ID
除外),您的 bq-sheets-slides.js
现在应如下所示(也可在 GitHub 代码库的 final
文件夹中找到):
bq-sheets-slides.js
/**
* Copyright 2018 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Filename for data results
var QUERY_NAME = "Most common words in all of Shakespeare's works";
// Replace this value with your Google Cloud API project ID
var PROJECT_ID = '';
if (!PROJECT_ID) throw Error('Project ID is required in setup');
/**
* Runs a BigQuery query; puts results into Sheet. You must enable
* the BigQuery advanced service before you can run this code.
* @see http://developers.google.com/apps-script/advanced/bigquery#run_query
* @see http://github.com/googleworkspace/apps-script-samples/blob/main/advanced/bigquery.gs
*
* @returns {Spreadsheet} Returns a spreadsheet with BigQuery results
* @see http://developers.google.com/apps-script/reference/spreadsheet/spreadsheet
*/
function runQuery() {
// Replace sample with your own BigQuery query.
var request = {
query:
'SELECT ' +
'LOWER(word) AS word, ' +
'SUM(word_count) AS count ' +
'FROM [bigquery-public-data:samples.shakespeare] ' +
'GROUP BY word ' +
'ORDER BY count ' +
'DESC LIMIT 10'
};
var queryResults = BigQuery.Jobs.query(request, PROJECT_ID);
var jobId = queryResults.jobReference.jobId;
// Wait for BQ job completion (with exponential backoff).
var sleepTimeMs = 500;
while (!queryResults.jobComplete) {
Utilities.sleep(sleepTimeMs);
sleepTimeMs *= 2;
queryResults = BigQuery.Jobs.getQueryResults(PROJECT_ID, jobId);
}
// Get all results from BigQuery.
var rows = queryResults.rows;
while (queryResults.pageToken) {
queryResults = BigQuery.Jobs.getQueryResults(PROJECT_ID, jobId, {
pageToken: queryResults.pageToken
});
rows = rows.concat(queryResults.rows);
}
// Return null if no data returned.
if (!rows) {
return Logger.log('No rows returned.');
}
// Create the new results spreadsheet.
var spreadsheet = SpreadsheetApp.create(QUERY_NAME);
var sheet = spreadsheet.getActiveSheet();
// Add headers to Sheet.
var headers = queryResults.schema.fields.map(function(field) {
return field.name.toUpperCase();
});
sheet.appendRow(headers);
// Append the results.
var data = new Array(rows.length);
for (var i = 0; i < rows.length; i++) {
var cols = rows[i].f;
data[i] = new Array(cols.length);
for (var j = 0; j < cols.length; j++) {
data[i][j] = cols[j].v;
}
}
// Start storing data in row 2, col 1
var START_ROW = 2; // skip header row
var START_COL = 1;
sheet.getRange(START_ROW, START_COL, rows.length, headers.length).setValues(data);
// Return the spreadsheet object for later use.
return spreadsheet;
}
/**
* Uses spreadsheet data to create columnar chart.
* @param {Spreadsheet} Spreadsheet containing results data
* @returns {EmbeddedChart} visualizing the results
* @see http://developers.google.com/apps-script/reference/spreadsheet/embedded-chart
*/
function createColumnChart(spreadsheet) {
// Retrieve the populated (first and only) Sheet.
var sheet = spreadsheet.getSheets()[0];
// Data range in Sheet is from cell A2 to B11
var START_CELL = 'A2'; // skip header row
var END_CELL = 'B11';
// Place chart on Sheet starting on cell E5.
var START_ROW = 5; // row 5
var START_COL = 5; // col E
var OFFSET = 0;
// Create & place chart on the Sheet using above params.
var chart = sheet.newChart()
.setChartType(Charts.ChartType.COLUMN)
.addRange(sheet.getRange(START_CELL + ':' + END_CELL))
.setPosition(START_ROW, START_COL, OFFSET, OFFSET)
.build();
sheet.insertChart(chart);
// Return the chart object for later use.
return chart;
}
/**
* Create presentation with spreadsheet data & chart
* @param {Spreadsheet} Spreadsheet with results data
* @param {EmbeddedChart} Sheets chart to embed on slide
* @returns {Presentation} Returns a slide deck with results
* @see http://developers.google.com/apps-script/reference/slides/presentation
*/
function createSlidePresentation(spreadsheet, chart) {
// Create the new presentation.
var deck = SlidesApp.create(QUERY_NAME);
// Populate the title slide.
var [title, subtitle] = deck.getSlides()[0].getPageElements();
title.asShape().getText().setText(QUERY_NAME);
subtitle.asShape().getText().setText('via GCP and G Suite APIs:\n' +
'Google Apps Script, BigQuery, Sheets, Slides');
// Data range to copy is from cell A1 to B11
var START_CELL = 'A1'; // include header row
var END_CELL = 'B11';
// Add the table slide and insert an empty table on it of
// the dimensions of the data range; fails if Sheet empty.
var tableSlide = deck.appendSlide(SlidesApp.PredefinedLayout.BLANK);
var sheetValues = spreadsheet.getSheets()[0].getRange(
START_CELL + ':' + END_CELL).getValues();
var table = tableSlide.insertTable(sheetValues.length, sheetValues[0].length);
// Populate the table with spreadsheet data.
for (var i = 0; i < sheetValues.length; i++) {
for (var j = 0; j < sheetValues[0].length; j++) {
table.getCell(i, j).getText().setText(String(sheetValues[i][j]));
}
}
// Add a chart slide and insert the chart on it.
var chartSlide = deck.appendSlide(SlidesApp.PredefinedLayout.BLANK);
chartSlide.insertSheetsChart(chart);
// Return the presentation object for later use.
return deck;
}
/**
* Runs a BigQuery query, adds data and a chart in a Sheet,
* and adds the data and chart to a new slide presentation.
*/
function createBigQueryPresentation() {
var spreadsheet = runQuery();
Logger.log('Results spreadsheet created: %s', spreadsheet.getUrl());
var chart = createColumnChart(spreadsheet);
var deck = createSlidePresentation(spreadsheet, chart);
Logger.log('Results slide deck created: %s', deck.getUrl());
}
在此 Codelab 中,“第二个文件”(即 Apps 脚本清单文件 appsscript.json
)不发挥任何作用。如需访问该文件,请前往代码编辑器浏览器标签页,然后从顶部菜单中依次选择查看 > 显示清单文件。内容应如下所示:
appsscript.json
{
"timeZone": "America/Los_Angeles",
"dependencies": {
"enabledAdvancedServices": [{
"userSymbol": "BigQuery",
"serviceId": "bigquery",
"version": "v2"
}]
},
"exceptionLogging": "STACKDRIVER"
}
清单文件是一种系统级配置文件,Apps 脚本通过该文件了解要为应用提供哪些执行环境。介绍清单文件的内容不在本 Codelab 的讨论范围内,但您可以大致了解其用途。
下面列出了其他资源,可帮助您深入了解本 Codelab 中涵盖的材料,并探索以编程方式访问 Google 开发者工具的其他方法。我们会努力确保此 Codelab 与相应代码库保持同步。
此应用的资源
- 此 Codelab 的链接:g.co/codelabs/bigquery-sheets-slides
- 源代码 repo
- 开发者视频(和)博文
- Google Cloud NEXT '18 会议
文档
- Google Apps 脚本文档网站
- Apps 脚本电子表格服务
- Apps 脚本幻灯片服务
- Apps 脚本 BigQuery 高级服务
相关视频和一般视频
- 其他 Google (Apps) 密钥?(Apps 脚本简介视频)
- 从电子表格访问 Google 地图?(视频)
- Google Apps 脚本视频库
- Launchpad Online 视频系列(...的前身)
- G Suite Dev Show 视频系列
相关资讯和一般资讯及更新
- 适用于 BigQuery 的 Google 表格数据连接器(公告)
- Google BigQuery 与 Google 云端硬盘集成(link1、link2)
- Google 开发者博客
- Google Cloud Platform 博客
- Google Cloud 大数据与机器学习博客
- Google Developers Twitter 账号 (@GoogleDevs)
- G Suite 开发者博客
- G Suite 开发者 Twitter (@googleworkspace)
- G Suite 开发者月度简报
其他 Codelab
入门级
- [REST API] G Suite 和 Google API (Drive API)
- [应用制作工具] 在应用制作工具中构建数据库 Web 应用
中级
- [Apps 脚本] CLASP Apps 脚本命令行工具
- [Apps 脚本] Gmail 加载项
- [Apps 脚本] Google 文档插件和 GCP Natural Language API
- [Apps 脚本] Hangouts Chat 机器人框架
- [REST API] 自定义报告工具 (Sheets API)
- [REST API] Github 许可 BigQuery 分析器的自定义幻灯片生成器(幻灯片 + BigQuery API)
参考应用
- Markdown 到 Google 幻灯片转换器 (Slides API)
下面列出了各种“代码挑战”,您可以采用不同的方式来增强或扩充我们在本 Codelab 中构建的示例。此列表当然并非详尽无遗,但应该能为您提供一些启发性的想法,让您知道下一步可以采取哪些措施。
- 应用。不想因使用 JavaScript 或 Apps 脚本施加的限制而受到限制?将此应用移植到您喜爱的编程语言,该语言使用 Google BigQuery、Google 表格和 Google 幻灯片的 REST API。
- BigQuery。针对莎士比亚数据集尝试不同的查询...或许能找到您感兴趣的查询。您可以在原始 Apps 脚本 BigQuery 示例应用中找到另一个查询示例。
- BigQuery。不妨试用 BigQuery 的其他一些公共数据集...也许能找到对您来说更有意义的数据集。
- BigQuery。之前,我们提到了您可以针对莎士比亚的作品或其他公共数据表尝试的其他查询,现在想再次分享此网页以及此网页。
- Google 表格。尝试使用其他图表类型。
- Google 表格和 BigQuery。换个角度来看,也许您在某个电子表格中有一个大型数据集。2016 年,BigQuery 团队推出了允许开发者使用 Google 表格作为数据源的功能(如需了解详情,请参阅博文 1 和 2)。
- 幻灯片。向生成的演示文稿添加其他幻灯片,例如与大数据分析相关的图片或其他素材资源。您可以参阅这份 Google 幻灯片内置服务指南,开始使用该服务。
- G Suite。从 Apps 脚本中找到其他 G Suite 或 Google 内置服务的用途,即Gmail、Google 云端硬盘、日历、文档、Google 地图、Google Analytics、YouTube 等,以及其他高级服务。如需了解详情,请参阅内置服务和高级服务的参考概览。