So I am trying to create an excel document that list all of my feature services / feature collections and what specific maps they are in, so far I have this, but when it runs it lists all my services in Column A, but then Column B is blank, any idea what could be happening? I am very new to python. Any help would be appreciated.
import arcgis
import openpyxl
# Set the URL of your ArcGIS Online portal
portal_url = 'https://yourportal.arcgis.com'
# Set your ArcGIS Online username and password
username = 'your_username'
password = 'your_password'
# Connect to the portal
gis = arcgis.GIS(portal_url, username, password)
# Search for all feature services and feature collections in the portal
items = gis.content.search(query='type: "Feature Service" OR type: "Feature Collection"', max_items=5000)
# Create a new Excel workbook
workbook = openpyxl.Workbook()
worksheet = workbook.active
# Add a header row to the worksheet
worksheet.append(['Feature Service/Collection', 'Maps Using Feature'])
# Iterate through the feature services and feature collections
for item in items:
# Search for maps in the portal that use the feature service or feature collection as a layer
maps = gis.content.search(query=f'type: "Web Map*" AND layers: {item.id}', max_items=5000)
# Create a list of the map names
map_names = [map.title for map in maps]
# Add a row to the worksheet with the feature service/collection name and the list of map names
worksheet.append([item.title, *map_names])
# Save the workbook to a file
workbook.save('feature_services_maps.xlsx')
When I tested this, I was getting an empty empty list when I printed the map_names list. Are you sure it is populating? I would try building in some print statements to test your results.
This is what the output looks like for me, I am using Enterprise 10.8.1, it seems like it is picking up more than just services but the built in esri tools as well.
your map_names variable is trying to populate a list with map.title, and it errors out telling me that map has no attribute 'title'
As I think it's more reliable that way.
I'm also not 100% sure you can query a webmap on its layers using the gis.content.search function. I wrote some code to search webmaps for all services in a portal/agol instance to find services that were unused, which you can find here https://github.com/joshsharpheward/gis-administration/blob/master/find_unused_services.py which I think you could modify to do what you need or at least use for inspiration!
So modifying a little of what you your code is, I was able to get the output of every map and every service inside of the map using this:
from arcgis.gis import GIS
from arcgis.mapping import WebMap
import arcpy
import pandas as pd
def main():
# logs into active portal in ArcGIS Pro
gis = GIS('pro')
arcpy.AddMessage("Logged into {} as {}".format(arcpy.GetActivePortalURL(), gis.properties['user']['username']))
# creates list of items of all map image, feature, vector tile and image services (up to 10000 of each) in active portal
services = (gis.content.search(query="", item_type="Map Service", max_items=10000) +
gis.content.search(query="", item_type="Feature Service", max_items=10000) +
gis.content.search(query="", item_type="Vector Tile Service", max_items=10000) +
gis.content.search(query="", item_type="Image Service", max_items=10000))
arcpy.AddMessage('Searching webmaps in {}'.format(arcpy.GetActivePortalURL()))
# creates list of items of all webmaps in active portal
web_maps = gis.content.search(query="", item_type="Web Map", max_items = 10000)
# Create an empty data frame to store the data
df = pd.DataFrame(columns=['Web Map', 'Service URL'])
# loops through list of webmap items
for item in web_maps:
# creates a WebMap object from input webmap item
web_map = WebMap(item)
# accesses basemap layer(s) in WebMap object
basemaps = web_map.basemap['baseMapLayers']
# accesses layers in WebMap object
layers = web_map.layers
# loops through basemap layers
for bm in basemaps:
# tests whether the bm layer has a styleUrl(VTS) or url (everything else)
if 'styleUrl'in bm.keys():
for service in services:
if service.url in bm['styleUrl']:
services.remove(service)
elif 'url' in bm.keys():
for service in services:
if service.url in bm['url']:
services.remove(service)
# loops through layers
for layer in layers:
# Add a new row to the data frame for each service used in the web map
if hasattr(layer, 'styleUrl'):
df.loc[len(df)] = [item.title, layer.styleUrl]
elif hasattr(layer, 'url'):
df.loc[len(df)] = [item.title, layer.url]
# Save the data frame to an Excel file
df.to_excel('web_maps.xlsx', index=False)
if __name__ == "__main__":
main()
Very useful script. I had a go at modifying it further to return the layers item ID and spatial reference as well, but failed. Anyone have any idea's on how to do that?