Formatting parameters for a field reordering tool

2858
7
Jump to solution
07-18-2016 05:52 AM
DavidHuggins
New Contributor II

I'm trying to make a script tool that reorders the fields in an attribute table and exports a new shapefile with the updated field order. I found a previous discussion (arctoolbox - How to re-order fields permanently using ArcGIS Make Query Table tool? - Geographic Inf... ) with code that used the Merge tool to accomplish this, and when I hardcoded it for a test shapefile, it worked well (despite having to list out the fields in the order desired in a string - line 59). In making a script tool, I'm not sure how to set the parameter to define new_field_order. I tried setting the parameter as a string, but am getting the exception in line 38 raised. How do I set this parameter to read a user-defined order for the fields in the same way I hardcoded it? Also, is there any way to reorder the fields in a temporary attribute table in ArcMap, write code to read the temporary order, and use that order to export the new shapefile (in order to avoid having to type out the desired order)?

Thanks!

Dave

import arcpy


def reorder_fields(table, out_table, field_order, add_missing=True):
    """ 
    Reorders fields in input featureclass/table
    :table:         input table (fc, table, layer, etc)
    :out_table:     output table (fc, table, layer, etc)
    :field_order:   order of fields (objectid, shape not necessary)
    :add_missing:   add missing fields to end if True (leave out if False)
    -> path to output table
    """
    existing_fields = arcpy.ListFields(table)
    existing_field_names = [field.name for field in existing_fields]


    existing_mapping = arcpy.FieldMappings()
    existing_mapping.addTable(table)


    new_mapping = arcpy.FieldMappings()


    def add_mapping(field_name):
        mapping_index = existing_mapping.findFieldMapIndex(field_name)


        # required fields (OBJECTID, etc) will not be in existing mappings
        # they are added automatically
        if mapping_index != -1:
            field_map = existing_mapping.fieldMappings[mapping_index]
            new_mapping.addFieldMap(field_map)


    # add user fields from field_order
    for field_name in field_order:
        if field_name not in existing_field_names:
            raise Exception("Field: {0} not in {1}".format(field_name, table))


        add_mapping(field_name)


    # add missing fields at end
    if add_missing:
        missing_fields = [f for f in existing_field_names if f not in field_order]
        for field_name in missing_fields:
            add_mapping(field_name)


    # use merge with single input just to use new field_mappings
    arcpy.Merge_management(table, out_table, new_mapping)
    return out_table


intable = r"Y:\Huggins_D\2016\Tool\Export_Output.shp"
outtable = r"Y:\Huggins_D\2016\Tool\Export_Output_TEST.shp"
new_field_order = ['ZIP4', 'NAME', 'TYPE', 'ADDRESS', 'CITY', 'ZIP5', 'STATE' ,'TYPE2', 'PHONE']
reorder_fields(intable, outtable, new_field_order, add_missing=True)
1 Solution

Accepted Solutions
AlexanderBrown5
Occasional Contributor II

David,

I changed the bottom of your script to:

# Input in toolbox: FIELDNAME;FIELDNAME; Example: ZIP4;NAME;TYPE;ADDRESS;CITY;ZIP5;STATE;TYPE2;PHONE

intable = arcpy.GetParameterAsText(0)
outtable = arcpy.GetParameterAsText(1)
new_field_order = arcpy.GetParameterAsText(2)

new_fields = new_field_order.split(';')
final_list = []

for field in new_fields:
  final_list.append(field)

reorder_fields(intable, outtable, final_list, add_missing=True)

I attached a toolbox for 10.1 & 10.2.  I have successfully run this a dozen times.  Make sure to input your text variable as such:

ZIP4;NAME;TYPE;ADDRESS;CITY;ZIP5;STATE;TYPE2;PHONE

Do not include any quotes in your string.  By parsing the fields in as one long direct string, you can split it into a list and properly pass the values into the script using the toolbox.  I also included the ability to select your shapefile directly.

Let me know if this works for you.

Regards,

Alex

View solution in original post

7 Replies
AlexanderBrown5
Occasional Contributor II

Dave,

I downloaded your script and set it up on some of my sample test data set.  Instead of posting screenshots of my field names, I included your field mappings below.

The first item is to update your python code line 58 to be a blank list:

new_field_order = [

Create a new toolbox => Right click => add => script.  Find your script in your file directory.

Set your script properties to mimic your variable name, and set to string.

When you input multiple field names as a string in the script window, make sure you enter the values separated by a semi-colon, single quotes enclosed:

'ZIP4;NAME;TYPE;ADDRESS;CITY;ZIP5;STATE;TYPE2;PHONE'

This will run your script properly from a script in a toolbox.

Reference:

"As A String"

Working with multivalue inputs—ArcPy Get Started | ArcGIS for Desktop

In addition, you could certainly read in all field attributes and select them to a variable.  Have another variable look through this multi value list or string, then utilize this to create your field mapping.  I'll try and post an example when I have a little more time to help.

Regards,

Alex

0 Kudos
DavidHuggins
New Contributor II

Thanks for the response Alex!

So I tried creating the empty list by replacing line 58, however, it did not appear to have an updated field orderFieldTool.jpg

It was working when I ran the just the script, but it does not appear to be setting that parameter correctly. The output was identical to the input.

Also, I would like to set the input and output as parameters as well

ex:

intable = arcpy.GetParameterAsText(0)

outtable = arcpy.GetParameterAsText(1)

new_field_order = []

and then write in the field order as a string depending on the shapefile input.

Thanks again for the help!

0 Kudos
AlexanderBrown5
Occasional Contributor II

David,

I can relate to your frustrations.  I am also experiencing some major inconsistencies with running it through a toolbox; it worked flawlessly a number of times, but now, for some odd reason, it is not re ordering the fields anymore.

Running this strictly through python works every time, but I cannot explain why the variables are not getting passed.

I'll post again when I have additional time to test.

~Alex

DavidHuggins
New Contributor II

Alex,

Yeah that's where I was at too. Thank you for taking a look, appreciate the help!

Cheers,


David

0 Kudos
AlexanderBrown5
Occasional Contributor II

David,

I changed the bottom of your script to:

# Input in toolbox: FIELDNAME;FIELDNAME; Example: ZIP4;NAME;TYPE;ADDRESS;CITY;ZIP5;STATE;TYPE2;PHONE

intable = arcpy.GetParameterAsText(0)
outtable = arcpy.GetParameterAsText(1)
new_field_order = arcpy.GetParameterAsText(2)

new_fields = new_field_order.split(';')
final_list = []

for field in new_fields:
  final_list.append(field)

reorder_fields(intable, outtable, final_list, add_missing=True)

I attached a toolbox for 10.1 & 10.2.  I have successfully run this a dozen times.  Make sure to input your text variable as such:

ZIP4;NAME;TYPE;ADDRESS;CITY;ZIP5;STATE;TYPE2;PHONE

Do not include any quotes in your string.  By parsing the fields in as one long direct string, you can split it into a list and properly pass the values into the script using the toolbox.  I also included the ability to select your shapefile directly.

Let me know if this works for you.

Regards,

Alex

DavidHuggins
New Contributor II

Alex,

This is perfect! Worked like a charm! I really appreciate you taking the time to help me!

Cheers!


Dave

AlexanderBrown5
Occasional Contributor II

Dave,

Awesome! No problem, glad I could help.

~Alex