【ArcGIS Pro二次开发】(55):给多个要素或表批量添加字段

在工作中可能会遇到这样的场景:有多个GDB要素、表格,或者是SHP文件,需要给这个要素或表添加相同的多个字段。

在这种情况下,手动添加就变得很繁琐,于是就做了这个工具。

需求具体如下图:

左图是待处理数据,有shp文件也有gdb文件。

右图是待添加字段的属性结构描述表,有4个参数,【字段名称、字段别名、字段类型、字段长度】。

(文件格式为Excel,文章末尾的下载链接会附上示例Excel)

工具的执行流程为:依次为左图待处理的数据添加右图定义好的字段。


一、要实现的功能

如上图所示,点击【字段处理】组【字段综合】面板下的【添加字段(批量)】工具。

在弹出的工具框中,分别输入参数:

1、包含要素或表格的文件夹。这里可以支持SHP文件和GDB文件,但不支持MDB。

2、包含字段属性的Excel表。这个表格的格式是固定的,在后面的工具链接里,我会将其一块共享,可自行下载,在此基础上修改可以少些错误。

E列的说明性文字只是查看用的,不会参与工具的计算(可以删掉)。这里列出6个字段类型格式,除此之外的类型文字是不认的。

3、关键字筛选。这是可选填的,如果你只想处理包含"规划"文字的要素和表,可以在关键字里输入。如果想全部处理,就可以不填任何文字。

最后点击执行即可,生成结果如下(以单个为例):


二、实现流程

第一步,从Excel表中获取字段的参数,返回双层List。

cs 复制代码
                    // 获取字段属性结构表
                    List<List<string>> list_field_attribute = new List<List<string>>();
                    // 建立 Excel 应用程序对象
                    Application excelApp = new Application();
                    // 打开 Excel 文件
                    Workbook workbook = excelApp.Workbooks.Open(excel_path);
                    // 获取工作表
                    var worksheet = workbook.Worksheets[1];
                    // 获取总行数
                    int row_count = worksheet.UsedRange.Rows.Count;
                    // 获取字段属性
                    for (int i = 3; i < row_count; i++)
                    {
                        // 获取字段属性
                        string mc = worksheet.Cells[i, 1].Value.ToString();               // 字段名称
                        string bm = worksheet.Cells[i, 2].Value.ToString();              // 字段别名
                        string field_type = worksheet.Cells[i, 3].Value.ToString();           // 字段类型
                        string lenth = worksheet.Cells[i, 4].Value.ToString();              // 字段长度
                        // 加入
                        list_field_attribute.Add(new List<string> { mc, bm, field_type, lenth });
                    }

第二步,从输入的文件夹中获取所有要素类和表。

首先是shp文件的情况:

cs 复制代码
        // 获取输入文件夹下的所有文件
        public static List<string> GetAllFiles(string folder_path, string key_word ="no match")
        {
            List<string> filePaths = new List<string>();

            // 获取当前文件夹下的所有文件
            string[] files = Directory.GetFiles(folder_path);
            // 判断是否包含关键字
            if (key_word == "no match")
            {
                filePaths.AddRange(files);
            }
            else
            {
                foreach (string file in files)
                {
                    // 检查文件名是否包含指定扩展名
                    if (System.IO.Path.GetExtension(file).Equals(key_word, StringComparison.OrdinalIgnoreCase))
                    {
                        filePaths.Add(file);
                    }
                }
            }

            // 获取当前文件夹下的所有子文件夹
            string[] subDirectories = Directory.GetDirectories(folder_path);

            // 递归遍历子文件夹下的文件
            foreach (string subDirectory in subDirectories)
            {
                filePaths.AddRange(GetAllFiles(subDirectory, key_word));
            }

            return filePaths;
        }

要获取gdb文件下要素和表,首先要获取gdb文件:

cs 复制代码
        public static List<string> GetAllGDBFilePaths(string folderPath)
        {
            List<string> gdbFilePaths = new List<string>();
            DirectoryInfo directoryInfo = new DirectoryInfo(folderPath);

            // 检查文件夹是否存在
            if (!directoryInfo.Exists)
            {
                throw new DirectoryNotFoundException("指定的文件夹路径不存在!");
            }

            // 查找所有GDB数据库文件(.gdb文件夹)
            DirectoryInfo[] gdbDirectories = directoryInfo.GetDirectories("*.gdb", SearchOption.AllDirectories);
            foreach (DirectoryInfo gdbDirectory in gdbDirectories)
            {
                // 获取GDB数据库的路径
                string gdbPath = gdbDirectory.FullName.Replace(@"/", @"\");

                // 添加到列表中
                gdbFilePaths.Add(gdbPath);
            }

            return gdbFilePaths;
        }

再从GDB文件下获取所有要素类和表:

cs 复制代码
        // 获取数据库下的所有要素类的完整路径
        public static List<string> GetFeatureClassPath(string gdb_path)
        {
            List<string> result = new List<string>();
            // 打开GDB数据库
            using Geodatabase gdb = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(gdb_path)));
            // 获取所有要素类
            IReadOnlyList<FeatureClassDefinition> featureClasses = gdb.GetDefinitions<FeatureClassDefinition>();
            foreach (FeatureClassDefinition featureClass in featureClasses)
            {
                using (FeatureClass fc = gdb.OpenDataset<FeatureClass>(featureClass.GetName()))
                {
                    // 获取要素类路径
                    string fc_path = fc.GetPath().ToString().Replace("file:///", "").Replace("/", @"\");
                    result.Add(fc_path);
                }
            }

            return result;
        }

        // 获取数据库下的所有独立表的完整路径
        public static List<string> GetTablePath(string gdb_path)
        {
            List<string> result = new List<string>();
            // 打开GDB数据库
            using Geodatabase gdb = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(gdb_path)));
            // 获取所有独立表
            IReadOnlyList<TableDefinition> tables = gdb.GetDefinitions<TableDefinition>();
            foreach (TableDefinition tableDef in tables)
            {
                using (Table table = gdb.OpenDataset<Table>(tableDef.GetName()))
                {
                    // 获取要素类路径
                    string fc_path = table.GetPath().ToString().Replace("file:///", "").Replace("/", @"\");
                    result.Add(fc_path);
                }
            }
            return result;
        }

获取所有输入要素和表后,即可添加字段:

【obj_all】为获取的所有要素和表的路径,【list_field_attribute】为获取的字段属性结构列表。

cs 复制代码
                    // 添加字段
                    foreach (var ob in obj_all)
                    {
                        string target_name = ob[ob.LastIndexOf(@"\")..];
                        // 如果不含关键字,直接添加字段
                        if (key_word != "")
                        {
                            foreach (var fa in list_field_attribute)
                            {
                                Arcpy.AddField(ob, fa[0], fa[2], fa[1], int.Parse(fa[3]));
                            }
                        }
                        else
                        {
                            // 如果含有关键字,筛选出含关键字的部分,再添加字段
                            if (target_name.Contains(key_word))
                            {
                                foreach (var fa in list_field_attribute)
                                {
                                    Arcpy.AddField(ob, fa[0], fa[2], fa[1], int.Parse(fa[3]));
                                }
                            }
                        }
                    }

以上便是工具实现的核心代码。


三、工具文件分享

我把工具都集合成工具箱,不再单独放单个工具,可以到这里下载完整工具箱,会不断更新:

【ArcGIS Pro二次开发】:CC工具箱https://blog.csdn.net/xcc34452366/article/details/131506345PS:可以直接点击...bin\Debug\net6.0-windows\下的.esriAddinX文件直接安装。

相关推荐
DXM05217 小时前
牟乃夏《ArcGIS Engine地理信息系统开发教程》学习笔记2
开发语言·javascript·笔记·学习·arcgis·ae
pianmian12 天前
arcgis几何与游标(2)
arcgis
GIS思维2 天前
一键解锁Landsat 9地表温度计算!ENVI与ArcGIS Pro全流程详解(无需NASA大气校正)
arcgis pro·envi·landsat9·地表温度计算
limit00752 天前
免费下载地图切片数据以及通过CesiumEarth在Windows和安卓本地浏览
低代码·3d·arcgis·web3·安卓
朗道十戒3 天前
在ArcGIS Pro中将栅格NoData值修改为特定值
python·arcgis
leichangqing3 天前
macos下 ragflow二次开发环境搭建
macos·二次开发·ragflow
create_right4 天前
CAD导入arcgis中保持面积不变的方法
arcgis
Chh07154 天前
[特殊字符] 第十四讲 | 空间异质性检验与地统计局部指标(LISA)应用
arcgis·数据分析·r语言
limit00756 天前
CesiumEarth能够本地浏览的三维倾斜模型切片(3DTiles)
chrome·低代码·arcgis·web3·旅游
DXM05216 天前
牟乃夏《ArcGIS Engine地理信息系统开发教程》学习笔记1
开发语言·经验分享·笔记·学习·arcgis·c#·arcgis engine