@Sinstick

Как настроить сортировку в программе на Python?

Есть программа с помощью которой формируется реестр документации из выбранной папки с именами файлов . Пользователь выбирает папку и в список выводятся все файлы которые в ней и в её подпапках исключая только игнорируемые имена папок ( скрин ниже ) , далее пользователь вводит в полях ввода нужную информацию и сохраняет сохраняет список в пдф файл.
Порядок файлов в папке

663ca3caaad7a514771024.png

Порядок файлов после того как выбрали папку и файлы добавились в список

663ca349e68e1891207431.png

Результат работы программы (PDF файл)

663ca5f924290329778006.png


Вопрос в том как сделать чтоб была либо возможность после того как файлы добавлены в список отсортировать так же как это происходит в папке в алфавитно числовом порядке от А-Я либо чтоб изначально список сортировался по такому методу во время формирования?

Исходный код модуля main.pyw

import os
from tkinter import *
from tkinter import ttk
from tkinter import filedialog
from tkinter import messagebox
from pdf_generator import save_to_pdf
import re
import keyboard

def select_folder():
    folder_selected = filedialog.askdirectory()
    if folder_selected:
        selected_folder_entry.delete(0, END)
        selected_folder_entry.insert(0, os.path.basename(folder_selected))
        process_folder(folder_selected)

def process_folder(folder_path):
    for item in tree.get_children():
        tree.delete(item)

    ignored_folders = {"А4", "А3", "ЧЕРТИ", "ЧЕРТЕЖИ", "а4", "а3", "черти", "чертежи"}

    index = 1
    pdf_files = find_pdfs(folder_path)
    print("Найденные PDF-файлы:")
    print(pdf_files)
    for pdf_file in pdf_files:
        folder_name = os.path.basename(os.path.dirname(pdf_file))
        if folder_name.lower() not in ignored_folders:
            insert_sorted(tree, index, (index, os.path.basename(pdf_file), ""))
            index += 1

    update_numbering()


def find_pdfs(directory):
    pdf_files = []
    for root_dir, _, files in os.walk(directory):
        for file in files:
            if file.lower().endswith('.pdf'):
                pdf_files.append(os.path.join(root_dir, file))
    return pdf_files

def insert_sorted(tree, index, values):
    children = tree.get_children()
    index_to_insert = len(children) + 1

    for child in children:
        child_values = tree.item(child, "values")
        if natural_sort_key(values[1]) < natural_sort_key(child_values[1]):
            index_to_insert = tree.index(child)
            break

    print("Adding item to the tree:", values)
    tree.insert("", index_to_insert, values=values)

def natural_sort_key(s):
    return [int(text) if text.isdigit() else text.lower() for text in re.split('([0-9]+)', s)]

def delete_items(event):
    for item in tree.selection():
        tree.delete(item)
    update_numbering()
    update_total_rows()

def update_numbering():
    children = tree.get_children("")
    for index, child in enumerate(children, start=1):
        tree.item(child, values=(index,) + tree.item(child, "values")[1:])

def on_entry_click(event):
    if entry.get() == "Введите кол-во экз.":
        entry.delete(0, END)
        entry.config(fg="black")

def on_focus_out(event):
    if entry.get() == "":
        entry.insert(0, "Введите кол-во экз.")
        entry.config(fg="grey")

def add_entry(event=None):
    quantity = entry.get()
    if quantity:
        if not tree.selection():
            for item_id in tree.get_children():
                tree.item(item_id, values=(tree.item(item_id, "values")[0], tree.item(item_id, "values")[1], quantity))
        else:
            for item_id in tree.selection():
                tree.item(item_id, values=(tree.item(item_id, "values")[0], tree.item(item_id, "values")[1], quantity))
        entry.delete(0, END)
        entry.insert(0, "Введите кол-во экз.")
        entry.config(fg="grey")
    update_total_rows()

def on_treeview_edit(event):
    selection = tree.selection()
    if selection:
        selected_item = selection[0]
        values = tree.item(selected_item, "values")
        if len(values) >= 3:
            value = values[2]
            entry.delete(0, END)
            entry.insert(0, value)
            entry.focus_set()
        else:
            print("Элемент не содержит третьего значения.")
    else:
        print("Не выбран элемент для редактирования.")

def update_total_rows():
    total_rows = len(tree.get_children())
    total_rows_label.config(text=f"Количество томов: {total_rows}")

def sort_column(col):
    items = [(natural_sort_key(tree.set(item, col)), item) for item in tree.get_children("")]
    items.sort()
    for index, (_, item) in enumerate(items):
        tree.move(item, "", index)
    tree.heading(col, command=lambda c=col: sort_column(c))

def on_label_click(event):
    if input_field.tag_configure("placeholder"):
        input_field.tag_delete("placeholder")
        input_field.delete(1.0, END)

def add_files_from_another_folder():
    folder_selected = filedialog.askdirectory()
    if folder_selected:
        ignored_folders = {"А4", "А3", "ЧЕРТИ", "ЧЕРТЕЖИ", "а4", "а3", "черти", "чертежи"}
        additional_pdf_files = find_pdfs(folder_selected)
        current_count = len(tree.get_children())  # Получить текущее количество элементов
        for pdf_file in additional_pdf_files:
            if not any(ignored_folder.lower() in pdf_file.lower() for ignored_folder in ignored_folders):
                insert_sorted(tree, current_count + 1, (current_count + 1, os.path.basename(pdf_file), ""))
                current_count += 1
        update_total_rows()

def select_all_items():
    tree.selection_set(tree.get_children())

def paste_items():
    # Получаем текст из буфера обмена
    selected_text = root.clipboard_get()
    # Заменяем текущее название выбранной папки текстом из буфера обмена
    selected_folder_entry.delete(0, END)
    selected_folder_entry.insert(0, selected_text)

root = Tk()
root.title("Реестр")
root.geometry("900x600")
root.resizable(False, False)

screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()

x = (screen_width - 900) // 2
y = (screen_height - 600) // 2

root.geometry(f"900x600+{x}+{y}")

menubar = Menu(root)
root.config(menu=menubar)

menubar.add_command(label="Выбрать папку", command=select_folder)
menubar.add_command(label="Сохранить", command=lambda: save_to_pdf(tree, selected_folder_entry.get(), input_field.get("1.0", "end-1c")))
menubar.add_command(label="Добавить файлы из другой папки", command=add_files_from_another_folder)

selected_folder_frame = Frame(root)
selected_folder_frame.pack(pady=10)

selected_folder_label = Label(selected_folder_frame, text="Заказ:", font=("Arial", 14, "bold"))
selected_folder_label.pack(side=LEFT)

selected_folder_entry = Entry(selected_folder_frame, font=("Arial", 12))
selected_folder_entry.pack(side=LEFT, padx=10)
selected_folder_entry.insert(0, "Название")

columns = ("№", "Имя файла", "Кол-во экз")
tree = ttk.Treeview(root, columns=columns, show="headings")
tree.pack(expand=1, fill=BOTH)

tree.heading("№", text="№", anchor=W, command=lambda: sort_column("#0"))
tree.heading("Имя файла", text="Имя файла", anchor=W, command=lambda: sort_column("#1"))
tree.heading("Кол-во экз", text="Кол-во экз", anchor=W, command=lambda: sort_column("#2"))

tree.column("№", stretch=NO, width=50)
tree.column("Имя файла", stretch=YES)
tree.column("Кол-во экз", stretch=NO, width=120)

tree.bind("<Delete>", delete_items)
tree.bind("<F2>", on_treeview_edit)

entry = Entry(root, fg="grey", width=90)
entry.insert(0, "Введите кол-во экз.")
entry.bind("<FocusIn>", on_entry_click)
entry.bind("<FocusOut>", on_focus_out)
entry.bind("<Return>", add_entry)
entry.pack(pady=5)

total_rows_label = Label(root, text="", font=("Arial", 12))
total_rows_label.pack()

update_total_rows()

vsb = ttk.Scrollbar(root, orient="vertical", command=tree.yview)
vsb.place(x=881, y=51, height=440)
tree.configure(yscrollcommand=vsb.set)

input_field = Text(root, width=90, height=2, padx=5, pady=5)
input_field.pack(padx=5, pady=5)

placeholder_style = {"font": ("Helvetica", 20), "foreground": "gray"}
input_field.insert(END, "ТЗ для Постпечатки", "placeholder")
input_field.tag_configure("placeholder", **placeholder_style)

input_field.bind("<Button-1>", on_label_click)

# Привязываем события нажатия на Ctrl+A и Ctrl+V к функциям выбора всех элементов и вставки элементов
keyboard.add_hotkey('ctrl+a', select_all_items)
keyboard.add_hotkey('ctrl+v', paste_items)

root.mainloop()

  • Вопрос задан
  • 255 просмотров
Пригласить эксперта
Ответы на вопрос 1
@Tiubert
Это скорее будет больше помощь, чем готовое решение.
Возможно..
По-моему папки и файлы изначально отсортированы по имени.


Не читая ваш код говорю, вам нужно взять имена всех файлов в директории и добавить их в список.
После этот список можно отсортировать с помощью list.sort() метода или использовать sorted(list). Он будет отсортирован вроде как вам нужно.
Потом уже смотря на этот список можно каждый из элементов на экран.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы