用 Python 和 ChatGPT API 翻译 Excel 的方法【2026年版·附可运行代码】

Translate Excel ChatGPT

最后更新:2026年6月 —— 已使用 OpenAI Python SDK v1.x 和 Chat Completions API 测试通过。

本教程使用 Chat Completions API,因为它简单且被广泛支持。对于新应用,你也可以考虑 OpenAI 的 Responses API 和结构化输出(structured outputs)。

翻译 Excel 文件的两种方式

在动手写第一行代码之前,先老实问自己一句:到底哪种方式更适合你?

  • 用 Python 写脚本(本文)。 如果你想批量翻译大量文件、定时跑任务,或者把它接入更大的流水线,这是最佳选择。你需要一个 OpenAI API 密钥,再加上一点 Python 基础。
  • 直接用现成工具。 如果你只是现在就想翻译一份表格,并且希望图表、公式、样式都被自动保留,那么把文件上传到 Doc2Lang 的 Excel 翻译工具 会更快,而且完全不用写代码。

本文聚焦 Python 这条路,给你一套完整、可直接运行的代码。同时,我们也会明确指出自己动手时容易踩坑的地方,让你做选择时心里有底。文章末尾还有一份完整的对比。

准备工作

开始之前,你需要准备这些东西:

  • Python 基础知识。 本文涉及代码。懂一些 Python 会更顺手,不过每一步我们都会讲解。
  • 已安装 Python。 如果还没装,到官网下载即可。
  • pip。 它用来安装 Python 库。只要你装了 Python 3,基本上就已经有 pip 了。
  • OpenAI API 密钥。 在 OpenAI 账户后台创建一个。同一个密钥可以用于当前所有模型(gpt-4ogpt-4o-mini 等等)。
  • 你的 Excel 文件。 把要翻译的 .xlsx 文件准备好。

把你的 API 密钥设置为环境变量,这样它就永远不会出现在代码里:

macOS / Linux:

export OPENAI_API_KEY="your_api_key_here"

Windows PowerShell:

$env:OPENAI_API_KEY="your_api_key_here"

.xlsx 文件的内部结构(选读背景)

当你把表格保存为 .xlsx 时,其实是把好几个文件打包进了一个压缩包。这种格式叫 OpenXML。如果你好奇,可以把文件后缀改成 .zip,解压后看看里面有什么:

  • xl/worksheets/ —— 每张工作表对应一个 XML 文件(sheet1.xmlsheet2.xml……)。你的行、列和单元格数据其实就存在这里。
  • xl/styles.xml —— 工作簿里的所有样式:哪些单元格加粗、哪些是蓝色、哪些数字按货币格式显示,等等。
  • xl/sharedStrings.xml —— 为了省空间,Excel 把每个唯一字符串只存一次,然后在用到的地方引用它。即使「合计」出现了 1000 次,也只存一份。
  • xl/workbook.xml —— 相当于目录:有哪些工作表、它们的顺序,以及工作表保护之类的属性。

像 openpyxl 这样的库会把这些细节大都帮你藏起来,但了解一下结构,在你需要做高级操作或排查问题时会很有帮助。

Windows 资源管理器显示解压后的 report.xlsx 内容

解压后的 report.xlsx:工作表、共享字符串、样式和工作簿结构,其实就是 zip 压缩包里的一堆 XML 文件。

用 openpyxl 读写 Excel 文件

openpyxl 是一个专门用来读写 Excel 文件(.xlsx.xlsm.xltx.xltm)的 Python 库。它让你可以直接操作工作表和单元格。

有一点要先说清楚:openpyxl 在单元格级别的操作上非常出色,但它并不是一个完整保真的 Excel 排版引擎。当你打开并重新保存文件时,形状、部分图片、图表、宏,以及单元格内部的富文本都可能无法被保留。对于启用了宏的 .xlsm 文件,请用 load_workbook(..., keep_vba=True) 加载,并以 .xlsm 格式保存,否则宏可能会丢失。这些局限我们会在文章末尾再回头细说。

1. 安装 openpyxl

pip install openpyxl

2. 核心概念

有几个概念可以直接对应到 openpyxl 上:

Workbook(工作簿) —— 整个 Excel 文件。

from openpyxl import load_workbook
 
workbook = load_workbook(filename="sample.xlsx")

Sheet(工作表) —— 一个工作簿包含一张或多张工作表。

sheet = workbook.active          # 当前激活的工作表
another_sheet = workbook["Sheet2"]  # 按名称指定的工作表

Cell(单元格) —— 行与列的交汇处,也是数据所在的地方。

cell_value = sheet["A1"].value   # 读取
sheet["B1"] = "Hello, Excel!"    # 写入

行与列 —— 轻松遍历它们:

for row in sheet.iter_rows(values_only=True):
    for value in row:
        print(value)

用 OpenAI API 翻译文本

用 openpyxl 把数据读进来之后,下一步就是用 OpenAI API 来翻译。

1. 安装 OpenAI Python 库

pip install openai

2. 一个现代化的翻译函数(2026年版)

import os
from openai import OpenAI
 
# 从环境变量读取密钥——千万别把它硬编码进脚本里。
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
 
def translate_text(text, target_lang="Chinese"):
    response = client.chat.completions.create(
        model="gpt-4o-mini",  # 快且省钱;追求最佳质量就用 "gpt-4o"
        messages=[
            {
                "role": "system",
                "content": (
                    f"You are a professional translator. Translate the user's text "
                    f"into {target_lang}. Return only the translation, with no extra commentary."
                ),
            },
            {"role": "user", "content": text},
        ],
    )
    return response.choices[0].message.content.strip()

提个醒: 很多旧教程用的是 openai.ChatCompletion.create() 加上 model="gpt-4"。那是 1.0 之前 SDK 的写法,在 openai>=1.0已经不能用了。上面的代码用的是当前的 client.chat.completions.create() 接口。想要低成本和高速度就选 gpt-4o-mini,需要最高翻译质量时就选 gpt-4o

3. 一个最朴素的初版

最常见的教程做法,就是遍历每一个单元格并直接覆盖它:

from openpyxl import load_workbook
 
workbook = load_workbook(filename="your_file.xlsx")
 
for sheet in workbook.worksheets:
    for row in sheet.iter_rows():
        for cell in row:
            if isinstance(cell.value, str):
                cell.value = translate_text(cell.value)
 
workbook.save("your_translated_file.xlsx")

它在演示里能跑,但放到真实的表格上就会暴露出实打实的问题:每个单元格发一次 API 请求(又慢又贵)、把公式也一起翻译从而破坏它们、而且完全没有应对限流的措施。下面我们把这些问题逐一解决。

让它达到生产可用

1. 不要翻译公式

如果某个单元格里是 =SUM(A1:A10) 这样的公式,翻译它会让表格出错。请跳过公式、空单元格以及非文本的值:

def is_translatable(cell):
    # 跳过空单元格、数字和公式单元格。
    value = cell.value
    return (
        isinstance(value, str)
        and value.strip() != ""
        and cell.data_type != "f"   # "f" = formula
    )

openpyxl 只会重写 cell.value,所以只要你不去碰非文本的单元格,数字格式、字体、填充以及大多数样式都会原封不动地保留下来。

2. 缓存重复字符串以降低成本

表格里总是反复出现同样的标签(「合计」「日期」、某个部门名称)。每个唯一字符串只翻译一次就够了:

cache = {}
 
def translate_cached(text, target_lang="Chinese"):
    if text not in cache:
        cache[text] = translate_text(text, target_lang)
    return cache[text]

对一份典型的报表来说,单凭这一招就能把你的 API 调用次数——以及账单——大幅削减。

3. 把多个单元格合并到一次请求里

「一个单元格一次 API 调用」是拖慢速度的最大元凶。改成在一次请求里发送多个字符串,并要求模型返回 JSON,这样你就能可靠地把结果对应回去:

import json
 
def translate_batch(texts, target_lang="Chinese"):
    numbered = {str(i): t for i, t in enumerate(texts)}
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {
                "role": "system",
                "content": (
                    f"You are a professional translator. Translate each value in the "
                    f"JSON object into {target_lang}. Keep the same keys. "
                    f"Return only a JSON object."
                ),
            },
            {"role": "user", "content": json.dumps(numbered, ensure_ascii=False)},
        ],
        response_format={"type": "json_object"},
    )
    result = json.loads(response.choices[0].message.content)
    return [result[str(i)] for i in range(len(texts))]

4. 限流时重试(指数退避)

撞上限流时,别让程序直接崩——等一等再试,并且每次把等待时间翻倍:

import time
 
def with_retry(func, *args, retries=5, **kwargs):
    for attempt in range(retries):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            wait = 2 ** attempt
            print(f"Error: {e}. Retrying in {wait}s...")
            time.sleep(wait)
    raise RuntimeError("Translation failed after several retries.")

5. 安全地处理不可信文件

如果你要处理别人上传的 Excel 文件,就得防范恶意 XML。请安装 defusedxml——只要它存在,openpyxl 就会自动启用它——并在加载之前先校验文件的大小和类型:

pip install defusedxml

对于你自己的文件,这一步是可选的;但对于任何不是你自己创建的文件,强烈建议这么做。

完整可运行脚本

下面是把前面所有内容合到一起、可以直接复制运行的脚本。它会收集唯一字符串、带重试地批量翻译、缓存结果、跳过公式,并保存到一个新文件,让你的原文件安然无恙。

import json
import os
import time
from openai import OpenAI
from openpyxl import load_workbook
 
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
 
TARGET_LANG = "Chinese"
MODEL = "gpt-4o-mini"   # 追求更高质量就用 "gpt-4o"
BATCH_SIZE = 40
 
 
def is_translatable(cell):
    value = cell.value
    return (
        isinstance(value, str)
        and value.strip() != ""
        and cell.data_type != "f"   # "f" = formula
    )
 
 
def translate_batch(texts, target_lang=TARGET_LANG, retries=5):
    numbered = {str(i): t for i, t in enumerate(texts)}
    system = (
        f"You are a professional translator. Translate each value in the JSON object "
        f"into {target_lang}. Keep the same keys. Return only a JSON object."
    )
    for attempt in range(retries):
        try:
            response = client.chat.completions.create(
                model=MODEL,
                messages=[
                    {"role": "system", "content": system},
                    {"role": "user", "content": json.dumps(numbered, ensure_ascii=False)},
                ],
                response_format={"type": "json_object"},
            )
            result = json.loads(response.choices[0].message.content)
            return [result[str(i)] for i in range(len(texts))]
        except Exception as e:
            wait = 2 ** attempt
            print(f"Error: {e}. Retrying in {wait}s...")
            time.sleep(wait)
    raise RuntimeError("Translation failed after several retries.")
 
 
# 1. 加载工作簿
workbook = load_workbook(filename="your_file.xlsx")
 
# 2. 收集所有唯一且可翻译的字符串
unique_texts = set()
for sheet in workbook.worksheets:
    for row in sheet.iter_rows():
        for cell in row:
            if is_translatable(cell):
                unique_texts.add(cell.value)
unique_texts = list(unique_texts)
 
# 3. 分批翻译,并构建一个 {原文: 译文} 的缓存
cache = {}
for start in range(0, len(unique_texts), BATCH_SIZE):
    chunk = unique_texts[start:start + BATCH_SIZE]
    cache.update(dict(zip(chunk, translate_batch(chunk))))
 
# 4. 把译文写回去,不碰公式和样式
for sheet in workbook.worksheets:
    for row in sheet.iter_rows():
        for cell in row:
            if is_translatable(cell):
                cell.value = cache[cell.value]
 
# 5. 保存到新文件
workbook.save("your_translated_file.xlsx")
print("Done!")

这就是一个完整实用的翻译器,代码量远不到 100 行——又快、又不会碰坏公式,而且比逐个单元格翻译的版本便宜得多。

进阶(选读):面向真实负载的加固

上面的脚本已经相当实用了。如果是更大或周期性运行的任务,再加上下面这三道防线会更稳妥。

别把所有异常都吞掉。 对每一个异常都重试,意味着无效的 API 密钥或写错的模型名也会被重试五次。请只在限流时重试,其余情况一律快速失败:

from openai import RateLimitError
 
def translate_batch(texts, target_lang=TARGET_LANG, retries=5):
    numbered = {str(i): t for i, t in enumerate(texts)}
    system = (
        f"You are a professional translator. Translate each value in the JSON object "
        f"into {target_lang}. Keep the same keys. Return only a JSON object."
    )
    for attempt in range(retries):
        try:
            response = client.chat.completions.create(
                model=MODEL,
                messages=[
                    {"role": "system", "content": system},
                    {"role": "user", "content": json.dumps(numbered, ensure_ascii=False)},
                ],
                response_format={"type": "json_object"},
            )
            result = json.loads(response.choices[0].message.content)
            missing = [str(i) for i in range(len(texts)) if str(i) not in result]
            if missing:
                raise ValueError(f"Missing translations for keys: {missing}")
            return [result[str(i)] for i in range(len(texts))]
        except RateLimitError:
            wait = 2 ** attempt
            print(f"Rate limited. Retrying in {wait}s...")
            time.sleep(wait)
    raise RuntimeError("Translation failed after several retries.")

这个版本还会校验模型是否返回了所有传给它的键,这样一旦响应被截断或格式不对,就会直接报错,而不会悄无声息地丢掉某些单元格。

去重时保持顺序。 用有序去重来代替 set,让日志和报错信息保持可预测:

# 原先写法:unique_texts = list(unique_texts),配合 set()
unique_texts = list(dict.fromkeys(collected_texts))

Python 脚本 vs. Doc2Lang:你该选哪个?

自己写脚本很强大,但它也有实打实的局限。下面是一份诚实的对比:

Python(自己动手)Doc2Lang
格式与图表得自己处理,很容易出问题自动保留
公式自己写条件来跳过自动跳过
需要准备什么OpenAI API 密钥 + 编程上传文件即可
适合谁需要自动化批量或周期性任务的开发者现在就需要翻译一份文件的任何人
由 Doc2Lang 翻译、完整保留格式的产品规格表

由 Doc2Lang 翻译的产品规格表——表格、列、颜色、工作表标签全部和原件一样原样保留。

试用 Excel 翻译工具 —— 无需 API 密钥,无需写代码。

一句话经验法则:如果你想把周期性的翻译任务自动化,就照着上面的脚本来做;如果你只是现在就想翻译一份表格、又不想写代码,那就 用 Excel 翻译工具——上传、翻译、下载,格式完好无损。

相关指南

常见问题

遇到限流错误怎么办?
OpenAI 会根据你的账户等级设置限流。可以用上面展示的指数退避重试、把批大小调小,或者在处理大量数据时升级账户等级。

如何一次翻译成多种语言?
遍历一个目标语言列表,对每种语言把整个流程跑一遍,并把每个结果保存到各自的文件里(比如 report_ja.xlsxreport_de.xlsx)。

使用 OpenAI API 要花钱吗?
要。它按使用的 token 数量计费。缓存重复字符串和批量请求(上面都演示过)能让成本保持在低位。对日常翻译来说,gpt-4o-mini 比那些更大的模型便宜得多。

这样能保留我的格式和公式吗?
脚本只会改动文本单元格的值,所以基本的单元格样式——字体、填充、边框、对齐方式和数字格式——通常都会被保留,公式也会被跳过。不过 openpyxl 并不是一个完整保真的 Excel 排版引擎。宏、形状、图表、图片、单元格内部的富文本,以及复杂的工作簿特性,都可能无法被完美保留。对于 .xlsm 文件,请用 keep_vba=True 加载并以 .xlsm 格式保存。如果相比自动化你更看重像素级精准的版式,那么专用工具会自动帮你处理好这些情况。

结语

借助 openpyxl 和 OpenAI API,你可以用远不到 100 行代码搭出一个又快、又不会碰坏公式的 Excel 翻译器——当你需要大规模自动化翻译时,它再合适不过。

如果你的首要诉求是保留版式而不是自动化,那么专用的 Excel 翻译工具可能更适合你——它能搞定 openpyxl 处理不了的图表、形状和样式。

无需写代码,直接翻译一份 Excel 文件