盘点一个Python Excel 数字转中文业务等级完整方案
- 2026-11-07 20:55:51
{"variant":"document","title":"盘点一个Python Excel 数字转中文业务等级完整方案","id":"58391"}
Excel 里有一列数字,看着没什么问题。
但是产品突然提了一个需求:
“这个等级字段不要显示 1、2、3,改成一级、二级、三级。”
这种需求在业务系统里特别常见。
比如客户等级:
1 普通客户
2 白银客户
3 黄金客户
4 钻石客户
再比如订单优先级:
1 低
2 中
3 高
开发的时候很多人第一反应就是写几个 if。
数据量小的时候确实能跑,但一旦 Excel 是运营每天导入的,几万行数据,等级规则还会调整,这种写法很快就开始难维护。
我之前处理这类 Excel 清洗任务,一般不会直接在循环里面堆业务判断。
先把数据读出来,看字段,再决定转换规则。
比如原始 Excel:
客户编号 用户名 等级 10001 张三 1 10002 李四 2 10003 王五 3
目标:
客户编号 用户名 等级 10001 张三 一级 10002 李四 二级 10003 王五 三级
Python 处理 Excel,我一般用 pandas。
安装:
```bash
pip install pandas openpyxl
先读取文件:
import pandas as pd
source_file = "customer_level.xlsx"
df = pd.read_excel(source_file)
print(df.head())
print(df.columns.tolist())
这里我习惯先打印列名。
别小看这个动作。
很多线上导入问题,不是代码错,而是 Excel 表头偷偷改了。
比如:
等级
变成:
客户等级
程序直接 KeyError。
不要一上来写转换逻辑,先确认数据长什么样。
简单版本可以这样处理:
level_map = {
1: "一级",
2: "二级",
3: "三级",
4: "四级"
}
df["等级"] = df["等级"].map(level_map)
df.to_excel(
"customer_level_result.xlsx",
index=False
)
这个写法适合固定业务。
但是实际项目里,我更喜欢加一层保护。
因为 Excel 里面的数据很不靠谱。
比如:
1
"1"
"一级"
空
null
都有可能出现。
如果直接 map,未知数据会变成空。
这种问题上线后才发现,很麻烦。
所以转换函数不要写得太死。
defconvert_level(value):
if pd.isna(value):
return"未知等级"
text = str(value).strip()
level_dict = {
"1": "一级",
"2": "二级",
"3": "三级",
"4": "四级"
}
return level_dict.get(text, "未知等级")
df["等级"] = df["等级"].apply(convert_level)
这个地方多处理了一步:
先转字符串。
因为 Excel 读取数字的时候:
1
可能是 int。
但是如果单元格格式特殊,也可能读成:
1.0
甚至:
'1'
业务数据清洗,不能只考虑理想输入。
不过“数字转中文等级”还有一个容易混淆的问题。
很多人说数字转中文,其实有两类。
第一类:
业务等级转换。
例如:
1 -> 一级
2 -> 二级
3 -> 三级
这种本质是枚举映射。
第二类:
金额、数量转换。
例如:
12345
转换:
一万二千三百四十五
这个才是真正的数字中文化。
两个不要混在一起。
我见过一个系统,把订单金额字段也套等级转换逻辑,最后生成报表:
订单金额:三级
这种问题排查起来很痛苦。
如果是金额数字转中文,我一般单独写一个工具。
比如:
defnumber_to_cn(num):
if num == 0:
return"零"
nums = [
"零",
"一",
"二",
"三",
"四",
"五",
"六",
"七",
"八",
"九"
]
units = [
"",
"十",
"百",
"千"
]
result = []
num = str(num)
length = len(num)
for index, item in enumerate(num):
n = int(item)
if n != 0:
result.append(nums[n])
result.append(
units[length - index - 1]
)
return"".join(result)
print(number_to_cn(325))
输出:
三百二十五
这个代码只是基础版。
真实业务里面还要处理:
10001
1000000
100000000
100.50
这些情况。
所以金额场景,我一般不会直接复制一个转换函数上线。
会先确认需求:
到底是展示?
还是财务报表?
还是合同打印?
不同场景要求完全不一样。
回到 Excel 等级转换。
生产环境里面,我还会加两个东西。
第一个是转换前后检查。
比如:
before_count = df["等级"].value_counts()
df["等级"] = df["等级"].apply(convert_level)
after_count = df["等级"].value_counts()
print("转换前:")
print(before_count)
print("转换后:")
print(after_count)
为什么?
因为如果突然来了:
等级=99
你至少能看到:
未知等级 5000条
而不是等业务发现报表异常。
第二个是保留原始字段。
不要直接覆盖。
很多线上事故都是这种:
原始数据被修改,没有办法追。
我通常这样:
df["原始等级"] = df["等级"]
df["等级名称"] = df["等级"].apply(
convert_level
)
输出:
等级 原始等级 等级名称
1 1 一级
2 2 二级
后面出现问题,还能回查。
最后给一个完整处理脚本。
适合每天跑 Excel 导入任务。
import pandas as pd
defconvert_level(value):
mapping = {
"1": "一级",
"2": "二级",
"3": "三级",
"4": "四级"
}
if pd.isna(value):
return"未知等级"
key = str(value).replace(".0", "").strip()
return mapping.get(
key,
"未知等级"
)
defprocess_excel():
df = pd.read_excel(
"customer.xlsx"
)
if"等级"notin df.columns:
raise Exception(
"Excel缺少等级字段"
)
df["原等级"] = df["等级"]
df["业务等级"] = (
df["等级"]
.apply(convert_level)
)
error_data = df[
df["业务等级"] == "未知等级"
]
if len(error_data) > 0:
print(
"发现异常等级:",
len(error_data)
)
df.to_excel(
"customer_result.xlsx",
index=False
)
if __name__ == "__main__":
process_excel()
这种脚本看起来没什么技术含量。
但实际工作里,很多数据处理任务就是靠这种小工具解决。
不要追求代码多漂亮。
关键是:
Excel 数据乱了,你能定位。
规则变了,你能修改。
出了问题,你能找到原始数据。
业务脚本最怕的不是代码少,而是跑完以后没人知道发生了什么。