Skip to main content

ArcMap 数据驱动生成属性统计表

前言

本教程只提供实现思路和关键api,因为源码有点技术性问题无法解决,但是根据本文思路只要你会最基础的api调用,绝对能实现本中文效果的。

完整实战:【原创】记一次使用数据驱动出图,顺手开发了一个动态表格生成脚本

脚本功能

  • 生成当前页面的数据表格
  • 批量导出页面,且同时生成表格,导出成mxdpdfjpg等各种格式
  • 使用多线程实现同时导出多个页面,如理100多个页面的时候非常有用

image-20211011160504330

实现思路

  • 创建一个方框元素,用来决定表格在哪里生成,表格颜色,线框颜色等
  • 创建一个文本元素,用来填充数据
  • 获取当前视图的集合范围,将当前范围内显示的数据提取出来
  • 根据提取的数据生成表格
  • 导出需要的格式
  • 遍历整个数据驱动,每一页都生成表格和导出数据
  • 多线程同时导出

1、生成两个复制元素

  • 首先是手动创建方框元素,借助方框元素来设定后面数据表格要生成在什么位置,表格的边框、背景样色,还有表格的大小。

01创建表格元素

  • 创建文本元素,用于给脚本渲染数据内容

02创建表格内容元素

  • 创建后给两个元素都指定一个名字,至此无法使用脚本执行的部分就完成,剩下的工作就开始调用api实现

image-20211011134354088

image-20211011134650334

  • 通过arcpy.mapping.ListLayoutElements函数,对方框元素和文本元素进行实例

2、识别数据都出现在哪些视图范围内,并提取

获取目标数据集,获取当前视图显示的范围,判断哪些数据集中哪些元素出现在了当前视图内,可以理解成当前视图数据的几何显示范围内包含了那几个目标数据,然后提取包含数据的对应字段,提取出当前页面数据

image-20211011140234695

  • 获取当前视图出现的目标数据集
# 数据图层或者shp文件
# 只要是 SearchCursor 支持的输入即可
target = '东安江左岸'

# 要提取数据的字段
fileds = ['编号', 'X坐标', 'Y坐标']

# 获取当前视图的几何范围
currt_page_shpe = mxd.dataDrivenPages.pageRow.shape

# 这里的 SHAPE@ 是获取每个元素的几何范围,具体可以参考官方文档
data =[]
with arcpy.da.SearchCursor(target, ["SHAPE@"] + fileds) as target_rows:
# 遍历每一个元素,判断源元素是否出现在当前视图
for row in target_rows:
# 使用 contains 方法判断两个几何是否存在包含关系
if currt_page_shpe.contains(row[0]):
# 如果存在,则将当前数据保存下来
# data 当前是一个二维数组
data.append([row[1], row[2], row[3]])
.../ # data其他操作

3、绘制表格和数据

因为arcpy无法创建元素,所以我们需要借助第一步手动生成的两个元素,对其进行克隆和位移,实现表格。

  • 根据数据集生成表格数据
  • 通过arcpy.mapping.ListLayoutElements函数,对方框元素和文本元素进行实例
# 获取mxd实例
mxd = arcpy.mapping.MapDocument(r"current")

# 获得方框元素和文本元素的实例
rect = arcpy.mapping.ListLayoutElements(mxd, wildcard='方框元素名称')[0]
text = arcpy.mapping.ListLayoutElements(mxd, wildcard='文本元素名称')[0]

# 遍历数据,生成页面
# 注意:data当前是一个二维数组,一维元素表示行,二维元素保存对应的列数据

# 遍历行
table_h = rect.elementHeight
table_w = rect.elementWidth
table_x = rect.elementPositionX
table_y = rect.elementPositionY
for each_row in data:
# 计算出每个框的大小和初始位置
x = # 可以根据table_x 和当前元素的索引计算出具体偏移的位置
y = # 可以根据table_y 和当前元素的索引计算出具体偏移的位置
w = # 当前位置的框的宽度,平均分宽度: table_h / len(each_row),或者指定宽度
h = # 当前位置的框的高度,平局分高度: table_y / len(data) , 这里只是距离,具体表格怎么生成非常灵活,原理就是复制元素,修改大小而已

#遍历列
for each_col in each_row:
# 克隆方框元素,绘制当前数据方框
new_rect = rect.clone("_rect_clone")

# 克隆文本元素,绘制当前无法编辑
new_text = text.clone("_text_clone")
new_text.text = each_col # 显示数据
new_text.fontSize = font_size # 字体大小,可以通过外部动态输入

# 通过 elementPositionX、elementPositionY 属性设置位置
# 通过 elementWidth、elementHeight 属性设置元素的长和宽,上面计算出来的


4、批量导出每个页面

  • 获取下一页
# 当前mxd数据驱动的所有页面
page_count = mxd.dataDrivenPages.pageCount

# 直接修改 currentPageID 则可以将视图进行更新,执行下一页
currt_page = mxd.dataDrivenPages.currentPageID

# 批量导出
for each_page in range(1, mxd.dataDrivenPages.pageCount+1):
mxd.dataDrivenPages.currentPageID = each_page

# 生成表格
create_table() ...

# 每页保存一个mxd
mxd.saveACopy('xxxx.mxd')

# 每页导出一个pdf、jpeg
mxd.mapping.exportxxxxx

  • 这里贴一下官方文档的api,按需调用即可

image-20211011155140240

  • 最终导出成多中格式,方便我们修改或者打印 image-20211011155236513

5、优化

上面几步做完,已经能自动导出每一页的图片,不过由于都是一个一个页面的数据,非常耗费时间,看了一下cpu和内存的占用也非常小,所以用多线程或者多进程,同时多出多个页面,即可实现效率翻倍。

  • 读取数据图层在最开始执行一次,保存到内存中
  • 遍历生成未填充表格数据的mxd文件
  • 每个mxd文件利用多线程来重新读取,然后生成表格