arcmap field calculator

ArcMap中,无论是在属性框中右击字段打开的field Calculate还是在Arctoolbox\Data Management Tools\Field\ 工具箱中的Calculate field ,都支持vba表达式。

字段计算器,用以计算字段值。这些字段值,可以是属性表里相关字段的综合,比如百分比,分解字段等;可以是和图形有关的值,比如点的xy坐标,面的中心点坐标,线的长度等等;也可以是为了满足某种特定需求而创造出来的值。

比如如下问题:
1.要找出图层某字段[A]里的重复值,并标上记号;
2.图层某字段[B],现在要将字段[B]中的 { 最大值 + 最小值 + 该行值 } 写入一个新字段[C]中;
3.字段[D]需要进行编号,号码格式为"000001","000002","000003","000004"...,"000202"..

4 .将点层的xy坐标按 x , y 的格式输出到 [E] 字段

1.重复记录标上记号
要找出图层某字段的重复记录,对于存储在Personal Geodatabasefeature而言,可以通过select by attribute找出重复值的记录:
              Sql: select * from layer where:
[A] in (select [A] from 层名 group by [A] having count([A]) >1)
这样执行下来的结果,就是该图层中,[A]字段值重复数大于等于2的所有记录,而对于不支持子查询的比如shapefile格式文件,可以怎么办呢?在属性表中新建一个字段,取名"test',类型设置为 long integer,然后右击该字段,选择field Calculate,勾选 advanced,写入以下代码:
' ----------------------------------------
' ESRI Support Home > Knowledge Base > Technical Articles > Article Detail 
' 代码参见 HowTo:  Identify duplicate field values
' @ Tsonghua 090924
' ----------------------------------------

Static d As Object 
Static i As Long 
Dim iDup As Integer 
Dim sField 
' ----------------------------------------
'这里填写需要检查的字段名
sField = [A] 
' ----------------------------------------
If (i = 0) Then 
Set d = CreateObject("Scripting.Dictionary") 
End If 
If (d.Exists(CStr(sField))) Then 
iDup = 1 
Else 
d.Add CStr(sField), 1 
iDup = 0 
End If 
i = i + 1
Pre_Logic VBA Script Code下方的 A= 窗口中填iDup
这是一段在ESRI Support(www.support.esri.com)上找到的代码,功能就是可以讲重复值做上记号,属于重复值的记录,[test]字段值计算结果为 1 ,否则为 0 。就是说,如果有三条记录[A]字段值分别为"aa","aa","aa",那么有一条被标上 0 ,剩余2条被标上 1 

对重复记录做了记号,如何处理,就可以随心所欲啦。这算是一个为了满足某种需求,而重新新建字段,并计算其值的例子
2.计算 [B].max + [B].min + [B]
这个问题,就是根据属性表里其他字段来重新提取所需要的信息进行组合。
这个例子,是在论坛上看到有人问的问题。同样,去ESRI的支持中心去搜了一下,找到了如下代码:
' ----------------------------------------
' ESRI Support 
' Author Christian Degrassig
' @ Tsonghua 090924
' ----------------------------------------
Dim pMxDoc As IMxDocument
Dim pFLayer As IFeatureLayer
Dim pData As IDataStatistics

Dim pCursor As ICursor
Dim pStatResults As IStatisticsResults

Static lngFlag as long
Dim lngLayerIndex as long
Dim strFieldName as string

'因为不清楚你的字段类型,所以这里设置三个变量类型为 Variant
Static varZMax as Variant
Static varZMin as Variant
Dim varVal as Variant

if lngFlag = 0 then
'1.注:这里填你需要取最大最小值的字段名
strFieldName = "B"  

'2.这里设置你需要计算字段值的图层所在图层索引号
'TOC中,从上至下,第一层 LayerIndex=0,第二层 为 1,以此类推..
'这里 LayerIndex值是第二个需要设置的地方 
lngLayerIndex = 0
Set pMxDoc = ThisDocument
Set pFLayer = pMxDoc.FocusMap.Layer(lngLayerIndex)
Set pCursor = pFLayer.Search(Nothing, False)
Set pData = New DataStatistics
pData.Field = strFieldName
Set pData.Cursor = pCursor
Set pStatResults = pData.Statistics
varZMax = pStatResults.Maximum 
varZMin = pStatResults.Minimum
lngFlag = 1
End If
'3.这里,第三个数请双击上面fields框中的对应字段
varVal= varZMax + varZMin + [B]
同样,在 "C =" 的框框中填入 varVal

字段计算器里,不管是一般的赋值表达式抑或是advanced里写的较复杂的表达式,其实都是在每一行运行一次,对该记录进行赋值运算。因此,如果需要将某参数值传递下去的话,可以用" static 参数 as 类型 "这样的参数声明方式,"Dim 参数 as 类型"的声明方式,只是在进行某条记录赋值的时候有效,一旦结束,参数值被清空。

例如,如果想对某字段赋值为 1234… 可以用如下赋值表达式:
Static i as long
Dim a as string
a=i+1
i=i+1
__esri_field_calculator_splitter__
a
' 注:__esri_field_calculator_splitter__ 是分割标志,具体的可以在field Calculate中写一个表达式,然后点击 save ,保存的文件是 ".cal"格式,可以用记事本打开编辑。对于一个经常用的表达式,可以写好之后保存("save")起来,下次使用的时候,只需要点"Load"加载过 来即可对比,
dim i as long
Dim a as string
a=i+1
i=i+1
__esri_field_calculator_splitter__
a

对比发现,用 static 方式声明的结果是 1234… 而用 dim方式声明的结果是 1111也就是说,dim声明的参数 ifield Calculate逐行运行的过程中,没有把参数值传递下去。

回过头来分析一下这段重新分析字段,获取最大值,最小值来组成新字段值的问题

if lngFlag = 0 then
'1.注:这里填你需要取最大最小值的字段名
strFieldName = "自定义的字段名"  

'2.这里设置你需要计算字段值的图层所在图层索引号
'TOC中,从上至下,第一层 LayerIndex=0,第二层 为 1,以此类推..
'这里 LayerIndex值是第二个需要设置的地方 
lngLayerIndex = 0
Set pMxDoc = ThisDocument
Set pFLayer = pMxDoc.FocusMap.Layer(lngLayerIndex)
Set pCursor = pFLayer.Search(Nothing, False)
Set pData = New DataStatistics
pData.Field = strFieldName
Set pData.Cursor = pCursor
Set pStatResults = pData.Statistics
varZMax = pStatResults.Maximum 
varZMin = pStatResults.Minimum
lngFlag = 1
End If
这段是解决问题的关键所在,它在field Calculate对第一行记录赋值的时候,已经对整层进行统计并获取了最大值pStatResults.Maximum 储存在参数 varZMax中,同时把获取的最小值pStatResults.Minimum 存在参数 varZMin中。因为对整层该字段的赋值过程中,只需要获取一次最大值最小值即可,因此这里做了个标志- - -lngFlag。一旦最大最小值获取完成,就让 lngFlag值为 1,以后的逐行赋值中,不再进行统计,而直接使用参数 varZMaxvarZMin的值。

最后一行 varVal= varZMax + varZMin + [待计算字段名]这就很简单了,直接进行加减运算。

3.按照需求对字段[D]编号

有了上面两则例子的提示,这里不难分析,其实只需要先按要求生成 1234… 然后对其格式标准化(也就是让字段长度一致,不足的补零)

参照如下代码:
' ----------------------------------------
'rec_Number_ConstantLengthString.cal
'Author: Ianko Tchoukanski
'http://www.ian-ko.com
' @ Tsonghua  090924
' ----------------------------------------
Static rec As Long
Static j As Long
Dim lStart As Long
Dim lInterval As Long
Dim i As Integer
Dim iStringLength As Integer
Dim sID As String
' ----------------------------------------
'set the variables below
iStringLength = 7
lStart = 0
lInterval = 1
' ----------------------------------------
sID = ""
If (j = 0) Then
rec = lStart
Else
rec = rec + lInterval
End If
For i = 1 To iStringLength - Len(CStr(rec))
sID = sID & "0"
Next i
sID = sID & CStr(rec)
j = j + 1
__esri_field_calculator_splitter__
sID


为了有更大的延展性,这段优秀的代码里将起始值、步长(就是编号每次增加的值)、字段规范长度等都设置为可以改变的参数,分别为:lStart lInterval iStringLength

自然地,可以有其他思路来解决问题:简单地生成1,2,3,。。。,然后规范一下格式为"0000000" 这种。如下参考代码:
'-------------------------------------
'rec_Number_ConstantLengthString2.cal
'Author: Ianko Tchoukanski
'http://www.ian-ko.com
'@ Tsonghua
'-------------------------------------
Dim sID As String
Dim sFormatString As String
sFormatString = "000000000"
sID= Format( [FID], sFormatString)

__esri_field_calculator_splitter__
sID

这段代码,同样地,也是我为了寻求某GIS交流群里群友问题答案的时候再ESRI支持中心上找到的,网址是http://www.ian-ko.com,他们写了一批优秀的表达式,打包为"
EasyCalculate50.zip "
,免费提供下载使用。同时还有个工具"ETGeoWizards99_92.exe",一样地很优秀,作为ArcGIS的插件,有很多实用的功能,只是这个插件只有些基本的处理是共享,其他更高级一些处理过程还有搭建的模块就是需要注册了。


要研究field Calculate中的vba,认真学习ian-ko.com提供的免费的EasyCalculate50,是个不错的选择。

4.将点 x y坐标值写入字段[E]

前面提到的几个例子,都是纯粹的属性字段的操作,field Calculate里提供使用vba对图形的某些属性性质进行获取或者修改的方法。

本例中,需要获取点层数据个点的坐标值,示例代码如下:
' ----------------------------------------
' @ Tsonghua  090924
' ----------------------------------------
Dim Output As string
Dim pPoint As IPoint
Set pPoint = [Shape]
Output = pPoint.X & "," & pPoint.Y
__esri_field_calculator_splitter__
Output
小结:

脚本处理,在ArcGIS desktop随处可见。引用diligentpig的一段话:
GeoprocessingArcGIS产品的三大核心(GeodatabaseGeovisualizationGeoprocessing)理念之一,也是AGSgp服务的基石。Desktop之所以强大,在很大程度上取决于Geoprocessing Framework的支撑。若要深入掌握Geoprocessing,除了反复操练ArcToolbox,还得写的一手好的Python Scripts才行。

GeodatabaseESRI基于对地理空间数据的理解,构建合适的数据结构来存储空间数据;Geovisualization是准确,漂亮地展现种类繁多,数量巨大,表达方式复杂的空间数据; GeoprocessingArcGIS产品中的具体体现。脚本技术是ArcGIS desktop应用来进行数据分析处理的重要方式,熟练掌握一点脚本知识,是不无裨益的。


对于vba的学习,可以根据具体的需要,在各处查阅资料,

推荐1ArcGIS desktop Help

可以说,在学习的过程中需要的资料,最详实的,莫过于帮助了。体系完善,相关链接齐全,相关内容讲解十分透彻。只不过是E文的,读起来有点烦。

推荐2ESRI中国社区

里面都是很熟悉的中文,活跃着许多热心博学的GISer。遇到了问题,可以先点搜索,输入关键字,标题搜索、全文搜索,先自己搜一把,找找答案,如果没有解决办法,就描述好问题发帖提问。这里太感谢社区的筒子们了,比如博学睿智的来生缘老师,诲人不倦,循循善诱,跟着他学,获益良多。

推荐3ESRI Support

这里的积淀更深一些,基本上现在遇到的问题,都有人早就碰到过,解决过。有主题讨论、知识讲解、脚本下载、补丁下载、bug信息等等内容。^^ 那里下载脚本资料等都是免费的。>_<论坛下载需要花积分,许多人灌水-_-..洪水泛滥了都..

ESRI技术支持是E文的,不过都是些很简单,把大致意思看懂,是需要的东西,就仔细找个字典慢慢查查^^.
也有些筒子们上去用中式E文发帖,呵呵,看起来也很亲切。


推荐4:比较优秀的基于ArcGIS开发的一些工具

像上面推荐的http://www.ian-ko.com,还有许多同样很优秀的GIS网站上有丰富的工具和学习资料。工欲善其事必先利其器,除了自己写工具之外,找到一些优秀的工具,可以事半功倍。
原文地址:https://www.cnblogs.com/zhangjun1130/p/2368901.html