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使用socket连接远程服务器的方法
Apr 29 Python
python对数组进行反转的方法
May 20 Python
python实现简单ftp客户端的方法
Jun 28 Python
Python教程之全局变量用法
Jun 27 Python
Python中的pack和unpack的使用
Mar 12 Python
Python扩展内置类型详解
Mar 26 Python
完美解决Pycharm无法导入包的问题 Unresolved reference
May 18 Python
python绘制立方体的方法
Jul 02 Python
python批量修改图片大小的方法
Jul 24 Python
利用pyinstaller打包exe文件的基本教程
May 02 Python
使用Python轻松完成垃圾分类(基于图像识别)
Jul 09 Python
基于python的itchat库实现微信聊天机器人(推荐)
Oct 29 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
syphon 虹吸式咖啡冲泡冲煮倒水的得与失
2021/03/03 冲泡冲煮
ThinkPHP的cookie和session冲突造成Cookie不能使用的解决方法
2014/07/01 PHP
PHP基于php_imagick_st-Q8.dll实现JPG合成GIF图片的方法
2014/07/11 PHP
用PHP写的一个冒泡排序法的函数简单实例
2016/05/26 PHP
PHP压缩图片功能的介绍
2019/03/21 PHP
var与Javascript变量隐式声明
2009/09/17 Javascript
腾讯与新浪的通过IP地址获取当前地理位置(省份)的接口
2010/07/26 Javascript
jQuery EasyUI API 中文文档 - PropertyGrid属性表格
2011/11/18 Javascript
Js 获取、判断浏览器版本信息的简单方法
2016/08/08 Javascript
微信小程序加载更多 点击查看更多
2016/11/29 Javascript
js中的面向对象入门
2017/03/06 Javascript
javascript 秒表计时器实现代码
2017/03/09 Javascript
gulp解决跨域的配置文件问题
2017/06/08 Javascript
layui 表格的属性的显示转换方法
2018/08/14 Javascript
30分钟快速实现小程序语音识别功能
2018/11/27 Javascript
JS散列表碰撞处理、开链法、HashTable散列示例
2019/02/08 Javascript
怎样使你的 JavaScript 代码简单易读(推荐)
2019/04/16 Javascript
JavaScript交换变量的常用方法小结【4种方法】
2020/05/07 Javascript
一起来了解一下JavaScript的预编译(小结)
2021/03/01 Javascript
python写的一个文本编辑器
2014/01/23 Python
python实现识别相似图片小结
2016/02/22 Python
Python实现查找最小的k个数示例【两种解法】
2019/01/08 Python
使用python实现回文数的四种方法小结
2019/11/24 Python
Pyqt5 关于流式布局和滚动条的综合使用示例代码
2020/03/24 Python
2020新版本pycharm+anaconda+opencv+pyqt环境配置学习笔记,亲测可用
2020/03/24 Python
python 使用多线程创建一个Buffer缓存器的实现思路
2020/07/02 Python
详解CSS3的图层阴影和文字阴影效果使用
2016/06/09 HTML / CSS
英国版MAC彩妆品牌:Illamasqua
2018/04/18 全球购物
告诉你怎样写创业计划书
2014/01/27 职场文书
中学教师培训制度
2014/01/31 职场文书
运动会邀请函范文
2014/02/06 职场文书
2014光棍节单身联谊活动策划书
2014/10/10 职场文书
我的长征观后感
2015/06/09 职场文书
创业计划书之零食店(进口)
2019/09/24 职场文书
看看如何用Python绘制小米新版天价logo
2021/04/20 Python
python numpy中setdiff1d的用法说明
2021/04/22 Python