属性映射经常用于属性表或Excel表的赋值,比如按用地用海表对规划用地的用地编码或用地名称赋值,将汇总好的用地指标表赋值给已经制好的Excel模板等。
下面试着在ArcGIS Pro SDK中实现功能上述这两个功能。
一、Excel表格映射到属性表Table
1、要实现的效果
如上图所示,打开【Excel表格映射到Table】工具框,选择输入的要素图层,如【规划用地】,接着输入参照字段和映射字段,最后打开用来映射的Excel表,注意这里打开的Excel表是到【sheet】级的。
点击执行,效果如下:
生成结果中,映射字段会按照映射表的对应键值一一赋值,如果参照字段不在映射表中,则不赋值。
2、实现流程
这里主要是采用几个GP工具【连接字段、计算字段】来实现的,核心步骤和代码如下:
首先需要获取Excel表中的2个表头,即字段名:
// 参数获取string map_tabel = textExcelPath.Text;string in_data = combox_fc.Text;string in_field = combox_bmField.Text;string map_field = combox_bmField_Copy.Text;// 获取连接表的2个字段名string exl_field01 = GetCellFromExcel(map_tabel, "A1");string exl_field02 = GetCellFromExcel(map_tabel, "B1");List<string> fields = new List<string>() { exl_field02 };// 从Excel文件中获取Cellvaluepublic static string GetCellFromExcel(string excelPath, string range){// 建立 Excel 应用程序对象Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();// 获取Excel文件名和表名List<string> files = DecomposeExcel(excelPath);string excel_name = files[0];string sheet_name = files[1];// 打开 Excel 文件Workbook workbook = excelApp.Workbooks.Open(excel_name);// 获取工作表Worksheet worksheet = workbook.Worksheets[sheet_name];// 获取单元格string Cellvalue = worksheet.Range[range].Value.ToString();// 保存并关闭 Excel 文件和应用程序对象workbook.Close(true);excelApp.Quit();// 返回valuereturn Cellvalue;}
这里还调用了一个方法【DecomposeExcel】,用于把输入的Excel文件分解为文件名和表名,代码如下:
// 分解Excel的文件名和表名public static List<string> DecomposeExcel(string excelPath){// 设置空列表List<string> list = new List<string>();// 获取最后一个"\"的位置int index = excelPath.LastIndexOf("\\");// 获取exl文件名string excel_name = excelPath.Substring(0, index);// 获取表名string sheet_name = excelPath.Substring(index + 1, excelPath.Length - index - 2);// 将exl文件名和表名加入列表list.Add(excel_name);list.Add(sheet_name);// 返回列表return list;}
然后调用GP工具【连接字段】,以参照字段为连接字段,将Excel表连接至属性表中:
// 连接字段JoinField(in_data, in_field, map_tabel, exl_field01, fields);// 连接字段public static async void JoinField(string in_data, string in_field, string join_table, string join_field, List<string> fields, bool isOutput = false){// 设置默认GPExecuteToolFlagsGPExecuteToolFlags executeFlags = GPExecuteToolFlags.AddToHistory;if (isOutput){executeFlags = GPExecuteToolFlags.AddToHistory | GPExecuteToolFlags.AddOutputsToMap;}// 执行GP工具var par_JoinField = Geoprocessing.MakeValueArray(in_data, in_field, join_table, join_field, fields, "NOT_USE_FM", "");await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.JoinField", par_JoinField, null, null, null, executeFlags));}
调用GP工具【计算字段】,将连接到属性表里的目标字段赋值给属性表里的映射字段:
// 计算字段CalculateField(in_data, map_field, "!" + exl_field02 + "!");// 计算字段public static async void CalculateField(string in_data, string field, string expression, bool isOutput = false){// 设置默认GPExecuteToolFlagsGPExecuteToolFlags executeFlags = GPExecuteToolFlags.AddToHistory;if (isOutput){executeFlags = GPExecuteToolFlags.AddToHistory | GPExecuteToolFlags.AddOutputsToMap;}// 执行GP工具var par_CalculateField = Geoprocessing.MakeValueArray(in_data, field, expression, "PYTHON3", "", "", "NO_ENFORCE_DOMAINS");await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.CalculateField", par_CalculateField, null, null, null, executeFlags));}
赋完值,顺便还可以删掉连接进来的字段。
以上便实现了将Excel表格映射到Table的功能。
二、属性表Table映射到Excel表格
1、要实现的效果
如上图所示,打开【Table映射到Excel表格】工具框,选择要赋值的Excel表,输入参照列和映射列(例子中是第1列和第2例),然后输入表格Table(例子里是一个汇总统计表),再输入参照字段和映射字段。
点击执行,效果如下:
生成结果中,Excel表格会根据汇总表的值进行填写,如果汇总表中没有相应的参照字段,则不会填写。
这个工具用处是很多的,例如生成【用地用海表,村庄结构功能表……】等一系列表格。
2、实现流程
第一步要从属性表Table中将对应的键值提取出来,输出一个字典,方便后面使用:
// 参数获取string map_tabel = combox_table.Text;string in_field = combox_bmField_in.Text;string map_field = combox_bmField_map.Text;string excelPath = textExcelPath.Text;int sheet_in_col = int.Parse(txtbox01.Text);int sheet_map_col = int.Parse(txtbox02.Text);// 将映射属性表中获取字典DictionaryDictionary<string, string> dict = await QueuedTask.Run(() => GetDictFromTable(map_tabel, in_field, map_field));// 从Table中获取Dictionarypublic static async Task<Dictionary<string, string>> GetDictFromTable(string in_table, string in_field_01, string in_field_02){Dictionary<string, string> dict = new();// 根据图层名找到当前图层var map = MapView.Active.Map;StandaloneTable initlayer = map.FindStandaloneTables(in_table)[0];await QueuedTask.Run(() =>{using (ArcGIS.Core.Data.Table table = initlayer.GetTable()){using (RowCursor rowCursor = table.Search(null, false)){TableDefinition tableDefinition = table.GetDefinition();while (rowCursor.MoveNext()){using (Row row = rowCursor.Current){// 获取valuevar key = row[in_field_01].ToString();var value = row[in_field_02].ToString();// 如果没有重复key值,则纳入dictif (!dict.Keys.Contains(key)){dict.Add(key, value);}}}}}});return dict;}
获取用来映射的字典后,就可以打开Excel文件进行赋值了。同样的,这里还是要先把Excel文件名进行一个分解:
// 建立 Excel 应用程序对象Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();// 获取Excel文件名和表名List<string> files = DecomposeExcel(excelPath);string excel_name = files[0];string sheet_name = files[1];// 打开 Excel 文件Workbook workbook = excelApp.Workbooks.Open(excel_name);// 获取工作表Worksheet worksheet = workbook.Worksheets[sheet_name];// 获取Excel表格中的数据,将特定列作为值for (int row = 1; row <= worksheet.UsedRange.Rows.Count; row++){// 获取对照值string in_value = worksheet.Cells[row, sheet_in_col].Value.ToString();// 赋值if (dict.Keys.Contains(in_value)){worksheet.Cells[row, sheet_map_col].Value = dict[in_value];}}// 保存并关闭 Excel 文件和应用程序对象workbook.Close(true);excelApp.Quit();
以上便实现了将Table映射到Excel表格的功能。
完整代码可以查看文章末尾放出的工程文件。
三、工程文件分享
最后,放上工程文件的链接:
AttributeMapperhttps://pan.baidu.com/s/1J79C5Qr7ClEyq5mrf12I9g?pwd=dqpjPS:可以直接点击...bin\Debug\net6.0-windows\下的.esriAddinX文件直接安装。