Use Cases (更新: 2026/6/2)

用 Claude Code 自动化电子表格: CSV、Google Sheets API 与 Apps Script

用 Claude Code 自动化 CSV 汇总、Google Sheets API 写入和 Apps Script 线索管理。

用 Claude Code 自动化电子表格: CSV、Google Sheets API 与 Apps Script

电子表格自动化看起来只是小工具,但它常常连接销售、咨询表单、广告费用、发票和内容 KPI。一旦导入规则错了,团队看到的不是“少了一行数据”,而是错误的收入、错误的优先级和错误的投放判断。

Claude Code 的价值不是替你在表格里猜公式,而是让它在代码仓库里创建可审查的脚本。你可以让它读取现有约定,生成 CSV 汇总脚本、Google Sheets API 写入脚本、Apps Script 分类逻辑,并在最后给出修改文件、执行命令和剩余风险。

本文用一个可复制的流程说明做法: 先在本地汇总 CSV,再用 Google Sheets API 追加咨询线索,最后用 Apps Script 在表格内自动分类。相关基础可以先看Claude Code 生产力技巧验证记录工作流。官方资料建议同时参考Claude Code docsClaude Code CLI usageGoogle Sheets API Node.js quickstartApps Script Sheets guideSheetJS docs

先划清数据边界

开始前先不要急着选库。最重要的问题是: 哪个表是事实来源,哪个表只是给人看的报表。很多团队的问题不是没有自动化,而是 CSV、Google Sheets、CRM、会计系统都能改同一个数字。Claude Code 再快,也无法替你判断哪个数字才可信。

可以把工作流分成三层。

作用例子适合交给 Claude Code 的任务
Raw不让人手改的原始输入表单提交、支付 CSV、广告导出导入、校验、错误行隔离
Clean类型统一的中间表日期、金额、状态名已规范化正规化、去重、必填列检查
Report给人阅读的报表月收入、咨询优先级、KPI 表汇总、图表 CSV、通知

初学者最容易把 API 直接写入 Report 页。这个页面通常有颜色、公式、冻结行、备注、合并单元格和人工排序,适合阅读,不适合机器追加。更安全的做法是只让程序写 Raw 或 Clean,再用公式、数据透视表、Looker Studio 或另一个脚本生成报表。

实例1: 汇总销售 CSV

先做一个不需要 Google 认证的版本。这样 Claude Code 生成的逻辑可以本地复现,代码审查也不会被权限问题挡住。

创建 data/sales.csv

date,channel,product,amount,status
2026-05-01,organic,Claude Code Cheatsheet,0,won
2026-05-02,gumroad,Prompt Template Pack,2980,won
2026-05-08,consultation,Team Workshop,120000,won
2026-05-11,gumroad,Prompt Template Pack,2980,refunded
2026-06-01,organic,Claude Code Cheatsheet,0,won
2026-06-02,consultation,Implementation Review,80000,won

创建 scripts/summarize-sales.mjs

import { mkdir, readFile, writeFile } from "node:fs/promises";
import path from "node:path";

const inputPath = process.argv[2] ?? "data/sales.csv";
const outputPath = process.argv[3] ?? "out/monthly-summary.csv";

function parseCsvLine(line) {
  const cells = [];
  let current = "";
  let inQuotes = false;

  for (let index = 0; index < line.length; index += 1) {
    const char = line[index];
    const next = line[index + 1];

    if (char === '"' && inQuotes && next === '"') {
      current += '"';
      index += 1;
      continue;
    }

    if (char === '"') {
      inQuotes = !inQuotes;
      continue;
    }

    if (char === "," && !inQuotes) {
      cells.push(current.trim());
      current = "";
      continue;
    }

    current += char;
  }

  cells.push(current.trim());
  return cells;
}

function parseCsv(source) {
  const lines = source.trim().split(/\r?\n/).filter(Boolean);
  const headers = parseCsvLine(lines[0]);

  return lines.slice(1).map((line) => {
    const cells = parseCsvLine(line);
    return Object.fromEntries(headers.map((header, index) => [header, cells[index] ?? ""]));
  });
}

function toMonth(dateValue) {
  const date = new Date(`${dateValue}T00:00:00Z`);
  if (Number.isNaN(date.getTime())) {
    throw new Error(`Invalid date: ${dateValue}`);
  }
  return dateValue.slice(0, 7);
}

const rows = parseCsv(await readFile(inputPath, "utf8"));
const summary = new Map();

for (const row of rows) {
  if (row.status !== "won") continue;

  const amount = Number(row.amount);
  if (!Number.isFinite(amount)) {
    throw new Error(`Invalid amount: ${JSON.stringify(row)}`);
  }

  const key = `${toMonth(row.date)},${row.channel}`;
  const current = summary.get(key) ?? { month: toMonth(row.date), channel: row.channel, deals: 0, revenue: 0 };
  current.deals += 1;
  current.revenue += amount;
  summary.set(key, current);
}

const output = [
  "month,channel,deals,revenue",
  ...[...summary.values()]
    .sort((a, b) => `${a.month}:${a.channel}`.localeCompare(`${b.month}:${b.channel}`))
    .map((row) => `${row.month},${row.channel},${row.deals},${row.revenue}`),
].join("\n");

await mkdir(path.dirname(outputPath), { recursive: true });
await writeFile(outputPath, `${output}\n`, "utf8");

console.log(`Wrote ${outputPath} (${summary.size} groups)`);

运行命令如下。

mkdir -p data out scripts
node scripts/summarize-sales.mjs data/sales.csv out/monthly-summary.csv
cat out/monthly-summary.csv

这个脚本的重点是遇到坏数据时立即失败。金额为空、日期格式错误、状态名变化,都不应该被悄悄算成 0。让 Claude Code 继续改进时,可以要求它加入行号、错误 CSV、退款状态测试和必填列检查。

实例2: 用 Google Sheets API 追加咨询线索

团队使用时,服务账号通常比个人 OAuth 更容易审计。你需要在 Google Cloud 启用 Sheets API,创建服务账号 JSON,将服务账号邮箱分享给目标表格,并在表格里准备 Raw 页。第一行放 createdAt,source,subject,amount,status

npm install googleapis
export GOOGLE_APPLICATION_CREDENTIALS="$PWD/service-account.json"
export SHEET_ID="your-google-sheet-id"

创建 scripts/append-lead-to-sheet.mjs

import { google } from "googleapis";

const { GOOGLE_APPLICATION_CREDENTIALS, SHEET_ID } = process.env;

if (!GOOGLE_APPLICATION_CREDENTIALS) {
  throw new Error("GOOGLE_APPLICATION_CREDENTIALS is required");
}

if (!SHEET_ID) {
  throw new Error("SHEET_ID is required");
}

const auth = new google.auth.GoogleAuth({
  keyFile: GOOGLE_APPLICATION_CREDENTIALS,
  scopes: ["https://www.googleapis.com/auth/spreadsheets"],
});

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

const source = process.argv[2] ?? "web";
const subject = process.argv[3] ?? "Claude Code consultation";
const amount = Number(process.argv[4] ?? 0);

if (!Number.isFinite(amount)) {
  throw new Error(`Invalid amount: ${process.argv[4]}`);
}

await sheets.spreadsheets.values.append({
  spreadsheetId: SHEET_ID,
  range: "Raw!A:E",
  valueInputOption: "USER_ENTERED",
  insertDataOption: "INSERT_ROWS",
  requestBody: {
    values: [[new Date().toISOString(), source, subject, amount, "new"]],
  },
});

console.log("Appended lead row");

执行示例。

node scripts/append-lead-to-sheet.mjs newsletter "Spreadsheet automation review" 50000

把这段交给 Claude Code 修改时,要明确环境变量名、写入范围、目标 tab、列顺序和不能提交凭证。服务账号 JSON 不应进入文章、Issue、聊天记录或 Git 历史。

实例3: 用 Apps Script 分类销售与咨询

如果工作流本身就在 Google Workspace 内,Apps Script 很方便。它可以响应表单提交、写入 Sheets、发送邮件,不需要单独服务器。但它也有执行时间、触发器、授权和发送配额限制。高频场景要先看官方的Apps Script quotas

把下面代码粘贴到 Apps Script 编辑器,并为 onFormSubmit 配置表单提交的安装型触发器。

const SETTINGS = {
  sheetName: "Leads",
  notifyTo: "sales@example.com",
  minAmountForHighPriority: 100000,
};

function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu("Lead Ops")
    .addItem("Rebuild lead status", "rebuildLeadStatus")
    .addToUi();
}

function onFormSubmit(event) {
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = spreadsheet.getSheetByName(SETTINGS.sheetName) || spreadsheet.insertSheet(SETTINGS.sheetName);
  ensureHeader_(sheet);

  const values = event && event.namedValues ? event.namedValues : {};
  const company = first_(values, "Company");
  const email = first_(values, "Email");
  const plan = first_(values, "Plan");
  const budget = Number(first_(values, "Budget") || 0);
  const priority = classifyLead_(plan, budget);

  sheet.appendRow([new Date(), company, email, plan, budget, priority, "new"]);

  if (priority === "high") {
    MailApp.sendEmail({
      to: SETTINGS.notifyTo,
      subject: `High priority lead: ${company}`,
      body: `Company: ${company}\nEmail: ${email}\nPlan: ${plan}\nBudget: ${budget}`,
    });
  }
}

function rebuildLeadStatus() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SETTINGS.sheetName);
  if (!sheet) throw new Error(`Sheet not found: ${SETTINGS.sheetName}`);
  ensureHeader_(sheet);

  const values = sheet.getDataRange().getValues();
  for (let rowIndex = 1; rowIndex < values.length; rowIndex += 1) {
    const row = values[rowIndex];
    const plan = String(row[3] || "");
    const budget = Number(row[4] || 0);
    const priority = classifyLead_(plan, budget);
    sheet.getRange(rowIndex + 1, 6).setValue(priority);
  }
}

function ensureHeader_(sheet) {
  const header = ["createdAt", "company", "email", "plan", "budget", "priority", "status"];
  const current = sheet.getRange(1, 1, 1, header.length).getValues()[0];
  if (current.join("") === "") {
    sheet.getRange(1, 1, 1, header.length).setValues([header]);
    sheet.setFrozenRows(1);
  }
}

function classifyLead_(plan, budget) {
  const normalizedPlan = String(plan).toLowerCase();
  if (budget >= SETTINGS.minAmountForHighPriority || normalizedPlan.includes("team")) {
    return "high";
  }
  if (budget >= 30000) {
    return "medium";
  }
  return "low";
}

function first_(namedValues, key) {
  const value = namedValues[key];
  return Array.isArray(value) ? value[0] || "" : "";
}

如果表单字段是中文,例如“公司名”“预算”“咨询内容”,就把 first_(values, "Company") 改成真实字段名。不要让 Claude Code 自己猜字段,也不要让它把个人信息打印到日志里。

Claude Code 依赖模板

好的依赖不是“帮我自动化表格”,而是明确输入、输出、范围和验证方式。

You are working on spreadsheet automation for this repository.

Goal:
- Import sales CSV rows from data/sales.csv.
- Write a monthly summary to out/monthly-summary.csv.
- Add a Google Sheets append script for the Raw tab.

Scope:
- You may edit scripts/summarize-sales.mjs and scripts/append-lead-to-sheet.mjs.
- You may add small tests or sample CSV files if needed.
- Do not edit content files, product links, analytics, or deployment settings.

Rules:
- Do not commit credentials.
- Use environment variables for SHEET_ID and GOOGLE_APPLICATION_CREDENTIALS.
- Fail loudly on invalid dates, invalid amounts, and missing required columns.
- Keep the code copy-paste runnable with Node.js 20 or later.

Verification:
- Run node --check on every script you edit.
- Run the CSV summary against data/sales.csv.
- For Google Sheets API, verify syntax locally and list the manual credential checks.
- Return changed files, commands run, output summary, and remaining risks.

验证命令也要写清楚。

node --check scripts/summarize-sales.mjs
node scripts/summarize-sales.mjs data/sales.csv out/monthly-summary.csv
node --check scripts/append-lead-to-sheet.mjs
git diff -- scripts/summarize-sales.mjs scripts/append-lead-to-sheet.mjs

如果团队长期使用,把这部分放进 CLAUDE.md,并结合Claude Code 权限指南限制可执行命令和可修改文件。

真实使用场景

第一个场景是月度销售报表。Gumroad、Stripe、手动发票和免费资料注册可以先导出 CSV,再统一统计。退款不计收入,免费线索只计数量,商品名的写法需要标准化。

第二个场景是咨询线索分级。预算、团队规模、计划类型、现有客户邮箱域名都可以成为规则。规则必须能解释,例如“预算超过 100000 日元或选择 team 方案”可以审查,“看起来不错”不可以。

第三个场景是文章和广告 KPI。把 slug、发布日期、搜索点击、CTA 点击、商品点击和咨询表单到达放在一张表里,就能看出哪些文章值得更新。事件命名可以参考Claude Code 分析实现指南

第四个场景是发票前检查。把交付日志和发票 CSV 对比,只把不一致的行写到审查表。第一版不要自动寄出发票,先让差异可见。

常见陷阱

最大的陷阱是列名不稳定。Amountamount收入混在一起时,脚本可能正常结束,却漏掉重要行。必须让 Claude Code 写出必填列检查。

第二个陷阱是把 Sheets 当数据库。Sheets 适合协作和检查,不适合交易、锁、权限正本和大批量写入。支付状态和访问权限应留在真正的应用数据库里。

第三个陷阱是泄露凭证。服务账号 JSON 不能进 Git、文档、Issue 或提示词。要求 Claude Code 不读取、不输出、不提交密钥。

第四个陷阱是忘记 Apps Script 触发器。代码粘贴成功不代表表单提交会执行。要检查安装型触发器、执行用户、首次授权、邮件配额和错误通知。

第五个陷阱是只看最终数字。报表必须显示读取行数、排除行数、错误行数和最后更新时间,否则你不知道自动化什么时候坏掉。

CTA: 把脚本变成运营流程

电子表格自动化要稳定,靠的不只是脚本,而是提示词、权限和验证记录。可以先用免费 Claude Code 速查表固定日常命令和检查习惯。需要可复用的提示词包和 CLAUDE.md 模板时,可以查看ClaudeCodeLab 产品

如果团队已经把销售、线索、广告或发票放在表格里,建议先设计凭证边界、人工审批和审查流程,再增加自动化。需要一起整理这些规则时,可以使用Claude Code 培训与咨询

实际尝试后的结果

Masa 的实践中,最有效的不是一开始接 Google Sheets API,而是先固定 CSV 列名、排除规则和失败方式。这样 Claude Code 的任务变得具体,审查也更快。Apps Script 对线索分级很方便,但通知条件含糊时邮件会暴增。最终更稳定的做法,是把电子表格连携看成 Raw、Clean、Report 的边界设计,再让 Claude Code 逐段实现和验证。

#Claude Code #spreadsheet #Excel #Google Sheets #automation
免费

免费 PDF: Claude Code 速查表

输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。

我们会妥善保护你的信息,不发送垃圾邮件。

把 Claude Code 变成真正能带来结果的工作流

先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。

Masa

关于作者

Masa

专注 Claude Code 实务流程、团队导入和内容转化的工程师。