<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Python私活300元:提取PDF的Excel表格

          共 14976字,需瀏覽 30分鐘

           ·

          2022-10-21 12:14

          在群里看到老師發(fā)這個需求時,我之前就寫過提取pdf的單子,所以沒有猶豫,立馬接了下來

          一 需求分析

          單單提取pdf中的表格數(shù)據(jù)還是很簡單的,使用pdfplumber這個庫,就可以很簡單的實現(xiàn),提取后保存到excel中,再使用pandas處理數(shù)據(jù),最后通過openpyxl設(shè)置表格樣式,難點在于人民幣金額自動轉(zhuǎn)大寫,這個我開始也沒有思路,最后在度娘那找到了解決方案

          二 解決步驟

          實現(xiàn)人民幣金額自動轉(zhuǎn)大寫

          import pdfplumber,openpyxl
          import pandas as pd
          from pathlib import Path
          from openpyxl import load_workbook
          from openpyxl.styles import Font, PatternFill, Border, Side, Alignment 

          def numtomoney(money):
              cnNums = ["零","壹","貳","叁","肆","伍","陸","柒","捌","玖"#漢字的數(shù)字
              cnIntRadice = ["""拾""佰""仟"#基本單位
              cnIntUnits = ["""萬""億""兆"#對應(yīng)整數(shù)部分擴展單位
              cnDecUnits = ["角""分""毫""厘"#對應(yīng)小數(shù)部分單位
              cnInteger = "整" #整數(shù)金額時后面跟的字符
              cnIntLast = "元" #整型完以后的單位
              maxNum = 999999999999999.9999 #最大處理的數(shù)字
              # IntegerNum 金額整數(shù)部分
              # DecimalNum 金額小數(shù)部分
              ChineseStr = "" #輸出的中文金額字符串
              parts =[] #分離金額后用的數(shù)組,預(yù)定義
              Symbol = "" #正負值標(biāo)記

              if money == ""
                  return ""

              money = float(money)
              if money >= maxNum:
                  return "超出最大范圍"

              if money == 0:
                  ChineseStr = cnNums[0] + cnIntLast + cnInteger
                  return ChineseStr

              if money < 0:
                  money = -money
                  Symbol = "負 "

              money = str(money) #轉(zhuǎn)換為字符串
              if money.find(".") == -1:
                  IntegerNum = money
                  DecimalNum = ""
              else:
                  parts = money.split(".")
                  IntegerNum = parts[0]
                  DecimalNum = parts[1][0:4]

              if int(IntegerNum) > 0:#獲取整型部分轉(zhuǎn)換
                  zeroCount = 0
                  IntLen = len(IntegerNum)
                  for i in range(0,IntLen):
                      n = IntegerNum[i]#整數(shù)部分字符串的第i個字符
                      p = IntLen - i - 1
                      q = p // 4#地板除,p<4時,為0,4>p<8時,等于1,等于8時,等于2
                      m = p % 4#求余數(shù),p<4時,為p,=4時為0
                      if n == "0":
                          zeroCount +=1
                      else:
                          if zeroCount > 0:
                              ChineseStr += cnNums[0]
                          zeroCount = 0 #歸零
                          ChineseStr += cnNums[int(n)] + cnIntRadice[m]
                          if m == 0 and zeroCount < 4:
                              ChineseStr += cnIntUnits[q]
                  ChineseStr += cnIntLast#整型部分處理完畢

              if DecimalNum != "":#小數(shù)部分
                  decLen = len(DecimalNum)
                  for i in range(0,decLen):
                      n = DecimalNum[i]
                      if n != "0":
                          ChineseStr += cnNums[int(n)] + cnDecUnits[i]
              if ChineseStr == "":
                  ChineseStr += cnNums[0] + cnIntLast + cnInteger
              elif DecimalNum == "0":
                  ChineseStr += cnInteger
              ChineseStr = Symbol + ChineseStr
              return ChineseStr
                  
          numtomoney(5648.89)

          數(shù)據(jù)提取和數(shù)據(jù)處理部分

          def get_data(file_path):
              pdf_path=Path(file_path)
              pdf_files=pdf_path.glob('*.pdf')
              for pdf_file in pdf_files:
                  df_list=[]
                  pdf = pdfplumber.open(path_or_fp=pdf_file)
                  for page in pdf.pages:
                      table=page.extract_table()#提取page對象中的表格數(shù)據(jù)為列表
                      df=pd.DataFrame(table)#把列表數(shù)據(jù)存入DataFrame中
                      df_list.append(df)
                  df_total=pd.concat(df_list)#合并表格
                  df_total=df_total.reset_index(drop=True)#重置索引,并刪除原索引
                  df_total.columns=df_total.iloc[0,:].tolist()#用第一行作為表頭
                  df_total.drop(index=0,inplace=True)#刪除第一行
                  df_total=df_total.reindex(columns=df_total.columns[[0,1,3,2,6,5,7,4]])#調(diào)整列順序
                  df_total.drop(columns=['配置要求'],inplace=True)#刪除配置要求列
                  
                  df_total.columns=['序號','名稱','規(guī)格及型號','品牌','單位','數(shù)量','單價(元)']
                  df_total['數(shù)量']=pd.to_numeric(df_total['數(shù)量'],errors='coerce')
                  df_total['單價(元)']=pd.to_numeric(df_total['單價(元)'],errors='coerce')
                  df_total['合價(元)']=df_total['數(shù)量']*df_total['單價(元)']
                  df_total['存放位置']=pd.NA
                  df_total.drop(index=df_total.index.tolist()[-2:],inplace=True)#刪除最后兩行數(shù)據(jù)
                  df_total=df_total.applymap(lambda x : x.replace('\n',''if isinstance(x,str) else x)#去除單元格中的換行
                  total=df_total['合價(元)'].sum(axis=0)
                  money=numtomoney(total)
                  row_num=df_total.shape[0]
                  df_total.loc[row_num+2,'序號']=f'{money}(¥{"%.2f" % total})'#2位小數(shù)
                  df_total.loc[row_num+3,'序號']='采購申請人簽字:'
                  df_total.loc[row_num+4,'序號']='實訓(xùn)室管理員簽字:'
                  p=Path(Path.cwd())
                  p1=p/'已提取文件'
                  if not p1.exists():#判斷文件夾是否存在,不存在就新建文件夾
                      p1.mkdir(exist_ok=True)
                  df_total.to_excel(f'./已提取文件/{pdf_file.stem}.xlsx',index=False)

          設(shè)置表格樣式



          def modify_style(wb,first_row_value,second_row_value,place,file_name):
              '''
              first_row_value 第一行標(biāo)題內(nèi)容
              second_row_value 第二行標(biāo)題內(nèi)容
              place,file  表格中'
          存放位置'列內(nèi)容
              file_name   最終保存的文件名稱
              '
          ''
              for sheet_name in wb.sheetnames:
                  ws = wb[sheet_name]
                  ws.insert_rows(1,2)#在第一行前面插入2行空行
                  alignment=Alignment(horizontal="center", vertical="center",wrap_text=True)
                  ws['A1'].value=first_row_value
                  ws['A1'].font=Font(name='宋體', size=16, bold=True, color='FF000000')
                  ws['A1'].alignment=alignment
                  ws['A2'].value=second_row_value
                  ws['A2'].font=Font(name='宋體', size=11, bold=True, color='FF000000')
                  ws['A2'].alignment=alignment
                  ws.merge_cells('A1:I1')#合并單元格
                  ws.merge_cells('A2:I2')
                  maxrows = ws.max_row # 獲取最大行
                  ws.column_dimensions["B"].width = 24  # 設(shè)置B列寬度為15
                  for col in ['C','D','G','H']:
                      ws.column_dimensions[col].width = 12  # 批量設(shè)置指定列寬度為12
                  for col in ['A','E','F','I']:
                      ws.column_dimensions[col].width = 4.5  # 批量設(shè)置指定列寬度為4.5
                  for i in range(3,maxrows+1):
                      cells = ws[i]
                      font = Font(name='宋體', size=11, bold=False, italic=False, color='FF000000')
                      alignment = Alignment(horizontal="center", vertical="center",wrap_text=True)
                      # 先定好side的格式
                      side_left = Side(style='thin', color='FF000000')
                      side_right = Side(style='thin', color='FF000000')
                      # 代入邊線中
                      border = Border(left=side_left, right=side_right, top=side_right, bottom=side_left)
                      for cell in cells:
                          cell.font = font
                          cell.alignment = alignment
                          cell.border = border
                  ws['A1'].font=Font(size=16, bold=True)
                  ws['A2'].font=Font(bold=True)
                  ws['A2'].alignment= Alignment(horizontal="center", vertical="center",wrap_text=True)
                  ws.row_dimensions[2].height=32#設(shè)置第二行行高
                  ws.row_dimensions[maxrows-1].height=28#設(shè)置倒數(shù)第二行行高
                  ws.row_dimensions[maxrows].height=28#設(shè)置倒數(shù)第一行行高
                  for i in range(3):
                      ws.merge_cells(f'A{maxrows-2+i}:H{maxrows-2+i}')
                      ws[f'A{maxrows-2+i}'].alignment=Alignment(horizontal="left", vertical="center",wrap_text=True)
                  ws['I4'].value=place    
                  for col in ['G','H']:#設(shè)置金錢符號
                      for i in range(4,maxrows+1):
                          ws[f'{col}{i}'].number_format='¥#,##0.00;¥-#,##0.00'
                  ws.merge_cells(f'I4:I{maxrows}')
                  
              wb.save('已完成-'+f'{file_name}.xlsx')
          file_path=Path(Path.cwd()/'已提取文件')
          files=file_path.glob('*.xlsx')
          for file in files:
              wb=load_workbook(file)
              file_name=file.stem
              modify_style(wb,'紹興市柯橋區(qū)職業(yè)教育中心耗材入庫單','項目名稱:柯橋區(qū)職業(yè)教育中心建筑專業(yè)實訓(xùn)耗材采購項目\n入庫時間:2022年9月29日 ','1號實訓(xùn)樓2樓庫房',file_name)

          三 最終結(jié)果

          四 技術(shù)總結(jié)

          代碼編寫過程遇到一個大坑,是表格合并時,index沒有重置,導(dǎo)致表格有多個index為0和1的行,再刪除第一行和合同價格匯總行時,會誤刪需要的行,這里推薦下老師的pandas課程,里面有很多干貨,報名老師的課程,讓我學(xué)到了很多技術(shù),解決了許多日常工作中的問題,大大提高我的工作效率,讓我的工作也輕松了不少,更重要的是,有了個門做兼職的技術(shù)!

          五 答案地址

          在本公眾號《螞蟻學(xué)Python》后臺回復(fù): 1015PDF代碼 

          可以得到數(shù)據(jù)素材和代碼答案


          今晚來螞蟻老師抖音直播間,Python帶副業(yè)全套餐有優(yōu)惠!!!


          瀏覽 69
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美精品乱人伦久久久久久 | 翔田千里熟妇息孑交尾 | 夜夜骚AV一二三区无码 | www天堂A v | 久久精品在线视频 |