python:openpyxl实现表格内容的读取和精准写入


需求

在这里插入图片描述

再想想,是读取一份表格内容对应数据填入到另一份表格数据,实现精准写入,还有一个注意点就是表格公司不能破坏,写入的数据可以自动被表格内的公式计算


思路

对于表格的操作,我第一个想到的就是pandas,但是对于这个情景仔细一下想,精准写入会不会破坏表格内的公式,能实现很精准的写入吗,我感觉应该会很麻烦。这里就需要引入另一个模块openpyxl,也是一个非常强大的表格处理,网上有很多文章的介绍

首先那些是变量和不变量,2个文件肯定是不变,变量是读取表格日期,y1,y2,写入表格的sheet1,sheet2(也就是读取好多表格写入一个表格中多个sheet表),数据的存储我首先想到的就是字典,他的键值对形式可以取值非常方便

代码实现

from openpyxl import load_workbook
from xlrd import xldate_as_datetime, xldate_as_tuple
import re

class HandleExecl(object):

    def __init__(self,date,file,sheet_name,write_file):
        self.date = date # 日期
        self.file = file # 读取文件
        self.sheet_name = sheet_name #写入文件sheet名
        self.write_file = write_file # 写入文件


    def read_execl(self):
        """
        读表
        :return: list
        """
        wb = load_workbook(self.file, data_only=True) #  data_only=True计算表格公式的结果
        ws = wb.active
        row_dict = {}
        count_row = 2
        # 行判断 (构成字典,key是日期,value日期所在的行数)
        for row in ws.iter_rows(max_row=34):
            try:
                date_time = xldate_as_datetime(row[0].value,0).strftime('%m/%d').replace('/','月') + "日"
                count_row += 1
                row_dict[date_time] = count_row
            except:
                pass
        # print(row_dict)
        row_num = row_dict[self.date]
        # 列判断 (也是构成字典,key是列名y3,value是一个区间列表,表示y3在多少列到多少列)
        count_column = 1
        column_list = []
        for column in ws.iter_cols():
            if count_column > 2:
                    column_list.append(str(column[0].value) + "-" + str(count_column))
            count_column += 1
        column_list = [column_list[i:i + 16] for i in range(0, len(column_list), 16)]
        column_dict = {}
        for j in column_list:
            if len(j) == 16:
                column_dict[j[0].split('-')[0]] = [j[0].split('-')[1],j[-1].split('-')[1]]
        # 查值 (行和列都确定好了,单元格内容也能动态表示,也是构成字典,最后组成列表)
        result_list = []
        for key in column_dict:
            dicts = {
                'shop_name': key
            }
            dicts["data"] = {}
            for i in range(int(column_dict[key][0]), int(column_dict[key][1])+1):

                dicts["data"][ws.cell(2, i).value] = ws.cell(row_num, i).value
            result_list.append(dicts)

        wb.close()

        return result_list

    def read_info(self):
        """
        写入表格店名对应行数
        :return: dict
        """
        wb = load_workbook(self.write_file)
        # 判断写入文件中哪一个sheet表 (确定写入表格日期是在哪一行,构成字典,key是日期,value日期所在的行数)
        if self.sheet_name == "sheet1":
            ws = wb[self.sheet_name]
            count_row = 5
            row_dicts = {}
            for row in ws.iter_rows():
                try:
                    # 关键字判断
                    if "sheet1" in str(row[1].value) and "=" not in str(row[1].value):
                        row_dicts[row[1].value] = count_row
                        count_row += 1
                except:
                    pass
            wb.close()
            return row_dicts
        elif self.sheet_name == "sheet2":
            ws = wb[self.sheet_name]
            count_row = 5
            row_dicts = {}
            for row in ws.iter_rows():
                try:
                    if "sheet2" in str(row[1].value) and "=" not in str(row[1].value):
                        row_dicts[row[1].value] = count_row
                        count_row += 1
                except:
                    pass
            wb.close()
            return row_dicts
        elif self.sheet_name == "sheet3":
            ws = wb[self.sheet_name]
            count_row = 5
            row_dicts = {}
            for row in ws.iter_rows():
                try:
                    if "sheet3" in str(row[1].value) and "=" not in str(row[1].value):
                        row_dicts[row[1].value] = count_row
                        count_row += 1
                except:
                    pass
            wb.close()
            return row_dicts

    def write_execl(self):
        """
        写入表格
        :return:
        """
        wb = load_workbook(self.write_file)
        ws = wb[self.sheet_name]
        # 接收2个方法返回的值
        data_list = self.read_execl() 
        write_dict = self.read_info() 
        # print(data_list)
        # print(write_dict)
        # 字典的遍历,取值操作
        for i in write_dict.keys():
            shop_name = i
            row = write_dict[shop_name]
            for j in data_list:
                if shop_name == j["shop_name"]:
                    # print(shop_name,row,j["data"]["转化数"])
                    # 异常判断,可能读取表格内容为控制,一定要是float,确保它能参与表格公式的计算
                    try:
                        ws.cell(row, 6, value=float(j["data"]["转化数"]))
                        ws.cell(row, 7, value=float(j["data"]["预计实际成交笔数"]))
                        ws.cell(row, 8, value=float(j["data"]["净利润目标"]))
                        ws.cell(row, 10, value=float(j["data"]["整体花费"]))
                        ws.cell(row, 11, value=float(j["data"]["实际成交金额"]))
                        ws.cell(row, 12, value=float(j["data"]["店铺预估净利润"]))
                    except:
                        pass
        wb.save(self.write_file)
        print("完成")
    
    # 方法跟上面一样,不一一介绍了
    def read_all_data(self):
        """
        合计
        :return:
        """
        wb = load_workbook(file,data_only=True)
        ws = wb.active
        count_row = 0
        dicts = {}
        # 行判断
        for row in ws.iter_rows():
            count_row += 1
            if row[0].value == "合计":
                dicts[row[0].value] = count_row
        row_num = dicts["合计"]
        # print(row_num)
        # 列判断
        count_column = 1
        column_list = []
        for column in ws.iter_cols():
            if count_column > 2:
                column_list.append(str(column[0].value) + "-" + str(count_column))
            count_column += 1
        column_list = [column_list[i:i + 16] for i in range(0, len(column_list), 16)]
        column_dict = {}
        for j in column_list:
            if len(j) == 16:
                column_dict[j[0].split('-')[0]] = [j[0].split('-')[1], j[-1].split('-')[1]]
        # 查值
        result_list = []
        for key in column_dict:
            dicts = {
                'shop_name': key
            }
            dicts["data"] = {}
            for i in range(int(column_dict[key][0]), int(column_dict[key][1]) + 1):
                dicts["data"][ws.cell(2, i).value] = ws.cell(row_num, i).value
            result_list.append(dicts)

        wb.close()
        return result_list

    def write_all_data(self):
        """
        总计写入
        :return:
        """
        wb = load_workbook(self.write_file)
        ws = wb[self.sheet_name]
        data_list = self.read_all_data()
        write_dict = self.read_info()
        # print(data_list)
        # print(write_dict)
        for i in write_dict.keys():
            shop_name = i
            row = write_dict[shop_name]
            for j in data_list:
                if shop_name == j["shop_name"]:
                    # print(shop_name,row,j["data"]["转化数"])
                    try:
                        ws.cell(row, 15, value=float(j["data"]["转化数"]))
                        ws.cell(row, 16, value=float(j["data"]["预计实际成交笔数"]))
                        ws.cell(row, 17, value=float(j["data"]["净利润目标"]))
                        ws.cell(row, 19, value=float(j["data"]["整体花费"]))
                        ws.cell(row, 20, value=float(j["data"]["实际成交金额"]))
                        ws.cell(row, 21, value=float(j["data"]["店铺预估净利润"]))
                    except:
                        pass
        wb.save(self.write_file)
        print("完成")


    def change_date(self,date):
        """
        日期转化
        :param date:
        :return:
        """
        return xldate_as_datetime(date,0).strftime('%m/%d').replace('/','月') + "日"



if __name__ == '__main__':
    date = "12月02日"
    file = "读取文件.xlsx"
    sheet_name = "sheet1"
    write_file = "写入文件.xlsx"
    obj = HandleExecl(date,file,sheet_name,write_file)
    obj.write_execl()
    obj.write_all_data()

总结

通过这次的小需求,再一次体会了字典的方便,Python每一个模块的强大,用对往往事半功倍。上述只是我用到的方法,如有其它好的方法,一起学习交流

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值