• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

ArcGIS Pro二次开发(25)属性映射

武飞扬头像
规划GIS会
帮助1

属性映射经常用于属性表或Excel表的赋值,比如按用地用海表对规划用地的用地编码或用地名称赋值,将汇总好的用地指标表赋值给已经制好的Excel模板等。

下面试着在ArcGIS Pro SDK中实现功能上述这两个功能。


一、Excel表格映射到属性表Table

1、要实现的效果

学新通如上图所示,打开【Excel表格映射到Table】工具框,选择输入的要素图层,如【规划用地】,接着输入参照字段和映射字段,最后打开用来映射的Excel表,注意这里打开的Excel表是到【sheet】级的。

点击执行,效果如下:

学新通

生成结果中,映射字段会按照映射表的对应键值一个一个地赋值,如果参照字段不在映射表中,则不赋值。

2、实现流程

这里主要是采用几个GP工具【连接字段、计算字段】来实现的,核心步骤和代码如下:

首先需要获取Excel表中的2个表头,即字段名:

  1.  
     
  2.  
    // 参数获取
  3.  
    string map_tabel = textExcelPath.Text;
  4.  
    string in_data = combox_fc.Text;
  5.  
    string in_field = combox_bmField.Text;
  6.  
    string map_field = combox_bmField_Copy.Text;
  7.  
    // 获取连接表的2个字段名
  8.  
    string exl_field01 = GetCellFromExcel(map_tabel, "A1");
  9.  
    string exl_field02 = GetCellFromExcel(map_tabel, "B1");
  10.  
    List<string> fields = new List<string>() { exl_field02 };
  11.  
     
  12.  
    // 从Excel文件中获取Cellvalue
  13.  
    public static string GetCellFromExcel(string excelPath, string range)
  14.  
    {
  15.  
    // 建立 Excel 应用程序对象
  16.  
    Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
  17.  
    // 获取Excel文件名和表名
  18.  
    List<string> files = DecomposeExcel(excelPath);
  19.  
    string excel_name = files[0];
  20.  
    string sheet_name = files[1];
  21.  
    // 打开 Excel 文件
  22.  
    Workbook workbook = excelApp.Workbooks.Open(excel_name);
  23.  
    // 获取工作表
  24.  
    Worksheet worksheet = workbook.Worksheets[sheet_name];
  25.  
     
  26.  
    // 获取单元格
  27.  
    string Cellvalue = worksheet.Range[range].Value.ToString();
  28.  
     
  29.  
    // 保存并关闭 Excel 文件和应用程序对象
  30.  
    workbook.Close(true);
  31.  
    excelApp.Quit();
  32.  
    // 返回value
  33.  
    return Cellvalue;
  34.  
    }
学新通

这里还调用了一个方法【DecomposeExcel】,用于把输入的Excel文件分解为文件名和表名,代码如下:

  1.  
    // 分解Excel的文件名和表名
  2.  
    public static List<string> DecomposeExcel(string excelPath)
  3.  
    {
  4.  
    // 设置空列表
  5.  
    List<string> list = new List<string>();
  6.  
    // 获取最后一个"\"的位置
  7.  
    int index = excelPath.LastIndexOf("\\");
  8.  
    // 获取exl文件名
  9.  
    string excel_name = excelPath.Substring(0, index);
  10.  
    // 获取表名
  11.  
    string sheet_name = excelPath.Substring(index 1, excelPath.Length - index - 2);
  12.  
    // 将exl文件名和表名加入列表
  13.  
    list.Add(excel_name);
  14.  
    list.Add(sheet_name);
  15.  
    // 返回列表
  16.  
    return list;
  17.  
    }
学新通

然后调用GP工具【连接字段】,以参照字段为连接字段,将Excel表连接至属性表中:

  1.  
    // 连接字段
  2.  
    JoinField(in_data, in_field, map_tabel, exl_field01, fields);
  3.  
     
  4.  
    // 连接字段
  5.  
    public static async void JoinField(string in_data, string in_field, string join_table, string join_field, List<string> fields, bool isOutput = false)
  6.  
    {
  7.  
    // 设置默认GPExecuteToolFlags
  8.  
    GPExecuteToolFlags executeFlags = GPExecuteToolFlags.AddToHistory;
  9.  
    if (isOutput)
  10.  
    {
  11.  
    executeFlags = GPExecuteToolFlags.AddToHistory | GPExecuteToolFlags.AddOutputsToMap;
  12.  
    }
  13.  
    // 执行GP工具
  14.  
    var par_JoinField = Geoprocessing.MakeValueArray(in_data, in_field, join_table, join_field, fields, "NOT_USE_FM", "");
  15.  
    await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.JoinField", par_JoinField, null, null, null, executeFlags));
  16.  
    }
学新通

调用GP工具【计算字段】,将连接到属性表里的目标字段赋值给属性表里的映射字段:

  1.  
    // 计算字段
  2.  
    CalculateField(in_data, map_field, "!" exl_field02 "!");
  3.  
    // 计算字段
  4.  
    public static async void CalculateField(string in_data, string field, string expression, bool isOutput = false)
  5.  
    {
  6.  
    // 设置默认GPExecuteToolFlags
  7.  
    GPExecuteToolFlags executeFlags = GPExecuteToolFlags.AddToHistory;
  8.  
    if (isOutput)
  9.  
    {
  10.  
    executeFlags = GPExecuteToolFlags.AddToHistory | GPExecuteToolFlags.AddOutputsToMap;
  11.  
    }
  12.  
    // 执行GP工具
  13.  
    var par_CalculateField = Geoprocessing.MakeValueArray(in_data, field, expression, "PYTHON3", "", "", "NO_ENFORCE_DOMAINS");
  14.  
    await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.CalculateField", par_CalculateField, null, null, null, executeFlags));
  15.  
    }
学新通

赋完值,顺便还可以删掉连接进来的字段。

以上便实现了将Excel表格映射到Table的功能。


二、属性表Table映射到Excel表格

1、要实现的效果

学新通如上图所示,打开【Table映射到Excel表格】工具框,选择要赋值的Excel表,输入参照列和映射列(例子中是第1列和第2例),然后输入表格Table(例子里是一个汇总统计表),再输入参照字段和映射字段。

点击执行,效果如下:

学新通

生成结果中,Excel表格会根据汇总表的值进行填写,如果汇总表中没有相应的参照字段,则不会填写。

这个工具用处是很多的,例如生成【用地用海表,村庄结构功能表……】等一系列表格。

2、实现流程

第一步要从属性表Table中将对应的键值提取出来,输出一个字典,方便后面使用:

  1.  
    // 参数获取
  2.  
    string map_tabel = combox_table.Text;
  3.  
    string in_field = combox_bmField_in.Text;
  4.  
    string map_field = combox_bmField_map.Text;
  5.  
    string excelPath = textExcelPath.Text;
  6.  
    int sheet_in_col = int.Parse(txtbox01.Text);
  7.  
    int sheet_map_col = int.Parse(txtbox02.Text);
  8.  
     
  9.  
    // 将映射属性表中获取字典Dictionary
  10.  
    Dictionary<string, string> dict = await QueuedTask.Run(() => GetDictFromTable(map_tabel, in_field, map_field));
  11.  
     
  12.  
    // 从Table中获取Dictionary
  13.  
    public static async Task<Dictionary<string, string>> GetDictFromTable(string in_table, string in_field_01, string in_field_02)
  14.  
    {
  15.  
    Dictionary<string, string> dict = new();
  16.  
    // 根据图层名找到当前图层
  17.  
    var map = MapView.Active.Map;
  18.  
    StandaloneTable initlayer = map.FindStandaloneTables(in_table)[0];
  19.  
    await QueuedTask.Run(() =>
  20.  
    {
  21.  
    using (ArcGIS.Core.Data.Table table = initlayer.GetTable())
  22.  
    {
  23.  
    using (RowCursor rowCursor = table.Search(null, false))
  24.  
    {
  25.  
    TableDefinition tableDefinition = table.GetDefinition();
  26.  
    while (rowCursor.MoveNext())
  27.  
    {
  28.  
    using (Row row = rowCursor.Current)
  29.  
    {
  30.  
    // 获取value
  31.  
    var key = row[in_field_01].ToString();
  32.  
    var value = row[in_field_02].ToString();
  33.  
    // 如果没有重复key值,则纳入dict
  34.  
    if (!dict.Keys.Contains(key))
  35.  
    {
  36.  
    dict.Add(key, value);
  37.  
    }
  38.  
    }
  39.  
    }
  40.  
    }
  41.  
    }
  42.  
    });
  43.  
    return dict;
  44.  
    }
学新通

获取用来映射的字典后,就可以打开Excel文件进行赋值了。同样的,这里还是要先把Excel文件名进行一个分解:

  1.  
    // 建立 Excel 应用程序对象
  2.  
    Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
  3.  
     
  4.  
    // 获取Excel文件名和表名
  5.  
    List<string> files = DecomposeExcel(excelPath);
  6.  
    string excel_name = files[0];
  7.  
    string sheet_name = files[1];
  8.  
    // 打开 Excel 文件
  9.  
    Workbook workbook = excelApp.Workbooks.Open(excel_name);
  10.  
    // 获取工作表
  11.  
    Worksheet worksheet = workbook.Worksheets[sheet_name];
  12.  
     
  13.  
    // 获取Excel表格中的数据,将特定列作为值
  14.  
    for (int row = 1; row <= worksheet.UsedRange.Rows.Count; row )
  15.  
    {
  16.  
    // 获取对照值
  17.  
    string in_value = worksheet.Cells[row, sheet_in_col].Value.ToString();
  18.  
    // 赋值
  19.  
    if (dict.Keys.Contains(in_value))
  20.  
    {
  21.  
    worksheet.Cells[row, sheet_map_col].Value = dict[in_value];
  22.  
    }
  23.  
    }
  24.  
    // 保存并关闭 Excel 文件和应用程序对象
  25.  
    workbook.Close(true);
  26.  
    excelApp.Quit();
学新通

以上便实现了将Table映射到Excel表格的功能。

完整代码可以查看文章末尾放出的工程文件。


三、工程文件分享

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

AttributeMapper学新通https://pan.百度.com/s/1J79C5Qr7ClEyq5mrf12I9g?pwd=dqpjPS:可以直接点击...bin\Debug\net6.0-windows\下的.esriAddinX文件直接安装。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgbigei
系列文章
更多 icon
同类精品
更多 icon
继续加载