浅谈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安装与使用redis的方法
Apr 19 Python
python实现SMTP邮件发送功能
Jun 16 Python
Python遍历文件夹和读写文件的实现方法
May 10 Python
Django自定义分页效果
Jun 27 Python
python 列表递归求和、计数、求最大元素的实例
Nov 28 Python
用python脚本24小时刷浏览器的访问量方法
Dec 07 Python
python3.6 如何将list存入txt后再读出list的方法
Jul 02 Python
Python数据可视化:饼状图的实例讲解
Dec 07 Python
实现Python与STM32通信方式
Dec 18 Python
Django的ListView超详细用法(含分页paginate)
May 21 Python
Pycharm plot独立窗口显示的操作
Dec 11 Python
PYTHON 使用 Pandas 删除某列指定值所在的行
Apr 28 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
服务器端解压缩zip的脚本
2006/12/22 PHP
PHP中mysql_field_type()函数用法
2014/11/24 PHP
php实现mysql备份恢复分卷处理的方法
2014/12/26 PHP
php实现的中文分词类完整实例
2017/02/06 PHP
yii2中LinkPager增加总页数和总记录数的实例
2017/08/28 PHP
Laravel实现通过blade模板引擎渲染视图
2019/10/25 PHP
html下载本地
2006/06/19 Javascript
JavaScript对象模型-执行模型
2008/04/28 Javascript
JavaScript DOM学习第八章 表单错误提示
2010/02/19 Javascript
javascript中setTimeout使用指南
2015/07/26 Javascript
JavaScript中匿名函数的用法及优缺点详解
2016/06/01 Javascript
15位和18位身份证JS校验的简单实例
2016/07/18 Javascript
AngularJS实现单独作用域内的数据操作
2016/09/05 Javascript
微信小程序 Page()函数详解
2016/10/17 Javascript
用Vue.extend构建消息提示组件的方法实例
2017/08/08 Javascript
jQuery实现点击DIV同时点击CheckBox,并为DIV上背景色的实例
2017/12/18 jQuery
JS使用对象的defineProperty进行变量监控操作示例
2019/02/02 Javascript
javascript用defineProperty实现简单的双向绑定方法
2020/04/03 Javascript
Vue简单实现原理详解
2020/05/07 Javascript
微信小程序实现拨打电话功能的示例代码
2020/06/28 Javascript
python实现的希尔排序算法实例
2015/07/01 Python
python简单文本处理的方法
2015/07/10 Python
利用Python抓取行政区划码的方法
2016/11/28 Python
python绘制双柱形图代码实例
2017/12/14 Python
python中将字典形式的数据循环插入Excel
2018/01/16 Python
利用 PyCharm 实现本地代码和远端的实时同步功能
2020/03/23 Python
sklearn线性逻辑回归和非线性逻辑回归的实现
2020/06/09 Python
scrapy与selenium结合爬取数据(爬取动态网站)的示例代码
2020/09/28 Python
阿迪达斯印度官方商城:adidas India
2017/03/26 全球购物
俄罗斯厨房产品购物网站:COOK HOUSE
2021/03/15 全球购物
财务部岗位职责
2013/11/19 职场文书
高中军训感言400字
2014/02/24 职场文书
爱祖国演讲稿
2014/05/04 职场文书
中学生爱国演讲稿
2014/09/05 职场文书
三好学生主要事迹怎么写
2015/11/03 职场文书
个人自我鉴定怎么写?
2019/07/01 职场文书