Python Forum
Insert csv data rows into a tree widget
Thread Rating:
  • 3 Vote(s) - 2.33 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Insert csv data rows into a tree widget
#1


I'm a beginner so dont beat me up too much :) .I have a program where a user enters a product number into a field and clicks a search button, the program then opens a csv file (see below), looks for that product number and should then only display (by inserting that data into a treeview) the data relevant, stopping once blank rows occur - this indicates the end of the part information and the start next part.

Example of the csv is below (excuse the use of the error box)
Error:
Product PartDesc Drawings Issues Documents 1-1841111-2 bad feeling Dwg1 Iss A c:\company\docs\tfpp\widget1.xls Dwg2 Iss B c:\company\docs\tfpp\bob.pdf Dwg25 Iss Z c:\company\docs\tfpp\itsatrap.pdf 1-1841111-4 tribble Dwg3 Iss C c:\company\docs\tfpp\wibble.xls 1-1841111-5 nothing Dwg4 Iss D c:\company\docs\tfpp\rocket.pdf Dwg5 Iss E c:\company\docs\tfpp\dwg1.doc
Unfortunately when I run the code I can only get a single csv row to display and have not been able to work out how get subsequent rows, stopping at a blank row. I am however, not convinced that the below code although its displays a single line as expected is operating correctly.

def search(self):
        if self.SOentry.get() != "":
            x = self.dwgtree.get_children()
            for item in x:
                self.dwgtree.delete(item)
            self.partdesc.delete(0,'end')
                
            with open("c:\python\projects\somedwgs.csv") as csvfile:
                    reader = csv.DictReader(csvfile)
                    for row in reader:
                        result=(row['Product'])
                        if self.SOentry.get() == result:
                                descr=(row['PartDesc'])
                                descDwg=(row['Drawings'])
                                descIss=(row['Issues'])
                                descDscr=(row['Documents'])
                                self.partdesc.insert(0,descr)
                                while True:
                                    #if row['PartDesc'] != "":
                                    if descDwg != "":
                                        self.dwgtree.insert("",'end',values=(descDwg,descIss,descDscr))
                                        next(reader)
                                        break
Reply
#2
Show at least enough code to run the sample
Reply
#3
Apologises, full code follow
import tkinter
import tkinter.font
from tkinter import ttk
import csv
from csv import DictReader
import sys
import os
import subprocess

tree_columns = ("Drawing", "Issue", "Document type")
sonumber = 0

class TFPP:

    def __init__(self):
        self.tree = None
        self._setup_widgets()
        self._build_tree()
     
    def _setup_widgets(self):
        
        #this is the setup & layout for the top part of the application i.e. the textbox and buttons.
        # setting up the 1st frame
        frame1=ttk.Frame()
        frame1.pack(fill='both', expand=False)

        AmpicsLabel = ttk.Label(frame1,justify="left", anchor="s", text=("Ampics Number :"))
        #sonumber = stringvar()
        self.SOentry=ttk.Entry(frame1,justify="left", width=15, textvariable = sonumber)
        Searchbutton = ttk.Button(frame1,text="Search",command='_do_search')
        AmpicsLabel.pack(side="left", padx=5)
        self.SOentry.pack(side="left", padx=5)
        Searchbutton = ttk.Button(frame1,text="Search", command=self.search)
        Searchbutton.pack(side="right", padx=3, pady=1)
        #
        #
        # setting up the 2nd frame
        frame2=ttk.Frame()
        frame2.pack(fill='both', expand=False)
        def _clear_text():
            self.partdesc.delete(0, 'end')
            self.SOentry.delete(0, 'end')
            x = self.dwgtree.get_children()
            for item in x:
                self.dwgtree.delete(item)

        DescLabel = ttk.Label(frame2,justify="left", anchor="sw", text=("Part Description : "))
        self.partdesc = ttk.Entry(frame2,background='#fff',justify="left", width=57)
        Resetbutton = ttk.Button(frame2,text="Reset",command=_clear_text)

        DescLabel.pack(side="left", padx=5)
        self.partdesc.pack(side="left", padx=5,pady=5)
        Resetbutton.pack(side="right", padx=3, pady=1)
        #
        #
        # setting up the 3rd frame
        frame3=ttk.Frame()
        frame3.pack(fill='both', expand=False)
        Quitbutton = ttk.Button(frame3,text="Quit", command=app.destroy)
        Quitbutton.pack(side="right", padx=3, pady=1) 
        #
        #
        # this is the setup & layout for the drawing list part.
        container = ttk.Frame()
        container.pack(fill='both', expand=False)
        self.dwgtree = ttk.Treeview(columns=tree_columns, show="headings")
        vsb = ttk.Scrollbar(orient="vertical", command=self.dwgtree.yview)
        self.dwgtree.grid(column=0, row=0, sticky='nsew', in_=container)
        vsb.grid(column=1, row=0, sticky='ns', in_=container)
        container.grid_columnconfigure(0, weight=1)
        container.grid_rowconfigure(0, weight=1)   

        #
        #
        # configures the layout of the tree
    def _build_tree(self):
        for col in tree_columns:
            self.dwgtree.heading(col,anchor="w", text=col.title(),
                command=lambda c=col: sortby(self.tree, c, 0))

            self.dwgtree.column("Drawing",width=120,anchor="w", stretch="no")
            self.dwgtree.column("Issue",width=75, anchor="w", stretch="no")
            self.dwgtree.column("Document type",anchor="w",width=300)
            self.treeview=self.dwgtree

        #
        #
        # this reads the csv file and loads the data into the tree
    def search(self):
        if self.SOentry.get() != "":
            x = self.dwgtree.get_children()
            for item in x:
                self.dwgtree.delete(item)
            self.partdesc.delete(0,'end')
                
            with open("c:\python\projects\somedwgs.csv") as csvfile:
                    reader = csv.DictReader(csvfile)
                    for row in reader:
                        result=(row['Product'])
                        if self.SOentry.get() == result:
                                descr=(row['PartDesc'])
                                descDwg=(row['Drawings'])
                                descIss=(row['Issues'])
                                descDscr=(row['Documents'])
                                self.partdesc.insert(0,descr)
                                while True:
                                    if descDwg != "":
                                        self.dwgtree.insert("",'end',values=(descDwg,descIss,descDscr))
                                        next(reader)

                                        break
              
      
       
    
if __name__ == "__main__":
    app = tkinter.Tk()
    app.title("Production Drawings")
    app.geometry("550x330")
    app.iconbitmap('telogo.ico')
    tfpp = TFPP()
    app.mainloop()
Reply
#4
quick look, general
You have searchbutton defined twice

I did a search for 1-1841111-2
At line 91, the tree (x)  is not populated
self.SOentry.get() = {str} '1-1841111-2'
# ... first read of data file:
OrderedDict([('Product\t           PartDesc\t      Drawings\t   Issues\t       Documents', '1-1841111-2\t    bad feeling\t   Dwg1\t      Iss A\t    c:\\company\\docs\\tfpp\\widget1.xls')])
It then crashes on result = (row['Product'])
because Product is part of a string.
I would do this differently. Give me some time, I'm about to eat dinner
Reply
#5
Ok,

I had my dinner.

here's how I would read this file.
The code would have been more compact if the structure were the same from line to line.
Since you are using tkinter, you obviously won't be using the show_current_product function,
but I put it there to show how to access the dictionary.
In addition, I wrote this so that the dictionary could handle multiple products with minor modifications.
Here's the code:
from pathlib import Path


class TryRead:
    def __init__(self):
        self.header = None
        self.product_dict = {}
        self.file = Path('.') / 'somedwgs.csv'

    def search(self, product_id):
        with self.file.open() as f:
            # skip first line (header)
            next(f)
            self.product_dict = {}
            product_found = False
            for line in f:
                line = line.strip().split('\t')
                if not product_found:
                    if line[0] != product_id:
                        continue
                product_found = True
                llen = len(line)
                if llen == 1:
                    break
                elif llen == 5:
                    product = line[0]
                    part_desc = line[1]
                    self.product_dict[product] = {}
                    self.product_dict[product]['PartDesc'] = part_desc
                    self.product_dict[product]['Drawings'] = {}
                    self.product_dict[product]['Drawings'][line[2]] = {}
                    self.product_dict[product]['Drawings'][line[2]]['Issues'] = line[3]
                    self.product_dict[product]['Drawings'][line[2]]['Documents'] = line[4]
                else:
                    self.product_dict[product]['Drawings'][line[0]] = {}
                    self.product_dict[product]['Drawings'][line[0]]['Issues'] = line[1]
                    self.product_dict[product]['Drawings'][line[0]]['Documents'] = line[2]
            # print(f'product_dict: {self.product_dict}')

    def show_current_product(self):
        if not self.product_dict:
            print('Please select a product')
        else:
            for key, value in self.product_dict.items():
                print(f'Product: {key}')
                for skey, svalue in value['Drawings'].items():
                    print(f'    {skey}')
                    for ikey, ivalue in svalue.items():
                        print(f'        {ikey}: {ivalue}')

if __name__ == '__main__':
    tr = TryRead()
    tr.search('1-1841111-2')
    tr.show_current_product()
and the results:
Output:
Product: 1-1841111-2     Dwg1         Issues: Iss A         Documents: c:\company\docs\tfpp\widget1.xls     Dwg2         Issues: Iss B         Documents: c:\company\docs\tfpp\bob.pdf     Dwg25         Issues: Iss Z         Documents: c:\company\docs\tfpp\itsatrap.pdf
Just in case there are any file differences, attached is  a copy of what I used

.csv   somedwgs.csv (Size: 391 bytes / Downloads: 316)
Reply
#6
thank you for your help, its close to what I'm looking for except that I will be inserting the data into a tree widget that has three columns. So in my case if I searched for 1-1841111-2 I would be aiming to see :
DRAWING.........ISSUE.............DOCUMENT TYPE
Dwg 1.................Iss A.................c:\company\docs\tfpp\widget1.xls
Dwg 2.................Iss B.................c:\company\docs\tfpp\bob.pdf
Dwg 25...............Iss Z.................c:\company\docs\tfpp\itsatrap.pdf

with other part searches bring up other data in the above layout
Reply
#7
But it's a simple process to manipulate the dictionary into any format that you need.
from pathlib import Path


class TryRead:
    def __init__(self):
        self.header = None
        self.product_dict = {}
        self.file = Path('.') / 'somedwgs.csv'
        self.out_field_size = 22

    def search(self, product_id):
        with self.file.open() as f:
            # skip first line (header)
            next(f)
            self.product_dict = {}
            product_found = False
            for line in f:
                line = line.strip().split('\t')
                if not product_found:
                    if line[0] != product_id:
                        continue
                product_found = True
                llen = len(line)
                if llen == 1:
                    break
                elif llen == 5:
                    product = line[0]
                    part_desc = line[1]
                    self.product_dict[product] = {}
                    self.product_dict[product]['PartDesc'] = part_desc
                    self.product_dict[product]['Drawings'] = {}
                    self.product_dict[product]['Drawings'][line[2]] = {}
                    self.product_dict[product]['Drawings'][line[2]]['Issues'] = line[3]
                    self.product_dict[product]['Drawings'][line[2]]['Documents'] = line[4]
                else:
                    self.product_dict[product]['Drawings'][line[0]] = {}
                    self.product_dict[product]['Drawings'][line[0]]['Issues'] = line[1]
                    self.product_dict[product]['Drawings'][line[0]]['Documents'] = line[2]
            # print(f'product_dict: {self.product_dict}')

    def generate_output(self):
        if not self.product_dict:
            print('Please select a product')
        else:
            for key, value in self.product_dict.items():
                for skey, svalue in value['Drawings'].items():
                    dlen = self.out_field_size - len(skey)
                    dlen2 = self.out_field_size - len(svalue['Issues'])
                    outstr = f"{skey}{'.' * dlen}{svalue['Issues']}{'.' * dlen2}{svalue['Documents']}"
                    yield outstr

    def show_formatted_product(self):
        for line in self.generate_output():
            print(line)

    def show_current_product(self):
        if not self.product_dict:
            print('Please select a product')
        else:
            for key, value in self.product_dict.items():
                print(f'Product: {key}')
                for skey, svalue in value['Drawings'].items():
                    print(f'    {skey}')
                    for ikey, ivalue in svalue.items():
                        print(f'        {ikey}: {ivalue}')

if __name__ == '__main__':
    tr = TryRead()
    tr.search('1-1841111-2')
    tr.show_current_product()
    print('')
    tr.show_formatted_product()
output (sans the header):
Output:
Product: 1-1841111-2     Dwg1         Issues: Iss A         Documents: c:\company\docs\tfpp\widget1.xls     Dwg2         Issues: Iss B         Documents: c:\company\docs\tfpp\bob.pdf     Dwg25         Issues: Iss Z         Documents: c:\company\docs\tfpp\itsatrap.pdf Dwg1..................Iss A.................c:\company\docs\tfpp\widget1.xls Dwg2..................Iss B.................c:\company\docs\tfpp\bob.pdf Dwg25.................Iss Z.................c:\company\docs\tfpp\itsatrap.pdf
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How to insert Dashed Lines in between Rows of a tabulate output Mudassir1987 0 496 Sep-27-2023, 10:09 AM
Last Post: Mudassir1987
  how do you style data frame that has empty rows. gsaray101 0 522 Sep-08-2023, 05:20 PM
Last Post: gsaray101
  Plot a pandas data fram via pyqtgraph with an modul import and qt designer widget Nietzsche 0 841 May-29-2023, 02:42 PM
Last Post: Nietzsche
  (Python) Pulling data from UA Google Analytics with more than 100k rows into csv. Stockers 0 1,217 Dec-19-2022, 11:11 PM
Last Post: Stockers
  How to properly format rows and columns in excel data from parsed .txt blocks jh67 7 1,873 Dec-12-2022, 08:22 PM
Last Post: jh67
  How to insert different types of data into a function DrData82 0 1,248 Feb-10-2022, 10:41 PM
Last Post: DrData82
  How to read rainfall time series and insert missing data points MadsM 4 2,165 Jan-06-2022, 10:39 AM
Last Post: amdi40
  The code I have written removes the desired number of rows, but wrong rows Jdesi1983 0 1,625 Dec-08-2021, 04:42 AM
Last Post: Jdesi1983
  Iterating Through Data Frame Rows JoeDainton123 2 2,901 Aug-09-2021, 07:01 AM
Last Post: Pedroski55
Lightbulb [Solved] df.loc: write data in certain rows ju21878436312 1 1,697 Jun-28-2021, 06:49 AM
Last Post: ju21878436312

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020