Python-Excel轉(zhuǎn)word表格并合并流程


工作中正好接到個(gè)小項(xiàng)目需要將Excel數(shù)據(jù)導(dǎo)出組成word表格并合并所有表格成一個(gè)word文檔肪康,這個(gè)流程涉及到Excel的解析荚恶、Word文檔的數(shù)據(jù)插入,多個(gè)Word文檔的合并磷支,對(duì)Word文檔插入圖片等谒撼,在嘗試構(gòu)寫腳本時(shí)發(fā)現(xiàn)百度谷歌的資料多有缺失或者干脆就是過時(shí)的方法,于是寫下這篇文章將自己在構(gòu)寫這個(gè)腳本時(shí)遇到的坑寫一下雾狈。

首先是解析Excel數(shù)據(jù)廓潜,Python的xlrd框架可以快速地幫助我們完成這一部分操作:

import xlrd

//獲取Excel文檔
workbook = xlrd.open_workbook(u'2019名單.xls')

//我們可以通過兩種不同的方式獲取Excel文檔中對(duì)應(yīng)的表單
sheet = workbook.sheets()[0]
sheet = getSheetByName("表單名字",workbook)

//通過xlrd的接口獲得表單的行數(shù)及列數(shù)
nrow = sheet.nrows
ncol = sheet.ncols

for i in range(1,nrow):
//cells代表的是Excel表單的每一行,即一個(gè)單元格組
    cells = sheet.row(i)
    //得到單元格組我們便可執(zhí)行下一步的插入Word文檔操作了
    insertCellsToWord(cells)

需要明白的是箍邮,最好不要在Python腳本中對(duì)Word文檔的效果進(jìn)行再定義茉帅,原因之一是因?yàn)槟_本并不全能,如果在腳本中對(duì)文檔效果進(jìn)行再定義锭弊,代碼會(huì)變得臃腫且難以維護(hù)堪澎,例如先通過腳本生成表單效果再對(duì)單元格進(jìn)行修改效果等等,這些操作最好先自行創(chuàng)建Word文檔進(jìn)行定義味滞,即樱蛤,通過Python腳本獲取預(yù)先定義好的Word文檔進(jìn)行插入數(shù)據(jù)的操作。
譬如剑鞍,我們有如下一張Word文檔昨凡。


我們需要填充的數(shù)據(jù)都在這個(gè)表單里,通過預(yù)先確定的唯一標(biāo)示符(即圖中的英文單詞)將Excel中的數(shù)據(jù)插入到對(duì)應(yīng)的單元格中蚁署。

//python-docx是Python較為常用的操控Word文檔的工具框架
from docx import Document

def insertCellsToWord(cells):
    //獲取預(yù)先設(shè)置的模板
    test = Document("XXXX模板.docx")
    for t in test.tables:
        for row in t.rows:
            //遍歷到單元格進(jìn)行數(shù)據(jù)插入
            for cell in row.cells:
                try:
                    set_cell(cell,cells)
                except Exception as e:
                    print(cells)
                    print(e)
    test_number = str(cells[0].value)
    //生成新模板
    test.save(output_path + "普通/" + test_number + ".docx")

def set_cell(cell,cells):
    //找到對(duì)應(yīng)的單元格進(jìn)行數(shù)據(jù)插入
    if cell.text == "school":
        cell.text = cells[13].value

需要注意的是便脊,當(dāng)你如此完成了插入數(shù)據(jù)的操作并預(yù)覽輸出的Word文檔時(shí),你會(huì)發(fā)現(xiàn)光戈,輸出的文檔并沒有按照你預(yù)先調(diào)制的展示效果展示哪痰,例如單元格中的文字居中,加粗久妆,字體修改等等晌杰,通過python-docx的操作會(huì)丟失這部分?jǐn)?shù)據(jù),cell.text = cells[13].value的操作并不會(huì)繼承效果筷弦,因此我們需要通過python-docx再次對(duì)單元格效果進(jìn)行設(shè)置肋演。

from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.shared import Pt

if cell.text == "school":
        cell.text = cells[13].value
        p = cell.paragraphs[0]
        p.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER
        r = p.runs[0]
        r.bold = True
        f = r.font
        f.size = Pt(12)

通過單元格的paragraphs屬性及runs屬性進(jìn)行樣式設(shè)置,在此烂琴,我設(shè)置了單元格居中爹殊,文字加粗以及字體大小設(shè)置為12,你可以在python-docx的官方文檔找到更多可參考的樣式屬性奸绷。

接下來開始進(jìn)行Word文檔合并边灭。
在合并之前需要說明的是,我們常常會(huì)遇到表單中需要插入圖片的需求健盒,比如每張表格都有一個(gè)一寸照之類的绒瘦,但在我構(gòu)寫這個(gè)腳本的踩坑中發(fā)現(xiàn)称簿,圖片并不能在合并文檔之前插入(也可能是我沒找到正確的方式),當(dāng)先插入圖片再進(jìn)行合并時(shí)惰帽,導(dǎo)出的合并文件必然是損壞的憨降,而導(dǎo)出沒有圖片的純文本合并文件卻不會(huì)損壞,因此该酗,我通過在第一次對(duì)單元格的文本設(shè)置中對(duì)標(biāo)注插入圖片的單元格替換唯一標(biāo)示符(例如上圖中的Icon變?yōu)镮con+“對(duì)應(yīng)的人員編號(hào)”)授药,然后在合并文件之后再次遍歷單元格插入圖片,理所應(yīng)當(dāng)?shù)奈仄牵@樣會(huì)導(dǎo)致腳本的效率大大降低悔叽,如果有更好的方式希望不吝賜教。


    normal_path = output_path + "普通/"
    
    //獲取本地所有待合并文檔
    files = os.listdir(normal_path)
    files.sort()
    
    normal_merge_docx = ""
    
    for index, filename in enumerate(files):
        if index == 0:
            normal_merge_docx = Document(normal_path + filename)
            continue
        sub_doc = Document(normal_path + filename)
        for el in sub_doc.element.body:
            normal_merge_docx.element.body.append(el)
    
    normal_merge_docx.save("normal_merge_docx.docx")

可能會(huì)有人問爵嗅,為什么要獲取第一個(gè)待合并文件對(duì)接下來的文檔進(jìn)行合并而不是新建一個(gè)Word文檔娇澎,對(duì)所有的待合并文件進(jìn)行合并呢?

原因在于睹晒,新建的Word文檔并不包含一些高于表格的樣式數(shù)據(jù)趟庄,如果使用新建文檔對(duì)所有待合并文檔合并,則預(yù)覽輸出文件會(huì)發(fā)現(xiàn)合并Word文檔的樣式錯(cuò)誤伪很,所以必須取一個(gè)待合并文檔作為基類來合并其他文檔戚啥,這樣才保證不會(huì)樣式丟失。

接著進(jìn)行圖片插入:

from docx.shared import Inches

//因?yàn)槲倚枰迦氲膱D片位置是確定的锉试,所以我直接設(shè)置入?yún)⑷ト?duì)應(yīng)的單元格插入圖片猫十,增加效率。
def insertImage(filename,row,col):
    output = Document(filename)
    for t in output.tables:
        cell = t.cell(row,col)
        if "-" in cell.text:
            print(cell.text)
            arr = cell.text.split("-")
            cell.text = ""
            p = cell.paragraphs[0]
            r = p.runs[0]
            pathstr = ""
            //getImage通過具體的標(biāo)識(shí)符去取本地圖片呆盖,若本地圖片有問題則通過dealImg對(duì)圖片處理再行插入
            try:
                pathstr = getImg(arr[0], arr[1])
            except Exception as e:
                print(e)
                pathstr = dealImg(getImg(arr[0], arr[1]), arr[1])
            r.add_picture(pathstr, width=Inches(0.84), height=Inches(1.2))
            p.alignment = WD_ALIGN_PARAGRAPH.CENTER
            

需要注意的是拖云,python-docx的文檔告訴我們,插入圖片的方法在單元格的paragraphs數(shù)組屬性的runs數(shù)組屬性中絮短,只有找到具體的run屬性才能add_picture
這里有一個(gè)問題昨忆,雖然在上述代碼中我們將對(duì)應(yīng)單元格的標(biāo)記文本(Icon-XXXXXXX)置為空丁频,但對(duì)應(yīng)的樣式屬性依然存在,如果通過celladd_paragraph增加paragraph再通過add_run增加run的樣式屬性邑贴,則會(huì)發(fā)現(xiàn)輸出文檔的圖像上多出一行席里,這是因?yàn)檫@個(gè)單元格的paragraphs數(shù)組變大了,即有兩組樣式屬性對(duì)應(yīng)不同文本拢驾,而在python-docx中又無法在不銷毀單元格的情況下對(duì)單元格內(nèi)的文本及樣式屬性進(jìn)行快速清空奖磁,因此,就需要在原來的標(biāo)記文本置為空的情況下獲取對(duì)應(yīng)的樣式屬性進(jìn)行插入圖片繁疤。

最后輸出文件:

output.save(filename)

整個(gè)流程便結(jié)束了咖为。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末秕狰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子躁染,更是在濱河造成了極大的恐慌鸣哀,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,744評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吞彤,死亡現(xiàn)場離奇詭異我衬,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)饰恕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門挠羔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人埋嵌,你說我怎么就攤上這事破加。” “怎么了莉恼?”我有些...
    開封第一講書人閱讀 163,105評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵拌喉,是天一觀的道長。 經(jīng)常有香客問我俐银,道長尿背,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,242評(píng)論 1 292
  • 正文 為了忘掉前任捶惜,我火速辦了婚禮田藐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吱七。我一直安慰自己汽久,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,269評(píng)論 6 389
  • 文/花漫 我一把揭開白布踊餐。 她就那樣靜靜地躺著景醇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪吝岭。 梳的紋絲不亂的頭發(fā)上三痰,一...
    開封第一講書人閱讀 51,215評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音窜管,去河邊找鬼散劫。 笑死,一個(gè)胖子當(dāng)著我的面吹牛幕帆,可吹牛的內(nèi)容都是我干的获搏。 我是一名探鬼主播,決...
    沈念sama閱讀 40,096評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼失乾,長吁一口氣:“原來是場噩夢啊……” “哼常熙!你這毒婦竟也來了纬乍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,939評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤症概,失蹤者是張志新(化名)和其女友劉穎蕾额,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體彼城,經(jīng)...
    沈念sama閱讀 45,354評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡诅蝶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,573評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了募壕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片调炬。...
    茶點(diǎn)故事閱讀 39,745評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖舱馅,靈堂內(nèi)的尸體忽然破棺而出缰泡,到底是詐尸還是另有隱情,我是刑警寧澤代嗤,帶...
    沈念sama閱讀 35,448評(píng)論 5 344
  • 正文 年R本政府宣布麦轰,位于F島的核電站卢鹦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜块请,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,048評(píng)論 3 327
  • 文/蒙蒙 一最仑、第九天 我趴在偏房一處隱蔽的房頂上張望的妖。 院中可真熱鬧润歉,春花似錦、人聲如沸渠鸽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽徽缚。三九已至憨奸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間凿试,已是汗流浹背排宰。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留红省,地道東北人额各。 一個(gè)月前我還...
    沈念sama閱讀 47,776評(píng)論 2 369
  • 正文 我出身青樓国觉,卻偏偏與公主長得像吧恃,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子麻诀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,652評(píng)論 2 354