【ArcGIS Pro二次开发】(23):用地编码和用地名称的规范性检查

在国空或村庄规划的编制过程中,随着规划用地的调整,经常会手动修改用地编码和用地名称,不可避免的会出现错误,如果单靠人工校对,累人又不能保证准确性。这个工具的目的就是检查用地编码和用地名称是否规范,二者是否一一对应。


一、要实现的功能

如上图所示,右键点击地图中的要素图层,点击【检查用地用海字段】按钮,打开工具框,选择图层的用地编码字段和用地名称字段,点击运行即可。

运行结果如下图:

要素会新增一个【用地用海检查】字段,用地编码和用地名称的规范性错误会列在字段里。


二、实现流程

创建ProWindow工具框等基础功能可以参看往期文章,这里只把实现核心功能的流程列举出来。

1、通过嵌入的Excel资源文件获取用地用海分类

在往期的文章用到一种方法,使用【字典(Dictionary)创建表格(Table)】来获取用地用海分类。这个方法有点麻烦,需要编辑字典,遇上复杂的表格不好操作。

这里采用另一个方法,使用嵌入式的文件的方式,直接从Excel文件中读取。

首先需要将Excel文件的生成操作设置为【嵌入的资源】,然后从资源中读取。

我这里不采用直接读取的方式,为了保险一点(可能没有必要),先把资源里的文件复制到本地,再从本地读取,代码如下:

            // 复制资源文件
            string folder = Project.Current.HomeFolderPath;
            string excelPath = @"用地用海_DM_to_MC.xlsx";
            string outputPath = System.IO.Path.Combine(folder, excelPath);  
            string resourceName = @"CheckFieldYDYH." + excelPath;    

            // 获取当前程序集的实例
            Assembly assembly = Assembly.GetExecutingAssembly();
            // 从嵌入资源中读取文件
            using (Stream stream = assembly.GetManifestResourceStream(resourceName))
            {
                // 创建目标文件
                using (FileStream fileStream = new FileStream(filePath, FileMode.Create))
                {
                    // 将文件从嵌入资源复制到目标文件
                    stream.CopyTo(outputPath );
                }
            }

在这个案例中,我们要读取Excel文件的内容是第一列和第二列的值,并将其输出成一个字典(Dictionary)即可。

代码如下:

            // 建立 Excel 应用程序对象
            Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
            // 打开 Excel 文件
            Workbook workbook = excelApp.Workbooks.Open(excelPath);
            // 获取工作表
            Worksheet worksheet = workbook.Worksheets[1];
            // 定义字典
            Dictionary<string, string> dict = new Dictionary<string, string>();
            // 获取Excel表格中的数据
            for (int row = 1; row <= worksheet.UsedRange.Rows.Count; row++)
            {
                string key = worksheet.Cells[row, col1].Value.ToString();
                string value = worksheet.Cells[row, col2].Value.ToString();
                dict.Add(key, value);
            }
            //  保存并关闭 Excel 文件和应用程序对象
            workbook.Close(true);
            excelApp.Quit();

至此,就实现了从Excel资源文件中读取数据并输出为字典(Dictionary)。

2、将目标字段值中的空值【null】转换为【空字符串】

下一步正常就该开始编辑属性表,但为了保证数据计算安全,这里再做了一件事,将2个目标字段值中的空值【null】转换为【空字符串】,这也是被空值坑过多次之后,我现在几乎都会做这个预处理。代码如下:

            // 获取所选图层的所有字段
            var fields = await QueuedTask.Run(() =>
            {
                return initlayer.GetFieldDescriptions();
            });

            // 使用异步任务在后台进行编辑操作
            await QueuedTask.Run(() =>
            {
                // 打开要素图层的表格
                var table = initlayer.GetTable();
                // 定位到属性表的游标
                using (var tableCursor = table.Search(null, false))
                {
                    while (tableCursor.MoveNext())
                    {
                        // 获取当前记录的值
                        var row = tableCursor.Current;
                        // 历数所有字段
                        foreach (var field in fields)
                        {
                            // 排除不可编辑的字段
                            if (field.IsReadOnly == false)
                            {
                                // 如果是字符串类型,则进行下一步
                                if (field.Type == FieldType.String)
                                {
                                    var currentValue = row[field.Name];
                                    if (currentValue is null)
                                    {
                                        currentValue = "";
                                    }
                                    // 更新该字段的值
                                    row[field.Name] = currentValue;
                                    row.Store(); // 保存修改
                                }
                            }
                        }
                    }
                }
            });

3、新建检查字段,并通过属性表编辑计算字段值

新建一个【用地用海检查】字段,打开当前选择的的要素图层的属性表进行编辑。

计算逻辑如下:

1)分别针对2个字段,通过【new List<string>(dict.Keys).Contains(bm)】判断该字段值是否在用地用海分类的规范命名范围内,如果不在范围内,刚输出错误信息。

2)如果2个字段都满足规范,则通过【dict[bm.ToString()] != mc.ToString()】判断用地编码和用地名称是否一一对应,如果有误,则输出错误信息。

3)最后给【用地用海检查】字段赋值即可。

            // 使用异步任务在后台进行编辑操作
            await QueuedTask.Run(() =>
            {
                // 打开要素图层的表格
                var table = initlayer.GetTable();
                // 定位到属性表的游标
                using (var tableCursor = table.Search(null, false))
                {
                    while (tableCursor.MoveNext())
                    {
                        // 获取当前记录的值
                        var row = tableCursor.Current;
                        var bm = row[bm_field];
                        var mc = row[mc_field];
                        // 定义错误信息文字
                        string err = "";
                        // 设置一个flag:是否符合规范
                        bool isOK = true;
                        // 检查编码字段
                        if (new List<string>(dict.Keys).Contains(bm) == false)
                        {
                            err += "BM错误;";
                            isOK = false;
                        }
                        // 检查名称字段
                        if (new List<string>(dict.Values).Contains(mc) == false)
                        {
                            err += "MC错误;";
                            isOK = false;
                        }
                        // 检查编码和名称是否一一对应
                        if (isOK)
                        {
                            if (dict[bm.ToString()] != mc.ToString())
                            {
                                err += "BM和MC不匹配";
                            }
                        }
                        // 检查字段赋值
                        row["用地用海检查"] = err;
                        row.Store();
                    }
                    this.Close();
                    MessageBox.Show("字段值更新完成!");
                }
            });

三、工程文件分享

 最后,放上工程文件的链接:

CheckFieldYDYHhttps://pan.baidu.com/s/1aumM78dtntI5an6HVl3owg?pwd=i3qd

PS:可以直接点击...bin\Debug\net6.0-windows\下的.esriAddinX文件直接安装。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

规划GIS会

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值