iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >怎么用Python解决Excel问题
  • 487
分享到

怎么用Python解决Excel问题

2023-07-06 00:07:39 487人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

本篇内容介绍了“怎么用python解决excel问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!「问题说明」这次要处理的excel有两个s

本篇内容介绍了“怎么用python解决excel问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

「问题说明」

这次要处理的excel有两个sheet,要根据其中一个sheet的数据来计算另外一个sheet的值。造成问题的点在于,要计算值的sheet里不仅仅有数值,还有公式。我们来看一下:

怎么用Python解决Excel问题

如上图所示,这个excel一共有两个sheet:CP和DS,我们要按照一定的业务规则,根据CP中的数据计算DS对应单元格的数据。图中蓝色方框框出来的是带公式的,而其他区域是数值。

我们来看看,如果我们按照之前说的处理逻辑,把excel一次性批量读取到dataframe处理,然后再一次性批量写回去有啥问题。这部分代码如下:

import pandas as pdimport xlwings as xw #要处理的文件路径fpath = "data/DS_fORMat.xlsm" #把CP和DS两个sheet的数据分别读入pandas的dataframecp_df = pd.read_excel(fpath,sheet_name="CP",header=[0])ds_df = pd.read_excel(fpath,sheet_name="DS",header=[0,1]) #计算过程省略...... #保存结果到excel       app = xw.App(visible=False,add_book=False)ds_format_workbook = app.books.open(fpath)ds_worksheet = ds_format_workbook.sheets["DS"]ds_worksheet.range("A1").expand().options(index=False).value = ds_df ds_format_workbook.save()ds_format_workbook.close()app.quit()

如上代码存在的问题在于,pd.read_excel()方法从excel里读取数据到dataframe的时候,对于有公式的单元格,会直接读取公式计算的结果(如果没有结果则返回Nan),而我们写入excel的时候是直接把dataframe一次性批量写回的,这样之前带公式的单元格,被写回的就是计算出来的值或Nan,而丢掉了公式。

好了,问题出现了,我们该如何解决呢?这里会想到两个思路:

  • dataframe写回excel的时候,不要一次性批量写回,而是通过行和列的迭代,只写回计算的数据,有公式的单元格不动;

  • 读取excel的时候,有没有办法做到对于有公式的单元格,读取公式,而不是读取公式计算的结果;

我确实按照上面两个思路分别尝试了一下,我们一起来看一下。

「方案1」

如下代码尝试遍历dataframe然后按单元格写入对应的值,有公式的单元格不动

#根据ds_df来写excel,只写该写的单元格for row_idx,row in ds_df.iterrows():    total_capabity_val = row[('Total','Capabity')].strip()    total_capabity1_val = row[('Total','Capabity.1')].strip()    #Total和1Gb  Eqv.所在的行不写    if total_capabity_val!= 'Total' and total_capabity_val != '1Gb  Eqv.':        #给Delta和LOI赋值        if total_capabity1_val == 'LOI' or total_capabity1_val == 'Delta':            ds_worksheet.range((row_idx + 3 ,3)).value = row[('Current week','BOH')]            print(f"ds_sheet的第{row_idx + 3}行第3列被设置为{row[('Current week','BOH')]}")         #给Demand和Supply赋值        if total_capabity1_val == 'Demand' or total_capabity1_val == 'Supply':            cp_datetime_columns = cp_df.columns[53:]            for col_idx in range(4,len(ds_df.columns)):                ds_datetime = ds_df.columns.get_level_values(1)[col_idx]                ds_month = ds_df.columns.get_level_values(0)[col_idx]                if type(ds_datetime) == str and ds_datetime != 'TTL' and ds_datetime != 'Total' and (ds_datetime in cp_datetime_columns):                    ds_worksheet.range((row_idx + 3,col_idx + 1)).value = row[(f'{ds_month}',f'{ds_datetime}')]                    print(f"ds_sheet的第{row_idx + 3}行第{col_idx + 1}列被设置为{row[(f'{ds_month}',f'{ds_datetime}')]}")                 elif type(ds_datetime) == datetime.datetime and (ds_datetime in cp_datetime_columns):                    ds_worksheet.range((row_idx + 3,col_idx + 1)).value = row[(f'{ds_month}',ds_datetime)]                         print(f"ds_sheet的第{row_idx + 3}行第{col_idx + 1}列被设置为{row[(f'{ds_month}',ds_datetime)]}")

如上的代码确实解决了问题,也即有公式的单元格的公式被保留了。但是,根据我们文章开头提到的Python处理excel的忠告,这个代码是有严重性能问题的,因为它通过api频繁操作excel的单元格,导致写入非常慢,在我的老迈Mac本上一共跑了40分钟,简直不可接受,故该方案只能放弃。

「方案2」

这个方案是希望做到读取excel有公式值的单元格的时候,能保留公式值。这只能从各个Python的excel库的API来寻找有无对应的方法了。Pandas的read_excel()方法我仔细看了一下没有对应的参数可以支持。Openpyxl我倒是找到了一个API可以支持,如下:

import openpyxlds_format_workbook = openpyxl.load_workbook(fpath,data_only=False)ds_wooksheet = ds_format_workbook['DS']ds_df =  pd.DataFrame(ds_wooksheet.values)

关键是这里的data_only参数,为True则返回数据,为False的情况下可以保留公式值

本以为找到了对应解决方案正一顿窃喜,但当我看到通过openpyxl读取到dataframe中的数据结构的时候,才被破了一盆冷水。因为我的excel表的表头是比较复杂的两级的表头,表头中还存在合并和拆分单元格的情况,这样的表头被openpyxl读取到dataframe后,没有按照pandas的多级索引进行处理,而是简单的被处理成数字索引0123...

但我对dataframe的计算会依赖多级索引,因此openpyxl的这种处理方式导致我后面的计算无法处理。

openpyxl不行,再看看xlwings呢?通过对xlwings API文档的一通寻找,还真给我找到了,如下所示:

怎么用Python解决Excel问题

Range类提供了一个Property叫formula,可以获取和设置formula。

看到这个我简直如获至宝,赶紧代码操练起来。也许出于惯性,又或许是被之前按行列单元格操作excel的效率搞怕了,我直接先想到的方案还是一次性批量搞定,也即一次性读取excel所有的公式,然后再一次性写回去,所以我一开始的代码是这样的:

#使用xlwings来读取formulaapp = xw.App(visible=False,add_book=False)ds_format_workbook = app.books.open(fpath)ds_worksheet = ds_format_workbook.sheets["DS"]#先把所有公式一次性读取并保存下来formulas = ds_worksheet.used_range.formula #中间计算过程省略... #一次性把所有公式写回去ds_worksheet.used_range.formula = formulas

可是我想错了,ds_worksheet.used_range.formula让我误解只会返回excel中的有公式的单元格的公式,但其实它返回的是所有的单元格,只是对有公式的单元格保留了公式。所以,当我重新写回公式的时候,会覆盖掉我通过dataframe计算完并写入excel的其他的值。

既然这样的话,那我只能对有公式的单元格分别处理而不是一次性处理了,所以代码得这样写:

#使用xlwings来读取formulaapp = xw.App(visible=False,add_book=False)ds_format_workbook = app.books.open(fpath)ds_worksheet = ds_format_workbook.sheets["DS"] #保留excel中的formula#找到DS中Total所在的行,Total之后的行都是formularow = ds_df.loc[ds_df[('Total','Capabity')]=='Total ']total_row_index = row.index.values[0]#获取对应excel的行号(dataframe把两层表头当做索引,从数据行开始计数,而且从0开始计数。excel从表头就开始计数,而且从1开始计数)excel_total_row_idx = int(total_row_index+2)#获取excel最后一行的索引excel_last_row_idx = ds_worksheet.used_range.rows.count#保留按日期计算的各列的formulai_col_formula = ds_worksheet.range(f'I3:I{excel_total_row_idx}').formulaN_col_formula = ds_worksheet.range(f'N3:N{excel_total_row_idx}').formulaT_col_formula = ds_worksheet.range(f'T3:T{excel_total_row_idx}').formulaU_col_formula = ds_worksheet.range(f'U3:U{excel_total_row_idx}').formulaZ_col_formula = ds_worksheet.range(f'Z3:Z{excel_total_row_idx}').formulaAE_col_formula = ds_worksheet.range(f'AE3:AE{excel_total_row_idx}').formulaAK_col_formula = ds_worksheet.range(f'AK3:AK{excel_total_row_idx}').formulaAL_col_formula = ds_worksheet.range(f'AL3:AL{excel_total_row_idx}').formula#保留Total行开始一直到末尾所有行的formulatotal_to_last_formula = ds_worksheet.range(f'A{excel_total_row_idx+1}:AL{excel_last_row_idx}').formula #中间计算过程省略... #保存结果到excel                 #直接把ds_df完整赋值给excel,会导致excel原有的公式被值覆盖ds_worksheet.range("A1").expand().options(index=False).value = ds_df #用之前保留的formulas,重置公式ds_worksheet.range(f'I3:I{excel_total_row_idx}').formula = I_col_formulads_worksheet.range(f'N3:N{excel_total_row_idx}').formula = N_col_formulads_worksheet.range(f'T3:T{excel_total_row_idx}').formula = T_col_formulads_worksheet.range(f'U3:U{excel_total_row_idx}').formula = U_col_formulads_worksheet.range(f'Z3:Z{excel_total_row_idx}').formula = Z_col_formulads_worksheet.range(f'AE3:AE{excel_total_row_idx}').formula = AE_col_formulads_worksheet.range(f'AK3:AK{excel_total_row_idx}').formula = AK_col_formulads_worksheet.range(f'AL3:AL{excel_total_row_idx}').formula = AL_col_formulads_worksheet.range(f'A{excel_total_row_idx+1}:AL{excel_last_row_idx}').formula = total_to_last_formula ds_format_workbook.save()ds_format_workbook.close()app.quit()

测试,如上代码完美地解决我的需求,而且性能上也完全没问题。

“怎么用Python解决Excel问题”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: 怎么用Python解决Excel问题

本文链接: https://www.lsjlt.com/news/356622.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么用Python解决Excel问题
    本篇内容介绍了“怎么用Python解决Excel问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!「问题说明」这次要处理的excel有两个s...
    99+
    2023-07-06
  • 用Python解决Excel问题的最佳姿势
     大家好,我是毕加锁。 今天给大家带来的是用Python解决Excel问题的最佳姿势 文末送书! 文末送书! 文末送书! 「问题说明」 这次要处理的excel有两个sheet,要根据其中一个sheet的数据来计算另外一个sheet的值。造...
    99+
    2023-09-03
    pandas python excel
  • excel下拉菜单使用问题怎么解决
    本篇内容主要讲解“excel下拉菜单使用问题怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“excel下拉菜单使用问题怎么解决”吧!excel下拉菜单使用教程:首先需要打开可编辑的exce...
    99+
    2023-06-30
  • pandas怎么解决excel科学计数法问题
    这篇文章主要介绍“pandas怎么解决excel科学计数法问题”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“pandas怎么解决excel科学计数法问题”文章能帮助大家解决问题。pandas解决ex...
    99+
    2023-07-04
  • 利用Python解决Excel问题的最佳方案总结
    目录「问题说明」「方案1」「方案2」「写在最后」「问题说明」 这次要处理的excel有两个sheet,要根据其中一个sheet的数据来计算另外一个sheet的值。造成问题的点在于,要...
    99+
    2023-05-15
    python excel python处理excel
  • python的Traceback问题怎么解决
    在Python中,Traceback通常是由程序中的错误或异常引起的。要解决Traceback问题,可以尝试以下几种方法: 仔细阅...
    99+
    2024-03-08
    python
  • Python排序问题怎么解决
    本文小编为大家详细介绍“Python排序问题怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“Python排序问题怎么解决”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1.冒泡排序冒泡排序(Bubble S...
    99+
    2023-07-06
  • python未解析的引用问题怎么解决
    Python未解析的引用问题可能有多种原因,以下是一些常见的解决方法: 检查引用的模块是否已经安装:如果使用的是第三方模块,可以...
    99+
    2023-10-25
    python
  • python实现excel转置问题详解
    excel转置分为两种情况,一个是较为简单的只需要行转列,列转行 最简单的转置,利用pandas里面的转置**.T**函数 代码如下: import pandas as pd d...
    99+
    2024-04-02
  • python socket粘包问题怎么解决
    今天小编给大家分享一下python socket粘包问题怎么解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我...
    99+
    2024-04-02
  • python互斥锁问题怎么解决
    在Python中,可以使用互斥锁(Lock)来解决互斥访问问题。互斥锁是一种线程同步的机制,它可以保证在同一时刻只有一个线程能够访问...
    99+
    2023-10-23
    python
  • python商品打折问题怎么解决
    要解决Python商品打折问题,你可以采取以下步骤:1. 首先,确定商品的原始价格和折扣率。你可以使用input()函数来获取用户输...
    99+
    2023-10-20
    python
  • Django使用问题怎么解决
    本篇内容介绍了“Django使用问题怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Django R...
    99+
    2024-04-02
  • Python之string编码问题怎么解决
    这篇文章主要介绍“Python之string编码问题怎么解决”,在日常操作中,相信很多人在Python之string编码问题怎么解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python之string编码...
    99+
    2023-07-05
  • 怎么使用github解决问题
    在当今软件开发行业中,Github已经成为了解决问题的一个重要工具。Github是一个面向开源及私有软件项目的托管平台,因为其丰富的特性得到了全球开发者的广泛喜爱。在利用Github解决问题时,需要注意以下几个方面。一、Github是什么G...
    99+
    2023-10-22
  • python selenium模拟点击问题怎么解决
    这篇文章主要介绍“python selenium模拟点击问题怎么解决”,在日常操作中,相信很多人在python selenium模拟点击问题怎么解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家...
    99+
    2023-06-30
  • 怎么在python中解决n皇后问题
    这期内容当中小编将会给大家带来有关怎么在python中解决n皇后问题,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。import copydef check(A,x,y): &...
    99+
    2023-06-14
  • Python之ThreadPoolExecutor线程池问题怎么解决
    本文小编为大家详细介绍“Python之ThreadPoolExecutor线程池问题怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“Python之ThreadPoolExecutor线程池问题怎么解决”文章能帮助大家解决疑惑,下面跟...
    99+
    2023-07-05
  • Vue router应用问题怎么解决
    这篇文章主要讲解了“Vue router应用问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Vue router应用问题怎么解决”吧!问题记录路由守卫的应用根据...
    99+
    2023-06-30
  • 怎么使用Puppeteer解决SEO问题
    这篇文章主要讲解了“怎么使用Puppeteer解决SEO问题”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用Puppeteer解决SEO问题”吧!引言在前端开发中,我们经常会遇到SEO...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作