Deleting datas from csv file using Tkinter treeview

As title, I’m searching for a method for deleting a row from a csv file, using a tkinter’s treeview GUI.
Basically, I delete a selection with:

    def elimina():
        with open('/path/to/file.csv', 'a',
                  encoding='UTF-8') as elenco_aggiornato:
            selezione = tree_colonne.selection()[0]
            values = tuple(tree_colonne.item(selezione)['values'])
            tree_colonne.item(selezione)['values']
            tree_colonne.delete(selezione)

…but I noticed that it deletes only graphically the item I select. I tried to create a variable for a csv writer for making a writerow method but I failed.
How can I delete what I select from the GUI to edit the csv file?

Opening a file for 'a' is append, which can only ever add data to it.
This is fine for adding more rows to the end of a CSV file and very
safe.

A CSV file is a text file. The only way to “delete” from it it to
rewrite the file without the rows you no longer want. In the simple case
you rewrite the entire file.

Make a copy of the original contents of the CSV; there’s a fair risk of
destroying your data while experimenting.

Cheers,
Cameron Simpson cs@cskk.id.au

I tried different combinations but I can’t understand the way to rewrite the file without the line I chose to delete. My function rewrite the whole file, erasing everything from it or I also obtained a copy of the whole file but with a repeated line that is not my choice.
After the code just posted above, my last attempt was:

    def elimina():
        with open('/path/to/file.csv', 'w',
                  encoding='UTF-8') as elenco_aggiornato:
            selezione = tree_colonne.selection()[0]
            values = tuple(tree_colonne.item(selezione)['values'])
            canc_info = tree_colonne.delete(selezione)
            scr_el_csv = csv.writer(elenco_aggiornato)
            scr_el_csv.writerow([canc_info, nome, nascita,
                                            piano_camera, letto, mal_pat_dis,
                                            allergie, protesi, alimentazione,
                                            presidi, ausilii, riposo])

Items between parenthesis are referred to a csv.reader method that print the results in a tkinter’s treeview with the ’ insert ’ method.
I also tried to put the treeview’s content in the csv.writerow method but I saw that is not possible.
For sure (as always) it would be a very silly thing to do but I can’t approach to this.

I’m still stucked on this passage. Anyone could help me, please?

I’m working with the author of pysimplesql. We are very close to releasing a new version that supports loading and deleting lines from a csv file loaded into a PySimpleGUI sg.Table (basically a wrapped tkinter treeview).

Take a look at the Csv example, and if you download, make sure to grab the development branch!

1 Like

I tried a lot of times to rewrite the file without the data that I don’t need but I can’t understand how to get the infos from the treeview after deleting from it.
I tried this:

import tkinter
from tkinter import *
from tkinter import ttk, messagebox
import csv


fin = Tk()

def cancella():
    selezione = tv.selection()[0]
    mb_canc = messagebox.askokcancel(
        title="Conferma di cancellazione",
        message="Si vuole confermare l'eliminazione permanente di")
    if mb_canc == True:
        tv.delete(selezione)
        with open('/path/to/file.csv', 'w') as elenco:
            tv.get()
            scrit = csv.writer(elenco)
            scrit.write()
            for row in scrittore:
                cogn = row[0]
                nom = row[1]
                nasc = row[2]
        elenco.close()
        

tv = ttk.Treeview(fin,
                  columns=("Nome", "Cognome", "Nascita"),
                  show='headings')

tv.column('#0')
tv.column('#1')
tv.column('#2')
tv.column('#3')

tv.heading('#0')
tv.heading('#1', text="Nome")
tv.heading('#2', text="Cognome")
tv.heading('#3', text="Nascita")

tv.pack()

with open('/path/to/file.csv', 'r+') as elenco:
    lettore = csv.reader(elenco)
    for row in lettore:
        cogn = row[0]
        nom = row[1]
        nasc = row[2]
        
        tv.insert("", 0, values=(cogn, nom, nasc))
    
puls_canc = Button(fin, text="Elimina",
                   command=cancella)
puls_canc.pack()


fin.mainloop()

…but treeview as no attribute ’ .get() '.
So, how can I get the windows upgraded from the selection deleted in the treeview windows to rewrite the file?

I need to return on this topic because I didn’t solved yet…
Now, I guess to be quiet next to the solution but it still messing me. So, here is the point:

from tkinter import *
from tkinter import ttk, messagebox
import csv


fin = Tk()

def cancella():
    selezione = tv.selection()[0]
    mb_canc = messagebox.askokcancel(
        title="Conferma di cancellazione",
        message="Si vuole confermare l'eliminazione permanente di")
    if mb_canc == True:
        with open('/path/to/file.csv', 'r+',
                  encoding='UTF-8') as elenco_aggiornato:
            cancel = tv.delete(selezione)
            tuptras = StringVar(cancel)
            get_tuptras = tuptras.get()
            riscrivi_tv = tv.item(ins_tv)
            scrit = csv.writer(elenco_aggiornato)
            scrit.writerow(riscrivi_tv)
        elenco_aggiornato.close() 
        

tv = ttk.Treeview(fin,
                  columns=("Nome", "Cognome", "Nascita"),
                  show='headings')

tv.column('#0')
tv.column('#1')
tv.column('#2')
tv.column('#3')

tv.heading('#0')
tv.heading('#1', text="Nome")
tv.heading('#2', text="Cognome")
tv.heading('#3', text="Nascita")

tv.pack()

with open('/path/to/file.csv', 'r+',
          encoding='UTF-8') as elenco:
    lettore = csv.reader(elenco)
    for row in lettore:
        cogn = row[0]
        nom = row[1]
        nasc = row[2]
        
        ins_tv = tv.insert("", 0, values=(cogn, nom, nasc))
    
puls_canc = Button(fin, text="Elimina",
                   command=cancella)
puls_canc.pack()


fin.mainloop()

This code return this:
canc_sp

…where the blue arrow is the data deleted after to be selected and now it seems to print the options for the function that I used; while the red arrow shows that the data in the column[0] is automatically affected (‘a’ is the last letter of a name… it was automatically deleted after deleting the row showed by the blue arrow, leaving only the last letter of it and I can’t understand why it does).

So, how can I delete the datas that I don’t need anymore leaving a blank space and how can I solve the problem given by what is shown by the red arrow?
In addition, once I have deleted a row, how can I ‘move’ the text of the document to avoid blank spaces leaved by the data deletion?

I’m still stucked on this passage. I’m trying different combinations of code but it seems impossible “write” on a file (in this case, a csv file) something deleted from a treeview’s window. I tried also the .get() method on the deleted item but it doesn’t work. I can’t find any way to do it.
Is it possible that anyone know the solution?

Try this:

def cancella():
    selezione = tv.selection()[0]
    mb_canc = messagebox.askokcancel(
        title = "Conferma di cancellazione",
        message = "Si vuole confermare l'eliminazione permanente di")
    if mb_canc:
        tv.delete(selezione)

        with open(r'/path/to/file.csv.new', 'w',
                  newline='', encoding='UTF-8') as elenco_aggiornato:
            scrit = csv.writer(elenco_aggiornato)
            
            for iid in tv.get_children():
                row = tv.item(iid, option='values')
                scrit.writerow(row)

        os.replace('/path/to/file.csv', r'/path/to/file.csv.bak')
        os.replace('/path/to/file.csv.new', r'/path/to/file.csv')

Note that it’s safer to write to a new file and then replace afterwards in case the code that’s writing fails part way through - that way, the original file is preserved until the write is complete. Keeping a backup of the original file is also a good idea.

After months, I restarted to work on this little project. After some little adjustments, this finally works fine.
I just had to avoid the os.replace because it works strange to me.
Thank you soooooooooooooooooooooo much! I was stucked on that!

Thanks for sharing Emanuele, I just started a similar project.