前 言
虽然在ArcGIS的python窗口内或IDE环境下,也可运行代码,但如果有频繁使用或需要提供给他人的情况,那么将代码封装为一个自定义脚本工具,则可提高使用效率,避免频繁修改变量定义,提供给他人时也可避免过多的沟通说明。
本文章主要介绍自定义脚本工具的创建、代码的导入、脚本参数的配置、参数的验证、以及脚本描述的编写。
环境:ArcGIS10.4(ArcGIS Pro也基本相同)
目 录
一、创建一个的自定义脚本工具
第一步:在目录处右键 --> 新建 --> 工具箱(不是Python工具箱!!)
第二步:右键创建好的工具箱 --> 添加 --> 脚本
第三步:填入脚本的名称与标签
(说明:若创建的脚本内存在其他脚本工具需要导入的函数,名称建议以纯英文命名,不包含中文以及任何特殊符号)
脚本文件和参数设置暂时不写,一直下一步,完成。至此,自定义脚本工具就创建好了。
二、Python代码的导入以及参数的传递
此时,我们写好的代码还未导入到脚本工具中。在导入前,我们需要从脚本参数内获取值。
本次创建脚本工具的示意代码如下:这个串代码的作用是对设置好数据驱动的工程进行地图的批量导出(详见作者的另一篇文章:arcgis-批量出图)
# coding=utf-8
import arcpy, os, sys
reload(sys)
sys.setdefaultencoding('utf-8')
def pic(mxd_path, fc_path, fc2_name, ddp_FieldName, Export_NameField, output, rtion):
if Export_NameField in ['', ' ', None]:
Export_NameField = ddp_FieldName
x = {}
cursor = arcpy.SearchCursor(fc_path) # 遍历 数据驱动要素的 驱动字段 和 文件命名字段组成 字典“x”
for row in cursor: #
x[row.getValue(ddp_FieldName)] = row.getValue(Export_NameField) #
pp = 0
for pageName in x.keys(): # 循环 “x”
mxd = arcpy.mapping.MapDocument(mxd_path) # 调用gis工程
df = arcpy.mapping.ListDataFrames(mxd)[0] # 获取布局
for lyr in arcpy.mapping.ListLayers(mxd, "", df): # 获取要素图层
if lyr.name == fc2_name:
lyr.definitionQuery = u"{1} LIKE \'%{0}%\'".format(pageName, ddp_FieldName) # 修改定义查询
mxd.save()
pageID = mxd.dataDrivenPages.getPageIDFromName(pageName) # 以驱动字段 获取 pageID (驱动索引)
mxd.dataDrivenPages.currentPageID = pageID # 数据驱动(跳转到 上述索引位置)
arcpy.mapping.ExportToPNG(mxd, os.path.join(output, '{}.png'.format(x[pageName])), resolution=rtion) # 导出 png
pp += 1
del mxd
if __name__ == '__main__':
mxd_path = u"D:\\test\\csdn.mxd" # 工程路径
fc_path = u'E:\\test\\csdn_1.gdb\\分区' # 驱动要素路径
fc2_name = u'像控点_SpatialJoin' # 像控点图层名称(在图层内显示的名称,不是要素名)
ddp_FieldName = u'分区号' # 数据驱动名称字段
Export_NameField = u'分区号' # 文件命名字段 # 可自定义,可与 数据驱动名称字段 保持一致,但本字段要素内必须有
output = u'E:\\test\\图' # 输出位置
rtion = 100 # 输出像素
pic(mxd_path, fc_path, fc2_name, ddp_FieldName, Export_NameField, output, rtion)
这串代码内有 7 个变量需要获取对应的脚本参数:
mxd_path = u'D:\\test\\csdn.mxd' # arcmap出图工程路径
fc_path = u'E:\\test\\csdn_1.gdb\\分区' # 驱动要素路径
fc2_name = u'像控点_SpatialJoin' # 像控点图层名称(在图层内显示的名称,不是要素名)
ddp_FieldName = u'分区号' # 数据驱动名称字段
Export_NameField = u'分区号' # 输出文件命名字段 # 可自定义,可与 数据驱动名称字段 保持一致,但本字段要素内必须有
output = u'E:\\test\\图' # 输出位置
rtion = 100 # 输出像素
那么,就需要用到arcpy内获取脚本参数的函数了。修改后的变量赋值如下:
mxd_path = arcpy.GetParameterAsText(0) # 工程路径
fc_path = arcpy.GetParameterAsText(1) # 驱动要素路径
fc2_name = arcpy.GetParameterAsText(2) # 像控点图层名称(在图层内显示的名称,不是要素名)
ddp_FieldName = arcpy.GetParameterAsText(3) # 数据驱动名称字段
Export_NameField = arcpy.GetParameterAsText(4) # 文件命名字段 # 可自定义,可与 数据驱动名称字段 保持一致,但本字段要素内必须有
output = arcpy.GetParameterAsText(5) # 输出位置
rtion = int(arcpy.GetParameterAsText(6)) # 输出像素
这个地方我们用到的是(GetParameterAsText)函数来获取参数。它是用来获取文本格式参数的。若参数为勾选项(输入为布尔型的情况下),则使用(GetParameter)来获取。它用于获取布尔值。
函数参数内的数值表示获取第几个参数。(脚本参数是以列表的格式返回,函数参数数值表示获取脚本参数列表的第几个)
仅用这两个函数可以满足大部分简单工具需要。其他情况可查阅帮助文档。
完成参数的输入后,下面就可以将python文件(.py格式文件)导入到脚本工具内了,注意python文件编码格式必须是(ANSI),若在IDE内编写的代码建议将其复制到 txt 文件中,并另存为(ANSI)的编码格式的 .py 文件。如下图:
下一步导入py文件:脚本处右键 --> 属性 --> 源 --> 选择 py 文件(可在创建自定义脚本工具时进行导入,文中为了逻辑顺序,将其放在此处)
py文件就导入到脚本工具中了,但此时的 代码 和 工具 处于分别存放的状态,建议此时(右键脚本工具 --> 导入脚本),将代码导入到脚本工具中,此时 修改 py 文件的代码时就不会影像脚本工具了。同时也可以对脚本工具进行加密(加密方式 右键脚本工具 --> 设置密码)仅加密代码不会影响工具的使用。
三、脚本参数的配置
3.1.示例代码的参数设置
在我们的演示代码中,一共有7个参数,分别如下,我们对其进行设置。如下图
mxd_path = arcpy.GetParameterAsText(0) # 工程路径
fc_path = arcpy.GetParameterAsText(1) # 驱动要素路径
fc2_name = arcpy.GetParameterAsText(2) # 像控点图层名称(在图层内显示的名称,不是要素名)
ddp_FieldName = arcpy.GetParameterAsText(3) # 数据驱动名称字段
Export_NameField = arcpy.GetParameterAsText(4) # 文件命名字段 # 可自定义,可与 数据驱动名称字段 保持一致,但本字段要素内必须有
output = arcpy.GetParameterAsText(5) # 输出位置
rtion = int(arcpy.GetParameterAsText(6)) # 输出像素
参数设置的说明
(0)工程文件的路径:也就是arcmap文档 (.mxd 文件)。我们对其参数进行命名和数据类型的选择。
(1)数据驱动要素:类型选择“要素图层”,因为设置成“要素图层”,可直接从内容列表内拖拽图层至脚本参数内,或从已有的图层内选择,若设置为“要素类”,则仅可从目录内选择,不够便捷。但“要素图层”也存在缺陷,会有少量工具的参数仅可为“要素类”,那么就应当对应的修改,游标的变量可为“要素图层”。
(2)像控点图层名称:这个地方是输入一个图层的名称,为字符串,为在代码内修改定义查询,不是选择一个图层。
(3)数据驱动名称字段:在数据驱动内设置为名称的字段,此参数为选择一个字段,那么我们就可以额外给他一个来源,从数据驱动要素内获取,如下:
(4)略
(5)输出文件的位置:就是导出的图片存放的位置。此处应选择一个文件夹。(可设置为工作空间,工作空间包含文件夹、文件地理数据库、个人地理数据库等)
(6)导出图片的像素大小:此处应输入一个整数,作为导出png函数的参数,数据类型可选择为“长整型”或“字符串”,但仍需在代码内使用 int() 进行类型转换。
“字符串”类型比较容易找到(对于作者来说),使用“长整型”的话,可将值域限制为数值,且可将参数设置成滚动条。
BUG说明:ArcGIS 10.4版本(未测试其他版本)的脚本工具,在定义、修改参数后运行可能会存在下拉选择箭头丢失的情况。若出现此情况,保存完工具后重新启动 ArcGIS可解决。
至此,示例代码及自定义脚本工具就配置好了,以下是其他的数据类型以及参数属性、参数验证的内容。
3.2.其他“数据类型”的介绍
本节主要介绍常用的数据类型;
(1)文件or要素
- ArcMap文档:在目录中选择一个(.mxd)格式的工程文件;
- 工作空间:在目录中一个工作空间(文件/个人地理数据库,shp文件、cad文件、文件夹)。若需要选择要素数据集可使用“工作空间or要素数据集”;
- 要素图层:在目录中选择一个(要素类)或下拉选择一个图层内已加载的(要素图层)或拖拽入一个(要素图层);
- 要素类:在目录中选择一个(要素类);(shp文件拥有单独的“数据类型”Shapefile);
- 表:主要用于输入(文件/个人地理数据库内表)和(Excel内Sheet表),也可读取(.shp与要素类的属性表);
- 文件:在文件管理中选择一个任意格式的文件。可通过“过滤器”限制文件格式,如需要读取个excel表,则可在“过滤器”处 --> 下拉选择“文件” --> 单击右侧出现的“...” --> 填入(xls)并确认。如果需要可选多个格式可使用英文的“;”进行分隔,如(xls;xlsx)。(gdb不适用文件的过滤器,请使用工作空间);
- 文件夹:在目录内选择一个文件夹;
- 栅格图层:与“2.要素图层”一致。
(2)字符
- 字符串:输入一串字符
- 双精度:输入带有小数位的数值(不可设置滚动条)
- 长整型:输入整数(可设置为滚动条)
- 日期:手动输入或选择一个日期
- 布尔型:输入一个布尔值(True(勾选)、False(未勾选)),选择此数据类型后参数自动变为勾选项,在代码内使用GetParameter获取值。
(3)其他
- 坐标系:选择一个坐标系(地理、投影、自定义)
- SQL表达式:字面意思,但必须选择“获取自”另一要素参数;
- 计算器表达式:字面意思,但必须选择“获取自”另一要素参数;
3.2.1.滚筒条的设置
注意:数据类型必须为“长整型”、双精度不可使用滚动条。
3.2.2.下拉值列表选择的方法配置
数据类型为“要素图层”、“字段”等均默认可下拉选择,数值、文本的数据类型可使用值列表的方式进行下拉选择。
3.3.“参数属性”的功能介绍
- 类型:分别为 必选(Required)、可选(Optional)、派生(Derived);前两个依据字面意思理解,表示该项参数为必须填写以及可以填写,派生一般用做输出参数;
- 方向:分别为 输入(Input)、输出(Output);大部分情况参数都作为输入参数,若作为输出,运行完成后该项可在运行结果窗口内查看;
- 多值:Yes(可在该参数内输入一组值)No(略);
- 默认:用于给该参数设置一个默认值,多值为Yes,默认值可通过“;”进行分隔;
- 环境:可以将参数的默认值设置为环境设置的值;
- 过滤器:可用于过滤文件格式、输入值的范围、值列表(参数下拉选择值)多过滤可用“;”进行分隔;
- 获取自:本项参数从其他参数内获取的可选值;
- 符号系统:作者不常用,略。
四、参数的验证
参数验证可用于,对参数进行细致过滤检测、折叠参数(使用目录折叠或展开参数)、锁定参数(灰色无法填写的)、自定义消息(给出错误参数提示)。下面我们来逐个讲解:
4.1.锁定参数(灰色无法填写的)
下面,我们有一个用于测试的脚本,有两个参数,需要做到参数1勾选的情况下,参数2可修改,参数1不勾选的情况下,参数2不可使用;
需要通过编辑“验证”代码的updateParameters方法内编写锁定规则,如下:
def updateParameters(self):
# 判断参数0的值
if self.params[0].value:
# 如果为 Ture 则将参数1设置为可写
self.params[1].enabled = True
else:
# 否则锁定参数1
self.params[1].enabled = False
return
如此,我们就依据规则,将滚动条改为锁定的了,但会发现,在勾选 0 的情况下,修改了 参数 1 再取消勾选 0 ,会发现我们修改的参数被锁定了,但不为默认值(如下图)。那么如何修改锁定情况下使用默认值呢?
代码如下:只需要在条件判断处添加赋值语句即可(若写入__init__内,则可作为设置默认值),此时,我们修改参数 1 再取消勾选后,会发现参数 1 又改回了默认值 10。
def updateParameters(self):
# 判断参数0的值
if self.params[0].value:
# 如果为 Ture 则将参数1设置为可写
self.params[1].enabled = True
else:
# 修改参数1的值
self.params[1].value = 10
# 锁定参数
self.params[1].enabled = False
4.2.参数的过滤与自定义消息
例如下图自定义脚本,需要输入一个“点”类型的要素,但通过“数据类型”无法控制输入的要素类型。
此时,我们就可通过arcpy的Describe获取要素的类型,并在验证的updateMessages方法内进行判断,若不为点要素则输出错误消息(鼠标移动到错误提示符号上查看)。代码与结果如下
def updateMessages(self):
# 获取参数0的shapeType
fc_type = arcpy.Describe(self.params[0].value).shapeType
# 判断
if fc_type != 'Point':
# 返回消息
self.params[0].setErrorMessage("The parameter must be a point feature class.")
return
4.3.参数分组、折叠
例如,有4个参数,需要将0,1放在一个组里;2,3放在另一个组里边,并且可以折叠显示。我们可以在initializeParameters方法内对参数的类别进行定义,代码如下:
def initializeParameters(self):
self.params[0].category = 'list1'
self.params[1].category = 'list1'
self.params[2].category = 'list2'
self.params[3].category = 'list2'
return
五、脚本描述的编辑
在目录窗口内右键脚本工具 --> 点击项目描述 --> 点击编辑(左上角)
标题:显示在脚本工具窗口,“帮助”的最上方;
摘要:显示在脚本工具窗口,“帮助”页内;
参数(对话框说明):在脚本工具窗口,点击该参数时“帮助”页内显示。
谢谢观看!!