I am attempting to use fiona and xlrd to convert a complicated excel spreadsheet to a shapefile (point). I am trying to figure out how, during the .write call, to send the list of coordinates I've pulled out of the spreadsheet and use them to draw the geometry. Here's an abbreviation of what I've got so far:

shapefile_dir = r'C:\Temp'
point_shapefile = os.path.join(shapefile_dir, '{}_export_p.shp'.format(datetime.now().strftime('%Y-%m-%d %H:%m')))

schema_properties = {
    'guid': 'str:50'
    'dateTime': 'str:16'

point_schema = {'geometry': 'Point', 'properties': schema_properties}

with fiona.open(point_shapefile, 'w', crs=from_epsg(4326), driver='ESRI Shapefile', schema=point_schema) as layer:
    with xlrd.open_workbook(wkbk) as wb:
        cs = wb.sheet_by_name('Master')
        keys = [cs.cell(0, col_index).value for col_index in xrange(cs.ncols)]
        dict_list = []
        for row_index in xrange(1, cs.nrows):
            d = {keys[col_index]: cs.cell(row_index, col_index).value for col_index in xrange(cs.ncols)}

        for idict in dict_list:
                guid = idict['A']
                dateTime = idict['DATE']
                declat = idict['DECLAT']
                declon = idict['DECLON']
                    layer.write({'geometry': (declat, declon), 'properties': {
                        'guid': guid,
                        'dateTime': dateTime
                except: #except clause for writing the geometry and attributes
            except: #except clause for getting values out of dictionary list

I'm a little overboard with xlrd because I need this to scale to read a workbook with n number of sheets.

But currently I'm getting an error

tuple indices must be integers, not str

Which of course means I'm missing something very basic.

My values are being fetched from the excel spreadsheet correctly, so I think I'm almost there. But I'm not sure I'm thinking through this procedure correctly. Should I be stashing the xlrd operations inside of the fiona write loop? How do I get from that list of XYs, cast them to float and then write them as a new row in the shapefile?

I reviewed Fiona - Preffered method for defining a schema

but I guess I'm not clear on how to adapt some of the methods in there to my own data.

  • Yeah, I am actually doing conversion from UTM to get the decimal degree notation, and didn't include it for sake of brevity. I still end up with good coords in declat and declon though.
    – auslander
    Commented Aug 30, 2017 at 11:28

1 Answer 1


Fiona uses the GeoJSON format and layer.write({'geometry': (declat, declon), ... is not correct

Why ?

declon= 5 # integer or float and not string !
declat = 50  # integer or float and not string !
geom = ({'geometry': (declat, declon)})
print geom
{'geometry': (50, 5)}

The GeoJSON format uses Point(longitude, latitude) (Point(x,y) and not Point(y,x)).

The correct formulation is

geom = {'type': 'Point', 'coordinates': (declon, declat)} # Point(x,y)
print geom
{'type': 'Point', 'coordinates': (5, 50)}


geom = {'type': 'Point', 'coordinates': (declon, declat)}
prop = {'guid': guid,'dateTime': dateTime}
output.write({'geometry':geom, 'properties': prop})
  • Perfect, thanks for the excellent explanation @gene!
    – auslander
    Commented Aug 30, 2017 at 11:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.