如何在React中获取Google Sheets表单、填充数据并导出为PDF
实现React应用对接Google Sheets并导出PDF的方案
核心思路
要完成你需求的三个步骤,核心是通过Google Sheets API读取模板、填充数据,再借助前端PDF生成工具将填充后的表格转为PDF供用户下载。
具体实现步骤
1. 配置Google Sheets API权限
- 在Google Cloud控制台创建项目,启用Google Sheets API,生成服务账号密钥(JSON格式)。
- 将预定义的Sheets模板共享给服务账号邮箱(密钥文件中的
client_email字段),权限设为编辑者。
2. 后端处理Sheets读写操作
前端直接暴露密钥存在安全风险,必须通过后端代理处理Sheets API请求,使用googleapis库实现:
// 后端Node.js示例代码 const { google } = require('googleapis'); const credentials = require('./service-account-key.json'); const auth = new google.auth.JWT( credentials.client_email, null, credentials.private_key, ['https://www.googleapis.com/auth/spreadsheets'] ); const sheets = google.sheets({ version: 'v4', auth }); // 读取模板数据 async function getSheetTemplate(spreadsheetId, range) { const res = await sheets.spreadsheets.values.get({ spreadsheetId, range }); return res.data.values; } // 向指定空行填充用户数据 async function fillSheetData(spreadsheetId, range, userData) { await sheets.spreadsheets.values.update({ spreadsheetId, range, valueInputOption: 'USER_ENTERED', resource: { values: [userData] } }); }
注意:
range需指定预定义空行的位置,例如'Sheet1!A5:E5'。
3. 前端触发流程并生成PDF
React组件中编写按钮点击逻辑,调用后端接口获取填充后的表格数据,再用jspdf+html2canvas生成PDF:
// React组件示例 import { useState } from 'react'; import { jsPDF } from 'jspdf'; import html2canvas from 'html2canvas'; const DataSubmit = () => { const [userData, setUserData] = useState({ name: '', email: '', phone: '' }); const [filledTable, setFilledTable] = useState(null); // 提交用户数据到后端,获取填充后的表格HTML const handleSubmit = async () => { const res = await fetch('/api/fill-sheet', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(userData) }); const tableHtml = await res.text(); setFilledTable(tableHtml); }; // 生成并下载PDF const downloadPDF = async () => { const tableElement = document.getElementById('filled-table'); const canvas = await html2canvas(tableElement); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF('p', 'mm', 'a4'); const imgWidth = 210; const imgHeight = (canvas.height * imgWidth) / canvas.width; pdf.addImage(imgData, 'PNG', 0, 0, imgWidth, imgHeight); pdf.save('filled-form.pdf'); }; return ( <div> <input type="text" placeholder="姓名" onChange={(e) => setUserData({...userData, name: e.target.value})} /> <input type="email" placeholder="邮箱" onChange={(e) => setUserData({...userData, email: e.target.value})} /> <input type="tel" placeholder="电话" onChange={(e) => setUserData({...userData, phone: e.target.value})} /> <button onClick={handleSubmit}>填充数据到表格</button> {filledTable && ( <> <div id="filled-table" dangerouslySetInnerHTML={{__html: filledTable}} /> <button onClick={downloadPDF}>下载PDF</button> </> )} </div> ); }; export default DataSubmit;
后端需将填充后的Sheets数据转为HTML表格结构返回给前端。
纯前端替代方案(适合非敏感数据)
若不想开发后端,可将Sheets模板设为公开可查看,用sheetjs(xlsx库)读取公开Sheets的CSV链接,在前端完成数据填充后转PDF:
// 前端读取公开Sheets示例 import XLSX from 'xlsx'; async function loadAndFillSheet(userData) { // 公开Sheets的CSV链接格式:https://docs.google.com/spreadsheets/d/{spreadsheetId}/gviz/tq?tqx=out:csv&sheet={sheetName} const res = await fetch('https://docs.google.com/spreadsheets/d/xxx/gviz/tq?tqx=out:csv&sheet=Sheet1'); const csvData = await res.text(); const workbook = XLSX.read(csvData, { type: 'string' }); const worksheet = workbook.Sheets[workbook.SheetNames[0]]; // 填充预定义空行 worksheet['A5'] = { v: userData.name }; worksheet['B5'] = { v: userData.email }; worksheet['C5'] = { v: userData.phone }; // 转为HTML表格用于生成PDF return XLSX.utils.sheet_to_html(worksheet); }
此方案缺点是Sheets需公开,数据安全性较低,仅适合非敏感数据场景。
关键注意点
- 禁止在前端代码中暴露Google服务账号密钥,必须通过后端代理处理API请求。
- 填充数据时需准确定位预定义空行,避免覆盖已有数据。
- 若表格内容过长,需在PDF生成时处理分页逻辑(
jspdf支持分页配置)。
内容的提问来源于stack exchange,提问作者holydragon
相关产品推荐
相关产品推荐

