Select to view content in your preferred language

How to control numeric format using arcpy

1011
5
Jump to solution
10-02-2024 02:27 PM
AntoinePrince1805
Occasional Contributor

Does anyone knows of a way to control numeric format for DOUBLE or FLOAT values using only arcpy outside of ArcGIS Pro? I would like to find any ways to control the allowed number of decimals and also the thousand separator. As of now, I have explored two options :

1. Specifying the scale of the field when creating a new field using the "AddField" function, but I found out that the "scale" and "precision" parameters are ignored when using on a feature class inside a geodatabase.

2. Using the layer CIM to access the numberFormat properties with the following script, but the fieldDescriptions list always return empty. After reading a bit on the problem, this seems more like a feature than a bug (eventhough I don't get why we cannot acces the list in a python script, bu we can in the python command promt, inside ArcGIS Pro).

aprx_path = [PATH_TO_APRX]
aprx = arcpy.mp.ArcGISProject(aprx_path)
map = aprx.listMaps()[0]
lyr = map.listLayers("MyLayer")[0]

lyr_cim = lyr.getDefinition('V3')

for fd in lyr_cim.featureTable.fieldDescriptions:
    fdNumFmt = fd.numberFormat
    fdNumFmt.useSeparator = True
    fdNumFmt.roundingValue = 2

 So here I am, stuck...

Please help!

Thanks!

0 Kudos
1 Solution

Accepted Solutions
JeffBarrette
Esri Regular Contributor

@AntoinePrince1805 

One of the efficiencies of the CIM is also one of its limitations.  The CIM mostly persists non-default data to minimize its size and improve performance.  So if no alterations are made to default field info, the field info does not appear in the CIM definition.

Try the code below.  The trick is to use MakeFeatureLayer which does include the CIM definitions, make alterations and copy the updated CIM information to your target layer. 

p = arcpy.mp.ArcGISProject('current')
m = p.listMaps()[0]

lyr = m.listLayers('Provinces')[0]
lyr_cim = lyr.getDefinition('V3')

fList = ["SQKM", "POP2001", "Shape_Length", "Shape_Area"]

#IF NO CIM FIELD DESC INFO IS AVAILBLE
if len(lyr_cim.featureTable.fieldDescriptions) == 0:
    print('No CIM Field Info')
    
    #Make temporary layer (which automatically gets CIM field info)
    mkLyr = arcpy.management.MakeFeatureLayer(lyr)[0]
    mkLyr_cim = mkLyr.getDefinition('V3')
    for fd in mkLyr_cim.featureTable.fieldDescriptions:
        if fd.fieldName in fList:
            fd.numberFormat.roundingOption = "esriRoundNumberOfDecimals"
            fd.numberFormat.roundingValue = 0
            fd.numberFormat.zeroPad = True         
    mkLyr.setDefinition(mkLyr_cim)
    
    #Copy CIM information and remove temporary layer
    lyr_cim.featureTable.fieldDescriptions = mkLyr_cim.featureTable.fieldDescriptions  
    lyr.setDefinition(lyr_cim)
    m.removeLayer(mkLyr)

 

 

 Jeff - arcpy.mp and Layout teams

View solution in original post

5 Replies
AntoinePrince1805
Occasional Contributor

Thanks. That yet confirms that this does not seem possible unless I manually edit a layer file inside ArcGIS Pro, but I am looking for a python stand-alone solution.

0 Kudos
JeffBarrette
Esri Regular Contributor

@AntoinePrince1805 

One of the efficiencies of the CIM is also one of its limitations.  The CIM mostly persists non-default data to minimize its size and improve performance.  So if no alterations are made to default field info, the field info does not appear in the CIM definition.

Try the code below.  The trick is to use MakeFeatureLayer which does include the CIM definitions, make alterations and copy the updated CIM information to your target layer. 

p = arcpy.mp.ArcGISProject('current')
m = p.listMaps()[0]

lyr = m.listLayers('Provinces')[0]
lyr_cim = lyr.getDefinition('V3')

fList = ["SQKM", "POP2001", "Shape_Length", "Shape_Area"]

#IF NO CIM FIELD DESC INFO IS AVAILBLE
if len(lyr_cim.featureTable.fieldDescriptions) == 0:
    print('No CIM Field Info')
    
    #Make temporary layer (which automatically gets CIM field info)
    mkLyr = arcpy.management.MakeFeatureLayer(lyr)[0]
    mkLyr_cim = mkLyr.getDefinition('V3')
    for fd in mkLyr_cim.featureTable.fieldDescriptions:
        if fd.fieldName in fList:
            fd.numberFormat.roundingOption = "esriRoundNumberOfDecimals"
            fd.numberFormat.roundingValue = 0
            fd.numberFormat.zeroPad = True         
    mkLyr.setDefinition(mkLyr_cim)
    
    #Copy CIM information and remove temporary layer
    lyr_cim.featureTable.fieldDescriptions = mkLyr_cim.featureTable.fieldDescriptions  
    lyr.setDefinition(lyr_cim)
    m.removeLayer(mkLyr)

 

 

 Jeff - arcpy.mp and Layout teams

AntoinePrince1805
Occasional Contributor

This is it!!

Exactly what I was looking for. Although you made me work a bit late for a friday afternoon, I am still grateful.

0 Kudos
AntoinePrince1805
Occasional Contributor

This answer has been deleted.

0 Kudos