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个对话框简单了事:

选择一个文件夹,把其下的所有pdf文件合并,然后转换输出csv文件: 

输出的文件格式如下:

更多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 eg

def 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 += tt
    return text

def 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.close
        print("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:
                pass
            if 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


完。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

年底了,准备跳槽的可以看看...

前两天跟朋友感慨,今年的铜九铁十、裁员、疫情导致好多人都没拿到offer!现在已经1月了,具体明年的金三银四只剩下两个月。 对于想跳槽的职场人来说,绝对要从现在开始做准备了。这时候,很多高薪技术岗、管理岗的缺口和市场需求也出…

企业该如何选择好的跨境数据传输平台

跨境数据传输平台是一种可以帮助企业在不同国家和地区之间安全传输数据的工具。它可以通过对数据进行加密、脱敏、压缩等处理,确保数据在传输过程中的安全性和完整性。同时,它还可以根据不同的合规要求,对数据进行分类、分级、备份等处理&…

Prometheus实战篇:Prometheus监控redis

准备环境 docker-compose安装redis docker-compose.yaml version: 3 services:redis:image:redis:5container_name: rediscommand: redis-server --requirepass 123456 --maxmemory 512mbrestart: alwaysvolumes:- /data/redis/data: /dataport:- "6379:6379"dock…

数据结构之各大排序(C语言版)

我们这里话不多说,排序重要性大家都很清楚,所以我们直接开始。 我们就按照这张图来一一实现吧! 一.直接插入排序与希尔排序. 这个是我之前写过的内容了,大家可以通过链接去看看详细内容。 算法之插入排序及希尔排序&#xff08…

Spring中的工厂类

目录 1.ApplicationContext 4.2.BeanFactory 1.ApplicationContext ApplicationContext的实现类,如下图: ClassPathXmlApplicationContext:加载类路径下 Spring 的配置文件 FileSystemXmlApplicationContext:加载本地磁盘下 S…

安徽2024考试公告一览表!有需要的速收藏

考公群体,越来越多! 考研减少的很多学生转来考公,24年国考人数突破291万,较23年增长约40万 考试难度,逐年增大,逐年创新! 结束的24国考,江浙省考,学生普遍反映难度增大&a…

[C#]使用OpenCvSharp实现二维码图像增强超分辨率

【官方框架地址】 github.com/shimat/opencvsharp 【算法介绍】 借助于opencv自带sr.prototxt和sr.caffemodel实现对二维码图像增强 【效果展示】 【实现部分代码】 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin…

代码随想录-刷题第四十七天

139. 单词拆分 题目链接:139. 单词拆分 思路:本题可以使用记忆化回溯,不再过多介绍,主要讲解完全背包方法。 单词就是物品,字符串s就是背包,单词能否组成字符串s,就是问物品能不能把背包装满。…

VSCode编辑器下载与安装

1、下载 官网下载地址: 打开下载地址,如下图,根据自己的平台选择相应版本下载(本文只针对Windows系统的安装,所以下载Windows版的)。 点击会自动下载,下载完成文件如下图: 2、安装…

python入门,list列表详解

目录 1.list的定义 2.index查找某元素的下标 3.修改 ​编辑 4.插入 ​编辑 5.追加元素 1.append,追加到尾部 2.extend,追加一批元素 ​编辑 6.删除元素 1.del 列表[下标] 2.列表.pop(下标) 3.列表.remove(元素) 7.清空列表 8.统计某一元素在列表内的数量 9.计算…

计算机组成原理 控制器

控制器 #mermaid-svg-cDexVavlf0QIZRSF {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-cDexVavlf0QIZRSF .error-icon{fill:#552222;}#mermaid-svg-cDexVavlf0QIZRSF .error-text{fill:#552222;stroke:#552222;}#me…

iOS苹果和Android安卓测试APP应用程序的差异

Hello大家好呀,我是咕噜铁蛋!我们经常需要关注移动应用程序的测试和优化,以提供更好的用户体验。在移动应用开发领域,iOS和Android是两个主要的操作系统平台。本文铁蛋讲给各位小伙伴们详细介绍在App测试中iOS和Android的差异&…

设计模式之装饰者模式【结构型模式】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档> 学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。各位小伙伴,如果您: 想系统/深入学习某…

Linux内存管理:(五)反向映射RMAP

文章说明: Linux内核版本:5.0 架构:ARM64 参考资料及图片来源:《奔跑吧Linux内核》 Linux 5.0内核源码注释仓库地址: zhangzihengya/LinuxSourceCode_v5.0_study (github.com) 1. 前置知识:page数据结…

【unity】基于Obi的绳/杆蓝图、绳杆区别及其创建方法

绳索 是通过使用距离和弯曲约束将粒子连接起来而形成的。由于规则粒子没有方向(只有位置),因此无法模拟扭转效应(维基百科),绳子也无法保持其静止形状。然而,与杆不同的是,绳索可以被撕裂/劈开,并且可以在运行时改变其…

LeetCode(36)有效的数独 ⭐⭐

请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图) 注…

微商城怎么弄才能开通呢?

​微商城的开通,对于许多商家来说,是进入移动电商领域的重要一步。它不仅能帮助你扩大销售渠道,还能让你更好地管理和服务你的客户。那么,微商城怎么弄才能开通呢? 1、注册微信公众号:首先,你需…

奇数码问题

title: 奇数码问题 date: 2024-01-05 11:52:04 tags: 逆序对 cstefories: 算法进阶指南 题目大意 解题思路 将二维转化为一维&#xff0c;求他的逆序对&#xff0c;如果逆序对的奇偶性相同&#xff0c;则能够实现。 代码实现 #include<iostream> #include<string.h&…

《MySQL系列-InnoDB引擎05》MySQL索引与算法

文章目录 第五章 索引与算法1 InnoDB存储引擎索引概述2 数据结构与算法2.1 二分查找法2.2 二分查找树和平衡二叉树 3 B树3.1 B树的插入操作3.2 B树的删除操作 4 B树索引4.1 聚集索引4.2 辅助索引4.3 B树索引的分裂 5 Cardinality值5.1 什么是Cardinality5.2 InnoDB存储引擎的Ca…

本地引入Element UI后导致图标显示异常

引入方式 npm 安装 推荐使用 npm 的方式安装&#xff0c;它能更好地和 webpack 打包工具配合使用。 npm i element-ui -SCDN 目前可以通过 unpkg.com/element-ui 获取到最新版本的资源&#xff0c;在页面上引入 js 和 css 文件即可开始使用。 <!-- 引入样式 --> <…