做Excel数据整理的人,大概都经历过这种崩溃时刻:一张表里中英文姓名、中英混排的备注、带单位的文本全挤在一列,想拆拆不开,想统计统计不了。手动处理吧,几百行数据能点到手抽筋;上网找插件吧,又要安装又要担心安全。其实Excel早就内置了一个不起眼却非常好用的函数——CODE,它就是专治这种"字符识别"问题的利器,配合LEFT、MID、SUMPRODUCT等函数,中英文分离、姓名统计这些让人头疼的活儿,几行公式就能搞定。
这篇文章我想从一个实际使用者的角度,把这个函数讲透:它为什么能识别中英文、怎么用它做文本分离、怎么在姓名统计场景里发挥价值,以及我用它处理数据时踩过的坑和总结出来的组合拳。不管你是Excel公式新手,还是每天跟名单、报表死磕的老手,这篇内容都能直接帮你省下大把时间。
1. CODE函数的工作原理:为什么它能"一眼认出"中英文
1.1 字符编码:每个字符的"身份证号"
计算机里的所有字符,不管是字母、数字、汉字还是标点符号,在存储的时候都会被映射成一个数字编码。这个编码就像是每个字符的"身份证号",而CODE函数的作用,就是返回文本字符串中第一个字符对应的编码。语法极其简单:
=CODE(text)随手测几个常见字符你就明白了:
=CODE("A")返回 65=CODE("a")返回 97=CODE("0")返回 48=CODE(" ")返回 32=CODE("!")返回 33
反过来,CHAR函数接收一个编码并返回对应字符,=CHAR(65)返回 "A"。这俩函数互为逆运算,很多文本处理场景都需要配合使用。
为什么这个函数值得专门写一篇文章?因为CODE的输出值能直接反映出字符所属的"族群"。标准ASCII字符(英文字母、数字、英文标点)的编码都集中在0到127这个区间,而中文字符在简体中文Windows环境下走的是GBK/GB2312双字节字符集,编码值的范围完全不同。也就是说,只要拿到一个字符的CODE值,你就能判断出它到底是"中文阵营"还是"英文阵营"。
1.2 中文环境下CODE返回值的"诡异现象"
我第一次用CODE函数的时候,被一个现象惊到了:在中文系统上,=CODE("中")返回的不是什么200多或者300多的正整数,而是一个负数。一开始我以为是公式写错了,查了半天才明白原因。
这是因为Excel在双字节字符集(DBCS)环境中,会把两个字节拼合出来的编码当作16位带符号整数来解释。中文汉字的编码字节中,最高位通常是1,于是整个数值就被解释成了负数。下面是我在简体中文版Excel里实测的一组示意值,不同系统版本可能有差异,但规律是稳定的:
| 字符 | CODE返回值(简体中文环境示意) | 说明 |
|---|---|---|
| A | 65 | 英文大写字母,属于ASCII区间 |
| z | 122 | 英文小写字母,属于ASCII区间 |
| 0 | 48 | 数字,属于ASCII区间 |
| (半角空格) | 32 | 单字节空格 |
| (全角空格) | 负数 | 全角符号,已超出单字节区间 |
| 中 | 负数 | 中文字符,绝对值远大于127 |
记住里面最关键的一条规律就行:只要这个字符是中文或者全角标点,CODE返回值的绝对值通常大于127;只要是标准的ASCII字符(英文、数字、半角标点),绝对值一定在0到127之间。这条规律就是后面所有分离公式和统计公式的基石。
1.3 判定"中文开头"的核心公式
有了上面的规律,判断一个单元格内容是不是中文开头,一行公式就解决了:
=IF(ABS(CODE(LEFT(A2,1)))>127,"中文开头","英文/数字开头")拆开看每一步的逻辑:
LEFT(A2,1):取出第一个字符。CODE函数只读取传入文本的首字符,这里用LEFT包裹,逻辑上更清晰,也方便后续替换成MID或者RIGHT做灵活处理。CODE(...):拿到这个字符的编码。ABS(...):把可能出现的负数转成正数,统一比较口径。这一步是灵魂,后面踩坑章节会细说。>127:判断是否属于中文字符区间。
这个公式就是整个CODE函数应用体系里的"地基"。后面的中英文分离、姓名统计,本质上都是在它的基础上做扩展。你先把它写在Excel里,拿"张三""John""12345"分别试一遍,马上就能体会到"字符识别"四个字的分量。
2. 中英文分离实战:三个公式覆盖九成混排场景
2.1 场景一:给混合名单批量打标签
假设你手里有一列客户名单,中英文混在一起,需要批量加上"中文姓名"或"英文姓名"的标记。A列数据长这样:
| 姓名 | 目标结果 |
|---|---|
| 张三 | 中文姓名 |
| John Smith | 英文姓名 |
| 李四 | 中文姓名 |
| Alice | 英文姓名 |
在B2输入核心公式,然后往下拖:
=IF(ABS(CODE(LEFT(A2,1)))>127,"中文姓名","英文姓名")这个操作本身不复杂,但它解决的是一个高频痛点:很多人遇到混合名单的第一反应是排序、筛选,或者人工肉眼分辨,费时费力。用CODE判定首字符,等于让Excel替你做这一步"眼力活"。
如果你还想更细地判断英文名是不是"标准的大写字母开头",可以再加一层:
=IF(AND(CODE(A2)>=65,CODE(A2)<=90),"大写字母开头","其他")这里直接对CODE(A2)做区间判断即可,因为大写字母的编码就是65到90,不涉及负数,不需要加ABS。
2.2 场景二:两段式混排文本的拆分
接下来是更硬核的场景:一个单元格里既有中文又有英文或数字,比如"张三abc""备注2024测试"这种。先说结论:如果数据是"中文在前、英文/数字在后"的两段式结构,最稳的办法是配合LEN和LENB这对"字节兄弟",而不是单独用CODE逐字扫描。
中文字符在数据库里占2个字节,英文字符占1个字节,于是就有两个经典公式:
- 中文字符数 =
LENB(A2) - LEN(A2) - 英文字符数 =
2 * LEN(A2) - LENB(A2)
拿"张三abc"举例:
LEN("张三abc")返回5,因为一共5个字符。LENB("张三abc")返回7,因为"张""三"各占2字节,a、b、c各占1字节。- 所以前面中文部分长度 = 7 - 5 = 2,后面英文部分长度 = 2×5 - 7 = 3。
于是提取中文用LEFT,提取英文用RIGHT:
=LEFT(A2, LENB(A2) - LEN(A2)) ' 返回"张三" =RIGHT(A2, 2*LEN(A2) - LENB(A2)) ' 返回"abc"有人会问:这篇不是在讲CODE吗,怎么这里用LEN和LENB?我的理解是,CODE在这里扮演"裁判员",LENB扮演"测量员"。对单纯的"前中后英"结构,LENB测量法最快最准;但如果数据里混了全角标点、特殊符号,LENB的字节计数就会被干扰,这时候CODE逐字符扫描反而更可靠。两者不是替代关系,是互补关系。
2.3 场景三:定位第一个英文字符的位置
如果数据不是简单的"中文在一段",而是"中文+英文+数字"交错排列,比如"abc124号码007"这种,上面LENB的办法就失效了,因为没有办法用一个固定的切分点分开。这时候CODE的"逐字符扫描"能力就派上用场了。
思路很直白:把文本拆成单个字符,逐个计算CODE值,找到第一个绝对值小于128的字符位置,这个位置就是第一个"非中文"字符出现的位置。数组公式如下:
=MIN(IF(ABS(CODE(MID(A2,ROW(INDIRECT("1:"&LEN(A2))),1)))<128,ROW(INDIRECT("1:"&LEN(A2)))))拆解一下:
ROW(INDIRECT("1:"&LEN(A2))):生成一个从1到文本长度的序列。比如文本长度是9,这里就生成{1;2;3;4;5;6;7;8;9}。MID(A2,这个序列,1):把每个字符逐个切出来。CODE(...):取每个字符的编码。ABS(...)<128:判断是否是ASCII字符,是则保留该位置序号。MIN:取最小的位置,也就是第一个非中文出现的位置。
拿到位置后,想提取"第一个非中文字符之前的中文部分",就在外层套一个LEFT:
=LEFT(A2, MIN(IF(ABS(CODE(MID(A2,ROW(INDIRECT("1:"&LEN(A2))),1)))<128,ROW(INDIRECT("1:"&LEN(A2))))) - 1)如果你是Excel 365用户,这样的数组公式直接回车就能出结果;但Office 2019及更早版本,必须按Ctrl+Shift+Enter三键确认,否则公式不会按数组方式运算,结果一定是错的。这也是很多人"公式下拉失效"的常见原因之一——不是公式坏,是没按三键。
如果你手里的Excel是2019或365,还可以用TEXTJOIN把"所有中文字符"一次抽出来:
=TEXTJOIN("",TRUE,IF(ABS(CODE(MID(A2,ROW(INDIRECT("1:"&LEN(A2))),1)))>127,MID(A2,ROW(INDIRECT("1:"&LEN(A2))),1),""))这个公式的本质是把每个中文字符筛选出来再用TEXTJOIN拼回去,算是CODE函数的一种"盗火"级用法。要注意TEXTJOIN在2016及更早版本里不存在,用了会报#NAME?错误。
2.4 整列落地:兜底处理与下拉注意事项
公式在单条数据上测试通过后,整列应用一般就是直接下拉。但实战中我强烈建议多做一个"兜底"处理。比如用LENB拆两段式文本时,如果单元格本来就是纯英文,LENB(A2)-LEN(A2)算出来是0,LEFT取0个字符会返回空值,这倒还好;但如果单元格是空的,整套公式都会变成#VALUE!错误。
我常用的兜底写法是:
=IF(LENB(A2)-LEN(A2)=0, A2, LEFT(A2,LENB(A2)-LEN(A2)))意思是:如果中文长度为0,就返回原文本;否则返回中文部分。这样纯英文的记录不会被清空,空单元格也不会一路报错传染下去。整列处理完,再用=TRIM(A2)清理首尾空格,数据就基本干净了。
3. 姓名统计进阶:从"分得出中英文"到"算得清姓氏分布"
3.1 用SUMPRODUCT一键统计中英文人数
单条数据打标签好办,但老板经常问的是"这批名单里中文名有多少个、英文名有多少个"。如果你先逐行拉公式,再用COUNTIF数标签,效率太低,而且中间多出一列辅助数据,后面清理起来也麻烦。
直接用SUMPRODUCT和CODE组合,一个公式出结果:
=SUMPRODUCT(--(ABS(CODE(LEFT(A2:A100,1)))>127))这个公式返回中文姓名的个数。英文姓名个数用同样套路,把大于号换成小于:
=SUMPRODUCT(--(ABS(CODE(LEFT(A2:A100,1)))<128))为什么能这样写?因为LEFT(A2:A100,1)会把整列首字符批量取出来,CODE再批量转编码,ABS和比较运算生成一组TRUE/FALSE逻辑值,双减号"--"强制把它们转成1/0,最后SUMPRODUCT求和就是计数。整个过程不依赖辅助列,一次成型。
有一点必须提醒:如果区域里有空单元格,CODE("")会直接报错。稳妥的做法是加一个排除空值的条件:
=SUMPRODUCT((A2:A100<>"")*(ABS(CODE(LEFT(A2:A100,1)))>127))另外,区域尽量用绝对引用写死,不要写A:A整列引用。整列计算会让SUMPRODUCT在几十万行数据上做无意义扫描,卡到Excel直接转圈圈。
3.2 拆解中文姓名:姓与名的自动切分
中文姓名的结构一般是"姓+单名"或"姓+双名",比如"王芳""王小明"。如果要做进一步的姓名分析,第一步就是把姓和名拆到两个独立字段。
取姓公式:
=LEFT(A2,1)取名公式:
=MID(A2,2,LEN(A2)-1)这里最巧妙的是LEN(A2)-1。它自动适配名字长度:
- "王芳":LEN=2,MID从第2位取1位,得到"芳"。
- "王小明":LEN=3,MID从第2位取2位,得到"小明"。
如果遇到复姓(欧阳、司马、诸葛),单字的"取姓"公式就不够用了。思路是维护一个复姓清单,先判断前两个字是否在复姓表里:
=IF(COUNTIF(复姓表,LEFT(A2,2)),LEFT(A2,2),LEFT(A2,1))COUNTIF函数会返回1或0,配合IF直接判断。现实中复姓名单往往只有几十个,维护成本很低,但能覆盖大多数边界情况。
3.3 姓氏频次统计:排行榜这样生成
统计每个姓氏的人数,是人事、行政、销售场景里的经典需求。做法很简单:先把"姓"提取到辅助列B列,然后去重,再逐个COUNTIF。
核心公式:
=LEFT(A2,1)去重后,统计某个姓氏"王"有多少人:
=COUNTIF(B:B,"王")不想用辅助列?可以直接对原始姓名列做通配符统计:
=COUNTIF(A:A,"王*")通配符"*"代表任意多个字符,"王*"的意思就是"以王开头的所有单元格"。这个写法在处理"张三、王五、王小二"这类数据时非常好用,也是生成姓氏排行榜的基础。
英文姓名的情况不一样,老外习惯"名在前、姓在后",中间用空格隔开。要提取英文姓,先用FIND定位空格位置:
=FIND(" ",A2)然后:
- 英文名(空格前的部分):
=LEFT(A2,FIND(" ",A2)-1) - 英文姓(空格后的部分):
=RIGHT(A2,LEN(A2)-FIND(" ",A2))
FIND是姓名统计里特别重要的辅助函数,它和CODE一起,基本可以覆盖"中文姓名"和"英文姓名"两套完全不同的统计口径。
3.4 中英文姓名混合表的统一统计模板
实际工作中,一张表里中英文姓名混排是最常见的情况。我的做法是做一个统一的处理模板,把姓名类型、姓、名分别拆到独立列,后面用数据透视表还是COUNTIF都随你。
B列判断姓名类型:
=IF(ABS(CODE(LEFT(A2,1)))>127,"中文","英文")C列取"姓",中文取首字,英文取空格后的部分:
=IF(B2="中文",LEFT(A2,1),IF(ISNUMBER(FIND(" ",A2)),RIGHT(A2,LEN(A2)-FIND(" ",A2)),""))D列取"名",中文取剩余部分,英文取空格前的部分:
=IF(B2="中文",MID(A2,2,LEN(A2)-1),IF(ISNUMBER(FIND(" ",A2)),LEFT(A2,FIND(" ",A2)-1),A2))这三列做完,你会发现所有的统计需求都变得异常简单:
- 中文姓氏TOP10:对C列做COUNTIF排序。
- 英文姓名重复率:对D列做分类汇总之类的操作。
- 中英文比例:对B列做透视表。
我之前处理一份两千多人的活动报名表,就是靠这个模板十分钟拆完,然后透视表出所有统计口径。如果没有这套拆列,光是区分中英文姓名就得折腾半天。
4. CODE函数踩坑实录:六个细节让结果差之千里
4.1 只认第一个字符,不认整串文本
CODE函数有一个非常容易让人误会的设定:它只返回"第一个字符"的编码。=CODE("中国")返回的不是"中"和"国"两个字的编码,而是"中"这一个字的编码。如果你想检查文本中每一个字符,就必须借助MID配合ROW(INDIRECT(...))序列逐个取字符,再用SUMPRODUCT或者数组公式汇总。很多人第一次写公式报错或结果不对,八成是没搞清楚这个"首字符限定"。
4.2 负数陷阱:比较前必须加ABS
这是CODE函数新手最容易踩的坑。直接写=CODE("中")>127,结果返回FALSE,因为"中"的编码是个负数,负数当然不大于127。你必须在外面套一层ABS,把它转成正数再跟127比较。可以这么说:所有涉及中文判定的CODE公式,ABS基本是标配。少了ABS,公式看起来逻辑没错,但运行起来全是反的,而且极难排查。
4.3 全角、半角字符会"冒充"中文
全角字母、全角数字、全角标点在存储时也是双字节的,编码绝对值同样大于127。也就是说,=ABS(CODE(LEFT("ABC",1)))>127的结果是TRUE,尽管"A"本质上是英文字母的全角写法。如果你的数据经常从网页或者其他系统粘贴过来,很容易混进全角字符,导致统计口径失真。处理办法是先做规范化:把全角转半角可以用SUBSTITUTE逐字符替换,或者在网上找一段全角半角转换的宏代码。最省事的办法是在公式里加一个前置处理,比如先=TRIM(A2)再去判断。
4.4 不可见字符带来的假英文
从网页、数据库导出的文本,经常自带换行符、制表符等不可见字符。=CODE碰上这些字符,返回的可能是10、9这类很小的ASCII值,于是明明是一个中文单元格,首字符却因为藏着换行符被判成"英文开头"。排查方法很简单:用=CODE(LEFT(A2,1))看看实际返回值,如果是个两位数的小数字,多半就是不可见字符。处理时对原始数据先做一次=CLEAN(A2),把非打印字符清掉,再做后续判断。
4.5 系统区域设置影响返回结果
CODE函数的返回结果和系统当前的区域设置、字符集是绑定的。在简体中文系统上,中文字符返回的是负值或大于127的值;但同样的公式换到英文系统上,中文可能直接被映射成问号等替代字符,返回63,整套"绝对值大于127判中文"的逻辑就失灵了。如果你的Excel文件要跨区域、跨版本共享,严谨的做法是不依赖单一CODE返回值,而是用=UNICODE函数配合固定判断区间,或者提前在不同环境里做一轮验证。
4.6 新版本Excel:用UNICODE函数更规整
Excel 2013及以上版本提供了UNICODE函数,它直接返回字符的Unicode码点,比如=UNICODE("中")返回20013。这是全球统一的编码标准,不随系统区域设置变化。用它做中文判定更干净:
=IF(UNICODE(LEFT(A2,1))>255,"中文","英文")ASCII字符最大127,扩展拉丁字符最大255,而汉字的Unicode码点从19968开始,用255做分界线非常清晰。唯一的问题是老版本Excel(2010及之前)没有UNICODE函数,如果你主要在老旧环境工作,还是得老老实实用CODE加ABS的组合。
5. 组合拳扩展:CODE还能顺手解决这些Excel难题
5.1 快速识别单元格里是否"混入了中文"
除了首字符识别,CODE还能判断整个单元格是否包含中文。方法是用SUMPRODUCT逐字符扫描,只要有任意一个字符的CODE绝对值大于127,就判定包含中文:
=IF(SUMPRODUCT(--(ABS(CODE(MID(A2,ROW(INDIRECT("1:"&LEN(A2))),1)))>127))>0,"含中文","不含中文")这个公式在数据清洗场景里非常有用。比如你有一批产品名要求必须用英文,拿这个公式一扫,混入中文的单元格全部自动标记,比肉眼检查快几个量级。老版本Excel记得三键确认,365版本直接回车。
5.2 检查编号是否以数字、大写字母开头
校验编号、工号、订单号格式时,经常要判断首字符的类型。数字的ASCII码是48到57,大写字母是65到90,小写字母是97到122。三个区间一组合,公式非常直观:
=IF(AND(CODE(A2)>=48,CODE(A2)<=57),"数字开头","非数字开头")想识别"以大写字母开头":
=IF(AND(CODE(A2)>=65,CODE(A2)<=90),"大写字母开头","其他")这类写法本质上就是把CODE函数当成"字符类型探测器",而不仅仅是查编码的工具。很多数据校验需求都能用这个思路秒掉。
5.3 用CHAR反向生成字符序列
既然CODE能取编码,CHAR就能反推字符。这个能力在批量生成测试数据、构造字符表时特别好用。比如在单元格里生成A到Z:
=CHAR(ROW(65:90))如果是365的动态数组,这个公式会直接溢出26个字母;老版本则需要选中纵向的26个单元格,输入公式后按Ctrl+Shift+Enter。同理,小写字母用CHAR(ROW(97:122)),数字0到9用CHAR(ROW(48:57))。我经常用这个技巧生成一个"大小写字母+数字"的全量字符表,然后配合CODE公式反查各种编码规则,两边对照,定位问题特别快。
5.4 与其它方案怎么选:一张表看清楚
做了这么多年数据处理,我觉得有必要把几种常见的中英文分离方案放在一起对比,方便你按自己的环境选:
| 方案 | 核心函数 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 编码判断法 | CODE/UNICODE | 兼容性好,可逐字符判断 | 全角字符会误判,老版本要注意负数 | 分类打标、边界定位、格式校验 |
| 字节测量法 | LENB/LEN | 公式短,算两段式数据极快 | 中英交错或含全角字符时失效 | 中文在前、英文在后的规则文本 |
| TEXTJOIN抽取法 | TEXTJOIN+MID+CODE | 一次抽出所有中文字符 | 需要Excel 2019及以上 | 提取纯中文部分 |
| 正则函数法 | REGEXTEXT等 | 功能最强,能处理复杂交错的文本 | 只有Excel 365新版本支持 | 复杂混排、批量替换 |
| Power Query | M语言/界面操作 | 可视化,适合重复性数据清洗 | 需要另起一个查询步骤,学习成本稍高 | 固定流程的清洗任务 |
我个人现在的习惯是:先看数据结构和版本环境。如果只是给名单打标签,CODE加ABS三秒搞定;如果要做复杂的中英交错提取,直接上Power Query,不在公式里硬杠。CODE函数真正的价值在于它足够轻、足够通用,在90%的日常场景里它都是最快的解法,而且它教给你的是"用编码思维看文本"这个底层能力,这个能力迁移到任何数据处理工具里都不过时。
回到文章开头那个场景——中英文混合的名单、拆不开的备注、理不清的姓名结构。你现在应该有了清晰的思路:判定首字符用CODE加ABS,两段式拆分用LENB加LEN,分类统计用SUMPRODUCT,姓名结构拆解用LEFT加MID加FIND。这套组合拳不依赖任何插件,原生Excel就能跑,学一次用十年,下次再遇到类似的数据,直接抄作业就行。