Python 3x query data using dates from datepicker dialog - python-3.x

One last attempt to solve this problem. I have a Python program that queries the database using a default rundate to today - timedelta(7). I have created a datepicker to be opened using a menu button if the user want to choose their own dates to query. I am having problems figuring out the query that will integrate the dates chosen by the datepicker into the program.
The datepicker works fine as I am able to print the start and end dates that are chosen using
def submit():
start = self.result1.strftime("%m/%d/%Y")
end = self.result2.strftime("%m/%d/%Y")
print(start, end)
I assume that the "print(start, end)" will have to be changed to "return(start,end)" to incorporate it into the main query but I could be wrong.
The initial query and top part of the interface is
import pyodbc
from datetime import date, timedelta
from tkinter import *
from tkinter.ttk import *
import calendar
from decimal import *
import sqlite3
import os
import pick
db = r"M:\CWA_DB\WPTS\WPTS_Prod\WPTS_PROD_be.accdb"
conn = pyodbc.connect('Driver={Microsoft Access Driver (*.mdb, *.accdb)};Dbq='+db)
cur = conn.cursor()
#Rundate, 7 days ago
rundate = date.today() - timedelta(7)
print(rundate)
#Query permits made effective since rundate
query = '''select `NPDES_ID`, `EffectiveDate`, `FacilityName`, `StateFacilityID`, `City`, `CountyName`
from Permits
where `EffectiveDate` >= ?
order by `NPDES_ID`'''
IDS=[]
FacCodes=[]
PermStrings=[]
PayStrings=[]
OwnerStrings=[]
MTB=[]
MTG=[]
MTR=[]
SWC=[]
MT0=[]
count=0
#for each row in result of query
for row in cur.execute(query, (rundate)):
try:
d= row[1].strftime('%m/%d/%Y')
except:
d=""
#create a display string with the appropriate information permit # - date - facility name - city, county
for i in range(len(row)):
if not row[i]:
row[i] = ""
permitstring=row[0]+" | "+d+"\t | "+row[2]+"\t | "+row[4]+", "+row[5]+" County"
IDS.append(row[0])
tempid=row[0]
#add the index to the appropriate permit type array, used to display seperately
if tempid[0:3]=="MTB":
MTB.append(count)
if tempid[0:3]=="MTG":
MTG.append(count)
if tempid[0:4]=="MTR0":
MTR.append(count)
if tempid[0:3]=="MT0" or tempid[0:3]=="MT4" or tempid[0:3]=="MTX":
MT0.append(count)
if tempid[0:4]=="MTR1":
SWC.append(count)
FacCodes.append(row[3])
PermStrings.append(permitstring)
count+=1
WPTSInv=[]
#get the owners for the permits
for i in range(len(IDS)):
query = '''select `Owner`
from Owners
where `StateFacilityID` = ?'''
for row in cur.execute(query, (str(FacCodes[i]))):
#create an owner name string for the facility ID
OwnerStrings.append("Owner: "+row[0])
#get payments on the permits
for i in range(len(IDS)):
paydate = date.today() - timedelta(60)
query = '''select `AmountPaid_credit`, `PayComment`, `DateReceived`, `WPTSinvoiceNo`
from Payments
where `NPDES_ID` = ? and `DateReceived` >= ?'''
PayStrings.append("\tPayment Received")
for row in cur.execute(query, (IDS[i],paydate)):
WPTSInv.append(row[3])
d= row[2].strftime('%m/%d/%Y')
#create a payment string
PayStrings[i]="\t$"+str(round(Decimal(row[0]),2))+" | "+d+" | "+row[1]
#Initiate interface
root = Tk()
master = Frame(root, name='master')
master.pack(fill=BOTH)
root.geometry("800x800+300+100")
root.title('WeeklyReport')
menu_bar = Menu(root)
def exit():
root.destroy()
def GetCalendar():
os.system("Pick.py")
root.wait_window
filemenu = Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="File", menu=filemenu)
filemenu.add_command(label="Exit", command=exit)
datemenu = Menu(menu_bar)
menu_bar.add_command(label='Change Date', command=GetCalendar)
root.config(menu=menu_bar)
# start the app
if __name__ == "__main__":
master.mainloop()
I have searched high and low for a solution but have not had much luck. I am sure others would be helped by an answer (even if the answer is that what I am trying to do is impossible)

Related

i am trying to populate sqlite data on wx.grid but cannot figure out how to display on grid by rows and columns

below is my code that can populate the table name but cannot display the query code
from the image i want my query data to be place on test text.
from array import array
from cProfile import label
from gettext import dpgettext
'''import wx
import datetime
import wx.adv
import sqlite3
import wx.grid as grid
'''
#dashboard frame
class mainGUI(wx.Frame):
def init(self,parent,title):
wx.Frame.init(self,parent,title=title,size=(1024,780))
self.initialise()
def initialise(self):
# connection to server adn curser setting
con = sqlite3.connect("NSWData.db")
print("DATABSE created SUCCESSFULLY")
cur=con.cursor()
panel=wx.Panel(self)
rows = wx.BoxSizer(wx. VERTICAL)
head = wx.StaticText(panel, label="Search the record per year")
font = head.GetFont() #get the standard font
font.PointSize += 10 #increases the size
font = font.Bold() #makes it bold
head.SetFont(font) #resets the font
rows.Add(head, 1, wx.ALIGN_CENTER|wx.BOTTOM, border=2)
numSize = wx.BoxSizer(wx.HORIZONTAL)
self.startText = wx.StaticText(panel, label="Enter the Start Year")
self.endTest = wx.StaticText(panel, label="Enter the End year")
self.sd =wx.TextCtrl( panel,)
self.ed =wx.TextCtrl( panel)
self.sbtn=wx.Button(panel, label="Search")
numSize.Add( self.startText,1,wx.ALIGN_CENTER|wx.RIGHT, border=10)
numSize.Add(self.sd,1,wx.ALIGN_CENTER|wx.RIGHT, border=10)
numSize.Add( self.endTest,1,wx.ALIGN_CENTER|wx.RIGHT, border=10)
numSize.Add(self.ed,1,wx.ALIGN_CENTER|wx.RIGHT, border=10)
numSize.Add(self.sbtn,1,wx.ALIGN_CENTER|wx.RIGHT, border=10)
rows.Add(numSize,2,wx.ALIGN_CENTER)
#grid table here
self.mygrid= grid.Grid(panel)
self.mygrid.CreateGrid(25,25)
rows.Add(self.mygrid,1,wx.EXPAND)
# adding search button event to get the current date
self.Bind(wx.EVT_BUTTON,self.onSearch,self.sbtn)
panel.SetSizerAndFit(rows)
self.Show(True)
def onSearch(self,evt):
try:
ys=int(self.sd.Value)
ye=int(self.ed.Value)
if ys<=ye:
s=str(ys)
y1=str(s+'%')
e=str(ye)
y2=str('%'+e)
print(y1)
print(y2)
con = sqlite3.connect("NSWData.db")
print("DATABaSE connection successfull")
cur=con.cursor()
qdata=cur.execute(f"SELECT * FROM records WHERE OFFENCE_FINYEAR LIKE '{y1}'OR `enter code here`OFFENCE_FINYEAR LIKE '{y2}'")
qdata.fetchall()
self.mygrid.ClearGrid()
metadata=qdata
labels=[]
for i in metadata.description:
labels.append(i[0])
labels=labels[1:]
for i in range(len(labels)):
self.mygrid.SetColLabelValue(i,labels[i])
for x in range(len(labels)):
for y in range(len(labels)):
self.mygrid.SetCellValue(x, y,'test')
# print(cur.fetchall())
if ys>ye:
wx.MessageBox("please enter the year in correct order")
except ValueError:
wx.MessageBox("please enter the correct year")
self.sd.Value=""
self.ed.Value=""
app=wx.App()
enter code here`frame=mainGUI(None,"data analysis app")
enter code here`app.MainLoop()
enter image description here

Check age in Tkinter using datetime

I am new to programming in python, and I want to create simple app for calculating your age based on the user input. I am using the 'datetime' module, and I found example of the program running in the terminal, but I don't know tow to link the entry box with the button using tkinter. This is the link from the code sample I am using and want to recreate it in tkinter.
import tkinter as tk
from datetime import date
def CheckAge():
global result # to return calculation
result = str(entry.get())
today = date.today()
#Convert user input into a date
dob_data = result.split("/")
dobDay = int(dob_data[0])
dobMonth = int(dob_data[1])
dobYear = int(dob_data[2])
dob = date(dobYear,dobMonth,dobDay)
#Calculate number of days lived
numberOfDays = (today - dob).days
#Convert this into whole years to display the age
age = numberOfDays // 365
label=tk.Label(root, "You are "+str(age) +" years old", command=CheckAge)
label.pack()
print("You are " + str(age) + " years old.")
result = 0
root = tk.Tk()
entry = tk.Entry(root)
entry.pack()
button = tk.Button(root, text="Calculate", command=CheckAge)
button.pack()
root.mainloop()
At the end of executing this code I get this error message:
dobDay = int(dob_data[0])
ValueError: invalid literal for int() with base 10: ''
As mentioned, I am beginner and I am using multiple code samples from online forums.
first of all, label does NOT have a command. Secondly, you need to add the attribute "text" to the label. So, here is the modified version of your code:
import tkinter as tk
from datetime import date
def CheckAge():
global result # to return calculation
result = str(entry.get())
today = date.today()
#Convert user input into a date
dob_data = result.split("/")
dobDay = int(dob_data[0])
dobMonth = int(dob_data[1])
dobYear = int(dob_data[2])
dob = date(dobYear,dobMonth,dobDay)
#Calculate number of days lived
numberOfDays = (today - dob).days
#Convert this into whole years to display the age
age = numberOfDays // 365
label=tk.Label(root, text="You are "+str(age) +" years old")
label.pack()
print("You are " + str(age) + " years old.")
result = 0
root = tk.Tk()
entry = tk.Entry(root)
entry.pack()
button = tk.Button(root, text="Calculate", command=CheckAge)
button.pack()
root.mainloop()
With these little modifications you should be able to get the result you wanted it.

Sqlalchemy filter by calculated datetime hybrid_property

I have a model Prescription.
from datetime import timedelta
from sqlalchemy.ext.hybrid import hybrid_property
class Prescription(db.Model):
""" docstring """
ID = db.column(db.Integer, primary_key=True)
date = db.Column(db.DateTime)
duration = db.Column(db.SmallInteger)
#hybrid_property
def expiration_date(self):
# return self.date + timedelta(days=self.duration)
return self.date + timedelta(days=7)
#classmethod
def actual(cls ):
""" docstring """
today = datetime.today()
return cls.query.filter(Prescription.expiration_date>=today)
I want to get only actual prescriptions in my actual method, and when I specify
#hybrid_property
def expiration_date(self):
return self.date + timedelta(days=7)
everything works like a charm.
But every prescription has a different duration, and when I specify
#hybrid_property
def expiration_date(self):
return self.date + timedelta(days=self.duration)
I've got an error
TypeError: unsupported type for timedelta days component: InstrumentedAttribute
I tried to make a little hack like this
#property
def days(self):
return int(self.duration)
but no luck.
Can anyone tell some workaround, or creating some lazy object for duration field or maybe another way get actual prescriptions, filtering by calculated expiration_date?
You might be trying to calculate a DATEDIFF:
Calculate DATEDIFF in POSTGRES using SQLAlchemy
Here, is_expired will generate a SQL query part which calculates difference in days between the start date and utcnow(), and compares the result with self.duration
This works in PostgreSQL, but I have not tested on other RDBMS.
from datetime import datetime
import sqlalchemy as sa
class Prescription:
ID = db.column(db.Integer, primary_key=True)
date = db.Column(db.DateTime)
duration = db.Column(db.SmallInteger)
#hybrid_property
def is_expired(self):
days_since_published = sa.func.trunc((
sa.extract('epoch', datetime.utcnow()) -
sa.extract('epoch', self.date)
) / 3600 / 24)
return days_since_published >= self.duration
#classmethod
def active(cls):
return cls.query.filter(is_expired=False)
In your #classmethod annotated actual() method, you are trying to access a non-static property(expiration_date) which is raising the error.
As per my understanding of what your code is doing, I have changed the code as follow:
from datetime import datetime,timedelta
from sqlalchemy.ext.hybrid import hybrid_property
from flask_sqlalchemy import SQLAlchemy
from flask import Flask
app = Flask(__name__)
db = SQLAlchemy(app)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SQLALCHEMY_DATABASE_URI'] ='sqlite:///'
class Prescription(db.Model):
""" docstring """
def mydefault(context):
return context.get_current_parameters()['date'] + timedelta(days=context.get_current_parameters()['duration'])
ID = db.Column(db.Integer,primary_key= True)
date = db.Column(db.Date)
duration = db.Column(db.SmallInteger)
expiration_date = db.Column(db.Date,default = mydefault)
#classmethod
def actual(cls ):
""" docstring """
today = datetime.today().date()
return cls.query.filter(Prescription.expiration_date>=today).all()
def __repr__(self):
return "Id:{} , date:{}, duration:{}, expiration_date:{}".format(self.ID,self.date,self.duration,self.expiration_date)
db.create_all()
q=Prescription(ID=1,date=datetime(2019,5,26).date(),duration = 1) #Expired
r=Prescription(ID=2,date=datetime(2019,5,20).date(),duration = 3) #Expired
s=Prescription(ID=3,date=datetime(2019,5,27).date(),duration = 5) #Not Expired
t = Prescription(ID=4,date=datetime.now().date(),duration = 1) #Not Expired
db.session.add(q)
db.session.add(r)
db.session.add(s)
db.session.add(t)
db.session.commit()
list_obj = Prescription.query.all()
print("All Objects in DB:-")
for l in list_obj:
print(l)
print()
print("Valid Prescription:")
print(Prescription.actual())
Output:
One thing I can suggest to you is since the model does not need the time of expiration.
So you could change
date = db.Column(db.DateTime)
to
date = db.Column(db.Date)
and it will ease your task :)

Displaying sqlite3 data into Treeview

I am writing some code that shows a list of food with their information.
My code:
-connects to data base and gets items successfully
-loops correctly
Problem:
-If the name of my product is one word (ex:eggs) my code displays everything in the correct column
-If the name of my product is two or more words (ex:frosted flakes) my code displays 'frosted' on first column then 'flakes' in next columns which is incorrect
from tkinter import ttk
import tkinter as tk
import sqlite3
try:
from Tkinter import *
except ImportError:
from tkinter import *
def View():
db = sqlite3.connect("food_data.db")
cursor = db.cursor()
cursor.execute("SELECT name, quantity, expdate FROM food ORDER BY expdate ASC")
for row in cursor:
disp=('{0} {1} {2}'.format(row[0], row[1], row[2]))
tree.insert("",tk.END, values=disp)
db.close()
root = tk.Tk()
root.geometry("800x480")
tree = ttk.Treeview(column=("column1","column2","column3"),show='headings')
tree.heading("#1", text="Name")
tree.heading("#2", text="Quantity")
tree.heading("#3", text="Expiration Date")
tree.pack()
b2 = tk.Button(text="view data", command=View)
b2.pack()
root.mainloop()
It is suppose to successfully display items with multiple words in their name onto one column and not carry to the next one.
def View():
db = sqlite3.connect("food_data.db")
cursor = db.cursor()
cursor.execute("SELECT name, quantity, expdate FROM food ORDER BY expdate ASC")
for row in cursor:
# disp=('{0} {1} {2}'.format(row[0], row[1], row[2]))
tree.insert("",tk.END, values=(row[0], row[1], row[2]))
db.close()
Do it this way rather you have to insert the content in the treeview as tuple or list after iterating over it.
tree.insert("",tk.END, values=(row[0], row[1], row[2]))

Bringing dialog window in from of Python window

My application has two separate dialog windows prior to opening the main application window. I am unable to figure out how to get the second dialog window (the calendar) to open in from of the black python screen (I apologize for my ignorance I don't know the name).
The messagebox contained in "rundate" opens first. If "no" is selected then the app_window opens. It is the app_window that gets hidden
conn = pyodbc.connect('Driver={Microsoft Access Driver (*.mdb, *.accdb)};Dbq='+db)
cur = conn.cursor()
app_window = tk.Tk()
app_window.geometry("1x1+0+0")
app_window.overrideredirect(True)
app_window.transient()
def rundate():
result = tkinter.messagebox.askyesno(title="Rundate", message="back 7 days?")
if result == True:
end = date.today()
start = date.today() - timedelta(7)
daterange = [pd.date_range(start, end)]
for single_date in daterange:
x = single_date.strftime("%m/%d/%Y")
rundate = x
print(rundate)
return rundate
else:
app_window.wm_title("Pick1")
app_window.geometry("250x150+100+100")
app_window.overrideredirect(False)
#app_window.mainloop()
cm = pick1.CalendarFrame(app_window)
cm.grid()
app_window.wait_variable(cm.wait_for_result)
return cm.rundate
rundate = rundate()
print(rundate)
Then a whole bunch of code for queries and whatnot then
After the messagebox is returned "yes" OR the dates are selected from the calendar then the interface gets initiated
# Initiate interface
root = Tk()
master = Frame(root, name='master')
master.pack(fill=BOTH)
root.geometry("800x800+300+100")
root.title('WeeklyReport')
menu_bar = Menu(root)
def exit():
root.destroy()
root.wait_window
I finally figured it out by adding "lift" Thank you!
app_window = tk.Tk()
app_window.geometry("1x1+0+0")
app_window.overrideredirect(True)
app_window.transient()
app_window.lift()

Resources