Python 在辦公自動化中的簡單應用 - 少數派#
#Omnivore
Matrix 首頁推薦
Matrix 是少數派的寫作社區,我們主張分享真實的產品體驗,有實用價值的經驗與思考。我們會不定期挑選 Matrix 最優質的文章,展示來自用戶的最真實的體驗和觀點。
文章代表作者個人觀點,少數派僅對標題和排版略作修改。
前言#
這篇文章的初衷是想讓更多的人能夠快速入門 Python 在辦公自動化中的簡單應用,最初的設想是每個應用場景都用不超過十行代碼來做演示,但是實際寫下來發現十行的篇幅還是小了點。為了達成目標,我臨時寫了個簡單的包傳到了 pypi 上,包裡面封裝了一些辦公中常用的功能,本篇文章中的相關腳本主要會結合這個工具包進行講解。
這個包中的許多函數為了易用性犧牲了靈活性,主要目的是想讓大家先用起來,體會到了便利才有更進一步學習的動力。等能夠熟練寫出和文中類似的腳本之後,可以直接看我包中的源碼進一步學習,裡面都是些比較典型的例子。
因為代碼中會使用到部分 windows 系統獨有的第三方包,所以如果你使用的是 macOS 之類的系統可能無法復現所有示例。
Python 是一種面向對象的腳本語言,它算是目前最容易學習的編程語言之一。如果大學學過 C 語言的話,入門 Python 可以說是輕輕鬆鬆。就算從來沒有接觸過編程的人,也可以在短時間內學會使用方法。這一點我不是亂說的,我曾經給同事培訓過,肯學的那部分人幾次會議就能初步上手使用了。當然,培訓之後肯定是要自己複習鞏固的,掌握新技能總是要投入時間和精力的,這點相信大家都明白。
閱讀基礎#
本篇文章主要是講應用實例,對於 Python 的基礎語法並不會進行介紹,所以在正式閱讀後面的內容之前,讀者需要先自行熟悉一下 Python 的基礎知識,不需要多深入,但是基本的數據類型、循環和條件控制、函數和類的基本概念是一定要掌握的。如果不知道從何學起的話建議去看菜鳥教程中的 Python 3 教程,耐心跟著教程敲一遍裡面的代碼實例。如果在學習的過程中碰到什麼無法理解的高級特性,不需要糾結,直接跳過就行。
學習本文時,理論上裝好 Python 環境後有個文本編輯器就可以進行,但是如果想要有更好的編程體驗的話,建議安裝 PyCharm 這一免費 Python 集成開發工具。
注意:為了確保後續教程能夠正常進行,請安裝 3.8 以上的 Python 環境,同時如果官方的 pip 源下載過慢的話可以在網上查找換源教程將其換為國內源。
安裝依賴#
使用如下命令先安裝好後續示例中會用到的第三方包:
pip install xoffice pandas openpyxl
路徑相關#
因為本篇的重點在於批量化操作,所以遍歷文件是避不開的基礎內容。這裡我會介紹兩種方式,第一種比較簡單,請務必掌握;第二種稍微難一點,看不懂的話可以先放著,後面基礎牢固了再考慮使用。
glob.glob()#
將 rename 文件夾中的所有 png 文件重命名為數字編號的文件。
import glob
import os
if __name__ == '__main__':
# 重命名時會用到的編號
index = 1
for file in glob.glob("rename/*.png"):
# 將路徑拆分為文件夾路徑和文件名兩部分
dir_path, file_path = os.path.split(file)
# 將文件名拆分為基礎名稱和拓展名
base_name, ext = os.path.splitext(file_path)
# 將文件重命名為 0001.png 這樣的格式
os.rename(file, os.path.join(dir_path, "%04d" % index + ext))
# 效果等同於 index = index + 1
index += 1
glob.glob()
這個函數用法非常簡單,可以遍歷一個目錄層級內的所有路徑名稱,並且還支持最簡單的正則表達式過濾,主要規則如下:
- ”*” :匹配 0 個或多個字符;
- “?”:匹配單個字符;
- “[]”:匹配指定範圍內的字符,如:[0-9] 匹配數字。
平常使用的時候其實一個 “” 就夠了,“*.ext” 匹配指定格式的文件;“.*” 匹配所有帶拓展名的文件,過濾掉文件夾;“*” 匹配所有文件或文件夾。
默認情況下這個函數只能遍歷一個文件夾內的文件,對於子文件夾中的文件無法遍歷,但是可以通過設置recursive=True
來達到遞歸遍歷的目的,此時需要搭配 “**” 來使用,它可以代表任意層級的目錄。
for file in glob.glob("rename/**/*", recursive=True):
print(file)
輸出結果:
rename\0001.png
rename\0002.png
rename\0003.png
rename\0004.png
rename\0005.png
rename\deep_dir
rename\deep_dir\Snipaste_2021-08-31_22-45-16.png
rename\deep_dir\Snipaste_2021-08-31_22-45-57.png
rename\deep_dir\Snipaste_2021-08-31_22-48-29.png
rename\deep_dir\Snipaste_2021-08-31_22-48-37.png
rename\deep_dir\Snipaste_2021-08-31_22-48-52.png
對於初學者而言後面遞歸遍歷的寫法搞不懂也沒關係,會用 “*” 進行最簡單的單一目錄層級遍歷就夠了。
最後有一個注意點,glob.glob()
遍歷出來的文件順序是固定的,一般等同於在文件管理器中按照名稱遞增排序的結果,在某些對文件順序敏感的場合使用時需要添加額外的排序代碼。
os.walk()#
這個函數有點繞,先看一個示例:
import os
if __name__ == '__main__':
for root, dirs, files in os.walk("rename", topdown=False):
for name in files:
print(os.path.join(root, name))
for name in dirs:
print(os.path.join(root, name))
輸出結果:
rename\deep_dir\Snipaste_2021-08-31_22-45-16.png
rename\deep_dir\Snipaste_2021-08-31_22-45-57.png
rename\deep_dir\Snipaste_2021-08-31_22-48-29.png
rename\deep_dir\Snipaste_2021-08-31_22-48-37.png
rename\deep_dir\Snipaste_2021-08-31_22-48-52.png
rename\0002.png
rename\0003.png
rename\0004.png
rename\0005.png
rename\0006.png
rename\deep_dir
先說基礎概念:
- root 所指的是當前正在遍歷的這個文件夾的本身的地址;
- dirs 是一個 list ,內容是該文件夾中所有的目錄的名字 (不包括子目錄);
- files 同樣是 list , 內容是該文件夾中所有的文件 (不包括子目錄)。
結合上面的例子理解,root 依次是 “rename\deep_dir” 和 “rename”,而 dirs 和 files 中則是 root 目錄下的文件夾列表和文件列表。可以注意到上面代碼中的topdown=False
,這個參數如果為True
,代表優先遍歷頂層目錄,反之則是優先遍歷子文件夾。所以如果上面代碼中的topdown=True
,那麼 root 的次序就會變為 “rename” 和 “rename\deep_dir”。不指定該參數時默認為優先遍歷頂層目錄,沒有特殊需求的話省略該參數保持默認即可。
這個函數其實還有另外幾個可選參數,但是很少用到,後面有需要的話可以自行學習。
PDF 相關#
從這一節開始就是一些我以前用到過的辦公自動化實例了,都是一些比較基礎的應用,更複雜的應用就需要特別定制了,本篇文章不會涉及。
圖片轉 PDF#
不知道大家有沒有碰到過需要批量掃描文件歸檔的場景,雖然現在很多時候可以通過手機軟件拍攝解決,但是正經歸檔的文件還是用專業的掃描儀效果更好。掃描儀掃出來的一般是圖片的格式,有些掃描儀自帶合成軟件,可以把掃出來的圖片轉成 PDF 文件,有些則需要自己在 Adobe Acrobat 之類的 PDF 軟件中手動轉換。單份的文件掃描轉換其實用這些圖形化軟件也不算費事,但是當需要一次掃一下午文件的時候,手動轉換就著實是一種折磨。
這裡會用到我封裝的包中的一個函數,先給出函數定義:
def img_to_pdf(
dir_path: str,
free: bool = False,
size: Sequence = None,
compress: bool = False,
compress_target: int = 200,
out_path: str = None
):
"""
圖片轉 pdf 文件
:param dir_path: 圖片所在文件夾,文件夾中圖片請按照順序編號,例如 0001.jpg、0002.jpg
:param free: 设为 True 后,页面尺寸随图片尺寸动态变化,两者始终保持一致
:param size: 页面尺寸,A0~A6,A0_L~A6_L,默认 A4
:param compress: 设为 True 后,对图片进行压缩,降低图片质量。开启此功能会大幅延长 pdf 文件生成时间
:param compress_target: 图片压缩的目标体积,kB
:param out_path: 输出的 pdf 文件地址,为空时默认在图片文件夹所在目录下创建同名 pdf 文件
:return:
"""
示例腳本的功能是遍歷 pdf 文件夾中所有的文件夾名稱,依次生成與文件夾名稱相同的 PDF 文件。
import glob
from xoffice import img_to_pdf
from xoffice.pdf import A4
if __name__ == '__main__':
for path in glob.glob("pdf/*"):
img_to_pdf(path, size=A4)
PDF 轉圖片#
這個用到的場景比較少,一般是發給在外面不方便開電腦的同事臨時查看時可能用到。
這裡先給出函數定義:
def pdf_to_img(
file_path: str,
index: Sequence[int] = None,
out_dir: str = None,
zoom_x: float = 4,
zoom_y: float = 4,
rotation_angle: float = 0
):
"""
pdf 文件轉為 png 圖片
:param file_path: pdf 文件路徑
:param index: 可以指定將哪些頁面轉為圖片,序號從 0 開始,默認為所有頁面
:param out_dir: 輸出文件夾,默認在 pdf 文件所在文件夾創建同名文件夾保存圖片
:param zoom_x: x 軸縮放尺寸
:param zoom_y: y 軸縮放尺寸
:param rotation_angle: 頁面旋轉角度,順時針為正
:return:
"""
示例腳本的功能是將 p1.pdf 文件轉為圖片格式。
from xoffice import pdf_to_img
if __name__ == '__main__':
pdf_to_img("pdf/p1.pdf")
郵件相關#
日常工作稍微正式一點的場合都有可能用到郵件,郵件有個好處就是可以留痕,後期可以防止相當多無意義的扯皮環節。大部分情況下用代碼發郵件毫無意義,除非是批量發送大量模板相同的通知郵件,因為我以前碰到過,所以也在這裡做個示範。
Python 中發郵件的包特別多,官方的、第三方的都有。官方的就是 smtplib 搭配 email,非官方的有 zmail、yagmail 等。下面要演示的是我自己對官方包封裝後的類,主要是用於演示,追求穩定的話推薦使用上面提到的第三方庫。
在正式開始之前需要給大家科普一些代發郵件的基礎知識。代發郵件也需要驗證用戶名和密碼,不過這裡的密碼不是正常在網頁端登錄時的密碼,而是郵箱授權碼,這個授權碼如何獲得需要自己去對應郵箱的幫助說明中查找。給出 QQ 和新浪兩個最常見郵箱的相關說明鏈接:
先給出類和函數的定義:
class EMail(object):
"""
用於發送郵件
"""
def __init__(self, user: str, password: str, host: str = None, port: int = 465, ssl: bool = True):
"""
初始化
:param user: 郵箱賬號
:param password: 郵箱授權碼
:param host: 服務器地址
:param port: 服務器端口
:param ssl: 是否 ssl 加密傳輸
"""
def connect(self):
"""
連接郵箱服務器
:return:
"""
def close(self):
"""
斷開郵箱服務器
:return:
"""
def send(self, to: Union[str, Sequence[str]], title: str, content: str, attachments: Sequence[str] = None):
"""
普通版發送郵件,使用時需要結合 connect 和 close 方法
:param to: 收件人,可以多人
:param title: 郵件主題
:param content: 郵件內容
:param attachments: 郵件附件,給出附件地址即可
:return:
"""
def easy_send(self, to: Union[str, Sequence[str]], title: str, content: str, attachments: Sequence[str] = None):
"""
簡易版發送郵件,將連接和斷開服務器整合在了一起,發送單份郵件時使用
:param to:
:param title:
:param content:
:param attachments:
:return:
"""
def md_to_html(text: str, css: str = None) -> str:
"""
md 格式文本轉 html 字符串
:param text: 待轉換 md 格式字符串
:param css: css 文件
:return:
"""
示例腳本的功能是將一篇 markdown 格式的文本轉為 html 格式發送到指定郵箱。這個功能目前只能說是能用,因為不同的郵箱支持 html 的程度不同,所以不一定能保證最終呈現效果都是一致的。
from xoffice import EMail
from xoffice.utils import md_to_html
if __name__ == '__main__':
e = EMail("user@qq.com", "password")
with open("test.md", "r", encoding="utf-8") as f:
e.easy_send(["to_user@sina.com"], "測試主題", md_to_html(f.read()), ["pdf/p1/1.png"])
Excel 相關#
從這一節開始就是重頭戲了,但是 Excel 和 Word 相關的操作太多了,展開來講太大了,幾萬字也不一定能說明白,我這裡只介紹幾個最基礎最常用的自動化操作。我在下面幾節中主要使用的是 pywin32,直接調用 windows 系統的 api 接口操作 office 軟件。這樣操作其實和直接寫 VBA 宏差別不大,所以所有的操作都可以去微軟官網的開發文檔中查找。
其實有相當多接口更加簡潔好用的第三方庫可以操縱這些 office 文檔,我在這裡之所以不用,是因為有些保密意識較強的單位內部文件會加密,只能以加密電腦上的 office 軟件才能正常打開,碰到過的朋友應該都能理解。
這裡先介紹一個場景,工作中難免會碰到一些數據匯總的雜活,具體表現形式就是群裡發一張表讓每個人填寫,最後統一發給專人匯總成一張總表。這種表格現在也可以通過雲文檔的方式實現匯總,給所有人權限讓他們自己到總表中去填寫數據,但終究有其局限性,畢竟有許多信息並不能對所有人透明。人數少的話一份一份打開複製粘貼也花不了太久,但是如果規模擴大的話,純人力就多少有點浪費時間了。
先給出類的定義:
class Excel:
"""
Excel 常用自動化操作,主要是為了配合 Word 使用,因此只封裝了獲取數據的方法
"""
def __init__(self, path: str, display_alerts: bool = False, visible: bool = True):
"""
初始化
:param path:
:param display_alerts: 覆蓋保存時是否出現警告提示
:param visible: 程序窗口是否可見
"""
def close(self):
"""
關閉文檔,退出應用程序
:return:
"""
def get_value(self, sht_name: Union[int, str], index: str):
"""
獲取指定單元格內數據
:param sht_name:
:param index:
:return:
"""
def get_text(self, sht_name: Union[int, str], index: str):
"""
獲取指定單元格內數據,統一轉為文本格式
:param sht_name:
:param index:
:return:
"""
def get_comment(self, sht_name: Union[int, str], index: str):
"""
獲取指定單元格的批註
:param sht_name:
:param index:
:return:
"""
def copy_chart(self, sht_name: Union[int, str], index: int):
"""
複製指定圖表
:param sht_name:
:param index: 圖表序號
:return:
"""
def copy_shape(self, sht_name: Union[int, str], index: Union[str, int]):
"""
複製指定圖片,這裡要注意,圖表也會算在其中,使用序號時務必小心
:param sht_name:
:param index: 可以為圖片的名稱或其序號,此處的圖片只能為浮動式圖片
:return:
"""
示例腳本的功能是將 excel 中所有表格文件中的 A2、B2、C2 單元格的數據匯總到 results.xlsx 文件中。
import glob
import pandas as pd
from xoffice import Excel
if __name__ == '__main__':
results = []
for file in glob.glob("excel/*"):
with Excel(file, visible=False) as e:
data = [
e.get_value("Sheet1", "A2"),
e.get_value("Sheet1", "B2"),
e.get_value(0, "C2"),
]
results.append(data)
df = pd.DataFrame(results, columns=["a", "b", "c"])
df.to_excel("excel/results.xlsx", index=False)
上面這個腳本如果用 xlwings 實現起來會更加簡單,想進一步學習 Excel 自動化的話建議好好看看它的官方文檔。
Word 相關#
Word 相關的自動化基本只有一種訴求,就是根據模板批量生產報告之類的文檔。其實 Word 軟件本身就帶有這樣的功能,就是名字比較讓人誤解,那就是郵件合併。通過導入外部表格之類的數據源,向 Word 模板之中插入郵件合併域,每一行數據都能生成一份對應的文檔。如果只是簡單的文本數據替換的話,建議大家直接使用軟件自帶的圖形界面處理,還能預覽,簡單又好用,唯一麻煩的就是需要匯總到 Excel 表格裡中轉一下。
我這裡會給出兩種可選的代碼方案,一種是使用郵件合併,另一種是使用 pywin32,後者不僅支持文本的替換,還支持圖表的插入。
generate_docx_by_mailmerge#
先介紹一下郵件合併域的插入方法,這裡以 WPS 為例,選擇 “插入 - 文檔部件 - 域”,在出現的選項卡中選擇郵件合併這一域名,然後在右邊的域代碼中隨便填一個用來標記的字符串即可。
先給出函數的定義:
def generate_docx_by_mailmerge(contents: dict, template: str, output: str):
"""
以郵件合併的方式快速生產 docx 文檔
:param contents: 要替換到模板中的內容
:param template: 文檔模板
:param output: 輸出文件路徑
:return:
"""
示例腳本的功能是以代碼內字典中的數據完成對模板中郵件合併域的替換。
from xoffice import generate_docx_by_mailmerge
if __name__ == '__main__':
contents = {
"頁眉": "炜智能",
"文本框": "編號",
"標題": "測試123",
"正文": "abc",
"表格a": [
{"表格a": 1, "表格b": 2, "表格c": 3},
{"表格a": 2, "表格b": 3, "表格c": 4},
{"表格a": 3, "表格b": 4, "表格c": 5},
{"表格a": 4, "表格b": 5, "表格c": 6},
]
}
generate_docx_by_mailmerge(contents, "word/mailmerge.docx", "word/output.docx")
Python 中有許多第三方庫可以完成這樣的操作,類似 docx-mailmerge、docx-mailmerge2 等都可以做到,我這裡只是對它們中的函數進行了簡單的封裝作為演示,方便大家上手。這裡唯一需要注意的是表格中的郵件合併域,可以看到使用腳本是可以根據數據自動增加表格的行數的。
郵件合併這種功能其實我本人是很少用腳本來實現的,因為如果是簡單的數據完全可以用 Excel 表格來匯總,如果是需要經過複雜運算的數據我也習慣先以表格的形式將結果存儲下來,有了表格數據的前提下直接用 Word 軟件中的圖形界面操作也不算麻煩。
excel2word#
下面介紹一種我以前經常用的自動化出報告的方法。以前經常出那種標準的實驗報告,報告的模板是固定的,整篇報告都是各種表格、圖表、樣品圖片等,而且因為數據都需要先經過 Excel 處理,所以每種實驗的報告數據都有一個固定的 Excel 處理模板。每次填完 Excel 表格之後還要手動把數據、圖表等再複製到 Word 模板中。說實話,填了一次之後我就完全不想填了。我很自然地就有了一個想法,填完 Excel 表格之後,讓腳本根據那個 Excel 表格以及 Word 模板直接生成一份報告。
先給出用到類的定義:
class Word:
"""
Word 自動化常用操作
"""
def __init__(self, path: str, display_alerts: bool = False, visible: bool = True):
"""
初始化
:param path: Word 文件地址
:param display_alerts: 覆蓋保存時是否出現警告提示
:param visible: 程序窗口是否可見
"""
def close(self):
"""
關閉文檔,退出應用程序
:return:
"""
def save(self, path: str):
"""
另存為文件
:param path:
:return:
"""
@property
def text(self) -> str:
"""
獲取文檔中所有字符串,包括正文、頁眉頁腳、Shape 內文本
:return:
"""
def replace_text(self, key: str, value: str):
"""
替換文檔中的指定文本
:param key:
:param value:
:return:
"""
def replace_content_inline_shape(self, key: int, value: str):
"""
替換文檔主體內容中指定序號的內嵌圖形,保持替換圖片的寬度與原始圖片相等
:param key: 需要替換的內嵌圖形在文檔中的序號,從 0 開始
:param value: 用於替換的圖片路徑
:return:
"""
def select_content_text(self, text: str):
"""
選中文檔主體內容中的指定文本,搭配 paste 使用可以完成 office 軟件間的部分互動
:param text:
:return:
"""
def paste(self):
"""
執行粘貼操作
:return:
"""
def set_content_inline_shape_size(self, index: int = None, width: float = None, height: float = None):
"""
保持圖片長寬比的前提下設置指定序號的內嵌圖像的寬度
:param index: 序號從 0 開始
:param width: 圖片寬度,單位為 cm
:param height: 圖片高度,單位為 cm
:return:
"""
上面這個類結合之前在 Excel 中提到的那個類,兩者結合一下就能很簡單的實現最初提到的需求。思路很簡單,先規定好 Word 模板中的標識符,比如{{ 0/A1 }}
代表 Excel 表格中第一張 Sheet 表的 A1 單元格中的數據(Python 中索引從 0 開始),{{ Sheet1/A2 }}
代表名為 Sheet1 的 Sheet 表中的 A2 單元格數據,{{ Sheet2/s:weizhineng }}
代表名為 Sheet2 的 Sheet 表中名為 weizhineng 的浮動式圖片,{{ 1/c:0 }}
代表第二張 Sheet 表中第一張插入的圖表;然後讓腳本讀取 Word 模板中的這些標識符,解析標識符的含義後到 Excel 表格中指定的位置查找目標數據,然後把這些數據粘貼回 Word,最後另存為一下就有了一份報告。
把上面的思路轉換為代碼就是如下的函數:
import re
from tqdm import tqdm
from xoffice.excel import Excel
from xoffice.word import Word
def excel2word(word: str, excel: str, output: str):
"""
根據 word 模板自動查找 excel 文件中的指定數據生成 word 報告
:param word: word 模板文件地址
:param excel: excel 數據文件
:param output: 輸出的 word 文檔地址
:return:
"""
word = Word(word, visible=False)
excel = Excel(excel, visible=False)
targets = re.findall(r'({{ (.+?)/(.+?) }})', word.text)
for target in tqdm(targets):
text, sht, ind = target
if sht.isdigit():
sht = int(sht)
try:
if re.match(r'^[a-z]+[0-9]+$', ind, re.I) is not None:
word.replace_text(text, excel.get_text(sht, ind))
elif re.match(r'^c:(.+)$', ind) is not None:
chart = re.match(r'^c:(.+)$', ind).group(1)
if chart.isdigit():
chart = int(chart)
excel.copy_chart(sht, chart)
word.select_content_text(text)
word.paste()
elif re.match(r'^s:(.+)$', ind) is not None:
shape = re.match(r'^s:(.+)$', ind).group(1)
if shape.isdigit():
shape = int(shape)
excel.copy_shape(sht, shape)
word.select_content_text(text)
word.paste()
else:
print(text + ":failed")
print(text + ":success")
except Exception:
print(text + ":failed")
word.save(output)
word.close()
excel.close()
看著相當複雜,但是大家實際使用的時候不必寫這麼一大堆,簡單幾行就可以完成一個腳本的編寫:
import glob
import os
from xoffice import excel2word
if __name__ == '__main__':
for path in glob.glob("word2/*.xlsx"):
dir_path, file_path = os.path.split(path)
base_name, ext = os.path.splitext(file_path)
output = os.path.join(dir_path, base_name + ".docx")
excel2word("word2/template.docx", path, output)
目前excel2word
這個函數並不算完美,文本替換算是全覆蓋,無論是正文、頁眉頁腳,還是文本框都適用,但是對於圖片和圖表僅支持正文範圍內的替換插入,不過也夠用了,正常也不会想着往頁眉頁腳動態插入圖片。如果真有這種需求也是可以實現的,我因為用不上就沒加進去。這裡替換到 Word 中的圖片和圖表大小是與 Excel 中一模一樣的,所以圖片尺寸需要提前規劃好。
我在上面把excel2word
函數的源碼貼出來並不是想要讓大家學會,只是想讓大家對於 Python 的第三方包有一個概念,就是你不用管它的源碼有多複雜,你只需要看懂函數的參數和效果,然後直接在腳本裡導入並使用即可。我在文中演示的所有自動化腳本都在十行左右,對於初學者而言並不算困難,只要你肯學,絕對是可以在短時間內學會的。
進階學習#
我在文中介紹的都是比較通用的腳本,但是其實每個人會遇到的問題和場景都有區別,當想要解決更個性化的需求時,就需要學習接口更底層一些的包了,例如 xlwings、python-docx、pikepdf 等,學習的方法也很簡單,去查它的官方文檔即可,文檔也不用全看,挑自己用的到的部分看看就行,著眼於它能做什麼,而不管它為什麼能。
如果想要更進一步拓展我上面演示的這些功能,建議直接去 Python 安裝目錄下的 Lib\site-packages\xoffice 文件夾中查看我寫的源碼,裡面的註釋還算完善,有基礎的話不難看懂。裡面 example 文件夾中還有幾個測試素材,可以用來驗證代碼的效果。源碼中用到了許多辦公自動化過程中常用的包,想要更靈活的編寫腳本的話建議有需求時可以深入學習一下。
如果對於數據處理有進一步的興趣,我建議學習 pandas 這個數據處理神器,它是 Python 中目前最強的數據處理包,而且現在微軟也已經將其引入自家的 Excel 軟件中,以後應該早晚都會普及的,先學起來百利而無一害。我現在一般只用 Excel 進行一些簡單的數據處理工作,稍微複雜一點的都是直接用 pandas 處理的,兩者之間的效率差距不是一星半點,最關鍵的是數據量大了之後 Excel 根本處理不過來,如果你試過用 Excel 打開一兩個 G 大小的表格文件的話應該就能明白我的意思。
後記#
上面這些腳本其實都可以再進一步封裝成命令行工具,或是圖形化軟件,我之前也寫過一些給同事用,有興趣的朋友可以試試,正好練練手。現代社會大部分工作都需要和電腦打交道,寫代碼其實並不是程序員的專利,掌握一些簡單的編程技巧可以讓某些工作變得相當簡單。Python 是一個不錯的切入點,你不需要懂這些第三方包是如何實現複雜功能的,你只需要找到能實現你需求的包,然後導入並調用它們就可以了。
> 下載 少數派 2.0 客戶端、關注 少數派公眾號,解鎖全新閱讀體驗 📰
> 實用、好用的 正版軟件,少數派為你呈現 🚀
generate_docx_by_mailmerge
© 本文著作權歸作者所有,並授權少數派獨家使用,未經少數派許可,不得轉載使用。