1. 程式人生 > >python之xlwt、xlrd和openpyxl

python之xlwt、xlrd和openpyxl

實現對excel檔案的讀寫功能

1.xlwt:對xls等excel檔案的寫入

2.xlrd:對xls等excel檔案的讀取

3.openpyxl:對xlsm、xlsx等excel檔案的讀寫

一、讀excel表(xlrd)

讀excel要用到xlrd模組,官網安裝(http://pypi.python.org/pypi/xlrd)。然後就可以跟著裡面的例子稍微試一下就知道怎麼用了。大概的流程是這樣的:

1、匯入模組

      import xlrd

2、開啟Excel檔案讀取資料

       data = xlrd.open_workbook('excel.xls')

3、獲取一個工作表

table = data.sheets()[0]          #通過索引順序獲取
table = data.sheet_by_index(0) #通過索引順序獲取
table = data.sheet_by_name(u'Sheet1')#通過名稱獲取

4、獲取整行和整列的值(返回陣列)

table.row_values(i)
table.col_values(i)

5、獲取行數和列數 

table.nrows
table.ncols

6、獲取單元格

table.cell(0,0).value
table.cell(2,3).value

就我自己使用的時候覺得還是獲取cell最有用,這就相當於是給了你一個二維陣列,餘下你就可以想怎麼幹就怎麼幹了。得益於這個十分好用的庫程式碼很是簡潔。但是還是有若干坑的存在導致話了一定時間探索。

1、首先就是我的統計是根據姓名統計各個表中的資訊的,但是除錯發現不同的表中各個名字貌似不能夠匹配,開始懷疑過編碼問題,不過後來發現是因為  空格。因為在excel中輸入的時候很可能會順手在一些名字後面加上幾個空格或是tab鍵,這樣看起來沒什麼差別,但是程式處理的時候這就是兩個完全  不同的串了。我的解決方法是給每個獲取的字串都加上strip()處理一下。效果良好

2、還是字串的匹配,在判斷某個單元格中的字串(中文)是否等於我所給出的的時候發現無法匹配,並且各種unicode也不太奏效,百度過一些解決  方案,但是都比較複雜或是沒用。最後我採用了一個比較變通的方式:直接從excel中獲取我想要的值再進行比較,效果是不錯就是通用行不太好,個  呢不能問題還沒解決。

二、寫excel表(xlwt)

  寫excel表要用到xlwt模組,官網下載(http://pypi.python.org/pypi/xlwt)。大致使用流程如下:

1、匯入模組

  import xlwt

2、建立workbook(其實就是excel,後來儲存一下就行)

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

3、建立表
  worksheet = workbook.add_sheet('My Worksheet')

4、往單元格內寫入內容

  worksheet.write(0, 0, label = 'Row 0, Column 0 Value')

5、儲存

  workbook.save('Excel_Workbook.xls')

由於我的需求比較簡單,所以這上面沒遇到什麼問題,唯一的就是建議還是用ascii編碼,不然可能會有一些詭異的現象。

當然xlwt功能遠遠不止這些,他甚至可以設定各種樣式之類的。附上一點例子

'''
Examples Generating Excel Documents Using Python’s xlwt,Here are some simple examples using Python’s xlwt library to dynamically generate Excel documents.Please note a useful alternative may be ezodf, which allows you to generate ODS (Open Document Spreadsheet) files for LibreOffice / OpenOffice. You can check them out at:http://packages.python.org/ezodf/index.html,
The Simplest Example
'''
import xlwt
workbook = xlwt.Workbook(encoding = 'ascii')
worksheet = workbook.add_sheet('My Worksheet')
worksheet.write(0, 0, label = 'Row 0, Column 0 Value')
workbook.save('Excel_Workbook.xls')
'''
Formatting the Contents of a Cell
'''
import xlwt
workbook = xlwt.Workbook(encoding = 'ascii')
worksheet = workbook.add_sheet('My Worksheet')
font = xlwt.Font() # Create the Font
font.name = 'Times New Roman'
font.bold = True
font.underline = True
font.italic = True
style = xlwt.XFStyle() # Create the Style
style.font = font # Apply the Font to the Style
worksheet.write(0, 0, label = 'Unformatted value')
worksheet.write(1, 0, label = 'Formatted value', style) # Apply the Style to the Cell
workbook.save('Excel_Workbook.xls')
'''
Attributes of the Font Object
'''
font.bold = True # May be: True, False
font.italic = True # May be: True, False
font.struck_out = True # May be: True, False
font.underline = xlwt.Font.UNDERLINE_SINGLE # May be: UNDERLINE_NONE, UNDERLINE_SINGLE, UNDERLINE_SINGLE_ACC, UNDERLINE_DOUBLE, UNDERLINE_DOUBLE_ACC
font.escapement = xlwt.Font.ESCAPEMENT_SUPERSCRIPT # May be: ESCAPEMENT_NONE, ESCAPEMENT_SUPERSCRIPT, ESCAPEMENT_SUBSCRIPT
font.family = xlwt.Font.FAMILY_ROMAN # May be: FAMILY_NONE, FAMILY_ROMAN, FAMILY_SWISS, FAMILY_MODERN, FAMILY_SCRIPT, FAMILY_DECORATIVE
font.charset = xlwt.Font.CHARSET_ANSI_LATIN # May be: CHARSET_ANSI_LATIN, CHARSET_SYS_DEFAULT, CHARSET_SYMBOL, CHARSET_APPLE_ROMAN, CHARSET_ANSI_JAP_SHIFT_JIS, CHARSET_ANSI_KOR_HANGUL, CHARSET_ANSI_KOR_JOHAB, CHARSET_ANSI_CHINESE_GBK, CHARSET_ANSI_CHINESE_BIG5, CHARSET_ANSI_GREEK, CHARSET_ANSI_TURKISH, CHARSET_ANSI_VIETNAMESE, CHARSET_ANSI_HEBREW, CHARSET_ANSI_ARABIC, CHARSET_ANSI_BALTIC, CHARSET_ANSI_CYRILLIC, CHARSET_ANSI_THAI, CHARSET_ANSI_LATIN_II, CHARSET_OEM_LATIN_I
font.colour_index = ?
font.get_biff_record = ?
font.height = 0x00C8 # C8 in Hex (in decimal) = 10 points in height.
font.name = ?
font.outline = ?
font.shadow = ?
'''
Setting the Width of a Cell
'''
import xltw
workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('My Sheet')
worksheet.write(0, 0, 'My Cell Contents')
worksheet.col(0).width = 3333 # 3333 = 1" (one inch).
workbook.save('Excel_Workbook.xls') 
'''
Entering a Date into a Cell
'''
import xlwt
import datetime
workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('My Sheet')
style = xlwt.XFStyle()
style.num_format_str = 'M/D/YY' # Other options: D-MMM-YY, D-MMM, MMM-YY, h:mm, h:mm:ss, h:mm, h:mm:ss, M/D/YY h:mm, mm:ss, [h]:mm:ss, mm:ss.0
worksheet.write(0, 0, datetime.datetime.now(), style)
workbook.save('Excel_Workbook.xls')
'''
Adding a Formula to a Cell
'''
import xlwt
workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('My Sheet')
worksheet.write(0, 0, 5) # Outputs 5
worksheet.write(0, 1, 2) # Outputs 2
worksheet.write(1, 0, xlwt.Formula('A1*B1')) # Should output "10" (A1[5] * A2[2])
worksheet.write(1, 1, xlwt.Formula('SUM(A1,B1)')) # Should output "7" (A1[5] + A2[2])
workbook.save('Excel_Workbook.xls')
'''
Adding a Hyperlink to a Cell
'''
import xlwt
workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('My Sheet')
worksheet.write(0, 0, xlwt.Formula('HYPERLINK("http://www.google.com";"Google")')) # Outputs the text "Google" linking to http://www.google.com
workbook.save('Excel_Workbook.xls')
'''
Merging Columns and Rows
'''
import xlwt
workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('My Sheet')
worksheet.write_merge(0, 0, 0, 3, 'First Merge') # Merges row 0's columns 0 through 3.
font = xlwt.Font() # Create Font
font.bold = True # Set font to Bold
style = xlwt.XFStyle() # Create Style
style.font = font # Add Bold Font to Style
worksheet.write_merge(1, 2, 0, 3, 'Second Merge', style) # Merges row 1 through 2's columns 0 through 3.
workbook.save('Excel_Workbook.xls')
'''
Setting the Alignment for the Contents of a Cell
'''
import xlwt
workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('My Sheet')
alignment = xlwt.Alignment() # Create Alignment
alignment.horz = xlwt.Alignment.HORZ_CENTER # May be: HORZ_GENERAL, HORZ_LEFT, HORZ_CENTER, HORZ_RIGHT, HORZ_FILLED, HORZ_JUSTIFIED, HORZ_CENTER_ACROSS_SEL, HORZ_DISTRIBUTED
alignment.vert = xlwt.Alignment.VERT_CENTER # May be: VERT_TOP, VERT_CENTER, VERT_BOTTOM, VERT_JUSTIFIED, VERT_DISTRIBUTED
style = xlwt.XFStyle() # Create Style
style.alignment = alignment # Add Alignment to Style
worksheet.write(0, 0, 'Cell Contents', style)
workbook.save('Excel_Workbook.xls')
'''
Adding Borders to a Cell
Please note: While I was able to find these constants within the source code, on my system (using LibreOffice,) I was only presented with a solid line, varying from thin to thick; no dotted or dashed lines.
'''
import xlwt
workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('My Sheet')
borders = xlwt.Borders() # Create Borders
borders.left = xlwt.Borders.DASHED # May be: NO_LINE, THIN, MEDIUM, DASHED, DOTTED, THICK, DOUBLE, HAIR, MEDIUM_DASHED, THIN_DASH_DOTTED, MEDIUM_DASH_DOTTED, THIN_DASH_DOT_DOTTED, MEDIUM_DASH_DOT_DOTTED, SLANTED_MEDIUM_DASH_DOTTED, or 0x00 through 0x0D.
borders.right = xlwt.Borders.DASHED
borders.top = xlwt.Borders.DASHED
borders.bottom = xlwt.Borders.DASHED
borders.left_colour = 0x40
borders.right_colour = 0x40
borders.top_colour = 0x40
borders.bottom_colour = 0x40
style = xlwt.XFStyle() # Create Style
style.borders = borders # Add Borders to Style
worksheet.write(0, 0, 'Cell Contents', style)
workbook.save('Excel_Workbook.xls')
'''
Setting the Background Color of a Cell
'''
import xlwt
workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('My Sheet')
pattern = xlwt.Pattern() # Create the Pattern
pattern.pattern = xlwt.Pattern.SOLID_PATTERN # May be: NO_PATTERN, SOLID_PATTERN, or 0x00 through 0x12
pattern.pattern_fore_colour = 5 # May be: 8 through 63. 0 = Black, 1 = White, 2 = Red, 3 = Green, 4 = Blue, 5 = Yellow, 6 = Magenta, 7 = Cyan, 16 = Maroon, 17 = Dark Green, 18 = Dark Blue, 19 = Dark Yellow , almost brown), 20 = Dark Magenta, 21 = Teal, 22 = Light Gray, 23 = Dark Gray, the list goes on...
style = xlwt.XFStyle() # Create the Pattern
style.pattern = pattern # Add Pattern to Style
worksheet.write(0, 0, 'Cell Contents', style)
workbook.save('Excel_Workbook.xls')

'''
134 TODO: Things Left to Document
Panes -- separate views which are always in view
Border Colors (documented above, but not taking effect as it should)
Border Widths (document above, but not working as expected)
Protection
Row Styles
Zoom / Manification
WS Props?
Source Code for reference available at: https://secure.simplistix.co.uk/svn/xlwt/trunk/xlwt/
'''

附錄:Excel 檔案格式

格式

副檔名

說明

Excel 工作簿

.xlsx

Excel 2010 和 Excel 2007 預設的基於 XML 的檔案格式。不能儲存 Microsoft Visual Basic for Applications (VBA) 巨集程式碼或 Microsoft Office Excel 4.0 巨集工作表 (.xlm)。

Excel 啟用巨集的工作簿(程式碼)

.xlsm

Excel 2016Excel 2013Excel 2010 和 Excel 2007的基於 XML 和啟用巨集的檔案格式。儲存 VBA 巨集程式碼或 Excel 4.0 巨集工作表 (.xlm)。

Excel 二進位制工作簿

.xlsb

Excel 2010 和 Excel 2007 的二進位制檔案格式 (BIFF12)。

模板

.xltx

Excel 2010 和 Excel 2007 的 Excel 模板預設的檔案格式。不能儲存 VBA 巨集程式碼或 Excel 4.0 巨集工作表 (.xlm)。

模板(程式碼)

.xltm

Excel 模板 Excel 2010 和 Excel 2007 啟用巨集的檔案格式。儲存 VBA 巨集程式碼或 Excel 4.0 巨集工作表 (.xlm)。

Excel 97- Excel 2003 工作簿

.xls

Excel 97 - Excel 2003 二進位制檔案格式 (BIFF8)。

Microsoft Excel 5.0/95 工作簿

.xls 

Excel 5.0/95 二進位制檔案格式 (BIFF5)

Excel 97- Excel 2003 模板

.xlt

Excel 模板的 Excel 97 - Excel 2003 二進位制檔案格式 (BIFF8)。

 

讀寫xmls檔案(openpyxl)

讀取Excel檔案

需要匯入相關函式。

from openpyxl import load_workbook

# 預設可讀寫,若有需要可以指定write_only和read_only為True
wb = load_workbook('mainbuilding33.xlsx')

預設開啟的檔案為可讀寫,若有需要可以指定引數read_onlyTrue

獲取工作表--Sheet

# 獲得所有sheet的名稱
print(wb.get_sheet_names())
# 根據sheet名字獲得sheet
a_sheet = wb.get_sheet_by_name('Sheet1')
# 獲得sheet名
print(a_sheet.title)
# 獲得當前正在顯示的sheet, 也可以用wb.get_active_sheet()
sheet = wb.active 

獲取單元格

# 獲取某個單元格的值,觀察excel發現也是先字母再數字的順序,即先列再行
b4 = sheet['B4']
# 分別返回
print(f'({b4.column}, {b4.row}) is {b4.value}')  # 返回的數字就是int型

# 除了用下標的方式獲得,還可以用cell函式, 換成數字,這個表示B4
b4_too = sheet.cell(row=4, column=2)
print(b4_too.value)

b4.column返回Bb4.row返回4, value則是那個單元格的值。另外cell還有一個屬性coordinate, 像b4這個單元格返回的是座標B4

獲得最大行和最大列

# 獲得最大列和最大行
print(sheet.max_row)
print(sheet.max_column)

獲取行和列

  • sheet.rows為生成器, 裡面是每一行的資料,每一行又由一個tuple包裹。
  • sheet.columns類似,不過裡面是每個tuple是每一列的單元格。
# 因為按行,所以返回A1, B1, C1這樣的順序
for row in sheet.rows:
    for cell in row:
        print(cell.value)

# A1, A2, A3這樣的順序
for column in sheet.columns:
    for cell in column:
        print(cell.value)

上面的程式碼就可以獲得所有單元格的資料。如果要獲得某行的資料呢?給其一個索引就行了,因為sheet.rows是生成器型別,不能使用索引,轉換成list之後再使用索引list(sheet.rows)[2]這樣就獲取到第三行的tuple物件。

for cell in list(sheet.rows)[2]:
    print(cell.value)

如何獲得任意區間的單元格?

可以使用range函式,下面的寫法,獲得了以A1為左上角,B3為右下角矩形區域的所有單元格。注意range從1開始的,因為在openpyxl中為了和Excel中的表達方式一致,並不和程式語言的習慣以0表示第一個值。

for i in range(1, 4):
    for j in range(1, 3):
        print(sheet.cell(row=i, column=j))
        
# out
<Cell mainbuilding33.A1>
<Cell mainbuilding33.B1>
<Cell mainbuilding33.A2>
<Cell mainbuilding33.B2>
<Cell mainbuilding33.A3>
<Cell mainbuilding33.B3>

還可以像使用切片那樣使用。sheet['A1':'B3']返回一個tuple,該元組內部還是元組,由每行的單元格構成一個元組。

for row_cell in sheet['A1':'B3']:
    for cell in row_cell:
        print(cell)
        

for cell in sheet['A1':'B3']:
    print(cell)

# out
(<Cell mainbuilding33.A1>, <Cell mainbuilding33.B1>)
(<Cell mainbuilding33.A2>, <Cell mainbuilding33.B2>)
(<Cell mainbuilding33.A3>, <Cell mainbuilding33.B3>)

根據字母獲得列號,根據列號返回字母

需要匯入, 這兩個函式存在於openpyxl.utils

from openpyxl.utils import get_column_letter, column_index_from_string

# 根據列的數字返回字母
print(get_column_letter(2))  # B
# 根據字母返回列的數字
print(column_index_from_string('D'))  # 4

將資料寫入Excel

工作表相關

需要匯入WorkBook

from openpyxl import Workbook

wb = Workbook()

這樣就新建了一個新的工作表(只是還沒被儲存)。

若要指定只寫模式,可以指定引數write_only=True。一般預設的可寫可讀模式就可以了。

print(wb.get_sheet_names())  # 提供一個預設名叫Sheet的表,office2016下新建提供預設Sheet1
# 直接賦值就可以改工作表的名稱
sheet.title = 'Sheet1'
# 新建一個工作表,可以指定索引,適當安排其在工作簿中的位置
wb.create_sheet('Data', index=1)  # 被安排到第二個工作表,index=0就是第一個位置

# 刪除某個工作表
wb.remove(sheet)
del wb[sheet]

寫入單元格

還可以使用公式哦

# 直接給單元格賦值就行
sheet['A1'] = 'good'
# B9處寫入平均值
sheet['B9'] = '=AVERAGE(B2:B8)'

但是如果是讀取的時候需要加上data_only=True這樣讀到B9返回的就是數字,如果不加這個引數,返回的將是公式本身'=AVERAGE(B2:B8)'

append函式

可以一次新增多行資料,從第一行空白行開始(下面都是空白行)寫入。

# 新增一行
row = [1 ,2, 3, 4, 5]
sheet.append(row)

# 新增多行
rows = [
    ['Number', 'data1', 'data2'],
    [2, 40, 30],
    [3, 40, 25],
    [4, 50, 30],
    [5, 30, 10],
    [6, 25, 5],
    [7, 50, 10],
]

由於append函式只能按行寫入。如果我們想按列寫入呢。append能實現需求麼?如果把上面的列表巢狀看作矩陣。只要將矩陣轉置就可以了。使用zip()函式可以實現,不過內部的列表變成了元組就是了。都是可迭代物件,不影響。

list(zip(*rows))

# out
[('Number', 2, 3, 4, 5, 6, 7),
 ('data1', 40, 40, 50, 30, 25, 50),
 ('data2', 30, 25, 30, 10, 5, 10)]

解釋下上面的list(zip(*rows))首先*rows將列表打散,相當於填入了若干個引數,zip從某個列表中提取第1個值組合成一個tuple,再從每個列表中提取第2個值組合成一個tuple,一直到最短列表的最後一個值提取完畢後結束,更長列表的之後的值被捨棄,換句話,最後的元組個數是由原來每個引數(可迭代物件)的最短長度決定的。比如現在隨便刪掉一個值,最短列表長度為2,data2那一列(豎著看)的值全部被捨棄。

rows = [
    ['Number', 'data1', 'data2'],
    [2, 40],
    [3, 40, 25],
    [4, 50, 30],
    [5, 30, 10],
    [6, 25, 5],
    [7, 50, 10],
]
# out
[('Number', 2, 3, 4, 5, 6, 7), ('data1', 40, 40, 50, 30, 25, 50)]

最後zip返回的是zip物件,看不到資料的。使用list轉換下就好了。使用zip可以方便實現將資料按列寫入。

儲存檔案

所有的操作結束後,一定記得儲存檔案。指定路徑和檔名,字尾名為xlsx

wb.save(r'D:\example.xlsx')

設定單元格風格--Style

先匯入需要的類from openpyxl.styles import Font, colors, Alignment

分別可指定字型相關,顏色,和對齊方式。

字型

bold_itatic_24_font = Font(name='等線', size=24, italic=True, color=colors.RED, bold=True)

sheet['A1'].font = bold_itatic_24_font

上面的程式碼指定了等線24號加粗斜體,字型顏色紅色。直接使用cell的font屬性,將Font物件賦值給它。

對齊方式

也是直接使用cell的屬性aligment,這裡指定垂直居中和水平居中。除了center,還可以使用right、left等等引數。

# 設定B1中的資料垂直居中和水平居中
sheet['B1'].alignment = Alignment(horizontal='center', vertical='center')

設定行高和列寬

有時候資料太長顯示不完,就需要拉長拉高單元格。

# 第2行行高
sheet.row_dimensions[2].height = 40
# C列列寬
sheet.column_dimensions['C'].width = 30

合併和拆分單元格

所謂合併單元格,即以合併區域的左上角的那個單元格為基準,覆蓋其他單元格使之稱為一個大的單元格。

相反,拆分單元格後將這個大單元格的值返回到原來的左上角位置。

# 合併單元格, 往左上角寫入資料即可
sheet.merge_cells('B1:G1') # 合併一行中的幾個單元格
sheet.merge_cells('A1:C3') # 合併一個矩形區域中的單元格

合併後只可以往左上角寫入資料,也就是區間中:左邊的座標。

如果這些要合併的單元格都有資料,只會保留左上角的資料,其他則丟棄。換句話說若合併前不是在左上角寫入資料,合併後單元格中不會有資料。

以下是拆分單元格的程式碼。拆分後,值回到A1位置。

sheet.unmerge_cells('A1:C3')

這裡就拿常用的說,具體的去看openpyxl文件