一. 需求

现有一个文件夹,里面存放若干PDF文件。还有一个Excel表格,记录了这些PDF的文件名。现在要进行双向核查,即 Excel表格中的PDF文件名 和 文件夹中的PDF是否一一对应,有无缺漏。

二. 实现过程

大致思路:使用xlrd读取Excel表格进行比对

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import os
import glob
import sys

import xlrd

# 指定要遍历的文件夹路径
folder_path = './pdf'
# 指定Excel文件路径
excel_file_path = './'

try:
"""处理PDF"""
# 使用glob模块获取文件夹中所有的PDF文件
pdf_files = glob.glob(os.path.join(folder_path, '*.pdf'))

# 提取文件名并存储到列表中
pdf_file_names = [os.path.basename(pdf_file) for pdf_file in pdf_files]
pdf_serial_number_list = []
excel_serial_number_list = []

# 式提取第二个-后面的内容
for name in pdf_file_names:
pdf_serial_number_list.append(name.split("-")[2])

"""处理Excel"""
# 过滤出扩展名为.xlsx或.xls的Excel文件
files = os.listdir(excel_file_path)
excel_files = [file for file in files if file.endswith(('.xlsx', '.xls'))]

if len(excel_files) == 1:
# 如果只有一个Excel文件,读取它
excel_file = excel_files[0]
excel_file_path = os.path.join(excel_file_path, excel_file)

elif len(excel_files) == 0:
print("当前目录下没有Excel文件。")
else:
print("当前目录下有多个Excel文件,请确保只有一个Excel文件。")
sys.exit(-1)

# 指定要读取的列数(N从1开始计数)
column_number = 14 # 这里示例为第2列

# 打开Excel文件以进行读取
print(excel_file_path)
workbook = xlrd.open_workbook(excel_file_path)
sheet = workbook.sheet_by_index(0) # 假设要读取第一个工作表

# 从第二行开始获取指定列的数据
column_data = [sheet.cell_value(row, column_number - 1) for row in range(1, sheet.nrows)]

# 打印读取的列数据
for data in column_data:
excel_serial_number_list.append(data.split("-")[1])

with open('output.txt', 'w') as file:
"""以PDF为准,开始比对"""
file.write("回单中存在,流水不存在:\n")
for number in pdf_serial_number_list:
if number not in excel_serial_number_list:
file.write(number + "\n")

file.write("\n")

"""以Excel为准,开始比对"""
file.write("流水中存在,回单不存在:\n")
for number in excel_serial_number_list:
if number not in pdf_serial_number_list:
file.write(number + "\n")
except Exception as e:
with open('error.txt', 'w') as file:
file.write("运行出错,错误信息如下:\n" + e)

三. 打包为单个EXE可执行文件

创建 file_version_info.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# UTF-8
#
# For more details about fixed file info 'ffi' see:
# http://msdn.microsoft.com/en-us/library/ms646997.aspx
VSVersionInfo(
ffi=FixedFileInfo(
# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
# Set not needed items to zero 0. filevers和prodvers应该始终是包含四个项的元组:(1、2、3、4),将不需要的项设置为0
filevers=(1, 0, 0, 0), # 文件版本******,鼠标悬浮exe会显示,也显示在 详细信息-文件版本,这个是检测版本的依据
prodvers=(3, 6, 0, 0), # 生产商,未见显示在哪里
# Contains a bitmask that specifies the valid bits 'flags'r
mask=0x3f, # 两个位掩码
# Contains a bitmask that specifies the Boolean attributes of the file.
flags=0x0,
# The operating system for which this file was designed.
# 0x4 - NT and there is no need to change it.
OS=0x40004, # 为其设计此文件的操作系统,0x4-NT,无需更改它
# The general type of file.
# 0x1 - the file is an application.
fileType=0x1, # 文件的常规类型,0x1-该文件是一个应用程序
# The function of the file.
# 0x0 - the function is not defined for this fileType
subtype=0x0, # 文件的功能,0x0表示该文件类型未定义
# Creation date and time stamp.
date=(0, 0) # 创建日期和时间戳
),
kids=[
StringFileInfo(
[
StringTable(
u'080404b0',
[StringStruct(u'CompanyName', u'515code.com'), # 公司,鼠标悬浮exe会显示
StringStruct(u'FileDescription', u'如如的回单-流水双向核查工具'), # 文件说明,鼠标悬浮exe会显示,也会显示在 详细信息-文件说明
StringStruct(u'FileVersion', u'1.0.0.0'), # 没见哪里显示
StringStruct(u'LegalCopyright', u'Copyright (C) 2023 515code.com'), # 版权,会显示在 详细信息-版权
StringStruct(u'ProductName', u'双向核查工具'), # 原始文件名,会显示在 详细信息-原始文件名
StringStruct(u'ProductVersion', u'1.0.0.0')]) # 产品版本,会显示在 详细信息-产品版本
]),
VarFileInfo([VarStruct(u'Translation', [2052, 1200])]) # 语言,中文简体
]
)

使用pyinstaller,执行命令:

1
pyinstaller --version-file=file_version_info.txt -i icon.ico --onefile main.py

四. 总结

类型 xlrd&xlwt&xlutils pandas OpenPyXL
读取 支持 支持 支持
写入 支持 支持 支持
修改 支持 支持 支持
xls 支持 支持 不支持
xlsx 高版本支持 支持 支持
大文件 不支持 支持 支持
效率
功能 较弱 强大 一般