python excel复制数据保留单元格格式(.xls.xlsx)

news2024/11/25 19:23:12

最近帮朋友开发一个数据excel根据条件动态过率的功能.读取生成用pandas很方便,但是这里有一点比较麻烦的是得保留原来的单元格格式.这点操作起来就要麻烦一点了.下面总结了.xlsx和.xls处理

在这里插入图片描述

1.xlsx 文件处理

xlsx文件处理可以使用openpyxl库进行处理,比较简单,流程如下

1.获取原来的数据cell

2.进行value和style复制

import openpyxl
import copy
# 复制excel 保留格式
# file_path : 原文件地址
# out_file_path : 输出文件地址
# ids : 条件
def copy_xlsx(file_path,out_file_path,ids):
    # 打开原表
    workbook = openpyxl.load_workbook(file_path, data_only=True)
    # 获取第一个sheet表
    sheet = workbook.sheet_by_index(0)

    # 创建一个新的 Excel 文件
    new_workbook = openpyxl.Workbook()
    new_sheet = new_workbook.active  # 选择新工作表
    # 复制数据和样式
    i = 1  # openpyxl 行号从1开始
    for row in sheet.iter_rows():
        # todo 这里条件按需添加,可以去掉
        if i ==1 or row[0].value in ids:
            # 复制行
            for source_cell in row:
                target_cell = new_sheet.cell(row=i, column=source_cell.column,value = source_cell.value)
                # 复制样式
                if source_cell.has_style:
                    # 设置样式 得用 copy.copy() 不然会报错
                    target_cell._style = copy.copy(source_cell._style)
                    target_cell.font = copy.copy(source_cell.font)
                    target_cell.border = copy.copy(source_cell.border)
                    target_cell.fill = copy.copy(source_cell.fill)
                    target_cell.number_format = copy.copy(source_cell.number_format)
                    target_cell.protection = copy.copy(source_cell.protection)
                    target_cell.alignment = copy.copy(source_cell.alignment)
            i += 1

    # 保存新的 Excel 文件
    new_workbook.save(out_file_path)

2. xls 文件处理

xls文件处理起来麻烦点,

首先得引入xlrd 只能进行读取,xlwt负责写入,xlutils相当中间人,可以简化很多操作

import xlrd
import xlwt
from xlutils.filter import process, XLRDReader, XLWTWriter

1.xlrd 获取workbook_rb, formatting_info=True 这个一定要加才能获取到格式,formatting_info模式是false是不获取格式.

2.通过 xlutils 获取到所有单元格格式

3.通过 xlwt 的 worksheet.write(i, col_num, cell.value,style) 写入value 及 style

import xlrd
import xlwt
from xlutils.filter import process, XLRDReader, XLWTWriter

# 创建 xls 
def create_xls(savePath:str,ids):
    
    # 创建一个新的 Excel 文件(写入模式)
    workbook_rb = xlrd.open_workbook(path.get(),formatting_info=True)  # 打开工作簿
    # 这里是关键,获取所有样式列表
    w = XLWTWriter()
    process(XLRDReader(workbook_rb, 'unknown.xls'), w)
    style_list = w.style_list
    
    sheet = sheet = workbook.sheet_by_index(0)

    new_workbook = xlwt.Workbook(encoding='utf-8')
    new_worksheet = new_workbook.add_sheet('sheet1')  # 添加一个新工作表,替换为你的工作表名称
	
    # xlrd 的 index 从0开始
    i=0
    for row_num, row in enumerate(sheet.get_rows(), start=0):
        if i ==0 or row[0].value in ids:
            for col_num, cell in enumerate(row, start=0):
                # 复制格式
                style = style_list[cell.xf_index]
                #获取当前单元格的style
                new_worksheet.write(i, col_num, cell.value,style)
            i+=1  
                
    new_workbook.save(savePath)
    return savePath

经过测试,上述代码是可以的,但是有个小问题

w = XLWTWriter()
process(XLRDReader(workbook_rb, 'unknown.xls'), w)
style_list = w.style_list

这段代码我就想获取到style_list 但的东西有点多,这里其实是复制了一个新的workbook对象.新对象里面有原始workbook的所有信息.

在这里插入图片描述
可以看到它包含的 原始 xlrd.book信息 ,xlwt.worksheet 信息(他已经将xlrd.book原始信息进行复制),style_list信息.

这个如果只是对于我们想获取style_list,那么这里信息有点太多.

因此我们能不能只获取style_list呢,我们通过XLWTWriter源码查询下style_list是如何获取的.看下能不能一探究竟.

通过过w.style_list进入源码查看,我们发现在xlutils.filter.BaseWriter.workbook 进行了定义.
在这里插入图片描述
接着我们找下style_list是如何进行赋值的,查询下发现如下代码self.style_list.append(wtxf),这个就是赋值代码.
在这里插入图片描述
让我们看下它是如何实现的,核心代码就是下面这个,大致流程就是

1.创建一个 xlwt.Style.XFStyle() 对象 wtxf

2.从rdbook中获取到格式信息 rdbook.xf_list

3.对 wtxf 进行各种赋值

		if not rdbook.formatting_info:
            return
        for rdxf in rdbook.xf_list:
            wtxf = xlwt.Style.XFStyle()
            #
            # number format
            #
            wtxf.num_format_str = rdbook.format_map[rdxf.format_key].format_str
            #
            # font
            #
            wtf = wtxf.font
            rdf = rdbook.font_list[rdxf.font_index]
            wtf.height = rdf.height
            wtf.italic = rdf.italic
            wtf.struck_out = rdf.struck_out
            wtf.outline = rdf.outline
            wtf.shadow = rdf.outline
            wtf.colour_index = rdf.colour_index
            wtf.bold = rdf.bold #### This attribute is redundant, should be driven by weight
            wtf._weight = rdf.weight #### Why "private"?
            wtf.escapement = rdf.escapement
            wtf.underline = rdf.underline_type #### 
            # wtf.???? = rdf.underline #### redundant attribute, set on the fly when writing
            wtf.family = rdf.family
            wtf.charset = rdf.character_set
            wtf.name = rdf.name
            # 
            # protection
            #
            wtp = wtxf.protection
            rdp = rdxf.protection
            wtp.cell_locked = rdp.cell_locked
            wtp.formula_hidden = rdp.formula_hidden
            #
            # border(s) (rename ????)
            #
            wtb = wtxf.borders
            rdb = rdxf.border
            wtb.left   = rdb.left_line_style
            wtb.right  = rdb.right_line_style
            wtb.top    = rdb.top_line_style
            wtb.bottom = rdb.bottom_line_style 
            wtb.diag   = rdb.diag_line_style
            wtb.left_colour   = rdb.left_colour_index 
            wtb.right_colour  = rdb.right_colour_index 
            wtb.top_colour    = rdb.top_colour_index
            wtb.bottom_colour = rdb.bottom_colour_index 
            wtb.diag_colour   = rdb.diag_colour_index 
            wtb.need_diag1 = rdb.diag_down
            wtb.need_diag2 = rdb.diag_up
            #
            # background / pattern (rename???)
            #
            wtpat = wtxf.pattern
            rdbg = rdxf.background
            wtpat.pattern = rdbg.fill_pattern
            wtpat.pattern_fore_colour = rdbg.pattern_colour_index
            wtpat.pattern_back_colour = rdbg.background_colour_index
            #
            # alignment
            #
            wta = wtxf.alignment
            rda = rdxf.alignment
            wta.horz = rda.hor_align
            wta.vert = rda.vert_align
            wta.dire = rda.text_direction
            # wta.orie # orientation doesn't occur in BIFF8! Superceded by rotation ("rota").
            wta.rota = rda.rotation
            wta.wrap = rda.text_wrapped
            wta.shri = rda.shrink_to_fit
            wta.inde = rda.indent_level
            # wta.merg = ????
            #
            self.style_list.append(wtxf)

拿到这个代码后就简单了,我们就是照着封装一下,就是使用了.这样我们只要能够获取到rdbook (也就是xlrd获取到的book),就是获取到style_list了.无需获取到其他我们不关注的信息.

这样代码就是可以简单搞成这样,效率会提高不少,只需引入xlrd,xlwt

import xlrd
import xlwt
# 获取到表的所有单元格格式
def get_style_list(rdbook:xlrd.Book):
    style_list=[]
    if not rdbook.formatting_info:
        return
    for rdxf in rdbook.xf_list:
        wtxf = xlwt.Style.XFStyle()
        #
        # number format
        #
        wtxf.num_format_str = rdbook.format_map[rdxf.format_key].format_str
        #
        # font
        #
        wtf = wtxf.font
        rdf = rdbook.font_list[rdxf.font_index]
        wtf.height = rdf.height
        wtf.italic = rdf.italic
        wtf.struck_out = rdf.struck_out
        wtf.outline = rdf.outline
        wtf.shadow = rdf.outline
        wtf.colour_index = rdf.colour_index
        wtf.bold = rdf.bold  # This attribute is redundant, should be driven by weight
        wtf._weight = rdf.weight  # Why "private"?
        wtf.escapement = rdf.escapement
        wtf.underline = rdf.underline_type
        # wtf.???? = rdf.underline #### redundant attribute, set on the fly when writing
        wtf.family = rdf.family
        wtf.charset = rdf.character_set
        wtf.name = rdf.name
        #
        # protection
        #
        wtp = wtxf.protection
        rdp = rdxf.protection
        wtp.cell_locked = rdp.cell_locked
        wtp.formula_hidden = rdp.formula_hidden
        #
        # border(s) (rename ????)
        #
        wtb = wtxf.borders
        rdb = rdxf.border
        wtb.left = rdb.left_line_style
        wtb.right = rdb.right_line_style
        wtb.top = rdb.top_line_style
        wtb.bottom = rdb.bottom_line_style
        wtb.diag = rdb.diag_line_style
        wtb.left_colour = rdb.left_colour_index
        wtb.right_colour = rdb.right_colour_index
        wtb.top_colour = rdb.top_colour_index
        wtb.bottom_colour = rdb.bottom_colour_index
        wtb.diag_colour = rdb.diag_colour_index
        wtb.need_diag1 = rdb.diag_down
        wtb.need_diag2 = rdb.diag_up
        #
        # background / pattern (rename???)
        #
        wtpat = wtxf.pattern
        rdbg = rdxf.background
        wtpat.pattern = rdbg.fill_pattern
        wtpat.pattern_fore_colour = rdbg.pattern_colour_index
        wtpat.pattern_back_colour = rdbg.background_colour_index
        #
        # alignment
        #
        wta = wtxf.alignment
        rda = rdxf.alignment
        wta.horz = rda.hor_align
        wta.vert = rda.vert_align
        wta.dire = rda.text_direction
        # wta.orie # orientation doesn't occur in BIFF8! Superceded by rotation ("rota").
        wta.rota = rda.rotation
        wta.wrap = rda.text_wrapped
        wta.shri = rda.shrink_to_fit
        wta.inde = rda.indent_level
        # wta.merg = ????
        #
        style_list.append(wtxf)
        return style_list


# 创建 xls
def copy_xls(file_path:str, savePath: str, ids):

    # 创建一个新的 Excel 文件(写入模式)
    workbook_rb = xlrd.open_workbook(file_path, formatting_info=True)  # 打开工作簿
    # 这里是关键,获取所有样式列表
    style_list = get_style_list(workbook_rb)
	# 获取第一个sheet
    sheet = sheet = workbook_rb.sheet_by_index(0)

    new_workbook = xlwt.Workbook(encoding='utf-8')
    new_worksheet = new_workbook.add_sheet('sheet1')  # 添加一个新工作表,替换为你的工作表名称

    # xlrd 的 index 从0开始
    i = 0
    for row in sheet.get_rows():
        # todo 这里条件按需添加,可以去掉
        if i == 0 or row[0].value in ids:
            for col_num, cell in enumerate(row, start=0):
                # 复制格式
                style = style_list[cell.xf_index]
                # 获取当前单元格的style
                new_worksheet.write(i, col_num, cell.value, style)
            i += 1

    new_workbook.save(savePath)
    return savePath

参考:

https://www.cnblogs.com/KeenLeung/p/14101049.html

https://blog.csdn.net/weixin_39804265/article/details/105127786

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1023982.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

接入网络技术

接入网络:是实现网络边缘的端系统与网络核心连接与接入的网络。 常见有以下几类: 1、电话拨号接入:这类接入方式在早期接入网络中主要用于家庭接入,利用了电话网络覆盖广泛的优点,能够方便地实现分散的家庭用户接入网…

指针笔试题讲解(让指针变得简单易懂)

数组名的理解 : 数组名就是首元素地址 但是有两个例外: 1. sizeof(数组名)这里的数组名表示整个数组的大小,sizeof(数组名)计算的是整个数组的大小,单位是字节 2. &数组名 这里的数组…

MouseBoost 3.2.3 Pro右键助手 for Mac

MouseBoost Mac 右键助手是一款专为 Mac 平台开发的鼠标增强工具, 其主要特点如下: 1. 可自定义菜单:MouseBoost Mac 右键助手允许用户自定义右键菜单,可以添加或删除菜单项,以适应不同用户的需求。 2. 多种快捷操作&a…

蓝桥杯 题库 简单 每日十题 day5

01 字符计数 #include<stdio.h> int main() { char c; int i,j0,k0; while((cgetchar())!\n){if(ca||ce||ci||cu||co)j;else k;} printf("%d\n%d",j,k); return 0; }02 棋盘 #include<iostream> using namespace std; const int N 2010; int n,m; int …

C++const关键字

本文旨在讲解C中相关const关键字的详解&#xff0c;希望读完本篇文章&#xff0c;可以让诸位对C中的const关键字有更深一步的认识&#xff01; 在C中&#xff0c;若想让类中某一个变量不再改变&#xff0c;可以使用const关键字进行修饰&#xff0c;让数据不被修改&#xff0c;使…

【AI视野·今日Robot 机器人论文速览 第三十六期】Tue, 19 Sep 2023

AI视野今日CS.Robotics 机器人学论文速览 Tue, 19 Sep 2023 (showing first 100 of 112 entries) Totally 112 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers General In-Hand Object Rotation with Vision and Touch Authors Haozhi Qi, Brent Yi…

element-ui问题合集(el-input-number加减一次就失效,el-select同时收集id与name)

el-select同时收集id与name 将id与name拼接成字符串&#xff0c;赋值给value&#xff0c;在使用时&#xff0c;获取value后&#xff0c;再使用split()方法进行分割 <el-select><el-option v-for"item in selectAttr" :label"item.name" :value&…

【深度学习-第3篇】使用MATLAB快速实现CNN分类(模式识别)任务,含一维、二维、三维数据演示案例

在本文中&#xff0c;我们将介绍如何使用 MATLAB 中的 Convolutional Neural Network&#xff08;CNN&#xff09;进行分类任务。我们将使用 MATLAB 的 Deep Learning Toolbox 来创建、训练和评估 CNN。 一、一个简单的案例 1 安装和准备 首先&#xff0c;确保已安装 MATLAB…

chat-gpt笔记:参数temperature与top_p

temperature 官方文档 temperature number or null Optional Defaults to 1 What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We…

Apache Hive 入门

目录 一、Apache Hive概述 1.1 什么是Hive ​1.2 为什么使用 Hive 1.3 Hive 和 Hadoop 关系 二、场景设计&#xff1a;如何模拟实现Hive功能 2.1 如何模拟实现 Apache Hive 的功能 2.2 映射信息记录 2.3 SQL 语法解析、编译 2.4 最终效果 ​三、Apache Hive 架…

【链表】K 个一组翻转链表-力扣 25 题

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

【前端知识】Three 学习日志(九)—— 阵列立方体和相机适配体验

Three 学习日志&#xff08;九&#xff09;—— 阵列立方体和相机适配体验 一、双层for循环创建阵列模型 //创建一个长方体几何对象Geometry const geometry new THREE.BoxGeometry(100, 100, 100); //材质对象Material const material new THREE.MeshLambertMaterial({col…

卷运维不如卷网络安全

最近发现很多从事运维的选择了辞职&#xff0c;重新规划自己的职业发展方向。运维工程师这个岗位在IT行业里面确实是处于最底层的&#xff0c;不管什么环节出现问题&#xff0c;基本都是运维背锅。背锅也就罢了&#xff0c;薪资水平也比不上别的岗位。 一般运维的薪资水平大多数…

【Spark】win10配置IDEA、saprk、hadoop和scala

终于&#xff0c;要对并行计算下手了哈哈哈。 一直讲大数据大数据&#xff0c;我单次数据处理量大概在1t上下&#xff0c;是过亿级的轨迹数据。 用python调用multiprogress编写的代码&#xff0c;用多线程也要一个多月跑完。 我对这个效率不太满意&#xff0c;希望能快一点再快…

Mac cocoapod 3分钟安装教程( 国内镜像源方法)

参考链接&#xff1a;2023最新总结&#xff0c;Mac下使用Homebrew完全指南&#xff01; - 知乎 1.打开终端&#xff0c; 执行&#xff1a; /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" 2.运行&#xff0c;可以选择清…

十、性能测试之数据库测试

性能测试之数据库测试 一、 数据库分类二、 mysql安装及密码的修改1、安装&#xff1a;数据库的版本 mysql5.7版方法1&#xff1a;直接安装方法2&#xff1a;使用rpm包安装方法3&#xff1a;docker方式安装 2、修改数据库的密码3、创建库4、创建表 三、存储引擎1、InnoDB特点 2…

【Java 基础篇】Java字节打印流详解:处理二进制数据的利器

当你需要将数据输出到文件或其他输出目标时&#xff0c;Java中的字节打印流是一个非常有用的工具。本文将详细介绍Java字节打印流&#xff0c;包括它的基本用法、常用方法以及一些实际应用示例。 什么是字节打印流&#xff1f; 在Java中&#xff0c;字节打印流是用于将字节数…

【MATLAB】安装 shared_slreportgen_reportexplorer_common 时检测到以下错误

解决方法 下载matlab的时候以及安装的时候关闭杀毒软件。 然后也可以把simulink和DSP以及signal processing 相关的toolbox全部不勾选&#xff08;推荐&#xff09; 这两个工具箱没有其实没啥大的影响&#xff0c;就是信号处理这块的增强功能没有了 &#xff08;来自&#xff…

【Windows】你所使用的用户账户没有启用此任务的权限

【Windows】你所使用的用户账户没有启用此任务的权限 1. 故障现象 有一台腾讯云的服务器更新补丁,更新后需要禁用自动重启.发生了以下报错 2. 解决方法 2.1 下载pstools 工具下载地址 https://learn.microsoft.com/zh-cn/sysinternals/downloads/pstools 将软件复制到桌…

理解MTU VLAN与端口VLAN两个概念

什么是MTU VLAN MTU VLAN 是指将最大传输单元&#xff08;Maximum Transmission Unit&#xff0c;MTU&#xff09;设置为特定值以适应 VLAN 环境的配置。 MTU 是指在网络通信中可以传输的最大数据包大小。以太网的常见 MTU 值为1500字节&#xff0c;这是指在以太网帧中的数据…