前面的文章《Python Pandas库批量处理Excel数据》简单介绍了利用Python的pandas库对大量的Excel文件进行合并,数据清洗等操作;pandas非常适合对大数据量的数据进行清洗和合并。但是在实际的工作中,除了像前文介绍那样对数据进行合并清洗外,还涉及其他的Excel表格数据的处理,这些数据的处理相对来说比较繁琐。

我们GIS行业涉及非常多的外业数据调查相关的工作,这些类似的项目都是需要根据外业调查获取到的信息填写到内业的表格中。根据外业调查表,按照一定规则更新对应的内业表信息,逻辑非常简单,只要会操作电脑的人通过简单培训就能进行这些内业数据录入,门槛很低;但是使用人工操作Office的方式进行,这些小项目的经费根本无法支付人力操作的成本,而且人工操作进行这些枯燥乏味的数据录入工作,数据录入质量很难保证,而且后面的质量检查也很麻烦。

这种枯燥乏味单一的工作交给程序来处理就会比较简单,而且成本低,数据处理效率高,更重要的是数据录入质量有保证。根据之前参与过的GIS数据调查项目数据录入程序的开发工作,整理一下python3中可以用于处理Excel文件的常用库,这些库的简单对比如下:

xlrd/xlwt:Python2和3都支持的库;xlrd库可以读取xls和xlsx;xlwt库只能写xls格式的文件,不支持写xlsx文件。

openpyxl:支持读写xlsx文件,功能较广泛,可以设置单元格格式等;但是不支持读写xls文件。

xlwings:支持读写xls和xlsx文件;也可以设置单元格格式等操作。

xlsxwriter:用于创建xlsx/xls文件;支持图片/表格/图表/格式等;缺点是不能打开/修改已有的文件。

简单使用代码

把上面的python3操作Excel常用库的对比信息分别保存到xlsx和xls文件中,然后以这两个文件为例,简单演示一下各个库对Excel文件的简单操作;表格如下图示。

xlrd库读取xls/xlsx文件

import xlrd

xlsx=r"D:\CodeList\ExecuteExcel\Python操作Excel库整理.xlsx"
xls=r"D:\CodeList\ExecuteExcel\Python操作Excel库整理.xls"

wb=xlrd.open_workbook(xls) #根据路径读取Excel文件(xlsx/xls)
#sheet = wb.sheet_by_index(0) #根据索引获取Excel文件中的sheet表格
sheet=wb.sheet_by_name('Sheet1') #通过sheet名称获取sheet表格
nrows = sheet.nrows  #行数
ncols=sheet.ncols    #列数
print("获取每一行的值列表")
for i in range(0,nrows):
    print(sheet.row_values(i)) #获取每一行的值列表
print("==============")
print("获取每一列的值列表")
for i in range(0,nrows):
    print(sheet.col_values(i)) #获取每一列的值列表

上面代码输出的信息如下图示;从输出的信息可以看到,通过函数sheet.row_values(i)/sheet.col_values(i)获取到的信息是一个列表,列表中包含了指定行/列的所有信息。类似的方法还有sheet.row_types(i)/sheet.col_types(i)获取行/列的数据类型列表信息。

上面的方法是直接获取整行或者整列的单元格值列表,如果想同时获取单元格的数据类型,则可以通过sheet.row_slice(i)或者sheet.col_slice(i)方法获取单元格对象列表,单元格对象包含的内容包含了数据类型和值;示例代码如下。

print("获取每一行单元格对象")
for i in range(0,nrows):
    print(sheet.row_slice(i))  #获取每一行单元格对象
print("==============")
print("获取每一列单元格对象")
for i in range(0,ncols):
    print(sheet.col_slice(i))   #获取每一列单元格对象

 

代码输出的结果如下图示。

除了像上面那样整行/整列遍历Excel表格外,还可以通过行列的索引号获取到指定单元格的信息,行列号的索引都是从0开始。

#遍历输出表头(第一行信息)
print("获取指定单元格值")
for i in range(0,ncols):
    print(sheet.cell(0,i).value)

 

上面代码输出的信息如下图所示。

xlwt库写xls文件

xlwt库无法直接修改xls文件,它一般只用于创建一个sheet表,往新建的sheet写入数据,并且可以设置单元格的格式,最后把数据保存到xls文件中。

以创建九九乘法表,然后按照一定的样式保存到xls文件中为例,简单介绍xlwt库写xls文件并设置样式的过程;代码如下:

 

import xlwt

wb=xlwt.Workbook()
sheet=wb.add_sheet('99乘法表')

def set_style(name, colorindex,bold = False):
    '''
    创建单元样式
    :param name: 字体名称
    :param colorindex: 颜色索引
    :param bold: 字体是否加粗
    :return: 样式对象
    '''
    # 为样式创建字体
    font = xlwt.Font()
    font.name = name  #字体名称
    font.bold = bold  #是否加粗字体
    font.colour_index=colorindex

    # 为样式创建背景
    pattern = xlwt.Pattern()
    pattern.pattern = xlwt.Pattern.SOLID_PATTERN
    pattern.pattern_fore_colour = 22 # 设置背景为灰色

    # 为样式创建边框
    borders = xlwt.Borders()
    #DASHED虚线;NO_LINE没有;THIN实线
    borders.top = xlwt.Borders.DASHED
    borders.bottom = xlwt.Borders.DASHED
    borders.right = xlwt.Borders.THIN
    borders.left = xlwt.Borders.THIN
    #设置边框颜色
    borders.left_colour =colorindex
    borders.top_colour = colorindex
    borders.right_colour = colorindex
    borders.bottom_colour = colorindex

    #创建对齐方式
    alignment = xlwt.Alignment()
    #其中horz代表水平对齐方式,vert代表垂直对齐方式
    # 0x01(左端对齐)、0x02(水平方向上居中对齐)、0x03(右端对齐)
    alignment.horz = 0x02
    # 0x00(上端对齐)、 0x01(垂直方向上居中对齐)、0x02(底端对齐)
    alignment.vert = 0x01

    style = xlwt.XFStyle()  # 初始化样式
    style.font = font
    style.pattern=pattern
    style.borders=borders
    style.alignment=alignment
    return style

bold=False
#循环遍历写入单元格并调用函数set_style()设置样式
for i in range(0,9):
    #索引为偶数的字体设置为加粗,奇数不加粗
    if i % 2 == 0:
        bold =True
    else:
        bold=False

    for j in range(0,i+1):
        sheet.write(i,j,
                    "{0}X{1}={2}".format(str(j+1),str(i+1),str((i+1)*(j+1))),
                    set_style("宋体",i,bold))

wb.save("99乘法表.xls")  #wb保存到文件 99乘法表.xls中

代码运行成功后,可以在python脚本所在的文件夹中已经生成文件【99乘法表.xls】,打开文件可以看到九九乘法表已经按照设置的字体,加粗,背景,边框颜色,边框的线类型等样式在表格中生成,如下图所示。

openpyxl读写xlsx

openpyxl读取指定单元格的示例代码如下,输出单元格的数据值,数据类型,字体大小,字体名称信息。

import openpyxl
wb=openpyxl.load_workbook(xlsx)
sheet2=wb[wb.sheetnames[0]]
print("A4单元格的值:",sheet2['A4'].value)
print("A4单元格的数据类型:",sheet2['A4'].data_type)
font=sheet2['A4'].font
print("字体名称:",font.name)
print("字号大小:",font.size)

代码中通过sheet2['A4'],定位到A4单元格,输出的信息如下图所示。

openpyxl读取xlsx文件,判断单元格的值如果是×,则把单元格的字体颜色改为红色,字体加粗,如果是√,字体颜色改为绿色。示例代码如下:

import openpyxl
from openpyxl.styles import Font,colors
wb=openpyxl.load_workbook(xlsx)
sheet2=wb[wb.sheetnames[0]] #根据sheet名称获取sheet

for row in sheet2.rows: 
    for cel in row:
        value=cel.value
        if value=="×":
            cel.font=openpyxl.styles.Font(bold=True,color=colors.RED)
        elif value=="√":
            cel.font = openpyxl.styles.Font(bold=True, color=colors.GREEN)
wb.save("openpyxl操作Excel.xlsx")#wb修改后另存为 openpyxl操作Excel.xlsx
wb.close()

上面代码运行后会在python脚本所在的文件夹中生成文件【openpyxl操作Excel.xlsx】,双击打开文件后可以看到字体的颜色已经根据判断进行了修改,如下图所示。

xlwings读写xls和xlsx

xlwings同时支持xlsx和xls格式的读取,写入,修改和设置单元格格式,并且可以在原文件上保存修改,相对前面的介绍的库来说功能较齐全。下面示例代码就是读取了xls文件,输出特定单元格的值,并修改保存。

import xlwings as xw

app = xw.App(visible=False, add_book=False)
app.display_alerts = False
app.screen_updating = False  # 是否实时刷新excel程序的显示内容
wb = app.books.open(xls)
sheet3 = wb.sheets[0]
cel=sheet3.range('A5')
print(cel.value)  #输出A5单元格值
cel.value="xlwings(推荐)"  #修改A5单元格的值
wb.save()  #保存修改
wb.close()  #关闭wb
app.quit()  #退出app

 下面的示例,通过xlwings库读取xlsx,如果单元格的值为×,则替换为【不支持】,单元格值为√则替换为为【支持】,示例代码如下:

import xlwings as xw

app = xw.App(visible=False, add_book=False)
app.display_alerts = False
app.screen_updating = False  # 是否实时刷新excel程序的显示内容
wb = app.books.open("openpyxl操作Excel.xlsx")
sheet3 = wb.sheets[0]

info = sheet3.used_range
nrows = info.last_cell.row #获取行数
ncolumns = info.last_cell.column  #获取列数
for row in range(1,nrows+1):
    for col in range(1,ncolumns+1):
        value=sheet3.range(row,col).value  #获取单元格值
        if value=="×":
            sheet3.range(row, col).value="不支持"
        elif value=="√":
            sheet3.range(row, col).value = "支持"
wb.save()  #保存修改
wb.close()  #关闭wb
app.quit()  #退出app

xlwings库通过sheet.range()函数定位到指定单元格;sheet.range()函数支持两种定位方式,一种是通过行列的索引号进行定位(注意这里的行列号索引都是从1开始),另一种通过单元格名称进行定位,例如A5。xlwings库还有一个优点就是可以保留单元格原有的样式,只是更新单元格的值。上面的代码运行后得到的结果如下图所示。

xlsxwriter库

xlsxwriter库功能跟前面的xlwt功能有点类似,都是创建一个新的表格,然后往表格里填入数据保存为Excel文件;不同的是xlsxwriter库同时可以保存为xls和xlsx,更强大的功能是xlsxwriter库支持设置指定字符的样式。我们前面介绍到可以设置单元格样式的的库,他们的最小单位都是单元格,就是说单元格里的字符只能设置一个样式,但是实际情况是一个单元格里的字符可以包含多种字体,如下图所示;B7单元格的字符就同时包含了两种字体【宋体】和【Wingdings 2】;带框的勾,其实它就是一个字符【R】,把它的字体改为【Wingdings 2】后,它就变成了带边框的√。

下面的示例代码就简单介绍一下使用xlsxwriter库实现带边框√加中文字符的样式设置(一个单元格包含多个样式)。

from xlsxwriter.workbook import Workbook
# 创建Excel对象
workbook = Workbook(filename='Infos1.xlsx')
worksheet = workbook.add_worksheet()
# 定义样式
style = workbook.add_format({'font_name': 'Wingdings 2', 
'color': 'red', 'bold': True})
# 表内容
expenses = (
    ['性别', 'R男  □女'],
    ['喜欢运动', '□乒乓球  R足球    □跑步'],
    ['喜欢电影类型', '□爱情     R喜剧     □战争     R惊悚'],)
row = 1
col = 0

def split_list_by_rich_word(word_list, rich_word):
    """根据rich_word将文本列表进一步拆分"""
    rt = []
    for word in word_list:
        if rich_word in word:
            tmp = word.split(rich_word)
            rt_tmp = []
            flag = False
            for t in tmp:
                if not flag:
                    flag = True
                    rt_tmp.append(t)
                else:
                    rt_tmp.append(rich_word)
                    rt_tmp.append(t)
            rt += rt_tmp
        else:
            rt.append(word)
    return rt

def str_2_rich_string_content(s, rich_word_list, style):
    """构建字体样式"""
    wl = [s]
    # 是否包含rich_word_list
    flag = False
    for r_w in rich_word_list:
        if r_w in s:
            flag = True
            wl = split_list_by_rich_word(wl, r_w)
    if not flag:
        return False, []
    # 添加样式
    for i in range(len(wl) - 1, -1, -1):
        if wl[i] in rich_word_list:
            wl.insert(i, style)
    if '' in wl:
        wl.remove('')
    return True, wl
# 表头
worksheet.write('A1', 'Item')
worksheet.write('B1', 'content')
for item, content in (expenses):
    # 需要设置特定样式字符串列表
    style_word = ['R']
    item_flag, item_rich_string = str_2_rich_string_content(s=content, rich_word_list=style_word, style=style)
    # 如果包含需要标记颜色的字段, 就以富文本的形式写入
    if item_flag:
        worksheet.write_rich_string(row, col+1, *item_rich_string)
    else:
        worksheet.write_string(row, col + 1, content)
    worksheet.write_string(row, col, item)
    row += 1
workbook.close()

上面代码参考博客:https://blog.csdn.net/qq_16949707/article/details/106627432 

代码运行成功后,打开生成的Excel文件,可以看到一个单元格内容包含了两种字体,如下图所示。

xlsxwriter库主要通过函数worksheet.write_rich_string()实现设置指定字符的样式,这个函数的定义如下:


待解决问题

xlsxwriter库虽然可以设置指定字符的样式,从而实现一个单元格内包含多种样式,但是这个库只能新建表格,无法对现有的Excel文件进行操作。而前面的xlwings和openpyxl只能设置整个单元格的样式,类似于带框√这种需求,xlwings和openpyxl就不能很好地满足;因为把单元格的字体都改为Wingdings 2,那些中文字符就会乱码,把单元格字体改为【宋体】,带框的√就会变成字符【R】,如下图所示。

总结
到这里,Python3操作Excel常用库整理就结束了,文章只是简单的介绍各个库简单的,常用的功能(比如说读,写,遍历定位单元格,修改单元格的值或者样式等),并没有深入;因为每个库的功能都比较多,如果深入的话,每个库都可以整理一个专栏出来了。
Python语言比较好的一个地方就是当你学习一个新的库时,你可以非常方便地去看库提供哪些函数,或者某个对象它有什么属性;例如如果你对xlwt库不熟悉,在Pycharm中按住【Ctrl】键,用鼠标点击【XFStyle】对象,你就可跳转到这个对象的源码,然后通过源码查看到这个对象的属性,提供的方法等信息;如下图所示。可以看到xlwt库的XFStyle对象可以设置字体,对齐,边框和背景等信息。

通过上面对Python3操作Excel文件常用库的整理可以看到xlwings的功能相对比较齐全,可以在原文件上修改且同时支持xls和xlsx,所以首先推荐使用xlwings库操作Excel。不管使用哪个库,最重要的是要知道如何去循环遍历Excel中的单元格,或者说定位到指定的单元格,然后才能结合Python的逻辑判断等功能,按照一定的业务逻辑对Excel文件进行读写编辑等操作。


参考:
xlwings中文文档
https://www.kancloud.cn/gnefnuy/xlwings-docs/1127450

openpyxl中文文档
https://www.osgeo.cn/openpyxl/index.html#documentation

xlrd文档:
https://xlrd.readthedocs.io/en/latest/index.html

博客:
https://blog.csdn.net/qq_169497

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐