![]() |
Insert csv data rows into a tree widget - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: Insert csv data rows into a tree widget (/thread-6187.html) |
Insert csv data rows into a tree widget - LMP2016 - Nov-09-2017 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) 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 RE: Insert csv data rows into a tree widget - Larz60+ - Nov-09-2017 Show at least enough code to run the sample RE: Insert csv data rows into a tree widget - LMP2016 - Nov-09-2017 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() RE: Insert csv data rows into a tree widget - Larz60+ - Nov-09-2017 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 RE: Insert csv data rows into a tree widget - Larz60+ - Nov-10-2017 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: Just in case there are any file differences, attached is a copy of what I used[attachment=280] RE: Insert csv data rows into a tree widget - LMP2016 - Nov-10-2017 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 RE: Insert csv data rows into a tree widget - Larz60+ - Nov-10-2017 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):
|