空间规划编制中,需要经常计算统计各用地面积,而最终成果中或报备材料中,不可缺少的就有用地用海现状表、土地利用/土地用途结构调整表等多种面积统计表,此工具就是用来生成各种面积统计表!
工具自带用地标准如下:
- 国标用地标准依据《国土空间规划用地用海分类指南》[2020.2],
- 江苏用地标准依据《江苏省村庄规划编制指南》(试行)[2020.8],
- 南京用地标准依据《南京市村庄规划编制技术指南》[2020.3]
1、用地统计常规操作
- 打开需要统计的图层属性表,任意字段右击,选择汇总
- 1选择汇总字段,建议选择Layer,2找到包含面积的Shape_Area,勾选总和,3选择输出位置,确定
- 新生成一个layer字段的汇总表,包含各类用地的面积汇总,导出Excel就可以编辑成各种需要的表格,距离各种表格还有N步。
2、用地汇总表/平衡表生成
- 打开土地用途统计工具,对应选择框选择单一现状用地或者规划用地,
- 选择用地标准,需要自定义标准的选择修改好的自定义用地标准.xls(后文获取)
- 选择保存位置,用现状用地框生成现状用地汇总表,用规划用地框生成规划用地汇总表。
注意:
- 各用地面积通过图层文件中ydbm和Shape_Area两个字段进行统计;
- 只有通过三调转换工具生成的图层才会自动添加ydbm字段,如没有可自行添加ydbm(用地编码);
- 刚编辑修改完的用地图层,请在Shape_Area字段右击,点击计算几何…选择平方米更新斑块面积;
- 保存关闭并重新打开的图层理论上已经自动更新完斑块面积,Shape_Area字段的计算几何…灰显,无法使用。
生成的用地汇总表/平衡表如下:
3、土地用途结构调整表生成
按照《江苏省村庄规划编制指南》(试行)2020年版的要求,报备材料包括“两图、两表、一库、一清单”。其中,“两表”包括规划指标表和土地用途结构调整表。
操作如下:
- 生成土地用途结构调整表需要有规划基期年用地和规划目标年用地,通过下拉菜单分别获取相应的图层。
- 选择用地标准,需要自定义标准的选择修改好的自定义用地标准.xls(后文获取)
- 选择保存位置,确定自动生成土地用途结构调整表.xls
注意:
自动生成的土地用途结构调整表包含用地中所有大、中、小类用地,适合设计过程中的校核与调整。不需要的可自行删除相应行
生成的土地用途结构调整表如下:
4、如何自定义标准
- 获取自定义用地标准.xls(后文获取)
- 按照当地标准修改YDBM、YDMC、YDFL
- 涉及不同标准,需要提供五种地类包含大类用地编码的最大值,如江苏村庄标准中,城乡建设用地包含06-14多个大类用地,填入最大值14
目前工具中可选标准的地类分布如下
江苏:01-05、06-14、15-17、18-28
南京:01-05、06-13、14-16、17-21
国标:01-03、04-12、13-15、16-22
5、脚本文件
GIS里python是2.7版本,自带的库不多,没有pandas就用的xlwt。
获取图层信息,通过ydbm和Shape_Area 生成字典,把同类面积进行汇总
import xlwt
import arcpy
def get_area(layer):
gather_dic ={}
table = arcpy.SearchCursor(layer)
for row in table:
if row.ydbm in gather_dic.keys():
gather_dic[row.ydbm] +=row.Shape_Area
else:
gather_dic[row.ydbm] = row.Shape_Area
return gather_dic
小类生成所属中类,中类生成所属大类
#各类用地汇总
def count_values(dic):
dic_count ={}
for key in dic:
dic_count[key] = dic[key]
for n in [6,4]:
for key in dic:
if len(key) == n:
if key[:n-2] not in dic_count.keys(): dic_count[key[:n-2]] =0
dic_count[key[:n-2]] += dic[key]
#print(dic_count)
return dic_count
用现状用地和规划用地生成一张有顺序的关键信息表,没有DataFrame就用个二维list吧
[编码,名称,现状面积,规划面积]
[编码,名称,现状面积,规划面积]
…
#生成列表
def set_table(xz_dic = {},gh_dic = {}):
dic_hb = {} #合成一个字典
for key in gh_dic:
if xz_dic.get(key):
dic_hb[key] = [xz_dic[key]/10000,gh_dic[key]/10000]
else:
dic_hb[key] = [0,gh_dic[key]/10000]
for key in xz_dic:
if not gh_dic.get(key):
dic_hb[key] = [xz_dic[key]/10000,0]
table = []
keys = list(dic_hb.keys())
keys.sort()
area = [0,0]
for key in keys:
table.append([key,dic_zw[bz][key]]+dic_hb[key]) #[编码,名称,现状面积,规划面积]
if len(key) == 2 :
area [0] += dic_hb[key][0]
area [1] += dic_hb[key][1]
table.append(['0','总计']+area)
return table
[u’农林用地’,u’城乡建设用地’,u’其他建设用地’,u’建设用地’,u’自然保护与保留用地’,u’海洋利用’]
为了能区分这几个大大类,且保证没有的时候不显示名称和合计,写了好几个版本,最后用的笨办法。
#计算各合计值插入表中,计算表中位置
def subtotal():
xzmj1 = ghmj1 = xzmj2 = ghmj2 = xzmj3 = ghmj3 = xzmj4 = ghmj4 = xzmj5 = ghmj5 = 0
n1 = n2 = n3 = n4 = n5 = 0
length = len(table)
for i in range(length-1):
#'js':[0, 5, 14, 17, 20, 28],
#算好每类的面积,有才显示
if int(table[i][0][:2])<= dic_fl[bz][1]:
if len(table[i][0]) == 2:
xzmj1 += table[i][2]
ghmj1 += table[i][3]
n1 = i+1
elif dic_fl[bz][1]+1 <= int(table[i][0][:2])<= dic_fl[bz][2]:
if len(table[i][0]) == 2:
xzmj2 += table[i][2]
ghmj2 += table[i][3]
n2 = i+1
elif dic_fl[bz][2]+1 <= int(table[i][0][:2])<= dic_fl[bz][3]:
if len(table[i][0]) == 2:
xzmj3 += table[i][2]
ghmj3 += table[i][3]
n3 = i+1
elif dic_fl[bz][3]+1 <= int(table[i][0][:2])<= dic_fl[bz][4]:
if len(table[i][0]) == 2:
xzmj4 += table[i][2]
ghmj4 += table[i][3]
n4 = i+1
elif dic_fl[bz][4]+1 <= int(table[i][0][:2])<= dic_fl[bz][5]:
if len(table[i][0]) == 2:
xzmj5 += table[i][2]
ghmj5 += table[i][3]
n5 = i+1
#[[0,0,0,1], [0,0,1,1], [0,0,1,1], [0,0,0,1], [0,0,0,1], [0,0,0,0]]
#u'农林用地',u'城乡建设用地',u'其他建设用地',u'建设用地',u'自然保护与保留用地',u'海洋利用',
list_insert = [] #表中合计的内容和位置
list_fw =[] #大大类的格位
n = 2
if n1 != 0:
list_insert.append([u'00', u'合计', xzmj1, ghmj1, n1])
list_fw.append( [2,n1+n,0,1,u'农林用地'])
n +=1
if n2 != 0:
list_insert.append([u'00', u'小计', xzmj2, ghmj2, n2])
start = list_fw[-1][1]+1 if len(list_fw)>0 else 2 #如果没有前一类,那就从2开始显示
list_fw.append([start,n2+n,1,1,u'城乡建设用地'])
n+=1
if n3 != 0 :
list_insert.append([u'00', u'小计', xzmj3, ghmj3, n3])
start = list_fw[-1][1]+1 if len(list_fw)>0 else 2
list_fw.append([start,n3+n,1,1,u'其他建设用地'])
n+=1
if n2 != 0 and n3 != 0: #如果两建设用地都有那才有合计
list_insert.append([u'3', u'合计', xzmj2+xzmj3, ghmj2+ghmj3, n3])
list_fw.append([list_fw[-2][0],list_fw[-1][1]+1,0,0,u'建设用地'])
n+=1
elif n2 != 0 or n3 != 0: #只有一种建设用地那就没合计
list_fw.append([list_fw[-1][0],list_fw[-1][1],0,0,u'建设用地'])
if n4 != 0 :
list_insert.append([u'00', u'合计', xzmj4, ghmj4, n4])
start = list_fw[-1][1]+1 if len(list_fw)>0 else 2
list_fw.append([start,n4+n,0,1,u'自然保护与保留用地'])
n+=1
if n5 != 0 :
list_insert.append([u'00', u'合计', xzmj5, ghmj5, n5])
start = list_fw[-1][1]+1 if len(list_fw)>0 else 2
list_fw.append([start,n5+n,0,1,u'海洋利用地'])
n=0
for i in list_insert:
table.insert(i[-1]+n,i) #塞到list里
n+=1
return list_fw
生成两种单元格样式,正常单元格和百分数单元格,不能整体设置格式么?显得很笨
#表格样式
def set_cell_style():
widths = [3.2,5,5,5,15,9,9,9,9,9]
for i in range(len(widths)):
sheet.col(i).width = int(widths[i]*300)
alignment = xlwt.Alignment()
alignment.horz = 0x02 # 0x01(左端对齐)、0x02(水平方向上居中对齐)、0x03(右端对齐)
alignment.vert = 0x01 # 0x00(上端对齐)、 0x01(垂直方向上居中对齐)、0x02(底端对齐)
alignment.wrap = 1 #自动转行
font = xlwt.Font() # 为样式创建字体
font.name = u'宋体'
borders = xlwt.Borders() # Create Borders
borders.left = borders.right = borders.top = borders.bottom = 1
borders.left_colour = borders.right_colour = borders.top_colour = borders.bottom_colour = 0x40
style = xlwt.XFStyle() #常规样式
style.num_format_str = '0.00'
style.alignment = alignment
style.font = font
style.borders = borders
style_pct = xlwt.XFStyle() #百分数样式
style_pct.num_format_str = '0.00%'
style_pct.alignment = alignment
style_pct.font = font
style_pct.borders = borders
return style,style_pct
生成横竖表头
#生成表头
def sheet_style():
if xz_layer == '' or gh_layer == '':
sheet_list = [[0,1,0,4, u'用地分类'], [0,1,5,5, u'面积(公顷)'], [0,1,6,6, u'比重(%)']]
else:
sheet_list = [[0,1,0,4, u'分类'], [0,0,5,6, u'规划基期年'], [0,0,7,8, u'规划目标年'], [0,1,9,9, u'规划期内面积增减'], [1,1,5,5, u'面积'], [1,1,6,6, u'比重'], [1,1,7,7, u'面积'], [1,1,8,8, u'比重']]
for cell in sheet_list: #分两种情况写入表头,单一用地和两种用地一起
sheet.write_merge(cell[0],cell[1],cell[2],cell[3],cell[4], style)
for lb in list_fw: #前面计算好的位置,在这里写入表格
sheet.write_merge(lb[0], lb[1], lb[2], lb[3], lb[4], style)
按顺序填入用地类别、用地面积、比重,比重填的是公式
# 填用地名称填数字
def input_value():
sta = 0
for n in range(len(table)):
#写入用地名称
if table[n][0] == '0': #总计
sheet.write_merge(n+2, n+2, 0, 4,table[n][1] , style)
elif table[n][0] == '3': #建设用地合计
sheet.write_merge(n+2, n+2, 1, 4,table[n][1] , style)
elif len(table[n][0]) == 2 : #大类
sheet.write_merge(n+2, n+2, 2, 4,table[n][1] , style)
elif len(table[n][0]) == 4: #中类
sheet.write_merge(n+2, n+2, 3, 4,table[n][1] , style)
else: #小类
sheet.write(n+2,4,table[n][1] , style)
#写入大类的其中
if n+1< len(table) and len(table[n][0]) == 2 and len(table[n+1][0]) == 4:
sta = n+3
elif n+1< len(table)and len(table[n][0]) >= 4 and len(table[n+1][0]) == 2 :
end = n+2
sheet.write_merge(sta,end, 2 ,2 ,u'其中' ,style)
#写入数字
if gh_layer == '' :
sheet.write(n+2, 5, table[n][2] , style) #现状面积
sheet.write(n+2, 6, xlwt.Formula( 'F'+str(n+3)+'/F$'+ str(len(table)+2)), style_pct) #比重
elif xz_layer == '':
sheet.write(n+2, 5, table[n][3] , style) #规划面积
sheet.write(n+2, 6, xlwt.Formula( 'F'+str(n+3)+'/F$'+ str(len(table)+2)), style_pct) #比重
elif gh_layer != '' and xz_layer != '':
sheet.write(n+2, 5, table[n][2] , style) #现状面积
sheet.write(n+2, 6, xlwt.Formula( 'F'+str(n+3)+'/F$'+ str(len(table)+2)), style_pct) #比重
sheet.write(n+2, 7, table[n][3] , style) #规划面积
sheet.write(n+2, 8, xlwt.Formula( 'H'+str(n+3)+'/H$'+ str(len(table)+2)), style_pct) #比重
sheet.write(n+2, 9, xlwt.Formula( 'H'+str(n+3)+ '-F'+str(n+3)), style) #差值
字典存着三种用地标准
dic_zw = {'js': {u'1301': u'\u516c\u56ed\u7eff\u5730', ...},
'nj': {u'0602': u'\u519c\u6751\u4f4f\u5b85\u7528\u5730',...},
'gb': {u'1304': u'\u673a\u573a\u7528\u5730',... }} #内置的标准,太长省略了
dic_fl = {'js':[0, 5, 14, 17, 28],
'nj':[0, 5, 13, 16, 21],
'gb':[0, 3, 12, 15, 22]} #三种标准的大大类划分
#获取GIS的面板信息
xz_layer = arcpy.GetParameterAsText(0)
gh_layer = arcpy.GetParameterAsText(1)
ydbz = arcpy.GetParameterAsText(2)
zdy_excel = arcpy.GetParameterAsText(3)
save_file = arcpy.GetParameterAsText(4)
开始了主程序
if __name__ == '__main__':
if zdy_excel : #优先自定义标准
arcpy.AddMessage(u'> 自定义标准 ..')
bz = 'zdy'
i = 0
zw =[0]
zdy = {}
table1 = arcpy.SearchCursor(zdy_excel)
for row in table1:
zdy[row.ydbm] = row.ydmc
if i < 5:
zw.append(row.ydfl)
i += 1
dic_zw[bz] = zdy
dic_fl[bz] = zw
elif ydbz == u'国家用地标准':
bz = 'gb'
arcpy.AddMessage(u'> 国家用地标准..')
elif ydbz == u'南京村庄标准':
bz = 'nj'
arcpy.AddMessage(u'> 南京村庄标准..')
else:
bz = 'js'
arcpy.AddMessage(u'> 江苏村庄标准..')
if xz_layer == '' and gh_layer == '': #给不选用地的一个错误警告
arcpy.AddError(u'=============================')
arcpy.AddError(u' 错误:至少选择一种用地!')
arcpy.AddError(u'=============================')
arcpy.ExecuteError
else:
xz_dic = gh_dic = {}
if xz_layer :
xz_dic = count_values(get_area(xz_layer))
xls = u'现状用地汇总表'
arcpy.AddMessage (u'> 获取现状用地面积..')
if gh_layer :
gh_dic = count_values(get_area(gh_layer))
xls = u'规划用地汇总表'
arcpy.AddMessage (u'> 获取规划用地面积..')
if xz_layer and gh_layer :
xls = u'土地用途结构调整表'
arcpy.AddMessage (u'> 计算面积..')
#形成数据表格
table = set_table(xz_dic,gh_dic)
#计算各地类合计
list_fw = subtotal()
arcpy.AddMessage (u'> 生成表格..')
#定义表格
workbook = xlwt.Workbook(encoding='utf-8')
#cell_overwrite_ok=True 可以反复写入
sheet = workbook.add_sheet('sheet',cell_overwrite_ok=True)
#获取数据单元格和比重单元格样式
style,style_pct = set_cell_style()
#填入表头
sheet_style()
#填入数值
input_value()
path = save_file + u'\\'+xls+'.xls'
workbook.save( path)
arcpy.AddMessage (u'> 保存位置:'+ path)
————————————————
9月16日更新了
工具箱更名为国土空间工具箱
国土空间工具箱1.3_by规划酱.tbx
自定义用地标准.xls
————————————————
需要GIS工具箱的同学,关注[ 公众号 ]回复“工具箱”,自动发送链接