简介:这是一款面向ArcGIS用户的编号辅助工具,可为mdb、gdb、shp三种常见地理数据格式批量添加顺序编号,适用于地图制图、空间数据管理及分析等场景,帮助GIS操作者免去手工逐个标注的繁琐流程。
资源包共74个文件,主要由32个dll组件、配套的xml配置说明、可执行的exe及config运行配置等构成,压缩后约7.1MB,结构清晰,便于直接调用或二次集成。工具基于ArcGIS官方API开发,依赖Carto、Geodatabase、Geometry等核心库,可直接读取地理数据库与矢量图层,完成字段设置、起始值设定后自动为各要素生成序列号,支持批量处理,也能针对单一图层操作。
该资源目前已有3991人学习下载。对于经常处理地理数据的用户而言,这款小工具能显著减少要素编号的重复劳作,提升数据整理和成图效率,是一份即下即用的轻量级GIS实用工具。
1. ARCGIS编号小工具:看起来只是写个字段,实际却让几十万要素对不上号
做GIS数据处理的人,多半都遇到过这种事:给几百个图斑编流水号,用FID+1凑合一下,结果交付时发现中间删过几条记录、排序也不对,编号全乱套。真正把“ARCGIS编号小工具”当回事,不是因为它能自动填个序号,而是它把“顺序号、组合码、跨图层统一编号”这些业务规则,从手工操作变成了能反复执行的流程——这才是它值得下载的地方。新手用它告别手抖填错,熟手拿它做批处理和入库前的编号校验。本篇按我实际拆过的项目来讲:怎么用字段计算器、怎么写脚本工具、编号规则哪些坑必须提前避开,以及最后怎么验证结果。
2. 字段计算器与Arcade:先解决单图层规则编号
2.1 为什么先推荐从字段计算器入手
对于单图层的顺序编号,最直接的工具就是属性表里的字段计算器。你不需要专门装什么插件,ArcGIS Pro和ArcMap都内置了。对新手来说,理解字段计算器有两个关键点:一个是“解析程序”选什么——Python还是Arcade;另一个是表达式写在哪、变量从哪来。
很多老用户习惯用Python解析,但ArcGIS Pro里推荐优先看Arcade。Arcade的好处是不依赖Python环境,跨产品通用,而且不需要你懂import、函数定义这些前置知识。对纯粹的编号任务,比如“按OBJECTID编号”“按某个字段排序后编号”,Arcade表达式更简洁,也不容易踩Python语法坑。
还有一个常见误解:字段计算器不只是在文本框里写一句!OBJECTID!就完事。表达式的结果类型必须和目标字段类型匹配。目标字段如果是文本型,你得写str(!OBJECTID!);如果是整型,你写!OBJECTID!就行。凡是编号工具翻车的情况,多半是这里先出了问题。
2.2 从零写一个Arcade表达式:零填充与拼接
假设需求是给地块图层生成一个“DL-0001”这种格式的编号,前两位是固定前缀,后面是四位流水号。目标字段是文本型,长度10。Arcade表达式可以这样写:
var prefix = "DL-"; var seq = $feature.OBJECTID; var padded = ""; if (seq < 10) { padded = "000" + seq; } else if (seq < 100) { padded = "00" + seq; } else if (seq < 1000) { padded = "0" + seq; } else { padded = "" + seq; } return prefix + padded;这段表达式的逻辑是按OBJECTID的位数做零填充:小于10补三个0,小于100补两个0,小于1000补一个0。$feature.OBJECTID是Arcade里获取当前要素字段值的标准写法。return语句返回拼接结果,字段计算器会把结果写进目标字段。
参数说明:prefix可以改成你业务里的行政区代码、要素类别码;padded的位数计算逻辑可以抽出来做成函数,但字段计算器里写函数要多几行,对于一次性编号任务,直接if判断更直观。另一个要注意的是:Arcade里$feature必须小写,大小写写反会直接报错。
2.3 用Python解析做同样的编号
有的单位还在用ArcMap,或者团队更习惯Python,那么字段计算器里把解析程序改成Python,表达式换成这样:
rec = !OBJECTID! prefix = "DL-" if rec < 10: pad = "000" + str(rec) elif rec < 100: pad = "00" + str(rec) elif rec < 1000: pad = "0" + str(rec) else: pad = str(rec) return prefix + padPython解析下,字段引用用英文感叹号包起来:!OBJECTID!。str()把数值转成字符串才能做拼接。这里有个容易忽略的细节:字段计算器的Python解析里,变量声明不需要类型关键字,而return可以用,但不是所有版本都支持。老版本里你需要写成prefix + pad作为表达式结果,不写return。我在实际项目里见过有人照抄带return的写法后报语法错误,就是因为版本差异。
参数说明:如果编号位数是固定的,比如统一六位,可以不用if判断,换成str(rec).zfill(6),这个方法会补零到六位。zfill是Python字符串的内置方法,比手写if利落。字段计算器对zfill的支持很稳定,只要确认目标字段是文本型就行。
2.4 按业务字段排序再编号
纯按OBJECTID编号有个隐患:OBJECTID的顺序通常是录入顺序,不一定等于业务上想要的排列。例如你想按“用地面积从大到小”编流水号,直接用OBJECTID就不行。这时可以借助数据排序后的新字段编号,或者用游标在脚本里处理。
字段计算器里处理排序编号比较别扭,我一般会新建一个双精度字段,用“按属性排序”功能给记录排序后,重新计算一个临时序号字段,再把这个临时序号组合进编号。但更稳妥的路线是用下一章的Python脚本工具。排序编号的真正难点不在表达式本身,而在于“本次排序和下次排序结果一致吗”。如果数据在编号后被编辑过,排序就会变,编号也就不稳定了。
3. 用Python脚本工具做编号:多图层与复杂规则的兜底
3.1 什么情况下必须脱离字段计算器
需求一旦超过单图层,字段计算器就不够用了。常见的三类需求是:多个图层统一编号(比如面、线、点共用一套流水号);编号前缀来自另一个图层的属性;编号前需要先做空间查询或者去重。这些逻辑在字段计算器里写不出来,或者写出来也没法复用。我一般会直接写一个Python脚本工具,放在工具箱里,双击就能跑。这也是“ARCGIS编号小工具”这类资源里最硬核的部分。
脚本工具的好处是:参数化输入、能处理多图层、能写循环和判断、还能把编号结果输出成日志文件。缺点是学习曲线稍微陡一点,但对做过几次的人来说,这类脚本完全够用。
3.2 最小可用的脚本工具骨架
下面是一个用arcpy实现的多图层统一编号脚本,按要素类的某个排序字段取流水号,然后把编号写回到指定字段。
import arcpy # 输入参数 target_fc = arcpy.GetParameterAsText(0) # 待编号要素类 order_field = arcpy.GetParameterAsText(1) # 排序字段 code_field = arcpy.GetParameterAsText(2) # 要写入编号的字段 prefix = arcpy.GetParameterAsText(3) # 编号前缀,如 "XZQ-" seq = 1 with arcpy.da.UpdateCursor(target_fc, [order_field, code_field], sql_clause=(None, "ORDER BY " + order_field)) as cursor: for row in cursor: row[1] = prefix + str(seq).zfill(5) cursor.updateRow(row) seq += 1 arcpy.AddMessage("编号完成,共处理 {} 条记录".format(seq - 1))逻辑说明:arcpy.da.UpdateCursor打开要素类,按order_field排序后逐行读取。每行的第二个字段(code_field)被写入prefix + 五位流水号,比如XZQ-00001。sql_clause里的ORDER BY是让游标按指定方式排序的关键,不写这个参数,游标默认按OBJECTID顺序,编号顺序就不受控。seq从1开始,每更新一行自增1。
参数说明:code_field必须是文本型字段,长度要够。假设前缀3个字符、流水号5位,字段长度应至少8。如果字段是短整型或双精度,写入“XZQ-00001”会直接报类型转换错误,或者被截断成数字。建议在脚本开头加一段校验,用arcpy.ListFields检查目标字段类型,不符合就抛出错误提示。
3.3 跨图层统一编号的写法
跨图层的场景通常是一个工作空间里有多个要素类,需要共享一个流水号,不能每个图层都从1开始。处理思路是:先记录全局起始序号,再依次处理每个图层。
import arcpy workspace = arcpy.GetParameterAsText(0) layer_list = arcpy.GetParameterAsText(1).split(";") prefix = arcpy.GetParameterAsText(2) seq_start = int(arcpy.GetParameterAsText(3)) arcpy.env.workspace = workspace seq = seq_start for layer_name in layer_list: fc = workspace + "\\" + layer_name with arcpy.da.UpdateCursor(fc, ["OBJECTID", "CODE"]) as cursor: for row in cursor: row[1] = prefix + str(seq).zfill(6) cursor.updateRow(row) seq += 1 arcpy.AddMessage("全部图层编号完成,全局流水号到 {}".format(seq))参数说明:layer_list用分号分隔多个图层名,是脚本工具里常用的多值参数传递方式。seq_start是自定义起始编号,比如从1000开始。这里默认每个图层的排序都按OBJECTID,如果业务上需要其它排序,同样要加sql_clause。注意处理完后检查各图层CODE字段里是否有重复值,重复往往意味着有要素在游标循环里被漏处理。
3.4 脚本工具的参数配置与调试技巧
在ArcGIS Pro里创建脚本工具时,参数类型设置比代码本身更容易出错。常见做法是:把待编号要素类设为“要素类”类型,排序字段设为“字段”类型并设置“依赖于要素类”属性,编号字段同样设为“字段”并过滤为文本类型。这种方式能避免用户手输字段名时打错字。调试时我习惯先用一个小数据集跑,加一条arcpy.AddMessage输出每条记录的编号结果,确认排序顺序没有问题再放到全量数据上执行。脚本工具里如果用了第三方库,要注意ArcGIS自带的Python环境可能没有安装,建议只在脚本里用arcpy和标准库函数。
4. 编号规则设计:位数、排序与易混字符的代价
4.1 预留位数不是拍脑袋定的
把编号规则设计成一个表,比直接写死更稳。编号通常由区段码、类别码、顺序码拼接而成。比如“P-01-000123”:P代表项目区,01代表地块类别,000123是流水号。设计时需要注意顺序码的位数,一旦流水号超过999,你又只留了三位,编号就会变成“P-01-1000”,顺序码占位被突破,后续排序肯定乱。我一般会按五年内的数据增长量估算,再乘以三作为预留。例如目前年增一万条,预留六位流水号,也就是到999999,足够很长一段时间内的使用。
位数越多越安全吗?不是。位数长了,录入出错的概率也高了,而且有些数据库字段长度有限制。文本型编号字段建议控制在20字符以内,超过这个长度会影响索引和查询性能。中间加分隔符虽然好读,但分隔符一旦统一为“-”,后面做字符串拆分时会省很多事。
4.2 编号里的字母要避开什么
很多编号规则里会混入字母,比如行政区的缩写“A”“B”“C”,或者类别码“XZ”“DL”。字母多了以后,用户手工填写就容易把I和1、O和0、Z和2搞混。设计规则时,最好避开I、O、Z三个字母,只保留A-H、J-N、P-Y这些不易混淆的字符。这也是很多标准编码方案的通行做法。另一个细节是字母大小写:数据库里默认排序可能区分大小写,建议统一用大写,录入时也强制转大写,否则“dl”和“DL”会被当成两种编号。
4.3 排序稳定性为什么决定编号质量
编号一旦写入,它不仅要唯一,还要在后续查询时具备稳定的排序语义。你的编号如果以“区域码+顺序号”拼接,那同区域的记录只需要比较数字部分就能排序。但如果顺序号前面补了0,排序出来是OK的。如果有人把000123录入成123,数字部分变短,排序位置就会出现错位。
ArcGIS的属性表排序是按字符逐位比较的,不是按数字大小。这意味着“P-01-987”会排在“P-01-1000”的前面,因为字符比较从第6位开始,’9’比’1’大。解决方法是统一用零填充,让同段位内数字位数相同。这个规则要在编号工具内部就强制掉,不能让用户自己判断补几个0。
4.4 业务编码与数据库保留字段的关系
在数据库设计层面,建议把编号字段设置为“唯一索引”。但ArcGIS的要素类不具备传统数据库的unique约束,你需要在编号前先做重复检查,或者编号后再跑一遍统计。常见做法是在脚本里用arcpy.Statistics_analysis对编号字段做频率统计,找出计数大于1的值,再单独输出到日志。这个步骤虽然不产生编号,但它是编号工具里不可或缺的一环。另一个和数据库相关的点是:如果字段已经有索引,更新大批量编号时索引会拖慢写入性能,建议在编号前删除索引,编号完成后再重建。
5. 避坑排查:编号错乱、类型截断与重复值
5.1 编号变成科学计数法显示
现象:给双精度字段写入“000123”,结果属性表里显示成123,或者变成1.23E+05这种形式。
原因:目标字段类型是数字型,数字型字段存储时不保留前导零,科学计数法只是显示方式之一;文本型字段才不会丢前导零。
解决:在脚本工具里加入字段类型检查,遇到数字型字段直接报错退出。字段计算器里则把目标字段改成文本型,或者在表达式里拼接一个不可见的字符强制转成字符串。最省心的办法是在创建编号字段时就设成文本型。
5.2 排序后编号乱序
现象:同一个图层跑了两次编号工具,第一次结果看着正常,第二次再跑,流水号顺序却和业务排序不一致。
原因:游标排序的字段值存在并列。例如排序字段是“行政区代码”,同一代码下的几百条记录彼此没有先后顺序,游标每次读取顺序不稳定,编号顺序就变了。
解决:排序字段用复合排序,比如“行政区代码 + 面积”或“行政区代码 + 要素唯一标识”。在sql_clause里写ORDER BY 行政区代码, 面积,保证同代码下也有稳定的先后关系。如果业务上不关心同代码内部顺序,就在编号里直接混排,不要依赖游标读取顺序。
5.3 编号出现重复值
现象:运行脚本后检查编号,发现同一个编号出现在两条记录上,但脚本日志显示处理条数是正确的。
原因:游标更新了部分记录,后续处理因为字段类型错误或事务中断,导致更新没写完;或者多个图层统一编号时,序号起始值设置重叠了。
解决:脚本开头先做唯一性前置检查,脚本结束再跑一次重复值统计。我自己习惯在脚本里加一个简易校验:把所有编号放进一个set,如果长度小于记录数,说明有重复,直接抛出异常。跨图层编号时,起始序号采用“上一个图层末尾值+1”而不是手动输入,可以从源头消掉重叠。
5.4 字段计算器表达式报错:!OBJECTID!无法识别
现象:在ArcMap里写!OBJECTID!提示“字段不存在”,但在ArcGIS Pro里却能跑通。
原因:版本差异。部分ArcMap版本在字段计算器的Python解析下需要先用!引用字段,但旧版对某些系统字段的支持有限;另外如果数据源是CAD或者某些只读格式,系统字段名称可能会变。
解决:先确认数据源类型。如果是个人地理数据库要素类,直接用!OBJECTID!;如果是SHP文件,改成!FID!。最稳的写法是先去属性表里看真实的字段名,复制到表达式里,别靠记忆。
5.5 全角空格与不可见字符导致编号对不上
现象:编号工具跑完,代码里用"DL-0001" in 图层查询,却查不到记录。
原因:编号字段里可能混入了全角空格或制表符,多半是字段值本身带的前后空格,或者表达式拼接时用了从外部复制来的不可见字符。
解决:写入编号前用strip()清理原始字段内容,编号完成后查询也做strip(),两边一致才能命中。排查时全选编号字段导出成文本,用编辑器开启显示空格模式,一眼就能看到问题。
6. 进阶用法:把编号工具封装成可复用流程与自动校验
当编号规则稳定以后,下一步就是把“编号工具”从一次性操作升级成团队可复用的流程。我会把Python脚本工具放到一个专门的文件地理数据库里,工具箱命名为“编号工具.tbx”,脚本参数只暴露要素类、排序字段、编号字段和前綴,其余规则全部固化在代码内部。这样非技术同事双击工具,按提示选数据就能出结果,不需要打开代码编辑器。
配合模型构建器,还能把编号前检查和编号后校验串成一条链:先运行“清空编号字段”脚本,再跑“生成编号”脚本,最后用“查找重复编号”工具输出重复列表。任何一步失败,模型就会停下来,不会留下半截乱的编号。
在实际项目里,我还会给“编号完成”这个节点加上一个统计输出,用arcpy.GetCount_management提取处理前后记录数,打印在工具消息窗口里。如果前后记录数不一致,说明有要素被地理数据库锁定,或者有版本编辑会话没提交。这个时候我不会继续往下做,先检查和修正数据源。
验证编号质量还有一个习惯性动作:把编号结果与原始排序字段做一次相关性检查。简单做法是用排序字段导出前十条记录,人工看编号顺序自然递增;或者写一小段脚本比较“顺序码是否严格递增”。以下是我常用的一段校验代码:
import arcpy fc = arcpy.GetParameterAsText(0) code_field = arcpy.GetParameterAsText(1) codes = [] with arcpy.da.SearchCursor(fc, [code_field]) as cursor: for row in cursor: codes.append(row[0]) sorted_codes = sorted(codes) if codes == sorted_codes: arcpy.AddMessage("编号顺序与排序一致,校验通过") else: arcpy.AddWarning("编号顺序与排序不一致,请检查数据")这段代码把编号字段全部取出,用Python的排序比较结果是否和原顺序一致。如果编号里带混合字符,可能需要在排序前统一用小写或去掉分隔符,否则比较结果没有意义。
从那以后,我每次做编号任务都会强制跑一遍这套流程:先设计规则表,再写脚本工具,最后校验重复和乱序。看起来多花了十分钟,但交付的时候几乎没有再因为编号问题返工过。希望帮到你。
本文还有配套的精品资源,点击获取