Python Tkinter text entry box to insert data to SQL Server - python

I have created a small python tkinter program designed to have a user write data into text entry boxes in the app then insert this data into a MS SQL server database. When clicking the insert button I am getting the following error message, stopping the app from insert the code into SQL.
cursor.execute("INSERT INTO TEST_DISA_MAIN_TABLE VALUES (:DENSITY_VALUE, :DATE, :TIME, :CHART_VALUE)",
pyodbc.ProgrammingError: ('The SQL contains 0 parameter markers, but 1 parameters were supplied', 'HY000')*
This is my code for the python insert function:
def insertvalue():
# Create a database or connect to one
conn = pyodbc.connect('Driver={SQL Server};'
'Server=MON-SQL-02;'
'Database=ENVIRONMENTAL;'
'Trusted_Connection=yes;')
# Create cursor
cursor = conn.cursor()
# Insert into table
cursor.execute("INSERT INTO TEST_DISA_MAIN_TABLE VALUES (:DENSITY_VALUE, :DATE, :TIME, :CHART_VALUE)",
{
'DENSITY_VALUE': DENSITY_VALUE.get(),
'DATE': DATE.get(),
'TIME': TIME.get(),
'CHART_VALUE': CHART_VALUE.get(),
})
# Commit changes
conn.commit()
#Close Connection
conn.close()
# Clear the text boxes
DENSITY_VALUE.delete(0, END)
DATE.delete(0, END)
TIME.delete(0, END)
CHART_VALUE.delete(0, END)
#Create text boxes
DENSITY_VALUE = Entry(root, width=30)
DENSITY_VALUE.grid(row=2, column=1)
DATE = Entry(root, width=30)
DATE.grid(row=3, column=1)
TIME = Entry(root, width=30)
TIME.grid(row=4, column=1)
CHART_VALUE = Entry(root, width=30)
CHART_VALUE.grid(row=5, column=1)
#Create Text box labels
DENSITY_VALUE_Label = Label(root, text="Density Value")
DENSITY_VALUE_Label.grid(row=2, column=0)
DATE_Label = Label(root, text="Date")
DATE_Label.grid(row=3, column=0)
TIME_Label = Label(root, text="Time")
TIME_Label.grid(row=4, column=0)
CHART_VALUE_Label = Label(root, text="Chart Value")
CHART_VALUE_Label.grid(row=5, column=0)
button = Button(root, text = "Show All Values", command = showvalues)
button.grid(row=0, column=0)
button = Button(root, text = "Insert Values", command = insertvalue)
button.grid(row=1, column=0)
#Commit changes
conn.commit()
# Close connection
conn.close()
root.mainloop()
I used this format to insert data into a sqlite3 db, but the same format is not working when inserting into a SQL Server database. I have tested the connection to the SQL server and can display values in the app so that part works correctly.

Related

How to display MySQL data using tkinter in Python?

I am new to tkinter and trying to make an invoice application using this library. The app will read an Excel file using the Browse button and then save the Excel data into MySQL database which is working fine. However, when I press the Report button, it's not displaying the record on new window and getting halt all the time. Even a new window won't open, it should display the record on the current window. Here is my code:
# Import the required Libraries
from tkinter import *
from tkinter import ttk, filedialog
from tkinter.filedialog import askopenfilename
import mysql.connector
import xlrd
import tkinter as tk
from tkinter import filedialog
def browse_button():
# Allow user to select a directory and store it in global var
# called folder_path
global folder_path
filename = filedialog.askopenfilename()
folder_path.set(filename)
print(filename)
def show_new_window():
print("Show new window called")
# Create the new window
new_window = tk.Toplevel(app)
new_window.title("Report")
# Create a label in the new window
label = tk.Label(new_window, text="Delivery Report")
label.pack()
# Connect to the database
conn = mysql.connector.connect(user='root',
password='',
host='localhost',
database='magnetico')
mycursor = conn.cursor()
mycursor.execute("SELECT id_user, Vendor, KM FROM perorder")
# Get the results
result = mycursor.fetchall()
# Close the cursor and connection
mycursor.close()
conn.close()
# Create a button for each row in the result
for row in result:
button = tk.Button(new_window, text=str(row))
button.pack()
# Set the geometry of tkinter frame
app = tk.Tk()
app.geometry("900x800")
folder_path = tk.StringVar()
# Add a heading
heading = tk.Label(app, text="Click the Button to browse the Files", font=("Helvetica", 16))
heading.grid(row=0, column=1, columnspan=2)
lbl1 = tk.Label(app, textvariable=folder_path)
lbl1.grid(row=1, column=1, padx=10, pady=10, sticky=tk.NSEW)
# Center the button
button2 = tk.Button(app, text="Browse", command=browse_button)
button2.grid(row=1, column=2, padx=10, pady=10, sticky=tk.NSEW)
button = tk.Button(app, text="Report", command=show_new_window)
button.grid(row=2, column=2, padx=10, pady=10, sticky=tk.NSEW)
# Set the row and column weights
app.columnconfigure(1, weight=1)
app.columnconfigure(2, weight=1)
app.rowconfigure(1, weight=1)
app.mainloop()
# Connect to the database
conn = mysql.connector.connect(user='root',
password='',
host='localhost',
database='magnetico')
# Open the workbook
book = xlrd.open_workbook("mpo1.xls")
# Get the sheet you want
sheet = book.sheet_by_name("Order Details")
# Iterate through the rows of the sheet
for row_idx in range(sheet.nrows):
# Get the values in the row
row = sheet.row_values(row_idx)
# Insert the row into the database
cursor = conn.cursor()
cursor.execute("INSERT INTO perorder (mp_task_nr, batch_id, dropoff_sequence, id_user_payout_type, task_status, city, fleet, id_user, Name, Vendor, order_date, UID, KM, total_amount, Remarks) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )", row)
conn.commit()

How to trigger a run button based on all the values in a list?

I have a Tkinter app and inside that app I have an OptionMenu which is giving me all the id's that are located in the list vehicleid. Please note that this list can become bigger or smaller.
Now I want my button to send the data of owner and vehicleid to a database based on what the user selects. So if I have for example 2 vehicleid's, I first need to select a specific vehicleid and for every vehicleid I need to select a specific owner.
So in case of 2 vehicleid my database should look like this:
vehicleid owner
C161 --- Spain
C162 --- United Kingdom
App looks like this:
This is my code:
owner = ['Spain', 'United Kingdom', 'Malaysia']
vehicleid = ['C161', 'C162']
window = Tk()
window.title("Running Python Script") # Create window
window.geometry('550x300') # Geo of the window
##These are the option menus
dd_owner = StringVar(window)
dd_owner.set(owner[0]) # the first value
w = OptionMenu(window, dd_owner, *owner)
w.grid(row=1, column=1)
dd_id = StringVar(window)
dd_id.set(vehicleid[0])
w0 = OptionMenu(window, dd_id, *vehicleid)
w0.grid(row=0, column=1)
##The run button
run_list_button =Button(window, text="Send data of ID's to database!")
run_list_button.grid(column=0, row=3)
##These are the titles
l1 = Label(window, text='Select Owner', width=15)
l1.grid(row=1, column=0)
l0 = Label(window, text='Select vehicle id:', width = 30)
l0.grid(row=0, column=0)
mainloop()
To begin with, you should store the data somewhere(a dictionary or a file..) and then read the data when the user presses the button.
import mysql.connector as mysql
....
mydb = mysql.connect(host = 'localhost',user = 'root',passwd = '****.',database = 'table_data')
data = {}
def store():
if dd_id.get() not in data:
data[dd_id.get()] = dd_owner.get()
print(data)
def upload():
cur = mydb.cursor()
for item in data.items():
sql = 'INSERT INTO table_data VALUES (%s,%s)'
params = (item[0],item[1])
cur.execute(sql,params)
mydb.commit()
print('Done')
....
# The store button
Button(window, text="Store data!",command=store).grid(column=0, row=3)
# The database button
Button(window, text="Send to database",command=upload).grid(column=0, row=4)
This will store the data in the database when the respective buttons are clicked, also duplicate entries or updatiion of entries will not be allowed.
Though your question is confusing. After looking at your discussion I understand that you want to send all data to the database only after the users have confirmed their choice.
In that case, you probably need a dictionary where you store both vehicle_id and owner {"vehicle_id": [], "owner": []} until the user clicks on the update database button. Once you have updated the database make sure to empty the dictionary so the previously selected items are not inserted into the database again.
Note: you would still need another button to be pressed several times to insert data into the dictionary. You can choose not to have the button by using the trace method of the control variable
Here is an example
from tkinter import *
import sqlite3
CREATE_QUERY = "CREATE TABLE IF NOT EXISTS vehicle(vehicle_id VARCHAR(5), owner VARCHAR(100));"
INSERT_QUERY = "INSERT INTO vehicle(vehicle_id, owner) VALUES(?, ?);"
SELECT_QUERY = "SELECT * FROM vehicle;"
sql_file = "sample.db"
id_dict = {"vehicle_id": [], "owner": []}
def create_data_base():
with sqlite3.connect(sql_file) as conn:
conn.execute(CREATE_QUERY)
conn.commit()
def insert_to_db():
global id_dict
with sqlite3.connect(sql_file) as conn:
for value in zip(*id_dict.values()):
conn.execute(INSERT_QUERY, value)
conn.commit()
id_dict = {"vehicle_id": [], "owner": []} # empty the list once you insert the data
display_data()
def display_data():
with sqlite3.connect(sql_file) as conn:
curr = conn.cursor()
curr.execute(SELECT_QUERY)
items = curr.fetchall()
print(items)
def add():
id_dict["vehicle_id"].append(dd_id.get())
id_dict["owner"].append(dd_owner.get())
print(id_dict)
owner = ['Spain', 'United Kingdom', 'Malaysia']
vehicleid = ['C161', 'C162']
window = Tk()
window.title("Running Python Script") # Create window
window.geometry('550x300') # Geo of the window
create_data_base()
##These are the option menus
dd_owner = StringVar(window)
dd_owner.set(owner[0]) # the first value
w = OptionMenu(window, dd_owner, *owner)
w.grid(row=1, column=1)
dd_id = StringVar(window)
dd_id.set(vehicleid[0])
w0 = OptionMenu(window, dd_id, *vehicleid)
w0.grid(row=0, column=1)
Button(window, text='Add', command=add).grid(column=1, row=3)
##The run button
run_list_button =Button(window, text="Send data of ID's to database!", command=insert_to_db)
run_list_button.grid(column=0, row=3)
##These are the titles
l1 = Label(window, text='Select Owner', width=15)
l1.grid(row=1, column=0)
l0 = Label(window, text='Select vehicle id:', width = 30)
l0.grid(row=0, column=0)
window.mainloop()
The above code will insert all the data from the dictionary to the database.

Tkinter Form and DB Insertion

Hi I am trying to create a db for a golf game I play with my son and am having some issues.
I keep getting the following error when trying to insert data into my db:
pyodbc.ProgrammingError: ('The SQL contains 0 parameter markers, but 1 parameters were supplied', 'HY000')
Here is the code:
import tkinter as TK
from tkinter import *
import pyodbc
golfers=Tk()
golfers.title("Golfers")
golfers.geometry('500x500')
#Databases
#Create a Database or Connect to one
conn = pyodbc.connect('Driver={SQL Server};'
'Server=DESKTOP-SCL1250\SQLEXPRESS01;'
'Database=tgt;'
'Trusted_Connection=yes;')
#Create Cursor
c=conn.cursor()
# c.execute("""CREATE TABLE tours(
# tour_code varchar NOT NULL,
# description varchar (255),
# PRIMARY KEY (tour_code))
# """)
# c.execute("""CREATE TABLE golfers (
# golfer_id int IDENTITY(1,1) NOT NULL,
# last_name varchar (255),
# first_name varchar (255),
# tour_code varchar FOREIGN KEY REFERENCES tours(tour_code)
# PRIMARY KEY (golfer_id))
# """)
def submit():
#Create a Database or Connect to one
conn = pyodbc.connect('Driver={SQL Server};'
'Server=DESKTOP-SCL1250\SQLEXPRESS01;'
'Database=tgt;'
'Trusted_Connection=yes;')
#Create Cursor
c=conn.cursor()
#Insert into table
c.execute('INSERT INTO golfers VALUES(:golfer_id, :last_name, :first_name, :tour_code)',
{
'golfer_id': golfer_id.get(),
'last_name': last_name.get(),
'first_name': first_name.get(),
'tour_code': tour_code.get()
})
#Commit Changes
conn.commit()
#Close Connection
conn.close()
#clear the text boxes
golfer_id.delete(0,END)
last_name.delete(0, END)
first_name.delete(0, END)
tour_code.delete(0,END)
#Create Text Boxes
golfer_id = Entry(golfers, width=30)
golfer_id.grid(row=0, column=1, padx=20)
last_name = Entry(golfers, width=30)
last_name.grid(row=1, column=1, padx=20)
first_name = Entry(golfers, width=30)
first_name.grid(row=2, column=1, padx=20)
tour_code = Entry(golfers, width=30)
tour_code.grid(row=3, column=1, padx=20)
#Create Text Box Labels
golfer_id_label = Label(golfers, text="Golfer ID")
golfer_id_label.grid(row=0, column=0)
last_name_label = Label(golfers, text="Last Name")
last_name_label.grid(row=1, column=0)
first_name_label = Label(golfers, text="First Name")
first_name_label.grid(row=2, column=0)
tour_code_label = Label(golfers, text="Tour Code")
tour_code_label.grid(row=3, column=0)
#Create Submit Button
submit_btn = Button(golfers, text="Add Record", command=submit)
submit_btn.grid(row=6, columnspan=2, pady=10, padx=10, ipadx=100)
#Commit Changes
conn.commit()
#Close Connection
conn.close()
golfers.mainloop()
Any help would be appreciated.

GUI-Tkinter-Python Program

How to create a button to open a new window in which all records are printed.
In the following part of program, i am unable to print records in a new window, but it gets printed in the already created window & the new window remains empty.
Here is that small part of program:-
root = Tk()
def query():
query = Tk()
query.title('Records')
query.iconbitmap(r'C:\Users\pankaj\Downloads\Elegantthemes-Beautiful-Flat-Document.ico')
query.geometry("450x350")
#Create a database or connect to one
conn = sqlite3.connect('Payslip.db')
# Create cursor
c = conn.cursor()
#Query the database
c.execute("SELECT *,oid from Payslip")
records = c.fetchall()
#print(records)# to print in the background
#Loop the results
print_records = ''
for record in records: #to show the records
print_records += str(record[0]) +"\t" + str(record[8])+ "\n"# \t to give space(tab) between them
query_label = Label(root, text=print_records)
query_label.grid(row=14, column=0, columnspan=2)
#Commit Change
conn.commit()
# Close Connection
conn.close()
#create a Query button
query_btn = Button(root, text="Show Records", command=query)
query_btn.grid(row=9,column=0, columnspan=2, pady=10, padx=10, ipadx=135)
Well, you are trying to print the print_records in the query_label, which you assigned to the root window:
query_label = Label(root, text=print_records)
You said you created a new window but I can't see it in the code, so you might want to do something like this:
def query():
top1 = Toplevel() # creates new window called top1
print_records = ''
for record in records: #to show the records
print_records += str(record[0]) +"\t" + str(record[8])+ "\n"
query_label = Label(top1, text=print_records) # now the query_label is assigned to top1
query_label.grid(row=14, column=0, columnspan=2)
However you want to do it:
query_label = Label(NEW_WINDOW, text=print_records)

Python / Tkinter - Error message when I try to save changes

I am building a database for tools and matrials list in Python using Tkinter for the GUI. I am running into issues when I try to edit data. Everything works until I click the save button in the editor window. It says: sqlite3.ProgrammingError: You did not supply a value for binding 1. Can anyone see what I am doing wrong here?
Here is my code:
from tkinter import *
import sqlite3
mud = Tk()
mud.title("Mud Data")
mud.geometry("400x600")
# Create database
conn = sqlite3.connect('well_sav.db')
# Create cursor
c = conn.cursor()
# Create table
# c.execute("""CREATE TABLE mud (
# mud_type text,
# mud_weight real ,
# mud_viscosity real,
# mud_pit_number real
# )""")
# Create Submit Function for DB
def submit():
# Connect to DB
conn = sqlite3.connect('well_sav.db')
# Create cursor
c = conn.cursor()
# Insert into table
c.execute("INSERT INTO mud VALUES (:mud_type, :mud_weight, :mud_viscosity, :mud_pit_number)",
{
'mud_type': mud_type.get(),
'mud_weight': mud_weight.get(),
'mud_viscosity': mud_viscosity.get(),
'mud_pit_number': mud_pit_number.get()
})
# Commit changes
conn.commit()
# Close connection
conn.close()
# Clear The Text Boxes
mud_type.delete(0, END)
mud_weight.delete(0, END)
mud_viscosity.delete(0, END)
mud_pit_number.delete(0, END)
# Function to edit a record
def edit():
# Create global variables
global editor
global mud_type_editor
global mud_weight_editor
global mud_viscosity_editor
global mud_pit_number_editor
editor = Tk()
editor.title("Edit mud")
editor.geometry("400x200")
conn = sqlite3.connect('well_sav.db')
c = conn.cursor()
record_id = delete_box.get()
c.execute("SELECT * FROM mud WHERE oid = " + record_id)
records = c.fetchall()
mud_type_editor = Entry(editor, width=30)
mud_type_editor.grid(row=0, column=1, pady=(10, 0))
mud_weight_editor = Entry(editor, width=30)
mud_weight_editor.grid(row=1, column=1)
mud_viscosity_editor = Entry(editor, width=30)
mud_viscosity_editor.grid(row=2, column=1)
mud_pit_number_editor = Entry(editor, width=30)
mud_pit_number_editor.grid(row=3, column=1)
# Create Text box Label
mud_type_label = Label(editor, text="Mud Type")
mud_type_label.grid(row=0, column=0, pady=(10, 0))
mud_weight_label = Label(editor, text="Mud Weight")
mud_weight_label.grid(row=1, column=0)
mud_viscosity_label = Label(editor, text="Mud Viscosity")
mud_viscosity_label.grid(row=2, column=0)
mud_pit_number_label = Label(editor, text="Mud Pit Number")
mud_pit_number_label.grid(row=3, column=0)
# Loop through results
for record in records:
mud_type_editor.insert(0, record[0])
mud_weight_editor.insert(0, record[1])
mud_viscosity_editor.insert(0, record[2])
mud_pit_number_editor.insert(0, record[3])
# Create save button
edit_button = Button(editor, text="Save Update", command=update)
edit_button.grid(row=7, column=1, pady=5, padx=5, ipadx=98)
conn.commit()
conn.close()
# Fucntion for updates
def update():
conn = sqlite3.connect('well_sav.db')
c = conn.cursor()
record_id = delete_box.get()
c.execute("""UPDATE mud SET
mud_type = :name,
mud_weight = :length,
mud_viscosity = :inside_diameter,
mud_pit_number = :outside_diameter
WHERE oid = :oid""",
{
'mud_type': mud_type_editor.get(),
'mud_weight': mud_weight_editor.get(),
'mud_viscosity': mud_viscosity_editor.get(),
'mud_pit_number': mud_pit_number_editor.get(),
'oid': record_id
})
conn.commit()
conn.close()
editor.destroy()
# Function to delete a record
def delete():
conn = sqlite3.connect('well_sav.db')
c = conn.cursor()
c.execute("DELETE FROM mud WHERE oid = " + delete_box.get())
conn.commit()
conn.close()
# Create Query Function
def query():
# Connect to DB
conn = sqlite3.connect('well_sav.db')
# Create cursor
c = conn.cursor()
# Query the DB
c.execute("SELECT *, oid FROM mud")
records = c.fetchall()
# print(records)
# Loop through results
print_records = ''
for record in records:
print_records += str(record[0]) + "\t " + str(record[1]) + \
"\t " + str(record[2]) + "\t " + \
str(record[3]) + str(record[4]) + "\n"
query_label = Label(mud, text=print_records)
query_label.grid(row=20, column=0, columnspan=2)
# Commit changes
conn.commit()
# Close connection
conn.close()
# Math Functions
def volume_per_foot(bha_result_text):
bha_gallons_per_foot = float(mud_viscosity.get()) * \
float(mud_viscosity.get()) / 1029.4
bha_result_text.set(str(bha_gallons_per_foot))
# Create Text Boxes
mud_type = Entry(mud, width=30)
mud_type.grid(row=0, column=1, pady=(10, 0))
mud_weight = Entry(mud, width=30)
mud_weight.grid(row=1, column=1)
mud_viscosity = Entry(mud, width=30)
mud_viscosity.grid(row=2, column=1)
mud_pit_number = Entry(mud, width=30)
mud_pit_number.grid(row=3, column=1)
delete_box = Entry(mud, width=30)
delete_box.grid(row=6, column=1)
# Create Text box Label
mud_type_label = Label(mud, text="Mud Type")
mud_type_label.grid(row=0, column=0, pady=(10, 0))
mud_weight_label = Label(mud, text="Mud Weight")
mud_weight_label.grid(row=1, column=0)
mud_viscosity_label = Label(mud, text="Mud Viscosity")
mud_viscosity_label.grid(row=2, column=0)
mud_pit_number_label = Label(mud, text="Pit Number")
mud_pit_number_label.grid(row=3, column=0)
delete_box_label = Label(mud, text="Select ID")
delete_box_label.grid(row=6, column=0)
# Create Submit Button
submit_button = Button(mud, text="Save", command=submit)
submit_button.grid(row=4, column=1, pady=5, padx=5, ipadx=121)
# Create Query Button
query_button = Button(mud, text="Show Muds", command=query)
query_button.grid(row=5, column=1, pady=5, padx=5, ipadx=79)
# Create edit button
edit_button = Button(mud, text="Edit Muds", command=edit)
edit_button.grid(row=7, column=1, pady=5, padx=5, ipadx=87)
# Create delete button
delete_button = Button(mud, text="Delete Mud", command=delete)
delete_button.grid(row=8, column=1, pady=5, padx=5, ipadx=80)
# Commit changes
conn.commit()
# Close connection
conn.close()
mud.mainloop()
And here is the error message:
Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/tkinter/__init__.py", line 1883, in __call__
return self.func(*args)
File "mud.py", line 123, in update
c.execute("""UPDATE mud SET
sqlite3.ProgrammingError: You did not supply a value for binding 1.
Hi #LoudEye and welcome to Stack Overflow! Try using ? instead of : like this:
c.execute("UPDATE mud SET mud_type=?,mud_weight = ?, mud_viscosity=?, mud_pit_number = ? WHERE...",(mud_type_editor.get(), mud_weight_editor.get(),mud_viscosity_editor.get(),mud_pit_number_editor.get()))
Note: You should also use WHERE also with question mark like I've used with SET

Categories

Resources