Python Tkinter GUI messy printing format - python

import pandas as pd
import csv
from tkinter import *
master = Tk()
textBox = Text(master, height=1, width=10)
textBox.grid(row=0, column=1)
fileVar = StringVar()
fileLabel = Label(master, textvariable=fileVar)
fileLabel.grid(row=3, column=1)
fileVar2 = StringVar()
fileLabel2 = Label(master, textvariable=fileVar)
fileLabel2.grid(row=3, column=2)
def retrieve_input():
Customer = textBox.get("1.0","end-1c")
fileread = pd.read_csv('50.csv', encoding='latin-1')
filevalue = fileread.loc[fileread['Customer'].str.contains(Customer, na=False),"Jul-18\nQty"]
productheader = fileread.loc[fileread['Customer'].str.contains(Customer, na=False), 'Product']
fileVar.set(productheader)
fileVar2.set(filevalue)
button1 = Button(master,text="Show Values", command=lambda: retrieve_input())
button1.grid(row=4, column=1)
mainloop()
I have this program that prints values in Tkinter Gui, for specific values in a specific row. However the format of the values being printed is quiet messy and I am unsure how to clean it up, In addition I would like for it to not display the numbers labeled next to it, Just the product name (blurred out in blue) and the value associated with it( which are the number values with decimals).
Here is a snapshot of the GUI:
In addition, at the very bottom of the list, this is also displayed:
Ideally, I would like for it to only show the header(July-18) and not the datatype
Also if it helps to know, these are forecast files, (reason for headers with dates)
Here is a dummy image of what my csv files look like:

Ok so after some testing I think I have found a fix that should work for you.
The main issue with spacing inside of your label is the problem with your font not being one that is considered monospace.
Try using the font Consolas and see how well that fixes your layout.
import pandas as pd
from tkinter import *
master = Tk()
textBox = Text(master, height=1, width=10, font=('Consolas', 12))
textBox.grid(row=0, column=1)
fileVar = StringVar()
fileLabel = Label(master, textvariable=fileVar, font=('Consolas', 12))
fileLabel.grid(row=3, column=1)
def retrieve_input():
department = textBox.get("1.0","end-1c")
fileread = pd.read_csv('50.csv', encoding='latin-1')
filevalue = fileread.loc[fileread['Customer'].str.contains(department, na=False),("Jul-18\nQty", "Product")]
fileVar.set(filevalue)
button1 = Button(master,text="Show Values", command=lambda: retrieve_input())
button1.grid(row=4, column=1)
master.mainloop()

Related

Generating CSV file with tkinter window

i'm trying to create CSV generator that will generate csv file for the list of users i will provide with to him.
Generated row should be looking like this:
add;Username#something.com;Rolename1
add;Username#something.com;Rolename2
add;Username2#something.com;Rolename1
add;Username2#something.com;Rolename2
This is if i select checkboxes for roles 1 and 2 it will add rows with both roles for the user.
So far i got to file getting generated but my main issue right now is that i don't know how to make it read users from tkinter Text and then saving that into csv. I would want it to only accept A-Z and 0-9 for usernames.
Here's my code so far:
from tkinter import *
from tkinter import ttk
import datetime
import pandas as pd
root = Tk()
root.geometry('500x500')
root.title("Csv generator")
#Creator name
creator = Entry(root, width=23)
creator.grid(column=1,row=0)
creator.insert(0, "Enter here your username")
#Functions entry
functionLabel = Label(root, text="FUNCTION", width=10).grid(column=0, row=1, padx=10)
clickFunction = StringVar()
clickFunction.set("Select your function")
Function = OptionMenu(root, clickFunction, "add", "chg", "cho", "del")
Function.grid(column=0, row=2, padx=10)
#Username list
usernameLabel = Label(root, text="USERNAME",width=10)
usernameLabel.grid(column=1, row=1, padx=10)
usernameList = Text(root, width=10, height=4)
usernameList.grid(column=1, row=1, padx=10, rowspan=4)
#Role List
rolesLabel = Label(root, text="ROLES", width=10)
rolesLabel.grid(column=2, row=1, padx=10)
rolesCheck1 = StringVar()
role1 = Checkbutton(root, text="Role01", variable=rolesCheck1, onvalue="Role01", offvalue="")
role1.grid(column=2, row=2, padx=10)
rolesCheck2 = StringVar()
role2 = Checkbutton(root, text="Role02", variable=rolesCheck2)
role2.grid(column=2, row=3, padx=10)
rolesCheck3 = StringVar()
role3 = Checkbutton(root, text="Role1", variable=rolesCheck3)
role3.grid(column=2, row=4, padx=10)
rolesCheck4 = StringVar()
role4 = Checkbutton(root, text="Role2", variable=rolesCheck4)
role4.grid(column=2, row=5, padx=10)
#Read Textbox
def usersout():
inputvalue = usernameList.get("1.0","end-1c")
print(inputvalue)
#CSV Creator part
def csvGenerate():
basename= creator.get()
suffix = datetime.datetime.now().strftime("%Y%m%d%H%M.csv")
filename = "_".join([basename, suffix]) # e.g. 'Creator_120508171442'
df = pd.read_csv('Template.csv')
df2 = df.append(usernameList, ignore_index=True)
df.to_csv(filename, index=False, header=False)
#Generate button
GENERATE = Button(root, text="GENERATE", command=csvGenerate).grid(column=0, row=6, columnspan=3)
root.mainloop()
Window
EDIT 20.10.2021:
Changed my code from csv to pandas as suggested but still no idea how to proceed.
I would suggest to create the checkbuttons using for loop and store those StringVars in a list which can be used easily latter to determine which roles are selected.
Note that csv module is used instead of pandas:
from tkinter import *
from tkinter import ttk
import datetime
import csv
root = Tk()
root.geometry('500x500')
root.title("Csv generator")
#Creator name
creator = Entry(root, width=23)
creator.grid(column=1, row=0)
creator.insert(0, "Enter here your username")
#Functions entry
Label(root, text="FUNCTION", width=10).grid(column=0, row=1, padx=10)
clickFunction = StringVar(value="Select your function")
OptionMenu(root, clickFunction, "add", "chg", "cho", "del").grid(column=0, row=2, padx=10)
#Username list
Label(root, text="USERNAME", width=10).grid(column=1, row=1, padx=10)
usernameList = Text(root, width=10, height=4)
usernameList.grid(column=1, row=1, padx=10, rowspan=4)
#Role List
Label(root, text="ROLES", width=10).grid(column=2, row=1, padx=10)
role_vars = [] # for storing those StringVars
# create the checkbuttons
for row, role in enumerate(("Role01", "Role02", "Role1", "Role2"), 2):
var1 = StringVar()
Checkbutton(root, text=role, variable=var1, onvalue=role, offvalue='').grid(row=row, column=2, padx=10, sticky='w')
role_vars.append(var1)
#CSV Creator part
def csvGenerate():
basename = creator.get()
suffix = datetime.datetime.now().strftime("%Y%m%d%H%M.csv")
filename = "_".join([basename, suffix]) # e.g. 'Creator_202110211234.csv'
with open(filename, "w", newline="") as file:
writer = csv.writer(file)
func = clickFunction.get() # use the StringVar instead
# get user list
users = usernameList.get('1.0', 'end-1c').splitlines()
# get selected roles
roles = [role.get() for role in role_vars if role.get()]
for user in users:
for role in roles:
writer.writerow([func, user, role])
#Generate button
Button(root, text="GENERATE", command=csvGenerate).grid(column=0, row=6, columnspan=3)
root.mainloop()
You can use pandas to generate csv
import pandas as pd
data = {'Product': ['Desktop Computer','Tablet','Printer','Laptop'],
'Price': [850,200,150,1300]
}
df = pd.DataFrame(data, columns= ['Product', 'Price'])
df.to_csv (r'C:\Users\Ron\Desktop\export_dataframe.csv', index = False, header=True)
print (df)
edit: you also have the csv package to create CSVs, but I prefer pandas as it is very simple to create a dict and transform it into DataFrame -> csv.

Copying text in tkinter from label or msgbeox

I been searching for methods to copy text to clipboard or copy the results from Tkinter gui but idk if there is a command or something
here is my code for now here the result comes in a messagebox can i copy it to clipboard
import tkinter.messagebox
import string
import random
def qs_msgbbox(): # qs_msgbbox
tkinter.messagebox.showinfo("Info", "For customer support or tip or rating contact:"
"dghaily725#gmail.com\npress the button for generated pass\nmsg will appear then copy\nthe generated password")
def gen_pass(k=9): # gen_pass
char = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!##$%^&*"
password = ''
for i in range(9):
password += random.choice(char)
tkinter.messagebox.showinfo("Password", password)
root = Tk()
root.title("Password Generator")
lbl1 = Label(root, text="Generate Password", bd=2, relief=SUNKEN, height=5, width=50, bg='black', fg='white')
lbl1.configure(font=(70))
lbl1.grid(row=0, column=2)
lbl2 = Label(root, text='For more information press the Question mark', bd=2, relief=SUNKEN, fg='red')
lbl2.configure(font=(70))
lbl2.grid(row=0, column=0, pady=10)
btn1 = Button(root, text='Press to Generate', height=5, width=50, bg='grey', command=gen_pass)
btn1.configure(font=(70))
btn1.grid(row=1, column=2, padx=460, pady=50)
btn2photo = PhotoImage(file='question.png')
btn2 = Button(root, image=btn2photo, width=30, height=30, command= qs_msgbbox)
btn2.grid(row=0, column=1)
root.mainloop()
and also just a quick small question is it better to use classes or this form
Tkinter does have a function for that, simply just
from tkinter import Tk
root = Tk()
root.clipboard_clear()
root.clipboard_append("Something to the clipboard")
root.update() # the text will stay there after the window is closed
Hope I could help
Greets
The above answer is perfectly fine. Infact its the method to do it. I read the comments, He had mentioned that it could only take in string. That is completely false. It can also take in functions. For example..
import tkinter as tk
root = tk.Tk()
#creating a entry Widget.(Labels are fine as well)
entry = tk.Entry(root)
entry.pack()
#NOW if you want to copy the whole string inside the above entry box after you
typed in #
def copy ():#assign this function to any button or any actions
root.clipboard_clear()
root.clipboard_append(entry.get()) #get anything from the entry widget.
root.mainloop()
Hoping this was helpful

Printing variables in tkinter GUI

This is my code:
import pandas as pd
from tkinter import *
master = Tk()
label1= Label(master, text='Department')
label1.grid(row=0, column=0)
textBox = Text(master, height=1, width=10)
textBox.grid(row=0, column=1)
def retrieve_input():
Department = textBox.get("1.0","end-1c")
fileread = pd.read_csv('50.csv', encoding='latin-1')
filevalue = fileread.loc[fileread['Customer'].str.contains(Department, na=False)]
def printSomething():
label = Label(master, textvariable=filevalue)
label.grid(row=3, column=1)
button1 = Button(master,text="Show Values", command=lambda: retrieve_input())
button1.grid(row=2, column=1)
mainloop( )
I have searched around Stack Overflow of how to do this, and was able to construct my code up until this point, However when I click the Show values button, nothing happens. I could find nowhere online that helped address this issue. Is there something fundamentally wrong with my code? Using Python 3.7
You define a nested printSomething function that would display something, but you never call that function.
This would fix that problem:
def retrieve_input():
Department = textBox.get("1.0","end-1c")
fileread = pd.read_csv('50.csv', encoding='latin-1')
filevalue = fileread.loc[fileread['Customer'].str.contains("Lam Dep", na=False)]
def printSomething():
label = Label(master, textvariable=filevalue)
label.grid(row=3, column=1)
printSomething()
But I'm not sure why you need the function in the first place; you can just do this:
def retrieve_input():
Department = textBox.get("1.0","end-1c")
fileread = pd.read_csv('50.csv', encoding='latin-1')
filevalue = fileread.loc[fileread['Customer'].str.contains("Lam Dep", na=False)]
label = Label(master, textvariable=filevalue)
label.grid(row=3, column=1)
But you have a second problem: You're trying to set the textvariable=filevalue, but that doesn't make any sense.
The textvariable has to be a tkinter.StringVar instance, not a plain old Python string. You can then set the StringVar to hold your string.
filevar = StringVar()
filevar.set(filevalue)
label = Label(master, textvariable=filevar)
label.grid(row=3, column=1)
… or just pass the text in directly, without a tkinter variable:
label = Label(master, text=filevalue)
label.grid(row=3, column=1)
There's still one more problem: Every time you call retrieveInput, it's going to create a new Label and grid it in front of whatever used to be there, but you never delete the old ones. So if you press the button over and over again, there will be a whole stack of invisible widgets just wasting resources.
It probably makes more sense to move the label creation to the global scope, just like the text box and the other label, and replace its text in this function, instead of creating a new label each time.
Using a StringVar is the simplest way to do this:
# ...
textBox = Text(master, height=1, width=10)
textBox.grid(row=0, column=1)
fileVar = StringVar()
fileLabel = Label(master, textvariable=fileVar)
fileLabel.grid(row=3, column=1)
def retrieve_input():
Department = textBox.get("1.0","end-1c")
fileread = pd.read_csv('50.csv', encoding='latin-1')
filevalue = fileread.loc[fileread['Customer'].str.contains("Lam Dep", na=False)]
fileVar.set(filevalue)
# ...
You may have other bugs in your code, but I think if you fix these three, you'll at least be pretty close to everything working.
Considering you are running Python 3.7, as you said, the following code will solve your problem:
import pandas as pd
from tkinter import *
master = Tk()
label1= Label(master, text='Department')
label1.grid(row=0, column=0)
textBox = Text(master, height=1, width=10)
textBox.grid(row=0, column=1)
def retrieve_input():
global text
department = textBox.get("1.0","end-1c")
fileread = pd.read_csv('50.csv', encoding='latin-1')
filevalue = fileread.loc[fileread['Customer'].str.contains("Lam Dep", na=False)]
text.set(filevalue)
button1 = Button(master,text="Show Values", command=retrieve_input)
button1.grid(row=2, column=1)
text = StringVar()
label = Label(master, textvariable=text)
label.grid(row=0, column=1)
mainloop()
You are facing these problems:
You are defining an inner function printSomething which is never called.
Even if you were calling printSomething you are going to create a new Label every time you press button1.
In this as, you don't need to use lambda to pass the callback that will be executed, you can simply pass command=retrieve_input
The simplest solution might be to define a StringVar (text) which is going to be associated with a Label (label), and when you press the button button1 you update call the method set on that variable text.

How to add a custom tkinter textbox in my Python app?

So I have been using python to do my 'ETLs' from SQL to Excel or CSV. I have just found it to be faster and easier than using SSIS.
While I do this in Jupyter I thought it would be a fun exercise to package this into an app that I can share with others. I'm not the most versed in tkinter and am trying to add a custom sized textbox that would be a little nicer than standard textbox for copy/pasting query. The issue is when I add the textbox, it instead adjusts the settings for the app window.
Here is what I have so far:
#Load Libraries
import pandas as pd
import numpy as np
import pyodbc
import xlsxwriter
from pandas import ExcelWriter
import openpyxl
import os
import datetime
from tkinter import *
#create window
def conVar():
server = e1.get()
db = e2.get()
un = e3.get()
pw = e4.get()
conn=("DRIVER={SQL Server};SERVER=%s;DATABASE=%s;UID=%s;PWD=%s" % (server, db, un, pw))
print(conn)
root = Tk()
root.title("SQL2Excel")
root.geometry("500x500")
Label(root, text="Server").grid(row=0)
Label(root, text="Database").grid(row=1)
Label(root, text="Username").grid(row=2)
Label(root, text="pw").grid(row=3)
Label(root, text="Tables").grid(row=6)
Label(root, text="or Enter Query").grid(row=7)
variable = StringVar(root)
variable.set(" ")
w = OptionMenu(root, variable, "test1", "test2", "test3")
r = root
r.geometry("250x150")
t = Text(r, height=20, width=40)
e1 = Entry(root)
e2 = Entry(root)
e3 = Entry(root)
e4 = Entry(root, show="*")
e1.grid(row=0, column=1)
e2.grid(row=1, column=1)
e3.grid(row=2, column=1)
e4.grid(row=3, column=1)
w.grid(row=6, column=1)
t.grid(row=8, column=1)
Button(root, text='Quit', command=root.destroy).grid(row=4, column=0, sticky=W, pady=4)
Button(root, text='Test Connection', command=conVar).grid(row=4, column=1, sticky=W, pady=4)
root.mainloop()
The idea is that once connection info is entered I will pull a list of tables into the combobox or let the user copy and paste a query into the larger text box. I really feel like I'm missing something easy but struggling at this point.
Can someone help show me the error of my ways? Thank you.
Your code is change the size of the root window
root.title("SQL2Excel")
root.geometry("500x500")
r = root
r.geometry("250x150")
Instead, try changing the geometry of the Combobox.
Also, I do not see a Combobox in your code

Python 2.7: Adding new items to Tkinter listbox without adding existing values

I am writing a simple bulk file utility. I have two listboxes in the GUI. Listbox1 contains a list of files that exist in whichever directory the user selects. The user can then add selected items in listbox1, to listbox2. Currently this allows duplicate items to be added. I would like to figure out how to check if selected items already exist in listbox2, and only add items that aren't already present.
Here is my code:
from Tkinter import *
import Tkinter, Tkconstants, tkFileDialog, tkMessageBox
import os, sys
class FileZap():
def __init__(self, root):
def getDir():
dir = tkFileDialog.askdirectory(initialdir="C:/")
self.user1.delete(0,END)
self.user1.insert(0,dir)
files = (file for file in os.listdir(dir)
if os.path.isfile(os.path.join(dir, file)))
for file in files:
self.listbox1.insert(0,file)
def selectAdd():
selection1 = self.listbox1.curselection()
for i in selection1:
selectedFiles = self.listbox1.get(i)
self.listbox2.insert(0, selectedFiles)
root.title("Test_App 1.0")
root.geometry("860x450")
self.listbox1 = Listbox(root, width=50, selectmode="multiple")
self.listbox1.grid(row=2, column=2)
self.scrollbar = Scrollbar(orient=VERTICAL, command=self.listbox1.yview)
self.listbox1.config(yscrollcommand=self.scrollbar.set)
self.scrollbar.grid(row=2, column=3, sticky="ns")
self.listbox2 = Listbox(root, width=50)
self.listbox2.grid(row=2, column=4)
self.label1 = Label(root, text="Select a folder: ")
self.label1.grid(row=1, column=1)
self.user1 = Entry(root, width="50")
self.user1.grid(row=1, column=2)
self.browse = Button(root, text="Browse", command=getDir)
self.browse.grid(row=1, column=3)
self.button2 = Button(root, text="Add to Selection", command=selectAdd)
self.button2.grid(row=3, column=3)
self.quit = Button(root, text="Exit", command=root.quit)
self.quit.grid(row=8, column=4)
root = Tkinter.Tk()
file_zap = FileZap(root)
root.mainloop()
In the above code the function selectAdd() performs the item manipulation. I was hoping to do this by adding another for loop within the function that returns the values in listbox2, and adding items if not in listbox2. However I can only seem to return selected values using .get, I can't figure out how to select all values. Also I'm not sure that this is even the best way to do this. Any help would be much appreciated!
How about just getting all values currently in the second listbox with listbox2.get(0,END) and if there are no duplicates add the selectedFiles:
def selectAdd():
selection1 = self.listbox1.curselection()
for i in selection1:
selectedFiles = self.listbox1.get(i)
list2files = self.listbox2.get(0, END)
if selectedFiles not in list2files:
self.listbox2.insert(0, selectedFiles)

Categories

Resources