Turning fields on and off using arcpy

12-11-2013 07:02 AM
New Contributor II

I am trying to use python to turn fields on and off for layers in my table of contents using the 'fieldInfo.setVisible' method. I can get it to run through and then output as setVisible = "NOT VISIBLE" but the fields remains visible and under the layer properties -> field tab the box is still checked next to the indicated field. Is this a bug or am I not using this method properly?

Code below:

import arcpy

mxd = arcpy.mapping.MapDocument("CURRENT")

### set layer
lyr = "StructurePnt"

fieldList = arcpy.ListFields(lyr)
desc = arcpy.Describe(lyr)

fieldInfo = desc.fieldInfo

### field index number
fldIndxNum = 6

fieldInfo.setVisible( fldIndxNum, 'NOT VISIBLE' )
print "\tField Name: " + fieldInfo.getFieldName(fldIndxNum)
print "\tVisible:    " + fieldInfo.getVisible(fldIndxNum)


Thank you,
Tags (2)
8 Replies
Occasional Contributor
Hi there,

Try using 'HIDDEN' instead of 'NOT VISIBLE'

From the FieldInfo help page:

setVisible (index, visible)

The index position.

The visible policy to set into the table.
VISIBLE �??Field is visible.
HIDDEN �??Field is hidden.
0 Kudos
New Contributor II
Thank you for the reply Clint,

I have replaced 'NOT VISIBLE' with 'HIDDEN'. The script runs as before and outputs:

Field Name: ARA
Visible:    HIDDEN

The field remains visible and not hidden and the check box in the fields tab is still checked. It is still not working tho this better follows the online help.
0 Kudos
Esri Esteemed Contributor
Hi Nathan,

Unfortunately, the behavior you are experiencing is "as-designed."  However, the visibility can be set as desired in a new layer created using MakeFeatureLayer.  Essentially what you need to do is create a Feature Layer with the desired field visibility, remove the original layer from the map, and then add the feature layer.

This is a bit cumbersome, however an enhancement request has been logged:

[#NIM087522  Please allow field visibility to be changed in an existing map layer.]
0 Kudos
New Contributor

Has ESRI updated this yet? I need to be able to use a script to turn off certain fields for a Feature Class without creating a new layer?

MVP Regular Contributor

I find it useful sometimes to run the geoprocessing tool and then right click the green ribbon > Copy Python Command-- that is, if the tool runs successfully. Then copy that into your python editor. You can see how the  parameters should look.



0 Kudos
New Contributor II

Thank you for the information.

My real intent was to be able to toggle about a dozen fields on and off in a layer. For most of the project we only need to use a few fields but as we are using subtypes, when copying and pasting features back and forth, lots of junk in the attribute tables can get transferred pretty easily regardless of having set all the domains and defaults. The only options that I can see for a layer are to turn all fields on and hide all fields. Writing a script seemed like the way to go but the 'setVisible' method turns out to be quite limited.

In short, is there a way to only turn on the fields that were previously visible? That would be pretty handy.

I know this takes this out of the 'Python' scope and I apologize but I am still seeking an answer to this problem.

Thanks again,
0 Kudos
Frequent Contributor
Sure....something like from here (link below) - enter the fields you want to keep in the 'desiredFields' list or use list fields from your orig fc to populate 'desiredFields':

0 Kudos
New Contributor

I have gotten a script to run but I am getting a runtime error, any ideas? the error happens at fields.append(row.getValue(f))

import arcpy
from arcpy import env
arcpy.env.overwriteOutput = True
arcpy.env.addOutputsToMap = False
arcpy.env.workspace = "C:/temp"
out_layer = "temp.lyr"

mxd = arcpy.mapping.MapDocument('CURRENT')
df = arcpy.mapping.ListDataFrames(mxd, '*')[0] # need to find way to get list of layers there can be more than one data frame
listfields = []
thebadlist = []
for LayerNeedsFieldsTurnedOff in arcpy.mapping.ListLayers(mxd):
 if LayerNeedsFieldsTurnedOff.isGroupLayer:
  print "group print"
 elif LayerNeedsFieldsTurnedOff.isFeatureLayer:
  fields = dict((f.name, []) for f in arcpy.ListFields(LayerNeedsFieldsTurnedOff) if not f.required)

  rows = arcpy.SearchCursor(LayerNeedsFieldsTurnedOff,"","","","")
  for row in rows:
   for f in fields.keys():

    #print row.getValue(f)

  for field, values in fields.iteritems():
   #print field
   if  field == "Shape":
   elif all(map(lambda s: s is None or not str(s).strip(), values)):

  # LayerNeedsFieldsTurnedOff = arcpy.mapping.ListLayers(mxd, 'exampledata', df)[0]
  # fill in your desired fields to remain visible
  desiredFields = listfields
  field_info = arcpy.Describe(LayerNeedsFieldsTurnedOff).fieldInfo # I need this for field count
  for i in range(field_info.count):
   if field_info.getfieldname(i) not in desiredFields:
    if field_info.getfieldname(i) == "SHAPE":
     field_info.setvisible(i, 'VISIBLE')
    elif field_info.getfieldname(i) == "Shape":
     field_info.setvisible(i, 'VISIBLE')
     field_info.setvisible(i, 'HIDDEN')
  arcpy.SaveToLayerFile_management(LayerNeedsFieldsTurnedOff, out_layer)
  arcpy.MakeFeatureLayer_management(LayerNeedsFieldsTurnedOff, 'temp_layer', '', '', field_info)
  refLyr = arcpy.mapping.Layer('temp_layer')
  # rename the ref layer the same as your target layer
  refLyr.name = LayerNeedsFieldsTurnedOff.name
  lyrfile = "C:/temp/temp.lyr"
  print LayerNeedsFieldsTurnedOff.name
  arcpy.ApplySymbologyFromLayer_management(refLyr, lyrfile)
  arcpy.mapping.UpdateLayer(df, LayerNeedsFieldsTurnedOff, refLyr, False)
  # mxd.save() 
  print 'cleaning up-'
  if arcpy.Exists('temp_layer'):
   print '\'temp_layer\' still in memory...deleting now...'
  print 'deleting obj refs...'
  del LayerNeedsFieldsTurnedOff, refLyr,  fields, f, i
  print 'done.'

0 Kudos