Set number formatting in Python in ARCGIS Pro

1353
13
Jump to solution
12-09-2020 07:12 PM
LeandraGordon
Occasional Contributor II

Hi All,

Is there any way set the default numeric formatting s in Arcpy for pro?

I am using ArcPro 2.4.0

I have a number of layers in a map that I am preparing for sharing into Portal and we wish to format the number of decimal places and enable/disable the thousands separators

I am using .LRYX files to style the features and this is set in the layer file e.g.:
{
"type" : "CIMFieldDescription",
"alias" : "SVCurr",
"fieldName" : "AllData_SVCurr",
"numberFormat" : {
"type" : "CIMNumericFormat",
"alignmentOption" : "esriAlignRight",
"alignmentWidth" : 0,
"roundingOption" : "esriRoundNumberOfDecimals",
"roundingValue" : 0,
"useSeparator" : true
},

 but it does not seem to be reading the layer file for this setting ( I am running Apply Symbology from Layer)

https://pro.arcgis.com/en/pro-app/tool-reference/data-management/alter-field-properties.htm does not seem to have these options

Thanks in advance.

2 Solutions

Accepted Solutions
LeandraGordon
Occasional Contributor II

Worked out how to do this using the Cartographic Information Model (https://pro.arcgis.com/en/pro-app/latest/arcpy/mapping/python-cim-access.htm) :

------------------------------------------------------------------------------------------------------------

#List of Fields to Format with comma delimiters
SpCommaDelimFields=["AllData_Ld","AllData_P", "AllData_SR"] 

#List of Fields to Format with 2 decimal places
SpTwoDecFields=["AllData_Ld","AllData_P", "AllData_SR"] 

currentProject = arcpy.mp.ArcGISProject("CURRENT")
currentMap = currentProject.listMaps()[0]  #I think this assumes there is only one map
layers = currentMap.listLayers()

for layer in layers:

        lyrCIM = layer.getDefinition('V2')
        if layer.name == "TheLayer":

       lyrCIM.showPopups = True # show popups
       lyrCIM.expanded = True # At least one of these seems to help the map refresh


# Modify the display of numeric fields
for fd in lyrCIM.featureTable.fieldDescriptions:
        fdNumFmt = fd.numberFormat
        if fd.fieldName in SpCommaDelimFields: 
                   fdNumFmt.useSeparator = True #Use a comma as a thousands separator
        if fd.fieldName in SpTwoDecFields: 
                   fdNumFmt.roundingValue = 2  #Two decimal places

-------------------------------------------------------------------------------------------------------------------
            # Push the changes back to the layer object
            layer.setDefinition(lyrCIM)
            #Get the layer definition again to check that it has changed
            lyrCIMNew = layer.getDefinition('V2')
            messages.addMessage( layer.name + " showPopups after: " + str(lyrCIMNew.showPopups))
            messages.addMessage( layer.name + " showMapTips after: " + str(lyrCIMNew.showMapTips))

        currentProject.save

 


Note that this is ArcPro 2.4 - the portion of the lyrx file that handles the format looks like this:
{
"type" : "CIMFieldDescription",
"alias" : "Ld",
"fieldName" : "AllData_Ld",
"numberFormat" : {
"type" : "CIMNumericFormat",
"alignmentOption" : "esriAlignRight",
"alignmentWidth" : 0,
"roundingOption" : "esriRoundNumberOfDecimals",
"roundingValue" : 2,
"useSeparator" : true
},

It's a good idea to export the Lyrx file and check the Json to see if it matches this example or check out the specification https://github.com/esri/cim-spec

EDIT: in 2.8 I use a script to check the Layer file directly - see below

 

View solution in original post

LeandraGordon
Occasional Contributor II
0 Kudos
13 Replies
DanPatterson
MVP Esteemed Contributor

I haven't tried, but  "roundingValue" : 0,

suggests to me to not use any rounding... what if you change it to 2 or 3? does it have any affect?


... sort of retired...
LeandraGordon
Occasional Contributor II

Changing it to 2 in the layer file is possible, then you get 2 decimal places, e.g.
{
"type" : "CIMFieldDescription",
"alias" : "Ld",
"fieldName" : "AllData_Ld",
"numberFormat" : {
"type" : "CIMNumericFormat",
"alignmentOption" : "esriAlignRight",
"alignmentWidth" : 0,
"roundingOption" : "esriRoundNumberOfDecimals",
"roundingValue" : 2,
"useSeparator" : true
},

The layerx file is saved with the correct number of decimal places if you alter the data in Fields View manually as well but then using Apply Symbology from Layer to apply those formatting settings doesn't work. The data is back at 6 decimal places so I'm looking for a way to make the changes in the Python script.

The only way to change the number formatting seems to be via Fields View - select each field, alter manually.... Not an ideal workflow when preparing multiple maps a week to upload to Portal for our users. 
We are generating the tables via a join to excel spreadsheets and there doesn't seem to be a way to alter the number formats when we do the join either.

Even if we could modify the default formatting in Pro from 6 decimal places, no comma it would help.

0 Kudos
DanPatterson
MVP Esteemed Contributor

Leandra... long been a complaint that the column formatting from spreadsheets isn't retained.  

I tend to use numpy arrays, or you can try *.csv format.  If you format the columns in the spreadsheet then the number of decimals is retained in the output.  Attached is a file that contained an id column and two originally identical columns.  The first was free-range formatted and the second with 4 decimal places to show.  With ExcelToTable, everything was displayed to 6 decimal places and there was no numeric truncation.  With the csv, the output truncated to the display width

A0,B1,C3
1,1.012345679,1.0123
2,1.012345678,1.0123
3,1.01234567,1.0123
4,1.0123456,1.0123
5,1.012345,1.0123
6,1.01234,1.0123
9,1.0123,1.0123

... sort of retired...
0 Kudos
LeandraGordon
Occasional Contributor II

I'm thinking now that the only way to address issues like this is to export the data as layer files, hack into the layer files and then redraw the whole map. e.g. https://community.esri.com/t5/python-questions/turn-off-fields-with-python/td-p/403316

I really don't know why ESRI has such limited functionality in arcpy.

0 Kudos
DanPatterson
MVP Esteemed Contributor

The limitation is how to deal with excel.  csv is a far safer format since there are no surprises


... sort of retired...
0 Kudos
LeandraGordon
Occasional Contributor II

Unfortunately that means actually rounding the data itself, which means that any calculations we want to do in pro will be inaccurate. What I need is the data to be stored with x decimals but display to users as a rounded value. It's not really a solution I'm afraid.

 

0 Kudos
LeandraGordon
Occasional Contributor II

Worked out how to do this using the Cartographic Information Model (https://pro.arcgis.com/en/pro-app/latest/arcpy/mapping/python-cim-access.htm) :

------------------------------------------------------------------------------------------------------------

#List of Fields to Format with comma delimiters
SpCommaDelimFields=["AllData_Ld","AllData_P", "AllData_SR"] 

#List of Fields to Format with 2 decimal places
SpTwoDecFields=["AllData_Ld","AllData_P", "AllData_SR"] 

currentProject = arcpy.mp.ArcGISProject("CURRENT")
currentMap = currentProject.listMaps()[0]  #I think this assumes there is only one map
layers = currentMap.listLayers()

for layer in layers:

        lyrCIM = layer.getDefinition('V2')
        if layer.name == "TheLayer":

       lyrCIM.showPopups = True # show popups
       lyrCIM.expanded = True # At least one of these seems to help the map refresh


# Modify the display of numeric fields
for fd in lyrCIM.featureTable.fieldDescriptions:
        fdNumFmt = fd.numberFormat
        if fd.fieldName in SpCommaDelimFields: 
                   fdNumFmt.useSeparator = True #Use a comma as a thousands separator
        if fd.fieldName in SpTwoDecFields: 
                   fdNumFmt.roundingValue = 2  #Two decimal places

-------------------------------------------------------------------------------------------------------------------
            # Push the changes back to the layer object
            layer.setDefinition(lyrCIM)
            #Get the layer definition again to check that it has changed
            lyrCIMNew = layer.getDefinition('V2')
            messages.addMessage( layer.name + " showPopups after: " + str(lyrCIMNew.showPopups))
            messages.addMessage( layer.name + " showMapTips after: " + str(lyrCIMNew.showMapTips))

        currentProject.save

 


Note that this is ArcPro 2.4 - the portion of the lyrx file that handles the format looks like this:
{
"type" : "CIMFieldDescription",
"alias" : "Ld",
"fieldName" : "AllData_Ld",
"numberFormat" : {
"type" : "CIMNumericFormat",
"alignmentOption" : "esriAlignRight",
"alignmentWidth" : 0,
"roundingOption" : "esriRoundNumberOfDecimals",
"roundingValue" : 2,
"useSeparator" : true
},

It's a good idea to export the Lyrx file and check the Json to see if it matches this example or check out the specification https://github.com/esri/cim-spec

EDIT: in 2.8 I use a script to check the Layer file directly - see below

 

LeandraGordon
Occasional Contributor II

Edit - Actually the code runs fine, but for whatever reason the change to the layer CIM isn't saved when I use

layer.setDefinition(lyrCIM) the changes aren't written back in 2.8.1 BUT I have also added lyrCIM.expanded = True to a few of the layers and ??maybe?? that forces a map refresh

0 Kudos
JaredPilbeam2
MVP Regular Contributor

I'm using Pro v. 2.8 and I don't see anything related to the Number Format menu in the exported *.lyrx file?  I am trying to do the same thing as you, which is to have a faster way to set the decimal place to 0 and check the Show thousands separators box.