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).
-
1I 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– matt wilkie2010年07月23日 21:21:50 +00:00Commented Jul 23, 2010 at 21:21
-
related (a foundation building block): gis.stackexchange.com/questions/80/…matt wilkie– matt wilkie2010年08月05日 22:40:47 +00:00Commented Aug 5, 2010 at 22:40
5 Answers 5
As of version 10.1 AlterAliasName() can be used to re-alias tables:
table = r"C:\path\to\connection.sde\OWNER.TABLE"
arcpy.AlterAliasName(table, "table_alias")
As of version 10.3 Alter Field can be used to re-alias fields:
table = r"C:\path\to\connection.sde\OWNER.TABLE"
arcpy.AlterField_management(table, "FIELD_NAME", new_field_alias="field_alias")
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()
-
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. Thanksuser2035– user20352011年02月24日 02:23:46 +00:00Commented Feb 24, 2011 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– scw2011年02月24日 02:25:20 +00:00Commented Feb 24, 2011 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– matt wilkie2011年02月24日 17:31:59 +00:00Commented Feb 24, 2011 at 17:31
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;
}
-
thanks Kirk, you've no idea how long I've been trying to figure this out. I'm guessing this is C#?matt wilkie– matt wilkie2010年07月23日 20:56:42 +00:00Commented Jul 23, 2010 at 20:56
-
1Yes, C#. Didn't test with featuredatasets though, but should work.Kirk Kuykendall– Kirk Kuykendall2010年07月23日 21:25:53 +00:00Commented Jul 23, 2010 at 21:25
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","#")
This solution is for user that use SQL server as geodatabase. you can manually change it by an SQL update command. all feature's name save in [sde].[GDB_OBJECTCLASSES] table. the alias name set simply if you change the alias column value .
UPDATE [sde].[sde].[GDB_OBJECTCLASSES]
SET AliasName = 'an alias name'
WHERE Name='your feature class name'
EDIT: this method is fast method for changing the alias name . but using IClassSchemaEdit is better because in sql update method you can't use alias name until reset feature workspace.
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
-
1So obvious now that I think about it! The same approach should be possible using a Personal GDB (Access .mdb) or any of the RDBMS storage options as well.matt wilkie– matt wilkie2015年02月10日 17:30:01 +00:00Commented Feb 10, 2015 at 17:30
-
for find it in other RDBMS i think it's better to copy a backup from your RDBMS and then change the alias name by ArcCatalog then compare current database with the backup you can see the changes and find out where aliasname save.Mehdi– Mehdi2015年03月03日 07:01:56 +00:00Commented Mar 3, 2015 at 7:01