最近由于工作需要,需要将70個word檔案的頁眉頁腳全部進行修改,在想到這個無聊/重複/沒有任何技術含量的工作時,我的内心是相當奔潰的。就在我接近奔潰的時候我突然想到完全可以用python腳本來實作這樣無聊的工作,确定目标後我便開始在網上尋找有沒有造好的輪子,但是結果讓我有點兒失望。關于python操作頁眉頁腳的文章屈指可數,僅存在的幾篇也都是片段代碼,僅僅可以參考而已,于是我便決定自己是實作批量替換頁眉頁腳的腳本。
經過搜集資料發現,python可以通過win32com以及docx擴充包來實作對word的操作,但是經過實際操作發現docx對檔案頁眉頁腳的處理不是很理想,于是我最終決定使用win32com來實作此功能。
使用的子產品确定下來後就是思路的問題,小小的記錄一下:
1、替換頁眉頁腳可以分成兩個部分來實作,一個是針對單個檔案的處理,另一個是針對檔案夾下所有檔案的處理,為了分别對此兩種情況進行不同的處理使用if判斷語句來讓程式進入不同的邏輯。
2、針對檔案夾下所有檔案需要處理的情況,則使用python的内置子產品os将檔案夾下所有doc檔案的絕對絕對路徑拼接出來,以便實作對每一個檔案的操作。對于單個檔案的處理則不需要這樣來做,隻需要将檔案的決定路徑确定下來即可。
3、在确定了檔案的路徑之後便開始進行對word的操作,在進行測試過程中發現這裡存在一個很大的坑,那就是word分節符的存在,分節符将整個word文檔分成了若幹部分,每個部分的頁眉和頁腳是獨立的,在這個地方繞了我好幾個小時。最終經過查資料發現section就是word的中每一個部分的對象,使用它便可以分别定位到每一個部分,解決了這個問題後剩下的邏輯便一氣呵成。
接下來直接上代碼:
import win32com,os,sys,re
from win32com.client import Dispatch, constants
import os,time
class Change_file_footer_header():
'''批量更改word檔案的頁眉頁腳'''
def __init__( self ):
self.file_or_files = input('請選擇需要修改檔案或者檔案夾 only 代表隻修改一個檔案 many 代表修改檔案夾下的所有檔案 :')
self.method = input( '請選擇需要更改的類型 1 代表頁眉,2代表頁腳:')
self.path = input( '請輸入需要更改檔案的目錄名稱:')
self.old_name = input( '請輸入需要更替換的名稱:')
self.new_name = input( '請輸入替換的名稱:')
def change_header( self ,path ,file ):
''' 更改檔案的頁眉 '''
w = win32com.client.Dispatch('Word.Application')
w.Visible = 0
w.DisplayAlerts = 0
doc = w.Documents.Open( path )
a = w.ActiveDocument.Sections
n = 0
for i in range( len(a) ):
name = w.ActiveDocument.Sections[i].Headers[0]
old_name = str(name)
print( old_name )
if self.old_name in old_name:
new_name = old_name.replace( self.old_name,self.new_name )
print( new_name )
w.ActiveDocument.Sections[i].Headers[0].Range.Find.ClearFormatting()
w.ActiveDocument.Sections[i].Headers[0].Range.Find.Replacement.ClearFormatting()
w.ActiveDocument.Sections[i].Headers[0].Range.Find.Execute( self.old_name, False, False, False, False, False, False, 1, False, self.new_name, 2 )
n = n+1
doc.Close()
create_time = time.strftime('%Y/%m/%d:%H/%M/%S', time.localtime(time.time()))
text = '{} : {}檔案====總共替換了{}個頁眉'.format(create_time, file, n)
self.log(text)
def change_footer( self ,path ,file ):
''' 更改檔案的頁腳 '''
w = win32com.client.Dispatch('Word.Application')
w.Visible = 0
w.DisplayAlerts = 0
doc = w.Documents.Open( path )
a = w.ActiveDocument.Sections
n = 0
for i in range( len(a) ):
name = w.ActiveDocument.Sections[i].Footers[0]
old_name = str(name)
print( old_name )
if self.old_name in old_name:
new_name = old_name.replace( self.old_name,self.new_name )
print( new_name )
w.ActiveDocument.Sections[i].Footers[0].Range.Find.ClearFormatting()
w.ActiveDocument.Sections[i].Footers[0].Range.Find.Replacement.ClearFormatting()
w.ActiveDocument.Sections[i].Footers[0].Range.Find.Execute( self.old_name, False, False, False, False, False, False, 1, False, self.new_name, 2)
n = n+1
doc.Close()
create_time = time.strftime('%Y/%m/%d:%H/%M/%S',time.localtime(time.time()))
text = '{} : {}檔案====總共替換了{}個頁腳'.format( create_time,file, n)
self.log(text)
def change_file_header( self ):
''' 循環周遊所輸入的檔案夾 '''
for root, dirs, files in os.walk( self.path ):
for i in files:
if i.split('.')[1] == 'docx' or i.split('.')[1] == 'doc':
print( '更改檔案的名稱',i )
file_path = os.path.join( root,i )
self.change_header( file_path ,i )
#time.sleep( 1 )
def change_file_footer( self ):
''' 循環周遊所需要修改頁腳的檔案夾 '''
for root, dirs, files in os.walk( self.path ):
for i in files:
if i.split('.')[1] == 'docx' or i.split('.')[1] == 'doc':
print( '更改檔案的名稱',i )
file_path = os.path.join( root,i )
self.change_footer( file_path ,i )
def log(self,text):
'''輸出日志子產品'''
file_name = './' + time.strftime('%Y%m%d%H',time.localtime(time.time())) + '.' + 'txt'
with open( file_name,"a+" ) as f:
f.write( text )
f.write( '\n' )
def run( self ):
if self.file_or_files == 'only':
file_name = self.path.split( '\\' )[ -1 ]
if self.method == '1':
self.change_header( self.path ,file_name )
elif self.method == '2':
self.change_footer( self.path,file_name )
elif self.file_or_files == 'many':
if self.method == '1':
self.change_file_header()
elif self.method == '2':
self.change_file_footer()
else:
print( '請輸入正确的選擇 only或者 many' )
if __name__ == '__main__':
Change_file_name = Change_file_footer_header()
Change_file_name.run()