第三章 管理地图文档和图层 ||| 第五章 自动化地图生产和打印
我们将在本章介绍以下案例:
- 查找地图文档和图层文件中损坏的数据源
- 调用MapDocument.findAndReplaceWorkspacePaths()方法修复损坏的数据源
- 调用MapDocument.replaceWorkspaces()方法修复损坏的数据源
- 调用replaceDataSource()方法修复单个图层和表
- 查找文件夹中所有地图文档中损坏的数据源
引言
GIS数据的移动,格式转换以及删除等操作是很普遍的情况。这些操作过程会导致许多地图文档或图层文件中数据源损坏。这些受损的数据源修复之后才能正常使用,如果涉及到大量的地图文档,修复数据源将会是一个巨大的工程。你可以使用arcpy.mapping
模块来自动化完成损坏数据源的查找和修复工作,而且不用打开受影响的地图文档。使用ListBrokenDataSources()
函数来查找损坏的数据源是一个简单的处理过程,该函数返回一个包含地图文档或者图层文件中所有损坏的数据源列表。在脚本中通常会先调用ListBrokenDataSources()
函数,之后迭代返回的列表数据并修复数据源。修复损坏的数据源的工作既可以针对单独的数据图层也可以针对一个工作空间内的所有图层。
查找地图文档和图层文件中损坏的数据源
数据源损坏是地图文档中常见问题。你可以使用arcpy.mapping
模块来查找已经移动或删除或转换格式的数据源。
Getting ready
在ArcMap中,数据源损坏的图层会在图层名称前面用红色感叹号来标识(如下图所示)。arcpy.mapping
模块中的ListBrokenDataSources()
函数会返回地图文档或图层文件中受损的图层对象列表:
How to do it...
按照以下步骤来学习如何查找地图文档文件中的损坏的数据源:
1.在ArcMap中打开C:\ArcpyBook\Ch4\Crime_BrokenDataLinks.mxd
。
你会看到该文档中的所有图层的数据源都已经损坏。在本案例中,地图文档中的数据移动到了其他文件夹中,数据删除或者转换为其他格式的话,你也会看到相同的提示符号。比如说,数据从个人地理数据库中迁移到文件地理数据库:
2.关闭ArcMap。
3.打开IDLE,创建一个新的脚本窗口。
4.导入arcpy.mapping
模块:
import arcpy.mapping as mapping
5.引用Crime_BrokenDataLinks.mxd
地图文档:
mxd=mapping.MapDocument(r"c:\ArcpyBook\Ch4\Crime_BrokenDataLinks.mxd")
6.获取损坏数据源列表:
lstBrokenDS = mapping.ListBrokenDataSources(mxd)
7.迭代列表并打印图层名称:
for layer in lstBrokenDS:
print layer.name
运行结果如下:
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()
函数返回一个损坏数据源的图层列表。我们可以使用for
循环语句迭代列表内容并对每个图层执行操作。在本案例中,我们只是简单地显示图层名称来说明函数返回的数据情况。在下一个案例中,我们将编写脚本来修复这些损坏的数据源。
There's more...
ListBrokenDataSources()
函数不仅可以返回地图文档中损坏的数据源图层列表,还可以查找图层文件(.lyr
)中损坏的数据源。只要简单地将图层文件的路径参数传递给该函数就可以查看该图层文件中是否存在损坏的数据源。需要说明一点的是打包好的地图文档或图层文件不需要这些函数来查找损坏的数据源,这是因为不同于图层文件,这类文件和数据是绑定在一起的。
调用MapDocument.findAndReplaceWorkspacePaths()方法修复损坏的数据源
MapDocument.findAndReplaceWorkspacePaths()
方法用于在地图文档中进行全局查找并替换所有图层和表的工作空间路径。你还可以一次替换多个工作空间类型的路径。
Getting ready
我们在学习修复数据集的方法前需要先介绍几个概念。你会发现涉及到修复损坏数据源的方法的时候,这些术语会经常提起,因此你需要理解在这些概念的含义。工作空间(workspace)可以简单地理解为数据的容器。它可以是一个文件夹(针对shapefile文件来说),个人地理数据库,文件地理数据库或是ArcSDE连接。工作空间路径(workspace path)是工作空间的系统路径。对于地理空间数据库来说,工作空间路径是包含地理数据库的名称在内的。数据集(dataset)则可以简单地理解为工作空间内的要素类或是表,而数据源(data source)则是工作空间和数据集的组合。不要混淆数据集和要素数据集两个概念,前者只是针对数据来说的一个笼统的概念,而后者则是地理数据库中的一个对象,作为要素类或其他数据集的容器。
arcpy.mapping
中有三个与修复受损数据源相关的类,分别是MapDocument
类,Layer
类以及TableView
类。每一个类中包含的方法都可以用于修复数据源。在本案例中,我们将看一下如何使用MapDocument
类中的findAndReplaceWorkspacePaths()
方法对地图文档中的图层和表执行全局的查找和替换操作。
How to do it...
按照以下步骤来学习如何使用findAndReplaceWorkspacePaths()
方法来修复地图文档中的图层和表:
1.在ArcMap中打开C:\ArcpyBook\Ch4\Crime_BrokenDataLinks.mxd
。
2.右键单击任意图层选择属性(Properties)。
3.点击源(Source)选项卡,你会注意到该图层引用的位置为
C:\ArcpyBook\Ch4\Data\OldData\CityOfSanAntonio.gdb
。文件地理数据库位置已经不存在了;数据已经移至C:\ArcpyBook\data
文件夹中了。
4.打开IDLE,创建一个新的脚本窗口。
5.导入arcpy.mapping
模块:
import arcpy.mapping as mapping
6.引用Crime_BrokenDataLinks.mxd
地图文件文件:
mxd=mapping.MapDocument(r"c:\ArcpyBook\Ch4\Crime_BrokenDataLinks.mxd")
7.使用findAndReplaceWorkspacePaths()
方法来修复该地图文档中所有数据源的路径:
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.运行脚本。
11.在ArcMap中打开C:\ArcpyBook\Ch4\Crime_DataLinksFixed.mxd
文件。如下图所示,所有的数据源已经修复完成:
How it work...
MapDocument.findAndReplaceWorkspacePaths()
方法用于在地图文档中进行全局查找并替换所有图层和表的工作空间路径。你还可以一次替换多个工作空间类型的路径。
There's more...
Layer
类和TableView
类同样可以使用findAndReplaceWorkspacePaths()
方法来执行相同的操作。对于Layer
和TableView
对象来讲,该方法用于修复地图文档文件中的单个损坏的数据源而不进行全局查找和替换。
使用MapDocument.replaceWorkspaces()方法修复损坏的数据源
在GIS操作课程中,数据从一种工作空间类型迁移到其他类型是相当普遍的操作。比如,许多组织机构会将数据从旧的个人地理数据库中迁移到新的文件地理数据库甚至是企业级的ArcSDE地理数据库中。你可以使用MapDocument.replaceWorkspaces()
方法来自动化完成数据集更新至不同工作空间类型中的工作。
Getting ready
MapDocument.replaceWorkspaces()
方法与MapDocument.findAndReplaceWorkspacePaths()
方法类类似,不过前者允许更改工作空间类型。比如,你可以从一个文件地理数据库中转为个人地理数据库。不过一次操作只能针对一个工作空间。在本案例中,我们将使用MapDocument.replaceWorkspaces()
方法将数据源从文件地理数据库转至个人地理数据库。
How to do it...
按照以下步骤来学习如何使用MapDocument.replaceWorkspaces()
来修复损坏的数据源:
1.在ArcMap中打开C:\ArcpyBook\Ch4\Crime_DataLinksFixed.mxd
。
2.如下图所示,注意到所有的图层和表位于一个叫CityOfSanAntonio.gdb
的文件地理数据库中:
3.打开IDLE,创建一个新的脚本窗口。
4.导入arcpy.mapping
模块:
import arcpy.mapping as mapping
5.引用Crime_BrokenLinksFixed.mxd
文件:
mxd=mapping.MapDocument(r"C:\ArcpyBook\Ch4\Crime_DataLinksFixed.mxd")
6.调用replaceWorkspaces()
方法,并将新旧地理数据库类型关键字参数传递给该方法:
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.运行脚本。
10.在ArcMap中打开C:\ArcpyBook\Ch4\Crime_DataLinksUpdated.mxd
文件。如下图所示,所有的数据源已经位于个人地理数据库中(扩展名为.mdb
):
How it work...
MapDocument.replaceWorkspaces()
方法接受的参数中包括新旧工作空间的路径以及工作空间类型。工作空间路径不言而喻,工作空间类型方面还是很有必要多阐述一下。工作空间类型是以字符串关键字(string keyword)的形式传递给方法。在本案例中,旧的工作空间类型为文件地理数据库因此使用了关键字FILEGDB_WORKSPACE
。新的工作空间类型的关键字为ACCESS_WORKSPACE
来表示个人地理数据库。个人地理数据库是存储在Mircrosoft的ACCESS文件中。还有一些不同的工作空间类型可以存储GIS数据。你要确保提供的工作空间类型与你的数据集相匹配。下面列出了一些可用的工作空间类型(许多人仍然会使用shapefile文件,这类文件的工作空间类型为SHAPEFILE_WORKSPACE
):
-
ACCESS_WORKSPACE
:个人地理数据库或Access工作空间 -
ARCINFO_WORKSPACE
:Arcinfo coverage工作空间 -
CAD_WORKSPACE
:CAD文件工作空间 -
EXCEL_WORKSPACE
:Excel文件工作空间 -
FILEGDB_WORKSPACE
:文件地理数据库工作空间 -
NONE
:用于忽略该参数 -
OLEDB_WORKSPACE
:OLE数据库工作空间 -
PCCOVERAGE_WORKSPACE
:PC ARC/INFO Coverage工作空间 -
RASTER_WORKSPACE
:栅格工作空间 -
SDE_WORKSPACE
:SDE地理数据库工作空间 -
SHAPEFILE_WORKSPACE
:shapefile文件工作空间 -
TEXT_WORKSPACE
:文本文件工作空间 -
TIN_WORKSPACE
:TIN工作空间 -
VPF_WORKSPACE
:VPF工作空间
调用replaceDataSource()方法修复单个图层和表
本章前面几个案例介绍了针对MapDocument
对象中用来修复数据链接的几种方法。Layer
对象和TableView
对象同样包含可用于修复数据链接的方法,不过这些方法只针对单个对象而不能作用于地图文档中的所有数据集。
Getting ready
Layer
类和TableView
类都有一个replaceDataSource()
方法。该方法针对单个图层或表来更改工作空间路径,工作空间类型以及数据集名称。在本案例中,你将编写脚本来更改某个图层的工作空间路径和类型。replaceDataSource()
方法适用于Layer
类和TableView
类。对于图层而言,既可以是地图文档中的图层也可以是图层文件中的图层。由于表不能包含在图层文件中,对表来讲只能是地图文档中的表。
How to do it...
按照以下步骤来学习如何使用replaceDataSource()
方法来修复地图文档中单个Layer
对象和TableView
对象:
1.在ArcMap中打开C:\ArcpyBook\Ch4\Crime_DataLinksLayer.mxd
文件。Crime数据框中包含一个Burglary的图层,该图层数据是位于CityOfSanAntonio
文件地理数据库中的一个要素类。你要用一个包含相同数据的shapefile文件来替换该要素类:
2.打开IDLE,创建一个新的脚本窗口。
3.导入arcpy.mapping
模块:
import arcpy.mapping as mapping
4.引用Crime_DataLinksLayer.mxd
文件:
mxd=mapping.MapDocument(r"C:\ArcpyBook\Ch4\Crime_DataLinksLayer.mxd")
5.获取Crime
数据框引用:
df = mapping.ListDataFrames(mxd,"Crime")[0]
6.查找Burglary
图层并保存在一个变量中:
lyr = mapping.ListLayers(mxd,"Burglary",df)[0]
7.针对获取的Layer
对象调用replaceDataSource()
方法,并将shapefile文件的引用路径参数,shapefile工作空间类型的关键字参数以及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.运行脚本。
11.在ArcMap中打开C:\ArcpyBook\Ch4\Crime_DataLinksNewLayer.mxd
文件。如下图所示,你会看到Burglary图层已经引用了新的工作空间:
12.右键单击Burglary图层选择属性(Properties)
13.点击源(Source)选项卡查看新的工作空间,工作空间类型和数据集名称:
How it work...
replaceDataSource()
方法接受两个必选参数和两个可选参数。前两个参数定义用于要替换图层的工作空间路径和类型。第三个参数dataset_name
是一个可选参数,该参数定义了用于替换的图层的数据集名称。该名称要求完全匹配。比如,在本案例中,我们Burglaries_2009
传递给dataset_name
参数,这个shapefile文件的名称将作为替换图层。如果该参数没有提供,那么arcpy
将会尝试查找与当前图层数据集名称相同的数据来进行替换。最后一个可选参数是validate
。默认情况下,该参数值为true
。当validate
为true
时,只有当workspace_path
值是一个有效工作空间才会进行更新操作。如果validate
为false
,不管workspace_path
是否是一个有效的工作空间,该方法都会进行工作空间的更新操作。这将会导致损坏的数据源的情况出现,不过这在需要事先创建或修改一个为尚未存在的数据做准备的地图文档时会很有用。
There's more...
Layer
类和TableView
类还包含一个findAndReplaceWorkspacePath()
方法,该方法与MapDocument.findAndReplaceWorkspacePaths()
非常相似。两者唯一的区别在于前者只针对单个Layer
或TableView
对象,而不是遍历整个地图文档或图层文件。
查找文件夹中所有地图文档文件中损坏的数据源
数据从一个工作空间迁移到另一个工作空间或是从某个工作空间类型迁移到其他工作空间类型中,这在许多机构部门是很普遍的事情。该情况发生时,所有地图文档或图层文件引用的这些数据源都会中断受损。如果是人工来查找每一个数据源,这会是一项巨大的工程。幸运的是,你可以创建一个地理处理脚本来查找一个或多个文件夹中所有损坏的数据源。
Getting ready
在本案例中,你将学习如何遍历搜索文件夹来查找在文件夹中的地图文档文件中所有损坏的数据源,并将这些图层的名称写入到文件中。
How to do it...
按照以下步骤来学习如何查找文件夹中所有地图文档文件中损坏的数据源:
1.打开IDLE,创建一个新的脚本窗口。
2.导入arcpy
和os
包:
import arcpy.mapping as mapping,os
3.定义一个开始搜索的系统路径。在本案例中,我们会从C盘根目录开始搜索,之后遍历搜索C盘下面所有的目录。你也可以定义一个更为明确的路径:
path = "C:"
4.打开一个文件用来写入损坏的数据图层的名称:
f = open('BrokenDataLinks.txt','w')
5.使用os.walk()
方法以及for
循环语句来遍历目录树:
for root,dirs,files in os.walk(path):
6.在for
循环语句中创建一个二级for
循环语句来遍历所有返回的文件。对于每一个文件,调用os.path.splitext()
方法来获取文件的文件名和扩展名:
for filename in files:
basename,extension = os.path.splitext(filename)
7.查看文件扩展名来查看是否为地图文档文件。如果是的话,首先获取该地图文档文件的完整路径,之后使用该路径创建一个新的地图文档对象实例并将地图文档名写入文件中,最后循环遍历每一个损坏的数据源并写入文件中:
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.关闭文件:
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.运行脚本。
11.打开生成的文本文件查看结果。你的结果会由于定义的path
变量中的路径不同而有区别。下图为我的结果:
How it work...
脚本中使用了Python的os
包以及arcpy.mapping
模块中的方法。os.walk()
方法会从你定义的C盘目录作为根目录开始遍历目录树,并返回每次遍历目录的路径,目录列表和文件列表。其中根目录可以是任意目录。os.walk()
方法返回一个包含根目录路径,目录列表和文件列表的三个元素的元组。之后我们循环遍历文件列表并调用os.path.splitext()
方法将每一个文件分离成文件名和扩展名。其中扩展名用来查看是否匹配地图文档文件的扩展名.mxd
字符串。判定为地图文档的文件的文件名会写入到一个文本文件中去,同时创建了一个新的地图文档对象实例。最后,我们调用ListBrokenDataSources()
函数生成地图文档中损坏的数据源列表,同时这些损坏的数据源的图层名称也被写入到文本文件中。