吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 136|回复: 3
收起左侧

[其他求助] 希望把代码中的功能用def函数包起来,之后我把gui界面里按钮和函数关联起来

[复制链接]
mango1022 发表于 2024-9-17 16:18
25吾爱币
写了一个py代码用于将Excel中的每日日报整合生成每周的周报,现在只能用cmd运行不好看,我现在用PySimpleGUI做了个GUI界面,但是由于功能是边想边写的所以导致代码顺序杂乱,所以希望把代码中的功能用def函数包起来,到时候我再添加到gui界面里面当点击某个按钮时候执行那个功能。



[Python] 纯文本查看 复制代码
import subprocess 
import string 
import glob 
import os 
import openpyxl 
from openpyxl import load_workbook
from docx import Document
from docx.oxml.ns import qn
from docx.shared import Pt
import datetime 
from datetime import datetime, timedelta

# 用户输入日期字符串
# 提示用户输入日期,并存储为字符串
def get_valid_date():
    while True:
        valid_date = input(" 请输入统计时间(例如:2024.7.19): ")
        try:
            # 尝试将输入转换为日期格式
            date_obj111 = datetime.strptime(valid_date, "%Y.%m.%d")
            return date_obj111.date()
        except ValueError:
            # 如果转换失败,说明输入格式不正确,提示用户重新输入
            print("")
            print("输入的日期格式不正确,请按照示例重新输入!\n")


date_str = get_valid_date() # 调用函数获取有效日期

user_input_date = date_str.strftime("%Y.%m.%d") # 以字符串形式输出日期,使用 strftime 方法

tjr = '张三' # 统计人姓名

# 将用户输入的日期字符串转换为datetime对象
try:
    date_obj = datetime.strptime(user_input_date, "%Y.%m.%d")

    tjsj = f"{date_obj.year}年{date_obj.month}月{date_obj.day}日"   # 将datetime对象格式化为中文日期格式: 2024年12月12日
    
    gzbm = date_obj.strftime("%Y%m%d")  # 将datetime对象格式化为工作表名格式: 20241212
    
    wjm = f"{date_obj.year}.{date_obj.month}"   # 将datetime对象格式化为文件名格式: 2024.12
    
    four_days_ago = date_obj - timedelta(days=4)    # 计算四天前的日期
    
    four_days_ago_str = f"{four_days_ago.year}年{four_days_ago.month}月{four_days_ago.day}日"   # 将四天前的日期格式化为中文日期格式: 2024年12月8日

# 如果日期格式错误,捕获ValueError异常并给出提示
except ValueError:
    print("输入的日期格式不正确,请按照 YYYY.M.D 的格式重新输入!")

# 定义一个函数来查找指定日期的Excel文件
def find_excel_file(date_str):
    # 构造文件模式
    file_pattern = f"工作日报{date_str}.xlsx"
    directory = 'D:\工作日报'
    # 使用指定的目录
    # matching_files = glob.glob(os.path.join(os.getcwd(), file_pattern))  # 原来的代码
    matching_files = glob.glob(os.path.join(directory, file_pattern))  # 修改后的代码
    
    # 检查找到的文件数量
    if len(matching_files) == 1:
        # 如果只有一个文件,返回文件路径
        return matching_files[0]
    elif len(matching_files) > 1: 
        # 如果找到多个文件,抛出异常
        print(" ")
        print("找到多个匹配的文件,请检查是否有重复命名的文件。")
        input("按回车键继续。")
        raise Exception
    else:
        # 如果没有找到文件,抛出文件未找到异常
        print(" ")
        print(f"未找到匹配的文件:“{file_pattern}”\n \n请检查文件是否存在此目录下:“{directory}”\n")
        input("按回车键继续。")
        raise FileNotFoundError
        

# 尝试查找Excel文件
try:
    
    excel_file_path = find_excel_file(wjm)  # 调用find_excel_file函数
    workbook = openpyxl.load_workbook(excel_file_path)  # 加载工作簿
    sheet_name = gzbm   # 获取指定名称的工作表
    
    if sheet_name in workbook.sheetnames:
        # 获取工作表索引
        sheet_index = workbook.sheetnames.index(sheet_name)
        # 检查工作表前后是否有足够的工作表
        if sheet_index >= 4:
            # 选取目标工作表前4个工作表
            selected_sheets = workbook.worksheets[sheet_index-4:sheet_index+1]
            #print(f"选取的工作表为:{selected_sheets}")
        else:
            # 如果工作表前不足四个工作表,抛出异常
            print(" ")
            print(f"警告:在选定的工作表“{sheet_name}”前不足四个工作表,请重新输入。\n")
            input("按回车键继续。")
            raise IndexError
            
    else:
        # 如果未找到指定的工作表,抛出异常
        print(" ")
        print(f"未找到指定的工作表“{sheet_name}”,请检查您的输入是否正确。\n")
        input("按回车键继续。")
        raise ValueError
    
except (IndexError, ValueError) as e:
    # 输出异常信息
    print(e)
    # input("按回车键继续。")
    # 可以在此处添加重新尝试的逻辑或直接退出程序

# 定义工作类别选项和优先级顺序
options = ["故障维修", "耗材配送", "设备安装与调试", "例行巡检", "软件安装"]
preferred_order = ["例行巡检", "故障维修", "设备安装与调试", "耗材配送", "软件安装"]

# 初始化分类工作字典
categorized_work = {}

# 遍历选定的工作表
for worksheet in selected_sheets:
    # 初始化非空单元格数量
    last_row = 0
    
    # 遍历B列,计算最后一行
    #统计一个工作表中第2列从第4行开始的非空单元格的数量
    for row in worksheet.iter_rows(min_row=4, min_col=2, max_col=2, values_only=True):
        # 如果单元格不为空,则增加非空单元格数量
        if row[0] is not None:
            # 更新非空单元格数量
            last_row += 1
            
    # 遍历B列和D列,处理工作类别为空的情况
    # 遍历工作表中的B列和D列,如果D列为空,让用户选择工作类别
    for row in worksheet.iter_rows(min_row=4, max_row=last_row, min_col=2, max_col=4):
        # 获取B列和D列的值
        b_column_value = row[0].value
        d_column_value = row[2].value
        # 如果D列工作类别为空,让用户选择工作类别
        if d_column_value is None:
            print(f"\n工作内容为: {b_column_value}")
            print("\n工作类别为空,选择一个工作类别:")
            for i, option in enumerate(options, start=1):
                print(f"{i}. {option}")
            
            # 循环直到用户输入有效的选项
            while True:
                print("")
                choice = input("请输入选项序号:")
                try:
                    choice = int(choice)
                    if 1 <= choice <= len(options):
                        d_column_value = options[choice - 1]
                        break
                    else:
                        print("")
                        print("无效的选项,请重新输入。")
                except ValueError:
                    print("")
                    print("无效的输入,请输入数字序号。")
            
            # 更新D列的值
            row[2].value = d_column_value

# 创建目录(如果不存在)
directory = 'D:\工作日报'
if not os.path.exists(directory):
    os.makedirs(directory)

# 保存修改后的Excel文件
file_name = f"{directory}/工作日报{wjm}.xlsx"
workbook.save(filename=file_name)

# 再次遍历选定的工作表,收集工作内容和类别
for worksheet in selected_sheets:
    # 初始化变量,用于记录工作表中有效数据的最后一行行号
    last_row = 0
    
    # 第一次遍历,从第四行开始,仅读取第二列的数据,以确定有效数据的结束行
    for row in worksheet.iter_rows(min_row=4, min_col=2, max_col=2, values_only=True):
        # 如果该单元格有值,更新last_row计数器
        if row[0] is not None:
            last_row += 1

    # 手动修正last_row的值,增加2以包含可能遗漏的两行数据
    last_row += 2
    #print("最后一行是:", last_row)
    # 第二次遍历,从第四行开始至修正后的最后一行,读取第二列至第四列的数据
    for row in worksheet.iter_rows(min_row=4, max_row=last_row, min_col=2, max_col=4, values_only=True):
        # 分别获取B列和D列的值
        b_column_value = row[0]
         # 将B列的值中的所有小写字母转换为大写字母
        #b_column_value = b_column_value.upper()
        if b_column_value is not None:
            b_column_value = b_column_value.upper()
        d_column_value = row[2]

        # 检查D列的值是否已存在于categorized_work字典中
        if d_column_value not in categorized_work:
            # 若不存在,创建一个新的集合
            categorized_work[d_column_value] = set()

        # 将B列的值添加到对应D列值的集合中
        categorized_work[d_column_value].add(b_column_value)

# 将收集到的集合转换为列表并排序
for category in categorized_work:
    categorized_work[category] = list(categorized_work[category])
    categorized_work[category].sort()

# 定义类别映射
category_mapping = {
    "例行巡检": "日常巡检类",
    "故障维修": "故障处理及维修类",
    "设备安装与调试": "设备安装与调试类",
    "耗材配送": "耗材配送",
    "软件安装": "软件安装"
}

# 加载Word模板文件
template_file = 'D:\生成新周报程序\模板.docx'
doc = Document(template_file)

# 获取文档中的第一个表格
table = doc.tables[0]

# 根据优先级顺序和实际存在的类别构建实际顺序列表
actual_order = [category for category in preferred_order if category in categorized_work]

# 定义中文数字列表
chinese_digits = list(string.digits[:10].translate(str.maketrans("0123456789", "零一二三四五六七八九")))[1:] + ['十']

# 构建编号类别字典
numbered_categories = {}
for idx, category in enumerate(actual_order):
    chinese_number = chinese_digits[idx] if idx < len(chinese_digits) else str(idx + 1)
    numbered_categories[category] = f"{chinese_number}、{category_mapping[category]}"

# 替换表格中的统计信息
for row in table.rows:
    for cell in row.cells:
        if '统计的人' in cell.text:
            cell.text = ''
            p = cell.add_paragraph()
            run = p.add_run(f"{tjr}")
            font = run.font
            font.name = '仿宋'
            run._element.rPr.rFonts.set(qn('w:eastAsia'), '仿宋')
            font.size = Pt(12) 
        elif '统计的时间' in cell.text:
            cell.text = ''
            p = cell.add_paragraph()
            run = p.add_run(f"{tjsj}")
            font = run.font
            font.name = '仿宋'
            run._element.rPr.rFonts.set(qn('w:eastAsia'), '仿宋')
            font.size = Pt(12)
        elif '统计时间段' in cell.text:
            cell.text = ''
            p = cell.add_paragraph()
            run = p.add_run(f'{four_days_ago_str}-{tjsj}')
            font = run.font
            font.name = '仿宋'
            run._element.rPr.rFonts.set(qn('w:eastAsia'), '仿宋')
            font.size = Pt(12)

# 删除表格单元格中的空行
for row in table.rows:
    for cell in row.cells:
        paragraphs_to_remove = [p for p in cell.paragraphs if p.text.strip() == ""]
        for paragraph in paragraphs_to_remove:
            p = paragraph._element
            p.getparent().remove(p)
            p._p = p._element = None
# 遍历表格的每一行
for row in table.rows:
    # 遍历行中的每一个单元格
    for cell in row.cells:
        # 检查单元格文本是否包含“工作内容和类别”
        if '工作内容和类别' in cell.text:
            # 清空单元格文本
            cell.text = ''
            # 移除单元格内所有段落元素
            for paragraph in cell.paragraphs:
                p = paragraph._element
                p.getparent().remove(p)
            paragraph = cell.add_paragraph()
            run = paragraph.add_run("工作量统计:")
            run.font.size = Pt(12)
            run.font.name = '仿宋'
            run._element.rPr.rFonts.set(qn('w:eastAsia'), '仿宋')
                               
            # 遍历实际工作类别顺序
            for idx, category in enumerate(actual_order):
                # 获取显示的类别
                display_category = numbered_categories[category]
                
                # 添加一个新的段落
                p = cell.add_paragraph()
                # 添加类别文本
                run = p.add_run(display_category)
                # 设置字体样式
                font = run.font
                font.name = '仿宋'
                # 设置字体为中文样式
                run._element.rPr.rFonts.set(qn('w:eastAsia'), '仿宋')
                # 设置字体大小
                font.size = Pt(14)
                # 设置字体加粗
                font.bold = True
                
                # 初始化计数器
                counter = 1
                
                # 遍历该类别下的所有工作内容
                for content in categorized_work[category]:
                    # 添加一个新的段落
                    p = cell.add_paragraph()
                    # 添加工作内容文本
                    run = p.add_run(f"{counter}. {content}")
                    # 设置字体样式
                    font = run.font
                    font.name = '仿宋'
                    # 设置字体为中文样式
                    run._element.rPr.rFonts.set(qn('w:eastAsia'), '仿宋')
                    # 设置字体大小
                    font.size = Pt(12)
                    # 增加计数器
                    counter += 1


# 获取当前的日期
today = datetime.now()
# 创建一个datetime对象,表示本月的第一天
first_day_of_month = datetime(today.year, today.month, 1)
# 计算本月的第一个星期一
first_monday_of_month = first_day_of_month - timedelta(days=first_day_of_month.isoweekday() % 7)
# 计算今天是本月的第几周
weeks_into_month = ((today - first_monday_of_month).days + 6) // 7

# 定义输出文件名,只保留年月:2024年7月
scwjm = f"{date_obj.year}年{date_obj.month}月"

# 指定输出文件的完整路径
output_file = f'D:\周报统计\周工作量统计({scwjm}第{weeks_into_month}周) .docx'

# 创建目录(如果不存在)
output_dir = os.path.dirname(output_file)
os.makedirs(output_dir, exist_ok=True)

# 保存文档至输出文件
doc.save(output_file)

# 打印成功写入文件的信息
print(f"\n")
print(f"周报已生成:{output_file}\n")

input("请按回车键继续,周报即将自动打开。")

# 使用系统默认程序打开输出文件
os.startfile(output_file)

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| mango1022 发表于 2024-9-17 16:23
这是日报
 楼主| mango1022 发表于 2024-9-17 16:26
 楼主| mango1022 发表于 2024-9-17 16:20
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-14 01:27

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表