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?

  • I would like to add a specific layer. – PEL Mar 29 '16 at 13:50
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):
    #Luke Pinner 2014

    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):
    #Luke Pinner 2014

    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')
  • This solution work perfectly. I've installed snippets for ArcGIS 10.3. I've simply downloaded the Snippets102.py and replace inside every 10.2 by 10.3. I do not close the quetion because I would like to know if it is possible to add only ONE layer. Not all the layers. – PEL Mar 29 '16 at 14:44
  • Here a related question (gis.stackexchange.com/questions/62147/…) – PEL Mar 29 '16 at 14:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.