浅谈Python xlwings 读取Excel文件的正确姿势


Posted in Python onFebruary 26, 2021

使用Python加载最新的Excel读取类库xlwings可以说是Excel数据处理的利器,但使用起来还是有一些注意事项,否则高大上的Python会跑的比老旧的VBA还要慢。

这里我们对比一下,用几种不同的方法,从一个Excel表格中读取一万行数据,然后计算结果,看看他们的耗时。

1. 处理要求:

一个Excel表格中包含了3万条记录,其中B,C两个列记录了某些计算值,读取前一万行记录,将这两个列的差值进行计算,然后汇总得出差的和。

文件是这个样子:Book300s.xlsx 。

浅谈Python xlwings 读取Excel文件的正确姿势

2. 处理方式有以下3种,我们对比一下耗时的大小。

处理方式 代码名称
1. 使用Python的xlwings类库,读取Excel文件,然后采用Excel的Sheet和Range的引用方式读取并计算 XLS_READ_SHEET.py
2. 直接使用Excel自带的VBA语言进行计算 VBA
3. 使用Python的xlwings类库,读取Excel文件,然后采用Python的自带数据类型List列表进行数据存储和计算 XLS_READ_LIST.py

3. 首先测试第一种,XLS_READ_SHEET.py

使用Python的xlwings类库,读取Excel文件,然后引用Excel的Sheet和Range的方式来读取并计算

#coding=utf-8
import xlwings as xw
import pandas as pd
import time

start_row = 2 # 处理Excel文件开始行
end_row = 10002 # 处理Excel结束行

#记录打开表单开始时间
start_open_time = time.time()

#指定不显示地打开Excel,读取Excel文件
app = xw.App(visible=False, add_book=False)
wb = app.books.open('D:/PYTHON/TEST_CODE/Book300s.xlsx') # 打开Excel文件
sheet = wb.sheets[0] # 选择第0个表单

#记录打开Excel表单结束时间
end_open_time = time.time()

#记录开始循环计算时间
start_run = time.time()

row_content = []
#读取Excel表单前10000行的数据,Python的in range是左闭右开的,到10002结束,但区间只包含2到10001这一万条
for row in range(start_row, end_row):
  row_str = str(row)
  #循环中引用Excel的sheet和range的对象,读取B列和C列的每一行的值,对比计算
  start_value = sheet.range('B' + row_str).value
  end_value = sheet.range('C' + row_str).value
  if start_value <= end_value:
    values = end_value - start_value
    #同时测试List数组添加记录
    row_content.append(values)

#计算和
total_values = sum(row_content)

#记录结束循环计算时间
end_run = time.time()
sheet.range('E2').value = str(total_values)
sheet.range('E3').value = '使用Sheet计算时间(秒):' + str(end_run - start_run)

#保存并关闭Excel文件
wb.save()
wb.close()

print ('结果总和:', total_values)
print ('打开并读取Excel表单时间(秒):',  end_open_time - start_open_time)
print ('计算时间(秒):',  end_run - start_run)
print ('处理数据条数:' , len(row_content))

用Python直接访问Sheet和Range取值的计算结果如下:

读取Excel文件用时 4.47秒

处理Excel 10000 行数据花费了117秒的时间。

浅谈Python xlwings 读取Excel文件的正确姿势

4. 然后我们用Excel自带的VBA语言来处理一下相同的计算。也是直接引用Sheet,Range等Excel对象,但VBA的数组功能实在是不好用,就不测试添加数组了。

Option Explicit

Sub VBA_CAL_Click()
  Dim i_count As Long
  Dim offset_value, total_offset_value As Double
  Dim st, et As Date
  st = Time()

  i_count = Sheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
  i_count = 10001
  For i_count = 2 To i_count
     If Range("C" & i_count).Value > Range("B" & i_count).Value Then
       offset_value = Range("C" & i_count).Value - Range("B" & i_count).Value
       total_offset_value = total_offset_value + offset_value
     End If
  Next i_count

  et = Time()
  Range("E2").Value = total_offset_value
  Range("E3").Value = et - st

  MsgBox "Result: " & total_offset_value & Chr(10) & "Running time: " & et - st
End Sub

VBA处理计算结果如下:

保存了3万条数据的Excel文件是通过手工打开的,在电脑上大概花费了8.2秒的时间

处理Excel 前10000行数据花费了1.16秒的时间。

浅谈Python xlwings 读取Excel文件的正确姿势

5.使用Python的xlwings类库,读取Excel文件,然后采用Python的自带数据类型List进行数据存储和计算,计算完成后再将结果写到Excel表格中

#coding=utf-8
import xlwings as xw
import pandas as pd
import time

#记录打开表单开始时间
start_open_time = time.time()

#指定不显示地打开Excel,读取Excel文件
app = xw.App(visible=False, add_book=False)
wb = app.books.open('D:/PYTHON/TEST_CODE/Book300s.xlsx') # 打开Excel文件
sheet = wb.sheets[0] # 选择第0个表单

#记录打开Excel表单结束时间
end_open_time = time.time()

#记录开始循环计算时间
start_run = time.time()

row_content = []
#读取Excel表单前10000行的数据,并计算B列和C列的差值之和
list_value = sheet.range('A2:D10001').value
for i in range(len(list_value)):
   #使用Python的类库直接访问Excel的表单是很缓慢的,不要在Python的循环中引用sheet等Excel表单的单元格,
   #而是要用List一次性读取Excel里的数据,在List内存中计算好了,然后返回结果
   start_value = list_value[i][1]
   end_value = list_value[i][2]
   if start_value <= end_value:
     values = end_value- start_value
     #同时测试List数组添加记录
     row_content.append(values)

#计算和
total_values = sum(row_content)
#记录结束循环计算时间
end_run = time.time()
sheet.range('E2').value = str(total_values)
sheet.range('E3').value = '使用List 计算时间(秒):' + str(end_run - start_run)

#保存并关闭Excel文件
wb.save()
wb.close()

print ('结果总和:', total_values)
print ('打开并读取Excel表单时间(秒):',  end_open_time - start_open_time)
print ('计算时间(秒):',  end_run - start_run)
print ('处理数据条数:' , len(row_content))

用Python的LIST在内存中计算结果如下:

读取Excel文件用时 4.02秒

处理Excel 10000 行数据花费了 0.10 秒的时间。

浅谈Python xlwings 读取Excel文件的正确姿势

6 结论:

Python操作Excel的类库有以往有 xlrd、xlwt、openpyxl、pyxll等,这些类库有的只支持读取,有的只支持写入,并且有的不支持Excel的xlsx格式等。

所以我们采用了最新的开源免费的xlwings类库,xlwings能够很方便的读写Excel文件中的数据,并支持Excel的单元格格式修改,也可以与pandas等类库集成使用。

VBA是微软Excel的原生二次开发语言,是办公和数据统计的利器,在金融,统计,管理,计算中应用非常广泛,但是VBA计算能力较差,支持的数据结构少,编辑器粗糙。

虽然VBA有很多不足,但是VBA的宿主Office Excel却是天才程序员基于C++开发的作品,稳定,高效,易用 。

有微软加持,VBA虽然数据结构少,运行速度慢,但访问自己Excel的Sheet,Range,Cell等对象却速度飞快,这就是一体化产品的优势。

VBA读取Excel的Range,Cell等操作是通过底层的API直接读取数据的,而不是通过微软统一的外部开发接口。所以Python的各种开源和商用的Excel处理类库如果和VBA来比较读写Excel格子里面的数据,都是处于劣势的(至少是不占优势的),例子2的VBA 花费了1.16秒就能处理完一万条数据。

Python基于开源,语法优美而健壮,支持面向对象开发,最重要的是,Python有丰富而功能强大的类库,支持多种工作场景的开发。

我们应该认识到,Excel对于Python而言,只是数据源文件的一种,当处理大量数据时,Python处理Excel就要把Excel当数据源来处理,一次性地读取数据到Python的数据结构中,而不是大量调用Excel里的对象,不要说频繁地写入Excel,就是频繁地读取Excel里面的某些单元格也是效率较低的。例子1的Python频繁读取Sheet,Range数据,结果花费了117秒才处理完一万条数据。

Python的计算效率和数据结构的操作方便性可比VBA强上太多,和VBA联合起来使用,各取所长是个好主意。

当Excel数据一次性读入Python的内存List数据结构中,然后基于自身的List数据结构在内存中计算,例子3的Python只用了 0.1秒就完成了一万条数据的计算并将结果写回Excel。

总结:

处理方式-计算Excel里的一万条记录的差值的总和 效率
1. 使用Python的xlwings类库,采用Excel的Sheet和Range的引用方式,按行读取Excel文件的记录并计算 差,计算用时 117秒
2. 直接使用Excel自带的VBA语言进行计算,也是采用Excel的Sheet和Range的引用方式,按行读取Excel文件的记录并计算 很高 ,计算用时 1.16秒
3. 使用Python的xlwings类库,一次性读取Excel文件中的数据到Python的List数据结构中,然后在Python的List列表中进行数据存储和计算 最高,计算用时 0.1秒     

到此这篇关于浅谈Python xlwings 读取Excel文件的正确姿势的文章就介绍到这了,更多相关Python xlwings 读取Excel内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python实现划词翻译
Apr 23 Python
Python对小数进行除法运算的正确方法示例
Aug 25 Python
Python实现网络端口转发和重定向的方法
Sep 19 Python
Python实现接受任意个数参数的函数方法
Apr 21 Python
python实现嵌套列表平铺的两种方法
Nov 08 Python
浅析python参数的知识点
Dec 10 Python
python批量识别图片指定区域文字内容
Apr 30 Python
Django项目基础配置和基本使用过程解析
Nov 25 Python
Pandas时间序列重采样(resample)方法中closed、label的作用详解
Dec 10 Python
Python实现CNN的多通道输入实例
Jan 17 Python
Python3使用xlrd、xlwt处理Excel方法数据
Feb 28 Python
python 两个一样的字符串用==结果为false问题的解决
Mar 12 Python
pycharm Tab键设置成4个空格的操作
Feb 26 #Python
解决pycharm 格式报错tabs和space不一致问题
Feb 26 #Python
pycharm 使用tab跳出正在编辑的括号(){}{}等问题
Feb 26 #Python
Python爬取网站图片并保存的实现示例
Feb 26 #Python
python中使用asyncio实现异步IO实例分析
Feb 26 #Python
浅析Python模块之间的相互引用问题
Feb 26 #Python
python实现学生通讯录管理系统
Feb 25 #Python
You might like
php去掉URL网址中带有PHPSESSID的配置方法
2014/07/08 PHP
php数组保存文本与文本反编成数组实例
2014/11/13 PHP
wamp服务器访问php非常缓慢的解决过程
2015/07/01 PHP
TP(thinkPHP)框架多层控制器和多级控制器的使用示例
2018/06/13 PHP
慎用 somefunction.prototype 分析
2009/06/02 Javascript
jquery中this的使用说明
2010/09/06 Javascript
控制input输入框中提示信息的显示和隐藏的方法
2014/02/12 Javascript
js实现图片旋转的三种方法
2014/04/10 Javascript
简述jQuery ajax的执行顺序
2016/01/05 Javascript
JavaScript事件 &quot;事件对象&quot;的注意要点
2016/01/14 Javascript
jQuery修改DOM结构_动力节点Java学院整理
2017/07/05 jQuery
分享19个JavaScript 有用的简写写法
2017/07/07 Javascript
Angular2实现组件交互的方法分析
2017/12/19 Javascript
jQuery+ajax读取json数据并按照价格排序示例
2018/03/28 jQuery
JavaScript事件对象深入详解
2018/12/30 Javascript
vue-i18n实现中英文切换的方法
2020/07/06 Javascript
使用python编写批量卸载手机中安装的android应用脚本
2014/07/21 Python
python中ConfigParse模块的用法
2014/09/29 Python
Python和C/C++交互的几种方法总结
2017/05/11 Python
Python3中的列表生成式、生成器与迭代器实例详解
2018/06/11 Python
Python 利用pydub库操作音频文件的方法
2019/01/09 Python
解决tensorboard多个events文件显示紊乱的问题
2020/02/15 Python
Python计算信息熵实例
2020/06/18 Python
python三引号如何输入
2020/07/06 Python
Python连接mysql数据库及简单增删改查操作示例代码
2020/08/03 Python
Python中使用aiohttp模拟服务器出现错误问题及解决方法
2020/10/31 Python
澳大利亚便宜隐形眼镜购买网站:QUICKLENS Australia
2018/10/06 全球购物
美国电力供应商店/电气批发商:USESI
2018/10/12 全球购物
华美博弈C/VC工程师笔试试题
2012/07/16 面试题
质量负责人任命书
2014/06/06 职场文书
研究生导师推荐信
2014/09/06 职场文书
2014年营销工作总结
2014/11/22 职场文书
红色故事汇观后感
2015/06/18 职场文书
田径运动会通讯稿
2015/07/18 职场文书
Golang 正则匹配效率详解
2021/04/25 Golang
Python3接口性能测试实例代码
2021/06/20 Python