使用python在不改变原有excel的格式下,修改指定单元格格式

需求

有一个账单,需要生成一个副本,但是需要将交易员列隐藏,不能改变原有的格式

xlsx的文件容易实现,使用openpyxl实现

xls的文件使用xlrd+xlutil实现

参考了https://segmentfault.com/q/1010000008270267

python 复制代码
class GenCopyReport(object):
    """生成账单备份,删除交易员列
    """
    def __init__(self, filename, broker_code) -> None:
        self.filename = filename
        self.broker_code = broker_code
        self.file_type = filename.split(".")[-1]

    def remove_col(self, content, sheet_name, col_name, skiprows):
        """删除指定sheet页指定列

        :param content: 二进制文件
        :param sheet_name: sheet 页名
        :param col_name: 列名
        :param skiprows: 列名所在行
        :raises ValueError: 异常
        :return: bytes | None
        """
        # 判断文件格式是 .xls 还是 .xlsx
        if self.file_type == "xls":
            # 处理 .xls 文件
            return self.remove_col_xls(content, sheet_name, col_name, skiprows)
        elif self.file_type == "xlsx":
            # 处理 .xlsx 文件
            return self.remove_col_xlsx(content, sheet_name, col_name, skiprows)
        else:
            raise ValueError("Unsupported file format")

    def copy2(self, wb):
        w = XLWTWriter()
        process(XLRDReader(wb, 'unknown.xls'), w)
        return w.output[0][1], w.style_list
    def remove_col_xls(self, content, sheet_name, col_name, skiprows):
        """支持xls后缀的处理方法

        :param content: 二进制
        :param sheet_name: sheet页名
        :param col_name: 列名
        :param skiprows: 列名所在行号
        :return: bytes | None
        """
        # 打开 Excel 文件,保留格式信息
        workbook = open_workbook(file_contents=content, formatting_info=True, on_demand=True)

        # 选择指定的 sheet
        sheet = workbook.sheet_by_name(sheet_name)

        # 找到需要删除的列索引
        for col_idx in range(sheet.ncols):
            if sheet.cell_value(skiprows-1, col_idx) == col_name:
                trader_col = col_idx
                break
        else:
            trader_col = None

        # 如果找到了需要删除的列,则删除该列
        if trader_col is not None:
            # 创建一个可编辑的 workbook 副本,并保留原文件的格式属性
            wb, s = self.copy2(workbook)
            wbs = wb.get_sheet(sheet_name)
            # styles = s[sheet.cell_xf_index(row_idx, trader_col)]

            # 删除指定列
            for row_idx in range(sheet.nrows):
                if row_idx == skiprows-1:
                    wbs.write(row_idx, trader_col, "备注", s[sheet.cell_xf_index(row_idx, trader_col)])
                else:
                    wbs.write(row_idx, trader_col, '', s[sheet.cell_xf_index(row_idx, trader_col)])

            # 保存修改后的 Excel 文件
            output_buffer = io.BytesIO()
            wb.save(output_buffer)
            return output_buffer.getvalue()
        else:
            return None

    def remove_col_xlsx(self, content, sheet_name, col_name, skiprows):
        """支持xlsx后缀的处理方法

        :param content: 二进制
        :param sheet_name: sheet页
        :param col_name: 列名
        :param skiprows: 列名所在行
        :return: bytes | None   如果没找到指定列,则返回None
        """
        # 从文件内容打开 Excel 工作簿
        input_buffer = io.BytesIO(content)
        wb = load_workbook(filename=input_buffer)

        # 选择指定的 sheet
        ws = wb[sheet_name]

        # 找到需要删除的列索引
        for col_idx, cell in enumerate(ws[skiprows], start=1):
            if cell.value == col_name:
                break
        else:
            return None
        # 删除指定列
        for row in range(1, ws.max_row + 1):
            cell = ws.cell(row=row, column=col_idx)
            if cell.coordinate in ws.merged_cells:
                # 如果是合并单元格,则跳过
                continue
            if row == skiprows:
                cell.value = "备注"
            else:
                cell.value = ""
            # ws.cell(row=row, column=col_idx, value="")

        # 将修改后的工作簿保存到二进制 buffer 中
        output_buffer = io.BytesIO()
        wb.save(output_buffer)
        return output_buffer.getvalue()

    
相关推荐
_.Switch10 分钟前
高级Python自动化运维:容器安全与网络策略的深度解析
运维·网络·python·安全·自动化·devops
老猿讲编程16 分钟前
一个例子来说明Ada语言的实时性支持
开发语言·ada
Chrikk1 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*1 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue1 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man1 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang
测开小菜鸟1 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
萧鼎3 小时前
Python并发编程库:Asyncio的异步编程实战
开发语言·数据库·python·异步
学地理的小胖砸3 小时前
【一些关于Python的信息和帮助】
开发语言·python
疯一样的码农3 小时前
Python 继承、多态、封装、抽象
开发语言·python