Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I have over a hundred FCs, each with 10 or 20 attributes to add or change the aliases for, two or more times a year. Needless to say, this is not something I'm going to grunt my way through. How can I automate this process?

Python solution preferred but will use anything that works.

I have access to Arcgis 9.3.1 and 10 (ArcInfo license level).

share|improve this question
1  
I found the [Edit Feature Class Schema][1] v9.3 developer sample for ArcCatalog . It changes the alias for the selected feature classes into the value hard coded in the script. So not a batch process but headed in that direction. [1]: resources.esri.com/help/9.3/ArcGISDesktop/com/samples/… –  matt wilkie Jul 23 '10 at 21:21
    
related (a foundation building block): gis.stackexchange.com/questions/80/… –  matt wilkie Aug 5 '10 at 22:40

3 Answers 3

This code works for me in 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;
}
share|improve this answer
    
thanks Kirk, you've no idea how long I've been trying to figure this out. I'm guessing this is C#? –  matt wilkie Jul 23 '10 at 20:56
1  
Yes, C#. Didn't test with featuredatasets though, but should work. –  Kirk Kuykendall Jul 23 '10 at 21:25
up vote 8 down vote accepted

With help from Mark Cederholm I have a working solution using python and arcobjects. It's rough around the edges, but it got the job done. After following the recipe on that page, create a new script which uses the GetLibPath, NewObj, CType, OpenFeatureClass functions from snippets.py. Also create the rename lookup tables in .csv format:

Field to Field Alias lookup (att_code-name_lookup.csv):

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

Feature class to FC Alias lookup (fc_code-name_lookup.csv):

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

and the 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()
share|improve this answer
    
This is so close to what I need (updating field aliases). What is the OpenFeatureClass portion of snippets look like? Mark's code doesn't have that piece. Thanks –  user2035 Feb 24 '11 at 2:23
    
Hi Jasperoid: you can comment on a specific answer by clicking the 'add comment' link, I've migrated your response on this answer. –  scw Feb 24 '11 at 2:25
    
@Jasperiod, I moved most of Mark's snippets into a module I call parco, which is where OpenFeatureClass is also. I don't remember creating it myself, but maybe I did. Anyway, there it is at line 125. –  matt wilkie Feb 24 '11 at 17:31

Another solution courtesy of Rob Clark:

You could use featureclass_to_featureclass with field mapping. Yes it creates another feature class but you could just have an output area to copy data and change aliases whilst it's doing it.

FC to FC dialog with Properties open (from context menu)

In python the syntax for the field_map part is tricky so go through it once interactively to set the parameters straight, let it run. Then go to results window, r-click and Copy python snippet. Here is a snippet re-combined into something a little easier to extend and re-use (more work could be done to break apart the pieces of the field map and properties):

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","#")
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.