Как отобразить стилизованный DataFrame в консоли tkinter

Вопрос или проблема

Я написал код на языке Python. Предоставленный код представляет собой приложение Python, которое обрабатывает файл Excel и выделяет определенные строки желтым цветом на основе определенных критериев в различных функциях. Он использует библиотеку Pandas для манипуляции данными, Tkinter для графического пользовательского интерфейса и pandastable для отображения DataFrame в табличном формате. По какой-то причине я не могу увидеть цветовую подсветку в консоли tkinter, однако я вижу ее в сохраненном выходном файле Excel.

Вот обзор функциональности кода:

Импорты: Код импортирует необходимые библиотеки: Pandas для манипуляции данными, NumPy для числовых операций, Tkinter для создания GUI, filedialog для открытия файлов, messagebox для отображения сообщений и pandastable для создания таблиц.

Функции подсветки: Код определяет несколько функций, которые выделяют строки на основе различных критериев:

highlight_missing_values: Подсвечивает строки, где отсутствуют определенные столбцы для типов плавающих ставок.

highlight_missing_ccy: Подсвечивает строки, где отсутствует валюта, но присутствует базовый индекс цен или основная ценовая кривая.

highlight_negative_spread: Подсвечивает строки, где спред отрицательный для строк типов активов.

highlight_spread_validation: Подсвечивает строки, где спред находится вне заданного диапазона.

highlight_explicit_validation: Подсвечивает строки, где в столбце “Интерпретировать записи как” не установлено значение “Маржа – Явная” для типов плавающих или управляемых ставок.

highlight_COA_ccy: Добавляет новый столбец в DataFrame на основе планового узла и валюты.

Функция process_excel: Эта функция является основной точкой входа в приложение. Она выполняет следующие шаги:

Открывает диалог выбора файла, чтобы позволить пользователю выбрать файл Excel. Читает разные листы из выбранного файла Excel. Очищает и объединяет данные из листов. Применяет функции подсветки к объединенному DataFrame. Отображает DataFrame в pandastable внутри окна Tkinter. Сохраняет выходной DataFrame в новом файле Excel.

Я попробовал следующий кусок кода, но он не подсвечивает строку в желтый цвет согласно определенной функции в консоли tkinter, я могу видеть DataFrame в консоли tkinter, но он не оформлен.

import pandas as pd
import numpy as np
from tkinter import Tk, filedialog, Label, Button, messagebox, Frame
from pandastable import Table

# Function to highlight missing values
def highlight_missing_values(row):
    if row['COA_Type'] == 'Floating' and pd.notna(row['Currency']):
        is_blank = row[['Lockout period', 'lookback(days)', 'Reset Interval', 'Amortization Type', 'Rate Index/ Coupon Spread Reference Index']].isnull().any()
        return 'background-color: yellow' if is_blank else ''
    return ''

# Function to highlight missing currency
def highlight_missing_ccy(row):
    return 'background-color: yellow' if pd.isna(row['Currency']) and (pd.notna(row['Base Price index']) or pd.notna(row['Base Price Curve'])) else ''

# Function to highlight negative spread
def highlight_negative_spread(row):
    return 'background-color: yellow' if row['A/L/O'] == 'A' and row['Period1'] < 0 else ''

# Function to highlight spread validation
def highlight_spread_validation(row):
    return 'background-color: yellow' if row['Period1'] > 35 or row['Period1'] < -10 else ''

# Function to highlight explicit validation
def highlight_explicit_validation(row):
    return 'background-color: yellow' if row['COA_Type'] in ['Floating', 'Managed'] and pd.notna(row['Interpret Entries As']) and row['Interpret Entries As'] != 'Margin - Explicit' else 

# Function to highlight COA currency
def highlight_COA_ccy(df):
    new_column_value = None
    for index in range(len(df)):
        planning_node_str = str(df.loc[index, 'Planning_node'])
        if planning_node_str.endswith('(QRM)') or planning_node_str.endswith(' OTHER USD'):
            new_column_value = planning_node_str
        df.loc[index, 'coa_ccy'] = new_column_value
    cols = df.columns.tolist()
    planning_node_id_idx = cols.index('Planning_node_id')
    cols.insert(planning_node_id_idx + 1, cols.pop(cols.index('coa_ccy')))
    return df[cols]

# Function to read the Excel file and perform operations
def process_excel():
    # Open file dialog to select Excel file
    file_path = filedialog.askopenfilename(title="Select an Excel file", filetypes=(("Excel files", "*.xlsx"), ("All files", "*.*")))
    if not file_path:
        messagebox.showerror("Error", "No file selected!")
        return

    try:
        xls = pd.ExcelFile(file_path)

        # Read sheets from the workbook
        sheet1_df = pd.read_excel(xls, sheet_name="Sheet1", header=1)
        sheet2_df = pd.read_excel(xls, sheet_name="Sheet2", header=1)
        eba_mapping = pd.read_excel(xls, sheet_name="EBA-mapping")
        index_currency_df = pd.read_excel(xls, sheet_name="Index-ccy", names=['Index', 'ccy'])

        # Data cleaning and merging
        sheet1_df = sheet1_df.apply(lambda x: x.str.strip() if x.dtype == "object" else x)
        sheet2_df = sheet2_df.apply(lambda x: x.str.strip() if x.dtype == "object" else x)

        selected_columns_df1 = sheet1_df[['Planning_node', 'Planning_node_id', 'Base Price index']]
        selected_columns_df2 = sheet2_df[['Lockout period', 'lookback(days)', 'Base Price index']]

        common_df = pd.concat([selected_columns_df1, selected_columns_df2], join='outer', axis=1, ignore_index=False)

        merged_df = pd.merge(common_df, eba_mapping[['COA', 'BS Flag', 'Rate Type']], left_on='Planning_node', right_on='COA', how='left')
        merged_df = merged_df.drop(columns=['COA']).rename(columns={'BS Flag': 'A/L/O', 'Rate Type': 'COA_Type'})

        # Apply the COA ccy function
        merged_df = highlight_COA_ccy(merged_df)

        # Display the DataFrame in the pandastable
        display_df(merged_df)

        # Save the output to an Excel file
        output_file = file_path.replace('.xlsx', '_output.xlsx')
        merged_df.to_excel(output_file, engine="openpyxl", index=False)
        messagebox.showinfo("Success", f"File saved as {output_file}")

    except Exception as e:
        messagebox.showerror("Error", str(e))

# Function to display the DataFrame in the Tkinter console using pandastable
def display_df(df):
    # Clear the previous table if it exists
    for widget in output_frame.winfo_children():
        widget.destroy()

    # Create a new Table in the output_frame
    table = Table(output_frame, dataframe=df, showtoolbar=True, showstatusbar=True)
    table.show()

    # Highlight rows based on logic from highlight functions
    for index, row in df.iterrows():
        style = highlight_missing_values(row)
        style += highlight_missing_ccy(row)
        style += highlight_negative_spread(row)
        style += highlight_spread_validation(row)
        style += highlight_explicit_validation(row)

        if style:
            table.getWidget().item(index).config(background=style.split(':')[-1])

# Main Tkinter window
root = Tk()
root.title("Excel Processor")
root.geometry("800x600")

# Label and Button
label = Label(root, text="Нажмите кнопку, чтобы выбрать файл Excel для обработки.")
label.pack(pady=10)

process_button = Button(root, text="Выбрать файл Excel", command=process_excel)
process_button.pack(pady=10)

# Frame for output console
output_frame = Frame(root)
output_frame.pack(pady=10, fill="both", expand=True)

# Run the application
root.mainloop()

Ответ или решение

Для отображения таблицы с выделением строк в Tkinter с использованием библиотеки pandastable, вам необходимо убедиться, что выделение стилей применяется корректно, так как Table из pandastable не поддерживает стилевые атрибуты, как это делает Pandas. Вместо этого, вы можете изменить цвет фона ячеек на основе условий, которые вы определили в ваших функциях выделения.

Ниже приведен обновленный код, который показывает, как можно правильно применить выделение строк в таблице:

import pandas as pd
import numpy as np
from tkinter import Tk, filedialog, Label, Button, messagebox, Frame
from pandastable import Table

# Функции выделения
def highlight_missing_values(row):
    if row['COA_Type'] == 'Floating' and pd.notna(row['Currency']):
        is_blank = row[['Lockout period', 'lookback(days)', 'Reset Interval', 'Amortization Type', 'Rate Index/ Coupon Spread Reference Index']].isnull().any()
        return is_blank
    return False

def highlight_missing_ccy(row):
    return pd.isna(row['Currency']) and (pd.notna(row['Base Price index']) or pd.notna(row['Base Price Curve']))

def highlight_negative_spread(row):
    return row['A/L/O'] == 'A' and row['Period1'] < 0

def highlight_spread_validation(row):
    return row['Period1'] > 35 or row['Period1'] < -10

def highlight_explicit_validation(row):
    return (row['COA_Type'] in ['Floating', 'Managed'] and pd.notna(row['Interpret Entries As']) and row['Interpret Entries As'] != 'Margin - Explicit')

# Функция обработки Excel файла
def process_excel():
    file_path = filedialog.askopenfilename(title="Выберите Excel файл", filetypes=(("Excel файлы", "*.xlsx"), ("Все файлы", "*.*")))
    if not file_path:
        messagebox.showerror("Ошибка", "Файл не выбран!")
        return

    try:
        xls = pd.ExcelFile(file_path)
        sheet1_df = pd.read_excel(xls, sheet_name="Sheet1", header=1)
        sheet2_df = pd.read_excel(xls, sheet_name="Sheet2", header=1)
        # Объединение и обработка данных
        # ... (ваша логика объединения здесь)

        display_df(merged_df)
        output_file = file_path.replace('.xlsx', '_output.xlsx')
        merged_df.to_excel(output_file, engine="openpyxl", index=False)
        messagebox.showinfo("Успех", f"Файл сохранен как {output_file}")

    except Exception as e:
        messagebox.showerror("Ошибка", str(e))

# Функция для отображения DataFrame
def display_df(df):
    for widget in output_frame.winfo_children():
        widget.destroy()

    table = Table(output_frame, dataframe=df, showtoolbar=True, showstatusbar=True)
    table.show()

    # Применение стилей к ячейкам
    for index, row in df.iterrows():
        if highlight_missing_values(row):
            table.getWidget().item(index, 0).config(background='yellow')
            # Применяйте цвет к другим ячейкам в строке при необходимости
        if highlight_missing_ccy(row):
            table.getWidget().item(index, 1).config(background='yellow')
        if highlight_negative_spread(row):
            table.getWidget().item(index, 2).config(background='yellow')
        if highlight_spread_validation(row):
            table.getWidget().item(index, 3).config(background='yellow')
        if highlight_explicit_validation(row):
            table.getWidget().item(index, 4).config(background='yellow')

# Основное окно Tkinter
root = Tk()
root.title("Обработчик Excel")
root.geometry("800x600")

label = Label(root, text="Нажмите кнопку для выбора файла Excel для обработки.")
label.pack(pady=10)

process_button = Button(root, text="Выбрать файл Excel", command=process_excel)
process_button.pack(pady=10)

output_frame = Frame(root)
output_frame.pack(pady=10, fill="both", expand=True)

root.mainloop()

Объяснение изменений:

  1. Функции выделения теперь возвращают булевы значения, которые определяют, нужно ли выделять строку. Это позволяет потом захотеть применить выделения к ячейкам.

  2. Обновленная функция display_df теперь итерирует по строкам и применяет цвет к ячейкам в зависимости от условий, используя метод config для изменения фона.

  3. управление выделениями: Вы можете легко настроить, как и какие ячейки должны быть выделены, в зависимости от вашего критерия.

Убедитесь, что вы правильно имплементировали все функции обработки и объединения данных перед тем, как к ним применяются функции выделения. Это позволит вам видеть выделения в вашем интерфейсе Tkinter.

Оцените материал
Добавить комментарий

Капча загружается...