1. 需求分析
将带有坐标和参数的表格信息(.xls,.xlsx)转换成地图图层(.shapefile)。
封装好的exe文件下载地址:
https://download.csdn.net/download/ashtyukjhf/19589740
2. 依赖模块
2.1 表格读取
Python用于表格读取的模块很多,由于此项目功能要求简单,只需要读取表格中的文本内容即可,应当选择尽量轻量级的模块,这里选用xlrd
进行表格的读取,需要注意版本为“1.2”。
安装时输入:
pip install xlrd==1.2
2.2 图层写入
图层的写入同样尽量选择轻量级的模块,这里选用pyshp
,安装时输入:
pip install pyshp
但是引用时要输入
import shapefile
3 功能实现
3.1 图层生成类的封装
由于生成shapefile图层的步骤比较复杂,这里单独写成一个类,对其功能进行封装。
class ShapeFileWriter(object):
def __init__(self,name:str,project=4326):
self.name=name#自定义图名
self.shp=shapefile.Writer(name+'.shp')
self.proj(project)#自定义投影坐标系
def __del__(self):
self.shp.close()
pass
def addField(self,key:str,keytype:str,length:str,decimal:str or int='6'):
if keytype=='F':
self.shp.field(key,keytype,length,decimal=int(decimal))
else:
self.shp.field(key,keytype,length)
def addPoint(self,x:float,y:float,values:list):
self.shp.point(x, y)
self.shp.record(*values)
def proj(self,p=4326):
wkt = 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AXIS["Latitude",NORTH],AXIS["Longitude",EAST],AUTHORITY["EPSG","4326"]]'
f = open(self.name+'.prj', 'w')
f.write(wkt)#写入投影信息
f.close()#关闭操作流
完整代码
# -*- coding: utf-8 -*-
import shapefile # 使用pyshp
import xlrd #版本为1.2
import os
class ShapeFileWriter(object):
def __init__(self,name:str,project=4326):
self.name=name
self.shp=shapefile.Writer(name+'.shp')
self.proj(project)
def __del__(self):
self.shp.close()
pass
def addField(self,key:str,keytype:str,length:str,decimal:str or int='6'):
if keytype=='F':
self.shp.field(key,keytype,length,decimal=int(decimal))
else:
self.shp.field(key,keytype,length)
def addPoint(self,x:float,y:float,values:list):
self.shp.point(x, y)
self.shp.record(*values)
def proj(self,p=4326):
wkt = 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AXIS["Latitude",NORTH],AXIS["Longitude",EAST],AUTHORITY["EPSG","4326"]]'
f = open(self.name+'.prj', 'w')
f.write(wkt)#写入投影信息
f.close()#关闭操作流
class Transform():
def __init__(self,name):
try:
os.makedirs(name)
except :pass
self.name = name
self.shape=ShapeFileWriter(name+'/'+name)
self.define()
self.load()
def define(self):
with open('字段定义.txt', mode='r', encoding='utf-8') as f:
a=f.readline().split('=')
b=f.readline().split('=')
self.x=int(a[1])
self.y=int(b[1])
#print(x,y)
fileds=f.readlines()
for filed in fileds:
filed=filed.replace('\n','').split(',')
self.shape.addField(*filed)
#print(filed)
def load(self):
try:
wb=xlrd.open_workbook(self.name+'.xlsx')
except :
try:
wb=xlrd.open_workbook_xls(self.name+'.xls')
except :pass
#print(wb)
table = wb.sheet_by_index(0)
#print (table)
for i in range(1,table.nrows):
values= (table.row_values(i))
try:
x=float(values[self.x])
y=float(values[self.y])
self.shape.addPoint(x, y, values)
except :pass
pass
name=input("文件名:")
name = name.split('.')[0]
Transform(name)
input('转换完成')
使用说明
使用方法
首先准备好xlsx或xls格式的数据表,表头只能有一行。
根据数据表表头编写字段定义文件字段定义.txt并与程序放在同一个文件夹。
运行程序,输入待转换的数据表文件名。
字段定义格式
投影定义
第一行,为投影类型,可选参数如下:
3857:球面墨卡托投影,用于谷歌地图、Bing地图、ESRI地图等;
4326:WGS-84坐标系,用于GPS坐标;
4610:西安80系;
4214:北京54系;
4490:中国大地坐标系2000。
如参数不在以上之列,则自动设置投影系为WGS-84。
坐标字段
第二、三行,为经纬度字段的位置,位置对应表格A列为0,B列为1……,以此类推。
字段属性
第四行及以后,根据数据表的表头,按顺序定义每一列的字段属性,每一行对应表格中的一列。
每一行第一词为字段名,尽量简短;
第二词为字段类型,'C’为字符型,'N’为整数型,'F’为浮点型,‘D’为日期;
第三词为字段长度,建议不要小于10;
若字段类型为’F’,可添加第四词,表示精确到小数点后的位数,留空则默认为6位。
示例
PROJECT=4326
X=2
Y=3
ID,N,20
NAME,C,20
LNG,F,20
LAT,F,20
VALUE1,F,30
VALUE2,F,30
注意事项
- 本程序只能读取数据表的第一个sheet,数据表存在多个sheet时可能读取失败;
- 字段定义文件的编码应为“UTF-8”,如果出现编码错误,用记事本打开,然后选择另存为,更改编码为“UTF-8”并替换原文件;
- 数据表文件名中如有空格,斜杆和多余的点号,会影响文件的读取和保存。