openpyxl在修改.xlsx文件后发现修改无效的问题


临时要处理大量数据,用的是.xlsx的格式保存,因为xlrd、xlwt和xlutils对xlsx文件太不友好了,所以.xlsx格式的文件我一般都用openpyxl进行修改。

在修改后结束程序的过程中,我发现文件并没有被修改,后来发现是还要再使用save函数。在网上查找也没人有这个问题(可能是因为我太菜),就在此记录一下。

关于相关函数的具体操作,在其他的文章中有很详细的描写,故我在此不多作赘述。

  1. 在一开始要:
# 可能需要先安装
import openpyxl
  1. 然后创建一个workbook类型的对象:
# 这里是默认可读可写的,可手动调整为只读或者只写
wt_book=openpyxl.load_workbook("Origin_File.xlsx") # 相对路径或绝对路径
  1. 接着获取工作表:
# 这里的active是获取打开文件时所显示的那一张表格,一般是第一张表
sheet=wt_book.active
  1. 在获取了工作表之后,就可以对该表的内容进行修改,修改完成之后需要保存:
# 在这里填写的文件,若存在则覆盖,若不存在则创建
wt_book.save("Final_File.xlsx") # 相对路径或绝对路径

这样应该就能够得到修改之后的文件:Final_File.xlsx

下面是我在对一个几千行的Excel文件进行数据处理时,用来删除.xlsx文件中无用数据过多的行时(即". ."过多)的代码:

在这个Origin_File.xlsx文件中,每相邻的两行为一项数据,故删除时要一起删,在记录要删除的行数时,只需要记录其中一行的行数即可.

# 要把xlrd返回到1.2.0版本才行,最新版本不支持xlsx文件,只支持xls文件
# 现在发现xlrd、xlwt和xlutils对xlsx文件太不友好了,所以换成openpyxl
# 之前删除操作之后发现没反应,后来发现是还要用save函数来保存
# 在遍历的时候,如果删除某一行,遍历还是会往下一位,则会跳过本来应该读取的下一行而去读取下下行
import openpyxl
# 用来筛选出不符合要求的行
def rewrite(wt_book):
    # 记录要删除的行数
    keep_rows=list()
    # 用来验证是否删除成功
    delete_num = 0
    # 获取打开时显示的工作表的表名
    sheet=wt_book.active
    # 获取原表的行数
    origin_rows=sheet.max_row
    print(sheet,'\n')
    # 记录现在遍历到了第几行
    row_count=0
    # 对每一行进行遍历,注意在删除操作时,row还是会往下走,即会跳过一次
    # 每一行都生成了一个元组,每个元组的元素为每个单元格的元素
    for row in sheet.rows:
        # 删除是从第1行开始,没有第0行
        row_count+=1
        # 计算空值的数目
        count=0
        for val in row:
            # 删掉数据有缺的那一行,并不检查BM列
            if val.value==".." and val.column_letter!="BM":
                count+=1
                break
        # 改变这个判断条件即可删除不同要求的行数
        if count>0:
            # 保存要删除的行数
            # 避免同时保存要删除的同一组的两行
            if len(keep_rows)!=0 and keep_rows[-1]+1==row_count and 	row_count%2==1:
                continue
            keep_rows.append(row_count)

    # 进行删除操作
    for num in keep_rows:
        # 奇数
        if num%2==1:
            sheet.delete_rows(num-1-delete_num)
            print("Delete ", num-1, "......")
            sheet.delete_rows(num-1-delete_num)
            print("Delete ", num, "......")
            delete_num += 2
        # 偶数
        else:
            sheet.delete_rows(num-delete_num)
            print("Delete ", num, "......")
            sheet.delete_rows(num - delete_num)
            print("Delete ", num+1, "......")
            delete_num += 2


    # 创建一个新文件来保存修改之后的文件
    # 这里可以填写相对路径
    wt_book.save("Final_File.xlsx")
    # 打开修改之后的文件并查询行数
    # 可填写相对路径
    final_book=openpyxl.load_workbook("Final_File.xlsx")
    final_sheet=final_book.active
    # 修改后的行数
    final_sheet_rows=final_sheet.max_row
    # 验证是否修改成功
    if origin_rows==final_sheet_rows+delete_num:
        print("Success to delete",'\n',"Delete ",delete_num," rows in total")
    else:
        print("Fail to delete")

if __name__=="__main__":
    # 获取一个Workbook对象,这里文件默认装备为可读可写
    # 填写文件名,带上文件格式
    # 可填写相对路径
    wt_book = openpyxl.load_workbook("Origin_File.xlsx")
    rewrite(wt_book)
    print("Complete")