1. 程式人生 > 程式設計 >Python操作Word批量生成合同的實現示例

Python操作Word批量生成合同的實現示例

背景:大約有3K家商家需要重新確認資訊並簽訂合同。合同是統一的Word版本。每個供應商需要修改合同內的金額部分。人工處理方式需要每個複製貼上且金額要生成大寫金額。基於重複工作可偷懶。用Python解救一下。

#匯入對應資料庫
import numpy as np 
import pandas as pd 
import os 
import docx
from docx.shared import Pt
from docx.oxml.ns import qn
#修改專案檔案地址
os.chdir(r'C:\Users\WIN7\Desktop\分期賬單自動化')
os.getcwd()

'''
人民幣數字轉大寫漢字
'''
# coding: utf-8
import warnings
from decimal import Decimal

def cncurrency(value,capital=True,prefix=False,classical=None):
  '''
  引數:
  capital:  True  大寫漢字金額
        False 一般漢字金額
  classical: True  元
        False 圓
  prefix:   True  以'人民幣'開頭
        False,無開頭
  '''
  if not isinstance(value,(Decimal,str,int)):
    msg = '''
    由於浮點數精度問題,請考慮使用字串,或者 decimal.Decimal 類。
    因使用浮點數造成誤差而帶來的可能風險和損失作者概不負責。
    '''
    warnings.warn(msg,UserWarning)
  # 預設大寫金額用圓,一般漢字金額用元
  if classical is None:
    classical = True if capital else False
    
  # 漢字金額字首
  if prefix is True:
    prefix = '人民幣'
  else:
    prefix = ''
    
  # 漢字金額字元定義
  dunit = ('角','分')
  if capital:
    num = ('零','壹','貳','叄','肆','伍','陸','柒','捌','玖')
    iunit = [None,'拾','佰','仟','萬','億','仟']
  else:
    num = ('〇','一','二','三','四','五','六','七','八','九')
    iunit = [None,'十','百','千','千']
  if classical:
    iunit[0] = '元' if classical else '圓'
  # 轉換為Decimal,並截斷多餘小數

  if not isinstance(value,Decimal):
    value = Decimal(value).quantize(Decimal('0.01'))

  # 處理負數
  if value < 0:
    prefix += '負'     # 輸出字首,加負
    value = - value     # 取正數部分,無須過多考慮正負數舍入
                # assert - value + value == 0
  # 轉化為字串
  s = str(value)
  if len(s) > 19:
    raise ValueError('金額太大了,不知道該怎麼表達。')
  istr,dstr = s.split('.')      # 小數部分和整數部分分別處理
  istr = istr[::-1]          # 翻轉整數部分字串
  so = []   # 用於記錄轉換結果
  
  # 零
  if value == 0:
    return prefix + num[0] + iunit[0]
  haszero = False   # 用於標記零的使用
  if dstr == '00':
    haszero = True # 如果無小數部分,則標記加過零,避免出現“圓零整”
    
  # 處理小數部分
  # 分
  if dstr[1] != '0':
    so.append(dunit[1])
    so.append(num[int(dstr[1])])
  else:
    so.append('整')     # 無分,則加“整”
  # 角
  if dstr[0] != '0':
    so.append(dunit[0])
    so.append(num[int(dstr[0])])
  elif dstr[1] != '0':
    so.append(num[0])    # 無角有分,新增“零”
    haszero = True     # 標記加過零了
    
  # 無整數部分
  if istr == '0':
    if haszero:       # 既然無整數部分,那麼去掉角位置上的零
      so.pop()
    so.append(prefix)    # 加字首
    so.reverse()      # 翻轉
    return ''.join(so)

  # 處理整數部分
  for i,n in enumerate(istr):
    n = int(n)
    if i % 4 == 0:     # 在圓、萬、億等位上,即使是零,也必須有單位
      if i == 8 and so[-1] == iunit[4]:  # 億和萬之間全部為零的情況
        so.pop()            # 去掉萬
      so.append(iunit[i])
      if n == 0:             # 處理這些位上為零的情況
        if not haszero:         # 如果以前沒有加過零
          so.insert(-1,num[0])    # 則在單位後面加零
          haszero = True       # 標記加過零了
      else:                # 處理不為零的情況
        so.append(num[n])
        haszero = False         # 重新開始標記加零的情況
    else:                  # 在其他位置上
      if n != 0:             # 不為零的情況
        so.append(iunit[i])
        so.append(num[n])
        haszero = False         # 重新開始標記加零的情況
      else:                # 處理為零的情況
        if not haszero:         # 如果以前沒有加過零
          so.append(num[0])
          haszero = True

  # 最終結果
  so.append(prefix)
  so.reverse()
  return ''.join(so)
#資料準備階段 匯入大寫
#讀取預備好的EXCEL表格
text = pd.read_excel('付款預備表.xlsx')
#print(text)
text['EC總應付額']
list1 = []
for i in text['EC總應付額']:
  list1.append(cncurrency(str(i)))
text.append(list1)
text['大寫金額'] = list1
text.shape[0]
print(text.head())
document12 = docx.Document('分期SPM模板(12期).docx')
document24 = docx.Document('分期SPM模板(24期).docx')
supp_num = 0 
for supp_num in range(text.shape[0]):
  paragraph_num = 0
  A = text.iat[supp_num,2]
  B = text.iat[supp_num,5]
  qishu = text.iat[supp_num,3]
  supp_name = text.iat[supp_num,1]
  user_name = text.iat[supp_num,4]
  content = "雙方確認,截止至 2020 年 3 月 31 日,扣除原合同和原合作約定到貨異常(包括但不僅限於缺貨、少貨、貨損、到貨不符)、違約責任、賠償責任、甲方代乙方墊付等所涉相關費用後,甲方尚欠付乙方貨款金額合計人民幣{}元(大寫:{})。".format(A,B)
  if qishu == "12期":
    p = document12.paragraphs[8].clear()
    run1 = p.add_run(content)
    run1.font.size = Pt(12)
    run1.font.name = '仿宋'
    run1.element.rPr.rFonts.set(qn('w:eastAsia'),'仿宋')
    document12.save("{}.docx".format(supp_name))
  else:
    p = document24.paragraphs[8].clear()
    run1 = p.add_run(content)
    run1.font.size = Pt(12)
    run1.font.name = '仿宋'
    run1.element.rPr.rFonts.set(qn('w:eastAsia'),'仿宋')
    document24.save("{}.docx".format(supp_name))

主要是分成四個板塊。
一:匯入相關的包,這個就不說了
二:數字金額轉大寫金額。這個網上一大堆的現成的函式,也就不用自己寫,Copy測試一下,OK的。
三:預備自己的資料。
四:本來想替換指定位置的內容的,但是發現操作相對有點困難,那就思維放大,直接替換整個段落。用個format,把需要替換的內容直接填入。然後用docx包裡面的.clear【清除段落】 加 add_run【新增段落】的方式,配合上.font.size 和.font.name 調整字型大小與字型。最後save就OJBK了。

到此這篇關於Python操作Word批量生成合同的實現示例的文章就介紹到這了,更多相關Python批量替換word內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!