Posts: 3
Threads: 1
Joined: Nov 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)
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
Posts: 12,022
Threads: 484
Joined: Sep 2016
Show at least enough code to run the sample
Posts: 3
Threads: 1
Joined: Nov 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()
Posts: 12,022
Threads: 484
Joined: Sep 2016
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
Posts: 12,022
Threads: 484
Joined: Sep 2016
Nov-10-2017, 02:48 AM
(This post was last modified: Nov-10-2017, 02:48 AM by Larz60+.)
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
somedwgs.csv (Size: 391 bytes / Downloads: 365)
Posts: 3
Threads: 1
Joined: Nov 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
Posts: 12,022
Threads: 484
Joined: Sep 2016
Nov-10-2017, 03:51 AM
(This post was last modified: Nov-10-2017, 03:56 AM by Larz60+.)
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
|