阿里云费用计算脚本

年底了,又到了算阿里云费用的时候了
1、导出阿里云的实例费用账单
2、请保证您的当前目录只有一个csv文件
3、目前只支持能分配财务单元的费用统计
4、执行本脚本请传入参数(参数是财务单元)
5、执行结果如下,只有这几列
‘账期’, ‘财务单元’,‘产品明细Code’, ‘产品明细’, ‘消费类型’, ‘账单类型’, ‘实例ID’, ‘实例昵称’, ‘资源组’, ‘实例配置’, ‘实例规格’, ‘私网IP’,
‘应付金额’
阿里云费用计算脚本_第1张图片

# -*- coding: UTF-8 -*-
import csv
import sys,os
from openpyxl import Workbook
from openpyxl.styles import Alignment
from openpyxl.styles import Font

#不支持oss waf ddos 快照统计

class ExcelWrite():
    def __init__(self,data,result_file_name,keys):
        self.__data = data
        self.__titile = self.__data[0]
        self.__index_1 = self.__titile.index('账期')# 确定每一列的索引
        self.__index_2 = self.__titile.index('财务单元')
        self.__index_3 = self.__titile.index('产品明细Code')
        self.__index_4 = self.__titile.index('产品明细')
        self.__index_5 = self.__titile.index('消费类型')
        self.__index_6 = self.__titile.index('账单类型')
        self.__index_7 = self.__titile.index('实例ID')
        self.__index_8 = self.__titile.index('实例昵称')
        self.__index_9 = self.__titile.index('资源组')
        self.__index_10 = self.__titile.index('实例配置')
        self.__index_11 = self.__titile.index('实例规格')
        self.__index_12 = self.__titile.index('私网IP')
        self.__index_13 = self.__titile.index('应付金额')
        self.__result_file_name = result_file_name
        self.__keys = keys #需要查找的财务单元
        self.__wb = Workbook()
        self.__sheet_pay = self.__wb.active
        self.__sheet_pay.title = u'总费用'
        #根据产品的code过滤每一种产品 并相应放到__product_data 里面
        self.__product = [['ecs','vm'],['rds','rords','bards'],['slb','slbpre'],['yundisk'],['prepaid_kvstore'],['badds'],['dtspre','dtspost'],['bandwidth_package','nat_gw','cbwp'],['ipv6bandwidth','ipv6gateway'],
                          ['elasticsearch','elasticsearchpre'],['cdn'],['mssp'],['eip'],['eci_betav1'],['ons','alikafka_pre'],['ri_pre'],['hbrpost'],['hdm_pre'],['opensearch_post'],['ri'],['mts'],['kms'],['cdi'],['ddos_fl_pre'],['sls'],['live'],['dmsenterprise'],
                          ['cbs_post'],['sas'],['pts','ptsbag'],['arms','arms_app_post'],['1'],['cas'],['cms_post'],['pvtzpost'],['alidns_pre'],['alimail'],['smartag']]
        #根据产品生成数据
        self.__product_data = [{'ecs':[]}, {'rds':[]}, {'slb':[]}, {'yundisk':[]},
                        {'prepaid_kvstore':[]}, {'badds':[]}, {'dtspre':[]},
                        {'bandwidth_package':[]}, {'ipv6bandwidth':[]},
                        {'elasticsearch':[]}, {'cdn':[]}, {'mssp':[]}, {'eip':[]}, {'eci_betav1':[]},
                        {'ons':[]}, {'ri_pre':[]}, {'hbrpost':[]}, {'hdm_pre':[]}, {'opensearch_post':[]}, {'ri':[]},
                        {'mts':[]}, {'kms':[]}, {'cdi':[]}, {'ddos_fl_pre':[]}, {'sls':[]}, {'live':[]}, {'dmsenterprise':[]},
                        {'cbs_post':[]}, {'sas':[]},  {'pts':[]}, {'arms':[]}, {'1':[]},
                        {'cas':[]}, {'cms_post':[]}, {'pvtzpost':[]}, {'alidns_pre':[]}, {'alimail':[]}, {'smartag':[]}]
        #根据产品生成sheet
        self.__product_sheet = [{'ecs':''}, {'rds':''}, {'slb':''}, {'yundisk':''},
                        {'prepaid_kvstore':''}, {'badds':''}, {'dtspre':''},
                        {'bandwidth_package':''}, {'ipv6bandwidth':''},
                        {'elasticsearch':''}, {'cdn':''}, {'mssp':''}, {'eip':''}, {'eci_betav1':''},
                        {'ons':''}, {'ri_pre':''}, {'hbrpost':''}, {'hdm_pre':''}, {'opensearch_post':''}, {'ri':''},
                        {'mts':''}, {'kms':''}, {'cdi':''}, {'ddos_fl_pre':''}, {'sls':''}, {'live':''}, {'dmsenterprise':''},
                        {'cbs_post':''}, {'sas':''},  {'pts':''}, {'arms':''}, {'1':''},
                        {'cas':''}, {'cms_post':''}, {'pvtzpost':''}, {'alidns_pre':''}, {'alimail':''}, {'smartag':''}]
        #根据产品记录总费用
        self.__all_pay = [{'ecs':[]}, {'rds':[]}, {'slb':[]}, {'yundisk':[]},
                        {'prepaid_kvstore':[]}, {'badds':[]}, {'dtspre':[]},
                        {'bandwidth_package':[]}, {'ipv6bandwidth':[]},
                        {'elasticsearch':[]}, {'cdn':[]}, {'mssp':[]}, {'eip':[]}, {'eci_betav1':[]},
                        {'ons':[]}, {'ri_pre':[]}, {'hbrpost':[]}, {'hdm_pre':[]}, {'opensearch_post':[]}, {'ri':[]},
                        {'mts':[]}, {'kms':[]}, {'cdi':[]}, {'ddos_fl_pre':[]}, {'sls':[]}, {'live':[]}, {'dmsenterprise':[]},
                        {'cbs_post':[]}, {'sas':[]},  {'pts':[]}, {'arms':[]}, {'1':[]},
                        {'cas':[]}, {'cms_post':[]}, {'pvtzpost':[]}, {'alidns_pre':[]}, {'alimail':[]}, {'smartag':[]}]
        self.remain_data = []
        self.__align = Alignment(horizontal='right')#样式右对齐
        self.__align_center = Alignment(horizontal='center')  # 样式右对齐
        self.__font = Font(u'宋体', size=11, bold=True, color='FF0000')#字体红色

#生成账单结果
    def create_file(self):
        self.remain_data=[]#无法确定费用的数据
        for item in self.__data[1:]:
            if item[ self.__index_2] in self.__keys:#根据财务单元过滤
                for search_key in self.__product:
                    if item[self.__index_3] in search_key:
                        for product_data in self.__product_data:
                            if search_key[0] ==  list(product_data.keys())[0]:
                                product_data[search_key[0]].append(item)
            else:
                self.remain_data.append(item)
        for product_data in self.__product_data:
            if len(list(product_data.values())[0]) != 0:
                for product_sheet in self.__product_sheet:
                    if list(product_data.keys())[0] == list(product_sheet.keys())[0]:
                        product_sheet[list(product_sheet.keys())[0]] = self.__wb.create_sheet(list(product_data.keys())[0].upper())
                data_ecs_handle = self.__handle_data(product_data) #ecs
                self.create_sheet(data_ecs_handle,list(product_data.keys())[0])
            else:
                #self.__sheet_ecs.cell(row=1, column=1, value='空')
                print('THIS {} is empty'.format(list(product_data.keys())[0]))

        #self.__create_sum_sheet()
        self.__wb.save(self.__result_file_name)
        self.__create_remain_csv()

    #创建 sheet
    def create_sheet(self,data_ecs_handle,tag):#obj是哪一个sheet  tag也是表明哪一种云服务
        ecs_title = ['账期','财务单元','产品明细Code','产品明细','消费类型','账单类型','实例ID','实例昵称','资源组','实例配置','实例规格','私网IP','应付金额']
        col_ecs = 1 #列
        row_ecs =1  #行
        for product_sheet in self.__product_sheet:
            if tag == list(product_sheet.keys())[0]:
                obj =product_sheet[tag]

        for j in ecs_title:
            obj.cell(row=row_ecs,column=col_ecs,value=j)
            col_ecs+=1
        row_ecs+=1
        time_ecs = data_ecs_handle[0][self.__index_1] # 设置初始账期,用来根据账期不同合并单元格,
        row_ecs_first = 2 #统计每月账单的开始行,用来算当前月账期的标记
        for ecs_item_row in data_ecs_handle:
            col_ecs = 1
            if ecs_item_row[self.__index_1] != time_ecs:#账期不同时开始合并单元格 计算这个月的费用
                obj.merge_cells(start_row=row_ecs, start_column=1, end_row=row_ecs, end_column=12)
                obj.cell(row=row_ecs, column=1, value=str(time_ecs)+'月份的费用为')
                obj.cell(row=row_ecs, column=1).font = self.__font
                obj.cell(row=row_ecs, column=1).alignment = self.__align
                sum = 0
                for i in range(row_ecs_first, row_ecs):
                    sum += obj['M' + str(i)].value
                sum = round(sum)
                print('{}{}月的费用为{}'.format(tag,time_ecs,sum))
                obj.cell(row=row_ecs, column=13, value=sum)
                obj.cell(row=row_ecs, column=13).font = self.__font

                for item  in self.__all_pay:
                    if  list(item.keys())[0] == tag:
                        item[tag].append({time_ecs:sum})

                row_ecs_first = row_ecs + 1
                time_ecs = ecs_item_row[self.__index_1]
                row_ecs += 1

            for ecs_item_col in ecs_item_row:#月份相同时 依次填充每一行里面的每一列
                obj.cell(row=row_ecs, column=col_ecs, value=ecs_item_col)
                col_ecs+=1
            row_ecs+=1

        obj.merge_cells(start_row=row_ecs, start_column=1, end_row=row_ecs, end_column=12)
        obj.cell(row=row_ecs, column=1, value=str(time_ecs) + '月份的费用为')
        obj.cell(row=row_ecs, column=1).font = self.__font
        obj.cell(row=row_ecs, column=1).alignment = self.__align
        sum = 0
        for i in range(row_ecs_first, row_ecs):
            sum += obj['M' + str(i)].value
        sum = round(sum)
        print('{} {}月的费用为{}'.format(tag, time_ecs, sum))
        obj.cell(row=row_ecs, column=13, value=sum)
        obj.cell(row=row_ecs, column=13).font = self.__font
        for item in self.__all_pay:
            if list(item.keys())[0] == tag:
                item[tag].append({time_ecs: sum})
        print('the sum pay is {}'.format(self.__all_pay))


    def __create_sum_sheet(self):
        row = 2 #行
        row_for_sum = 3 #填写行的总计 从第三行开始算
        self.__sheet_pay.cell(row=row, column=1, value='账期')
        col_for_row1 = 2 #第一行的列数 从第二列开始算
        for pay in self.__all_pay:

            for key,value in list(pay.items()):

                if len(value) != 0:#标题
                    self.__sheet_pay.cell(row=2, column=col_for_row1, value=key)
                    #每一种云服务列相同,行都是从第二行开始
                    row = 3
                    for item in value:
                        for key1,value1 in list(item.items()):
                            if  not isinstance(self.__sheet_pay.cell(row=row,column=1).value,str) :#第一列的账期不存在时
                                 self.__sheet_pay.cell(row=row, column=1, value=key1)
                                 row_for_sum+=1 #月份增加一次加一行
                            self.__sheet_pay.cell(row=row, column=col_for_row1, value=value1)
                            row += 1
                     #每一种云服务重新换列
                    col_for_row1+=1
        print(row_for_sum,col_for_row1)

        #标题
        first_month = self.__sheet_pay.cell(row=3,column=1).value
        last_month = self.__sheet_pay.cell(row=(row_for_sum-1),column=1).value
        self.__sheet_pay.merge_cells(start_row=1, start_column=1, end_row=1, end_column=col_for_row1)
        self.__sheet_pay.cell(row=1, column=1, value=first_month+'到'+last_month+'的总费用')
        self.__sheet_pay.cell(row=1, column=1).font = self.__font
        self.__sheet_pay.cell(row=1, column=1).alignment = self.__align_center

        #行列的合计
        self.__sheet_pay.cell(row=row_for_sum, column=1, value='合计')
        self.__sheet_pay.cell(row=2, column=col_for_row1, value='合计')
        self.__sheet_pay.cell(row=2, column=col_for_row1).font = self.__font
        self.__sheet_pay.cell(row=row_for_sum, column=1).font = self.__font


        #算每一列的总和
        for col_pay in range(2,col_for_row1):
            sum_for_the_whole_col = 0
            for row_pay in range(3,row_for_sum):
                sum_for_the_whole_col+=self.__sheet_pay.cell(row=row_pay,column=col_pay).value
            self.__sheet_pay.cell(row=row_for_sum, column=col_pay, value=sum_for_the_whole_col)
            self.__sheet_pay.cell(row=row_for_sum, column=col_pay).font = self.__font

        #算每一行的总和
        for row_pay in range(3,(row_for_sum+1)):
            sum_for_the_whole_row = 0
            for col_pay in range(2, col_for_row1):
                sum_for_the_whole_row += self.__sheet_pay.cell(row=row_pay, column=col_pay).value
            self.__sheet_pay.cell(row=row_pay, column=col_for_row1, value=sum_for_the_whole_row)
            self.__sheet_pay.cell(row=row_pay, column=col_for_row1).font = self.__font

    def __create_remain_csv(self):
        print('现在生成remain.csv文件,这是没有匹配到的数据 ')
        path = "remain.csv"
        with open(path, 'w', encoding='UTF-8') as f:
            f_csv = csv.writer(f)
            f_csv.writerow(self.__data[0])
            f_csv.writerows(self.remain_data)



    #根据sheet的每一列提取数
    def __handle_data(self,data_ecs):
        data_ecs_handle=[]
        for item in list(data_ecs.values())[0]:
            item_data = []
            item_data.append(item[self.__index_1])
            item_data.append(item[self.__index_2])
            item_data.append(item[self.__index_3])
            item_data.append(item[self.__index_4])
            item_data.append(item[self.__index_5])
            item_data.append(item[self.__index_6])
            item_data.append(item[self.__index_7])
            item_data.append(item[self.__index_8])
            item_data.append(item[self.__index_9])
            item_data.append(item[self.__index_10])
            item_data.append(item[self.__index_11])
            item_data.append(item[self.__index_12])
            item_data.append(float(item[self.__index_13]))
            data_ecs_handle.append(item_data)
        return  data_ecs_handle




#读取csv文件
def get_data(file,title):
    data = []
    try:
        with open(file,'r', encoding='UTF-8-sig') as csvfile:
            csv_reader = csv.reader(csvfile)
            for row in csv_reader:
                data.append(row)
    except:
        print('您的文件读取格式不对')
        sys.exit(1)

    #判断要的每一列数据是否存在
    print('titel is {}'.format(data[0]))
    for item in title:
        if item not in data[0]:
            print('this {} content is not exist'.format(item))
            sys.exit(1)
    return data

def get_arg():
    if len(sys.argv) == 1 :
        print("只需要一个参数,请输入财务单元例如  浙江新闻app 天目云")
        sys.exit(1)
    path = os.getcwd()
    dirs = os.listdir(path)
    csv = 0
    file= ''
    for dir in dirs:
        if csv > 1:
            print('您的当前目录不止一个csv文件')
            sys.exit(1)
        if os.path.splitext(dir)[1] ==  '.csv':
            file = dir
            csv+=1
    return    [sys.argv[1:],file]



if __name__ == '__main__':
    title = ['账期', '财务单元','产品明细Code', '产品明细', '消费类型', '账单类型', '实例ID', '实例昵称', '资源组', '实例配置', '实例规格', '私网IP',
             '应付金额'] # 需要的每项数据
    args = get_arg()
    data = get_data(args[1],title) #读取csv文件获取数据
    result_file_name =args[0][0]+'.xls'   # 统计生成的账单文件
    obj = ExcelWrite(data,result_file_name,args[0])
    obj.create_file()

你可能感兴趣的:(python)