本篇文章是圍繞以下四點(diǎn)帶大家學(xué)習(xí)xlwings。
xlwings是什么
xlwings安裝更新與卸載
xlwings詳細(xì)使用
案例分享
1.xlwings是什么
在日常生活中我們或多或少的都會(huì)跟Excel打交道,比如做銷售統(tǒng)計(jì),人力的考勤,學(xué)生的考試成績(jī)等等,甚至在某些領(lǐng)域會(huì)涉及到批量操作Excel表格,那對(duì)于非程序員來說,可能使用Excel中的函數(shù),但是在某種場(chǎng)景下這些又是不好使的,只能熬夜加班啦!但是對(duì)于程序員來說,可能就是分分鐘的事,輕松搞定。
那在我們Python中有哪些模塊(或者第三方庫(kù))可以輕松處理Excel 呢?給大家列出來學(xué)習(xí)一下
哇slwings是不是很香,更詳細(xì)的大家可以去參看趣味干貨中的:Python殺死Excel?眾多模塊哪家強(qiáng),鏈接:https://mp.weixin.qq.com/s/uL6JbxNWUYa7yjUp8aorSA
簡(jiǎn)單介紹下xlwings,xlwings是一個(gè)可以實(shí)現(xiàn)從Excel調(diào)用Python,也可在python中調(diào)用Excel的庫(kù)。開源免費(fèi),一直在更新。特點(diǎn):
1、xlwings支持.xls讀,支持.xlsx文件讀寫。
2、支持Excel操作。
3、支持VBA。
4、強(qiáng)大的轉(zhuǎn)換器可以處理大部分?jǐn)?shù)據(jù)類型,包括在兩個(gè)方向上的numpy array和pandas DataFrame。
文檔鏈接:https://docs.xlwings.org/en/stable/index.html
有沒有發(fā)現(xiàn),xlwings宗旨就是讓Excel飛起來!!!
2.xlwings安裝與使用
安裝
像安裝其他模塊一樣,使用pip安裝即可
pip install xlwings
如果你是在使用Anaconda也可以,使用conda安裝
conda install xlwings
請(qǐng)注意,官方的conda軟件包可能落后于幾個(gè)版本。但是,您可以使用conda-forge通道(如果已經(jīng)安裝了xlwings,請(qǐng)用upgrade替換安裝):
conda install -c conda-forge xlwings
注意:在安裝過程中,xlwings也是有依賴項(xiàng)的,但是依賴項(xiàng)通過conda或pip自動(dòng)安裝
Windows:pywin32
Mac:psutil,appscript
如果原來安裝過,使用如下操作更新
要更新到最新的xlwings版本,請(qǐng)?jiān)诿钐崾痉羞\(yùn)行以下內(nèi)容:
pip install --upgrade xlwings
或者:
conda update -c conda-forge xlwings
通過運(yùn)行以下內(nèi)容(確保先關(guān)閉Excel),確保您的Excel加載項(xiàng)版本與您的Python軟件包保持同步:
xlwings addin install
若要卸載xlwings,移步下面的操作
要完全卸載xlwings,請(qǐng)先卸載加載項(xiàng),然后使用安裝xlwings軟件包時(shí)使用的相同方法(pip或conda)卸載xlwings軟件包:
xlwings addin remove
然后
pip uninstall xlwings
或者:
conda remove xlwings
最后,手動(dòng)刪除個(gè)人文件夾中的.xlwings目錄(如果存在)。
3.xlwings詳細(xì)使用
在我們操作之前可以先了解下,如下內(nèi)容:
• 新建:創(chuàng)建一個(gè)不存在的工作薄或者工作表
• 打開:打開一個(gè)已經(jīng)存在的工作薄
• 引用:就是告訴程序,你要操作哪個(gè)對(duì)象。比如你打開了A、B、C三個(gè)工作薄,現(xiàn)在你想操作A工作薄,就要先引用A
• 激活:我們可以同時(shí)打開多個(gè)工作薄,但是一次只能操作一個(gè)工作簿,我們正在操作的這個(gè)工作薄稱為**當(dāng)前活動(dòng)工作薄。
在xlwings中
• Excel程序用App來表示,多個(gè)Excel程序集合用Apps表示;
• 單個(gè)工作簿用Book表示,工作簿集合用Books表示;
• 單個(gè)工作表用Sheet表示,工作表集合用Sheets表示;
• 區(qū)域用Range表示,既可以是一個(gè)單元格,也可以是一片單元格區(qū)域。
對(duì)Excel進(jìn)行操作主要使用如下三個(gè)類:
import xlwings as xw
xw.App 打開一個(gè)excel應(yīng)用
xw.Book 創(chuàng)建一個(gè)工作薄
xw.Sheet 創(chuàng)建一個(gè)工作表
初試:創(chuàng)建一個(gè)excel表格并保存
import xlwings as xw
# 打開excel,參數(shù)visible表示處理過程是否可視,add_book表示是否打開新的Excel程序
with xw.App(visible=True,add_book=False) as app:
# 創(chuàng)建一個(gè)工作薄
book = app.books.add()
# 工作薄中創(chuàng)建一個(gè)sheet表
sht = book.sheets.add()
# 向表格的A1單元格寫入“Hello Python”
sht.range('A1').value = 'Hello Python'
# 保存
book.save('./test.xlsx')
理解App
App就是我們打開的一個(gè)Excel應(yīng)用,在我們程序員看來一個(gè)App對(duì)象就是一個(gè)Excel的實(shí)例,在此實(shí)例下創(chuàng)建工作薄。因此我們要?jiǎng)?chuàng)建工作簿,就必須先創(chuàng)建App實(shí)例。一個(gè)App實(shí)例可以創(chuàng)建多個(gè)工作簿Book。
使用xlwings可以創(chuàng)建一個(gè)或者多個(gè)App,而每個(gè)App中又可以創(chuàng)建多個(gè)工作薄Book,并且多個(gè)App之間是相互獨(dú)立的。
要使用xlwings就需要先引用該庫(kù)
import xlwings as xw
app=xw.App()
pid = app.pid
print(pid) # 6260就是這個(gè)App的PID
綜合:
import xlwings as xw
app=xw.App()
pid = app.pid
# 就是這個(gè)App的PID
app1=xw.App()
pid1 = app1.pid
print(pid,pid1) # 6260
count = xw.apps.count
print(count)
print(xw.apps.keys())
創(chuàng)建App
我們可以通過xw.app()創(chuàng)建一個(gè)新的app實(shí)例
app=xw.App(visible=True,add_book=False) # 當(dāng)然也可以通過app.visible = True設(shè)置可見性
其中可以設(shè)置參數(shù)visible:用來設(shè)置程序是否可見,True表示可見(默認(rèn)),F(xiàn)lase不可見。addbook用來設(shè)置是否自動(dòng)創(chuàng)建工作簿,True表示自動(dòng)創(chuàng)建(默認(rèn)),F(xiàn)alse不創(chuàng)建。當(dāng)設(shè)置成addbook=False時(shí),可以創(chuàng)建App,但是還未生成PID,只有當(dāng)這個(gè)App創(chuàng)建了工作簿后,才會(huì)生成自己的PID 。
創(chuàng)建成果后可以查看pid
import xlwings as xw
app=xw.App()
pid = app.pid
print(pid) # 6260就是這個(gè)App的PID
綜合:
import xlwings as xw
app=xw.App()
pid = app.pid
# 就是這個(gè)App的PID
app1=xw.App()
pid1 = app1.pid
print(pid,pid1) # 6260
count = xw.apps.count
print(count)
print(xw.apps.keys())
結(jié)果:
可以引用某個(gè)app實(shí)例進(jìn)行操作并激活
app = xw.apps[992]
app.activate() # 或者app.activate(steal_focus=True)
# 當(dāng)steal_focus=True時(shí), Excel程序變?yōu)樽钋芭_(tái)的應(yīng)用,并且把焦點(diǎn)從Python切換到Excel
在操作一個(gè)app對(duì)象的時(shí)候要先引用工作薄,但是引用并不代表激活,激活就是當(dāng)前操作的工作薄。
常用的屬性有:
app.screen_updating:打開屏幕更新,我們可以看到xlwings對(duì)Excel進(jìn)行操作的過程,關(guān)閉更新可以加速腳本運(yùn)行。默認(rèn)是打開的。
app.display_alerts:在使用Excel的過程中,經(jīng)常會(huì)遇到一些提醒信息,比如關(guān)閉前的保存提示、數(shù)據(jù)有效性的警告窗口,若想隱藏這些窗口可以設(shè)置成False。如果提醒信息是需要反饋的,Excel會(huì)選擇默認(rèn)的方式True
import xlwings as xw
app = xw.App(visible=False, add_book=False) # 界面設(shè)置
app.display_alerts = False # 關(guān)閉提示信息
app.screen_updating = False # 關(guān)閉顯示更新
wb = app.books.add() # 創(chuàng)建新的工作簿
sht = wb.sheets['Sheet1'] # 實(shí)例化工作表
sht.range('A1').value = 'Hello World!'
print(sht.range('A1').value) # 讀取
wb.close()
app.kill()
其中關(guān)閉app有兩種方式,通過測(cè)試使用kill()函數(shù)更快些。
app.kill():通過殺掉進(jìn)程,強(qiáng)制Excel app退出
app.quit():退出excel程序,不保存任何工作簿
工作簿Book與Books
前面介紹了app,并且一個(gè)app可以包含多個(gè)工作薄,如何在app中創(chuàng)建工作薄呢?
創(chuàng)建Book對(duì)象
官方給出的創(chuàng)建工作薄的方式如下:
兩種方式的區(qū)別:方式1是創(chuàng)建一個(gè)新的App,并在新App中新建一個(gè)Book,方式2是在當(dāng)前App下新建一個(gè)Book
如果是打開一個(gè)已經(jīng)存在的則使用:
wb = app.books.open('絕對(duì)或者相對(duì)路徑的excel文件')
'或者
wb = xw.Book('絕對(duì)或者相對(duì)路徑的excel文件')
其中創(chuàng)建Book對(duì)象的參數(shù)如下:
Book(fullname=None, updatelinks=None, readonly=None, format=None,
password=None, writerespassword=None, ignorereadonlyrecommended=None,
origin=None, delimiter=None, editable=None, notify=None, converter=None,
addtomru=None, local=None, corruptload=None, impl=None)
詳細(xì)情況可以參考文檔:https://docs.microsoft.com/zh-cn/office/vba/api/excel.workbooks.open
xw.Book('絕對(duì)或者相對(duì)路徑的excel文件')既可以打開工作薄也可以引用工作簿。
激活與保存
wb.activate()
# 如果steal_focus=True, 則把窗口顯示到最上層,并且把焦點(diǎn)從Python切換到Excel
wb.activate(steal_focus=True)
保存工作薄:
wb.save()
# 或者使用指定路徑保存
wb.save('存儲(chǔ)路徑')
關(guān)閉
關(guān)閉工作薄也很簡(jiǎn)單,就是使用wb.close(),注意:wb.close()只是關(guān)閉并不會(huì)保存,所以在關(guān)閉之前必須要使用save()進(jìn)行一下保存才可以??梢钥紤]使用with搭建上下文,實(shí)現(xiàn)關(guān)閉資源。
import xlwings as xw
app=xw.App(visible=True,add_book=False)
app.display_alerts=False
app.screen_updating=False
# 文件位置:filepath,打開test文檔,然后保存,關(guān)閉,結(jié)束程序
filepath=r'test.xlsx'
wb=app.books.open(filepath)
wb.save()
wb.close()
app.quit()
若想獲取當(dāng)前活動(dòng)App中的所有books,可以直接通過下列方式
import xlwings as xw
# 當(dāng)前活動(dòng)App的工作簿集合
books = xw.books
# 或者使用app.books獲取
# books = app.books
工作表Sheet與查看所有Sheets
新建Sheet
sht = wb.sheets.add()
# 或者
sht = wb.sheets.add('test',after='sheet2')
參數(shù)1為工作表名稱,省略的話為Excel默認(rèn)名稱,參數(shù)2為插入位置,可選before或者after
若想引用某一個(gè)Sheet,可以通過下面方式
sht = wb.sheets('sheet1') # 指定名稱獲取sheet工作表
sht = wb.sheets(1) # 根據(jù)序號(hào)獲取
sht = xw.sheets.active #獲取當(dāng)前活動(dòng)的工作表
import xlwings as xw
app=xw.App(visible=True,add_book=False)
app.display_alerts=False
app.screen_updating=False
# 文件位置:filepath,打開test文檔,然后保存,關(guān)閉,結(jié)束程序
filepath=r'test.xlsx'
wb=app.books.open(filepath)
# add()是在現(xiàn)有的sheets集合列表中追加新的Sheet
sht1 = wb.sheets.add()
sht2 = wb.sheets.add()
print(wb.sheets.count)
sht3 = wb.sheets(1)
# sht1.activate()
sht3.range('A1').value = 'Hello Running'
wb.save('test1.xlsx')
wb.close()
app.quit()
sheet對(duì)象可以調(diào)用的方法有:
sheet.activate sheet.charts sheet.index
sheet.api sheet.clear sheet.name
sheet.autofit sheet.clear_contents sheet.names
sheet.book sheet.delete sheet.pictures
sheet.cells sheet.impl sheet.range
......
常用的有:
# 清除工作表所有內(nèi)容和格式
sht.clear()
# 清除工作表的所有內(nèi)容但是保留原有格式
sht.clear_contents()
# 刪除工作表
sht.delete()
# 自動(dòng)調(diào)整行高列寬
sht.autofit('c')
# 在活動(dòng)工作簿中選擇
sht.select()
可以通過屬性獲取獲取工作表的名稱、所有單元格的區(qū)域?qū)ο?/font>、當(dāng)前工作表的索引值
sht.name sht.cells sht.index sht.names
引用區(qū)域與單元格操作
在操作區(qū)域或者單元格之前,首先就要引用他們,其實(shí)就是表明你要操作的區(qū)域或者單元格是哪些??梢哉J(rèn)為區(qū)域是多個(gè)單元格。
引用區(qū)域的方式有很多種,下面列舉一下常見的引用方式:
xw.Range('A1:D4')
xw.Range((1,1), (4,4))
xw.Range(xw.Range('A1'),xw.Range('D4'))
xw.Range(xw.Range('A1:E6'),xw.Range('C3:D7'))
xw.Range('NamedRange')
app.range("A1") # 注意是小寫的range
sht.range('A1')
xw.books['MyBook.xlsx'].sheets[0].range('A1')
sht['A1']
sht['A1:D4']
sht[0,5]
sht[:5,:5]
區(qū)域管理可以通過如下方式:
range.offset(rowoffset=5,columnoffset=2) 表示偏移,rowoffset行偏移量(正數(shù)表示向下偏移,負(fù)數(shù)相反),columnoffset列偏移量(正數(shù)表示向右偏移,負(fù)數(shù)相反)
注意:是將選區(qū)范圍進(jìn)行偏移,內(nèi)容不進(jìn)行偏移
range.expand(mode='down') 擴(kuò)展區(qū)域,參數(shù)可選取 'down' , 'right' ,'table' ,類似我們使用向下、向右或者下右方的區(qū)域擴(kuò)展操作。
range.resize(rowsize=4, columnsize=2) 表示調(diào)整選中區(qū)域的大小,參數(shù)表示調(diào)整后區(qū)域的行、列的數(shù)量。
range.current_region 表示全選 類似Ctrl + A
對(duì)區(qū)域或單元格進(jìn)行操作:
存儲(chǔ)數(shù)據(jù)
儲(chǔ)存單個(gè)值
# ".value“屬性
sht.range('A1').value=1
儲(chǔ)存列表
# 將列表[1,2,3]儲(chǔ)存在A1:C1中
sht.range('A1').value=[1,2,3]
# 將列表[1,2,3]儲(chǔ)存在A1:A3中
sht.range('A1').options(transpose=True).value=[1,2,3]
# 將2x2表格,即二維數(shù)組,儲(chǔ)存在A1:B2中,如第一行1,2,第二行3,4
sht.range('A1').options(expand='table').value=[[1,2],[3,4]]
讀取數(shù)據(jù)
讀取單個(gè)值
# 將A1的值,讀取到a變量中
a=sht.range('A1').value
將值讀取到列表中
#將A1到A2的值,讀取到a列表中
a=sht.range('A1:A2').value
# 將第一行和第二行的數(shù)據(jù)按二維數(shù)組的方式讀取
a=sht.range('A1:B2').value
清除與刪除
# 清除range的內(nèi)容
rng.clear_contents()
# 清除格式和內(nèi)容
rng.clear()
# 刪除
rng.delete(shift=None)
其他設(shè)置
# 獲取數(shù)字格式
rng.number_format
# 設(shè)置數(shù)字格式
rng.number_format = '0.00%'
rng.insert(shift=None, copy_origin='format_from_left_or_above')
# 返回區(qū)域第一行的行號(hào)
rng.row
# 返回區(qū)域的第一列的號(hào),注意返回的列號(hào)不是ABCD,而是1234
rng.column
# 獲取行高 或者設(shè)置行高
rng.row_height
rng.row_height = 20
# 獲取列寬或設(shè)置列寬
rng.column_width
rng.column_width = 20
# 自適應(yīng)行高列寬
rng.autofit()
rng.columns.autofit()
rng.rows.autofit()
# 合并單元格
rng.merge(across=False)
rng.merge_area # 返回合并單元格區(qū)域
rng.merge_cells # 返回True或者False,測(cè)試是否在合并單元格區(qū)域
rng.unmerge() # 取消單元格合并
# 背景色
rng.color # 獲取指定區(qū)域的背景色
xw.Range('A1').color = (255,255,255) # 設(shè)置背景色
xw.Range('A2').color = None # 去除背景色
其他參考
range.add_hyperlink range.clear_contents range.count
range.address range.color range.current_region
range.api range.column range.end
range.autofit range.column_width range.expand
range.clear range.columns range.formula
...等等
range.add_hyperlink('https://www.baidu.com','百度')
range.color = (128,128,128) RGB通道顏色,可獲取or設(shè)置
range.row/column 獲取第幾行/列,注意是第幾而不是下標(biāo)
range.formula 可以設(shè)置計(jì)算表達(dá)式,用來進(jìn)行表內(nèi)計(jì)算
range.current_region 返回當(dāng)前range所在區(qū)域的區(qū)域表達(dá),這個(gè)比較難描述,好比一個(gè)Excel中互相連接的單元格都是連城一片,兩個(gè)片之間沒有任何相鄰就是互相獨(dú)立的。
range.count 返回這個(gè)range中共有多少單元格,合并單元格仍然按未合并的算
range.offset(a,b) 獲取到當(dāng)前range向右a格,向下移動(dòng)b格同樣大小的那片區(qū)域,ab可以為負(fù)值
range.rows/columns 返回行/列的各個(gè)range對(duì)象
range.expand
參考案例代碼:
批量寫入并讀取數(shù)據(jù)
import xlwings as xw
wb = xw.Book()
sht = wb.sheets.active
# 向工作表中寫入行列值
for i in range(1, 6):
for j in range(1, 6):
sht.range(i, j).value = '({}, {})'.format(i, j)
print(sht.range((1, 1), (5, 5)).expand().value) # 批量讀取
print(sht.range(1, 1).expand('right').value) # 按行讀
print(sht.range(1, 1).expand('down').value) # 按列讀
wb.close()
提前設(shè)置好表格的顏色,如圖
import xlwings as xw
from itertools import product
app = xw.App(visible=False) # 隱藏Excel
wb = app.books.open('test.xlsx') # 打開工作簿
sht = wb.sheets['Sheet1'] # 實(shí)例化工作表
for cell in list(map(''.join, product('ABCDEFGH', '1'))): # A1 B1 C1 D1 E1 F1 G1 H1
print(cell, sht.range(cell).color) # 填充顏色
wb.close()
局中插入圖片
截屏2021-11-22 下午8.40.22
import os
import xlwings as xw
wb = xw.Book()
sht = wb.sheets['Sheet1']
rng = sht.range('A1')
fileName = os.path.join(os.getcwd(), 'aa.png')
width, height = 120, 100 # 指定圖片大小
left = rng.left + (rng.width - width) / 2 # 居中
top = rng.top + (rng.height - height) / 2
sht.pictures.add(fileName, left=left, top=top, width=width, height=height)
wb.save('test2.xlsx')
wb.close()
綜合案例:
import xlwings as xw
wb = xw.Book()
sht = wb.sheets[0]
info_list = [['110202111111234','帳篷',5],
['110202111118891','行李箱','16'],
['110202111111004','微波爐','20'],
['110202111132741','電冰箱','13'],
['110202111109852','樂事薯片','30'],
['110202111112030','魯花花生油','12'],
['110202111190391','羽絨服','9'],
['110202111122319','防曬霜','18'],
]
# 寫入表頭
titles = [['商品編號(hào)','商品名稱','數(shù)量']]
sht.range('a1').value = titles
# 寫入數(shù)據(jù)
sht.range('a2').value = info_list
# 保存數(shù)據(jù)
wb.save('goods.xlsx')
若想更新里面的數(shù)據(jù),由于有些商品被賣出,商品數(shù)量就會(huì)發(fā)生變化。另外還有一批貨是新引入的。參考代碼如下:
import xlwings as xw
wb = xw.Book()
sht = wb.sheets[0]
info_list = [['110202111111234','帳篷','5'],
['110202111118891','行李箱','16'],
['110202111111004','微波爐','20'],
['110202111132741','電冰箱','13'],
['110202111109852','樂事薯片','30'],
['110202111112030','魯花花生油','12'],
['110202111190391','羽絨服','9'],
['110202111122319','防曬霜','18'],
]
# 寫入表頭
titles = [['商品編號(hào)','商品名稱','數(shù)量']]
sht.range('a1').value = titles
# 寫入數(shù)據(jù)
sht.range('a2').value = info_list
# 保存數(shù)據(jù)
wb.save('goods.xlsx')
# 讀取數(shù)據(jù)
goods_list = sht.range('a2').expand('table').value
for goods in goods_list:
goods[0] = str(int(goods[0]))
goods[2] = int(goods[2])
print(goods_list)
new_info = [['110202111111234','帳篷',5],
['110202111118891','行李箱',16],
['110202111111004','微波爐',20],
['110202111132741','電冰箱',10],
['110202111124660','羊毛衫',8],
['110202111109852','樂事薯片',10],
['110202111112030','魯花花生油',12],
['110202111190391','羽絨服',0],
['110202111122319','防曬霜',9],
['110202111124560','牛仔褲',18],
['110202111134798','老爹鞋',11]]
# 去重
extra = [i for i in new_info if i not in goods_list]
# print(extra)
# 讀取extra每個(gè)商品的包裹號(hào),判斷是否存在并更新,然后添加
ids = sht.range(2, 1).expand('down').value
ids = [str(int(id)) for id in ids]
rows = len(sht.range('a2').expand('table').value)
# 更新已有數(shù)據(jù)的庫(kù)存
for goods in extra:
if goods[0] in ids:
row_number = ids.index(goods[0])
print(row_number,goods[1])
sht[row_number+1,2].value = goods[2]
else:
for i in range(3):
sht[rows+1,i].value =goods[i]
rows+=1
wb.save('goods.xlsx')
結(jié)果:
更多關(guān)于python培訓(xùn)的問題,歡迎咨詢千鋒教育在線名師。千鋒教育擁有多年IT培訓(xùn)服務(wù)經(jīng)驗(yàn),采用全程面授高品質(zhì)、高體驗(yàn)培養(yǎng)模式,擁有國(guó)內(nèi)一體化教學(xué)管理及學(xué)員服務(wù),助力更多學(xué)員實(shí)現(xiàn)高薪夢(mèng)想。