Modification des alias de classe d'entités et de champs en masse à l'aide d'ArcPy?


14

J'ai plus d'une centaine de FC, chacun avec 10 ou 20 attributs pour ajouter ou modifier les alias, deux fois ou plus par an. Inutile de dire que ce n'est pas quelque chose que je vais grogner. Comment puis-je automatiser ce processus?

La solution Python est préférée mais utilisera tout ce qui fonctionne.

J'ai accès à Arcgis 9.3.1 et 10 (niveau de licence ArcInfo).


1
J'ai trouvé l'exemple de développeur [Edit Feature Class Schema] [1] v9.3 pour ArcCatalog. Il modifie l'alias des classes d'entités sélectionnées en valeur codée en dur dans le script. Ce n'est donc pas un processus discontinu mais dirigé dans cette direction. [1]: resources.esri.com/help/9.3/ArcGISDesktop/com/samples/…
matt wilkie

connexes (un bloc de construction de fondation): gis.stackexchange.com/questions/80/…
matt wilkie

Réponses:


7

Depuis la version 10.1, AlterAliasName () peut être utilisé pour recréer des alias de tables:

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

À partir de la version 10.3, Alter Field peut être utilisé pour renommer les champs:

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

8

Avec l'aide de Mark Cederholm, j'ai une solution de travail utilisant python et arcobjects . C'est rude sur les bords, mais ça a fait le travail. Après avoir suivi la recette sur cette page, créez un nouveau script qui utilise les GetLibPath, NewObj, CType, OpenFeatureClassfonctions de snippets.py. Créez également les tables de recherche renommées au format .csv:

Recherche d'alias de champ à champ (att_code-name_lookup.csv):

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

Classe d'entités vers la recherche d'alias FC (fc_code-name_lookup.csv):

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

et le script:

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()

C'est tellement proche de ce dont j'ai besoin (mise à jour des alias de champ). À quoi ressemble la partie OpenFeatureClass des extraits de code? Le code de Mark n'a pas cette pièce. Merci

Salut Jasperoid: vous pouvez commenter une réponse spécifique en cliquant sur le lien 'ajouter un commentaire', j'ai migré votre réponse sur cette réponse.
scw

@Jasperiod, j'ai déplacé la plupart des extraits de Mark dans un module que j'appelle parco , où se trouve également OpenFeatureClass. Je ne me souviens pas l'avoir créé moi-même, mais peut-être que je l'ai fait. Quoi qu'il en soit, il est à la ligne 125 .
matt wilkie

6

Ce code fonctionne pour moi dans 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;
}

merci Kirk, vous ne savez pas depuis combien de temps j'essaie de comprendre cela. Je suppose que c'est C #?
matt wilkie

1
Oui c#. N'a pas testé avec les jeux de fonctionnalités, mais devrait fonctionner.
Kirk Kuykendall

3

Une autre solution gracieuseté de Rob Clark :

Vous pouvez utiliser featureclass_to_featureclass avec le mappage de champ. Oui, cela crée une autre classe d'entités, mais vous pouvez simplement avoir une zone de sortie pour copier les données et modifier les alias pendant qu'il le fait.

Boîte de dialogue FC vers FC avec Propriétés ouverte (depuis le menu contextuel)

En python, la syntaxe de la field_mappartie est délicate, alors parcourez-la une fois de manière interactive pour définir les paramètres directement, laissez-la s'exécuter. Ensuite, allez dans la fenêtre des résultats , cliquez sur le bouton r et cliquez sur Copier l'extrait de python . Voici un extrait re-combiné en quelque chose d'un peu plus facile à étendre et à réutiliser (plus de travail pourrait être fait pour séparer les morceaux de la carte de champ et des propriétés):

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","#")

2

Cette solution est destinée aux utilisateurs qui utilisent SQL Server comme géodatabase. vous pouvez le modifier manuellement par une commande de mise à jour SQL. le nom de toutes les fonctionnalités est enregistré dans la table [sde]. [GDB_OBJECTCLASSES]. le nom d'alias défini simplement si vous modifiez la valeur de la colonne d'alias.

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

EDIT: cette méthode est une méthode rapide pour changer le nom d'alias. mais l'utilisation de IClassSchemaEdit est meilleure car dans la méthode de mise à jour SQL, vous ne pouvez pas utiliser le nom d'alias jusqu'à la réinitialisation de l'espace de travail de la fonctionnalité.

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

1
Si évident maintenant que j'y pense! La même approche devrait être possible en utilisant un Personal GDB (Access .mdb) ou l'une des options de stockage du SGBDR également.
matt wilkie

pour le trouver dans d'autres SGBDR, je pense qu'il est préférable de copier une sauvegarde de votre SGBDR, puis de modifier le nom d'alias par ArcCatalog, puis de comparer la base de données actuelle avec la sauvegarde, vous pouvez voir les modifications et savoir où enregistrer le nom d'alias.
Mehdi
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.