Change fields alias  in layer within mxd?

6446
20
09-03-2012 05:10 AM
BartłomiejStaroń
New Contributor III
It is possible to change fields alias  in layer within mxd by arcpy?(Table Options > Appearance)
Tags (2)
20 Replies
RhysDonoghue2
New Contributor III

I have just written a Python script that does what I mentioned above - it works great.  Here are the steps:

1) Use arcpy.ListFields() to get field names and field aliases from a feature class, and output to a csv file

2) In the csv file, update the alias column

3) Loop through the layers in the map document using arcpy.mapping.ListLayers()

4) If the layer supports "DATASOURCE", create a feature layer using layer.dataSource as the in_features and layer.definitionQuery as the where_clause

5) Save the feature layer to a layer file

6) Create a new arcpy.mapping.Layer from the layer file

7) Set the min and max scales for the new layer using the original layer, i.e. layer.minScale

8) Set the label classes, similar to the previous step

9) Apply the symbology of the original layer using arcpy.ApplySymbologyFromLayer_management()

10) Add the layer to the mxd using arcpy.mapping.InsertLayer()

11) Remove the original layer using arcpy.mapping.RemoveLayer()

12) Save a copy of the mxd using mxd.saveACopy()

This works really well and runs in less than a minute even on large mxds.  

DamianoMontrasio
New Contributor III

Hi Rhys Donoghue,

can you post your code as example?

I'm trying to simply set field.aliasName = row[1].encode('utf8') and export Layerfile but  don't works...

Thanks!

Damiano

0 Kudos
RhysDonoghue2
New Contributor III

Hi Damiano, my code is at work and I am on holiday, so I can't post my code at the moment.  However, where are you setting the alias?  In general, you should set the alias in the geodatabase, not in the map document (MXD file).  If you set the alias in the gdb, you don't need to update your alias each time you add the feature class to a map document.  Also, you shouldn't be exporting to a layer file.  Instead you should be using arcpy.SaveToLayerFile_management(), then later if you need to, you can use 

arcpy.ApplySymbologyFromLayer_management() to update a layer with the symbology.  Also, note that saving a layer file does not save all of the layer properties - which it should, however, it should save the aliases fine.  

Let me know if you need more details.

0 Kudos
DamianoMontrasio
New Contributor III

Hi Rhys,

Thanks for the response, but I need to renaming ALIAS name in MXD... My Feature Class are in Oracle non ESRI GDB with read Only permission...

It's strange that a simply UI task in ArcMap don't have a corresponding function in arcpy.

Why aliasName properties of field is "(Read and Write)"????

Field—ArcPy Classes | ArcGIS Desktop 

Now I'm trying with toolbox script and CURRENT mxd... maybe...

if I have news, I will update you...

Damiano

0 Kudos
RhysDonoghue2
New Contributor III

Hi Damiano,

From the Googling I did earlier, I believe aliasName is readonly, although you may be able to use ArcObjects to change it (I didn't look into this).

I just realised I may have copied the script I wrote at work to my USB drive.  I will see if I can get it for you.  Will reply soon.  It may do exactly what you want.

Regards,

Rhys

0 Kudos
RhysDonoghue2
New Contributor III

This is how to change the alias in the geodatabase (I realise this is not what you want - just adding it here in case someone else wants to use it).  Will send through a few scripts soon - sorry I'm not sure how to add the script below other than copying and pasting, which messes up the indenting:

import arcpy, csv

def main(inputFile,wksp,fc):
arcpy.env.workspace = wksp

fields = []
excludedFields = ["objectid","shape","shape_length","shape_area","o_shape","o_shape_length","o_shape_area"]

for field in arcpy.ListFields(fc):
fields.append(field.name)

with open(inputFile, 'rb') as csvfile:
csvreader = csv.reader(csvfile)

for row in csvreader:
if row[0] in fields and row[0].lower() not in excludedFields:

in_table = fc
field = row[0]
new_field_name = row[0]
new_field_alias = row[1]

print field

arcpy.AlterField_management(in_table, field, new_field_name, new_field_alias)

if __name__ == '__main__':

# change the parameters below
inputFile = # input CSV file
wksp = # input workspace
fc = # input feature class
main(inputFile,wksp,fc)

0 Kudos
RhysDonoghue2
New Contributor III

Hi Damiano,

Here's the code below that should work for you.  I can see couple of things in there that need tidying up, e.g. the error trapping, and changing the hardcoded file names to parameters.  This script below does what I mentioned in my twelve steps above.  The only issue I had was I couldn't copy the advanced label expressions and I couldn't tick the advanced label expression box (but this can be done via ArcObjects, if you don't want to do it manually).  The script basically rebuilds your MXD with the new layer aliases that were updated in the geodatabase using the previous script I sent through above.  This is not quite what you are after since you can't change the aliases in the GDB, however, hopefully this is enough to put you on the right track. 

If I understand what you want to do, I would probably create a feature layer with field aliases, and use the code below.  If you're really stuck, what you could do is use ArcPy to recreate your feature classes in a file geodatabase but without the data, e.g. use the Make Feature Layer tool and use '1=2' for the where clause, then use the Copy Features tool to create the FCs from the feature layers.  Then use the Alter Field tool to create the Aliases in the FGDB, and use the script below to update the MXD.  Then once you've done that, close your MXD, rename your FGDB, open your MXD and repair the datasources to point to Oracle.  This sounds complicated but is quite easy - unless you're working with complex data sets, e.g. geometric networks, topology, etc. however, since you're using native Oracle, not SDE, I doubt this would be an issue for you.

Regards,


Rhys

I have added the code here, which should have the correct indenting: Your Python Trinket 

import os, time, arcpy, csv
from datetime import datetime

def main(layers,visibleFields,directory,results_folder,layer_files_folder):

arcpy.env.overwriteOutput = True

for folder, dirs, files in os.walk(directory):
for file in files:
if file.endswith('test.mxd'): # add your MXD name here
try:
path = os.path.join(folder, file)

mxd = arcpy.mapping.MapDocument(path)
data_frame = arcpy.mapping.ListDataFrames(mxd, "Layers")[0]

i = 0

for lyr in arcpy.mapping.ListLayers(mxd, "", data_frame):

# todo - add properties from group layers
if lyr.supports("DATASOURCE"):

field_info = ''

if lyr in layers:
desc = arcpy.Describe(lyr)
field_info = desc.fieldInfo

for i in range(0, field_info.count):
if field_info.getFieldName(i) not in visibleFields:
field_info.setVisible(i, "HIDDEN")

# make a feature layer
in_features=lyr.dataSource
out_layer=lyr.name
where_clause=lyr.definitionQuery if lyr.supports("definitionQuery") else ''
layer = arcpy.MakeFeatureLayer_management(in_features,out_layer,where_clause,"",field_info)

# save the feature layer to a layer file
in_layer = layer
out_layer = os.path.join(layer_files_folder, str(i) + '.lyr')
arcpy.SaveToLayerFile_management(in_layer, out_layer)

# create a new layer
reference_layer = lyr
insert_layer = arcpy.mapping.Layer(out_layer)
insert_position = "AFTER"

# set the min and max scales for the layer
insert_layer.minScale = lyr.minScale
insert_layer.maxScale = lyr.maxScale

# copy the label classes from the original layer to the new layer
if lyr.supports("LABELCLASSES"):
className = ''
expression = ''
SQLQuery = ''

for lblClass in lyr.labelClasses:
className = lblClass.className
expression = lblClass.expression
SQLQuery = lblClass.SQLQuery
if expression[:3] == 'def':
print 'Warning: layer "%s" users an Advanced Label Expression' % (lyr.name)

for lblClass in insert_layer.labelClasses:
lblClass.className = className
lblClass.expression = expression
lblClass.SQLQuery = SQLQuery

# show the labels
if lyr.supports("SHOWLABELS") and expression[:3] != 'def':
insert_layer.showLabels = lyr.showLabels

# apply the symbology of the original layer to the new layer
in_layer=insert_layer
in_symbology_layer = lyr
arcpy.ApplySymbologyFromLayer_management(in_layer, in_symbology_layer)

# add the layer to the map document
arcpy.mapping.InsertLayer(data_frame, reference_layer, insert_layer, insert_position)

# remove the original layer
arcpy.mapping.RemoveLayer(data_frame, lyr)
i += 1

mxd.saveACopy(os.path.join(directory, 'output.mxd'))

del mxd

except OSError:
print 'Error with ' + file

if __name__ == '__main__':
layers = ['','',''] # add your layer names here
visibleFields = ['','',''] # add your field names here
directory = r'C:\dev\map documents (mxds)'
results_folder = r'C:\dev\scripts\Python\output'
layer_files_folder = r'C:\dev\gisdata\layer files\temp'

main(layers,visibleFields,directory,results_folder,layer_files_folder)

DamianoMontrasio
New Contributor III

Thanks a lot Rhys,

you suggested an interesting idea with a local FGDB as support only for the data structure ...
I'll do some tests and then update the whole community ...
I hope I have not ruined your holidays ...

0 Kudos
RhysDonoghue2
New Contributor III

Sounds good Damiano, I'm keen to know how you get on.

0 Kudos
DamianoMontrasio
New Contributor III

Hi Rhys,

I came back today after a week of vacation, I can tell you that your suggestion has worked.
Adding the FCs from GDB I see the correct aliases (set by the code), I only need to change the source and point to the SDE.

I will do it these days but I do not think I find particular difficulties ..

thank you again!

Damiano