ESRI中国社区学习心得之Field CalculatorWord文档格式.docx
《ESRI中国社区学习心得之Field CalculatorWord文档格式.docx》由会员分享,可在线阅读,更多相关《ESRI中国社区学习心得之Field CalculatorWord文档格式.docx(65页珍藏版)》请在冰豆网上搜索。
2.在FieldCalculator中再次使用遍历(同VBA中写法)50
3.加标志使得FieldCalculator中不做不必要的多次执行51
ARCGIS学习心得——之FieldCalculator
为什么要把FieldCalculator专门作为一章呢,是因为FieldCalculator着实很强大,利用FieldCalculator总能达到事半功倍的效果,具体有多厉害,我们下面来一一介绍。
[学习笔记]ArcMap中的VBA之FieldCalculator
http:
//bbs.esrichina-
------<
学习笔记>
------
ArcMap中,无论是在属性框中右击字段打开的FieldCalculator还是在Arctoolbox\DataManagementTools\Field\工具箱中的Calculatefield,都支持vba表达式。
字段计算器,用以计算字段值。
这些字段值,可以是属性表里相关字段的综合,比如百分比,分解字段等;
可以是和图形有关的值,比如点的xy坐标,面的中心点坐标,线的长度等等;
也可以是为了满足某种特定需求而创造出来的值。
比如如下问题:
1.要找出图层某字段[A]里的重复值,并标上记号;
2.图层某字段[B],现在要将字段[B]中的{最大值+最小值+该行值}写入一个新字段[C]中;
3.字段[D]需要进行编号,号码格式为"
000001"
"
000002"
000003"
000004"
...,"
000202"
…;
4.将点层的xy坐标按x,y的格式输出到[E]字段
1.重复记录标上记号
要找出图层某字段的重复记录,对于存储在PersonalGeodatabase中feature而言,可以通过selectbyattribute找出重复值的记录:
1.Sql:
select*fromlayerwhere:
2.[A]in(select[A]from层名groupby[A]havingcount([A])>
1)
这样执行下来的结果,就是该图层中,[A]字段值重复数大于等于2的所有记录,而对于不支持子查询的比如shapefile格式文件,可以怎么办呢?
在属性表中新建一个字段,取名"
test'
,类型设置为longinteger,然后右击该字段,选择FieldCalculator,勾选advanced,写入以下代码:
1.'
----------------------------------------
2.'
ESRISupportHome>
KnowledgeBase>
TechnicalArticles>
ArticleDetail
3.'
代码参见HowTo:
Identifyduplicatefieldvalues
4.'
@Tsonghua090924
5.'
6.StaticdAsObject
7.StaticiAsLong
8.DimiDupAsInteger
9.DimsField
10.'
11.'
这里填写需要检查的字段名
12.sField=[A]
13.'
14.If(i=0)Then
15.Setd=CreateObject("
Scripting.Dictionary"
)
16.EndIf
17.If(d.Exists(CStr(sField)))Then
18.iDup=1
19.Else
20.d.AddCStr(sField),1
21.iDup=0
22.EndIf
23.i=i+1
在Pre_LogicVBAScriptCode下方的A=窗口中填iDup
这是一段在ESRISupport()上找到的代码,功能就是可以讲重复值做上记号,属于重复值的记录,[test]字段值计算结果为1,否则为0。
就是说,如果有三条记录[A]字段值分别为"
aa"
,那么有一条被标上0,剩余2条被标上1。
对重复记录做了记号,如何处理,就可以随心所欲啦。
这算是一个为了满足某种需求,而重新新建字段,并计算其值的例子
2.计算[B].max+[B].min+[B]
这个问题,就是根据属性表里其他字段来重新提取所需要的信息进行组合。
这个例子,是在论坛上看到有人问的问题。
同样,去ESRI的支持中心去搜了一下,找到了如下代码:
ESRISupport
AuthorChristianDegrassig
6.DimpMxDocAsIMxDocument
7.DimpFLayerAsIFeatureLayer
8.DimpDataAsIDataStatistics
9.DimpCursorAsICursor
10.DimpStatResultsAsIStatisticsResults
11.StaticlngFlagaslong
12.DimlngLayerIndexaslong
13.DimstrFieldNameasstring
14.'
因为不清楚你的字段类型,所以这里设置三个变量类型为Variant
15.StaticvarZMaxasVariant
16.StaticvarZMinasVariant
17.DimvarValasVariant
18.iflngFlag=0then
19.
'
1.注:
这里填你需要取最大最小值的字段名
20.
strFieldName="
B"
21.
2.这里设置你需要计算字段值的图层所在图层索引号
22.
TOC中,从上至下,第一层LayerIndex=0,第二层为1,以此类推..
23.
这里LayerIndex值是第二个需要设置的地方
24.
lngLayerIndex=0
25.
SetpMxDoc=ThisDocument
26.
SetpFLayer=pMxDoc.FocusMap.Layer(lngLayerIndex)
27.
SetpCursor=pFLayer.Search(Nothing,False)
28.
SetpData=NewDataStatistics
29.
pData.Field=strFieldName
30.
SetpData.Cursor=pCursor
31.
SetpStatResults=pData.Statistics
32.
varZMax=pStatResults.Maximum
33.
varZMin=pStatResults.Minimum
34.
lngFlag=1
35.EndIf
36.'
3.这里,第三个数请双击上面fields框中的对应字段
varVal=varZMax+varZMin+[B]
同样,在"
C="
的框框中填入varVal
字段计算器里,不管是一般的赋值表达式抑或是advanced里写的较复杂的表达式,其实都是在每一行运行一次,对该记录进行赋值运算。
因此,如果需要将某参数值传递下去的话,可以用"
static参数as类型"
这样的参数声明方式,"
Dim参数as类型"
的声明方式,只是在进行某条记录赋值的时候有效,一旦结束,参数值被清空。
例如,如果想对某字段赋值为1,2,3,4…可以用如下赋值表达式:
1.Staticiaslong
2.Dimaasstring
3.a=i+1
4.i=i+1
5.__esri_field_calculator_splitter__
6.a
注:
__esri_field_calculator_splitter__是分割标志,具体的可以在FieldCalculator中写一个表达式,然后点击save,保存的文件是"
.cal"
格式,可以用记事本打开编辑。
对于一个经常用的表达式,可以写好之后保存("
save"
)起来,下次使用的时候,只需要点"
Load"
加载过来即可
对比,
1.dimiaslong
对比发现,用static方式声明的结果是1,2,3,4…而用dim方式声明的结果是1,1,1,1,…也就是说,dim声明的参数i在FieldCalculator逐行运行的过程中,没有把参数值传递下去。
回过头来分析一下这段重新分析字段,获取最大值,最小值来组成新字段值的问题
1.iflngFlag=0then
2.
3.
自定义的字段名"
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.EndIf
这段是解决问题的关键所在,它在FieldCalculator对第一行记录赋值的时候,已经对整层进行统计并获取了最大值pStatResults.Maximum储存在参数varZMax中,同时把获取的最小值pStatResults.Minimum存在参数varZMin中。
因为对整层该字段的赋值过程中,只需要获取一次最大值最小值即可,因此这里做了个标志---lngFlag。
一旦最大最小值获取完成,就让lngFlag值为1,以后的逐行赋值中,不再进行统计,而直接使用参数varZMax,varZMin的值。
最后一行varVal=varZMax+varZMin+[待计算字段名]这就很简单了,直接进行加减运算。
3.按照需求对字段[D]编号
有了上面两则例子的提示,这里不难分析,其实只需要先按要求生成1,2,3,4…然后对其格式标准化(也就是让字段长度一致,不足的补零)。
参照如下代码:
为了有更大的延展性,这段优秀的代码里将起始值、步长(就是编号每次增加的值)、字段规范长度等都设置为可以改变的参数,分别为:
lStart,lInterval
,iStringLength
自然地,可以有其他思路来解决问题:
简单地生成1,2,3,。
。
,然后规范一下格式为"
0000000"
这种。
如下参考代码:
-------------------------------------
rec_Number_ConstantLengthString2.cal
Author:
IankoTchoukanski
//www.ian-
@Tsonghua
6.'
7.DimsIDAsString
8.DimsFormatStringAsString
9.sFormatString="
000000000"
10.sID=Format([FID],sFormatString)
11.__esri_field_calculator_splitter__
12.sID
这段代码,同样地,也是我为了寻求某GIS交流群里群友问题答案的时候再ESRI支持中心上找到的,网址是http:
//www.ian-,他们写了一批优秀的表达式,打包为"
EasyCalculate50.zip"
,免费提供下载使用。
同时还有个工具"
ETGeoWizards99_92.exe"
,一样地很优秀,作为ArcGIS的插件,有很多实用的功能,只是这个插件只有些基本的处理是共享,其他更高级一些处理过程还有搭建的模块就是需要注册了。
要研究FieldCalculator中的vba,认真学习ian-提供的免费的EasyCalculate50,是个不错的选择。
4.将点xy坐标值写入字段[E]
前面提到的几个例子,都是纯粹的属性字段的操作,FieldCalculator里提供使用vba对图形的某些属性性质进行获取或者修改的方法。
本例中,需要获取点层数据个点的坐标值,示例代码如下:
@Tsonghua
090924
4.DimOutputAsstring
5.DimpPointAsIPoint
6.SetpPoint=[Shape]
7.Output=pPoint.X&
"
&
pPoint.Y
8.__esri_field_calculator_splitter__
9.Output
这一段的绝大部分是拷贝自FieldCalculator的Help文档
下载(293.09KB)
2010-6-2312:
18
5.对图形的操作
求距离小于指定值的任意两点连线的长度和角度
1、先用addxycoordinate将点的座标加入属性表,下图是加入点座标后的属性表
下载(89.97KB)
2009-9-722:
17
2、用pointdistance求出指定距离内任意两点的距离,下图指定距离为1500米
下载(44.28KB)
注意searchradius为1500
求出的结果,为一dbf文件:
下载(57.42KB)
3、将上步结果中distance为0的记录删掉(arcgis9.3这步不需要做,因它不会求点和自身的距离),增加angle、fx、fy、tx、ty几个double类型字段,用以存放角度,起点x、y座标和终点x、y座标
下载(114.78KB)
4、用上表中input_fid字段将上表和第一步中加了点座标的属性表连接,连接字段为属性表中的fid,并将属性表中的point_x、point_y分别赋给fx和fy。
下载(52.87KB)
5、去掉连接,然后按上步的方法再用near_fid连接属性表,给tx、ty赋值。
连接后的结果:
下载(201.26KB)
6、计算角度
在angle字段名上点右键,选fieldcalculator,选中advanced,在Pre-logidVBAScriptCode窗口内输入下列内容:
if[tx]-[fx]>
0and[ty]-[fy]>
0then
a=atn(([ty]-[fy])/([tx]-[fx]))*180/4/atn
(1)
elseif[tx]-[fx]<
0
then
a=(4*atn
(1)+atn(([ty]-[fy])/([tx]-[fx])))*180/4/atn
(1)
elseif[tx]-[fx]>
0and[ty]-[fy]<
a=(8*atn
(1)+atn(([ty]-[fy])/([tx]-[fx])))*180/4/atn
(1)
elseif[tx]-[fx]=0and[ty]-[fy]>
a=90
elseif[tx]-[fx]=0and[ty]-[fy]<
a=270
0and[ty]-[fy]=0then
a=0
endif
在angle=下面的窗口内输入a
至此距离小于指定值的任意两点连线的长度和角度都已求出。
前面的部分的结果是个dbf文件,将这个dbf文件按(fx,fy)展成点文件后即可利用http:
dLength=[NEAR_DIST]
dAngle=[NEAR_ANGLE]
修改为:
dLength=[DISTANCE]
dAngle=[ANGLE]
6.距离小于一定数值的点之间连线
近日偶得一个距离小于一定数值的点之间连线方法,写出来与大家同享。
假设要将点文件or_point中距离小于1000的点之间连线,下面是具体步骤:
1、首先用near工具找出距离小于1000的点:
文件原属性表:
下载(27.02KB)
2009-9-621:
50
使用下面的工具:
下载(14.24KB)
参数设置:
下载(45.5KB)
inputfeatures和nearfeatures均填你的点文件,searchradius填1000,angle选项选中。
运行工具后的点文件属性表:
下载(52.95KB)
然后按属性选出距离大于0的点导出到另一文件(比如new_point.shp),并在新文件中建一整型字段,比如dummy。
下载(44.98KB)
2、新建一线文件(比如p2l.shp),和new_point一起加入arcmap,并使线文件为最上一层:
下载(16.65KB)
打开new_point的属性表,在dummy上点右键,选fieldcalculator,在弹出的窗口内点advanced,在Pre-logidVBAScriptCode窗口内输入下列代码:
DimpMxDocAsIMxDocument
DimpMapAsIMap
DimpPointAsIPoint
DimpEndPointAsIPoint
DimpLineAsesriGeometry.ILine
DimpTransformAsITransform2D
DimdLengthAsDouble
DimdAngleAsDouble
DimpSegCollAsISegmentCollection
DimPiAsDouble
DimpFeatclsAsIFeatureClass
DimpFeatLayerAsIFeatureLayer
DimiLayerOrderAsInteger
DimpFCursorAsIFeatureCursor
DimpFBufferAsIFeatureBuffer
Pi=4*Atn
(1)
SetpMxDoc=ThisDocument
SetpMap=pMxDoc.FocusMap
SetpFeatLayer=pMap.Layer(iLayerOrder)
SetpFeatcls=pFeatLayer.FeatureClass
Se