How to assign name to map layer in APRX when importing from MXD?

1503
3
02-12-2019 03:23 PM
Arne_Gelfert
Occasional Contributor III

Background:
I am tasked with rebuilding a bunch of web maps for ArcGIS Server (Enterprise) using set of MXD's behind existing map services. One reason I am doing it through ArcGIS Pro is to play with the new scale based symbologies for Map Image Layers versus creating multiple layers. At the same time, I want to script out map service publishing for any simple maps using arcpy. Starting with a large number of MXD's, I imported them into a blank APRX.

Here is how I grab my list of MXD's:

mxdpath = r'U:\pydev\portal\republish_hou\mxdlist.txt'
with open(mxdpath) as f:
   mxdlist = [mxd.strip() for mxd in f.readlines()]‍‍‍

Then I start importing the MXD's one by one as maps into a new blank project file, which I created inside ArcGIS Pro.

import arcpy
aprx = arcpy.mp.ArcGISProject(r'c:\temp\blank.aprx')

for mxd in mxdlist:
   #### To be able to see which maps are going in, I add the following print stmt
   print("Importing the following....{0}".format(mxd.split('\\')[-1]))
   aprx.importDocument(mxd,include_layout=False)

   #### The following was to keep an eye on total count of maps
   print("Currently {0} maps in Project file.".format(len(aprx.listMaps())))

   #### Here I'm attempting to name the maps with the name of the source MXD
   aprx.listMaps()[-1].name = mxd.split('\\')[-1][:-4]

aprx.saveACopy(r'c:\temp\no_longer_blank.aprx')‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍


This seemed to work fine for a small sample, 3-4 MXD's.  In my case, I then tried web map #1 with has 32 MXD files, and it looked like it worked.

len(mxdlist)
>32
len(aprx.listMaps())
>32‍‍‍‍

But when it look at the names of the maps, I find that some are missing, and have been replaced with names such as "Layers", "Layers1, "Layers2". 

cnt = 0
while True:
   if aprx.listMaps()[cnt]:
      print(cnt," ",aprx.listMaps()[cnt].name)
      cnt += 1
   else:
      break

In fact, there is a strange pattern of which names are missing:

>0 Counties
1 Layers
2 Cities
3 Buildings
4 Roads
5 Rivers
6 Playgrounds
7 Lakes
8 Hospitals
9 Churches
10 Hydrants
11 Layers1
12 Rubberduckies
13 Monuments
14 PoliceStations
15 SevenElevens
16 ParkingLots
17 States
18 ZipCodes
19 Districts
20 Divisions
21 Layers2
22 Parks
23 Schools
24 Colleges
25 Geocaches
26 Hotels
27 GasStations
28 SwimmingPools
29 Museums
30 Cemeteries
31 Flamingos‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

What's going on here? Each MXD has a name that's a valid string, that should be used for naming the map inside the APRX. Why does this fail for maps 1, 11, and 21? It looks like my reference to the last map in the list doesn't work. In fact, the maps called "Layers" contain the data from other "named" maps, e.g. 'States'. Then 'States' gets completely different input and not what should be coming from 'States.mxd'.

Now, let's try this. Let's not try to name the maps at all. Let them remain nameless. When script finishes,...

[m.name for m in aprx.listMaps()]
>['Layers',
 'Layers1',
 'Layers10',
 'Layers11',
 'Layers12',
 'Layers13',
 'Layers14',
 'Layers15',
 'Layers16',
 'Layers17',
 'Layers18',
 'Layers19',
 'Layers2',
 'Layers20',
 'Layers21',
 'Layers22',
 'Layers23',
 'Layers24',
 'Layers25',
 'Layers26',
 'Layers27',
 'Layers28',
 'Layers29',
 'Layers3',
 'Layers30',
 'Layers31',
 'Layers4',
 'Layers5',
 'Layers6',
 'Layers7',
 'Layers8',
 'Layers9']

aprx.listMaps(0)[2].name
>'Layers10'‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

So looks like the ordering of the maps in that list goes like 1,10,11,12,13,....2,20,21,22....  I'm sorry maybe there is a good reason for that. But it makes no sense to me. If you have a working solution to offer on how I should name my maps during import, please share. Maybe I've missed something in the documentation.

3 Replies
Arne_Gelfert
Occasional Contributor III

Duh! - I think I should've answered this myself in the same breath with asking the question. Each new map gets the default name 'Layers" unless that's already taken, in which case it becomes "Layers1"... so simply referencing that new layer as "Layers" instead of the [-1] index works. As such:

aprx.listMaps('Layers')[0].name = mxd.split('\\')[-1][:-4]
0 Kudos
JaredPilbeam2
MVP Regular Contributor

Hi Arne,

When you saveACopy were you able to save an individual aprx file for each map? That would be ideal. I have a script largely based off yours but it's saving all six of my test maps in one project (aprx). I put the saveACopy in the for loop and left it out, but same difference.

import arcpy, os

#List MXDs in workspaceMXD  
workspaceMXD = r"C:\gisfile\GISmaps\AtlasMaps\ATLAS_MAPS_20\TestFolder"
arcpy.env.workspace = workspaceMXD
arcpy.env.overwriteOutput = True
mxdlist = arcpy.ListFiles("*.mxd")

#aprx project
aprx = arcpy.mp.ArcGISProject(r"C:\gisfile\GISmaps\AtlasMaps\MXDtoAPRX_tempdelete\MXDtoAPRX_tempdelete.aprx")

for mxd in mxdlist:
    fullpath = os.path.join(workspaceMXD, mxd)
    print("Importing: {}".format(fullpath))
    aprx.importDocument(fullpath)

    #the count of the maps
    print("Currently {0} maps in Project file.".format(len(aprx.listMaps())))

    #name the maps
    aprx.listMaps()[-1].name = mxd.split("\\")[-1][:-4]

aprx.saveACopy(r"C:\gisfile\GISmaps\AtlasMaps\ATLAS_MAPS_20\TestFolder.aprx")
0 Kudos
Arne_Gelfert
Occasional Contributor III

I think you'd have to save your copy inside the loop. Close the aprx. Set the aprx variable back to an empty aprx and import the next mxd. Haven't tried it but that should work. In my case, I wanted to have all the maps together in one project.