python中使用xlrd、xlwt操作excel表格详解


Posted in Python onJanuary 29, 2015

最近遇到一个情景,就是定期生成并发送服务器使用情况报表,按照不同维度统计,涉及python对excel的操作,上网搜罗了一番,大多大同小异,而且不太能满足需求,不过经过一番对源码的"研究"(用此一词让我觉得颇有成就感)之后,基本解决了日常所需。主要记录使用过程的常见问题及解决。

python操作excel主要用到xlrd和xlwt这两个库,即xlrd是读excel,xlwt是写excel的库。可从这里下载https://pypi.python.org/pypi。下面分别记录python读和写excel.

python读excel——xlrd

这个过程有几个比较麻烦的问题,比如读取日期、读合并单元格内容。下面先看看基本的操作:

首先读一个excel文件,有两个sheet,测试用第二个sheet,sheet2内容如下:

python中使用xlrd、xlwt操作excel表格详解

python 对 excel基本的操作如下:

# -*- coding: utf-8 -*-
import xlrd
import xlwt
from datetime import date,datetime

def read_excel():
  # 打开文件
  workbook = xlrd.open_workbook(r'F:\demo.xlsx')
  # 获取所有sheet
  print workbook.sheet_names() # [u'sheet1', u'sheet2']
  sheet2_name = workbook.sheet_names()[1]

  # 根据sheet索引或者名称获取sheet内容
  sheet2 = workbook.sheet_by_index(1) # sheet索引从0开始
  sheet2 = workbook.sheet_by_name('sheet2')

  # sheet的名称,行数,列数
  print sheet2.name,sheet2.nrows,sheet2.ncols

  # 获取整行和整列的值(数组)
  rows = sheet2.row_values(3) # 获取第四行内容
  cols = sheet2.col_values(2) # 获取第三列内容
  print rows
  print cols

  # 获取单元格内容
  print sheet2.cell(1,0).value.encode('utf-8')
  print sheet2.cell_value(1,0).encode('utf-8')
  print sheet2.row(1)[0].value.encode('utf-8')
  
  # 获取单元格内容的数据类型
  print sheet2.cell(1,0).ctype

if __name__ == '__main__':
  read_excel()

运行结果如下:

python中使用xlrd、xlwt操作excel表格详解

那么问题来了,上面的运行结果中红框框中的字段明明是出生日期,可显示的确实浮点数。好的,来解决第一个问题:

1、python读取excel中单元格内容为日期的方式

python读取excel中单元格的内容返回的有5种类型,即上面例子中的ctype:

ctype : 0 empty,1 string, 2 number, 3 date, 4 boolean, 5 error

即date的ctype=3,这时需要使用xlrd的xldate_as_tuple来处理为date格式,先判断表格的ctype=3时xldate才能开始操作。现在命令行看下:

>>> sheet2.cell(2,2).ctype #1990/2/22
>>> sheet2.cell(2,1).ctype #24
>>> sheet2.cell(2,0).ctype #小胖
>>> sheet2.cell(2,4).ctype #空值(这里是合并单元格的原因)
>>> sheet2.cell(2,2).value #1990/2/22
33656.0
>>> xlrd.xldate_as_tuple(sheet2.cell_value(2,2),workbook.datemode)
(1992, 2, 22, 0, 0, 0)
>>> date_value = xlrd.xldate_as_tuple(sheet2.cell_value(2,2),workbook.datemode)
>>> date_value
(1992, 2, 22, 0, 0, 0)
>>> date(*date_value[:3])
datetime.date(1992, 2, 22)
>>> date(*date_value[:3]).strftime('%Y/%m/%d') 
'1992/02/22'

即可以做下简单处理,判断ctype是否等于3,如果等于3,则用时间格式处理:

if (sheet.cell(row,col).ctype == 3):
  date_value = xlrd.xldate_as_tuple(sheet.cell_value(rows,3),book.datemode)
  date_tmp = date(*date_value[:3]).strftime('%Y/%m/%d')

那么问题又来了,上面 sheet2.cell(2,4).ctype 返回的值是0,说明这个单元格的值是空值,明明是合并的单元格内容"好朋友",这个是我觉得这个包功能不完善的地方,如果是合并的单元格那么应该合并的单元格的内容一样,但是它只是合并的第一个单元格的有值,其它的为空。

>>> sheet2.col_values(4)
[u'\u5173\u7cfb', u'\u597d\u670b\u53cb', '', u'\u540c\u5b66', '', '', u'\u4e00\u4e2a\u4eba', '']
>>> for i in range(sheet2.nrows):
  print sheet2.col_values(4)[i]
关系
好朋友

同学


一个人

>>> sheet2.row_values(7)
[u'\u65e0\u540d', 20.0, u'\u6682\u65e0', '', '']
>>> for i in range(sheet2.ncols):
  print sheet2.row_values(7)[i]
无名
20.0
暂无


>>>

2、读取合并单元格的内容

这个是真没技巧,只能获取合并单元格的第一个cell的行列索引,才能读到值,读错了就是空值。

即合并行单元格读取行的第一个索引,合并列单元格读取列的第一个索引,如上述,读取行合并单元格"好朋友"和读取列合并单元格"暂无"只能如下方式:

>>> print sheet2.col_values(4)[1]
好朋友
>>> print sheet2.row_values(7)[2]
暂无

 >>> sheet2.merged_cells # 明明有合并的单元格,为何这里是空
 []

疑问又来了,合并单元格可能出现空值,但是表格本身的普通单元格也可能是空值,要怎么获取单元格所谓的"第一个行或列的索引"呢?

这就要先知道哪些是单元格是被合并的!

3、获取合并的单元格

读取文件的时候需要将formatting_info参数设置为True,默认是False,所以上面获取合并的单元格数组为空,

>>> workbook = xlrd.open_workbook(r'F:\demo.xlsx',formatting_info=True)
>>> sheet2 = workbook.sheet_by_name('sheet2')
>>> sheet2.merged_cells
[(7, 8, 2, 5), (1, 3, 4, 5), (3, 6, 4, 5)]

merged_cells返回的这四个参数的含义是:(row,row_range,col,col_range),其中[row,row_range)包括row,不包括row_range,col也是一样,即(1, 3, 4, 5)的含义是:第1到2行(不包括3)合并,(7, 8, 2, 5)的含义是:第2到4列合并。

利用这个,可以分别获取合并的三个单元格的内容:

>>> print sheet2.cell_value(1,4)  #(1, 3, 4, 5)
好朋友
>>> print sheet2.cell_value(3,4)  #(3, 6, 4, 5)
同学
>>> print sheet2.cell_value(7,2)  #(7, 8, 2, 5)
暂无

发现规律了没?是的,获取merge_cells返回的row和col低位的索引即可! 于是可以这样一劳永逸:

>>> merge = []
>>> for (rlow,rhigh,clow,chigh) in sheet2.merged_cells:
  merge.append([rlow,clow])
  
>>> merge
[[7, 2], [1, 4], [3, 4]]
>>> for index in merge:
  print sheet2.cell_value(index[0],index[1])
  
暂无
好朋友
同学
>>>

python写excel——xlwt

写excel的难点可能不在构造一个workbook的本身,而是填充的数据,不过这不在范围内。在写excel的操作中也有棘手的问题,比如写入合并的单元格就是比较麻烦的,另外写入还有不同的样式。这些要看源码才能研究的透。

我"构思"了如下面的sheet1,即要用xlwt实现的东西:

python中使用xlrd、xlwt操作excel表格详解

基本上看起来还算复杂,而且看起来"很正规",完全是个人杜撰。

代码如下:

'''
设置单元格样式
'''

def set_style(name,height,bold=False):
  style = xlwt.XFStyle() # 初始化样式

  font = xlwt.Font() # 为样式创建字体
  font.name = name # 'Times New Roman'
  font.bold = bold
  font.color_index = 4
  font.height = height

  # borders= xlwt.Borders()
  # borders.left= 6
  # borders.right= 6
  # borders.top= 6
  # borders.bottom= 6

  style.font = font
  # style.borders = borders

  return style


#写excel
def write_excel():
  f = xlwt.Workbook() #创建工作簿

  '''
  创建第一个sheet:
    sheet1
  '''
  sheet1 = f.add_sheet(u'sheet1',cell_overwrite_ok=True) #创建sheet
  row0 = [u'业务',u'状态',u'北京',u'上海',u'广州',u'深圳',u'状态小计',u'合计']
  column0 = [u'机票',u'船票',u'火车票',u'汽车票',u'其它']
  status = [u'预订',u'出票',u'退票',u'业务小计']

  #生成第一行
  for i in range(0,len(row0)):
    sheet1.write(0,i,row0[i],set_style('Times New Roman',220,True))

  #生成第一列和最后一列(合并4行)
  i, j = 1, 0
  while i < 4*len(column0) and j < len(column0):
    sheet1.write_merge(i,i+3,0,0,column0[j],set_style('Arial',220,True)) #第一列
    sheet1.write_merge(i,i+3,7,7) #最后一列"合计"
    i += 4
    j += 1

  sheet1.write_merge(21,21,0,1,u'合计',set_style('Times New Roman',220,True))

  #生成第二列
  i = 0
  while i < 4*len(column0):
    for j in range(0,len(status)):
      sheet1.write(j+i+1,1,status[j])
    i += 4

  f.save('demo1.xlsx') #保存文件

if __name__ == '__main__':
  #generate_workbook()
  #read_excel()
  write_excel()

需要稍作解释的就是write_merge方法:

write_merge(x, x + m, y, w + n, string, sytle)
x表示行,y表示列,m表示跨行个数,n表示跨列个数,string表示要写入的单元格内容,style表示单元格样式。其中,x,y,w,h,都是以0开始计算的。

这个和xlrd中的读合并单元格的不太一样。

如上述:sheet1.write_merge(21,21,0,1,u'合计',set_style('Times New Roman',220,True))

即在22行合并第1,2列,合并后的单元格内容为"合计",并设置了style。

 

如果需要创建多个sheet,则只要f.add_sheet即可。

如在上述write_excel函数里f.save('demo1.xlsx') 这句之前再创建一个sheet2,效果如下:

python中使用xlrd、xlwt操作excel表格详解

代码也是真真的easy的了:

'''
  创建第二个sheet:
    sheet2
  '''
  sheet2 = f.add_sheet(u'sheet2',cell_overwrite_ok=True) #创建sheet2
  row0 = [u'姓名',u'年龄',u'出生日期',u'爱好',u'关系']
  column0 = [u'小杰',u'小胖',u'小明',u'大神',u'大仙',u'小敏',u'无名']

  #生成第一行
  for i in range(0,len(row0)):
    sheet2.write(0,i,row0[i],set_style('Times New Roman',220,True))

  #生成第一列
  for i in range(0,len(column0)):
    sheet2.write(i+1,0,column0[i],set_style('Times New Roman',220))

  sheet2.write(1,2,'1991/11/11')
  sheet2.write_merge(7,7,2,4,u'暂无') #合并列单元格
  sheet2.write_merge(1,2,4,4,u'好朋友') #合并行单元格
  
  f.save('demo1.xlsx') #保存文件
Python 相关文章推荐
python网络爬虫采集联想词示例
Feb 11 Python
python实现查询苹果手机维修进度
Mar 16 Python
使用pyecharts无法import Bar的解决方案
Apr 23 Python
删除python pandas.DataFrame 的多重index实例
Jun 08 Python
Linux系统(CentOS)下python2.7.10安装
Sep 26 Python
Python中浅拷贝copy与深拷贝deepcopy的简单理解
Oct 26 Python
python实现狄克斯特拉算法
Jan 17 Python
python数据化运营的重要意义
Nov 25 Python
pytorch实现mnist分类的示例讲解
Jan 10 Python
tensorflow 环境变量设置方式
Feb 06 Python
python GUI库图形界面开发之PyQt5状态栏控件QStatusBar详细使用方法实例
Feb 28 Python
Python实现照片卡通化
Dec 06 Python
Python中实现常量(Const)功能
Jan 28 #Python
Python使用random和tertools模块解一些经典概率问题
Jan 28 #Python
Python中的异常处理学习笔记
Jan 28 #Python
Python中集合类型(set)学习小结
Jan 28 #Python
Python中使用装饰器和元编程实现结构体类实例
Jan 28 #Python
Python实现Const详解
Jan 27 #Python
python映射列表实例分析
Jan 26 #Python
You might like
解析php中获取系统信息的方法
2013/06/25 PHP
php读取mssql的ntext字段返回值为空的解决方法
2014/12/30 PHP
php实现session自定义会话处理器的方法
2015/01/27 PHP
PHP实现简易计算器功能
2020/08/28 PHP
为数据添加append,remove功能
2006/10/03 Javascript
Eclipse下jQuery文件报错出现错误提示红叉
2014/01/13 Javascript
纯js实现div内图片自适应大小(已测试,兼容火狐)
2014/06/16 Javascript
JS烟花背景效果实现方法
2015/03/03 Javascript
JavaScript表单验证开发
2016/11/23 Javascript
vue.js实现的绑定class操作示例
2018/07/06 Javascript
Node.JS枚举统计当前文件夹和子目录下所有代码文件行数
2019/08/23 Javascript
基于原生JS封装的Modal对话框插件的示例代码
2020/09/09 Javascript
一行JavaScript代码如何实现瀑布流布局
2020/12/11 Javascript
[07:39]第一届亚洲邀请赛回顾视频
2017/02/14 DOTA
[01:47]2018年度DOTA2最佳教练-完美盛典
2018/12/16 DOTA
python小技巧之批量抓取美女图片
2014/06/06 Python
Python中使用wxPython开发的一个简易笔记本程序实例
2015/02/08 Python
python实现kNN算法
2017/12/20 Python
详解Django中六个常用的自定义装饰器
2018/07/04 Python
python中csv文件的若干读写方法小结
2018/07/04 Python
如何利用Boost.Python实现Python C/C++混合编程详解
2018/11/08 Python
python3.x 生成3维随机数组实例
2019/11/28 Python
基于python3.7利用Motor来异步读写Mongodb提高效率(推荐)
2020/04/29 Python
解决python执行较大excel文件openpyxl慢问题
2020/05/15 Python
推荐10个HTML5响应式框架
2016/02/25 HTML / CSS
AmazeUI 点击元素显示全屏的实现
2020/08/25 HTML / CSS
韩国家庭购物网上商店:Nsmall
2017/05/07 全球购物
建筑工程专业毕业生自荐信
2013/10/19 职场文书
乌鸦喝水教学反思
2014/02/07 职场文书
水利公司纪检监察自我鉴定
2014/02/25 职场文书
家电业务员岗位职责
2014/03/10 职场文书
元旦文艺汇演主持词
2014/03/26 职场文书
小学中等生评语
2014/12/29 职场文书
国庆节到了,利用JS实现一个生成国庆风头像的小工具 详解实现过程
2021/10/05 Javascript
7个关于Python的经典基础案例
2021/11/07 Python
MySQL深分页问题解决思路
2022/12/24 MySQL