Python Excel解析

版权声明:本文为博主原创文章,可以转载,但得注明出处。更多精彩文章请关注微信公众号:gloryroadtrain https://blog.csdn.net/SeeTheWorld518/article/details/49536599

Python解析Excel时需要安装两个包,分别是xlrd(读excel)和xlwt(写excel),安装方法如下:

pip install xlrd
pip install xlwt

读取Excel表

读取excel前需要先引入该模块(import xlrd)。但是需要注意的是,用xlrd读取excel表时,返回的xlrd.Book类型,是只读的,不能对其进行操作。

下面介绍一下读取Excel的流程及使用的一些函数:

1、打开Excel文件并读取数据

xlrd.open_workbook(filename)

filename是要读取的excel表名,当然要加上表所在目录的路径。
如:

data = xlrd.open_workbook('c:\\t2.xls')

查看一下data类型:

>>> type(data)
<class 'xlrd.book.Book'>

可见data是xlrd.book.Book类的一个实例。

2、获取一个工作表(sheet)

获取一个工作表的方法有三种,分别为:
(1)通过索引顺序获取

table = data.sheets()[index_number]

index_number表示表的索引号,索引号从0开始,表示第一张表,1表示第二张表,依次类似。
查看一下data.sheets这个方法的原型:

>>> help(data.sheets)
sheets(self) method of xlrd.book.Book instance
    ##
    # @return A list of all sheets in the book.
    # All sheets not already loaded will be loaded.

这个方法的作用是,将excel中所有表存于list中并返回。

(2)通过索引顺序获取

table = data.sheet_by_index(index_number)

index_number表示表的索引号,索引号从0开始,表示第一张表,1表示第二张表,依次类似。
函数原型:

sheet_by_index(self, sheetx) method of xlrd.book.Book instance
    ##
    # @param sheetx Sheet index in range(nsheets)
    # @return An object of the Sheet class

(3)通过名称获取

table = data.sheet_by_name(sheet_name)

sheet_name表示工作表的名字,但是需要注意的是这个表明的字符串需要使用Unicode的字符串,如:

table = data.sheet_by_name(u'Sheet1')

函数原型:

sheet_by_name(self, sheet_name) method of xlrd.book.Book instance
    ##
    # @param sheet_name Name of sheet required
    # @return An object of the Sheet class

3、获取整行和整列的值

返回一行:

table.row_values(row_index)

row_index表示行索引号,0表示第一行,1表示第二行,以此类推。返回的结果是row_index 行组成的list。

返回一列:

table.col_values(col_index)

col_index表示行索引号,0表示第一列,1表示第二列,以此类推。返回的结果是col_index 行组成的list。

4、获取表的行数和列数
获取行数和列数都是固定语法:

table.nrows #获取行数
table.ncols  #获取列数

5、获取单元格中的值
语法:

table.cell(row_index, col_index).value

row_index:表示表的行索引号。
col_index:表示表的列索引号。

创建Excel表

Python中使用的是xlwt模块来生成Excel文件,并且可以控制单元格的格式。xlwt.Workbook()返回的xlwt.Workbook类型的save(filepath)方法可以保存excel文件。下面就让我们看看写excel文件的流程及需要使用的函数吧。
写excel前也必须先导入该模块(import xlwt)。流程如下:

1、创建工作表(workbook)

创建workbook,其实就是创建excel,写完数据后,保存就ok了。
语法:

workbook = xlwt.Workbook(encoding = 'ascii')

查看一下workbook类型:

>>> type(workbook)
<class 'xlwt.Workbook.Workbook'>

可见workbook是xlwt.Workbook类的一个实例。

2、创建表

worksheet = Workbook.add_sheet(sheet_name)

如:

worksheet = Workbook.add_sheet('note')

3、往单元格中写内容

worksheet.write(r, c, label='', style=<xlwt.Style.XFStyle object>)

参数说明:
r :表示行索引号,从0开始。
c :表示列索引号,从0开始。
label :表示要写的内容。

4、保存excel表
语法:

workbook.save(Excel_name)

Excel_name表示保存为什么名,当然可以保存在具体的目录下。如:

workbook.save('c:\\Excel_Test.xls')

修改Excel

上面我们介绍了读和写excel,前两种都是不能修改excel的,但是在实际的工作中,经常会遇到修改已经存在的Excel文件这种需求,通常我们能想到的办法,就是先打开这个excel,然后将内容读入到内存,进行处理,然后写到一个新的同名excel文件中,最后直接用修改后的excel文件覆盖了老的excel文件即可。值得我们高兴的是,python已经帮我们实现了这么一个功能模块,那就是模块xlutils,这个模块依赖于xlrd和xlwt模块,它提供了复制excel文件内容和修改文件内容的功能。其实也就是在xlrd.Book和xlwt.Workbook之间建立了一个管道来实现修改功能。实现流程如下图所示:

4

引入模块
引入模块时,需要同时引入读模块和修改模块,如下:

import xlrd
from xlutils.copy import copy

打开excel开始将内容读到内存中:

readbook = xlrd.open_workbook('c:\\t2.xls')

使用xlutils.copy模块的copy()方法将原excel另外拷贝一份,准备修改操作:

copyBook = copy(readbook)

接下来就是从readBook中(也就是原excel中,注意这里读取数据的时候必须从原excel中读取)取得要修改的工作表,然后使用copybook取到相同工作表,使用进行修改操作,最后把修改的内容保存到

读取到要修改的工作表,如:

readSheet = readBook.sheet_by_index(0)

注意:
上面这种读sheet的方法是xlrd模块中的方法,它是没有write()方法,所以是不能写的。
然后将要修改的sheet或整个excel文档拷贝一份:

copyBook = copy(readbook) #拷贝整个excel
copyBook = copy(readSheet) #拷贝第一张表,然后拿到要修改的表
writeSheet = copybook.get_sheet(0)

上面的通过get_sheet()获取的sheet是有write()方法,所以能写。
然后进行修改操作,如:

writeSheet.write(1,0,'asd')#修改表一种的第二行第一个单元格内容

当然,上面的实例只是一个简单的写操作,我们还可做一些更复杂的写操作,修改完数据以后,将新的excel表保存并覆盖旧的excel表即可,这就实现了对excel修改的操作需求。

copybook.save('c:\\t2.xls')

注意:
读必须从原表中读取,写必须写入拷贝的表中。
下面是一个修改已存在excel的实例:修改t2.xls,并将里面小写字母变成大写字母

import xlrd
from xlutils.copy import copy

#打开excel文档并将内容读取到内存
readbook = xlrd.open_workbook('c:\\t2.xls')
#将excel内容拷贝一份
copybook = copy(readbook)

for i in range(len(readbook.sheets())) :
  '''
  遍历excel文档中的每个工作表,进行下面的处理
  '''
  #获得拷贝excel中的表i
  sheet = copybook.get_sheet(i)
  #获取原excel文档中的表i
  readSheet = readbook.sheet_by_index(i)

  for row in range(readSheet.nrows) :
    '''
    对表i中的单元格数据做如下处理
    '''
    for col in range(readSheet.ncols) :
      cell = readSheet.cell(row, col).value
      print "type is :", type(cell),cell
      if type(cell) in (str, unicode) :
        '''
        判断一下读取出来的单元格数据格式,
        如果为str和unicode的字符串,就调用字符串的upper函数,
        将小写改成大写。 
        '''
        res = cell.upper()#把小些改大写
        sheet.write(row, col, res)#将修改的内容写入拷贝的excel中
      #sheet.write(row, col, '中文'.decode('GBK'))
#将拷贝的excel保存并覆盖原来的excel文件
copybook.save('c:\\wcx\\t2.xls')

编码问题

借助上面的例子,我们来讨论一下Python中编码的问题。
在介绍编码前,先介绍一下Python中判断字符编码的一些函数:

方法一:
isinstance()函数,如:

s = 'ad'
isinstance(s, unicode) #判断s是否是Unicode字符串

方法二:

print type(s).__name__ #看看字符串s是普通字符串还是Unicode字符串

方法三:
使用chardet模块进行字符编码判断。

#安装chardet模块
pip install chardet
#导入该模块
import chardet
>>> t
'sdf'
>>> type(t)
<type 'str'>
>>> chardet.detect(t)
{'confidence': 1.0, 'encoding': 'ascii'}

Python中的字符串类型有两种,一种是str类型,一种是Unicode类型。除了Unicode类型的字符串外,其他编码的字符串都是str类型的。例:

>>> s = u'中国'
>>> type(s)
<type 'unicode'>
>>> t = "sdf"
>>> type(t)
<type 'str'>

看下面这个例子:

>>> s = u'中国'
>>> type(s)
<type 'unicode'>
>>> str(s)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

为什么会报错呢?
首先我们查看一下我们系统默认编码:

>>> import sys
>>> sys.getdefaultencoding()#查看系统默认编码
'ascii'

从结果可以看出,系统默认编码时ASCII码,ASCII码编码中一个字符只占一个字节,而Unicode编码中一个字符占2个字节(因为要表示中文汉字)。
当调用str()函数将一个Unicode字符串转str类型时,如果我们没有指定编码,就会采用系统默认编码(ascii)对Unicode字符进行编码,但是ascii码和Unicode编码的字符所占字节数不一致,那些非ascii编码的字符就不能被转化,这就是为什么会报UnicodeEncodeError这个错。

那到底str和Unicode之间怎么转呢?
这就需要用到Python提供的解码(decode)和编码(encode)函数了,其实str是Unicode字符串编码(encode)后的字符串,相反的Unicode就是str解码(decode)后的字符串,这样str和Unicode之间转换起来就简单了。如:

>>> s = u'中国'
>>> type(s)
<type 'unicode'>
>>> g = s.encode('gbk')
>>> type(g)
<type 'str'>
>>> u = s.encode('utf-8')
>>> type(u)
<type 'str'>
>>> str(g)
'\xd6\xd0\xb9\xfa'
>>> str(u)
'\xe4\xb8\xad\xe5\x9b\xbd'
>>> t = "asdf"
>>> c = t.decode('ascii')
>>> type(c)
<type 'unicode'>

不过我们还有另一个种处理办法:
那就是将系统默认缺省编码改成utf-8,如下:

>>> import sys 
>>> reload sys
>>> sys.setdefaultencoding('utf-8')

utf-8是一种针对Unicode的可变长度字符编码,它用1到6个字节编码Unicode字符,所以显示中文。将系统默认编码设置为utf-8后,就可以直接使用str()函数直接转化Unicode字符了,不用再使用编码解码函数了。如:

>>> s = u"表单"
>>> str(s)
'\xe8\xa1\xa8\xe5\x8d\x95'

网络上传的json、excel、字节流等数据串都被转化成Unicode字符,这样更通用。所以我们从excel中读取出来的数据只要是字符类型的都会被转成Unicode字符(通常需要判断一下),而我们程序中通常都用的是utf-8,所以需要将Unicode转化成uft-8后再处理这些字符,处理完后,再转成Unicode的通过网络传回去,这样保持传回去的字符集和获得的字符集编码一样,就会不出现乱码。

在上面修改excel实例程序中,写了这么一句,虽然被注释了:

sheet.write(row, col, '中文'.decode('GBK'))

这句的目的是,让写入excel中的中文不出现乱码,这里设计到一个内码的概念。

什么叫内码呢?
内码是指计算机汉字系统中使用的二进制字符编码,是沟通输入、输出与系统平台之间的交换码,通过内码可以达到通用和高效率传输文本的目的。
而win默认gbk作为系统内部编码,所以要想显示正确的中文,就需要将GBK解码成Unicode,然后传输给excel。

猜你喜欢

转载自blog.csdn.net/SeeTheWorld518/article/details/49536599