我使用 Python (2.7) ArcMap 脚本多年,现在我尝试将其转换为与 ArcPro (Python 3) 一起使用。我已将 ArcMap 脚本的一半转换为 ArcPro(使用 Visual Studio),但在修改其定义查询后仍坚持修改代码以缩放到图层范围。
地图名称为“邮件列表地图”。
我想用来导出 pdf 地图的布局称为:“Irrigation_Services_Maps”
我要更改地图标题的表名称是一个名为 irrStats 的变量。它有两列,客户名称和频率(客户名称的数量 - 每条记录代表一个灌溉点。单个客户可以有多个灌溉点)
我想创建一个以客户名称为标题以及与该客户关联的所有灌溉点的地图,并将其导出为 pdf 格式。
有人可以指导我重写这个吗?我花了一整天的时间来审查这个问题,但没有找到明显的解决方案。你可能会认为这比这更容易。
代码问题从 ##### 开始的行开始。我不知道如何添加行号。
谢谢
import arcpy, os
from datetime import datetime
startTime = datetime.now()
print ((datetime.now() - startTime))
irrFile = arcpy.GetParameterAsText(0) # Gets the irrigation file with the data in it
pdfFolder = arcpy.GetParameterAsText(1) # Asks for folder location to put the pdf output files
arcpy.AddMessage(pdfFolder)
pdflist = [f for f in os.listdir(pdfFolder) if f.endswith(".pdf")]
for f in pdflist:
os.remove(os.path.join(pdfFolder, f))
arcpy.env.overwriteOutput = True # Allows us to run the script repeatedly without deleting the intermediate files
aprx = arcpy.mp.ArcGISProject("CURRENT")
aprxMap = aprx.listMaps("Mailing List Map")[0]
lyt=aprx.listLayouts("Irrigation_Services_Maps")[0]
scratchDir = pdfFolder + "\\scratch" # Temporary folder to store temp data
arcpy.AddMessage(scratchDir)
if not os.path.exists(scratchDir):
os.makedirs(scratchDir)
arcpy.env.workspace = scratchDir
arcpy.env.overwriteOutput = True
tempFGDB = arcpy.CreateFileGDB_management(scratchDir, "scratchGDB").getOutput(0)
arcpy.AddMessage(tempFGDB)
arcpy.env.workspace = tempFGDB
irrStats = "irr_stats"
if arcpy.Exists(irrStats):
arcpy.Delete_management(irrStats)
arcpy.Frequency_analysis(irrFile, irrStats, "cus_name")
with arcpy.da.SearchCursor(irrStats, ("FREQUENCY", "cus_name")) as rows: # Goes through the irrStats table
for row in rows:
cusName = row[1]
cusFreq = row[0]
if len(cusName) > 1:
arcpy.AddMessage(cusName)
lyr = aprxMap.listLayers(irrFile)[0]
lyr.definitionQuery = ""
lyr.definitionQuery = "\"cus_name\" = " + "'" + cusName + "'"
for xyz in aprx.listLayouts():
for elm in xyz.listElements("TEXT_ELEMENT"):
if elm.name == "customer":
elm.text = (cusName) # and changes the title (text element "Customer") to selected name in table
###### Don't know how to code Extent, Scale and Refresh View for ArcPro
###### Old ArcMap code needing rewrite below this point
pdfMap = pdfFolder + "\\" + cusName + ".pdf"
if cusFreq == 1: # if there is only one customer record
arcpy.AddMessage("Name : " + cusName)
ext = lyr.getExtent()
df.extent = ext
arcpy.RefreshActiveView() # redraw the map
df.scale = 1000 # set the scale to 1000
arcpy.RefreshActiveView() # redraw the map
arcpy.mapping.ExportToPDF(mxd, pdfMap)
elif cusFreq > 1: # if there is more than 1 record
arcpy.AddMessage("Name2 : " + cusName)
ext = lyr.getExtent() # Find out the extent
df.extent = ext # zoom to it
arcpy.RefreshActiveView() # redraw the map
if df.scale < 1000: #set the scale to 1000 is extent is < 1000
df.scale = 1000
else:
df.scale = df.scale * 1.2 # otherwise make the scale 1.2 times the layers extent
arcpy.RefreshActiveView() # refresh the map
arcpy.mapping.ExportToPDF(mxd, pdfMap) # export the map
arcpy.AddMessage("more than one")
else:
arcpy.AddMessage("Name3 : " + cusName)
lyr.definitionQuery = ""
有几件事你必须注意。
对于 ArcGIS Pro 和“CURRENT”工程,对 arcpy.mp-API 的所有更改都会导致 ArcGIS Pro 中的直接更新,因此无需调用
refreshActiveView
函数。
可以使用 arcpy.Describe 检索数据元素的属性(例如图层):
desc = arcpy.Describe(lyr)
etxent = desc.extent
在 ArcGIS Pro 中,您不再使用 DataFrame,而是使用类
MapFrame
(页面布局元素)和 MapView
(活动地图)。
在这两个类上,您都有一个属性 camera
,它使您可以访问比例尺:
map_view = aprxMap.activeView
camera = map_view.camera
#get current extent:
current_extent = camera.getExtent()
#set extent
camera.setExtent(extent)
比例尺也是相机类的一个属性(读和写):
camera = map_view.camera
#read
scl = camera.scale
#write
camera.scale *= 1.5
也许您可以使用此缩小转换为 ArcGIS Pro 时出现的问题范围。
我发布了我的最终代码,因为我在网上找不到很多这样的例子。我希望它能有所帮助,因为我发现在线文档很难理解。
import arcpy, os
from datetime import datetime
startTime = datetime.now()
print ((datetime.now() - startTime))
irrFile = arcpy.GetParameterAsText(0) # Gets the irrigation file with the data in it
pdfFolder = arcpy.GetParameterAsText(1) # Asks for folder location to put the pdf output files
arcpy.AddMessage(irrFile)
pdflist = [f for f in os.listdir(pdfFolder) if f.endswith(".pdf")]
for f in pdflist:
os.remove(os.path.join(pdfFolder, f))
arcpy.env.overwriteOutput = True # Allows us to run the script repeatedly without deleting the intermediate files
aprx = arcpy.mp.ArcGISProject("CURRENT")
aprxMap = aprx.listMaps("Mailing List Map")[0]
scratchDir = pdfFolder + "\\scratch" # Temporary folder to store temp data
arcpy.AddMessage(scratchDir)
if not os.path.exists(scratchDir):
os.makedirs(scratchDir)
arcpy.env.workspace = scratchDir
arcpy.env.overwriteOutput = True
tempFGDB = arcpy.CreateFileGDB_management(scratchDir, "scratchGDB").getOutput(0)
arcpy.AddMessage(tempFGDB)
arcpy.env.workspace = tempFGDB
irrStats = "irr_stats"
if arcpy.Exists(irrStats):
arcpy.Delete_management(irrStats)
arcpy.Frequency_analysis(irrFile, irrStats, "cust_name")
lyt=aprx.listLayouts("Irrigation_Services_Maps")[0]
with arcpy.da.SearchCursor(irrStats, ("FREQUENCY", "cust_name")) as rows:
for row in rows:
cusName = row[1]
cusFreq = row[0]
if len(cusName) > 1:
arcpy.AddMessage(cusName)
lyr = aprxMap.listLayers(irrFile)[0]
lyr.definitionQuery = ""
lyr.definitionQuery = "\"cust_name\" = " + "'" + cusName + "'"
if cusName == 'DEPT OF TRANSPORTATION':
cusName = "DOT"
arcpy.AddMessage(cusName)
for xyz in aprx.listLayouts():
for elm in xyz.listElements("TEXT_ELEMENT"):
if elm.name == "customer":
elm.text = (cusName)
pdfMap = pdfFolder + "\\" + cusName + ".pdf"
mf = lyt.listElements('mapframe_element')[0]
if cusFreq == 1: # if there is only one customer record
arcpy.AddMessage("Name : " + cusName)
mf.camera.setExtent(mf.getLayerExtent(lyr, False, True))
mf.camera.scale = 1000
lyt.exportToPDF(pdfMap)
elif cusFreq > 1: # if there is more than 1 record
arcpy.AddMessage("Name2 : " + cusName)
mf.camera.setExtent(mf.getLayerExtent(lyr, False, True))
if mf.camera.scale < 1000: #set the scale to 1000 is extent is < 1000
mf.camera.scale = 1000
else:
mf.camera.scale = mf.camera.scale * 1.2 # otherwise make the scale 1.2 times the layers extent
lyt.exportToPDF(pdfMap) # export the map
arcpy.AddMessage("more than one")
else:
arcpy.AddMessage("Name3 : " + cusName)
lyr.definitionQuery = ""
mf.panToExtent(mf.getLayerExtent(lyr, False, True))
将避免每次重新检查并将比例设置为 1000。因为看起来它停留在那里,您可以按该比例设置地图框而不改变。