【办公自动化】土地利用/土地用途统计工具

空间规划编制中,需要经常计算统计各用地面积,而最终成果中或报备材料中,不可缺少的就有用地用海现状表、土地利用/土地用途结构调整表等多种面积统计表,此工具就是用来生成各种面积统计表!

工具自带用地标准如下:

  • 国标用地标准依据《国土空间规划用地用海分类指南》[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工具箱的同学,关注[ 公众号 ]回复“工具箱”,自动发送链接

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

规划酱

谢谢鼓励!一起自动化!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值