-1

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.

Brzydal
  • 1
  • 2
  • Does this answer your question? [Tkinter: AttributeError: NoneType object has no attribute ](https://stackoverflow.com/questions/1101750/tkinter-attributeerror-nonetype-object-has-no-attribute-attribute-name) – TheLizzard Oct 19 '21 at 13:00

2 Answers2

0

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.

Pommepomme
  • 115
  • 1
  • 11
  • I don't think the problem is in the writing of the csv file but getting the data out of the `tkinter` window. Also when writing an answer try explaining what OP did wrong. Right now all I see is a suggestion to yse `pandas` instead of `csv`. – TheLizzard Oct 19 '21 at 13:16
  • Thank you @TheLizzard that's exactly what i want to know and instead i got answer to use something else without even exlaining how to use it. – Brzydal Oct 19 '21 at 13:32
  • @Brzydal The problem is that you have `Function = OptionMenu(...).grid(...)`. That doesn't do what you expect it to do. Instead split it in 2 lines: `Function = OptionMenu(...)` and `Function.grid(...)`. Also next time if you are getting an error post it in the question. – TheLizzard Oct 19 '21 at 13:42
  • Sorry if I misunderstood the question, but as I saw "get()" functions called, I thought this part was successful since you didn't mention any errors or problems anywhere – Pommepomme Oct 19 '21 at 13:45
  • @TheLizzard i've switched from csv to pandas and also took your suggestion about (...).grid(...) still no idea how to proceed but thanks anyway. – Brzydal Oct 20 '21 at 18:43
0

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()
acw1668
  • 40,144
  • 5
  • 22
  • 34
  • thank you so much! it's working now! – Brzydal Oct 21 '21 at 05:42
  • Just curious why did you use `enumerate(..., 2)` instead of `row+2`? – TheLizzard Oct 21 '21 at 10:40
  • @TheLizzard No special reason. Why do you ask this if both have the same result? – acw1668 Oct 21 '21 at 10:53
  • @acw1668 I usually use `row+2` and I haven't seen anyone really use the `start` argument in `enumerate`. So I was curious if you had a special reason. I always look over code as if I am writing it and check if it matches what I would have written. – TheLizzard Oct 21 '21 at 11:16
  • @TheLizzard If I can specify the start index, then why to perform `row+2` in each iteration. – acw1668 Oct 21 '21 at 11:21