又帮了财务小姐姐的一个小忙-python处理excel

	又到了一月一次的财务小姐姐不舒服的时候了(我说的是处理工资条)。她们又要开始忙起来了。
最近收到一个朋友的一个小问题,他不知道如何处理,想问问我有什么好的办法。
我首先就想到了用python来处理excel的这个,于是就上手写了一个小程序,如下。
	
1.需求:由于财务统计了一张所有员工的工资单,但是在发工资的时候,不仅要将钱给到员工手中,
	   还需要一张单人的工资条。但是这样就要复制好多个标题头,贴到每个人的工资条上面
	   (n个员工就要复制n次,repeat很多,很麻烦)。
	   如图:原图如下:

原始图片

想要实现的效果图如下:这样就可以打印,撕下来做成一张张的工资条了

复制1-4行,粘贴到每个人的前面做表头

2.分析:选用python来操作,调用openplxy包。
	   为了保存原表的数据,应该先将原表的所有内容全部保存在字典里面;
	   然后新建一张表,根据要求将数据粘贴进去;
	   之后对数据的格式按照原表的样式重新弄一遍。

3,上代码:
from openpyxl import Workbook, load_workbook
from openpyxl.styles import fills,colors,NamedStyle,Font,Side,Border,PatternFill,Alignment,Protection
import openpyxl
import datetime
import sys

"""先用一个类来实现一些表格的操作"""
class ExcelUtils():
    """获取Excel表格内容"""
    # def __init__(self,excelfilepath,sheet_name):
    #     print(excelfilepath, sheet_name)
    #     self.excelfilepath = excelfilepath # excelfilepath 为excel文件的完整路径
    #     self.sheet_name = sheet_name       #sheet_name为excel表的sheet名称
    #     self.ws = self.getsheet()		   #python的类可以在初始化方法中调用类的其他方法
    def __init__(self, excelfilepath):
        print(excelfilepath)
        self.excelfilepath = excelfilepath  # excelfilepath 为excel文件的完整路径

        self.ws = self.getsheet()  # python的类可以在初始化方法中调用类的其他方法

    def getsheet(self):
        self.wb = openpyxl.load_workbook(self.excelfilepath, data_only=True) # 获取整个excel表对象

        # ws = self.wb.active # 获取当前sheet对象
        # self.sheet_name = sheet_name  # sheet_name为excel表的sheet名称
        sheet_names = self.wb.sheetnames
        ws = self.wb[sheet_names[len(sheet_names) - 1]]
        return ws

    def get_row_count(self):
        row_count =self.ws.max_row #获取当前sheet的最大行数
        return row_count

    def __get_cell_value(self,row_index, col_index):
        cell_value = self.ws.cell(row_index,col_index).value
        # 根据入参的值获取单元格的数据,两个下划线表示类的私有化方法
        return cell_value

    def get_colum_count(self):
        colum_count =self.ws.max_column #获取当前sheet的最大列数
        return colum_count

    def get_merged_info(self):
        """
        获取合并单元格的坐标范围,例如:“C1: D2”
        """
        merged_info = self.ws.merged_cells
        return merged_info

    def get_merged_cell_value(self,row_index, col_index):
        """
        既能获取普通单元格的数据又能获取合并单元格数据
        row_index和col_index,最小行和最小列请传1
        该方法的原理为将合并单元格的范围都视为获取合单元格左上角第一个普通单元格的值
        """
        cell_value = None
        mergedlist = self.get_merged_info()
        for merged in mergedlist:
            # 将获取到的单元格对象拆分为四个值
            row_start, row_end, colum_start, colum_end = merged.min_row, merged.max_row, merged.min_col, merged.max_col
            if row_index >= row_start and row_index <= row_end:
                if col_index >= colum_start and col_index <= colum_end:
                    cell_value = self.__get_cell_value(row_start, colum_start)
                    break  # 防止循环去进行判断出现值覆盖的情况。找到了想要的值,就不能再继续找了,必须直接跳出循环,返回出去
                else:
                    cell_value = self.__get_cell_value(row_index, col_index)
            else:
                cell_value = self.__get_cell_value(row_index, col_index)
        return cell_value # 返回的就是合并单元的值,为字符串类型
    def get_first_row(self):
        """
        获取第一行的数据
        """
        columns = excelutils.ws.max_column #获取最大列数
        rowdata = []
        for i in range(1, columns + 1): # range函数的结束数字本身并不执行,所以需要+1
            cellvalue = excelutils.ws.cell(row=1, column=i).value
            rowdata.append(cellvalue)
        return rowdata

    def get_sheet_data_by_dict(self):
        #将整个sheet列表除了第一行以外的内容全部作为字典的值进行储存
        rowdata = self.get_first_row()
        all_sheet_value_dict = []
        for row in range(1, self.ws.max_row ):
            valuedict = {}
            for col in range(1, self.ws.max_column + 1):
                valuedict[rowdata[col - 1]] = self.get_merged_cell_value(row + 1, col)
            all_sheet_value_dict.append(valuedict)
        return all_sheet_value_dict

    def save_excle(self):
        self.wb.save(self.excelfilepath)

# argv_str = sys.argv
# # print(argv_str)
# excel_name = argv_str[1]
excel_name = "乾元农业2020年9月基地工资表.xlsx"
aa = ExcelUtils(excel_name)

"""获取合并的单元格内容,保存在title_head里面"""
title_head = []
title_head.append(aa.get_merged_cell_value(1, 1))
title_head.append(aa.get_merged_cell_value(2, 1))
title_head.append(aa.get_merged_cell_value(3, 1))
title_head.append(aa.get_merged_cell_value(3, 2))
title_head.append(aa.get_merged_cell_value(3, 3))
title_head.append(aa.get_merged_cell_value(3, 34))
title_head.append(aa.get_merged_cell_value(3, 35))
for i in range(3, 5):
    for j in range(4, 34):
        title_head.append(aa.get_merged_cell_value(i, j))
print(title_head)
"""获取每个单元格的内容保存在num_list"""
num_list = []
for i in range(5, aa.get_row_count()):
    for j in range(4, 34):
        num_list.append(aa.get_merged_cell_value(i, j))
other_list = []
for i in range(5, aa.get_row_count()-1, 2):
    other_list.append(aa.get_merged_cell_value(i, 1))
    other_list.append(aa.get_merged_cell_value(i, 2))
    other_list.append(aa.get_merged_cell_value(i, 3))
    other_list.append(aa.get_merged_cell_value(i, 34))
    other_list.append(aa.get_merged_cell_value(i, 35))

# # #保存写操作
a = datetime.datetime.now()
date_str = a.strftime('%Y%m%d%H%M%S')
ws2 = aa.wb.create_sheet("数据处理" + date_str, 0)
# 批量合并单元格
"""先找一个字体的模板"""
my_alignment = Alignment(
    horizontal = 'general', # 水平:常规
    vertical = 'bottom',   # 垂直:底部对齐
    text_rotation = 0,   # 文本方向:0度
    wrap_text = False,   # 自动换行
    shrink_to_fit = False,  # 缩小字体填充
    indent = 0 # 缩进0
  )
index_other_data = 0
# font = Font('黑体', size=14, color=colors.BLACK, bold=False, italic=True, underline='double')
"""定义好大标题和小标题的字体样式"""
font = Font('黑体', size=14, color=colors.BLACK, bold=True)
font_head2 = Font('黑体', size=10, color=colors.BLACK, bold=True)
"""设置合并单元格并写入数据和更改字体样式"""
my_alignment1 = Alignment(horizontal='center', vertical='center', wrap_text = True)
for i in range(1, (aa.get_row_count()-5)//2*6, 6):
    ws2.merge_cells(start_row=i, start_column=1, end_row=i, end_column=35)
    ws2.cell(i, 1).alignment = my_alignment1
    ws2.cell(i, 1).font = font
    ws2.cell(i, 1).value = title_head[0]
    ws2.merge_cells(start_row=i+1, start_column=1, end_row=i+1, end_column=35)
    ws2.cell(i+1, 1).alignment = my_alignment1
    ws2.cell(i+1, 1).font = font
    ws2.cell(i+1, 1).value = title_head[1]
    ws2.merge_cells(start_row=i + 2, start_column=1, end_row=i + 3, end_column=1)
    ws2.cell(i+2, 1).alignment = my_alignment1
    ws2.cell(i+2, 1).font = font_head2
    ws2.cell(i+2, 1).value = title_head[2]
    ws2.merge_cells(start_row=i + 2, start_column=2, end_row=i + 3, end_column=2)
    ws2.cell(i+2, 2).alignment = my_alignment1
    ws2.cell(i+2, 2).font = font_head2
    ws2.cell(i+2, 2).value = title_head[3]
    ws2.merge_cells(start_row=i + 2, start_column=3, end_row=i + 3, end_column=3)
    ws2.cell(i+2, 3).alignment = my_alignment1
    ws2.cell(i+2, 3).font = font_head2
    ws2.cell(i+2, 3).value = title_head[4]
    ws2.merge_cells(start_row=i + 2, start_column=34, end_row=i + 3, end_column=34)
    ws2.cell(i+2, 34).alignment = my_alignment1
    ws2.cell(i+2, 34).font = font_head2
    ws2.cell(i+2, 34).value = title_head[5]
    ws2.merge_cells(start_row=i + 2, start_column=35, end_row=i + 3, end_column=35)
    ws2.cell(i+2, 35).alignment = my_alignment1
    ws2.cell(i+2, 35).font = font_head2
    ws2.cell(i+2, 35).value = title_head[6]

    ws2.merge_cells(start_row=i + 4, start_column=1, end_row=i + 5, end_column=1)
    ws2.cell(i+4, 1).alignment = my_alignment1
    ws2.cell(i+4, 1).value = other_list[index_other_data]
    ws2.merge_cells(start_row=i + 4, start_column=2, end_row=i + 5, end_column=2)
    ws2.cell(i+4, 2).alignment = my_alignment1
    ws2.cell(i+4, 2).value = other_list[index_other_data+1]
    ws2.merge_cells(start_row=i + 4, start_column=3, end_row=i + 5, end_column=3)
    ws2.cell(i+4, 3).alignment = my_alignment1
    ws2.cell(i+4, 3).value = other_list[index_other_data+2]
    ws2.merge_cells(start_row=i + 4, start_column=34, end_row=i + 5, end_column=34)
    ws2.cell(i+4, 34).alignment = my_alignment1
    ws2.cell(i+4, 34).value = other_list[index_other_data+3]
    ws2.merge_cells(start_row=i + 4, start_column=35, end_row=i + 5, end_column=35)
    ws2.cell(i+4, 35).alignment = my_alignment1
    ws2.cell(i+4, 35).value = other_list[index_other_data+4]
    index_other_data += 5
index_num_data = 0
"""写入单个单元格的数据并设置样式"""
for row in range(3, (aa.get_row_count()-5)//2*6, 6):
    index_head_data = 7
    for i in range(4, 34):
        ws2.cell(row, i).alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)
        ws2.cell(row, i).value = title_head[index_head_data]
        ws2.cell(row+1, i).alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)
        ws2.cell(row+1, i).value = title_head[index_head_data+30]
        ws2.cell(row+2, i).alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)
        ws2.cell(row+2, i).value = num_list[index_num_data]
        ws2.cell(row+3, i).alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)
        ws2.cell(row+3, i).value = num_list[index_num_data + 30]
        index_head_data += 1
        index_num_data += 1
    index_num_data += 30
"""设置某些指定单元格的宽度"""
letter_A = chr(65)
ws2.column_dimensions[letter_A].width = 5
for i in range(3, 26):
    letter = chr(i + 65)
    ws2.column_dimensions[letter].width = 4
for i in range(0, 7):
    letter_A = chr(65)
    letter = chr(i + 65)
    ws2.column_dimensions[letter_A+letter].width = 4
aa.save_excle()
print('完成!')
4,程序运行之后的效果图:多了一个sheet,也就是第一个

程序运行后的效果图

5.总结:新手刚学,CV的地方太多,有些地方还可以优化,由于时间关系,先就这样实现,后面有新的需求,
	   再一起优化一下~

对于有C++等编程基础的同学, 搞python上手还是挺快的,毕竟都是面向对象嘛。对象?这个程序中我只有一个对象,不合理。。。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Qter_Sean

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值