ArcMap中,無論是在屬性框中右擊字段打開的field Calculate還是在Arctoolbox\Data Management Tools\Field\ 工具箱中的Calculate field ,都支持vba表達式。
1.重復記錄標上記號
要找出圖層某字段的重復記錄,對於存儲在Personal Geodatabase中feature而言,可以通過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 類型 "的聲明方式,只是在進行某條記錄賦值的時候有效,一旦結束,參數值被清空。 例如,如果想對某字段賦值為 1,2,3,4… 可以用如下賦值表達式: 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 方式聲明的結果是 1,2,3,4… 而用 dim方式聲明的結果是 1,1,1,1,…也就是說,dim聲明的參數 i在field 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,以后的逐行賦值中,不再進行統計,而直接使用參數 varZMax,varZMin的值。 最后一行 varVal= varZMax + varZMin + [ 待計算字段名 ] 這就很簡單了,直接進行加減運算。 3.按照需求對字段[D]編號 有了上面兩則例子的提示,這里不難分析,其實只需要先按要求生成 1,2,3,4… 然后對其格式標准化(也就是讓字段長度一致,不足的補零)。 參照如下代碼: ' ---------------------------------------- '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 才行。 Geodatabase是ESRI基於對地理空間數據的理解,構建合適的數據結構來存儲空間數據;Geovisualization是准確,漂亮地展現種類繁多,數量巨大,表達方式復雜的空間數據; Geoprocessing在ArcGIS產品中的具體體現。腳本技術是ArcGIS desktop應用來進行數據分析處理的重要方式,熟練掌握一點腳本知識,是不無裨益的。 對於vba的學習,可以根據具體的需要,在各處查閱資料, 推薦1:ArcGIS desktop Help 可以說,在學習的過程中需要的資料,最詳實的,莫過於幫助了。體系完善,相關鏈接齊全,相關內容講解十分透徹。只不過是E文的,讀起來有點煩。 推薦2:ESRI中國社區 里面都是很熟悉的中文,活躍着許多熱心博學的GISer。遇到了問題,可以先點搜索,輸入關鍵字,標題搜索、全文搜索,先自己搜一把,找找答案,如果沒有解決辦法,就描述好問題發帖提問。這里太感謝社區的筒子們了,比如博學睿智的來生緣老師,誨人不倦,循循善誘,跟着他學,獲益良多。 推薦3:ESRI Support 這里的積淀更深一些,基本上現在遇到的問題,都有人早就碰到過,解決過。有主題討論、知識講解、腳本下載、補丁下載、bug信息等等內容。^^ 那里下載腳本資料等都是免費的。>_<論壇下載需要花積分,許多人灌水-_-..洪水泛濫了都.. ESRI技術支持是E文的,不過都是些很簡單,把大致意思看懂,是需要的東西,就仔細找個字典慢慢查查^^. 也有些筒子們上去用中式E文發帖,呵呵,看起來也很親切。 推薦4:比較優秀的基於ArcGIS開發的一些工具 像上面推薦的 http://www.ian-ko.com ,還有許多同樣很優秀的GIS網站上有豐富的工具和學習資料。工欲善其事必先利其器,除了自己寫工具之外,找到一些優秀的工具,可以事半功倍。 |