参考资料https://www.zhihu.com/column/pyqt5
最终效果软件
导入安装包
pip install PyQt5 -i https://pypi.douban.com/simple
pip install PyQt5-tools -i https://pypi.douban.com/simple
要使用PyQt5编写一个文本处理程序,你可以按照以下步骤进行:
安装PyQt5:如果你还没有安装PyQt5,请使用pip安装它。打开命令提示符或终端窗口,然后运行以下命令:
shell
pip install PyQt5 -i https://pypi.douban.com/simple
pip uninstall PyQt5
# 不要安装下面的
pip install PyQt5-tools -i https://pypi.douban.com/simple
pip uninstall PyQt5-tools
pip install --upgrade sip -i https://pypi.douban.com/simple
pip install PyQt5 --use-feature=2020-resolver -i https://pypi.douban.com/simple
pip install --upgrade pyqt5-plugins -i https://pypi.douban.com/simple
pip install --upgrade sip -i https://pypi.douban.com/simple
pip install --upgrade pyqt5 -i https://pypi.douban.com/simple
创建主窗口:使用PyQt5创建一个主窗口,这将作为应用程序的入口点。你可以使用Qt Designer设计主窗口的界面,或者手动编写代码来创建窗口。
添加文本处理功能:根据你的需求,在主窗口中添加文本处理功能。这可能包括打开和保存文本文件、编辑文本、查找和替换文本、格式化文本等。你可以使用QTextEdit、QPlainTextEdit等控件来显示和编辑文本。
编写处理函数:为文本处理功能编写函数,以便在需要时执行。例如,你可以编写一个函数来查找文本中的特定字符串,并高亮显示它们。
连接信号和槽:在PyQt5中,信号和槽机制用于处理事件和消息。你可以将按钮的点击事件与相应的槽函数连接起来,以便在用户单击按钮时执行特定的操作。
运行应用程序:最后,运行应用程序并测试它是否按预期工作。你可以使用QApplication对象来运行应用程序,并使用主窗口对象显示它。
下面是一个简单的示例代码,演示如何使用PyQt5创建一个基本的文本处理程序:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QTextEdit, QVBoxLayout, QWidget
class TextProcessor(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('Text Processor')
self.setGeometry(300, 300, 300, 200)
# 创建文本编辑器和按钮
self.text_edit = QTextEdit(self)
self.button = QPushButton('Process', self)
self.button.clicked.connect(self.processText)
# 创建垂直布局并将控件添加到布局中
layout = QVBoxLayout()
layout.addWidget(self.text_edit)
layout.addWidget(self.button)
# 创建容器并将布局添加到容器中
container = QWidget()
container.setLayout(layout)
self.setCentralWidget(container)
def processText(self):
# 处理文本的代码将放在这里
pass
if __name__ == '__main__':
app = QApplication(sys.argv)
processor = TextProcessor()
processor.show()
sys.exit(app.exec_())
在这个示例中,我们创建了一个名为TextProcessor的类,它继承自QMainWindow。我们创建了一个QTextEdit控件和一个QPushButton控件,并将它们添加到一个垂直布局中。我们还连接了按钮的点击事件与processText方法。processText方法将在用户单击按钮时被调用,你可以在这里编写处理文本的代码。最后,我们创建了一个QApplication对象并显示主窗口。
最终完整代码
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QFileDialog, QLabel, QLineEdit
from PyQt5.QtGui import QIcon
from openpyxl import load_workbook
from openpyxl.styles import *
import pandas as pd
import string
import os
from openpyxl import Workbook
class FileProcessor(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('冬装奖励处理')
self.setWindowIcon(QIcon('icon.png')) # 设置窗口图标,需要一个PNG格式的图标文件
self.setGeometry(300, 300, 500, 200) # 设置窗口位置和大小
layout = QVBoxLayout() # 创建垂直布局
# 创建文件选择按钮和标签
self.input_btn = QPushButton('选择文件')
self.input_btn.clicked.connect(self.select_file)
layout.addWidget(self.input_btn)
self.input_label = QLabel('请选择文件')
layout.addWidget(self.input_label)
# 创建处理按钮和处理标签
self.process_btn = QPushButton('处理文件')
self.process_btn.clicked.connect(self.process_file)
layout.addWidget(self.process_btn)
self.process_label = QLabel('处理中...')
layout.addWidget(self.process_label)
# 创建输出标签和文件路径输入框
self.output_label = QLabel('输出文件路径:')
layout.addWidget(self.output_label)
self.output_line = QLineEdit()
layout.addWidget(self.output_line)
# 将布局设置到窗口上
self.setLayout(layout)
self.show()
def select_file(self):
# 打开文件选择对话框,并获取选中的文件路径
fname = QFileDialog.getOpenFileName(self, '打开文件', os.getcwd())[0]
if fname: # 如果用户选择了文件
self.input_label.setText('已选择文件:' + fname) # 更新标签显示选中的文件路径
self.output_line.setText(fname) # 将输出路径设置为选中的文件路径,这里仅作示例,实际上你可能需要生成一个新的文件名或目录结构
def process_file(self):
# 这里是处理文件的逻辑,例如读取选中的文件内容并保存到新的文件中。这里只是一个示例。
selected_file = self.input_label.text().split(':')[1] # 获取选中的文件路径(去掉“已选择文件:”文字)
print(selected_file)
parent_path = os.path.dirname(selected_file)
file_path2 = parent_path + '/冬季奖励数据处理结果.xlsx'
self.data_deal(selected_file)
print(file_path2+'数据处理')
self.style_deal(file_path2)
print(file_path2 + '格式处理')
self.process_label.setText('文件已处理!') # 更新标签显示处理完成的信息(这里只是一个示例)
self.output_line.setText(file_path2) # 更新输出路径的显示(这里只是一个示例)
@staticmethod
def create_excel(self, file_path):
# 没有就创建
if os.path.exists(file_path):
print("文件已存在")
print(file_path)
else:
# 创建一个新的 Excel 文件
wb = Workbook()
wb.save(file_path)
@staticmethod
def set_cell_style(self, ws):
# 边框
border = Border(
left=Side(border_style='thin', color='000000'),
right=Side(border_style='thin', color='000000'),
top=Side(border_style='thin', color='000000'),
bottom=Side(border_style='thin', color='000000'),
)
# 对齐
alignment = Alignment(
horizontal='center',
vertical='center',
text_rotation=0,
indent=0
)
# 字体
font = Font(
name='微软雅黑',
size=11,
bold=False,
italic=False,
strike=False,
color='000000'
)
rows = ws.max_row # 获取最大行
columns = ws.max_column # 获取最大列
# 遍历表格内容,注意:openpyxl下标是从1开始
for i in range(1, rows + 1):
for j in range(1, columns + 1):
# 设置边框
ws.cell(i, j).border = border
# 设置居中对齐
ws.cell(i, j).alignment = alignment
# 设置字体
ws.cell(i, j).font = font
return ws
@staticmethod
def number_to_column(self, n):
"""Convert a number to the corresponding column letter in Excel"""
column = ""
while n > 0:
n -= 1
column = string.ascii_uppercase[n % 26] + column
n //= 26
return column
@staticmethod
def auto_col_width(self, ws):
lks = [] # 英文变量太费劲,用汉语首字拼音代替
for i in range(1, ws.max_column + 1): # 每列循环
lk = 1 # 定义初始列宽,并在每个行循环完成后重置
for j in range(1, ws.max_row + 1): # 每行循环
sz = ws.cell(row=j, column=i).value # 每个单元格内容
if isinstance(sz, str): # 中文占用多个字节,需要分开处理
lk1 = len(sz.encode('gbk')) # gbk解码一个中文两字节,utf-8一个中文三字节,gbk合适
else:
lk1 = len(str(sz))
if lk < lk1:
lk = lk1 # 借助每行循环将最大值存入lk中
# print(lk)
lks.append(lk) # 将每列最大宽度加入列表。(犯了一个错,用lks = lks.append(lk)报错,append会修改列表变量,返回值none,而none不能继续用append方法)
# 第二步:设置列宽
for i in range(1, ws.max_column + 1):
k = self.number_to_column(i) # 将数字转化为列名,26个字母以内也可以用[chr(i).upper() for i in range(97, 123)],不用导入模块
ws.column_dimensions[k].width = lks[i - 1] + 2 # 设置列宽,一般加两个字节宽度,可以根据实际情况灵活调整
return ws
@staticmethod
def sheet_name_deal(self, file_path):
wb = load_workbook(file_path)
# 获取sheet页,修改第一个sheet页面名为销售明细
name1 = wb.sheetnames[0]
ws1 = wb[name1]
ws1.title = "销售明细"
wb.save(file_path)
# 首行
@staticmethod
def style_deal(self, file_path1):
wb = load_workbook(file_path1)
name_list = wb.sheetnames
for name in name_list:
ws = wb[name]
self.set_cell_style(ws)
# 自适应列宽
self.auto_col_width(ws)
wb.save(file_path1)
@staticmethod
def data_deal(self, file_path1):
# 使用os.path.dirname()获取父路径
parent_path = os.path.dirname(file_path1)
file_path2 = parent_path+'/冬季奖励数据处理结果.xlsx'
self.sheet_name_deal(file_path1)
self.create_excel(file_path2)
# 读入数据
df1 = pd.read_excel(file_path1, sheet_name='销售明细')
df2 = df1[df1['季节名称'] == '冬'].copy()
# 筛选品类
category_list = ['大衣', '派克服', '皮毛一体', '皮羽绒', '羽绒服', '麂皮绒', '坎毛', '水貂派克服', '雪兰貂']
# 字典
category_dict = dict(zip(category_list, [True] * len(category_list)))
df2 = df2.loc[df2['品类名称'].isin(category_list), :]
# 修改直销价为浮点类型
df2['直销价'] = df2['直销价'].astype('float')
# 单价在500元以上 1000元以下的衣服
df3 = df2[(df2['直销价'] >= 500) & (df2['直销价'] < 1000)].copy()
# 单价在1000元以上的衣服
df4 = df2[df2['直销价'] >= 1000].copy()
# 500-1000部门商店品类销售数量
index_list = ['日期', '部门名称', '商店名称', '品类名称']
value_list = ['销售数量']
df31 = df3.pivot_table(index=index_list, values=value_list, aggfunc='sum')
df31['提成金额'] = df31['销售数量'] * 50
df31 = df31.reset_index()
# 部门客户销售数量
index_list = ['日期', '部门名称', '商店名称']
value_list = ['销售数量']
df32 = df3.pivot_table(index=index_list, values=value_list, aggfunc='sum')
df32['提成金额'] = df32['销售数量'] * 50
df32 = df32.reset_index()
# 1000元以上部门商店品类销售数量
index_list = ['日期', '部门名称', '商店名称', '品类名称']
value_list = ['销售数量']
df41 = df4.pivot_table(index=index_list, values=value_list, aggfunc='sum')
df41['提成金额'] = df41['销售数量'] * 100
df41 = df41.reset_index()
# 部门客户销售数量
index_list = ['日期', '部门名称', '商店名称']
value_list = ['销售数量']
df42 = df4.pivot_table(index=index_list, values=value_list, aggfunc='sum')
df42['提成金额'] = df42['销售数量'] * 100
df42 = df42.reset_index()
# 部门品类销售数量
df51 = df31.copy()
df52 = df41.copy()
df51['500元档位数量'] = df51.pop('销售数量')
df52['1000元档位数量'] = df52.pop('销售数量')
index_list = ['部门名称', '品类名称']
value_list = ['500元档位数量']
df511 = df51.pivot_table(index=index_list, values=value_list, aggfunc='sum')
value_list = ['1000元档位数量']
df521 = df52.pivot_table(index=index_list, values=value_list, aggfunc='sum')
df53 = pd.merge(df511, df521, how='outer', left_index=True, right_index=True)
df54 = df53.reset_index()
df54 = df54.fillna(0)
# 日期部门客户大类备注
df60 = df2.copy()
df61 = df60[df60['直销价'] >= 500]
index_list = ['日期', '部门名称', '商店名称']
column_list = ['品类名称']
# value_list = ['销售数量']
df666 = df61.pivot_table(index=index_list, columns=column_list, values='销售数量', aggfunc='sum')
df666 = df666.reset_index()
# 生成备注列
notes_list = []
# 获取列名
start_len = len(index_list)
column_list = df666.columns.tolist()
df666 = df666.fillna(0)
for row in df666.itertuples():
strings = ''
for pos in range(start_len, len(column_list)):
col_name = column_list[pos]
num = getattr(row, col_name)
num = int(num)
if num != 0:
strings = strings + str(num) + '件' + col_name + ','
# 切片操作
strings = strings[:-1] + "" # 将最后一个字符替换为空
notes_list.append(strings)
# 删除品类列
sum_len = len(column_list)
df667 = df666.copy()
for pos in range(start_len, sum_len):
col_name = column_list[pos]
df667.pop(col_name)
df667['备注'] = pd.Series(notes_list)
# 获取部门客户品类
df71 = df31.copy()
df72 = df41.copy()
df71['500元档位数量'] = df71.pop('销售数量')
df72['1000元档位数量'] = df72.pop('销售数量')
index_list = ['日期', '部门名称', '商店名称']
value_list = ['500元档位数量']
df711 = df71.pivot_table(index=index_list, values=value_list, aggfunc='sum')
value_list = ['1000元档位数量']
df721 = df72.pivot_table(index=index_list, values=value_list, aggfunc='sum')
df73 = pd.merge(df711, df721, how='outer', left_index=True, right_index=True)
df74 = df73.reset_index()
df74 = df74.fillna(0)
df74['总奖励金额'] = df74['500元档位数量'] * 50 + df74['1000元档位数量'] * 100
df75 = pd.merge(df74, df667, how='left')
wb = load_workbook(file_path2)
# 获取sheet页,修改第一个sheet页面为
name1 = wb.sheetnames[0]
ws1 = wb[name1]
ws1.title = "500-1000冬装销售明细"
# 创建工作表
wb.create_sheet("500-1000客户品类销售")
wb.create_sheet("500-1000客户销售")
wb.create_sheet("1000以上冬装销售明细")
wb.create_sheet("1000以上客户品类销售")
wb.create_sheet("1000以上客户销售")
wb.create_sheet("部门品类销售")
wb.create_sheet("部门客户品类销售")
wb.create_sheet("部门客户销售备注")
wb.create_sheet("部门客户档位销售")
wb.save(file_path2)
# 将生成的工作表导入到程序中
result_sheet = pd.ExcelWriter(file_path2, engine='openpyxl') # 先定义要存入的文件名xxx,然后分别存入xxx下不同的sheet
# df1将0转变为空
df3.to_excel(result_sheet, "500-1000冬装销售明细", index=False, na_rep=0, inf_rep=0)
df31.to_excel(result_sheet, "500-1000客户品类销售", index=False, na_rep=0, inf_rep=0)
df32.to_excel(result_sheet, "500-1000客户销售", index=False, na_rep=0, inf_rep=0)
df4.to_excel(result_sheet, "1000以上冬装销售明细", index=False, na_rep=0, inf_rep=0)
df41.to_excel(result_sheet, "1000以上客户品类销售", index=False, na_rep=0, inf_rep=0)
df42.to_excel(result_sheet, "1000以上客户销售", index=False, na_rep=0, inf_rep=0)
df54.to_excel(result_sheet, "部门品类销售", index=False, na_rep=0, inf_rep=0)
df666.to_excel(result_sheet, "部门客户品类销售", index=False, na_rep=0, inf_rep=0)
df667.to_excel(result_sheet, "部门客户销售备注", index=False, na_rep=0, inf_rep=0)
df75.to_excel(result_sheet, "客户档位销售", index=False, na_rep=0, inf_rep=0)
# 这步不能省,否则不生成文件
result_sheet._save()
if __name__ == '__main__':
app = QApplication(sys.argv)
processor = FileProcessor()
processor.show()
sys.exit(app.exec_())
打包成exe软件
安装依赖
pip install pyinstaller -i https://pypi.tuna.tsinghua.edu.cn/simple
使用pyinstaller将py文件打包为exe
1.打开对应py文件,在Terminal终端,输入:pyinstaller -F -w ’文件名‘.py
pyinstaller -F -w 文件处理.py
生成的exe文件位置在哪里?
打包后的exe文件在项目的dist目录下:
最终效果