1

I want to batch insert WMS layer to my arcmap MXD project with python/arcpy script.

Some issues has been unanserwed, here my "state of art":

All of these solution propose to use

  1. ArcMap to Add WMS layer manually
  2. do "Save as Layer File"
  3. reuse the .lyr to add to a new TOC by arcpy with this code

    mxd = arcpy.mapping.MapDocument("CURRENT")  
    df = arcpy.mapping.ListDataFrames(mxd)[0]   
    imagery_lyr = arcpy.mapping.Layer(r"path\to\.lyr")  
    arcpy.mapping.AddLayer(df, imagery_lyr)  
    

The lastest idea work properly with "static" WMS services. When you have a "dynamic" changing WMS services, you need to maintain manually all the pre-generated lyr.

Does somebody know how to load WMS layer into ArcMap MXD with arcpy?

Does somebody know how to create .lyr file from WMS with arcpy?

user2856
  • 65,736
  • 6
  • 115
  • 196
PEL
  • 374
  • 1
  • 8

1 Answers1

1

This is not possible in pure arcpy.

It can be done in python, but requires the use of arcobjects. One way to access arcobjects in python is to use the comtypes package.

Firstly install comtypes and get set up with the arcobjects snippets module. See this question for links to the snippets module and for more information on accessing arcobjects from python.

Below is some code, derived from the ArcGIS documentation and the ArcMap CSW Client to generate a layer file of the WMS. You need to write the layer file to disk to be able to use ArcPy to add it to an MXD, but you can delete the file once it's been added to the map.

import sys
import arcview,arcpy
from comtypes import COMError
from snippets import GetModule, CType, NewObj

def ConnectWMS(url):

GetModule("esriSystem.olb")
GetModule("esriCarto.olb")
GetModule("esriGISClient.olb")

import comtypes.gen.esriSystem as esriSystem
import comtypes.gen.esriCarto as esriCarto
import comtypes.gen.esriGISClient as esriGISClient

##Create an WMSMapLayer Instance - this will be added to the map later
pWMSGroupLayer = NewObj(esriCarto.WMSMapLayer, esriCarto.IWMSGroupLayer)

##Create and configure wms connection name, this is used to store the connection properties
pPropSet = NewObj(esriSystem.PropertySet, esriSystem.IPropertySet)
pPropSet.SetProperty("URL", url)
pConnName = NewObj(esriGISClient.WMSConnectionName, esriGISClient.IWMSConnectionName)
pConnName.ConnectionProperties = pPropSet

##Use the name information to connect to the service
pDataLayer = CType(pWMSGroupLayer, esriCarto.IDataLayer)
pName = CType(pConnName, esriSystem.IName)
pDataLayer.Connect(pName)

##Get service description, which includes the categories of wms layers
pServiceDesc = pWMSGroupLayer.WMSServiceDescription

return pWMSGroupLayer,pServiceDesc

def CreateWMSGroupLayer(url, outpath, visible, *layernames):

GetModule("esriCarto.olb")
import comtypes.gen.esriCarto as esriCarto

# Connect to WMS
pWMSGroupLayer,pServiceDesc = ConnectWMS(url)

#Find matching layers
if layernames:
    pLayerDescs=[find_layer(pServiceDesc,l) for l in layernames]

    ##Configure the layer before adding it to the map
    pWMSGroupLayer.Clear()
    for i,pLayerDesc in enumerate(pLayerDescs):
        if pLayerDesc is None:
            # raise  Exception('Unable to find layer "%s"'%layernames[i])
            # warnings.warn('Unable to find layer "%s"'%layernames[i])
            sys.stderr.write('Warning: Unable to find layer "%s"\n'%layernames[i])
            continue
        pWMSMapLayer = pWMSGroupLayer.CreateWMSLayer(pLayerDesc)
        CType(pWMSMapLayer, esriCarto.ILayer).Visible=visible
        pWMSGroupLayer.InsertLayer(pWMSMapLayer, i)

pLayer = CType(pWMSGroupLayer, esriCarto.ILayer)
pLayer.Visible=visible

##create a new LayerFile and populate it with the layer
pLayerFile = NewObj(esriCarto.LayerFile, esriCarto.ILayerFile)
pLayerFile.New(outpath)
pLayerFile.ReplaceContents(pLayer)
pLayerFile.Save()

return outpath


def find_layer(servicedesc, layername): '''Recursive layer matching. Recursion is necessary to handle non data (folder/subfolder) "layers"''' layer = None for i in range(servicedesc.LayerDescriptionCount): layerdesc = servicedesc.LayerDescription(i) if layerdesc.LayerDescriptionCount == 0: if layerdesc.Name == layername: return layerdesc else: continue layer = find_layer(layerdesc, layername) if layer:break return layer

if name == 'main': url = 'http://someserver/ogc/wms?' path1 = r'C:\Temp\test1.lyr' path2 = r'C:\Temp\test2.lyr' path3 = r'C:\Temp\test3.lyr' try: #All layers lyr = CreateWMSGroupLayer(url, path1, visible=False) #A couple of layers lyr = CreateWMSGroupLayer(url, path2, False, 'lyr0', 'lyr1') #A single layer lyr = CreateWMSGroupLayer(url, path3, False, 'lyr2')

except COMError as e:
    print('Unable to add WMS')

user2856
  • 65,736
  • 6
  • 115
  • 196
  • Here a related question (http://gis.stackexchange.com/questions/62147/how-to-add-individual-layer-of-wms-group-layer-to-arcmap) – PEL Mar 29 '16 at 14:56