2

I attended a pretty awesome demonstration from Jeffrey Barrette at the Esri UC a few weeks ago on creating dynamic tables in ArcMap. This functionality will greatly benefit the aviation department at my firm. I have got the scripting all taken care of for creating the dynamic tables in the Layout (using graphic and text elements). However, this works by cloning a horizontal line, vertical line, and two text elements.

I have already got a working function to add a text element to a map layout via comtypes and ArcObjects, but I cannot seem to get the graphic line part correct. I am using some of the basic functions from a modified version of Snippets (from https://bitbucket.org/maphew/canvec/src/eaf2678de06f/Canvec/Scripts/parco.py). Here is my function for adding a horizontal line:

def add_horizontal_line():
    GetDesktopModules()
    import comtypes.gen.esriFramework as esriFramework
    import comtypes.gen.esriArcMapUI as esriArcMapUI
    import comtypes.gen.esriSystem as esriSystem
    import comtypes.gen.esriGeometry as esriGeometry
    import comtypes.gen.esriCarto as esriCarto
    import comtypes.gen.esriDisplay as esriDisplay
    import comtypes.gen.stdole as stdole

    # set mxd
    pApp = GetApp()  #current open mxd
    pDoc = pApp.Document
    pMxDoc = CType(pDoc, esriArcMapUI.IMxDocument)
    pMap = pMxDoc.FocusMap
    pAV = CType(pMap, esriCarto.IActiveView)
    pSD = pAV.ScreenDisplay

    # set coords for elment
    pFact = CType(pApp, esriFramework.IObjectFactory)
    pEnv = pAV.Extent
    x = (pEnv.XMin + pEnv.XMax) / 2
    y = (pEnv.YMin + pEnv.YMax) / 2

    # from point
    pUnk_pt1 = pFact.Create(CLSID(esriGeometry.Point))
    pPt = CType(pUnk_pt1, esriGeometry.IPoint)
    pPt.PutCoords(x, y)

    # to point
    pUnk_pt2 = pFact.Create(CLSID(esriGeometry.Point))
    pPt2 = CType(pUnk_pt2, esriGeometry.IPoint)
    pPt2.PutCoords(x + 500, y) # next point 500 units east to form straight line

    # line (from point - to point)
    pUnk_line = pFact.Create(CLSID(esriGeometry.Line))
    pLg = CType(pUnk_line, esriGeometry.ILine2)
    pLg.PutCoords(pPt, pPt2)

    # preset color according to RGB values
    pUnk_color = pFact.Create(CLSID(esriDisplay.RgbColor))
    pColor = CType(pUnk_color, esriDisplay.IRgbColor)
    pColor.Red, pColor.Green, pColor.Blue = (0,0,0) #black line

    # set line properties
    pUnk_line = pFact.Create(CLSID(esriDisplay.SimpleLineSymbol))
    pLineSymbol = CType(pUnk_line, esriDisplay.ISimpleLineSymbol)
    pLineSymbol.Color = pColor

    # create the actual element
    pUnk_elm = pFact.Create(CLSID(esriCarto.LineElement))
    pLineElement = CType(pUnk_elm, esriCarto.ILineElement)
    pLineElement.Symbol = pLineSymbol
    pElement = CType(pLineElement, esriCarto.IElement)
    pElement.Name = 'horizLine'
    pElement.Geometry = pLg

    # add to map
    pGC = CType(pMap, esriCarto.IGraphicsContainer)
    pGC.AddElement(pElement, 0)
    pGCSel = CType(pMap, esriCarto.IGraphicsContainerSelect)
    pGCSel.SelectElement(pElement)
    iOpt = esriCarto.esriViewGraphics + \
    esriCarto.esriViewGraphicSelection
    pAV.PartialRefresh(iOpt, None, None)
    return 

I am getting an Error (parameter is incorrect) in this line:

pElement.Geometry = pLg

However, from the API reference it says the ILine2 interface PutCoords method can be used to set coordinates of the line using a FromPoint and ToPoint (IPoint objects). My understanding of ArcOjbects is not very strong, but it seemed from help docs that this would work. I even tried to explicitly set the pLg.FromPoint and ToPoint passing in the appropriate coordinates and that did not work either. Does anyone know what I'm doing wrong here?

4

Try replacing this line:

pUnk_line = pFact.Create(CLSID(esriGeometry.Line))

with this:

pUnk_line = pFact.Create(CLSID(esriGeometry.Polyline))

In the help on LineElementClass is says right at the bottom:

Geometry: LineElement accepts geometry of type esriGeometryPolyline. The Polyline is used as the geometry with which the symbol is drawn.

  • Thanks (Duncan?). That sounded promising, but unfortunately it did not work. Now it does not seem to create an ILine2 interface instance. My pLg variable is returned as a NoneType which not to my surprise I get the error "NoneType" object has no attribute PutCoords. – crmackey Jul 30 '14 at 15:16
  • 1
    Well I've never actually attempted to use ArcObjects via Python but I do use it in VB. Don't worry the code looks OK to me it's some quirk that needs ironing out. – Hornbydd Jul 30 '14 at 15:24
  • 1
    I would add it's always nice to see some comments in the code, can't get enough of that especially in ArcObjects! :) – Hornbydd Jul 30 '14 at 15:27
  • 1
    And if I could bug you one more time, for some reason the pElement.Name property is not being set. I just looked back in the help docs and I see why...That is because apparently I made that up because it has no "Name" property. Any ideas on how to name an element? Or just what interface I'd do that in? I could probably figure it out from there. Once I have the element named, I can get at it with arcpy mapping. Edit - Nevermind, got it! Found the IElementProperties interface! I'm loving the power of ArcObjects...Now I just need to learn C# or VB :) – crmackey Jul 30 '14 at 15:44
  • 1
    I think you only ever crack ArcObjects when you fully accept that navigating the help file is the first thing you must do. It's usually all in there. But there are many parts of the help file that simply don't give you enough information or examples and then you end up at websites like these. – Hornbydd Jul 30 '14 at 15:57

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.