引子
最近在做一些數據處理和計算的工作,因爲數據是以.csv格式保存的,因此剛開始直接用Excel來處理。但是做着做着發現重複的勞動其實並沒有多大的意義,於是就想着寫個小工具幫着處理。以前正好在一本書上看到過使用Python來處理Excel表格,可惜沒有仔細看。於是我到處查找資料,終於算是完成了任務,因此撰寫此文就算是總結吧。
在這裏我還會順帶介紹一下如何處理.csv文件,因爲某些情況下這是必須的(後面會提到)。
環境配置
下面的環境配置是針對Windows操作系統的,其他操作系統差別不是很大,可以參考一下。
我使用的Python版本號是2.7.12,如果你的Python是2.x,請確保在2.6以上。在Python 3.x上可能會有些不太一樣,所以要注意,可以參考其他的文檔和博客。
Python自帶的csv
模塊可以處理.csv文件。
xlrd
和xlwt
兩個模塊分別用來讀Excel和寫Excel,只支持.xls和.xlsx格式,Python不默認包含。這兩個模塊之間相互獨立,沒有依賴關係,也就是說可以根據需要只安裝其中一個。
xlutils
模塊可以同時讀寫一個已存在的Excel文件,依賴於xlrd
和xlwt
。
安裝這三個模塊時,可以去PyPI去搜索需要的模塊並下載。在我寫這篇文章時,xlrd
是有一個適合python 3.x的.whl文件和一個通用的.tar.gz的源碼文件。xlwt
是提供了同時適用於python 2.x和3.x的.whl文件和一個通用的.tar.gz的源碼文件,還提供了pip的安裝方式。xlutils
與xlwt
情況相同。
安裝過程中我是默認你已經配好了環境變量,並且pip是可用的,如果在命令行裏執行pip命令顯示找不到命令,可以在網上搜索相關解決方案,這裏不做贅述。
下面簡單說一下幾種安裝模塊的方式。
安裝源碼文件需要先解壓,然後進入到源碼目錄執行下面命令:
python setup.py install
- 1
安裝.whl文件執行下面命令:
pip install <你的.whl文件>
- 1
使用pip安裝前要確認你的網絡是可用的,然後執行命令:
pip install <模塊名>
- 1
當你看到類似Successfully的字樣時,表明已經安裝成功了。如果沒成功,那就一定是有什麼原因了,可以自己上網搜索具體解決方案。
使用xlrd
讀Excel
xlrd
提供的接口比較多,常用的如下:
open_workbook()
打開指定的Excel文件,返回一個Book對象。
通過Book對象可以得到各個Sheet對象(一個Excel文件可以有多個Sheet,每個Sheet就是一張表格)。
Book.nsheets
返回Sheet的數目。
Book.sheets()
返回所有Sheet對象的list。
Book.sheet_by_index(index)
返回指定索引處的Sheet。相當於Book.sheets()[index]
。
Book.sheet_names()
返回所有Sheet對象名字的list。
Book.sheet_by_name(name)
根據指定Sheet對象名字返回Sheet。
通過Sheet對象可以獲取各個單元格,每個單元格是一個Cell對象。
Sheet.name
返回表格的名稱。
Sheet.nrows
返回表格的行數。
Sheet.ncols
返回表格的列數。
Sheet.row(r)
獲取指定行,返回Cell對象的list。
Sheet.row_values(r)
獲取指定行的值,返回list。
Sheet.col(c)
獲取指定列,返回Cell對象的list。
Sheet.col_values(c)
獲取指定列的值,返回list。
Sheet.cell(r, c)
根據位置獲取Cell對象。
Sheet.cell_value(r, c)
根據位置獲取Cell對象的值。
Cell.value
返回單元格的值。
下面是一段示例代碼:
import xlrd
wb = xlrd.workbook('test.xls')
# 打印每張表的最後一列
# 方法1
for s in wb.sheets():
print "== The last column of sheet '%s' ==" % (s.name)
for i in range(s.nrows):
print s.row(i)[-1].value
# 方法2
for i in range(wb.nsheets):
s = wb.sheet_by_index(i)
print "== The last column of sheet '%s' ==" % (s.name)
for v in s.col_values(s.ncols - 1):
print v
# 方法3
for name in wb.sheet_names():
print "== The last column of sheet '%s' ==" % (name)
s = wb.sheet_by_name(name)
c = s.ncols - 1
for r in range(s.nrows):
print s.cell_value(r, c)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
使用xlwt
寫Excel
相對來說,xlwt
提供的接口就沒有xlrd
那麼多了,主要如下:
Workbook()
是構造函數,返回一個工作簿的對象。
Workbook.add_sheet(name)
添加了一個名爲name的表,類型爲Worksheet。
Workbook.get_sheet(index)
可以根據索引返回Worksheet(前提是已經添加到Workbook中了)。
Worksheet.write(r, c, vlaue)
是將vlaue填充到指定位置。
Worksheet.row(n)
返回指定的行。
Row.write(c, value)
在某一行的指定列寫入value。
Worksheet.col(n)
返回指定的列。
通過對Row.height
或Column.width
賦值可以改變行或列默認的高度或寬度。(單位:0.05 pt,即1/20 pt)
Workbook.save(filename)
保存文件。
有這麼幾點需要注意一下:
xlwt
模塊最大能寫65535行,256列,如果超過這個範圍,程序運行就會出現錯誤,那麼可能需要找一些其他方法來解決。如果我們只注重數據的處理,那麼可以採用csv
模塊來替代。文件默認的編碼方式是
ascii
,如果要改變編碼方式,指定Workbook()
的encoding
參數,如Workbook(encoding='utf-8')
。表的單元格默認是不可重複寫的,如果有需要,在調用
add_sheet()
的時候指定參數cell_overwrite_ok=True
即可。
下面是一段示例代碼:
import xlwt
book = xlwt.Workbook(encoding='utf-8')
sheet = book.add_sheet('sheet_test', cell_overwrite_ok=True)
sheet.write(0, 0, 'Python')
sheet.row(0).write(1, 'is')
sheet.write(0, 2, 'very very useful.')
sheet.col(2).width = 4000
book.save('test.xls')
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
除了基本的寫入數據之外,xlwt
還可以改變單元格格式。上面的write
方法允許接受一個XFStyle
(意爲eXcel File Style)類型的參數,放在最後的位置。easyxf()
可以快速生成一個XFStyle對象。
這裏簡單介紹一下其用法:
import datetime, xlwt
# ... some code
font = xlwt.Font()
font.name = 'Arial'
font.height = 240 # font size: 12pt
pattern = xlwt.Pattern()
pattern.pattern = xlwt.Pattern.SOLID_PATTERN
pattern.pattern_fore_colour = 0x0A
style = xlwt.XFStyle()
style.num_format_str = '0.00%'
style.font = font
style.pattern = pattern
a = 8
b = 10
# 以百分比的形式顯示,保留兩位小數
sheet.write(0,3, float(a) / b, style)
# 顯示日期
sheet.row(0).write(4, datetime.date(2016,8,14), xlwt.easyxf(
'font: name Arial, height 240;'
'pattern: pattern squares, fore_color red;',
num_format_str = 'YYYY-MM-DD'
)
)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
使用xlutils
修改Excel
通過xlrd.open_workbook()
打開的Book對象是隻讀的,不能直接對其進行修改操作,而xlwt.Workbook()
返回的Workbook對象雖然可寫,但是寫的時候只能從零寫起,那如果要修改一個已經存在的Excel該怎麼辦呢?
慶幸的是,在xlutils.copy
中有個copy()
方法,我們可以將一個xlrd.Book
對象轉化爲一個xlwt.Workbook
對象,這樣我們就可以直接對已存在的Excel文件進行修改了。
用法舉例如下:
import xlrd
import xlutils.copy
book = xlrd.open_workbook('test.xls', formatting_info=True)
wtbook = xlutils.copy.copy(book)
wtsheet = wtbook.get_sheet(0)
wtsheet.write(0, 0, 'Ok, changed!')
wtbook.save('test.xls')
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
要注意的是:
調用
xlrd.open_workbook()
時,如果不指定formatting_info=True
,那麼修改後整個文檔的樣式會丟失。對一個單元格進行write
操作時,如果不指定樣式,也會將原來的樣式丟失。注意調用
copy()
的方法。也可以通過聲明from xlutils.copy import copy
來直接調用copy()
。
使用csv
讀寫csv文件
與讀寫Excel文件相比,csv文件的讀寫是相當方便的。
直接看下面的例子吧。
import csv
file1 = open('test1.csv', 'rb')
reader = csv.reader(file1)
for line in reader:
for col in line:
print col,
print
file1.close()
file2 = file('test2.csv', 'wb')
writer = csv.writer(file2)
writer.writerow([1,2,3,4,5])
writer.writerows([
[6,7,8],
[9,10,11,12],
[13,14,15,16,17]
])
file2.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
這個程序涉及到了下面的方法:
csv.reader()
返回一個DictReader對象。csv.writer()
返回一個DictWriter對象。DictWriter.writerow()
寫一行。DictWriter.writerows()
寫多行。
需要注意的問題是:當我們需要寫csv的時候,打開文件一定要帶上’b’,否則可能會往文件裏輸出空行。Python 3.x情況會有些不同。
More…
[1] https://github.com/python-excel/xlrd/
[2] https://github.com/python-excel/xlwt/
[3] https://github.com/python-excel/tutorial/