POST
|
@MohamedHassan17 , are you using applySymbologyFromLayer by chance? If so, there are some alternative solutions. If not, we would need a reproducible case. Jeff
... View more
Monday
|
0
|
0
|
35
|
IDEA
|
This has been hanging around for some time now but this has been possible for many releases with Layer.saveACopy(). Jeff - Layout and arcpy.mp teams
... View more
Friday
|
0
|
0
|
23
|
POST
|
@masa I tried your code on my Pro 3.3 machine, even with V2 and it worked. I would recommend trying on a more current build of Pro. There have been 5 new releases plus many patches since 2.8. Jeff
... View more
Friday
|
0
|
1
|
64
|
IDEA
|
@SamuelRomero2, I'm not sure if I'm understanding this correctly because this can be scripted using arcpy.mp. Please let us know if the following snippet isn't what you are looking for. import os customPath = r'C:\Temp' p = arcpy.mp.ArcGISProject('current') for lyt in p.listLayouts(): lyt.exportToPAGX(os.path.join(customPath, lyt.name)) Jeff - Layout and arcpy.mp teams
... View more
a week ago
|
0
|
1
|
100
|
POST
|
@MK13 Again, this is just a work around but have you tried something like ... import os p = arcpy.mp.ArcGISProject('current') relpath = p.homeFolder m = p.listMaps('Map')[0] for l in m.listLayers(): if l.name == 'GreatLakes': lyr1 = arcpy.mp.LayerFile(os.path.join(relpath, 'GreatLakes.lyrx')).listLayers('GreatLakes')[0] l.symbology = lyr1.symbology #Also copy label classes l_cim = l.getDefinition('V3') lyr1_cim = lyr1.getDefinition('V3') l_cim.labelClasses = lyr1_cim.labelClasses l.setDefinition(l_cim) l.showLabels = True #Just in case they are not visible Jeff
... View more
a week ago
|
1
|
0
|
49
|
POST
|
@masa here is some sample code to at least create the ei_cim.symbol. PointSymbol still needs to be defined if needed. Lines 6-26 below were added. I also altered how I'm finding the locator map frame in the CIM elements list instead of hard coding an index number (line 38-40). p = arcpy.mp.ArcGISProject('current')
lyt = p.listLayouts()[0]
mf = lyt.listElements('MapFrame_Element', 'Main MF')[0]
lyt_cim = lyt.getDefinition('V3')
#Create Polygon Symbol with solid stroke outline and transparenent fill
polyStrokeRGBColor = arcpy.cim.CreateCIMObjectFromClassName('CIMRGBColor', 'V3')
polyStrokeRGBColor.values = [0, 0, 0, 100]
polySymLyr1 = arcpy.cim.CreateCIMObjectFromClassName('CIMSolidStroke', 'V3')
polySymLyr1.capStyle = "Round"
polySymLyr1.joinStyle = "Round"
polySymLyr1.width = 1
polySymLyr1.color = polyStrokeRGBColor
polyFillRGBColor = arcpy.cim.CreateCIMObjectFromClassName('CIMRGBColor', 'V3')
polyFillRGBColor.values = [0, 0, 0, 0]
polySymLyr2 = arcpy.cim.CreateCIMObjectFromClassName('CIMSolidFill', 'V3')
polySymLyr2.color = polyFillRGBColor
polySym = arcpy.cim.CreateCIMObjectFromClassName('CIMPolygonSymbol', 'V3')
polySym.symbolLayers = [polySymLyr1, polySymLyr2]
polySymRef = arcpy.cim.CreateCIMObjectFromClassName('CIMSymbolReference', 'V3')
polySymRef.symbol = polySym
#Create Extent indicator
ei_cim = arcpy.cim.CreateCIMObjectFromClassName('CIMExtentIndicator', 'V3')
ei_cim.sourceMapFrame = mf.name
ei_cim.extentIndicatorType = "Frame"
ei_cim.isVisible = True
ei_cim.name = "extent_indicator"
ei_cim.symbol = polySymRef
#ei_cim.pointSymbol = ptSymRef
for elm in lyt_cim.elements:
if elm.name == 'Locator MF':
elm.extentIndicators.insert(0, ei_cim)
#Set back to layer
lyt.setDefinition(lyt_cim) Jeff
... View more
a week ago
|
0
|
3
|
113
|
POST
|
@masa I believe the issue is that you don't have ei_cim.symbol or ei_cim.pointSymbol defined. It will require much more code to define these because multiple CIM classes are required to construct them from scratch. This is a classic example of where the Layout or MapFrame objects could use a helper function to insert an extent indicator, especially now that new layouts can be created. I would suggest adding an Esri Idea requesting this exact functionality. If you are not creating a layout in your script, it may be a lot easier to modify an already existing extent indicator. Jeff - Layout and arcpy.mp teams. I'll see if I can come up with a CIM solution later.
... View more
a week ago
|
0
|
0
|
113
|
POST
|
Thanks @MK13 for bringing this to my attention. This is something we are looking into and need to coordinate with the core GP/arcpy team. Here is a brief explanation and a couple of possible work-arounds. ApplySymbologyFromLayer is a core GP/arcpy method. It runs on the GP thread which includes includes GP dialogs, models, and script tools. The GP thread provides isolation so the application (main thread) can continue to run. Arcpy.mp was designed to work with the application objects and also runs on the main thread. When using a script tool, its important to hook the results back to the main thread and this can be done using the technique mentioned by @TanGnar above. import os p = arcpy.mp.ArcGISProject('current') relpath = p.homeFolder lyr = arcpy.GetParameter(0) if lyr.name == ‘GreatLakes’: lyrx = os.path.join(relpath, 'GreatLakes.lyrx’) arcpy.management.ApplySymbologyFromLayer(lyr, lyrx) arcpy.SetParameter(1, lyr) Another alternative is to use an all arcpy.mp solution where you "copy" the symbology using this technique. import os p = arcpy.mp.ArcGISProject('current') relpath = p.homeFolder for lyr in p.listMaps(‘Map’).listLayers(): if lyr.name == ‘GreatLakes’: lyrx = os.path.join(relpath, 'GreatLakes.lyrx’) lyrx_lyr = lyrx.listLayers(‘GreatLakes’)[0] lyr.symbology = lyrx_lyr.symbology And at Pro 3.4 we hope to introduce a new (feature) Layer.pasteProperties(source_layer, properties) method that allows you copy existing layer properties from a source layer where it defaults to all default properties OR you can specify keywords such as symbology, or definition queries, field aliases, or pop-ups, etc, Jeff - Layout and arcpy.mp teams
... View more
a week ago
|
1
|
1
|
60
|
POST
|
@MK13 there is not a way to activate a map frame from arcpy.mp and we don't have plans to provide that capability but I would like to hear more about your scenario. We have a few exceptions (e.g., opening and closing views) but try to provide functions that can work with scripts in the application and stand alone scripts outside the application. Activating a map frame would only work in the application. The .NET SDK provides finer grained capabilities to perform operations like this and its main focus with Add-ins is to work within the contest of the application. Jeff - Layout and arcpy.mp teams
... View more
2 weeks ago
|
1
|
0
|
94
|
IDEA
|
@RonnieRichards this should be possible using Python CIM Access Here is a code snippet that could be used to find if a layer is a query layer. aprx = arcpy.mp.ArcGISProject('current')
m = aprx.listMaps()[0]
qlyr = m.listLayers('MyQueryLayer')[0]
cim_qlyr = qlyr.getDefinition("V3")
if type(cim_qlyr.featureTable.dataConnection).__name__ == 'CIMSqlQueryDataConnection':
print('Ureka, its a query layer') Next you could continue with modifying other CIM property, like the SQLQuery l_cim.featureTable.dataConnection.sqlQuery = "select OBJECTID,Shape,STATE_NAME,STATE_FIPS,SUB_REGION,STATE_ABBR,POP1990,POP2000,POP90_SQMI from ARCPYMAPPING_01.APM_PRO_states WHERE SUB_REGION = 'Mtn'"
qlyr.setDefinition(cim_qlyr) Data connection info is also there. Does this work for you? Jeff - Layout and arcpy.mp teams
... View more
3 weeks ago
|
0
|
0
|
58
|
IDEA
|
I just started to build a more complete solution to this specific workflow and other workflows that came up during the User Conference. I'll combine several solutions into one downloadable sample. While I was building this workflow I realized a couple of extra steps. First, if you simply disable a map series, any dynamic map series text or queries, etc will not work so your resulting duplicated layout will not display correctly. Second, I found it better to remove the map series instead of disable it because once you replace the dynamic nature of these elements, re-enabliing the map series will not re-create the dynamic capabilities. In the script below, you can see I have code to first remove the dynamic nature of map series to be hard coded BEFORE I remove the map series from the layout using Python CIM access. pageList = arcpy.GetParameter(0) #List of selected pages via script tool
removeMS = arcpy.GetParameter(1) #Boolean to remove map series from copied layout
#Reference the current project and layout
p = arcpy.mp.ArcGISProject('CURRENT')
lyt = p.listLayouts('Duplicate')[0]
#Confirm there is a map series
if not lyt.mapSeries is None:
ms = lyt.mapSeries
#Confirm the map series is enabled
if ms.enabled:
#Iterate through each choosen page
for page in pageList:
#Set the current map series page based on page name
ms.currentPageNumber = ms.getPageNumberFromName(page)
#Make the duplicate copy with new name
cpLyt = p.copyItem(lyt, 'Copy_' + page)
#Optional - remove the map series
if removeMS:
#Must convert title text from dynamic to static
title = cpLyt.listElements('Text_Element', 'Title')[0]
title.text = page
#Must convert table frame from dynamic to static
m = p.listMaps('Duplicate')[0]
lyr = m.listLayers('State Outlines')[0]
lyr.definitionQuery = f"STATE_NAME = '{page}'"
#Remove map series
cpLyt_cim = cpLyt.getDefinition('V3')
cpLyt_cim.mapSeries = None
cpLyt.setDefinition(cpLyt_cim) I hope to make the samples available soon, Jeff - Layout and arcpy.mp teams
... View more
3 weeks ago
|
0
|
0
|
56
|
IDEA
|
@HaydenWelch I completely understand your point of view. Are you also saying that in the UI, you have to refresh to ensure you get the proper export? That would definitely be a bug (the UI export or arcpy.mp export should always render proper output). Pro should automatically update and we purposely did not include a refresh option (like we had in ArcMap arcpy.mapping) because Pro's underlying architecture/services should do the automatic refresh. If they are not working, then we need to address that. It might be possible to provide a refresh option but I want to make sure we are providing the correct solution. Refresh my be a workaround but also an unnecessary step that will also be a performance hit. I hope this make sense. If I could get some clarification on your workflow and possible repro steps, then we can make sure a proper fix/solution is provided.
... View more
3 weeks ago
|
0
|
0
|
113
|
IDEA
|
@HaydenWelch , thanks for the feedback. I'd like to know what type of layout elements are not updating for you. Ideally, layouts should automatically refresh on their own without having force a refresh. There are some core geoprocessing operations that may update data behind the scenes that doesn't trigger components in the app to refresh. At Pro 3.3 the core Arcpy team introduced arcpy.RefreshLayer() that should trigger the appropriate updates in the App when data is being modified. Another way to get the Layout to redraw is to use something like: p = arcpy.mp.ArcGISProject('current')
lyt = p.listLayouts('Some Layout')[0]
lyt_cim = lyt.getDefinition('V3')
lyt.setDefinition(lyt_cim) The code above forces the layout and its elements to redraw BUT DOES NOT force underlying data to update. That is what arcpy.RefreshLayer(). MapSeries.refresh() is for situations where data in the index layer has been updated. Think of it as a specialized version of arcpy.RefreshLayer(). If this helps solve your issue, great, but if you there is a reason you really need to refresh a layout that is not data specific, please let us know. Jeff - Layout and arcpy.mp teams
... View more
3 weeks ago
|
0
|
0
|
120
|
IDEA
|
@ShannonJ Below is a snippet of code. Keep in mind that there are number of different approaches and things to consider. In the example below, I'm exporting a Layout, not a map series. If you have dynamic text and other features managed by the map series, then you could need to update that using arcpy. import arcpy, os, sys relpath = os.path.dirname(sys.argv[0]) p = arcpy.mp.ArcGISProject(os.path.join(relpath, 'MapSeriesExamples.aprx')) m = p.listMaps('StatesWithRegions')[0] l = m.listLayers('States_WithRegions')[0] #unique values in layer all_values = [row[0] for row in arcpy.da.SearchCursor(l, 'sub_region')] unique_values = set(all_values) print(unique_values) #reference layout and map frame lyt = p.listLayouts('BasedOnSelection')[0] mf = lyt.listElements('MapFrame_Element', 'ZoomToRegion')[0] #create comboPDF = arcpy.mp.PDFDocumentCreate(os.path.join(relpath, 'Output', 'CombinedOutput.pdf')) #iterate through the unique list of field values and: # - create a selection # - set the map frame extent to that selection # - export to temp PDF, combine into combo pdf, then delete the temp pdf # - clear the selection for value in unique_values: query = f"SUB_REGION = '{value}'" arcpy.SelectLayerByAttribute_management(l, 'NEW_SELECTION', query) mf.camera.setExtent(mf.getLayerExtent(l, True, True)) lyt.exportToPDF(os.path.join(relpath, 'Output', 'temp.pdf')) comboPDF.appendPages(os.path.join(relpath, 'Output', 'Temp.pdf')) os.remove(os.path.join(relpath, 'Output', 'Temp.pdf')) arcpy.SelectLayerByAttribute_management(l, 'CLEAR_SELECTION') comboPDF.saveAndClose() os.startfile(os.path.join(relpath, 'Output','CombinedOutput.pdf')) print('Finished') Jeff
... View more
07-08-2024
07:45 AM
|
0
|
0
|
166
|
IDEA
|
@ShannonJ would you be interested in an Python Map Automation (arcpy.mp) snippet. What it would do is get a list of unique field values to iterate over, select all features with that value, set the extent of the map frame to the selected features, and export before moving onto the next unique value. Individual pages could be generated or, if a PDF, optional, appended all into a single PDF. Jeff - arcpy.mp and Layout teams
... View more
07-05-2024
02:11 PM
|
0
|
0
|
203
|
Title | Kudos | Posted |
---|---|---|
1 | a week ago | |
1 | a week ago | |
1 | 2 weeks ago | |
1 | 02-09-2024 03:08 PM | |
1 | 01-23-2024 09:51 AM |
Online Status |
Offline
|
Date Last Visited |
2 weeks ago
|