ArcMapの結合フィールドをプログラムで識別しますか?


9

ArcMapで2つのデータセットをテーブル結合するために使用されている結合フィールドをプログラムで識別することは可能ですか?現在、ArcGIS 10.0、SP5を使用しており、ArcPyソリューションを希望しますが、ArcPyソリューションが利用できない場合でも、他のソリューションに反対することはありません。

私が試した方法の1つは、すべてのフィールドをループして、一致する「baseName」を探すことでしたが、これは、両方のデータベースのフィールド名が同じであることを期待している「教育的な推測」にすぎません。

私が求めているものをグラフィックで表現するために、基本的には「結合の追加」ダイアログに表示される「入力結合フィールド」と「出力結合フィールド」を識別したいと思いますが、もちろん事後です。

「入力結合フィールド」と「出力結合フィールド」を識別する方法は?

これは、「参加」をプログラムで検出できるかどうかに関するタグ付きの質問です。、しかしこの場合、2つ(またはそれ以上)のデータセットを結合するために使用されているFIELDを識別する機能を拡張したいと思います。


どのバージョンのArcGISを使用していますか?そして、私はあなたが具体的にこれをArcObjectsではなくarcpyで行う方法を探しているタグに基づいていると思いますか?
blah238 2013

現在、ArcGIS 10.0、SP5を使用しています。そして、はい、私はArcPyソリューションを探しています/期待していますが、それが唯一の選択肢である場合、ArcObjectsソリューションに反対することはありません。
RyanKDalton 2013

1
これは、おそらく魅力的なドキュメントです:edndoc.esri.com/arcobjects/9.2/ComponentHelp/esriGeoDatabase/…これにはpRelClassが含まれますこれは、結合テーブルと結合フィールド、およびカーディナリティを定義するために使用されるRelationshipClassです。Openメソッドは、新しいRelQueryTableを作成するか、そのクラスが既に作成されている場合は既存のRelQueryTableへの参照を返します。このメソッドを呼び出して、pRelClassを含む参照を見つけることができます
lewis

@lewis、既存のRelQueryTableへの参照を取得するためにファクトリオブジェクトを使用する必要はありません-私の回答を参照してください。
blah238 2013

回答:


7

このに基づいた、レイヤー上のすべての結合を列挙し、それらの宛先とソースのテーブル名、およびプライマリキーと外部キーをリストするためのArcObjectsアプローチを次に示します。

  1. ILayer1つ以上の結合を持つへの参照を取得します
  2. キャストILayerするIDisplayTable
  3. IDisplayTable.DisplayTableプロパティをキャストしますIRelQueryTable
  4. 現在のテーブルはIRelQueryTable
    1. 点検RelQueryTableDestinationTableSourceTableプロパティを
    2. プロパティのOriginPrimaryKeyおよびOriginForeignKeyプロパティを調べIRelQueryTable.RelationshipClassます。
    3. 現在のテーブルをcurrent RelQueryTableSourceTableプロパティに設定します

このPythonスクリプト(comtypesとこのヘルパーモジュールを使用)は、最新のものから最も古いものまですべての結合を処理し、各結合の宛先およびソーステーブル名、起点のプライマリキー、起点の外部キーを出力します。

from ESRICOMHelpers import * # helper module from https://gis.stackexchange.com/a/5082/753
esriArcMapUI = GetESRIModule("esriArcMapUI")
esriCarto = GetESRIModule("esriCarto")
esriGeoDatabase = GetESRIModule("esriGeoDatabase")

def listJoins(table):
    while CType(table, esriGeoDatabase.IRelQueryTable):
        relQueryTable = CType(table, esriGeoDatabase.IRelQueryTable)
        destTable = relQueryTable.DestinationTable
        sourceTable = relQueryTable.SourceTable
        destDataset = CType(destTable, esriGeoDatabase.IDataset)
        sourceDataset = CType(sourceTable, esriGeoDatabase.IDataset)
        relClass = relQueryTable.RelationshipClass
        print destDataset.Name, sourceDataset.Name, relClass.OriginPrimaryKey, relClass.OriginForeignKey
        table = sourceTable

if __name__ == "__main__":
    #app = GetCurrentApp() # Use if run in-process
    app = GetApp("ArcMap") # Use if run in a standalone script
    mxd = CType(app.Document, esriArcMapUI.IMxDocument)

    # Gets the first layer in the active data frame
    map = mxd.FocusMap
    lyr = map.Layer[0]

    # Need to get the "display table" to access the joins
    displayTable = CType(lyr, esriCarto.IDisplayTable).DisplayTable

    # List the layer's joined tables
    listJoins(displayTable)

3つの結合を持つソースレイヤーを指定した場合の出力例:

join_table_3 master_fc_join_table_1_join_table_2 JOIN_ID_3 master_fc.MASTER_ID
join_table_2 master_fc_join_table_1 JOIN_ID_2 master_fc.MASTER_ID
join_table_1 master_fc JOIN_ID_1 MASTER_ID

詳細については、PythonからArcObjectsにアクセスする方法を参照してください


これは非常に有望に見えます。comtypesパッケージをインストールし、ヘルパー関数コードを追加しましたが、エラーが発生します"global name 'esriGeoDatabase' is not defined"。行の前のコードでどこに/どのように定義する必要がありますwhile CType(table, esriGeoDatabase.IRelQueryTable)か?
RyanKDalton 2013

含まれていませんが、ある時点で、必要な特定のESRIオブジェクトライブラリの周りのcomtypesラッパーをインポートする必要があります。私のヘルパーモジュールを使用すると、と同じくらい簡単esriGeoDatabase = GetESRIModule("esriGeoDatabase")です。
blah238 2013

了解、ありがとう。これはArcMapのレイヤーでも機能しますか?各レイヤーをコードに渡しlayerList = arcpy.mapping.ListLayers(mxd)ていlistJoins(table)ますが、whileステートメントではスキップされます。
RyanKDalton 2013

arcpyオブジェクトとcomtypesオブジェクトの間でキャストできないと思うので、ArcObjectsを介してILayer参照を取得する必要があります。より完全な例を含むようにコードを更新しました。これは、関連する行をコメント化/コメント解除することで、プロセスの内外で使用できるはずです。
blah238

近づいて、ウォークスルーの忍耐に感謝します...ここで、見たい実際のマップドキュメントファイル(* .mxd)をどのように送信しましたか? app.Document戻ってくる'NoneType' object has no attribute 'Document'
RyanKDalton 2013

1

フィールドのすべてのデータを文字列に入れ、(それらを順序付けした後)それらをfuzzycompare関数と比較し、特定の精度で最も一致する、または一致しないものを選択します。

この解決策は、一部のデータが収まらない場合です。両方の列が常に収まると思われる場合は、通常の比較関数で完全に一致するかどうかを並べ替えて比較します。


0

これを試して:

  • メタデータツールセットXSLT変換ツールを使用して、問題のデータセットのxml / htmlメタデータファイルを書き出します。

    arcpy.XSLTransform_conversion(r'X:\temp\Scratch.gdb\fc_FeatureToPoint',"C:\Program Files\ArcGIS\Desktop10.1\Metadata\Stylesheets\ArcGIS.xsl", r'X:\temp\Metadata.html')
  • HTMLパーサーを使用してメタデータファイルを読み取り、結合フィールドツールのジオプロセシング履歴から結合フィールドを検索します

  • XSLT変換ツールからの出力例

XSLT変換ツールからの出力


1
これは本当に有望だと思った本当に賢いアイデアですが、私のテストから、「JoinField」と呼ばれるGPツールを使用してファイルを結合した場合にのみ機能するように見えます。これは、GPプロセス履歴の一部として記述されているためです。その層のために。ユーザーがUIを介して結合を作成した場合、JoinFieldプロセス行は出力ファイルに存在しません。素晴らしいアイデアです!
RyanKDalton 2013

1
とにかく、これについてはGPの履歴には依存しません。繰り返し発生するプロセスでは、フィーチャクラスがほとんど使用できなくなる大量のデータにすばやくマウントされるため、できるだけ早く削除するようにしています。
blah238 2013

-1

結合されたテーブル名はIFeatureLayer-IFeatureLayerDefinitionオブジェクトに文字列として存在します。おそらく結合SQLとフィールド名が含まれていると思います。

http://edndoc.esri.com/arcobjects/8.3/diagrams/Map%20Layer%20Object%20Model.pdf

それとも、そのオブジェクトにアクセスできないということですか?


IFeatureLayerDefinition「結合SQL」は含まれません。DefinitionExpressionフィーチャレイヤーの定義クエリを公開するプロパティが設定されている場合にのみ表示されます。これは、表示される行を制限するWHERE句です。
blah238 2013

RelationshipClassただし、プロパティはありますが、これは最新の結合のみを公開していると思います。IRelQueryTableそれらをすべて取得するには、代わりにを使用する必要があります。
blah238 2013

-2

フィールド名に関係なく一致するフィールドを見つけるには、次のようにします。

import arcpy

fc = r"temp/RiversJoined.shp"

fldList1 = [f.name for f in arcpy.ListFields(fc)]
fldList2 =[g.name for g in arcpy.ListFields(fc)]

for f in fldList1:
    values1 = [f_row[0] for f_row in arcpy.da.SearchCursor(fc, (f))]
    for g in fldList2:
        values2 = [g_row[0] for g_row in arcpy.da.SearchCursor(fc,(g))]
        #compare field values
        #get names of matching fields
        if (fldList2.index(g) != fldList1.index(f) and values1 == values2):
            print "match: " + str(g) + " match: "+ str(f)

私の答えをノックした人にねえ:私の答えのどこが悪いのか教えてくれませんか?ありがとう。
mwil 2013

1
これは、質問されたとおりの質問には答えていないようです。ファジー比較の回答と同じです。フィールドが同一である(またはあいまいに類似している)場合、それらが実際に結合で使用されているかどうかには関係ありません。
blah238 2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.