0

Thanks all for your suggestions. Adding self. before calling my functions fixed that issue. I'm now running into a different issue where the stored procedure I am using isn't getting properly read into the pandas dataframe. I don't get any errors, the tkinter window pops up like it should, but when the PDF gets generated, there is no data in the rows, just the column names and other formatting I've written in.

I added print(df) to the code to check if it was an issue with the data getting read from the dataframe to the PDF, but print(df) just returns Empty DataFrame.

from tkinter import *
import pyodbc
import pandas as pd
from reportlab.lib import colors
from reportlab.platypus import *
from reportlab.lib import styles
from reportlab.lib.units import inch

# Create connection 
server = 'XXXXXXX' 
database = 'XXXXXXX' 
username = 'XXXXXXXX' 
password = 'XXXXXXXXX' 

try:
    cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+password+'')
except:
    raise NameError('unable to connect')

#save stored procedure to a global variable
storedProc = 'EXEC [presentation].[pdf_project] '

elements = []

class NewPDF:
    def __init__(self):
        window = tk.Tk()
        window.title("Form Example")
        window = tk.Frame(window)
        window.grid(column=0,row=0, sticky=(tk.N,tk.W,tk.E,tk.S))
        window.columnconfigure(0, weight = 1)
        window.rowconfigure(0, weight = 1)
        window.pack(pady = 100, padx = 100)

        self.tkvar = tk.StringVar(window)
    
        choices = {'2021','2020','2019','2018'}
        self.tkvar.set('2021')
        
        popupMenu = tk.OptionMenu(window, self.tkvar, *choices)
        tk.Label(window, text = "Pick Year").grid(row = 1, column = 1)
        popupMenu.grid(row = 1, column = 2)
        
        tk.Label(window, text = "Customer").grid(row = 2, column = 1)

        self.e1 = tk.Entry(window)
        self.e1.grid(row = 2, column = 2)

        self.param_year = self.tkvar.get()
        self.param_cust = str(self.e1.get())

        B = tk.Button(window, text = "Make PDF", command=self.make_df_and_pdf()).grid(row = 3, column = 1)

        self.tkvar.trace('w', self.change_dropdown())

        window.mainloop()


    def change_dropdown(self, *args):
        print(args)

    def make_df_and_pdf(self):
        #param_year = self.tkvar.get()
        #param_cust = str(self.e1.get())
        params = "'" + self.param_cust + "'," + self.param_year + ""
        querystring = storedProc + params

        df = pd.read_sql_query(querystring, cnxn)
        lista = [df.columns[:,].values.astype(str).tolist()] + df.values.tolist()
        #cust_list = (df['CUSTOMER'].unique())
        #cust_list = cust_list.tolist()

        #print(df)

        styles = getSampleStyleSheet()

        ts = [('ALIGN', (1,1), (-1,1), 'LEFT'),
        ('BOX', (0,0), (3,0), 2, colors.red),
        ('FONT', (0,0), (-1,0), 'Times-Bold'),
        ('GRID', (0,1), (-1,-1), 0.5, colors.grey)] 

        n_table = Table(lista, colWidths = (1.5*inch, 1.5*inch, 1.5*inch, 1.5*inch, 1.5*inch), repeatRows = 1)
        table_style = TableStyle(ts)
        n_table.setStyle(table_style)

        PATH_OUT = "Desktop"
        doc = SimpleDocTemplate(PATH_OUT + 'UserInputPDF_Test.pdf')
        elements.append(Paragraph("CustomerTAT", styles['Title']))
        elements.append(n_table)

        doc.build(elements)




NewPDF()

EDIT: The stored procedure operates as it should within SQL. Here is the code for my stored procedure:

USE [XXXXX]
GO
/****** Object:  StoredProcedure [presentation].[pdf_project]    Script Date: 6/22/2021 4:31:20 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:      XXXXXX
-- Create date: 
-- Description: 
-- =============================================
ALTER PROCEDURE [presentation].[pdf_project] 
    -- Add the parameters for the stored procedure here
    @CustomerName varchar(50) = '', 
    @Year int = 0
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for procedure here
    SELECT CUSTOMER, [TAT Whole Days], [SHIP DATE], YEAR([SHIP DATE]) AS YEAR,
    CASE
        WHEN MONTH([SHIP DATE]) IN (1,2,3) THEN 'Q1'
        WHEN MONTH([SHIP DATE]) IN (4,5,6) THEN 'Q2'
        WHEN MONTH([SHIP DATE]) IN (7,8,9) THEN 'Q3'
        ELSE 'Q4'
    END AS QUARTER
    FROM presentation.CustomerTAT
    WHERE (YEAR([SHIP DATE]) = @Year or YEAR([SHIP DATE]) = @Year) 
    AND CUSTOMER = @CustomerName
END
gizzzmo
  • 1
  • 1
  • 3
    Please show the full error. – Bryan Oakley Jun 21 '21 at 22:20
  • 1
    You just leaked your SQL server credentials. Make sure to change them, like *right now*, or else someone can gain access to your SQL server!!! – Ayush Garg Jun 21 '21 at 22:25
  • There are a lot of additional modules and code that make it harder to help with the question. It would be best if removed to isolate the core problem `tkinter`... plus as said above, you have also made public your server credentails. – D.L Jun 21 '21 at 22:25
  • I think your code has [this](https://stackoverflow.com/questions/5767228/why-is-the-command-bound-to-a-button-or-event-executed-when-declared) mistake – TheLizzard Jun 21 '21 at 22:32
  • 1
    You are using `reportlab.platypus.Frame` instead of `tkinter.Frame`. – acw1668 Jun 21 '21 at 23:08
  • Thanks, @acw1668! That solved the issue with `Frame`. And thanks for pointing out the SQL server credentials. I just put in some dummy info for the credentials, so it wasn't my actual server credentials. I'll make sure to just put in XXX's if I post something similar in the future. I am now running into a similar error when passing the `command=NewPDF.make_df_and_pdf()` line. The error reads, **TypeError: make_df_and_pdf() missing 1 required positional argument: 'self'.** I think it's because I need to instantiate an object, but I don't have anything I want to put for the self parameter. – gizzzmo Jun 22 '21 at 14:29
  • You should use `command=self.make_df_and_pdf` instead. Also `self.tkvar.trace('w', self.change_dropdown)`. – acw1668 Jun 22 '21 at 14:41
  • 1
    Please show your stored proc. Does it return a resultset at end? Are you using [SET NOCOUNT ON](https://stackoverflow.com/a/14979756/1422451)? – Parfait Jun 22 '21 at 21:13
  • `command=self.make_df_and_pdf()` should be `command=self.make_df_and_pdf`, and `self.tkvar.trace('w', self.change_dropdown())` should be `self.tkvar.trace('w', self.change_dropdown)` instead (already mentioned in my past comment). Also `self.param_cust` and `self.param_year` are empty strings inside `make_df_and_pdf()`. – acw1668 Jun 24 '21 at 15:35

0 Answers0