原文:How to Create a Feedback Form using the Google Sheets API,作者:Georgey V B

Google 表单提供了一种创建在线表单和收集用户数据的简单方法。在本教程中,我们将使用 Google Sheets 和 Next.js 来构建一个简单的表单。

我们将使用 Next.js 作为前端,使用 Google Sheets 作为后端,来发送我们通过表单接收到的数据。这样我们就可以学习如何使用 Next.js 和 Google Sheets 来构建一个简单的表单。

这是我们将在本教程中介绍的内容:
1. 如何在 Google Cloud Console 中创建新项目
2. 如何将新项目与 Google Sheet 连接
3. 如何在 Next.js 应用程序中创建前端表单
4. 如何将表单连接到 Google Sheet

为了帮助你理解,我创建了一个 GitHub 仓库,如果你有不清楚的地方,可以参考。

如何在 Google Cloud Console 中创建新项目

要访问 Google Sheets API,我们首先需要在 Google Cloud Console 上创建一个新项目。访问这个站点,转到控制台并创建一个新项目。

cloud-new

创建新项目后,转到 APIs and Services,然后单击 Enable APIs and Services

cloud-enable

从库中搜索 Google Sheets 并启用它。

enable-sheets-api

现在,转到 APIs and Services,点击 Credentials,然后点击 New Credential,创建一个新的 Service 账号。

create-cred

给它一个合适的名字并填写所有细节。生成服务帐户后,将电子邮件 ID 复制到某处。之后我们需要将其添加到我们的 Google 表单中。我们刚刚创建了一个 Bot 帐户来处理将从前端发送的各种请求。

接下来,单击 Credentials 中的 Service account,然后将它们移至 Keys。单击 Add Key,确保将其设置为 JSON 格式。

google_key

创建新密钥时将下载一个文件,它包含我们将前端应用程序连接到 Google 表单时所需的所有环境变量。

如何将新项目连接到 Google Sheet

现在让我们将 Google Cloud Console 上新创建的项目与 Google Sheet 连接起来。访问 Google Sheets 并创建一个新的电子表单。

在我们继续之前,请随意放入一些原始数据,以便我们在下一节中调用请求时可以获取一些内容。

完成后,单击 Share 并添加我们刚刚创建的服务帐户电子邮件。确保你授予它编辑器访问权限 Editor access 并取消 Notify people(选中通知人员)。

share

现在是有趣的部分。让我们转到代码编辑器并为我们的表单创建前端。

如何创建前端表单

为了构建前端,我们将使用 Next.js,并使用 API-routes 功能将 POST 请求发送到我们的 Google Sheet。

使用以下命令安装 Next:

npx create-next-app

为了构建表单,并加快开发过程,我们将使用一些第三方包。所以继续安装以下内容:

npm i @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^4 react-hook-form
  • Chakra-UI:一个可访问的框架,它帮助我加快了大多数应用程序的前端设计。
  • React-Hook-Form:帮助你即时构建具有客户端验证的高效表单。

在本教程中,我将更多地关注执行表单的功能,而不是构建客户端验证。这里是使用 React-Hook-Form 添加客户端验证的完整指南。当然也可以随意访问 Chakra-UI 文档。

安装所有软件包后,使用任何代码编辑器打开它。在 Next.js 中,你在 /pages 文件夹中创建的每个文件都是一个单独的路由。你可以创建一个新文件,但在这里我将使用根文件本身,即 /pages/index.js

清除所有预先生成的代码行。现在,让我们为 Form 创建一个基本结构。

import { VStack, Text, Input } from "@chakra-ui/react"

function Home () {
    function submitHandler () {
     // POST request
    }
    
    return (
        <VStack>
          <Text fontSize="2xl" fontWeight="bold">
            Your response matters!
          </Text>
          
          <form onSubmit={submitHandler}>
              <Input placeholder="Enter Name" />
              <Button>Submit!</Button>
          </form>
        </VStack>
    )
}

VStack 包含下方所有元素。这是 flex-direction: column 的简写。其余的代码应该是不言自明的。

Chakra-UI 的美妙之处在于它的每个组件都非常类似于 HTML 元素,大大减少了学习曲线。

你可以添加更多你选择的输入字段。这是最终结果:

form

现在让我们处理用户提交时的表单响应。为此,我们将使用 react-hook-form

为了从表单中获取响应,我们必须导入 useForm 钩子,如下所示:

import { useForm } from 'react-hook-form';

从钩子中,解构以下内容:

const {
    register,
    handleSubmit
  } = useForm();

handleSubmit 包裹我们之前创建的 submitHandler

<form onSubmit={handleSubmit(submitHandler)}>
   {/* Input fields here */}               
</form>

现在将 register 添加到所有输入字段,如下所示:

<Input placeholder="Enter your message" {...register('name') />

现在,当点击按钮时,我们应该能够看到输入的数据。只需将数据记录到控制台,如下所示:

function submitHandler (data) {
	console.log(data);
}

完成后,让我们现在为要从表单发送的 POST 请求创建一个新的 API 路由。

如何将表单连接到 Google Sheet

./pages/api/ 路由中创建一个新文件。你在此路由中创建的每个文件都是一个 api-route,它提供对所有 Node.js 功能的访问。

继续在路由中创建一个新文件,比如 ./pages/api/sheet.js。构建一个基本的 GET 请求,看看是否一切正常:

function handler (req, res) {
	res.json({message: "It works!"});
}

export default handler;

要检查 API 请求此时是否有效,请转到 http://localhost:3000/api/sheet

完成后,让我们首先使用本机 Fetch 方法设置要从前端发送的 POST 请求。

async function submitHandler (data) {
	const response = await fetch("/api/sheet", {
    		method: "POST",
        	body: JSON.stringify(data),
        	headers: {
        		'Content-Type': 'application/json',
      		},
    	})
}

在做任何其他事情之前,我们必须下载另一个包:

npm install googleapis

在 API-route(/pages/api/sheet)上,解构我们从前端得到的数据。

import {google} from "googleapis"

async function handler (req, res) {
    if (req.method === "POST"){
    		const {name, message} = req.body;
		res.json({message: "It works!"});
    }
}

export default handler;

注意:默认情况下,API 路由将侦听 GET 请求,所以我们必须明确地检查该方法是否是一个 POST 请求。

在继续之前,还有最后一件事要设置,那就是环境变量。在我们创建新密钥时,打开包含所有 credential 的 JSON 文件。

在根目录中创建一个新文件 .env.local,继续,并输入以下变量。

CLIENT_EMAIL=yourclientemail
CLIENT_ID=yourclientid
PRIVATE_KEY=yourprivatekey
SPREADSHEET_ID=yourspreadsheetid

完成后,我们几乎完成了设置 API 路由来处理我们将发送到 Google Sheet 的请求。首先,让我们创建一个身份验证令牌:

const auth = new google.auth.GoogleAuth({
    credentials: {
      client_email: process.env.CLIENT_EMAIL,
      client_id: process.env.CLIENT_ID,
      private_key: process.env.PRIVATE_KEY.replace(/\\n/g, '\n'),
    },
    scopes: [
      'https://www.googleapis.com/auth/drive',
      'https://www.googleapis.com/auth/drive.file',
      'https://www.googleapis.com/auth/spreadsheets',
    ],
  });

要访问 Google Sheet,我们的应用程序首先需要提供一些范围——通常是读写访问权限。

你可以在官方 Google 表单文档中找到有关范围的更多信息。

你可能想知道我在第三个环境变量中使用的 replace 方法。这是由于我之前遇到的一个典型错误。浏览 Stack Overflow 后,我终于找到了解决方案。看起来 PRIVATE_KEY 需要通过删除原始密钥中的斜杠来正确解析。这可以使用替换方法轻松解决。

你可以在我创建的这个拉取请求中找到这个错误。

接下来,传入身份验证令牌并指定 API 的版本。最新的是 v4。

const sheets = google.sheets({
    auth,
    version: 'v4',
  });

然后我们调用 spreadsheets.value.append 方法将用户条目附加到电子表单的单元格中。

const response = await sheets.spreadsheets.values.append({
      spreadsheetId: process.env.DATABASE_ID,
      range: 'Sheet1!A2:C',
      valueInputOption: 'USER_ENTERED',
      requestBody: {
        values: [[name, message]],
      },
    });

你可以从 URL 本身找到电子表单 ID:

https://docs.google.com/spreadsheets/d/{spreadsheetID}/edit#gid=0

范围决定了应用程序必须读取或写入的行和列。如果你对如何查找范围感到困惑,你可以通过用户界面使用 Google 表单本身来确定它。

select_range

第三个属性 valueInputOption 确定如何将用户输入的值解析到电子表单中。

例如,如果用户输入了一个数字,那么电子表单也会将其作为数字读取。

第四个属性携带要附加到特定单元格中的数据。要附加多个值,你可以将它们全部放在一个数组中,例如在这个示例下——名称和消息。

要结束 API 路由,最后将响应发送回前端:

res.status(201).json({response, result: "Feedback posted to spreadsheet!"})

如果一切顺利,你应该能够发出 POST 请求,并成功地将新的单元格值添加到电子表单中。

总结

恭喜!你已准备好开始收集反馈。你可以在你的网站上创建自己的反馈表,或者你可以与现有服务(如 Typeform)集成。

但是如果你希望将反馈表保留在你的网站上,在你的页面上,这就是与 Google Sheets API 集成的用武之地。

Google Sheets API 非常基础——它可以读取和写入电子表格。此外,它是完全免费的,尽管你在特定时间范围内可以发出的 API 请求有限制。

因此,Google Sheets API 非常适合小型应用程序和受众较少的平台。如果你有任何问题,请在 Twitter 上联系我。