9

I am trying to write a python macro for ArcGIS 10.2 that will automate the process of labeling points in a layer based on different types of apartments. For example, one style of apartments would have a blue square with white bold text as one label; another would have a pink square with black bold text; another would have a red square with a white bold text, etc.

What expression or function would you use in arcpy to alter the style of these labels?

Currently, the script labels the apartments by a map code and changes its name in the TOC to apartments, as it should.

enter image description here

Now I want to change the font, graphic, and size of the labels to look make a unique label for each, and then make a button to press and simply automate the process any time we have to do one of these layers.

Is there any way the fonts, labels, and graphics can be changed with the use of Python scripting (ArcPy, IDLE, etc.)?


I decided to edit this post to give a final description of what I'm going for here so there's no confusion. Essentially, the points on the map will go from looking like the above picture to this:

enter image description here


I have tried using the lblClass.expression function, however the code I am trying to use doesn't work. I figure that is probably the step in the right direction. Below is some code that I've tried to use just to get the labelClass.expression to change the fonts of the labels.

for lblClass in aptLayer.labelClasses:
lblClass.showClassLabels = True
def getLabel (Code, Type):
if Type == "MRR":
    return "<FNT name = 'Arial' size = '12'>" & Code & "</FNT>"
elif Type == "TAX":
    return "<FNT name = 'Arial' size = '12'>" & Code & "</FNT>"
elif Type == "MRT":
    return "<FNT name = 'Arial' size = '12'>" & Code & "</FNT>"
elif Type == "GSS":
    return "<FNT name = 'Arial' size = '12'>" & Code & "</FNT>"
elif Type == "TGS":
    return "<FNT name = 'Arial' size = '12'>" & Code & "</FNT>"
else:
    return "<FNT name = 'Arial' size = '12'>" & Code & "</FNT>"

lblClass.expression = getLabel( [Map_Code],[Type])
7

The arcpy.mapping API only provides access to a limited number of layer properties that can be directly modified but all properties found in the Layer Properties dialog box can be modified using the UpdateLayer function. The information is extracted from a source layer and applied to the layer in a map document that needs to be updated. The source_layer can either be a layer (.lyr) file or a layer within a map document. UpdateLayer is a robust function because it can be used in several different ways to produce different results.

You need to create the symbology/labels how you want, and save it to a layer file. Then load that layer file using arcpy.mapping.UpdateLayer().

If multiple people need to run the python add-in, then you need to make the layer file accessible to everyone, such as a public network drive.


I ended up making a custom Update Layer Properties toolbox. It allows you to select a layer in the ArcMap TOC, and then select an input layer file. It then updates the layer with all the properties within the layer file, and re-sources back to the original feature class. It will work with data that's in gdb, mdb, shp, or sde.

View the Source Code

Please let me know if you have any questions.

enter image description here

  • I created a separate layer file from another point based data layer with everything all set (symbology and labels), it executes, but all it seems to do is completely replace the unlabeled, unsymbolized apartment file (whichever one I choose to add) with the sourceLayer apartment file. I'm assuming this is because of the False in the "update symbology only" section. Is there a way that this can be executed so it will just apply the symbology and labels but not move the points to a different location? – Tyler Spears Oct 23 '14 at 16:19
  • What kind of functions would I go about looking for to do that? I'm not too familiar with re-sourcing. I appreciate your help this far, by the way. – Tyler Spears Oct 23 '14 at 20:38
  • I tried adjusting this to fit my code. It works up through the UpdateLayer function, but at line 35: refocus_layer = arcpy.mapping.ListLayers(mxd, original_fc_name)[0] it throws an error saying that the index is out of range. – Tyler Spears Oct 30 '14 at 19:35
  • That means that the arcpy.mapping.ListLayers method is not finding a layer in the current mxd with the same name as your input_layer_file (an index of [0] returning index out of range means there are no items in the list). – XIY Oct 31 '14 at 12:12
  • I did, and I feel like this is very close, but the problem is, after the UpdateLayer part finishes, it throws the following error: Traceback (most recent call last): File "E:\_Tyler Temp\Python\IanTest.py", line 30, in <module> refocus_layer = arcpy.mapping.ListLayers(mxd, original_fc_name)[0] IndexError: list index out of range – Tyler Spears Oct 31 '14 at 18:08
6

Another option is to set custom label expression on the layer (changing size and color..etc) using python:

e.g.

def FindLabel ( [NAME], [POPULATION] ):
  if long([POPULATION]) >= 250000:
    return "<CLR red='255'><FNT size = '14'>" + [NAME] + "</FNT></CLR>"
  else:
    return [NAME]

Building label expressions

They may be set via:

LabelClass (arcpy.mapping)

EDIT:

Try this:

def FindLabel ([Code], [Type]):
  if [Type] == "MRR":
    return "<FNT name = 'Arial' size = '12'>" + Code + "</FNT>"
  elif [Type] == "TAX":
    return "<FNT name = 'Arial' size = '12'>" + Code + "</FNT>"
  elif [Type] == "MRT":
    return "<FNT name = 'Arial' size = '12'>" + Code + "</FNT>"
  elif [Type] == "GSS":
    return "<FNT name = 'Arial' size = '12'>" + Code + "</FNT>"
  elif [Type] == "TGS":
    return "<FNT name = 'Arial' size = '12'>" + Code + "</FNT>"
  else:
    return "<FNT name = 'Arial' size = '12'>" + Code + "</FNT>"

You can remove your other line statements (for loop, labClass, and call to function). Also, the function needs to be called FindLabel.

  • I tried to utilize something similar to a function like this. I created a definition called def getLabel (Code, Type) and then after setting up the if-else statements for the different map codes I use, I then set 'lblClass.expression = getLabel( "[Map_Code]","[Type]" )', which just returns an error TypeError: unsupported operand type(s) for &: 'str' and 'str' I'm basically following the Esri website's examples. If I can simply prove I can change the font, I can then move on to adjusting the more difficult aspects (such as the shape, background and color of the labels). – Tyler Spears Oct 30 '14 at 20:24
  • @Tyler Spears, Try removing the double quotes around the field names. – artwork21 Oct 31 '14 at 10:59
  • When I do that, it says that the parameters aren't defined. – Tyler Spears Oct 31 '14 at 12:26
  • @Tyler Spears, Can you post your code in your question? You have a single quote outside of the function parentheses. – artwork21 Oct 31 '14 at 12:37
  • Absolutely, I have updated my question to show my code. – Tyler Spears Oct 31 '14 at 13:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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