第三章 管理地圖文檔和圖層 ||| 第五章 自動化地圖生產(chǎn)和打印
我們將在本章介紹以下案例:
- 查找地圖文檔和圖層文件中損壞的數(shù)據(jù)源
- 調(diào)用MapDocument.findAndReplaceWorkspacePaths()方法修復(fù)損壞的數(shù)據(jù)源
- 調(diào)用MapDocument.replaceWorkspaces()方法修復(fù)損壞的數(shù)據(jù)源
- 調(diào)用replaceDataSource()方法修復(fù)單個圖層和表
- 查找文件夾中所有地圖文檔中損壞的數(shù)據(jù)源
引言
GIS數(shù)據(jù)的移動,格式轉(zhuǎn)換以及刪除等操作是很普遍的情況。這些操作過程會導(dǎo)致許多地圖文檔或圖層文件中數(shù)據(jù)源損壞。這些受損的數(shù)據(jù)源修復(fù)之后才能正常使用,如果涉及到大量的地圖文檔,修復(fù)數(shù)據(jù)源將會是一個巨大的工程。你可以使用arcpy.mapping模塊來自動化完成損壞數(shù)據(jù)源的查找和修復(fù)工作,而且不用打開受影響的地圖文檔。使用ListBrokenDataSources()函數(shù)來查找損壞的數(shù)據(jù)源是一個簡單的處理過程,該函數(shù)返回一個包含地圖文檔或者圖層文件中所有損壞的數(shù)據(jù)源列表。在腳本中通常會先調(diào)用ListBrokenDataSources()函數(shù),之后迭代返回的列表數(shù)據(jù)并修復(fù)數(shù)據(jù)源。修復(fù)損壞的數(shù)據(jù)源的工作既可以針對單獨(dú)的數(shù)據(jù)圖層也可以針對一個工作空間內(nèi)的所有圖層。
查找地圖文檔和圖層文件中損壞的數(shù)據(jù)源
數(shù)據(jù)源損壞是地圖文檔中常見問題。你可以使用arcpy.mapping模塊來查找已經(jīng)移動或刪除或轉(zhuǎn)換格式的數(shù)據(jù)源。
Getting ready
在ArcMap中,數(shù)據(jù)源損壞的圖層會在圖層名稱前面用紅色感嘆號來標(biāo)識(如下圖所示)。arcpy.mapping模塊中的ListBrokenDataSources()函數(shù)會返回地圖文檔或圖層文件中受損的圖層對象列表:

How to do it...
按照以下步驟來學(xué)習(xí)如何查找地圖文檔文件中的損壞的數(shù)據(jù)源:
1.在ArcMap中打開C:\ArcpyBook\Ch4\Crime_BrokenDataLinks.mxd。
你會看到該文檔中的所有圖層的數(shù)據(jù)源都已經(jīng)損壞。在本案例中,地圖文檔中的數(shù)據(jù)移動到了其他文件夾中,數(shù)據(jù)刪除或者轉(zhuǎn)換為其他格式的話,你也會看到相同的提示符號。比如說,數(shù)據(jù)從個人地理數(shù)據(jù)庫中遷移到文件地理數(shù)據(jù)庫:

2.關(guān)閉ArcMap。
3.打開IDLE,創(chuàng)建一個新的腳本窗口。
4.導(dǎo)入arcpy.mapping模塊:
import arcpy.mapping as mapping
5.引用Crime_BrokenDataLinks.mxd地圖文檔:
mxd=mapping.MapDocument(r"c:\ArcpyBook\Ch4\Crime_BrokenDataLinks.mxd")
6.獲取損壞數(shù)據(jù)源列表:
lstBrokenDS = mapping.ListBrokenDataSources(mxd)
7.迭代列表并打印圖層名稱:
for layer in lstBrokenDS:
print layer.name
運(yùn)行結(jié)果如下:
District_Crime_Join
Bexar_County_Boundary
District_Crime_Join
Bexar_County_Boundary
Bexar_County_Boundary
Texas_Counties_LowRes
School_Districts
Crime_surf
Bexar_County_Boundary
Crime2009Table
8.腳本保存為c:\ArcpyBook\Ch4文件夾下的FindFixBrokenData.py。
How it works...
ListBrokenDataSources()函數(shù)返回一個損壞數(shù)據(jù)源的圖層列表。我們可以使用for循環(huán)語句迭代列表內(nèi)容并對每個圖層執(zhí)行操作。在本案例中,我們只是簡單地顯示圖層名稱來說明函數(shù)返回的數(shù)據(jù)情況。在下一個案例中,我們將編寫腳本來修復(fù)這些損壞的數(shù)據(jù)源。
There's more...
ListBrokenDataSources()函數(shù)不僅可以返回地圖文檔中損壞的數(shù)據(jù)源圖層列表,還可以查找圖層文件(.lyr)中損壞的數(shù)據(jù)源。只要簡單地將圖層文件的路徑參數(shù)傳遞給該函數(shù)就可以查看該圖層文件中是否存在損壞的數(shù)據(jù)源。需要說明一點(diǎn)的是打包好的地圖文檔或圖層文件不需要這些函數(shù)來查找損壞的數(shù)據(jù)源,這是因?yàn)椴煌趫D層文件,這類文件和數(shù)據(jù)是綁定在一起的。
調(diào)用MapDocument.findAndReplaceWorkspacePaths()方法修復(fù)損壞的數(shù)據(jù)源
MapDocument.findAndReplaceWorkspacePaths()方法用于在地圖文檔中進(jìn)行全局查找并替換所有圖層和表的工作空間路徑。你還可以一次替換多個工作空間類型的路徑。
Getting ready
我們在學(xué)習(xí)修復(fù)數(shù)據(jù)集的方法前需要先介紹幾個概念。你會發(fā)現(xiàn)涉及到修復(fù)損壞數(shù)據(jù)源的方法的時候,這些術(shù)語會經(jīng)常提起,因此你需要理解在這些概念的含義。工作空間(workspace)可以簡單地理解為數(shù)據(jù)的容器。它可以是一個文件夾(針對shapefile文件來說),個人地理數(shù)據(jù)庫,文件地理數(shù)據(jù)庫或是ArcSDE連接。工作空間路徑(workspace path)是工作空間的系統(tǒng)路徑。對于地理空間數(shù)據(jù)庫來說,工作空間路徑是包含地理數(shù)據(jù)庫的名稱在內(nèi)的。數(shù)據(jù)集(dataset)則可以簡單地理解為工作空間內(nèi)的要素類或是表,而數(shù)據(jù)源(data source)則是工作空間和數(shù)據(jù)集的組合。不要混淆數(shù)據(jù)集和要素數(shù)據(jù)集兩個概念,前者只是針對數(shù)據(jù)來說的一個籠統(tǒng)的概念,而后者則是地理數(shù)據(jù)庫中的一個對象,作為要素類或其他數(shù)據(jù)集的容器。
arcpy.mapping中有三個與修復(fù)受損數(shù)據(jù)源相關(guān)的類,分別是MapDocument類,Layer類以及TableView類。每一個類中包含的方法都可以用于修復(fù)數(shù)據(jù)源。在本案例中,我們將看一下如何使用MapDocument類中的findAndReplaceWorkspacePaths()方法對地圖文檔中的圖層和表執(zhí)行全局的查找和替換操作。
How to do it...
按照以下步驟來學(xué)習(xí)如何使用findAndReplaceWorkspacePaths()方法來修復(fù)地圖文檔中的圖層和表:
1.在ArcMap中打開C:\ArcpyBook\Ch4\Crime_BrokenDataLinks.mxd。
2.右鍵單擊任意圖層選擇屬性(Properties)。
3.點(diǎn)擊源(Source)選項(xiàng)卡,你會注意到該圖層引用的位置為
C:\ArcpyBook\Ch4\Data\OldData\CityOfSanAntonio.gdb。文件地理數(shù)據(jù)庫位置已經(jīng)不存在了;數(shù)據(jù)已經(jīng)移至C:\ArcpyBook\data文件夾中了。
4.打開IDLE,創(chuàng)建一個新的腳本窗口。
5.導(dǎo)入arcpy.mapping模塊:
import arcpy.mapping as mapping
6.引用Crime_BrokenDataLinks.mxd地圖文件文件:
mxd=mapping.MapDocument(r"c:\ArcpyBook\Ch4\Crime_BrokenDataLinks.mxd")
7.使用findAndReplaceWorkspacePaths()方法來修復(fù)該地圖文檔中所有數(shù)據(jù)源的路徑:
mxd.findAndReplaceWorkspacePaths(r"C:\ArcpyBook\Ch4\OldData\CityOfSanAntonio.gdb",r"C:\ArcpyBook\data\CityOfSanAntonio.gdb")
8.保存為一個新的mxd文件:
mxd.saveACopy(r"C:\ArcpyBook\Ch4\Crime_DataLinksFixed.mxd")
9.腳本保存為C:\ArcpyBook\Ch4\MapDocumentFindReplace.py。
10.運(yùn)行腳本。
11.在ArcMap中打開C:\ArcpyBook\Ch4\Crime_DataLinksFixed.mxd文件。如下圖所示,所有的數(shù)據(jù)源已經(jīng)修復(fù)完成:

How it work...
MapDocument.findAndReplaceWorkspacePaths()方法用于在地圖文檔中進(jìn)行全局查找并替換所有圖層和表的工作空間路徑。你還可以一次替換多個工作空間類型的路徑。
There's more...
Layer類和TableView類同樣可以使用findAndReplaceWorkspacePaths()方法來執(zhí)行相同的操作。對于Layer和TableView對象來講,該方法用于修復(fù)地圖文檔文件中的單個損壞的數(shù)據(jù)源而不進(jìn)行全局查找和替換。
使用MapDocument.replaceWorkspaces()方法修復(fù)損壞的數(shù)據(jù)源
在GIS操作課程中,數(shù)據(jù)從一種工作空間類型遷移到其他類型是相當(dāng)普遍的操作。比如,許多組織機(jī)構(gòu)會將數(shù)據(jù)從舊的個人地理數(shù)據(jù)庫中遷移到新的文件地理數(shù)據(jù)庫甚至是企業(yè)級的ArcSDE地理數(shù)據(jù)庫中。你可以使用MapDocument.replaceWorkspaces()方法來自動化完成數(shù)據(jù)集更新至不同工作空間類型中的工作。
Getting ready
MapDocument.replaceWorkspaces()方法與MapDocument.findAndReplaceWorkspacePaths()方法類類似,不過前者允許更改工作空間類型。比如,你可以從一個文件地理數(shù)據(jù)庫中轉(zhuǎn)為個人地理數(shù)據(jù)庫。不過一次操作只能針對一個工作空間。在本案例中,我們將使用MapDocument.replaceWorkspaces()方法將數(shù)據(jù)源從文件地理數(shù)據(jù)庫轉(zhuǎn)至個人地理數(shù)據(jù)庫。
How to do it...
按照以下步驟來學(xué)習(xí)如何使用MapDocument.replaceWorkspaces()來修復(fù)損壞的數(shù)據(jù)源:
1.在ArcMap中打開C:\ArcpyBook\Ch4\Crime_DataLinksFixed.mxd。
2.如下圖所示,注意到所有的圖層和表位于一個叫CityOfSanAntonio.gdb的文件地理數(shù)據(jù)庫中:

3.打開IDLE,創(chuàng)建一個新的腳本窗口。
4.導(dǎo)入arcpy.mapping模塊:
import arcpy.mapping as mapping
5.引用Crime_BrokenLinksFixed.mxd文件:
mxd=mapping.MapDocument(r"C:\ArcpyBook\Ch4\Crime_DataLinksFixed.mxd")
6.調(diào)用replaceWorkspaces()方法,并將新舊地理數(shù)據(jù)庫類型關(guān)鍵字參數(shù)傳遞給該方法:
mxd.repalceWorkspaces(r"C:\ArcpyBook\data\CityOfSanAntonio.gbd","FILEGDB_WORKSPACE",r"C:\ArcpyBook\new_data\CityOfSanAntonio_Personal.mdb","ACCESS_WORKSPACE")
7.保存為一個新的mxd文件:
mxd.saveACopy(r:"C:\ArcpyBook\Ch4\Crime_DataLinksUpdated.mxd")
8.腳本保存為C:\ArcpyBook\Ch4\MapDocumentReplaceWorkspace.py。
9.運(yùn)行腳本。
10.在ArcMap中打開C:\ArcpyBook\Ch4\Crime_DataLinksUpdated.mxd文件。如下圖所示,所有的數(shù)據(jù)源已經(jīng)位于個人地理數(shù)據(jù)庫中(擴(kuò)展名為.mdb):

How it work...
MapDocument.replaceWorkspaces()方法接受的參數(shù)中包括新舊工作空間的路徑以及工作空間類型。工作空間路徑不言而喻,工作空間類型方面還是很有必要多闡述一下。工作空間類型是以字符串關(guān)鍵字(string keyword)的形式傳遞給方法。在本案例中,舊的工作空間類型為文件地理數(shù)據(jù)庫因此使用了關(guān)鍵字FILEGDB_WORKSPACE。新的工作空間類型的關(guān)鍵字為ACCESS_WORKSPACE來表示個人地理數(shù)據(jù)庫。個人地理數(shù)據(jù)庫是存儲在Mircrosoft的ACCESS文件中。還有一些不同的工作空間類型可以存儲GIS數(shù)據(jù)。你要確保提供的工作空間類型與你的數(shù)據(jù)集相匹配。下面列出了一些可用的工作空間類型(許多人仍然會使用shapefile文件,這類文件的工作空間類型為SHAPEFILE_WORKSPACE):
-
ACCESS_WORKSPACE:個人地理數(shù)據(jù)庫或Access工作空間 -
ARCINFO_WORKSPACE:Arcinfo coverage工作空間 -
CAD_WORKSPACE:CAD文件工作空間 -
EXCEL_WORKSPACE:Excel文件工作空間 -
FILEGDB_WORKSPACE:文件地理數(shù)據(jù)庫工作空間 -
NONE:用于忽略該參數(shù) -
OLEDB_WORKSPACE:OLE數(shù)據(jù)庫工作空間 -
PCCOVERAGE_WORKSPACE:PC ARC/INFO Coverage工作空間 -
RASTER_WORKSPACE:柵格工作空間 -
SDE_WORKSPACE:SDE地理數(shù)據(jù)庫工作空間 -
SHAPEFILE_WORKSPACE:shapefile文件工作空間 -
TEXT_WORKSPACE:文本文件工作空間 -
TIN_WORKSPACE:TIN工作空間 -
VPF_WORKSPACE:VPF工作空間
調(diào)用replaceDataSource()方法修復(fù)單個圖層和表
本章前面幾個案例介紹了針對MapDocument對象中用來修復(fù)數(shù)據(jù)鏈接的幾種方法。Layer對象和TableView對象同樣包含可用于修復(fù)數(shù)據(jù)鏈接的方法,不過這些方法只針對單個對象而不能作用于地圖文檔中的所有數(shù)據(jù)集。
Getting ready
Layer類和TableView類都有一個replaceDataSource()方法。該方法針對單個圖層或表來更改工作空間路徑,工作空間類型以及數(shù)據(jù)集名稱。在本案例中,你將編寫腳本來更改某個圖層的工作空間路徑和類型。replaceDataSource()方法適用于Layer類和TableView類。對于圖層而言,既可以是地圖文檔中的圖層也可以是圖層文件中的圖層。由于表不能包含在圖層文件中,對表來講只能是地圖文檔中的表。
How to do it...
按照以下步驟來學(xué)習(xí)如何使用replaceDataSource()方法來修復(fù)地圖文檔中單個Layer對象和TableView對象:
1.在ArcMap中打開C:\ArcpyBook\Ch4\Crime_DataLinksLayer.mxd文件。Crime數(shù)據(jù)框中包含一個Burglary的圖層,該圖層數(shù)據(jù)是位于CityOfSanAntonio文件地理數(shù)據(jù)庫中的一個要素類。你要用一個包含相同數(shù)據(jù)的shapefile文件來替換該要素類:

2.打開IDLE,創(chuàng)建一個新的腳本窗口。
3.導(dǎo)入arcpy.mapping模塊:
import arcpy.mapping as mapping
4.引用Crime_DataLinksLayer.mxd文件:
mxd=mapping.MapDocument(r"C:\ArcpyBook\Ch4\Crime_DataLinksLayer.mxd")
5.獲取Crime數(shù)據(jù)框引用:
df = mapping.ListDataFrames(mxd,"Crime")[0]
6.查找Burglary圖層并保存在一個變量中:
lyr = mapping.ListLayers(mxd,"Burglary",df)[0]
7.針對獲取的Layer對象調(diào)用replaceDataSource()方法,并將shapefile文件的引用路徑參數(shù),shapefile工作空間類型的關(guān)鍵字參數(shù)以及shapefile文件名稱傳遞給該方法:
lyr.replaceDataSource(r:"C:\ArcpyBook\data","SHAPEFILE_WORKSPACE","Burglaries_2009")
8.保存為一個新的地圖文檔文件:
mxd.saveACopy(r"C:\ArcpyBook\Ch4\Crime_DataLinksNewLayer.mxd")
9.腳本保存為C:\ArcpyBook\Ch4\LayerReplaceDataSource.py。
10.運(yùn)行腳本。
11.在ArcMap中打開C:\ArcpyBook\Ch4\Crime_DataLinksNewLayer.mxd文件。如下圖所示,你會看到Burglary圖層已經(jīng)引用了新的工作空間:

12.右鍵單擊Burglary圖層選擇屬性(Properties)
13.點(diǎn)擊源(Source)選項(xiàng)卡查看新的工作空間,工作空間類型和數(shù)據(jù)集名稱:

How it work...
replaceDataSource()方法接受兩個必選參數(shù)和兩個可選參數(shù)。前兩個參數(shù)定義用于要替換圖層的工作空間路徑和類型。第三個參數(shù)dataset_name是一個可選參數(shù),該參數(shù)定義了用于替換的圖層的數(shù)據(jù)集名稱。該名稱要求完全匹配。比如,在本案例中,我們Burglaries_2009傳遞給dataset_name參數(shù),這個shapefile文件的名稱將作為替換圖層。如果該參數(shù)沒有提供,那么arcpy將會嘗試查找與當(dāng)前圖層數(shù)據(jù)集名稱相同的數(shù)據(jù)來進(jìn)行替換。最后一個可選參數(shù)是validate。默認(rèn)情況下,該參數(shù)值為true。當(dāng)validate為true時,只有當(dāng)workspace_path值是一個有效工作空間才會進(jìn)行更新操作。如果validate為false,不管workspace_path是否是一個有效的工作空間,該方法都會進(jìn)行工作空間的更新操作。這將會導(dǎo)致?lián)p壞的數(shù)據(jù)源的情況出現(xiàn),不過這在需要事先創(chuàng)建或修改一個為尚未存在的數(shù)據(jù)做準(zhǔn)備的地圖文檔時會很有用。
There's more...
Layer類和TableView類還包含一個findAndReplaceWorkspacePath()方法,該方法與MapDocument.findAndReplaceWorkspacePaths()非常相似。兩者唯一的區(qū)別在于前者只針對單個Layer或TableView對象,而不是遍歷整個地圖文檔或圖層文件。
查找文件夾中所有地圖文檔文件中損壞的數(shù)據(jù)源
數(shù)據(jù)從一個工作空間遷移到另一個工作空間或是從某個工作空間類型遷移到其他工作空間類型中,這在許多機(jī)構(gòu)部門是很普遍的事情。該情況發(fā)生時,所有地圖文檔或圖層文件引用的這些數(shù)據(jù)源都會中斷受損。如果是人工來查找每一個數(shù)據(jù)源,這會是一項(xiàng)巨大的工程。幸運(yùn)的是,你可以創(chuàng)建一個地理處理腳本來查找一個或多個文件夾中所有損壞的數(shù)據(jù)源。
Getting ready
在本案例中,你將學(xué)習(xí)如何遍歷搜索文件夾來查找在文件夾中的地圖文檔文件中所有損壞的數(shù)據(jù)源,并將這些圖層的名稱寫入到文件中。
How to do it...
按照以下步驟來學(xué)習(xí)如何查找文件夾中所有地圖文檔文件中損壞的數(shù)據(jù)源:
1.打開IDLE,創(chuàng)建一個新的腳本窗口。
2.導(dǎo)入arcpy和os包:
import arcpy.mapping as mapping,os
3.定義一個開始搜索的系統(tǒng)路徑。在本案例中,我們會從C盤根目錄開始搜索,之后遍歷搜索C盤下面所有的目錄。你也可以定義一個更為明確的路徑:
path = "C:"
4.打開一個文件用來寫入損壞的數(shù)據(jù)圖層的名稱:
f = open('BrokenDataLinks.txt','w')
5.使用os.walk()方法以及for循環(huán)語句來遍歷目錄樹:
for root,dirs,files in os.walk(path):
6.在for循環(huán)語句中創(chuàng)建一個二級for循環(huán)語句來遍歷所有返回的文件。對于每一個文件,調(diào)用os.path.splitext()方法來獲取文件的文件名和擴(kuò)展名:
for filename in files:
basename,extension = os.path.splitext(filename)
7.查看文件擴(kuò)展名來查看是否為地圖文檔文件。如果是的話,首先獲取該地圖文檔文件的完整路徑,之后使用該路徑創(chuàng)建一個新的地圖文檔對象實(shí)例并將地圖文檔名寫入文件中,最后循環(huán)遍歷每一個損壞的數(shù)據(jù)源并寫入文件中:
if extension = ".mxd":
fullpath = os.path.join(root,filename)
mxd = mapping.MapDoucment(fullpath)
f.write("MXD:" + filename + "\n")
brknList = mapping.ListBrokenDataSources(mxd)
for brknItem in brknList:
f.write("\t" +brknItem.name + "\n")
8.關(guān)閉文件:
f.close()
9.完整代碼如下所示:
import arcpy.mapping as mapping,os
path = r"C:"
f = open("BrokenDataLinks.txt","w")
for root,dirs,files in os.walk(path):
for filename in files:
basename,extension = os.path.splitext(filename)
if extension = ".mxd":
fullpath = os.path.join(root,filename)
mxd = mapping.MapDocument(fullpath)
f.write("MXD:" + filename + "\n")
brknList = mapping.ListBrokenDataSources(mxd)
for brknItem in brknList:
f.write("\t" + brknItem.name + "\n")
f.close()
10.運(yùn)行腳本。
11.打開生成的文本文件查看結(jié)果。你的結(jié)果會由于定義的path變量中的路徑不同而有區(qū)別。下圖為我的結(jié)果:

How it work...
腳本中使用了Python的os包以及arcpy.mapping模塊中的方法。os.walk()方法會從你定義的C盤目錄作為根目錄開始遍歷目錄樹,并返回每次遍歷目錄的路徑,目錄列表和文件列表。其中根目錄可以是任意目錄。os.walk()方法返回一個包含根目錄路徑,目錄列表和文件列表的三個元素的元組。之后我們循環(huán)遍歷文件列表并調(diào)用os.path.splitext()方法將每一個文件分離成文件名和擴(kuò)展名。其中擴(kuò)展名用來查看是否匹配地圖文檔文件的擴(kuò)展名.mxd字符串。判定為地圖文檔的文件的文件名會寫入到一個文本文件中去,同時創(chuàng)建了一個新的地圖文檔對象實(shí)例。最后,我們調(diào)用ListBrokenDataSources()函數(shù)生成地圖文檔中損壞的數(shù)據(jù)源列表,同時這些損壞的數(shù)據(jù)源的圖層名稱也被寫入到文本文件中。