Hinzufügen einer Ebene zum Öffnen von mxd mithilfe von ArcObjects von außerhalb des Kartendokuments stürzt in ArcMap ab

8

Ich habe eine Access-Datenbank (MS Access 2010), mit der Benutzer eine Vielzahl von Landbehandlungsinformationen eingeben können, einschließlich zugehöriger Punkte, Linien oder Polygone, die Benutzer auswählen können. Die Datenbank wird dann als Teil des Projekts in eine Master-Geodatabase geladen. und ermöglichen Sie dem Benutzer, die Features in einer ArcMap anzuzeigen. In Arc 9.3 wurde dies alles mit VBA erreicht und funktionierte gut. Aufgrund des Upgrades auf Arc 10 ist VBA keine Option mehr und ich habe gelernt, wie man in Python programmiert und die Befehle über Access mithilfe der Shell-Funktion aufruft. Ich habe fast alles abgeschlossen, bis auf die Möglichkeit, Benutzern das Hinzufügen ihrer Funktion zum aktuellen ArcMap-Dokument zu ermöglichen. Hier sind die Schritte, die ausgeführt werden sollten.

1) Der Benutzer klickt im Access-Programm auf eine Schaltfläche, mit der die gewünschten Funktionen identifiziert werden.

2) Der Zugriff bestimmt, ob der richtige mxd geöffnet ist und wenn nicht, wird er geöffnet (das Dokument ist normalerweise geöffnet, sodass dieser Schritt häufig nicht erforderlich ist).

3) Das Python-Skript wird mit dem Python-Shell-Befehl geöffnet, identifiziert das richtige und geöffnete mxd und fügt dem geöffneten ArcMap-Dokument eine Funktion hinzu

Ich habe sowohl arcpy als auch ArcObjects ausprobiert. Ich kann arcpy innerhalb der geöffneten Map ausführen, aber das Öffnen einer Python-Datei über VBA in MS Access manipuliert das geöffnete mxd nicht. Das ESRI-Forum schlug vor, mit ArcObjects zu arbeiten. Ich habe Code gefunden und verwendet, um Layer zu identifizieren und zu bearbeiten, die bereits in das ArcMap-Dokument von Interesse geladen wurden, bin aber völlig fest davon überzeugt, wie man einen neuen Layer identifiziert und hinzufügt. Hier ist der Code, ich denke, es wird funktionieren, wenn ich die Layer-Datei im letzten Codeabschnitt korrekt identifizieren kann. Zumindest läuft alles ohne den pMap.AddLayer (FC) am Ende des Codes, aber ich bin ein Ökologe und kein ausgebildeter Programmierer, sodass mir möglicherweise noch etwas fehlt. Jede Hilfe wäre dankbar.

Update: Ich bin jetzt sehr nah dran. Ich kann das Feature in der Geodatabase identifizieren, aber jetzt stürzt ArcMap ab, wenn versucht wird, die Daten zur Karte hinzuzufügen, und ich generiere den Fehler: COMError: (-2147467259, 'Nicht angegebener Fehler', (Keine, Keine, Keine, 0, Keine)) . Meine Ausgabe scheint jedoch die richtige Funktion zu identifizieren. Ich bin mir nicht sicher, warum ArcMap abstürzt. Bitte helfen Sie, ich bin so nah.

import arcpy
from arcpy import env
import os
import sys
import comtypes.gen.esriArcMapUI as esriArcMapUI
import comtypes.gen.esriCarto as esriCarto
import comtypes.gen.esriGeoDatabase as esriGeoDatabase
import comtypes.gen.esriFramework as esriFramework
import comtypes.gen.esriSystem as esriSystem
import comtypes.gen.esriDataSourcesFile as DataSourcesFile

#Eventaully these will be the arguments that call the feature
#test = sys.argv[0]
#Name = sys.argv[1]
#Alias = sys.argv[2]

def NewObj(MyClass, MyInterface):
    from comtypes.client import CreateObject
    try:
        ptr = CreateObject(MyClass, interface=MyInterface)
        return ptr
    except:
        return None

def CType(obj, interface):
    try:
        newobj = obj.QueryInterface(interface)
        return newobj
    except:
        return None

def GetApp():
    """Get a hook into the current session of ArcMap""" 
    #from comtypes.gen import esriFramework
    pAppROT = NewObj(esriFramework.AppROT, esriFramework.IAppROT)
    if pAppROT is not None:
        iCount = pAppROT.Count 
        if iCount == 0: 
            print 'No ArcGIS application currently running.  Terminating ...' 
            return None 
        for i in range(iCount): 
            pApp = pAppROT.Item(i)  #returns IApplication on AppRef
            print pApp.Name
            if pApp.Name == 'ArcMap': 
                print "ArcMap found"
                pDoc = pApp.Document
                print pDoc.Title
                if pDoc.Title == "CreateShapefile10x.mxd" or pDoc.Title == "CreateShapefile10x":
                    return pApp 
    print 'No ArcMap session is running at this time.' 
print "No AppROT found"
print "Failed"
return None

pApp = GetApp()

try:
    pDoc = pApp.Document
    pMxDoc = CType(pDoc, esriArcMapUI.IMxDocument)
    pMap = pMxDoc.FocusMap
    if pMap.Name == "LTDL Layers":

        ###New Code###

        sPath = r"Y:\LTDL_Data\LTDL_Files\Abate_Seeding_1965\Abate_Seeding_1965.gdb"
        sPath1 = r"Abate_Seeding_1965"
        pWSF = NewObj(esriDataSourcesGDB.FileGDBWorkspaceFactory, esriGeoDatabase.IWorkspaceFactory)
        print pWSF
        pWS = pWSF.OpenFromFile(sPath, 0)
        pDS = CType(pWS, esriGeoDatabase.IDataset)

        print "Workspace name: " + pDS.BrowseName
        print "Workspace category: " + pDS.Category

        FWSS = CType(pWS, esriGeoDatabase.IFeatureWorkspace)
        FL = NewObj(esriCarto.FeatureLayer, esriCarto.IFeatureLayer)
        FL.FeatureClass = FWSS.OpenFeatureClass(sPath1)
        print FL
        print FL.FeatureClass.AliasName
        LAN = CType(FL, esriCarto.ILayer)
        LAN.Name = FL.FeatureClass.AliasName + ": Project Boundary"
        print LAN.Name

        ###New Code###

        pMap.AddLayer(FC)
        pLayout = pMxDoc.PageLayout
        pActiveView = CType(pLayout, esriCarto.IActiveView)
        pActiveView.Refresh()
        pMxDoc.UpdateContents
    print "Done"
except:
    print "Failed"
user6287
quelle
1
Versuchen Sie, mit IObjectFactory den Singleton für die Workspace-Factory im richtigen Prozess wie in dieser Frage zu erstellen: ArcMap / ArcObjects - Zeichnen von Grafiken auf dem Bildschirm: Erläuterung oder Lernprogramm für Draw / Refresh / PartialRefresh-Methoden?
blah238
Es wurde versucht, ein Textelement wie beschrieben hinzuzufügen, und es wurde immer noch ein Fehler ausgegeben. pFact = CType (pApp, esriFramework.IObjectFactory) graphicsContainer = pMxDoc.ActiveView.GraphicsContainer textElement = CType (pFact.Create ("esriCarto.TextElement"), esriCarto.ITextElement) graphicsContainer.AddElement (TextElement) esriCarto.esriViewGraphics, None, None). Als nächstes habe ich eine leere Ebene ohne Datenquelle hinzugefügt und mapAdmin2.FireChangeFeatureClass (OFL, NFC) verwendet, um eine Datenquelle zuzuweisen. ArcMap wurde gestartet und stürzte dann ab und wurde wie zuvor heruntergefahren.
user6287
1
Diese Frage sollte wahrscheinlich geschlossen werden, da der Autor anscheinend das Interesse verloren hat.
blah238

Antworten:

2

Sie fügen Ihrer Karte eine Ebene "FC" hinzu, die "FL" oder "LAN" sein sollte. Entweder der Feature-Layer oder der Layer sollte funktionieren.

Beachten Sie, dass sich die Karte möglicherweise in der Datenansicht anstelle der Layoutansicht befindet. In diesem Fall ist pMxDoc.PageLayout falsch ... Ich kann nicht sagen, was pLayout ist, da es nicht im Codeblock definiert ist.

Es wäre sicherer, IMXDocument.FocusMap zu verwenden, da dies entweder ein Typlayout oder eine Datenansicht sein kann.

Angenommen, pApp ist IApplication:

IMxDocument pDoc = (IMxDocument) pApp.Document;
IMap pMap = pDoc.FocusMap;
pMap.AddLayer(LAN);

OR

(pApp.Document as IMxDocument).FocusMap.AddLayer(LAN);

Normalerweise mache ich das in den drei Zeilen, damit es für den Leser nicht so verwirrend ist.

  • Hoppla! das war C #, mein schlechtes! Die VB ist von hier aus nicht allzu schwer zu trainieren, da Sie bereits mit der pMap = pMxDoc.FocusMap beschäftigt sind.

ps Ich persönlich ziehe es vor, meine Objekte zu dimmen. Dadurch ist es einfacher herauszufinden, was passiert:

dim pMxDoc as IMxDocument = ctype(pApp.Document, IMxDocument)
dim pMap as IMap = pMxDoc.FocusMap

Auf diese Weise weiß der Leser mit Sicherheit, was jedes Objekt ist.

Michael Stimson
quelle
Abgesehen davon, dass diese Frage über anderthalb Jahre alt ist, handelt es sich um Python + comtypes, nicht um C # oder VB.NET. Und ich denke, die FC-Sache war wahrscheinlich nur ein Tippfehler in der Frage und nicht der eigentliche Code, da es NameErrorstattdessen einen gegeben hätte.
blah238
3
Ich habe mir nicht angesehen, wie alt der Thread war, das ist für den nächsten Leser, der hier von Google hierher kommt, nicht wichtig, so wie ich es schon oft getan habe ... so oft hatte ich das Gefühl, ich sollte mitmachen. Eine Frage ist eine Frage, und um der nächsten Leser willen sollte ich auf den offensichtlichen Fehler hinweisen.
Michael Stimson