这是一个基于字段计算的工具。
有时候我们会遇到一些混杂着各种中文、英文、数字、特殊符号的文字,这个工具的目的是从这些复杂文字中提取出想要的特定文字。
比如说从CAD测绘图中可以读取到类似【混3】、【砖2】的文字,如果想要从中提取出层数或结构,就可以用这个工具实现。
一、要实现的功能
如上图所示,点击【提取特定文字】工具,选择地图内的要素图层或独立表,再选择要处理的包含复杂文字的字段和要输出结果的字段,再选择提取模式,点击执行即可。
执行结果如下:
有点像字段计算器计算的结果,实际上用字段计算器也能实现上面的效果,有兴趣的可以看一下这一篇文章:Arcgis小技巧【10】——字段计算器的简单用法和示例
二、实现流程
首先要从当前选择的图层或独立表中获取【Table】,作为后续字段计算的载体。
因为选择的可能是要素图层或者独立表,写了一个通用方法,考虑的比以前要多一些。
// 从图层获取Table
public static Table GetTableFromLayer(string fcPath)
{
// 判断是否选择了图层
if (fcPath == "")
{
MessageBox.Show("请选择一个要素图层或表");
return null;
}
// 根据图层名找到当前图层
var map = MapView.Active.Map;
var init_featurelayer = map.FindLayers(fcPath);
var init_table = map.FindStandaloneTables(fcPath);
// 判断当前选择的是要素图层还是独立表
if (init_featurelayer.Count == 0)
{
// 是独立表的情况
StandaloneTable init_layer = map.FindStandaloneTables(fcPath)[0];
return init_layer.GetTable();
}
if (init_table.Count == 0)
{
// 是要素图层的情况
FeatureLayer init_layer = map.FindLayers(fcPath)[0] as FeatureLayer;
return init_layer.GetTable();
}
return null;
}
获取到【Table】之后,就可以通过游标进行字段计算了:
await QueuedTask.Run(() =>
{
// 获取所选图层的所有字段
var tb = ToolManager.GetTableFromLayer(layer_path);
// 字段计算
using (ArcGIS.Core.Data.Table table = tb)
{
using (RowCursor rowCursor = table.Search(null, false))
{
TableDefinition tableDefinition = table.GetDefinition();
while (rowCursor.MoveNext())
{
using (Row row = rowCursor.Current)
{
// 获取输入字段的值
var value_in = row[field_in].ToString();
// 提取特定文字
row[field_out] = ToolManager.GetWord(value_in, model);
// 保存
row.Store();
}
}
}
}
});
这里的ToolManager.GetWord(value_in, model)方法就是最核心的代码了,主要是通过正则表达式来实现:
// 提取特定文字【model包括:中文、英文、数字、特殊符号】
public static string GetWord(string txt_in, string model = "中文")
{
string chinesePattern = "[\u4e00-\u9fa5]"; // 匹配中文字符的正则表达式
string englishPattern = "[a-zA-Z]"; // 匹配英文字符的正则表达式
string digitPattern = @"\d"; // 匹配数字的正则表达式
string specialCharPattern = @"[^a-zA-Z0-9\u4e00-\u9fa5\s]"; // 匹配特殊符号的正则表达式
string txt = "";
if (model == "中文")
{
Regex chineseRegex = new Regex(chinesePattern);
txt = ExtractMatches(txt_in, chineseRegex);
}
else if (model == "英文")
{
Regex englishRegex = new Regex(englishPattern);
txt = ExtractMatches(txt_in, englishRegex);
}
else if (model == "数字")
{
Regex digitRegex = new Regex(digitPattern);
txt = ExtractMatches(txt_in, digitRegex);
}
else if (model == "特殊符号")
{
Regex specialCharRegex = new Regex(specialCharPattern);
txt = ExtractMatches(txt_in, specialCharRegex);
}
return txt;
}
// 正则匹配
public static string ExtractMatches(string input, Regex regex)
{
string result = "";
MatchCollection matches = regex.Matches(input);
foreach (Match match in matches)
{
result += match.Value;
}
return result;
}
核心代码并不长,正则表达式之前在python中用过,这次在c#中实现,基本差不多,还是很好用的。
三、工程文件分享
最后,放上工程文件的链接:
GetWordhttps://pan.baidu.com/s/1IJ6qDrMKcZqWCsPceAy5bA?pwd=y1vyPS:可以直接点击...bin\Debug\net6.0-windows\下的.esriAddinX文件直接安装。