What Will We Do?We will use a point shapefile and export it as a CSV file using ArcPY. So in the end you will have a new toolbox with a custom tool just for you.
What Will I Learn?You will learn to:
- iterate over features of a layer
- file operations in ArcPY
- create “interfaces” for your sript
What Do I need?“Unfortunately” you’ll need a running version of ArcGIS version 10.x. A text editor with syntax highlighting like sublime 3 would be a plus.
1) Iterate Over FeaturesThe iteration over features works with a so-called searchCursor:
The SearchCursor function establishes a read-only cursor on a feature class or table. The SearchCursor can be used to iterate through row objects and extract field values. The search can optionally be limited by a where clause or by field, and optionally sorted.And according to the example in the help file it’s really easy, assuming our shapefile has the name “point_shape” and we are interested in the attribute name:
import arcpy cursor = arcpy.SearchCursor("point_shape") for row in cursor: print(row.getValue("name"))This is quite easy and works like a charm. The geometry for a simple point shapefile is probably stored in the field called shape and we can also extract coordinates by row:
import arcpy cursor = arcpy.SearchCursor("point_shape") for row in cursor: print row.getValue("Shape").getPart().X, row.getValue("Shape").getPart().YThis will print X and Y coordinates for every feature. As point features can be multipart as well we needed to call the getPart() function to get the part we are interested in for our singlepart points. If you’re not sure whether your shape information is stored in “Shape” as above you can ask the feature for the name of the shape information using the describe function:
desc = arcpy.Describe("point_shape") desc.ShapeFieldNameBy now we can iterate over features and print the coordinates and one attribute. As we don’t know the attribute names in the shapefiles by default we need to get a list of field names. We can do this right away using listFields:
fields = arcpy.ListFields("point_shape") for field in fields: print field.name
2) File WritingAs we want to store all the information in a single file we need some other module to write a file and determine OS paths and so on:
import os userhome = os.path.expanduser('~') desktop = os.path.join(userhome,'Desktop')For the file writing itself we will open a new file, write lines into it, save it and close it:
with open(desktop + os.sep + 'data.txt', 'w') as file: text = """This is my line to write to the file""" file.write(text) file.close()I am using the triple quotes to be able to use single quotes in the string which I want to write to the file.
3) Bringing It TogetherAll we need to do now is to iterate over the features and write each feature information to a line. The basic code would look like this:
import arcpy import os cursor = arcpy.SearchCursor("point_shape") fields = arcpy.ListFields("point_shape") userhome = os.path.expanduser('~') desktop = os.path.join(userhome,'Desktop') text = '' with open(desktop + os.sep + 'data.txt', 'w') as file: for field in fields: text += field.name + """;""" text += """X;Y """ for row in cursor: for field in fields: text += str(row.getValue(field.name)) + """;""" text += str(row.getValue("Shape").getPart().X) + """;""" + str(row.getValue("Shape").getPart().Y) + """ """ file.write(text) file.close()The strange quotation marks mimic the line breaks we need to put into our file. Furthermore we need to change anything we get to a string so we use th str() function in line 15.
4) Making It GenericAt the moment we have one fixed attribute which is the name of the shapefile. As we want to call the tool independently from the shapefiles name we need to get this generic. We will combine this with the creation of the toolbox itself. But first: ArcPY has an easy way of generalisation when creating a toolbox we will use the first (or in Python language the “zeroest” element of inputs of the toolbox:
inputshape= arcpy.GetParameterAsText(0)But where do we get the Parameter as text from? Open up the toolbox, Right click inside the toolbox window and select Add Toolbox,New Toolbox in the popup and give it a nice name: Now we need to add the script to the toolbox by right clicking the new toolbox and selecting Add Script: Select your saved python script from above in the next dialog: Now comes the crucial part: We need to define the input parameter which is a point feature class in our case. So in the upper box select Feature Layer as Data Type and give it a name for the screen: As we are just interested in Single Part Point feature classes we select Feature Class as Filter and deselect everything except Point In the end the tool looks like this and should only list point feature classes of your current project: What we need to do in the end? Use the input in our script. So right-click on the script in the toolbox and edit it. Simply add the following line after our import XX lines:
inputshape= arcpy.GetParameterAsText(0)This stores the name of the feature class in the variable inputshape. Now just replace these lines:
cursor = arcpy.SearchCursor("point_shape") fields = arcpy.ListFields("point_shape")with these two lines:
cursor = arcpy.SearchCursor(inputshape) fields = arcpy.ListFields(inputshape)That’s it! You can download the python script here.
What Next?Try yourself to make the output filename generic/selectable.
Thank you for reading. Your comments will be valuable.
ps: There is a script/toolbox from @calvinmetcalf on github called esri2open which adds GeoJSON/CSV export to ArcGIS.
ArcGIS Online seems to have recently started supporting GeoJSON: http://blogs.esri.com/esri/arcgis/2014/12/16/arcgis-online-geojson/
Hi, if I may add a few remarks to your code: Your SearchCursor object isn’t deleted, so the script does not necessarily remove the lock from the feature class you’re processing. To do this, add del cursor at the end, when you’re finished. Even better would be to use a with statement for the SearchCursor as well, as this will ensure that the feature class is unlocked even if the script throws an error. (credits to /u/sarcasmful *) Your writer now writes the ‘value’ of the shapefield as well to the output file. This results in a column holding values… Read more »
Thanks for pasting your reddit comment!
Thanks for this!