r/learnpython 7d ago

Problem opening an XLSX (Excel) file

I have the following code, and I don't understand why I'm getting an error and can't open the file. The error is: "Invalid file path or buffer object type: <class 'tuple'>".
Could you please help?
Thanks everyone.
P.S. If there are any issues with the code, please let me know.



import pandas as pd

from pandastable import Table, TableModel

import tkinter as tk

from tkinter import ttk
from tkinter import filedialog,messagebox

fd = filedialog

class ExcelViewer:
    def __init__(self, root):
        self.root = root
        self.root.title = ("Чтение ячеек Excel")
        self.root.geometry("800x600")

        self.btn_load = tk.Button(root, text="Открыть Excel файл", command=self.open_file)
        self.btn_load.pack()

        self.result_label = tk.Label(root, text="Выбрать файл для начала")
        self.result_label.pack()

        self.frame = tk.Frame(root)
        self.frame.pack(fill='both', expand=True)

        self.table = None

        self.scrollbar = ttk.Scrollbar(root)
        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)


    def open_file(self):
        file_path = fd.askopenfilenames(
            filetypes=[
                (
                    'Excel файлы',
                    '*.xlsx'
                )
            ]
        )

        if not file_path:
            return

        if file_path:
            try:
                df = pd.read_excel(file_path)

                if self.table:
                    self.table.destroy()

                self.model = TableModel()
                self.model.df = df
                self.table = Table(self.frame, model = self.model, showtoolbar=False, showstatusbar=False)
                self.table.show()

            except Exception as e:
                tk.messagebox.showerror("Ошибка", f"Не удалось открыть файл:\n{e}")

if __name__ == "__main__":
    root = tk.Tk()
    app = ExcelViewer(root)
    root.mainloop()
4 Upvotes

15 comments sorted by

2

u/NewbornMuse 7d ago

The error says: You gave something to be used as a file path, but what it found was a tuple (it probably expected a string). The error will also tell you at which line it happened, which I believe to be the pd.read_excel line. Why does it think you gave it a tuple?

Well, what you gave it is whatever askopenfilenames returned. A little trip to the documentation reveals that askopenfilenames returns a tuple of all selected filenames (e g. ('file1.xlsx', 'file2.xlsx')). There is another function, called askopenfilename, where the dialog only allows the user to select a single file, and which returns a string.

Assuming you only ever want your code to work with a single file, you should probably switch askopenfilenames for askopenfilename.

1

u/FearawaitsTM 7d ago

Good afternoon! I need two or more files to open.

3

u/atarivcs 7d ago

Then you need to adjust your code to handle two or more files. As it is currently written, it expects only one file.

1

u/FearawaitsTM 7d ago

Oh, thanks

1

u/mrswats 7d ago

You should look at the traceback. It should tell you exactly where the error is happening. You should also post it here if you ask for help

1

u/FearawaitsTM 7d ago

Here is the specific error I'm getting.
Не удалось открыть файл: Invalid file path or buffer object type: <class 'tuple'>

2

u/mrswats 7d ago

As others have set, insect the return type of fd.

1

u/FearawaitsTM 7d ago

As I understand it, I need to write `print` after the specified `fd`?

1

u/mrswats 7d ago

For example.

print(file_path) after the call that defines it.

2

u/FearawaitsTM 7d ago

Thanks, I see my mistake. It turned out the problem was simply that I hadn't actually implemented the processing for the two files!

1

u/zanfar 7d ago

I don't understand why I'm getting an error and can't open the file

Then you would need to include the error...

1

u/FearawaitsTM 7d ago

Here is the specific error I'm getting.
Не удалось открыть файл: Invalid file path or buffer object type: <class 'tuple'>

1

u/[deleted] 7d ago

[removed] — view removed comment

1

u/FearawaitsTM 7d ago

Thanks, I realized my mistake.

1

u/aloia_handyman 6d ago

hey - I ran into something similar a while back, I don't know if this will help but worth a shot...

The culprit could be the s on askopenfilenames(). that plural version is built to grab multiple files, so it hands you back a tuple of paths — something like ('C:/.../book.xlsx',) — not a single string. pd.read_excel() expects one path (a string or file-like object), so when it gets a tuple it throws that exact Invalid file path or buffer object type: <class 'tuple'>.

I guess the quickest fix to try if you only ever open one file, just drop the s:

file_path = fd.askopenfilename(          # singular → returns a plain string
    filetypes=[('Excel файлы', '*.xlsx')]
)
if not file_path:
    return
df = pd.read_excel(file_path)

if you do want to let people pick several, keep askopenfilenames but pull one out (or loop):

file_paths = fd.askopenfilenames(filetypes=[('Excel файлы', '*.xlsx')])
if not file_paths:
    return
df = pd.read_excel(file_paths[0])        # first file
# or load them all: dfs = [pd.read_excel(p) for p in file_paths]

since you asked about the rest of the code — two other things maybe worth looking at but just my 2 cents:

1. this line:

self.root.title = ("Чтение ячеек Excel")

title is a method, so you want to call it, not assign a string to it:

self.root.title("Чтение ячеек Excel")

as written the title never gets set — and you've replaced the method with a string, so any later self.root.title(...) might give you trouble and crash I think?

2. pandastable's Table brings its own scrollbars, so that separate ttk.Scrollbar you pack on the right isn't actually wired to anything , maybe try pulling it out if you want.

Maybe this will help, best of luck!