1

Consider a Feature Class and two of its fields are "UTM_grid" and the "OID".

Scripting with python 2.7 for ArcGIS 10.3.

"UTM_grid" field contains the geographic info (e.g. B1SD40B) and was broken down into "UTM_block" + "UTM_sheet" (B1 + SD40B) and then using a dictionary and list structure UTM_block-->UTM_sheet-->OID was organized with this syntax:

{ 'UTM_block_1' : { 'UTM_sheet_A' : [ oid_1 , oid_2 ] }, { UTM_sheet_2 : [ oid_3 , oid_4, oid_5 ] } }

We need to create shapefiles with features (identified by the object value - oid) based on the follow data structure (OIDs will be organized regarding an UTM/location based structure):

  • UTM_block_* will be a folder
  • UTM-sheet_* its subfolder.
  • List of objects (OIDs) will populate the shapefile.

Note: Features Classes to export are in a SDE geodatabase. We read/list the FCs in that GDB and for each FC we need to process the export of its features by UTM block-sheet into shapefiles. Looking at the fields "UTM_grid" and "ObjectID" we check while sheet ( utm_grid[1] ) = "foo", read the corresponding OID, and put the Feature into a Shapefile inside the (sub)folder (which has the associated sheet name). The same logic could be used to organize sheets inside the block folders.


Another point we have to deal with is that the shapefile should only have some fields of the original Feature Class:

We have used fieldmappings and arcpy.FeatureClassToFeatureClass_conversion() to create a non-UTM-organized shapefile from a Feature Class with the fields that we need.


Now the problem is how to process the feature export to get UTM-organized shapefiles! How can we manage it?

Bellow is what we have now inside a function:

with arcpy.da.SearchCursor(feature_class, ['UTM_grid' , 'OBJECTID']) as cursor:
    dic = dict()
    for row in cursor:
        UTM_sheet_value = row[0]
        oid_value = row[1]

        try:
            b_s_split = UTM_sheet_value.split('_') # split of block & sheet

        except Exception, e:
            pass
            print(UTM_sheet_value)
            print(e)

        else:
            dic.setdefault( b_s_split[0], {} ).setdefault( b_s_split[1], [] ).append( oid_value )

            # create folders & subfolders (blocks & sheets) in a directory
            dir_path = os.path.dirname("E:\\")
            dirs = [ [b_s_split[0]] , [b_s_split[1]] ]

            for item in itertools.product(*dirs):
                if not os.path.isdir(os.path.join(dir_path, *item)):
                    os.makedirs(os.path.join(dir_path, *item))
1

You could try something like this:

import os
import arcpy



arcpy.env.overwriteOutput = 1

output_folder = r"full_path_to_folder"

fc = r"full_path_to_feature_class"

fields = ["OID@","SHAPE@","UTM_GRID"] #modify as required

template_fc = r"full_path_to_template_schema" #with fields you want to keep - they should also be in the field list above

fc_data = dict([(row[0],(row[1],row[2])) for row in arcpy.da.SearchCursor(fc,fields)]) # read data from feature class, objectid as key, shape and utm_grid as value list

utm_dict = {}

for k,v in fc_data.iteritems():
    block_sheet = v[1].split("_")
    utm_dict.setdefault(block_sheet[0],{}).setdefault(block_sheet[1],[]).append(k)


for block, sheets in utm_dict.iteritems():

    sheet_folders = [os.path.join(output_folder,block,sheet_key) for sheet_key in sheets.keys()]#create folders for each block, with sheets as subfolders
    for sf in sheet_folders:
        if not os.path.exists(sf):
            os.makedirs(sf)

        sheet_id = os.path.basename(sf)
        sheet_shapefile = os.path.join(sf,"{0}.shp".format(sheet_id))

        if arcpy.Exists(sheet_shapefile):
            arcpy.Delete_management(sheet_shapefile)
        arcpy.CreateFeatureclass_management(sf,sheet_id,"POLYGON",template_fc)

        sheet_cursor = arcpy.da.InsertCursor(sheet_shapefile, fields)
        sheet_rows = [(i,fc_data[i][0],fc_data[i][1]) for i in sheets[sheet_id]]
        for sr in sheet_rows:
            sheet_cursor.insertRow(sr)

        del sheet_cursor
  • used your code suggestion with a template_fc but could not get what we need, thank you – AbreuFreire Apr 29 '16 at 16:45
  • What was the issue? – Nxaunxau Apr 29 '16 at 16:50
0

Solution:

fd_temp_path = "\\path\\to\\dataset"
shp_dir = "\\path\\to\\shp_dir"
if not os.path.exists(shp_dir):
    os.makedirs(shp_dir)
# list FC in dataset "TEMP" in a SDE
fc = arcpy.ListFeatureClasses(feature_dataset="TEMP")

for fc in sorted(fc_mapped):
    fc_mapped_path = os.path.join(fd_temp_path, fc)
    basename = fc_mapped_path.rsplit('.', 1)[-1]

    # FOL_250K/UTM values 
    utm_field = "FOL_250K"
    sql_prefix = "DISTINCT {}".format(utm_field)
    sql_suffix = None
    distinct_utm = [ i[0] for i in arcpy.da.SearchCursor(fc_mapped_path, utm_field, sql_clause=(sql_prefix, sql_suffix) ) ]

    # folders & export by utm values  
    for utm in distinct_utm:
        if utm[0] is None:
            print("FOL_250K empty")
            pass
        else:
            delim = "_"
            utm_parse = utm.split(delim, 1)
            print("utm_parse: ")
            print(utm_parse)

            if len(utm_parse) == 2:
                block, sheet = utm_parse  
                sheet_path = os.path.join(shp_dir, block, sheet)  
                if not os.path.exists(sheet_path):  
                    os.makedirs(sheet_path)
                arcpy.FeatureClassToFeatureClass_conversion(  
                    fc_mapped_path,  ## in_features  
                    sheet_path,  ## out_path  
                    "{}_{}_{}".format(block, sheet, basename),  ## out_name  
                    "FOL_250K = '{}'".format(utm)  ## where_clause  
                )
            else:
                raise ValueError("Parse {} was not possible with {}".format(utm, delim))

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.