Python 快速合并PDF表格转换输出CSV文件

单位的刷脸考勤机后台系统做得比较差,只能导出每个部门的出勤统计表pdf,格式如下:

近期领导要看所有部门的考勤数据,于是动手快速写了个合并pdf并输出csv文件的脚本。

安装模块

pypdf2,pdfplumber,前者用于合并,后者用于读表格。

C:\>pip install pypdf2
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Collecting pypdf2
  Using cached https://pypi.tuna.tsinghua.edu.cn/packages/8e/5e/c86a5643653825d3c913719e788e41386bee415c2b87b4f955432f2de6b2/pypdf2-3.0.1-py3-none-any.whl (232 kB)
Installing collected packages: pypdf2
Successfully installed pypdf2-3.0.1

C:\>pip install pdfplumber
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Collecting pdfplumber
  Using cached https://pypi.tuna.tsinghua.edu.cn/packages/f8/d3/f58c2d5d86a585e438c6708f568eca79e7c4e6ee3d5210cf8b31d38cb021/pdfplumber-0.10.3-py3-none-any.whl (48 kB)
Requirement already satisfied: pdfminer.six==20221105 in d:\program files\python\lib\site-packages (from pdfplumber) (20221105)
Requirement already satisfied: Pillow>=9.1 in d:\program files\python\lib\site-packages (from pdfplumber) (10.2.0)
Requirement already satisfied: pypdfium2>=4.18.0 in d:\program files\python\lib\site-packages (from pdfplumber) (4.25.0)
Requirement already satisfied: charset-normalizer>=2.0.0 in d:\program files\python\lib\site-packages (from pdfminer.six==20221105->pdfplumber) (3.3.2)
Requirement already satisfied: cryptography>=36.0.0 in d:\program files\python\lib\site-packages (from pdfminer.six==20221105->pdfplumber) (41.0.7)
Requirement already satisfied: cffi>=1.12 in d:\program files\python\lib\site-packages (from cryptography>=36.0.0->pdfminer.six==20221105->pdfplumber) (1.16.0)
Requirement already satisfied: pycparser in d:\program files\python\lib\site-packages (from cffi>=1.12->cryptography>=36.0.0->pdfminer.six==20221105->pdfplumber) (2.21)
Installing collected packages: pdfplumber
Successfully installed pdfplumber-0.10.3

读取、合并文件

PyPDF2

读取和合并pdf文件正好以前写过,主要代码如下: 

    with codecs.open(file_path, 'rb', encoding='utf-16') as file:
        pdf_reader = PyPDF2.PdfReader(file)
        text = ''
        for page_num in range(len(pdf_reader.pages)):
            tt = pdf_reader.pages[page_num].extract_text()
            print(tt)
            text += tt
......

    pdfMerge = PyPDF2.PdfMerger()
    try:
        for pdf in pdfLists:
            pdfMerge.append(pdf, import_outline=False)
        pdfMerge.write(pdfFileN)
        pdfMerge.close
        print("PDF files merged successfully!")

......

表格读取

pdfplumber

读取代码如下:

pdf =  pdfplumber.open(pdfFileN)
for page in pdf.pages:
    tables = page.extract_tables(table_settings = {})
    for table in tables:
        print(table)

遍历得到的是一个个二维列表,可以根据需要自己清洗数据。

程序界面

easygui

就用这个库,弄2个对话框简单了事:

更多easygui内容请见: 

Python 简易图形界面库easygui 对话框大全-CSDN博客文章浏览阅读4.2k次,点赞117次,收藏96次。提供了“继续”和“取消”选项,并返回True(表示继续)或False(表示取消)。", title="结束", ok_button="干得好!easygui.ccbox(msg, title, choices=('退出[E]','取消[C]'))选择“Chocolate”后点OK就把所选择的项赋值给变量choice,点Cancel则返回None。如果选择了第一个按钮,则返回“True”。提供了Yes和No的选择,并返回“True”或“False”。在列表框中提供了可供选择的由元组或列表指定的选项列表。https://blog.csdn.net/boysoft2002/article/details/135179267Python 简易图形界面库easygui 对话框大全(续)-CSDN博客文章浏览阅读1.2k次,点赞67次,收藏58次。Python 简易图形界面库easygui 对话框大全-CSDN博客提供了“继续”和“取消”选项,并返回True(表示继续)或False(表示取消)。", title="结束", ok_button="干得好!easygui.ccbox(msg, title, choices=('退出[E]','取消[C]'))选择“Chocolate”后点OK就把所选择的项赋值给变量choice,点Cancel则返回None。如果选择了第一个按钮,则返回“True”。https://blog.csdn.net/boysoft2002/article/details/135297373几样拼凑在一起,完成合并和转换pdf表格,完整代码如下:

import sys,os
import datetime as dt
import PyPDF2,pdfplumber
import easygui as egdef get_pdf_text(file_path):with codecs.open(file_path, 'rb', encoding='utf-16') as file:pdf_reader = PyPDF2.PdfReader(file)text = ''for page_num in range(len(pdf_reader.pages)):tt = pdf_reader.pages[page_num].extract_text()print(tt)text += ttreturn textdef strDateTime(diff=0):now = dt.datetime.now()future_time = now + dt.timedelta(days=diff)    return f'{future_time.year:04}{future_time.month:02}{future_time.day:02}_{future_time.hour:02}{future_time.minute:02}{future_time.second:02}'txtStart = "PDFmerged_"
try:Dir = eg.diropenbox(msg=None, title=None, default='./')pdfLists = [f for f in os.listdir(Dir) if f.endswith('.pdf') and not f.startswith(txtStart)]pdfFileN = Dir + '\\' + txtStart + strDateTime() + ".pdf"
except:print('取消退出!')sys.exit(0)if len(pdfLists)==0:eg.msgbox("此文件夹没有Pdf文件!", title="结束", ok_button="Fail")sys.exit(0)
else:pdfMerge = PyPDF2.PdfMerger()try:for pdf in pdfLists:pdfMerge.append(pdf, import_outline=False)pdfMerge.write(pdfFileN)pdfMerge.closeprint("PDF files merged successfully!")except:eg.msgbox("合并pdf失败!", title="结束", ok_button="Fail")sys.exit(0)pdf =  pdfplumber.open(pdfFileN)
dct = dict()
for page in pdf.pages:tables = page.extract_tables(table_settings = {})for table in tables:for lst in table:tmp = lst[1:]tmp = [tmp[0]]+tmp[3:8]+[tmp[-1]]try:tmp[0] = tmp[0].replace('\n','')tmp[0] = tmp[0].split('/')tmp[0] = tmp[0][-1]except:passif lst[0]=='时间':dct[lst[0]] = tmp[0]else:dct[','.join([lst[0],tmp[0] if tmp[0] else ''])] = ','.join(tmp[1:]) if all(tmp[1:]) else ''
pdf.close()
try:os.remove(pdfFileN)
except:pass
try:fn = "考勤表(" + dct['时间'] + ")"+strDateTime()+".csv"
except:fn = "考勤表"+strDateTime()+".csv"
try:with open(fn, 'w') as f:for k,v in dct.items():print(','.join([k,v]), file=f)eg.msgbox(f"考勤表保存成功!\n\n\n\t文件名:{fn}", title="结束", ok_button="Good!")print(f"CSV file written successfully! by HannYang {strDateTime()}")
except:eg.msgbox("保存csv文件失败!", title="结束", ok_button="Fail")

后话

如要直接输出Excel表格,则另要安装和导入xlwt模块。大致代码如下:

    myxl = xlwt.Workbook()
    style = xlwt.easyxf('align: wrap yes; align: horiz center; font: bold yes;borders:top thin; borders:bottom thin; borders:left thin; borders:right thin;') 
    sheet = myxl.add_sheet('考勤表')
    wcol = [20,40,50,75,40,75]
    for i in range(6):
        sheet.col(i).width = wcol[i]*80
    sheet.write_merge(0,0,0,8,'出勤统计报表',style)
    style = xlwt.easyxf('borders:top thin; borders:bottom thin; borders:left thin; borders:right thin;') 
    sheet.write_merge(1,1,0,1,'单位(盖章):',style)
    sheet.write_merge(2,2,0,1,'*经办人:',style)
    sheet.write(1,3,'填表日期:',style)
    sheet.write_merge(1,1,4,8,strToday(),style)
    sheet.write(2,3,'*联系电话:',style)
    sheet.write(2,2,adminName,style)
    sheet.write_merge(2,2,4,8,adminMobil,style)
    for i,t in enumerate(head.strip().split(',')):
            sheet.write(3,i,t,style)
    with open('考勤表.csv', 'r') as f:
        for i,row in enumerate(csv.reader(f)):
            if i==0:continue
            for j,col in enumerate(row):
                    sheet.write(3+i,j,col,style)
    excelfile = 'Output_'+strDateTime()+'('+defaultValue+').xls'
    myxl.save(excelfile)

另外不赶时间的话,可以用PySimpleGUI库写个带漂亮gui界面的程序,具体参见:

探索PySimpleGUI:一款简洁易用的图形用户界面库-CSDN博客文章浏览阅读1.9k次,点赞105次,收藏88次。PySimpleGUI是一个基于Tkinter、WxPython、Qt等底层库构建的图形界面框架,其设计目标是使Python GUI编程变得更加简单直观,大大降低了入门门槛。无论是初学者还是经验丰富的开发者,都可以快速上手并高效地创建出功能丰富、外观现代的桌面应用程序。PySimpleGUI的核心优势在于其高度抽象化的API设计,它提供了包括按钮、输入框、列表框、滑块等各种常见的GUI元素。除了基本的布局和样式设置,PySimpleGUI还支持事件驱动的编程模型。https://blog.csdn.net/boysoft2002/article/details/135315323


完。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/321344.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华清远见作业第二十一天——IO(第四天)

思维导图&#xff1a; 创建出三个进程完成两个文件之间拷贝工作&#xff0c;子进程1拷贝前一半内容&#xff0c;子进程2拷贝后一半内容&#xff0c;父进程回收子进程的资源。 代码&#xff1a; #include<myhead.h> int main(int argc, const char *argv[]) {if(argc!3)…

使用results.csv文件数据绘制mAP对比图

yolov5每次train完成&#xff08;如果没有中途退出&#xff09;都会在run目录下生成expX目录&#xff08;X代表生成结果次数 第一次训练完成生成exp0 第二次生成exp1…以此类推&#xff09;。expX目录下会保存训练生成的weights以及result.txt文件&#xff0c;其中weights是训练…

freeRTOS——队列集知识总结及实战

1队列集概念 可以在任务间传递不同数据类型的消息 作用&#xff1a;用于对多个队列或信号量进行“监听”&#xff0c;其中不管哪一个消息到来&#xff0c;都可让任务退出阻塞状态 2队列集API函数 1&#xff09;创建队列集 QueueSetHandle_t xQueueCreateSet( const UBaseType…

调用百度地图 API 的步骤详解

百度地图 Web 服务 API 为开发者提供 http/https 接口&#xff0c;即开发者通过 http/https 形式发起检索请求&#xff0c;获取返回 json 或 xml 格式的检索数据。用户可以基于此开发 JavaScript、C#、C、Java 等语言的地图应用。百度地图 API 在线地址为&#xff1a;baidumap.…

C#使用switch多路选择语句判断何为季节

目录 一、 switch语句 二、示例 三、生成 一、 switch语句 switch语句是多路选择语句&#xff0c;它通过一个表达式的值来使程序从多个分支中选取一个用于执行的分支。 switch表达式的值只可以是整型、字符串、枚举和布尔类型。 switch语句中多个case可以使用一个break。 在…

氢燃料电池——产品标准规范汇总和梳理

文章目录 氢燃料电池模块 氢燃料电池发动机 氢燃料电池汽车 加氢系统 总结 氢燃料电池模块 GB/T 33978-2017 道路车辆用质子交换膜燃料电池模块 GB/T 43361-2023 气体分析 道路车辆用质子交换膜燃料电池氢燃料分析方法的确认 GB/T 29729-2022 氢系统安全的基本要求 GB/T 4…

python报错:TypeError: Descriptors cannot be created directly.

问题 报错提示&#xff1a; TypeError&#xff1a;不能直接创建描述符。 如果此调用来自 _pb2.py 文件&#xff0c;则您生成的代码已过期&#xff0c;必须使用 protoc > 3.19.0 重新生成。 如果您不能立即重新生成原型&#xff0c;其他一些可能的解决方法是&#xff1a; 1.…

(JAVA)-(网络编程)-初始网络编程

网络编程就是在通信协议下&#xff0c;不同的计算机上运行的程序&#xff0c;进行的数据传输。 讲的通俗一点&#xff0c;就是以前我们写的代码是单机版的&#xff0c;网络编程就是联机版的。 应用场景&#xff1a;即时通信&#xff0c;网游对战&#xff0c;金融证券&#xf…

C之BS开发

一、 BS 概述与 boa 搭建 1.1 BS 模式开发概述 BS 模式&#xff1a; 浏览器与服务器模式&#xff0c; 即通过浏览器访问服务器的 Web 资源。 1.1.1 web 前端开发技术 主要包含&#xff1a; HTML 、 CSS 、 XML/JSON 、 Javascript 、 AJAX HTML 超文本标记语言 ( 英文全称…

IDEA+SpringBoot项目下静态资源访问路径陷阱:静态资源访问404

IDEASpringBoot项目下静态资源访问路径陷阱&#xff1a;静态资源访问404 今天使用SpringBoot项目的时候遇到静态资源访问不到的问题——404。接下来就是这篇博客所说的问题了——>静态资源访问不到&#xff0c;404。 今天使用SpringBoot项目的时候遇到静态资源访问不到的问…

在Ubuntu22.04上部署Stable Diffusion

在AI绘画软件领域Stable-Diffusion&#xff08;简称SD&#xff09;在开源领域绝对是不二之选&#xff0c;他的插件方式可以让此软件具有更多的功能&#xff0c;开发者社群为此提供了大量免费高质量的外接预训练模型&#xff08;fine-tune&#xff09;和插件&#xff0c;并持续维…

若依项目(ruoy-vue)多模块依赖情况简要分析

主pom文件关键点分析 properties标签声明变量信息&#xff1a;版本号、编码类型、java版本spring-boot依赖形式&#xff1a;spring-boot-dependencies、pom、importdependencies中添加本项目内部模块&#xff0c;同时在modules中声明模块packaging打包选择pom设置打包maven-co…