Excel 一键生成 GDB|国土建库神器,多工作表批量创建要素类、字段别名、字段默认值
- 2026-09-18 19:59:30
做国土空间、村庄规划、自然资源数据建库,很多同行都有过这样的经历:新建 GDB 之后,要逐个创建要素类,手动添加每一个字段、设置字段别名、配置字段类型、填写字段长度、设置默认值。 一套规划库十几个要素类,几十个字段,纯手工点鼠标,大半天时间就耗没了,还很容易出现字段类型选错、别名漏填、长度设置错误等低级问题,后期质检全部打回返工。
今天分享一套实测落地的 ArcPy 脚本工具 Excel 转 GDB3.0,直接在 Excel 中完成全部库结构配置,一键批量生成文件地理数据库,自动创建要素类、批量建字段、设置别名、配置字段默认值。村庄规划、国土数据治理、专项数据库建库都可以直接复用,大幅减少重复机械操作。
一、真实建库痛点:手动搭建 GDB 有多折磨
自然资源项目建库,我们经常要新建一套标准 FileGDB 数据库。常规手工操作流程:
新建文件地理数据库; 新建每一个要素类,选择几何类型、坐标系; 逐个添加字段,设置字段名、字段类型、字段长度; 手动录入字段中文别名; 部分字段还要配置字段默认值; 重复上面步骤处理下一个要素类。
痛点汇总
要素类多、字段量大,重复点击,耗时久; 人工操作极易出错:字段类型选错、别名遗漏、长度不对; 标准变更之后,要重新手动修改每一个要素类,修改成本高; 不同项目复用库结构,只能复制粘贴,不方便版本管理。
✅Excel 驱动自动化方案把全部库结构写进 Excel:数据库名称、要素类名称、字段名、中文别名、字段类型、字段长度、字段默认值全部在表格维护。运行脚本一键生成完整 GDB,后期标准调整,只需要修改 Excel 表格,重新跑脚本即可。
工具适配环境:ArcGIS10.x(Python2.7),依赖 xlrd 库;ArcGIS Pro 需要调整库与编码语法。
二、脚本核心能力一览
⚠️注意:本脚本只生成库结构(空要素类),只创建表结构,不会导入业务属性数据;适合建库前期搭建标准框架。
三、Excel 模板格式说明
Excel 文件内部工作表分为两部分:
Excel文件名称 第一个工作表:别名映射表用于配置【要素类名称 — 要素类中文别名】,两列,第一列别名,第二列要素类英文名称。脚本读取这张表,给每个生成的要素类设置中文别名。 其余工作表:对应各个要素类每一张 sheet 代表 GDB 中的一个要素类。 序号 字段名称 字段代码 字段类型 字段长度 小数位数 1 标识码 BSM Char 18 2 要素代码 YSDM Char 10 ....
小提示:
字段类型填写 INT 会自动转为 LONG;FLOAT 自动转为 DOUBLE;空值默认为 TEXT 文本; 不需要默认值,F 列留空; 空行、无效行会自动跳过;工作表数据行数≤1 直接跳过该要素类。
四、完整 Python 代码
# -*- coding: utf-8 -*-import xlrdimport arcpyimport osimport sysreload(sys)sys.setdefaultencoding('utf-8')# ========== GET PARAMETERS ==========xls_path = arcpy.GetParameterAsText(0)geometry_type = arcpy.GetParameterAsText(1)spatial_ref_param = arcpy.GetParameterAsText(2)# Validate inputsif not xls_path or not os.path.isfile(xls_path):arcpy.AddError("Invalid Excel file path: {}".format(xls_path))sys.exit(1)if not geometry_type:arcpy.AddError("Geometry type not specified")sys.exit(1)# ========== CREATE FILE GEODATABASE ==========excel_dir = os.path.dirname(xls_path)excel_basename = os.path.splitext(os.path.basename(xls_path))[0]gdb_name = excel_basename + ".gdb"output_gdb = os.path.join(excel_dir, gdb_name)if not arcpy.Exists(output_gdb):try:arcpy.CreateFileGDB_management(excel_dir, gdb_name)arcpy.AddMessage("Created file geodatabase: {}".format(output_gdb))except Exception as e:arcpy.AddError("Failed to create geodatabase: {}".format(str(e)))sys.exit(1)else:arcpy.AddMessage("Using existing geodatabase: {}".format(output_gdb))# ========== HANDLE SPATIAL REFERENCE ==========def prepare_spatial_ref(param):if not param:arcpy.AddWarning("No spatial reference specified, defaulting to WGS84 (4326)")return arcpy.SpatialReference(4326)if ';' in param:param = param.split(';')[0]arcpy.AddMessage("Cleaned spatial reference string (removed suffix)")return paramspatial_ref = prepare_spatial_ref(spatial_ref_param)# ========== READ EXCEL ==========data = xlrd.open_workbook(xls_path)sheet_names = data.sheet_names()if len(sheet_names) == 0:arcpy.AddError("Excel file contains no sheets.")sys.exit(1)# ========== 1. Read alias mapping from first sheet ==========alias_mapping = {}first_sheet_name = sheet_names[0]first_table = data.sheet_by_name(first_sheet_name)arcpy.AddMessage("Reading alias mapping from sheet: '{}'".format(first_sheet_name))arcpy.AddMessage("Total rows in mapping sheet: {}".format(first_table.nrows))start_row = 1 # skip header row (change to 0 if no header)for row_idx in range(start_row, first_table.nrows):row = first_table.row_values(row_idx)if len(row) < 2:continuealias_cell = row[0]name_cell = row[1]if not name_cell:continuealias = unicode(alias_cell).strip() if alias_cell else u''fc_name = unicode(name_cell).strip() if name_cell else u''if fc_name:alias_mapping[fc_name] = aliasarcpy.AddMessage(" Mapping: '{}' -> '{}'".format(fc_name, alias))arcpy.AddMessage("Total mapping entries loaded: {}".format(len(alias_mapping)))# ========== 2. Process remaining sheets ==========arcpy.AddMessage("Start processing " + str(len(sheet_names)-1) + " data sheets")# Helper function to convert default value based on field typedef convert_default_value(value, field_type):"""Convert default value to appropriate type for ArcGIS field."""if value is None or value == '':return None# Convert to unicode string firstvalue_str = unicode(value).strip()if field_type == 'TEXT':return value_strelif field_type == 'LONG':try:# Accept both integer and float stringsreturn int(float(value_str))except:return Noneelif field_type == 'DOUBLE':try:return float(value_str)except:return Noneelif field_type == 'DATE':# Keep as string, ArcGIS will parsereturn value_strelse:return value_strfor idx, sheetname in enumerate(sheet_names[1:], start=2):try:original_sheetname = sheetnameif isinstance(sheetname, unicode):sheetname = sheetname.encode('utf-8')table = data.sheet_by_name(sheetname.decode('utf-8') if isinstance(sheetname, str) else sheetname)if table.nrows <= 1:arcpy.AddWarning("Sheet '{}' has no data rows, skipped.".format(original_sheetname))continueoutput_name = sheetnameoutput_path = os.path.join(output_gdb, output_name)# Step 1: Create empty feature classarcpy.CreateFeatureclass_management(output_gdb, output_name, geometry_type, "", "", "", spatial_ref)arcpy.AddMessage("Created feature class: {}".format(output_name))# Step 2: Add fields and set default valuesfor i in range(1, table.nrows):row = table.row_values(i)if len(row) < 5:continue# Columns (0-based index)field_alias_raw = row[1] if len(row) > 1 else Nonefield_name_raw = row[2] if len(row) > 2 else Nonefield_type_raw = row[3] if len(row) > 3 else Nonefield_length_raw = row[4] if len(row) > 4 else Nonefield_default_raw = row[5] if len(row) > 5 else None # Default value column (F)if not field_name_raw:continuefield_name = unicode(field_name_raw).encode('utf-8').strip().replace(" ", "_")field_type = unicode(field_type_raw).encode('utf-8').upper() if field_type_raw else "TEXT"field_length = int(field_length_raw) if field_length_raw else 50field_alias = unicode(field_alias_raw).encode('utf-8') if field_alias_raw else field_namefield_default = unicode(field_default_raw).strip() if field_default_raw else None# Map type to ArcGIS typesif field_type in ["INT", "INTEGER"]:field_type = "LONG"elif field_type in ["FLOAT", "DOUBLE"]:field_type = "DOUBLE"else:field_type = "TEXT"# Add fieldarcpy.AddField_management(output_path, field_name, field_type, "", "", field_length, field_alias)# Set default value if providedif field_default is not None and field_default != '':# Convert default value according to field typeconverted_default = convert_default_value(field_default, field_type)if converted_default is not None:try:arcpy.AssignDefaultToField_management(output_path, field_name, converted_default)arcpy.AddMessage(" Set default value for '{}': {}".format(field_name, converted_default))except Exception as def_e:arcpy.AddWarning(" Could not set default value for '{}': {}".format(field_name, str(def_e)))else:arcpy.AddWarning(" Invalid default value for field '{}' (type {}): '{}' - skipped".format(field_name, field_type, field_default))# Step 3: Set feature class alias (last step)fc_name_unicode = unicode(output_name) if isinstance(output_name, str) else output_namefc_alias = alias_mapping.get(fc_name_unicode, u'')if fc_alias:try:arcpy.AlterAliasName(output_path, fc_alias)arcpy.AddMessage(" SUCCESS: Set alias '{}' for '{}'".format(fc_alias, output_name))except Exception as alias_e:arcpy.AddWarning(" FAILED to set alias for '{}': {}".format(output_name, str(alias_e)))else:arcpy.AddWarning(" No alias found for feature class name: '{}'".format(fc_name_unicode))arcpy.AddMessage("Completed: " + original_sheetname)except Exception as e:arcpy.AddWarning("Sheet '{}' failed: {}".format(sheetname, str(e)))arcpy.AddMessage("All processing completed. Output geodatabase: {}".format(output_gdb))
五、制作 ArcGIS 脚本工具,零代码运行
把 py 脚本封装成工具箱,不用修改源码,界面填写参数即可运行。
依赖说明:需要 xlrd 库,ArcGIS10.x 环境一般自带;缺少库会报导入失败。
将代码复制到记事本,保存,后缀修改为 .py;ArcGIS 目录窗口,右键文件夹 →【新建】→【工具箱】; 工具箱右键【添加】→【脚本】; 填写工具名称、标签、描述,选择 py 脚本文件; 配置 3 个脚本输入参数:
点击完成,工具制作完毕。
💡小技巧:右键工具箱选择【导入脚本】,把 py 脚本嵌入工具箱,拷贝给同事也可以直接打开运行。
运行逻辑:
选择 Excel 文件,设置几何类型、坐标系,点击确定; 脚本执行,在 Excel 所在文件夹自动生成同名.gdb; 查看 ArcGIS 结果消息窗口,看哪些要素类成功、哪些警告报错。
六、高频踩坑与避坑指南
坑 1:ImportError: No module named xlrd
现象:运行直接报错找不到 xlrd。解决:ArcGIS10.x 默认自带,如果缺失,需要给 ArcGIS 内置 Python 环境安装 xlrd 库。
坑 2:中文乱码、别名设置失败
脚本基于 Python2.7,Excel 尽量另存为
.xls格式;xlsx 格式部分版本 xlrd 读取会出现中文异常。优先使用 xls。
坑 3:要素类已经存在会怎么样
脚本不会自动删除原有要素类!如果 GDB 里面已经有同名要素类,再次运行会报错。
实操建议:测试阶段,直接删除旧 GDB,重新运行脚本生成全新库结构。
坑 4:字段默认值设置失败
检查默认值和字段类型匹配,数字类型不要填写中文文本;文本字段可以填写中文默认值。不合法默认值脚本会给出警告并跳过,不会中断整体流程。
坑 5:ArcGIS Pro 无法直接运行
脚本是 Python2.7 语法,Pro 是 Python3;reload(sys)、sys.setdefaultencoding、unicode()这些语法在 Python3 不存在,需要改写;xlrd 读取 excel 也需要适配,Pro 用户需要做代码改造。
坑 6:脚本只生成空库结构
⚠️划重点:脚本只搭建库框架,不会导入业务数据。生成空要素类之后,再把业务数据追加进来。
七、项目落地工作流推荐
自然资源建库完整流程:
根据项目建库标准,整理 Excel 配置模板:要素类、字段名、别名、字段类型、默认值; 使用本脚本一键生成标准 FileGDB 空库框架; 导入业务矢量数据,Append 追加进对应要素类; 执行修复几何、拓扑检查、属性校验,完成建库。
拓展价值:不同项目只要维护不同 Excel 模板,就可以快速生成对应标准 GDB,建库标准变更,只修改 Excel 表格即可,版本管理非常方便。
【文末小结】
Excel 转 GDB 脚本,把国土建库从手工点点鼠标,转变为表格驱动,批量创建要素类、字段、别名、字段默认值; 环境适配 ArcGIS10.x Python2.7,优先使用 xls 格式 Excel;Pro 需要做语法改造;依赖 xlrd 库; 脚本只生成空库结构,不导入业务矢量数据;已有同名要素类需要手动删除,避免报错; 可以封装为工具箱,不懂 Python 代码也能直接运行,库标准修改只维护 Excel 表格; 适合村庄规划、自然资源专项库、数据治理项目前期快速搭建数据库框架。
📌不想自己复制代码、手动一步步添加脚本到工具箱的朋友,可以关注公众号,后台回复 GDB 获取已经封装好的工具包 + 配套 Excel 配置模板 + 原版Python 代码,下载即可直接使用。