最近由於工作需要,需要將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()