资讯动态

ArcGIS编号工具实战:字段计算器与ArcPy脚本实现顺序编号

发布时间:2026/10/18 17:45:17 来源:尧图企业网站定制
简介这款ARCGIS编号小工具专为地理信息系统GIS用户打造解决mdb、gdb和shp三类常见数据格式的要素顺序编号问题适用于批量管理地理要素、快速生成标识码等场景。资源包共74个文件包含32个dll、32个xml、4个config、4个exe和2个manifest大小约7.1MBdll多为ESRI.ArcGIS核心组件如Geodatabase、Geometry、Carto等xml为配置说明exe是可直接运行的主程序。依托ArcGIS API实现地理数据库读写与几何对象处理用户可自定义编号字段和起始值对图层进行批量或定向更新省去手动录入的繁琐环节。已有3991人学习下载适合从事数据分析、地图制图与空间规划的GIS工作者能有效提升数据预处理效率属于即下即用的实用桌面工具。1. 为什么 ArcGIS 里编个号也要专门做个小工具做过一次外业图斑的应该都有体会数据采集完、属性表填完要打印附图时才发现编号根本没到位。我见过 A同学对着几千行要素手动下拉填充填到一半复制错行整张图的编号全乱也见过某开发者用字段计算器直接FID1出来全是负数。编号这事看着简单实际上它决定了后面制图、出表、入库、接边每道工序能不能对上号。与其每次现想方案不如把一套「顺序编号→断号检查→重复校验」的流程固定下来。这个 ARCGIS 编号小工具解决的就是这件事在 ArcGIS 里给矢量数据做可重复、可检查、可交付的顺序编号覆盖新手能直接跑的字段计算器方案也覆盖熟手需要的 ArcPy 脚本与断号排查。下面从最常用的字段计算器说起再到脚本批处理和避坑全程按我平时落地的顺序来写。2. 字段计算器快编十分钟搞定顺序编号先确认三个前提2.1 顺序编号的核心思路seq() 与自增变量字段计算器是很多人第一个接触的编号工具但真用起来十个里有八个翻车。常见做法是在表达式框里写FID 1这个思路在简单情况下能用可一旦你删过数据、做过筛选FID 中间就有空洞编号会断而且 FID 在编辑会话里可能根本不连续。真正稳定的做法是给字段计算器一个记忆变量让它自己记住上次编到几。ArcGIS 字段计算器左侧的预逻辑脚本代码框里可以写一小段 Python右侧表达式框调用它。最常见的写法是# 预逻辑脚本代码框里定义 tick 0 def seq(): global tick tick tick 1 return tick# 表达式框里调用 seq()这段逻辑的关键在于tick是模块级变量字段计算器对每条记录执行一次表达式时这个变量不会重置所以每次调用seq()都会比上次大 1。和FID1的根本区别是它不依赖数据本身的行号而是从 0 开始自己计数删过行也不会断号。用的时候有几个参数要确认。第一字段类型必须是短整型或长整型如果你拿文本字段跑这个表达式返回的整数会被自动转成字符串通常没问题但如果你对格式有要求得在脚本里先做格式化。第二右侧表达式框里只要写seq()这几个字符不要把def seq():也抄进去。第三跑之前确认这个图层没有启动编辑器或者启动了编辑器但还没保存因为编号写进属性表后如果编辑器里回滚你可能会误以为脚本写错了。2.2 前缀、区段和小数位把编号编成能直接打印的格式实际制图时没有人想要光秃秃的 1、2、3。图斑编号通常是BX-2024-001这种组合前缀区分项目区年份区分批次三位数保证排序。字段计算器完全能做这件事只要把表达式从纯数字改成字符串拼接。# 预逻辑脚本代码框 tick 0 def bh(prefix, year): global tick tick tick 1 return {0}-{1}-{2:03d}.format(prefix, year, tick)# 表达式框里调用 bh(BX, 2024){2:03d}是 Python 格式化语法里的位数控制03d表示至少三位、不足补零所以第 1 条会编成BX-2024-001第 12 条是BX-2024-012。这个写法比先编完数字再手动加前缀省很多事而且打印的时候排序规则很友好001 一定排在 002 前面。但这里有一个隐藏很深的坑如果你用的是按属性选择后的选择集字段计算器默认是对全表执行不是只算选中的要素。很多人选中 50 个图斑跑完发现整个图层 1000 个要素全被编了号。解决方法是提前把选中要素导出成一个新图层在导出后的图层上跑编号编完再替换回去或者在 ArcGIS Pro 里把计算器右上角的应用范围明确改成仅所选要素。另外如果你的数据源是企业级地理数据库SDE里的版本化图层字段计算器常常报字段不可编辑或对象被锁定我一般不会在这种图层上直接跑编号而是先导出到文件地理数据库再处理。还有一个容易被忽略的前提条件编号字段不能有重复值约束。如果字段上建了唯一索引而表里已经有几条脏数据占用了编号跑一半会直接报错中止前面的编号还留在表里。所以用字段计算器之前先确认目标字段是空的、没建唯一索引或者先做一次重复值清理。三个前提总结下来非 SDE 版本化数据、目标字段类型正确且为空、计算范围理解清楚。满足这三条字段计算器方案是最快的一招。3. ArcPy 重排编号把一次手工操作变成可重跑的工序3.1 用 UpdateCursor 做全表重排字段计算器适合小数据量、一次性编号。但当图层有几千上万个要素或者你需要在不同批次数据间来回重跑手工点计算器就不够看了。ArcPy 脚本可以把这个过程变成一个可重复执行的工序双击运行、输入参数、拿到结果。重排编号最常用的接口是arcpy.UpdateCursor或者arcpy.da.UpdateCursor后者速度更快也更接近现代写法。import arcpy fc rC:\project\data.gdb\parcels # 目标要素类 sort_field OBJECTID # 排序依据字段 number_field BH # 要写入编号的字段 # 关键技术点先收集排序好的 OBJECTID 列表再按这个列表逐条更新 order [row[0] for row in arcpy.da.SearchCursor(fc, [OBJECTID], sql_clause(None, ORDER BY sort_field))] i 1 with arcpy.da.UpdateCursor(fc, [OBJECTID, number_field]) as cursor: for oid, _ in cursor: if oid in order: cursor.updateRow([oid, i]) i 1这里花了我不少时间才想明白一个逻辑UpdateCursor遍历要素时返回顺序在多数情况下是按 OBJECTID但严格说游标的结果顺序不是官方保证的一旦你有过滤器、连接或视图顺序就可能是乱的。所以我先用SearchCursor配 SQL 的ORDER BY生成一个排好序的 OBJECTID 列表然后在更新游标里逐个对比。这种方法牺牲了一点点内存但顺序绝对可控。参数上要注意两处。第一sql_clause的第二个元素必须是字符串元组格式(None, ORDER BY 字段名)前一个元素是 WHERE 子句不需要就写None。第二i是 Python 整数如果你目标字段是文本型cursor.updateRow传整数进去会自动转字符串但建议你提前统一类型避免长整型字段写入了超过字段精度的值。3.2 加前缀、留位数把编号标准化成 BX-2024-001全表重排只解决了顺序问题实际交付时你通常还需要带上项目标识和位数控制。ArcPy 脚本里做这件事比字段计算器更直观因为所有格式逻辑都写在明面上下次换需求改一处就行。import arcpy fc rC:\project\data.gdb\parcels prefix BX # 项目前缀按需更换 year 2024 # 批次年份 sort_field OBJECTID number_field BH order [row[0] for row in arcpy.da.SearchCursor(fc, [OBJECTID], sql_clause(None, ORDER BY sort_field))] i 1 with arcpy.da.UpdateCursor(fc, [OBJECTID, number_field]) as cursor: for oid, _ in cursor: if oid in order: bh {0}-{1}-{2:03d}.format(prefix, year, i) cursor.updateRow([oid, bh]) i 1这段代码的逻辑和第 2 章的计算器表达式一致但好处是它不受编辑会话选择集这些交互状态影响双击跑就完事。常见做法是把这份脚本存成.py文件在 ArcGIS 自带的 Python 环境里用命令行执行python renumber.py跑之前要检查几个参数fc的路径如果是要素类直接写到要素类如果是文件地理数据库里的数据集路径写法是gdb路径\数据集名\要素类名。sort_field一般用 OBJECTID 就行但如果你希望按行政区代码排序后再编号把ORDER BY后面的字段换成那个字段。有一点要注意如果多个要素的排序字段值相同它们的相对顺序是不确定的所以需要再加一个字段做次级排序写成ORDER BY 字段1, 字段2。这套脚本我通常会多设计一个起始编号参数因为有些项目要求从上一批的末尾继续编而不是每批都从 1 开始。把这个参数暴露成变量用i start_number初始化就行。另外脚本跑完不会像字段计算器那样弹窗告诉你编了多少条所以末尾最好加一句print(编号完成共重排 %d 条要素 % (i - start_number))方便在命令行里确认结果。4. 断号与重复检查提交成果前那段必须跑的校验4.1 断号检测脚本把要打印的号段拉出来扫一遍编号编完了制图也没问题但最怕的是提交时发现中间断了号。图斑删除、筛选遗漏、字段计算器半途报错都会造成看着有序、实际有洞的情况。断号在属性表里很难一眼看出尤其是三位数以上的编号。我一般会在提交前跑一段独立的断号检查脚本它不修改任何数据只输出缺失的号段。import arcpy fc rC:\project\data.gdb\parcels fields [BH] existing set() with arcpy.da.SearchCursor(fc, fields) as cursor: for row in cursor: if row[0] is not None: existing.add(str(row[0])) # 从编号中提取数字部分BK-2024-001 - 1 numbers [] for val in existing: parts str(val).split(-) try: numbers.append(int(parts[-1])) except ValueError: continue missing [] for i in range(1, max(numbers) 1): if i not in numbers: missing.append(i) print(缺号数量:, len(missing)) print(缺号列表:, missing[:100])这段脚本的原理是先把全部编号收集成一个集合然后从编号字符串里切出最后一段数字做一个 1 到最大值的全量对比。集合去重天然解决了重复问题——如果某个编号重复出现集合里只有一个但断号校验会因此漏掉重复项所以重复检查要单独写一段别混在一起。参数上要注意的是分隔符。我用的是 BMP 短横线-如果你的编号用的是下划线或点号记得改split的参数。另一种常见情况是纯数字编号不带前缀那parts[-1]取到的还是数字本身逻辑不受影响只是int()转换前最好加一层strip()去掉空格。4.2 重复号与超长号一起查清楚断号检查只解决有没有洞重复号是另一个问题而且更隐蔽。很多项目提交时要求编号唯一但如果表里有两行要素都编成了BX-2024-001断号检查根本发现不了因为 1 这个数字在集合里只出现一次看起来是连续的。所以我对每个编号工具包都会附带一段重复与长度检查脚本一次性把三类问题列出来。import arcpy from collections import Counter fc rC:\project\data.gdb\parcels fields [BH] vals [] with arcpy.da.SearchCursor(fc, fields) as cursor: for row in cursor: if row[0] is not None: vals.append(str(row[0])) counter Counter(vals) dups {k: v for k, v in counter.items() if v 1} print(重复编号:, dups) too_long [v for v in set(vals) if len(v) 15] print(超长编号:, too_long)这里的 Counter 是 Python 标准库的计数工具dups字典的键就是重复的编号值是出现次数。超长编号的判断标准取决于你的字段长度——如果编号字段是文本型且宽度只有 20而编号本身有 18 位看起来能放下但打印时字体稍大就会溢出图框。我一般把长度阈值设成字段宽度的 80%留出余量。这两段脚本可以合并成一个check_number.py文件跑完会同时输出缺号、重复、超长三类信息。如果三项都为空打印结果干净到只有一行检查通过这是我最喜欢的输出。如果发现问题就回到第 3 章的重排脚本再跑一次然后重新检查直到通过。这套流程不复杂但能挡掉很多交付后才发现的尴尬。5. 避坑记录编号工具最常见的五个翻车现场5.1 科学计数法长整型编号变成了 1.0000E10现象字段计算器编完序号打开属性表发现编号显示成1.2345678901E10排序全乱。原因目标字段是浮点型或双精度Python 整数写入浮点字段后被自动转成科学计数法显示或者编号整体超过了短整型的上限 32767字段自动溢出。解决编号字段务必用长整型或文本型不要用浮点型。如果已经建好字段先新建一个长整型字段跑编号跑完再删除旧字段如果必须保留原字段名可以用 ArcPy 的AlterField改属性但更省事的做法是删掉重建。5.2 选择集没生效只给选中要素编号结果全表都被改了现象在某图层上按行政区框选了一批图斑只想给这批编BX-2024-001起的号字段计算器跑完发现整个图层的 2000 个要素全部被编了号。原因字段计算器默认范围是所有记录选择集是否符合预期取决于版本和界面选项很多版本根本不认选择集。解决在 ArcGIS Pro 里打开计算器前先在应用下拉框里选择仅所选要素或者在 Arcmap 里先执行arcpy.SelectLayerByAttribute_management把选中要素导出成临时图层再跑。用脚本方案则天然规避这个问题因为重排脚本只处理传入的fc不会误伤其他数据。5.3 编辑器没保存退出后编号全部回滚现象开着编辑会话编完号看着属性表里一切正常关闭工程时弹窗提示保存随手点了不保存第二天打开数据编号全没了。原因字段计算器在某些版本里如果编辑器处于开启状态写入属于编辑操作必须显式保存编辑才能落盘。解决跑编号前先看 ArcGIS 界面顶部有没有保存编辑按钮有就先停掉编辑会话脚本方式不受影响因为 ArcPy 的UpdateCursor走的是自提交事务关闭游标即生效。我个人的习惯是跑完脚本后再打开属性表抽查三五个要素确认值已经写入再关工程这个习惯救过我很多次。5.4 删除图斑后不重排现象某项目初期编了 300 个号后来外业复核删掉 20 个无效图斑剩下的编号变成 1、2、4、5、7打印附图时缺号明显。原因删除要素不会自动触发编号重排编号只是属性值不是行号。解决交付前强制跑一次断号检查脚本发现缺号就运行重排脚本把剩余的要素重新从 1 开始编号。这里有个经验重排前先跟下游确认有没有其他表通过编号关联如果有关联表也要同步更新否则编号一变外业调查表就对不上了。5.5 版本化图层直接改编号失败现象SDE 里的要素类跑 ArcPy 脚本编号时报Editing may not be performed in this environment但同一个脚本在文件地理数据库上跑得好好的。原因企业级地理数据库的版本化图层有独立的事务和锁机制需要先注册版本并启动编辑会话ArcPy 裸脚本默认进不了版本化编辑环境。解决不要在版本化图层上直接跑编号。常见做法是把数据复制或导出到文件地理数据库编号完成后通过truncate append或者 ArcGIS 的数据加载工具写回去。如果必须在 SDE 里改就用 ArcGIS Pro 的编辑会话手动跑字段计算器或者用arcpy.da.Editor包一层编辑会话但那个复杂度已经不划算了。6. 把编号工具封装成脚本工具参数怎么设才能让外业同事也敢点6.1 三个核心参数与脚本骨架命令行脚本在你自己机器上好用但交给不懂代码的同事双击.py文件往往换来一句闪了一下啥也没发生。所以我会把重排脚本封装成 ArcGIS Pro 的脚本工具Script Tool把可变的地方全部暴露成工具参数别人只需要在弹窗里选图层、填前缀、点确定。核心参数就三个不要贪多参数名类型是否必填说明目标要素类要素图层是可以是图层名或要素类路径从下拉框选排序字段字段是默认 OBJECTID也可选行政区代码等起始编号长整型否默认 1续编号时填上一批的末位 1把脚本参数接进来需要在脚本里用arcpy.GetParameterAsText接收界面值再把之前硬编码的路径和变量替换成参数import arcpy fc arcpy.GetParameterAsText(0) sort_field arcpy.GetParameterAsText(1) start_number int(arcpy.GetParameterAsText(2) or 1) order [row[0] for row in arcpy.da.SearchCursor(fc, [OBJECTID], sql_clause(None, ORDER BY sort_field))] i start_number with arcpy.da.UpdateCursor(fc, [OBJECTID, BH]) as cursor: for oid, _ in cursor: if oid in order: cursor.updateRow([oid, i]) i 1 arcpy.AddMessage(编号完成共处理 %d 条要素 % (i - start_number))要点有两个。第一工具面板里把目标要素类的参数类型设为要素图层这样用户可以从内容列表直接选择图层不会填错路径排序字段设成字段类型后ArcGIS 会自动给一个下拉列表限制用户只能选你指定的字段。第二脚本里原来写死的number_field BH没有暴露成参数原因是这个字段在多数项目里是统一约定暴露出去反而增加选错字段的概率改字段名时直接改脚本源码就好。6.2 输出验证与重跑习惯工具封装完成不代表可以无脑点。我会在工具执行的最后加一段校验逻辑跑完编号后立即调一次断号检查函数如果检查出缺号直接给红色警告图标而不是让用户自己去查。这个习惯来自一次真实教训——脚本确实跑完了但排序字段里有空值导致部分要素被排到末尾编号出现空洞而界面显示已完成用户信以为真。从那以后我每次给新图层做编号都会强制走一遍先备份要素类→跑重排工具→跑断号检查→抽查三五个要素看格式确认无误再进入出图流程。这个流程看着多花五分钟实际上挡住过好几次返工。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑