赞
踩
虽然在ArcGIS的python窗口内或IDE环境下,也可运行代码,但如果有频繁使用或需要提供给他人的情况,那么将代码封装为一个自定义脚本工具,则可提高使用效率,避免频繁修改变量定义,提供给他人时也可避免过多的沟通说明。
本文章主要介绍自定义脚本工具的创建、代码的导入、脚本参数的配置、参数的验证、以及脚本描述的编写。
环境:ArcGIS10.4(ArcGIS Pro也基本相同)
第一步:在目录处右键 --> 新建 --> 工具箱(不是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 文件的代码时就不会影像脚本工具了。同时也可以对脚本工具进行加密(加密方式 右键脚本工具 --> 设置密码)仅加密代码不会影响工具的使用。
在我们的演示代码中,一共有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可解决。
至此,示例代码及自定义脚本工具就配置好了,以下是其他的数据类型以及参数属性、参数验证的内容。
本节主要介绍常用的数据类型;
(1)文件or要素
(2)字符
(3)其他
注意:数据类型必须为“长整型”、双精度不可使用滚动条。
数据类型为“要素图层”、“字段”等均默认可下拉选择,数值、文本的数据类型可使用值列表的方式进行下拉选择。
参数验证可用于,对参数进行细致过滤检测、折叠参数(使用目录折叠或展开参数)、锁定参数(灰色无法填写的)、自定义消息(给出错误参数提示)。下面我们来逐个讲解:
下面,我们有一个用于测试的脚本,有两个参数,需要做到参数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
例如下图自定义脚本,需要输入一个“点”类型的要素,但通过“数据类型”无法控制输入的要素类型。
此时,我们就可通过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个参数,需要将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
在目录窗口内右键脚本工具 --> 点击项目描述 --> 点击编辑(左上角)
标题:显示在脚本工具窗口,“帮助”的最上方;
摘要:显示在脚本工具窗口,“帮助”页内;
参数(对话框说明):在脚本工具窗口,点击该参数时“帮助”页内显示。
谢谢观看!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。