Mengubah kelas fitur dan alias bidang secara massal menggunakan ArcPy?

14

Saya memiliki lebih dari seratus FC, masing-masing dengan 10 atau 20 atribut untuk menambah atau mengubah alias untuk, dua atau lebih kali setahun. Tak perlu dikatakan, ini bukan sesuatu yang saya akan dengarkan melalui saya. Bagaimana saya mengotomatiskan proses ini?

Solusi Python lebih disukai tetapi akan menggunakan apa pun yang berfungsi.

Saya memiliki akses ke Arcgis 9.3.1 dan 10 (tingkat lisensi ArcInfo).

matt wilkie
sumber
1
Saya menemukan [Edit Fitur Skema Kelas] [1] sampel pengembang v9.3 untuk ArcCatalog. Ini mengubah alias untuk kelas fitur yang dipilih menjadi nilai yang dikodekan dalam skrip. Jadi bukan proses batch tetapi menuju ke arah itu. [1]: resources.esri.com/help/9.3/ArcGISDesktop/com/samples/…
matt wilkie
terkait (blok bangunan fondasi): gis.stackexchange.com/questions/80/…
matt wilkie

Jawaban:

7

Pada versi 10.1 AlterAliasName () dapat digunakan untuk re-alias tabel:

table = r"C:\path\to\connection.sde\OWNER.TABLE"
arcpy.AlterAliasName(table, "table_alias")

Pada versi 10.3 Alter Field dapat digunakan untuk membuat ulang bidang alias:

table = r"C:\path\to\connection.sde\OWNER.TABLE"
arcpy.AlterField_management(table, "FIELD_NAME", new_field_alias="field_alias")
Kelly Thomas
sumber
8

Dengan bantuan dari Mark Cederholm saya memiliki solusi yang berfungsi menggunakan python dan arcobjects . Itu kasar di tepinya, tapi itu menyelesaikan pekerjaan. Setelah mengikuti resep di halaman itu, buat skrip baru yang menggunakan GetLibPath, NewObj, CType, OpenFeatureClassfungsi dari snippets.py. Juga buat tabel ganti nama pencarian dalam format .csv:

Pencarian ke Field Alias ​​(att_code-name_lookup.csv):

Attrib_Name,Alias_Name
CODE,Specification Code
VALDATE,Validity Date
...

Kelas fitur untuk pencarian Alias ​​FC (fc_code-name_lookup.csv):

"FC_Name","AliasName"
"BS_1250009_0","Navigational Aid"
"BS_1370009_2","Residential Area"
...

dan skripnya:

import sys
sys.path.append('k:/code')
from snippets import GetLibPath, NewObj, CType, OpenFeatureClass
sWorkingDir = "k:/code/"
sFileGDB = sWorkingDir + "blank_canvec.gdb"
sResourceDir = "k:/code/"
sFCAliasFile = sResourceDir + "fc_code-name_lookup.csv"
sAttAliasFile = sResourceDir + "att_code-name_lookup.csv"
sProduct = "ArcEditor"

def BuildFieldAliasLookup():
    lookup = {}
    f = open(sAttAliasFile, "r")
    bFirst = True
    for line in f:
        # Skip first line
        if bFirst:
            bFirst = False
            continue
        sTokens = line.replace('"','').split(',')
        sFieldName = sTokens[0]
        sAlias = sTokens[1]
        lookup[sFieldName] = sAlias
    return lookup

def AlterAlias():
    # Initialize
    from comtypes.client import GetModule
    import arcgisscripting
    sLibPath = GetLibPath()
    GetModule(sLibPath + "esriGeoDatabase.olb")
    GetModule(sLibPath + "esriDataSourcesGDB.olb")
    import comtypes.gen.esriGeoDatabase as esriGeoDatabase
    gp = arcgisscripting.create(9.3)

    try:
        gp.setproduct(sProduct)
    except:
        gp.AddMessage(gp.GetMessages(2))

    # Build field alias lookup table
    AttrLookup = BuildFieldAliasLookup()
    # Open alias file and loop through lines
    f = open(sFCAliasFile, "r")
    bFirst = True
    for line in f:
        # Skip first line
        if bFirst:
            bFirst = False
            continue
        sTokens = line.replace('"','').split(',')
        sFCName = sTokens[0]
        sAlias = sTokens[1]
        print "Processing: ", sFCName
        # Open feature class
        try:
            pFC = OpenFeatureClass(sFCName)
        except:
            print "Could not open ", sFCName
            continue
        # Alter feature class alias
        try:
            pSE = CType(pFC, esriGeoDatabase.IClassSchemaEdit)
            pSE.AlterAliasName(sAlias)
        except:
            print "Error altering class alias"
            continue
        # Alter field aliases
        try:
            for sKey in AttrLookup.keys():
                i = pFC.FindField(sKey)
                if i == -1:
                    continue
                sAlias = AttrLookup[sKey]
                pSE.AlterFieldAliasName(sKey, sAlias)
        except:
            print "Error altering field aliases"
    print "Done."

print 'Field <--> Alias lookup table is:', BuildFieldAliasLookup()
print AlterAlias()
matt wilkie
sumber
Ini sangat dekat dengan apa yang saya butuhkan (memperbarui alias bidang). Seperti apa porsi potongan OpenFeatureClass? Kode Mark tidak memiliki bagian itu. Terima kasih
Halo Jasperoid: Anda dapat mengomentari jawaban tertentu dengan mengeklik tautan 'tambahkan komentar', saya telah memigrasikan respons Anda pada jawaban ini.
scw
@Jas Periode, saya memindahkan sebagian besar cuplikan Mark ke modul yang saya sebut parco , yang juga merupakan tempat OpenFeatureClass. Saya tidak ingat membuatnya sendiri, tetapi mungkin saya melakukannya. Bagaimanapun, itu ada di jalur 125 .
matt wilkie
6

Kode ini berfungsi untuk saya di 9.3.1 ...

public static void TestAlterAlias(IApplication app)
{
    // make a dictionary of old/new names
    Dictionary<string, string> nameDict = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
    nameDict.Add("qsectionalias", "qsectionalias2");
    nameDict.Add("sursysalias", "sursysalias2");
    string[] directories =  System.IO.Directory.GetDirectories(@"D:\Projects\EmpireOil\data",@"*.gdb",
        System.IO.SearchOption.TopDirectoryOnly);
    foreach(string dir in directories)
    {
        List<IName> fcnames = GetFCNames(dir);
        foreach (IName fcName in fcnames)
        {
            ChangeFieldAliases(fcName, nameDict);
        }
    }
}

public static void ChangeFieldAliases(IName fcName, Dictionary<string, string> aliasDict)
{
    IFeatureClass fc = (IFeatureClass)fcName.Open();
    IClassSchemaEdit3 cse = (IClassSchemaEdit3)fc;
    ((ISchemaLock)fc).ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);
    SortedList<string, string> changeList = new SortedList<string, string>();
    for (int i = 0; i < fc.Fields.FieldCount; i++)
    {
        string fldName = fc.Fields.get_Field(i).Name;
        string alias = fc.Fields.get_Field(i).AliasName;
        if (aliasDict.ContainsKey(alias))
        {
            changeList.Add(fldName, aliasDict[alias]);
            // set it blank for now, to avoid problems if two fields have same aliasname.
            cse.AlterFieldAliasName(fldName, "");
        }
    }

    // change the alias
    foreach (KeyValuePair<string, string> kvp in changeList)
        cse.AlterFieldAliasName(kvp.Key, kvp.Value);
    ((ISchemaLock)fc).ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
}

public static List<IName> GetFCNames(string wsPath)
{
    List<IName> names = new List<IName>();
    IWorkspaceFactory wsf = new ESRI.ArcGIS.DataSourcesGDB.FileGDBWorkspaceFactoryClass();
    IWorkspace ws = wsf.OpenFromFile(wsPath, 0);
    IEnumDatasetName enumName = ws.get_DatasetNames(esriDatasetType.esriDTAny);
    enumName.Reset();
    IDatasetName dsName = null;
    while ((dsName = enumName.Next()) != null)
    {
        if(dsName is IFeatureClassName)
            names.Add((IName)dsName);
        else if(dsName is IFeatureDatasetName)
        {
            IEnumDatasetName enumName2 = dsName.SubsetNames;
            enumName2.Reset();
            IDatasetName dsName2;
            while((dsName2=enumName2.Next())!= null)
            {
                if(dsName2 is IFeatureClassName)
                    names.Add((IName)dsName2);
            }
        }
    }
    return names;
}
Kirk Kuykendall
sumber
terima kasih Kirk, Anda tidak tahu sudah berapa lama saya mencoba untuk mencari tahu ini. Saya kira ini C #?
matt wilkie
1
Ya, C #. Tidak menguji dengan set data berfitur, tetapi harus bekerja.
Kirk Kuykendall
3

Solusi lain dari Rob Clark :

Anda bisa menggunakan Featureeclass_to_featureclass dengan pemetaan bidang. Ya itu menciptakan kelas fitur lain tetapi Anda hanya bisa memiliki area output untuk menyalin data dan mengubah alias saat sedang melakukannya.

Dialog FC ke FC dengan Properties terbuka (dari menu konteks)

Dalam python, sintaks untuk field_mapbagian ini rumit, jadi lewati sekali secara interaktif untuk meluruskan parameter, biarkan berjalan. Lalu pergi ke jendela hasil , r-klik dan Salin potongan python . Berikut ini cuplikan yang digabungkan kembali menjadi sesuatu yang sedikit lebih mudah untuk diperluas dan digunakan kembali (lebih banyak pekerjaan dapat dilakukan untuk memecah potongan peta bidang dan properti):

inFC = 'e:/Canvec/fix.gdb/HD_1480009_2'
outFC = 'HD_with_aliases'
out_wspace = 'e:/canvec/fix.gdb'
where_clause = '#'      # use default
config_keyword = '#'    #    "

# build field map
fmap_out_att = 'CODE /\Specification code/\ '  # field and alias name
fmap_properties = 'true true false 4 Long 0 0 ,First,#,'  # field properties
fmap_in_att = 'e:/Canvec/fix.gdb/HD_1480009_2,CODE,-1,-1'  # input FC and field

# construct the complete field map
field_map = fmap_out_att + fmap_properties + fmap_in_att
   # results in:
   # "CODE /\Specification code/\ true true false 4 Long 0 0 ,First,#,e:/Canvec/fix.gdb/HD_1480009_2,CODE,-1,-1"


arcpy.FeatureClassToFeatureClass_conversion(inFC, out_wspace, outFC, 
        where_clause, field_map, config_keyword)

# the template command copied from Results window, used for building above
# arcpy.FeatureClassToFeatureClass_conversion("e:/Canvec/fix.gdb/HD_1480009_2","e:/canvec/fix.gdb","HD_with_aliases3","#","CODE /\Specification code/\ true true false 4 Long 0 0 ,First,#,e:/Canvec/fix.gdb/HD_1480009_2,CODE,-1,-1","#")
matt wilkie
sumber
2

Solusi ini untuk pengguna yang menggunakan SQL server sebagai geodatabase. Anda bisa mengubahnya secara manual dengan perintah pembaruan SQL. simpan semua nama fitur di tabel [sde]. [GDB_OBJECTCLASSES]. nama alias ditetapkan hanya jika Anda mengubah nilai kolom alias.

UPDATE [sde].[sde].[GDB_OBJECTCLASSES] 
SET AliasName = 'an alias name' 
WHERE Name='your feature class name'

EDIT: metode ini adalah metode cepat untuk mengubah nama alias. tetapi menggunakan IClassSchemaEdit lebih baik karena dalam metode pembaruan sql Anda tidak dapat menggunakan nama alias hingga mereset ruang kerja fitur.

Public Sub SetAliasName(FeatureClass As IFeatureClass, AliasName As String)
        Dim abjTable As ITable = FeatureClass
        Dim objClass As IObjectClass = abjTable
        Dim edit As IClassSchemaEdit = objClass
        edit.AlterAliasName(AliasName)
End Sub
Mehdi
sumber
1
Begitu jelas sekarang sehingga saya memikirkannya! Pendekatan yang sama harus dimungkinkan menggunakan Personal GDB (Access .mdb) atau opsi penyimpanan RDBMS apa pun juga.
matt wilkie
untuk menemukannya di RDBMS lain saya pikir lebih baik untuk menyalin cadangan dari RDBMS Anda dan kemudian mengubah nama alias dengan ArcCatalog kemudian membandingkan basis data saat ini dengan cadangan Anda dapat melihat perubahan dan mencari tahu di mana aliasname simpan.
Mehdi