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 的一段話:
Geoprocessing ArcGIS 產品的三大核心( Geodatabase Geovisualization Geoprocessing )理念之一,也是 AGS gp 服務的基石。 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網站上有豐富的工具和學習資料。工欲善其事必先利其器,除了自己寫工具之外,找到一些優秀的工具,可以事半功倍。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM