最近有個需求要處理excel 格式的數據,數據量比較大。用傳統的語言似乎不太好處理,於是改用python實現,這里記錄一下實現過程。
首先,科普一下xlsx xls的excel文件區別是什么。
-
xls是03版Office Microsoft Office Excel 工作表的格式,用03版Office,新建Excel默認保存的Excel文件格式的后綴是.xls;
-
xlsx是07版Office Microsoft Office Excel 工作表的格式,用07版Office,新建Excel默認保存的的Excel文件格式后綴是.xlsx。
使用xls的唯一理由只能是照顧老版本軟件的兼容性需要
xls的壞處有:
- 如果你的數據超出256列和65536行,使用xls會導致數據被截斷
- 使用xls格式后,無法使用一系列Excel新功能
- 使用xls格式會導致文件體積暴增
- 使用xls格式無法挽救出錯文件
- xls格式沒有xlsx格式快
所以大家以后還是用xlsx格式吧。
好了,言歸正傳,開始寫一下實現部分,處理的部分用到了下面幾個庫
1. sudo easy_install pip
2. pip install openpyxl #讀取xlsx格式excel文件
3. pip install xlrd #讀取xls 格式excel文件
4. pip install uniout #可以顯示中文
5. pip install numpy #數據保存
openpyxl模塊
安裝如上,處理excel的模塊庫有幾種,我只記錄跟使用了這一個,好用就行。
記錄相關用法:
from openpyxl import load_workbook,Workbook
# 設置文件 mingc
addr = "yourexcel.xlsx"
# 打開文件
wb = load_workbook(addr)
#獲取當前活躍的sheet
# sheet=wb.get_active_sheet()
#一般不清楚活躍的sheet是什么,所以這里可以指定用第一個sheet
sheetnames = wb.get_sheet_names()
#獲取第一個sheet
sheet = wb.get_sheet_by_name(sheetnames[0])
#獲取列
print(sheet["B"])
#打印B列第2行的值(index從0算起)
print (sheet["B"][1].value)
#獲取sheet 列和行數
print(sheet.max_row)
print(sheet.max_column)
#數據保存生成xlsx格式excel文件
workbook = Workbook()
sheet_output = workbook.active
sheet_output.title = "sheet_export"
sheet_output.append(["第一列內容","第二列內容","第三列內容","第四列內容"])
...#導出append你處理好的列數據
workbook.save('my_file_export.xlsx')
#其他處理
....
xlrd模塊
xlrd用來讀取xls excel文件,相關用法如下:
import xlrd
workbook = xlrd.open_workbook('yourexcel.xls') # 打開xls文件
worksheets = workbook.sheets()[0] # 打開第一張表
nrows = worksheets.nrows # 獲取表的行數
#行操作:
sheet1.row_values(0) # 獲取第一行所有內容,合並單元格,首行顯示值,其它為空。
sheet1.row(0) # 獲取單元格值類型和內容
sheet1.row_types(0) # 獲取單元格數據類型
#表操作
sheet1.row_values(0, 6, 10) # 取第1行,第6~10列(不含第10表)
sheet1.col_values(0, 0, 5) # 取第1列,第0~5行(不含第5行) 這個比較好用,取第幾列,行范圍內容數據
sheet1.row_slice(2, 0, 2) # 獲取單元格值類型和內容
sheet1.row_types(1, 0, 2) # 獲取單元格數據類型
#其他處理
....
中文處理
先說一下我的需求實現,我需要將一份xlsx數據全部吃進來,然后與另一份xls格式的文件比對(包含空的情況),把篩選數據另存起來導出,功能目的很明確。
在實現的過程中發現,讀取到的不是unicode字符就是十六進制的東西,結合之前的理解。大家可以參考一下之前記錄的一篇關於python 編碼解碼的理解[Python]輸出中文的方法,搞懂編碼encode和解碼decode.
處理實現如下:
#遍歷第一列內容,包含中文格式,這里有2個處理。
#第一個,指定python版本編碼方式:
import sys
if sys.version_info[0] == 3:
from importlib import reload
reload(sys)
if sys.version_info[0] == 2:
reload(sys)
sys.setdefaultencoding('utf-8')
#第二個,對內部的utf-8編碼的數據先解碼再編碼即可拿到中文數據
for i in xrange(1,sheet.max_row):
tempData = {}
if len(str(sheet["A"][i].value)) == 0 or sheet["A"][i].value == None: #為空處理
tempData["第一列"] = "nil"
else:
tempData["第一列"] = sheet["A"][i].value.decode('utf-8').encode('utf-8')
....
numpy模塊
這個模塊主要用到了一個功能是數據保存,數據保存方式很多,這里我也只用到了numpy。
這里有一個地方要注意,加載npy數據的時候要注意參數allow_pickle=True,numpy有一個版本變動,后面不支持必須要加這個arg
import numpy as np
# Save ur dic data.
np.save('my_file_source.npy', dicData)
#npy格式文件內容讀取,格式為dic
dic_exportData = np.load('my_file_source.npy',allow_pickle=True).item()
補充
這里,我的需求數據里有發現數據包含重復的情況,因此需要額外處理一下。
方法是將那一列數據先存到一個list里,通過該方法將重復數量大於2的print並以追加模式保存進txt文檔里,供使用者查看。
def get_sort_list(templist):
setlist = set(templist)
dictlist = {}
for item in setlist:
if templist.count(item) >=2:
dictlist.update({item:templist.count(item)})
print("dup key list count : ",len(dictlist))
print("dup key list : ",dictlist)
if len(dictlist) !=0:
file = open('dup_key.txt', 'a+')
for k,v in dictlist.items():
file.write(str(k)+' '+str(v)+'\n')
file.close()