KeKeBB0609 发表于 2024-4-24 16:42

一个到期时间提醒

浏览到坛友需要一个证书到期提醒的弹窗,索性做了一个
我将在这里一步步解释代码,纯新手可以学习,高手也请指点不足

import tkinter as tk
from tkinter import ttk,Listbox, Button, font, filedialog, messagebox
import pandas as pd
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
import unicodedata
import re
import configparser
import os
file_path=None
refresh_time=None
remaining_days=None

def zengze(value_str):
    number = re.search(r'\d+(\.\d+)?', str(value_str))
    if number:#如果找到了匹配项,提取它的值
      extracted_number = float(number.group())
      return extracted_number
    else:
      return value_str
def pad_to_width(text, width):
    text_width = 0
    for char in text:
      char_width = unicodedata.east_asian_width(char)
      if char_width in ('F', 'W'):
            text_width += 2 #全角和宽字符占用两个字符宽度
      else:
            text_width += 1 #其他字符占用一个字符宽度
    padding_needed = width - text_width
    if padding_needed > 0:
      return text + ' ' * padding_needed
    else:
      return text #如果不需要填充,则直接返回原字符串
def read_excel_file():
    global file_path
    x=int(entry_1.get())
    file_path = filedialog.askopenfilename(filetypes=[("Excel files", "*.xlsx;*.xls")])#打开文件对话框以选择Excel文件
    if file_path:
      try:#使用pandas读取Excel文件
            read_excel_to_dict(file_path,remaining_days)
            xieru(file_path,x)
      except Exception as e:print(f"Error reading Excel file: {e}")#如果发生错误,打印错误信息

def auto_excel_file(file_path):
    x=int(entry_1.get())
    if file_path is not None:
      read_excel_to_dict(file_path,x)
      xieru(file_path,x)
    else:print(f'file_path:{file_path}')

def read_excel_to_dict(file_path, x):
    today = datetime.today().date()#获取当前日期
    df = pd.read_excel(file_path, engine='openpyxl')#使用pandas读取Excel文件
    dict_list = []#初始化一个空列表来存储每行的数据字典
    below_dict_list = []#初始化一个空列表来存储满足条件的数据字典
    for index, row in df.iterrows():#遍历DataFrame的每一行
      credential_name = row['证件名称']
      credential_name = pad_to_width(credential_name,20)
      valid_period_years_1 = row['证件有效期']#证件有效期以年为单位
      valid_period_years = zengze(valid_period_years_1)
      valid_period_years_1 = pad_to_width(f"   {valid_period_years_1}", 11)
      issue_Date = row['发证日期']
      date_str = "{:08d}".format(issue_Date)
      year = int(date_str[:4])
      month = int(date_str)
      day = int(date_str)
      issue_Date = datetime(year, month, day).date()
      expiry_Date_1 = issue_Date + relativedelta(years=valid_period_years)
      youxiaoqi_1 = (expiry_Date_1 - today).days
      days_remaining = pad_to_width(f'   {(expiry_Date_1 - today).days}天', 15)
      expiry_Date_1 = pad_to_width(f" {expiry_Date_1.strftime('%Y-%m-%d')}", 11)
      issue_Date_1 = pad_to_width(issue_Date.strftime('%Y-%m-%d'), 11)

      Personnel_Qualification_Date = row['人员资质日期']
      date_str_1 = "{:08d}".format(Personnel_Qualification_Date)
      year_1 = int(date_str_1[:4])
      month_1 = int(date_str_1)
      day_1 = int(date_str_1)
      Personnel_Qualification_Date = datetime(year_1, month_1, day_1).date()
      Validity_period_of_personnel_qualifications_1 = row['人员资质有效期']
      Validity_period_of_personnel_qualifications = zengze(Validity_period_of_personnel_qualifications_1)
      Expiration_date_of_personnel_qualification = Personnel_Qualification_Date + relativedelta(
            years=Validity_period_of_personnel_qualifications)
      youxiaoqi_2 = (Expiration_date_of_personnel_qualification - today).days
      days_remaining_1 = (Expiration_date_of_personnel_qualification - today).days
      Personnel_Qualification_Date_1 = pad_to_width(Personnel_Qualification_Date.strftime('%Y-%m-%d'), 13)
      Validity_period_of_personnel_qualifications_1 = pad_to_width(f"   {Validity_period_of_personnel_qualifications_1}",11)
      Expiration_date_of_personnel_qualification_1 = pad_to_width(
            f" {Expiration_date_of_personnel_qualification}", 14)
      days_remaining_1_1 = pad_to_width(f'   {days_remaining_1}天', 13)

      Test_report_date = row['检测报告日期']
      date_str_2 = "{:08d}".format(Test_report_date)
      year_2 = int(date_str_2[:4])
      month_2 = int(date_str_2)
      day_2 = int(date_str_2)
      Test_report_date = datetime(year_2, month_2, day_2).date()
      Validity_period_of_testing_report_1 = row['检测报告有效期']
      Validity_period_of_testing_report = zengze(Validity_period_of_testing_report_1)
      Expiration_date_of_testing_report = Test_report_date + relativedelta(years=Validity_period_of_testing_report)
      youxiaoqi_3 = (Expiration_date_of_testing_report - today).days
      days_remaining_2 = (Expiration_date_of_testing_report - today).days
      Test_report_date_1 = pad_to_width(Test_report_date.strftime('%Y-%m-%d'), 10)
      Validity_period_of_testing_report_2 = pad_to_width(f"   {Validity_period_of_personnel_qualifications_1}", 13)
      Expiration_date_of_testing_report_1 = pad_to_width(f"{Expiration_date_of_testing_report.strftime('%Y-%m-%d')}",13)
      days_remaining_2_1 = pad_to_width(f'   {days_remaining_2}天', 13)

       #判断有效期是否小于指定值
      if youxiaoqi_1 < x or youxiaoqi_2 < x or youxiaoqi_3 < x:
         #将满足条件的数据添加到新的字典中
            below_dict = {
                '证件名称': credential_name,
                '发证日期': issue_Date_1,
                '有效期_1': youxiaoqi_1,
                '证件有效期': valid_period_years_1,
                '证件到期日期': expiry_Date_1,
                '证件到期天数': days_remaining,
                '人员资质日期': Personnel_Qualification_Date_1,
                '有效期_2': youxiaoqi_2,
                '人员资质有效期': Validity_period_of_personnel_qualifications_1,
                '人员资质到期日期': Expiration_date_of_personnel_qualification_1,
                '人员资质到期天数': days_remaining_1_1,
                '检测报告日期': Test_report_date_1,
                '有效期_3': youxiaoqi_3,
                '检测报告有效期': Validity_period_of_testing_report_2,
                '检测报告到期日期': Expiration_date_of_testing_report_1,
                '检测报告到期天数': days_remaining_2_1
            }
            below_dict_list.append(below_dict)
      else:
         #将不满足条件的数据添加到原有的字典列表中
            credentials_dict = {
                '证件名称': credential_name,
                '发证日期': issue_Date_1,
                '有效期_1': youxiaoqi_1,
                '证件有效期': valid_period_years_1,
                '证件到期日期': expiry_Date_1,
                '证件到期天数': days_remaining,
                '人员资质日期': Personnel_Qualification_Date_1,
                '有效期_2': youxiaoqi_2,
                '人员资质有效期': Validity_period_of_personnel_qualifications_1,
                '人员资质到期日期': Expiration_date_of_personnel_qualification_1,
                '人员资质到期天数': days_remaining_1_1,
                '检测报告日期': Test_report_date_1,
                '有效期_3': youxiaoqi_3,
                '检测报告有效期': Validity_period_of_testing_report_2,
                '检测报告到期日期': Expiration_date_of_testing_report_1,
                '检测报告到期天数': days_remaining_2_1
            }
            dict_list.append(credentials_dict)

    return below_dict_list, dict_list
def xieru_biaoti():
    upper_listbox.insert(tk.END, f"{pad_to_width('证件名称',20)}{pad_to_width('发证日期', 12)}{pad_to_width('证件有效期', 12)}{pad_to_width('证件到期日期', 14)}{pad_to_width('证件到期天数', 13)}{pad_to_width('人员资质日期', 14)}{pad_to_width('资质有效期', 12)}{pad_to_width('资质到期日期', 14)}{pad_to_width('资质到期天数', 14)}{pad_to_width('检测报告日期', 14)}{pad_to_width('报告有效期', 11)}{pad_to_width('报告到期日期', 14)}报告到期天数")
    below_listbox.insert(tk.END, f"{pad_to_width('证件名称',20)}{pad_to_width('发证日期', 12)}{pad_to_width('证件有效期', 12)}{pad_to_width('证件到期日期', 14)}{pad_to_width('证件到期天数', 13)}{pad_to_width('人员资质日期', 14)}{pad_to_width('资质有效期', 12)}{pad_to_width('资质到期日期', 14)}{pad_to_width('资质到期天数', 14)}{pad_to_width('检测报告日期', 14)}{pad_to_width('报告有效期', 11)}{pad_to_width('报告到期日期', 14)}报告到期天数")
def xieru(file_path,x):
    cert_name = "已到期证件:\n"#初始化cert_name为空字符串
    count = 0# 初始化计数器
    max_per_line = 5# 每行最多显示的证件名称数量
    below_dict_list, dict_list = read_excel_to_dict(file_path, x)
    upper_listbox.delete(0, 'end')
    below_listbox.delete(0, 'end')
    xieru_biaoti()
    for item in dict_list:#在列表框中显示不满足条件的字典数据
      upper_listbox.insert(tk.END, f"{item['证件名称']}\n{item['发证日期']}\n{item['证件有效期']}\n{item['证件到期日期']}\n{item['证件到期天数']}\n{item['人员资质日期']}\n{item['人员资质有效期']}\n{item['人员资质到期日期']}\n{item['人员资质到期天数']}\n{item['检测报告日期']}\n{item['检测报告有效期']}\n{item['检测报告到期日期']}\n{item['检测报告到期天数']}")
    # messagebox.showinfo("到期提示",below_dict_list['证件名称'])
    for dict_item in below_dict_list:
      if '证件名称' in dict_item:
            cert_name = cert_name+pad_to_width(dict_item['证件名称'] ,20)
            count+=1
            if count % max_per_line == 0:# 如果当前行已达到最大数量,则添加换行符,并重置计数器
                cert_name += "\n"
                count = 0

   #在列表框中显示满足条件的字典数据
    for item in below_dict_list:
      below_listbox.insert(tk.END, f"{item['证件名称']}\n{item['发证日期']}\n{item['证件有效期']}\n{item['证件到期日期']}\n{item['证件到期天数']}\n{item['人员资质日期']}\n{item['人员资质有效期']}\n{item['人员资质到期日期']}\n{item['人员资质到期天数']}\n{item['检测报告日期']}\n{item['检测报告有效期']}\n{item['检测报告到期日期']}\n{item['检测报告到期天数']}")
    messagebox.showinfo("到期提示", cert_name)
def read_ini_file(section, option):
    global file_path, refresh_time, remaining_days
    ini_file_path = 'settings.ini'
    config = configparser.ConfigParser()
    if os.path.exists(ini_file_path):
      config.read(ini_file_path)
      if section in config and option in config:
            value = config
         #根据选项类型进行转换
            if option == 'refresh_time':
                try:
                  value = int(value)
                except ValueError:
                  print(f"读取的刷新时间不是有效的整数: {value}")
                  return
            elif option == 'remaining_days':#新添加的剩余天数读取功能
                try:
                  value = int(value)
                except ValueError:
                  print(f"读取的剩余天数不是有效的整数: {value}")
                  return
         #根据选项更新全局变量
            if option == 'file_path':
                file_path = value
                print(f"从settings.ini中读取到文件路径: {file_path}")
            elif option == 'refresh_time':
                refresh_time = value
                print(f"从settings.ini中读取到刷新时间: {refresh_time}秒")
            elif option == 'remaining_days': #更新剩余天数的全局变量
                remaining_days = value
                print(f"从settings.ini中读取到剩余天数: {remaining_days}天")
            else:
                print(f"从settings.ini中读取到{option}的值: {value}")
      else:
            print(f"settings.ini中没有找到[{section}]下的{option}")
    else:
      print("没有找到settings.ini文件")

def on_checkbox_change(*args):
    global file_path
    is_checked = checkbox_var.get()

    if is_checked:
      if not file_path:
            messagebox.showerror("错误", "请先读取一个Excel文件")
            checkbox_var.set(0)
      else:
            config = configparser.ConfigParser()
            config.read('settings.ini')
            config['FILE_SETTINGS'] = {'file_path': file_path}#使用部分
            with open('settings.ini', 'w') as configfile:config.write(configfile)
            print("文件路径已保存到settings.ini中")
            checkbox.config(text="是否记住文件路径:是\n(下次启动程序时将自动读取文件)")
    else:
      config = configparser.ConfigParser()
      config.read('settings.ini')
      if 'FILE_SETTINGS' in config and 'file_path' in config['FILE_SETTINGS']:
            del config['FILE_SETTINGS']['file_path'] #只删除 下的file_path项
            with open('settings.ini', 'w') as configfile:config.write(configfile)
            print("文件路径已从settings.ini中删除")
      checkbox.config(text="是否记住文件路径:否\n(下次启动程序时不会自动读取文件)")
def remaining_time_format(seconds):
      minutes, seconds = divmod(seconds, 60)# 将秒数转换为分钟和秒的格式
      return f"剩余时间: {int(minutes):02d}:{int(seconds):02d}"
def auto_up(*args):
    if checkbox_var_1.get():
      auto_excel_file(file_path)
      Update_time(int(entry.get()))
      if checkbox_var_1:
            time_up=int(int(entry.get())*1000)
            window.after(time_up, auto_up)
def Update_time(remaining_time):
    time_label.config(text=remaining_time_format(remaining_time))
    if remaining_time > 0:window.after(1000,lambda: Update_time(remaining_time-1))
def on_save_config():
    global is_remember_refresh_time
    refresh_time = entry.get()
    is_remember_refresh_time = checkbox_var_1.get()#获取复选框状态
    if is_remember_refresh_time and not refresh_time:
      messagebox.showerror("错误", "请先输入刷新时间")
      return
    try:
      if is_remember_refresh_time:
            refresh_time_int = int(refresh_time)
            config = configparser.ConfigParser()#读取现有的配置文件
            config.read('settings.ini')
            if 'REFRESH_SETTINGS' not in config:#如果配置文件不存在REFRESH_SETTINGS部分,则创建它
                config['REFRESH_SETTINGS'] = {}
            config['REFRESH_SETTINGS']['refresh_time'] = str(refresh_time_int)#更新或写入刷新时间到REFRESH_SETTINGS部分
            checkbox_1.config(text="是否记住刷新时间:是")
      else:#如果复选框未选中,则检查并删除REFRESH_SETTINGS部分(如果存在)
            checkbox_1.config(text="是否记住刷新时间:否")
            if os.path.exists('settings.ini'):
                config = configparser.ConfigParser()
                config.read('settings.ini')
                if 'REFRESH_SETTINGS' in config:#如果存在REFRESH_SETTINGS部分,则删除它
                  del config['REFRESH_SETTINGS']
                with open('settings.ini', 'w') as configfile:#将修改后的配置写回文件
                  config.write(configfile)
                messagebox.showinfo("成功", "已删除刷新时间设置")
                print('刷新时间设置已从settings.ini中删除')
      if is_remember_refresh_time:#如果复选框选中并且有有效输入,将修改后的配置写回文件
            with open('settings.ini', 'w') as configfile:
                config.write(configfile)
            messagebox.showinfo("成功", "刷新时间已保存")
            print('刷新时间已保存到settings.ini中')
            auto_up(None)
    except ValueError:
      checkbox_var_1.set(0)
      messagebox.showerror("错误", "请输入有效的刷新时间(整数)")
   
def on_text_change(P):
    try:
      int(P)#尝试将文本框内容转换为整数
      return True#验证成功,但这里不需要做任何操作,因为验证本身不会改变标签文本
    except ValueError:
      return False#验证失败,返回False阻止字符被输入
#创建一个函数来更新标签文本,当文本框失去焦点时调用
def update_label_text(event):#添加event参数
    try:
      number = int(entry.get())#获取文本框内容并转换为整数
       #更新标签文本
      if number < 10:
            label.config(text=f"秒数已设置为: {number}秒(数据过大时不建议低于10秒)")
      else:
            label.config(text=f"秒数已设置为: {number}秒")
    except ValueError:
       #如果不是数字,则重置标签文本
      label.config(text="请输入有效的数字")
def update_label_1_text(event):#添加event参数
    try:
      number = int(entry_1.get())#获取文本框内容并转换为整数
      label_1.config(text=f"提醒天数已设置为: {number}天")#更新标签文本
    except ValueError:
       #如果不是数字,则重置标签文本
      label.config(text="请输入有效的数字")
def on_save_remaining_days():
    global is_remember_remaining_days
    remaining_days = entry_1.get()
    is_remember_remaining_days = checkbox_var_2.get()
    if is_remember_remaining_days and not remaining_days:
      messagebox.showerror("错误", "请先输入剩余天数")
      return

    try:
      if is_remember_remaining_days:
            remaining_days_int = int(remaining_days)
            config = configparser.ConfigParser()
            config.read('settings.ini')
            if 'REMAINING_DAYS_SETTINGS' not in config:
                config['REMAINING_DAYS_SETTINGS'] = {}
            config['REMAINING_DAYS_SETTINGS']['remaining_days'] = str(remaining_days_int)
            checkbox_2.config(text="是否记住剩余天数:是")
      else:
            checkbox_2.config(text="是否记住剩余天数:否")
            if os.path.exists('settings.ini'):
                config = configparser.ConfigParser()
                config.read('settings.ini')
                if 'REMAINING_DAYS_SETTINGS' in config:
                  del config['REMAINING_DAYS_SETTINGS']
                with open('settings.ini', 'w') as configfile:
                  config.write(configfile)
                messagebox.showinfo("成功", "已删除剩余天数设置")
                print('剩余天数设置已从settings.ini中删除')
      if is_remember_remaining_days:
            with open('settings.ini', 'w') as configfile:
                config.write(configfile)

            messagebox.showinfo("成功", "剩余天数已保存")
            print('剩余天数已保存到settings.ini中')
    except ValueError:
      checkbox_var_2.set(0)
      messagebox.showerror("错误", "请输入有效的剩余天数(整数)")
#创建主窗口
window = tk.Tk()
window.title("证件信息")
#获取屏幕宽度和高度
screen_width = window.winfo_screenwidth()
screen_height = window.winfo_screenheight()
#计算窗口的宽度和高度
window_width = 1100
window_height = 500
#计算窗口左上角应该放置的位置,使其居中
x_coordinate = (screen_width // 2) - (window_width // 2)
y_coordinate = (screen_height // 2) - (window_height // 2)
#设置窗口的位置
window.geometry(f"{window_width}x{window_height}+{int(x_coordinate)}+{int(y_coordinate)}")

#创建变量来跟踪复选框的状态
checkbox_var = tk.IntVar(value=0)#初始值设为0,表示未选中状态
checkbox_var_1 = tk.IntVar(value=0)#初始值设为0,表示未选中状态
checkbox_var_2 = tk.IntVar(value=0)#初始值设为0,表示未选中状态
read_ini_file('FILE_SETTINGS', 'file_path')#读取文件路径
read_ini_file('REFRESH_SETTINGS', 'refresh_time')#读取刷新时间
read_ini_file('REMAINING_DAYS_SETTINGS', 'remaining_days')#读取剩余天数

if file_path:checkbox_var.set(1)
if refresh_time:checkbox_var_1.set(1)
if remaining_days:checkbox_var_2.set(1)

if refresh_time is None:refresh_time=60
if remaining_days is None:remaining_days=30

refresh_time_var = tk.StringVar()
refresh_time_var.set(str(refresh_time))
remaining_days_var = tk.StringVar()
remaining_days_var.set(str(remaining_days))

#创建父容器
frame = ttk.Frame(window)
frame_1=ttk.Frame(window)
frame.grid(row=0, column=0, pady=0, sticky="news")#'news'代表北、东、南、西,意味着frame将扩展到父容器的所有可用空间
frame_1.grid(row=1, column=0, pady=0, sticky="news")
window.rowconfigure(0, pad=0)#控制第一行之间的间隔
window.rowconfigure(1, pad=0)#控制第二行之间的间隔
window.rowconfigure(2, pad=0)#控制第三行之间的间隔

#创建水平滚动条
xscrollbar = ttk.Scrollbar(frame, orient=tk.HORIZONTAL)
xscrollbar.grid(row=2,column=1,sticky="ew")
#创建垂直滚动条
yscrollbar = ttk.Scrollbar(frame, orient=tk.VERTICAL)
yscrollbar.grid(row=0,column=2,sticky="ns")
#设置字体
font_name = "Consolas"#你可以换成任何你想要的等宽字体名称
font_size = 8
label_1=tk.Label(frame,text="证件列表:")
label_1.grid(row=0,column=0)
#创建无需弹窗列表框
upper_listbox = tk.Listbox(frame, width=168, height=12, xscrollcommand=xscrollbar.set, yscrollcommand=yscrollbar.set)
upper_listbox.grid(row=0,column=1)
upper_listbox_listbox_font = tk.font.Font(family=font_name, size=font_size)
upper_listbox.config(font=upper_listbox_listbox_font) #应用字体到列表框
label_2=tk.Label(frame,text="弹窗列表:")
label_2.grid(row=1,column=0)

#创建需要弹窗列表框
below_listbox = tk.Listbox(frame, width=168, height=12, xscrollcommand=xscrollbar.set, yscrollcommand=yscrollbar.set)
below_listbox.grid(row=1,column=1)
below_listbox_listbox_font = tk.font.Font(family=font_name, size=font_size)
below_listbox.config(font=below_listbox_listbox_font)#应用字体到列表框

#设置滚动条与列表框的关联
xscrollbar.config(command=upper_listbox.xview)
yscrollbar.config(command=upper_listbox.yview)
xscrollbar.config(command=below_listbox.xview)
yscrollbar.config(command=below_listbox.yview)

#创建复选框
checkbox_1 = tk.Checkbutton(frame_1, text="是否记住刷新秒数:否",variable=checkbox_var_1, command=on_save_config)
checkbox_1.grid(row=0, column=3, pady=0, sticky="news")
#创建标签
label = tk.Label(frame_1, text="请输入秒数:秒")
label.grid(row=0, column=4, pady=0, sticky="news")
time_label = tk.Label(frame_1, text="剩余时间: 00:00")
time_label.grid(row=1, column=5, pady=0, sticky="news")

#创建文本框,并设置validate和validatecommand选项来限制输入为数字
entry = tk.Entry(frame_1, textvariable=refresh_time_var,validate="key", validatecommand=(frame_1.register(on_text_change), '%P'))
entry.grid(row=0, column=5, pady=0, sticky="news")

checkbox_2 = tk.Checkbutton(frame_1, text="是否记住剩余天数:否",variable=checkbox_var_2, command=on_save_remaining_days)
checkbox_2.grid(row=0, column=0, pady=0,padx=40, sticky="news")
#创建标签
label_1 = tk.Label(frame_1, text="请输入天数阈值:天")#Remaining_time
label_1.grid(row=0, column=1, pady=0, sticky="news")
#创建文本框,并设置validate和validatecommand选项来限制输入为数字
entry_1 = tk.Entry(frame_1, textvariable=remaining_days_var,validate="key", validatecommand=(frame_1.register(on_text_change), '%P'))
entry_1.grid(row=0, column=2, pady=0, sticky="news")
update_label_text(None)
update_label_1_text(None)
#绑定entry的失焦事件到update_label_text函数
entry.bind('<FocusOut>', update_label_text)
entry_1.bind('<FocusOut>', update_label_1_text)
#创建按钮
read_button = tk.Button(frame_1, text="读取Excel文件", command=read_excel_file)
read_button.grid(row=1, column=2, pady=0, sticky="news")
checkbox = tk.Checkbutton(frame_1, text="是否记住文件路径:否\n(下次启动程序时不会自动读取文件)", variable=checkbox_var,command=on_checkbox_change)
checkbox.grid(row=1, column=3, pady=0, sticky="news")

if checkbox_var :checkbox.config(text="是否记住文件路径:")
if checkbox_var_1 :
    checkbox_1.config(text="是否记住刷新时间:")
    auto_up(None)
if checkbox_var_2 :checkbox_2.config(text="是否记住剩余天数:")
auto_excel_file(file_path)

#进入消息循环
window.mainloop()

KeKeBB0609 发表于 2024-4-24 17:04

本帖最后由 KeKeBB0609 于 2024-4-24 17:18 编辑

示例表格
证件名称 发证日期 证件有效期 人员资质日期人员资质有效期 检测报告日期 检测报告有效期
示例:1证 20240102 1年 20240102 1年 20240109 1年
示例:2证 20240103 1.5年 20240103 1.5年 20240110 1.5年

https://static.52pojie.cn/static/image/hrline/5.gif

def zengze(value_str):
    number = re.search(r'\d+(\.\d+)?', str(value_str))
    if number:#如果找到了匹配项,提取它的值
      extracted_number = float(number.group())
      return extracted_number
    else:
      return value_str
* `re.search(pattern, string)`: 这是Python的正则表达式库`re`中的一个函数,用于在字符串中搜索与给定模式匹配的第一个位置。
* `r'\d+(\.\d+)?'`: 这是一个正则表达式模式。
      + `\d+`: 匹配一个或多个数字。
      + `(\.\d+)?`: 匹配一个小数点后跟一个或多个数字,但这个部分是可选的(由问号`?`表示)。
* `str(value_str)`: 确保 `value_str` 是一个字符串,这样我们可以对它使用正则表达式。
* 如果在 `value_str` 中找到与模式匹配的部分,`re.search` 会返回一个匹配对象;否则返回 `None`。
* `if number:`: 检查 `number` 是否为 `None`。如果不是,说明找到了与正则表达式模式匹配的部分。
* `number.group()`: 从匹配对象中提取匹配的字符串。
* `float(number.group())`: 将提取的字符串转换为浮点数。
* `return extracted_number`: 返回转换后的浮点数。

KeKeBB0609 发表于 2024-4-24 17:29

def read_excel_file():
    global file_path
    x=int(entry_1.get())
    file_path = filedialog.askopenfilename(filetypes=[("Excel files", "*.xlsx;*.xls")])#打开文件对话框以选择Excel文件
    if file_path:
      try:#使用pandas读取Excel文件
            read_excel_to_dict(file_path,remaining_days)
            xieru(file_path,x)
      except Exception as e:print(f"Error reading Excel file: {e}")#如果发生错误,打印错误信息
定义一个read_excel_file函数用于读取Excel文件
使用global声明file_path为全局变量可以跨函数访问和修改
创建局部变量x并赋值为输入框的值
使用filedialog.askopenfilename方法打开一个文件对话框,让用户选择Excel文件。返回并将其赋值给全局变量file_path
filetypes参数指定了文件对话框中只显示Excel文件(.xlsx和.xls)。
如果file_path不为空(即用户选择了文件),则调用方法read_excel_to_dict和xieru方法并传递指定变量

KeKeBB0609 发表于 2024-4-24 17:17

def pad_to_width(text, width):
    text_width = 0
    for char in text:
      char_width = unicodedata.east_asian_width(char)
      if char_width in ('F', 'W'):
            text_width += 2
      else:
            text_width += 1
    padding_needed = width - text_width
    if padding_needed > 0:
      return text + ' ' * padding_needed
    else:
      return text
pad_to_width(text, width)方法接收两个变量,text接收文本,例如:‘示例:1证’,width接收整数,例如20
首先创建一个计算宽度的变量text_width并初始化为0
循环遍历接收到的字符串text,if判断遍历到的字符是否为全角或宽字符,如果是则占用两个宽度,text_width自增2,若不是则自增1。
最后判断接收到的字符串是否需要填充空格,并返回

KeKeBB0609 发表于 2024-4-24 17:38

def auto_excel_file(file_path):
    x=int(entry_1.get())
    if file_path is not None:
      read_excel_to_dict(file_path,x)
      xieru(file_path,x)
    else:print(f'file_path:{file_path}')
定义auto_excel_file函数接收变量auto_excel_file
x在楼上有说明
判断file_path是否不为空
实际上if是根据结果T真(true)和F假(false)来判断是否执行语句,T则执行语句,F则不执行语句或者执行else(否则)后面的语句。
而T通常为非0的值,0则为F,这里可以写成if file_path:但是这里为了防止不可预见的错误以及展示not用法故而使用此写法。

lww32 发表于 2024-4-24 18:43

高手高手高手高手高手高手高手高手高手

Qim626 发表于 2024-4-24 19:40

Python,写的很好,厉害!

心中有梦闯天下 发表于 2024-4-24 20:55

有没有成品分享下

KeKeBB0609 发表于 2024-4-24 21:12

心中有梦闯天下 发表于 2024-4-24 20:55
有没有成品分享下

明天私信给你

theonechen 发表于 2024-4-24 21:40

太实用了,棒棒棒
页: [1] 2 3 4
查看完整版本: 一个到期时间提醒