I have a table that's being populated from a database. you can edit the table then update the database with the new data. I have this:
def populate(self):
tablerow = 0
rowcount = 0
self.ui.widget_unass_fights.clearContents()
self.ui.widget_unass_fights.setRowCount(0)
for row in x:
rowcount += 1
self.ui.widget_unass_fights.setRowCount(rowcount)
self.ui.widget_unass_fights.setItem(tablerow, 0, QtWidgets.QTableWidgetItem(str(row[0])))
self.ui.widget_unass_fights.setItem(tablerow, 2, QtWidgets.QTableWidgetItem(str(row[2])))
self.ui.widget_unass_fights.setItem(tablerow, 3, QtWidgets.QTableWidgetItem(str(row[3])))
self.ui.widget_unass_fights.setItem(tablerow, 4, QtWidgets.QTableWidgetItem(str(row[4])))
self.ui.widget_unass_fights.setItem(tablerow, 5, QtWidgets.QTableWidgetItem(str(row[5])))
self.ui.widget_unass_fights.setItem(tablerow, 8, QtWidgets.QTableWidgetItem(str(row[8])))
combobox1 = QComboBox()
combobox1.clear()
for j in self.plane_list_combo:
self.ui.widget_unass_fights.setItem(tablerow, 1, QtWidgets.QTableWidgetItem(""))
combobox1.addItem(j)
self.ui.widget_unass_fights.setCellWidget(tablerow, 1, combobox1)
self.ui.widget_unass_fights.cellWidget(tablerow, 1).setCurrentText(row[1])
combobox2 = QComboBox()
combobox2.clear()
combobox2.addItem("")
combobox3 = QComboBox()
combobox3.clear()
combobox3.addItem("")
for j in self.pilot_list_combo:
self.ui.widget_unass_fights.setItem(tablerow, 6, QtWidgets.QTableWidgetItem(""))
self.ui.widget_unass_fights.setItem(tablerow, 7, QtWidgets.QTableWidgetItem(""))
combobox2.addItem(j)
combobox3.addItem(j)
self.ui.widget_unass_fights.setCellWidget(tablerow, 6, combobox2)
self.ui.widget_unass_fights.setCellWidget(tablerow, 7, combobox3)
self.ui.widget_unass_fights.cellWidget(tablerow, 6).setCurrentText(row[6])
self.ui.widget_unass_fights.cellWidget(tablerow, 7).setCurrentText(row[7])
tablerow += 1
print(self.ui.widget_unass_fights.cellWidget(0, 1).currentText())
def update(self)
rowcount = self.ui.widget_unass_fights.rowCount()
print(self.ui.widget_unass_fights.cellWidget(0, 1).currentText())
for i in range(rowcount):
flight_id = self.ui.widget_unass_fights.item(i, 0).text()
flight_reg = self.ui.widget_unass_fights.cellWidget(i, 1).currentText()
desc = self.ui.widget_unass_fights.item(i, 2).text()
date = self.ui.widget_unass_fights.item(i, 3).text()
etd = self.ui.widget_unass_fights.item(i, 4).text()
flight_time = self.ui.widget_unass_fights.item(i, 5).text()
pilot = self.ui.widget_unass_fights.cellWidget(i, 6).currentText()
co_pilot = self.ui.widget_unass_fights.cellWidget(i, 7).currentText()
max_pax = self.ui.widget_unass_fights.item(i, 8).text()
columns 1, 6, and 7 are combo boxes
When I tried running the update function I got the error:
self.ui.widget_unass_fights.cellWidget(i, 1).currentText()
AttributeError: 'QWidget' object has no attribute 'currentText'
so I put in the 2 print commands to try to find out why. the print command in the populate function works, but the print command in the update function doesn't, they are copy and paste of each other, they should both work right? what am I doing wrong?
EDIT - after fiddling around I found that It will only let me call the last row of the table, none of the others.
Related
I want to show all data from my SQL Database in a TableWidget
if i enter print(row) and change the cursor in the for loop to mycursor.fetchall() it shows the values in the consoles. but tablewidget stays empty
Error in console: TypeError: 'NoneType' object is not iterable
Is there a way to use a Model based QTableView like in an offline Db
self.tbl_mitarbeiter.setColumnWidth(0,100)
self.tbl_mitarbeiter.setColumnWidth(1,100)
self.tbl_mitarbeiter.setColumnWidth(2,100)
self.tbl_mitarbeiter.setColumnWidth(3,100)
self.tbl_mitarbeiter.setColumnWidth(4,100)
self.tbl_mitarbeiter.setColumnWidth(5,100)
self.tbl_mitarbeiter.setColumnWidth(6,100)
tbl_mitarbeiter_header = ["Personalnummer","Name", "Abteilungsid", "Kontakt", "Eintrittsdatum", "Austrittsdarum", "Notizen"]
self.tbl_mitarbeiter.setHorizontalHeaderLabels(tbl_mitarbeiter_header)
self.load_data()
def load_data(self):
sql = 'SELECT * FROM mitarbeiter LIMIT 50'
# mycursor.execute(sql)
self.tbl_mitarbeiter.setRowCount(50)
tablerow = 0
for row in mycursor.execute(sql):
print(row)
self.tbl_mitarbeiter.setItem(tablerow, 0, QtWidgets.QTableWidgetItem(row[0]))
self.tbl_mitarbeiter.setItem(tablerow, 1, QtWidgets.QTableWidgetItem(row[0]))
self.tbl_mitarbeiter.setItem(tablerow, 2, QtWidgets.QTableWidgetItem(row[0]))
self.tbl_mitarbeiter.setItem(tablerow, 3, QtWidgets.QTableWidgetItem(row[0]))
self.tbl_mitarbeiter.setItem(tablerow, 4, QtWidgets.QTableWidgetItem(row[0]))
self.tbl_mitarbeiter.setItem(tablerow, 5, QtWidgets.QTableWidgetItem(row[0]))
self.tbl_mitarbeiter.setItem(tablerow, 6, QtWidgets.QTableWidgetItem(row[0]))
tablerow+=1
Model Based but also returns empty values
#TableModel
self.mod_mitarbeiter = QtSql.QSqlRelationalTableModel()
self.mod_mitarbeiter.setTable("mitarbeiter")
self.mod_mitarbeiter.setRelation(2,QtSql.QSqlRelation("abteilungen","Abteilungsid", "Abteilung"))
self.tbl_mitarbeiter.setItemDelegate(QtSql.QSqlRelationalDelegate())
self.db_refresh()
def db_refresh(self):
model = self.mod_mitarbeiter
abfrage = """UPDATE mitarbeiter"""
query.exec(abfrage)
model.select()
self.tbl_mitarbeiter.setModel(model)
I have files(xlsx) which contain data like agent name and its data, then agent name and its data.
Example:
How can I add a column which will contain the agent names in all the columns which have its data? I want to create a dataframe and calculate kpis.
Expected output:
We can add the name to the columns in the below format to the respective cells.
import openpyxl
from copy import copy
path = "C:/Users/Python/TestData.xlsx"
wb = openpyxl.load_workbook(path)
sheet_obj = wb.active
Name = sheet_obj.cell(row = 1, column = 1)
#NameFont = sheet_obj.cell(row = 2, column = 1)
sheet_obj.cell(row = 2, column = 8).value = "Name"
sheet_obj.cell(row = 2, column = 8)._style = copy(sheet_obj.cell(row = 2, column = 1)._style)
sheet_obj['H3'] = Name.value
sheet_obj.cell(row = 3, column = 8)._style = copy(sheet_obj.cell(row = 3, column = 1)._style)
sheet_obj['H4'] = Name.value
sheet_obj.cell(row = 4, column = 8)._style = copy(sheet_obj.cell(row = 4, column = 1)._style)
sheet_obj['H5'] = Name.value
sheet_obj.cell(row = 5, column = 8)._style = copy(sheet_obj.cell(row = 5, column = 1)._style)
sheet_obj['H6'] = Name.value
sheet_obj.cell(row = 6, column = 8)._style = copy(sheet_obj.cell(row = 6, column = 1)._style)
sheet_obj['H7'] = Name.value
sheet_obj.cell(row = 7, column = 8)._style = copy(sheet_obj.cell(row = 7, column = 1)._style)
sheet_obj['H8'] = Name.value
sheet_obj.cell(row = 8, column = 8)._style = copy(sheet_obj.cell(row = 8, column = 1)._style)
wb.save(path)
Below is the output:
Keep this in a loop if we want to apply this for entire excel sheet, this can be done based on the name.
I need your help in order to solve this problem.
I am trying to enter a line in a database where the program has to find a material X in the database and then get the quantity value. After that, the program creates a new line where it adds the stock entered by the user + the current stock in a new line. The program works as long as the last line in the database is the same material X, but in case the last line is for material Y, then it raises this error.
Here I attach the code:
from tkinter import *
from tkinter import ttk
from datetime import datetime
import sqlite3
class Main:
db_name = 'materiales.db'
def __init__(self,window):
self.wind = window
self.wind.title('Stock App')
#create frame
frame = LabelFrame(self.wind, text = 'Add stock')
frame.grid(row = 0, column = 0, columnspan = 3, pady = 20)
# Name Input
Label(frame, text = 'Name: ').grid(row = 1, column = 0)
self.name = Entry(frame)
self.name.focus()
self.name.grid(row = 1, column = 1)
# Quantity Input
Label(frame, text = 'Quantity: ').grid(row = 2, column = 0)
self.quantity = Entry(frame)
self.quantity.grid(row = 2, column = 1)
# Button Add Stock
ttk.Button(frame, text = 'Add Stock', command = self.add_stock).grid(row = 3, columnspan = 2, sticky = W + E)
#Log Message
self.message = Label(text = '', fg = 'red')
self.message.grid(row = 3, column = 0, columnspan = 2, sticky = W + E)
#Button Search Stocks
ttk.Button(text = 'Search Stocks', command = self.search_stocks).grid(row = 5, column = 0, columnspan = 3, pady = 20, sticky = W + E)
def run_query(self, query, parameters = ()):
with sqlite3.connect(self.db_name) as conn:
cursor = conn.cursor()
result = cursor.execute(query, parameters)
conn.commit()
return result
def validation(self):
return len(self.name.get()) != 0 and len(self.quantity.get()) !=0
def add_stock(self):
time = datetime.now().strftime("%B %d, %Y")
hour = datetime.now().strftime("%I:%M%p")
query = 'SELECT totalstock FROM stocks WHERE name = ? AND MovementID = ( SELECT max( MovementID ) FROM stocks)'
parameters = (self.name.get(),)
lastrecord = self.run_query(query, parameters)
total = lastrecord.fetchone()[0]
total += int(self.quantity.get())
if self.validation():
query = 'INSERT INTO stocks VALUES(NULL, ?, ?, ?, ?, ?)'
parameters = (self.name.get(), self.quantity.get(), total, time, hour)
self.run_query(query, parameters)
self.message['text'] = 'Stock for {} added succesfully'.format(self.name.get())
self.name.delete(0, END)
self.quantity.delete(0, END)
else:
self.message['text'] = 'Name and Quantity required'
self.get_product()
def search_stocks(self):
self.edit_wind = Toplevel()
self.edit_wind.title = 'Search Stocks'
#Name Product
Label(self.edit_wind, text = 'Name: ').grid(row = 0, column = 1)
name = Entry(self.edit_wind)
name.grid(row = 0, column = 2)
Button(self.edit_wind, text = 'Search', command = lambda: self.edit_records(new_name.get(), name, new_price.get(), old_price)).grid(row = 4, column = 2, sticky = W)
def edit_records(self, name):
query = 'SELECT totalstock FROM stocks WHERE name = ? AND MovementID = ( SELECT max( MovementID ) FROM stocks)'
parameters = (name)
self.run_query(query, parameters)
self.edit_wind.destroy()
self.message['text'] = 'Total stock is {}'.format(totalstock)
self.get_product()
if __name__ == '__main__':
window = Tk()
application = Main(window)
window.mainloop()
Here I attach the complete error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Xavi\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1884, in __call__
return self.func(*args)
File "C:\Users\Xavi\Desktop\Program\stock\stocklist.py", line 58, in add_stock
total = lastrecord.fetchone()[0]
TypeError: 'NoneType' object is not subscriptable
>>>
Happy new year 2021 and thanks for your help
This line causes the error if no records match the selection criteria in the query:
total = lastrecord.fetchone()[0]
If no records match then lastrecord.fetchone() evaluates to None, resulting in the TypeError.
You could handle this by using a try/except block:
try:
total = lastrecord.fetchone()[0]
except TypeError:
total = 0
or an if/else:
row = lastrecord.fetchone()
if row is None:
total = 0
else:
total = row[0]
or more succintly
row = lastrecord.fetchone()
total = row[0] if row is not None else 0
I have a GUI where results from a dataframe are populated into a treeview within python based on filters previously input. The user can then click on treeview and update the values to the desired number. The number of rows within the view can vary from 1 - 20+. Once the user has updated the view as desired, I have a button below "Check Allocation".
It is at this point I want to "export" the treeview into a dataframe for me to run against another table. I cant seem to simply export this as a dataframe. Is there any work around this? I only need the first and last columns (of the 8) to check the newly updated file.
Here is what I have so far.
def PrintAllocation(self):
treeview = tkk.Treeview(root)
treeview.grid(column = 1, row = 8, columnspan = 4, padx = 1, pady = 1)
cols = list(matches.columns)
treeview["columns"] = cols
for i in cols:
treeview.column(i, width = 100, anchor = "w")
treeview.heading(i,text=i,anchor='w',)
for index, row in matches.iterrows():
treeview.insert("",0,text=index,values=list(row))
def set_cell_value(event): # Double click to enter the edit state
for item in treeview.selection():
#item = I001
item_text = treeview.item(item, "values")
#print(item_text[0:2]) # Output the value of the selected row
column= treeview.identify_column(event.x)# column
print(column)
row = treeview.identify_row(event.y) #row
cn = int(str(column).replace('#',''))
rn = int(str(row).replace('I',''))
if column == '#8':
entryedit = Text(root,width=50,height = 1)
entryedit.grid(column = 2, row = 9, padx = 1, pady = 1)
else:
entryedit = Text(root,width=10,height = 1)
entryedit.grid(column = 2, row = 9, padx = 1, pady = 1)
def saveedit():
treeview.set(item, column=column, value=entryedit.get(0.0, "end"))
entryedit.destroy()
okb.destroy()
okb = ttk.Button(root, text='OK', width=4, command=saveedit)
okb.grid(column = 3, row = 9,padx = 1, pady=1)
def CheckAllocation():
children = treeview.getchildren()
for child in children:
print(treeview.set(child))
treeview.bind('<Double-1>', set_cell_value) # Double-click the left button to enter the edit
button_check = Button(root,text="Check Allocation", command = CheckAllocation)
button_check.grid(column = 2, row = 10, padx = 10, pady=10)
'''
I don't really understand your code but when I need to get a treeview to pandas I do it as follows:
First I create an empty list for each column in the treeview.
column_a_list = []
column_b_list = []
column_c_list = []
column_d_list = []
Then running through the lines of the treeview in a "for" function, I append to each column list the value of the column in each line.
for child in self.treeview.get_children():
column_a_list.append(self.treeview.item(child)["values"][0])
column_b_list.append(self.treeview.item(child)["values"][1])
column_c_list.append(self.treeview.item(child)["values"][2])
column_d_list.append(self.treeview.item(child)["values"][3])
Then I create a dictionary from all the lists, using the header as the key and lists are the values as a list.
full_treeview_data_dict = {'HEADER A': column_a_list, 'HEADER B': column_b_list, 'HEADER C': column_c_list, 'HEADER D': column_d_list,}
Then I create a dataframe from the dictionary.
treeview_df = pd.DataFrame.from_dict(full_treeview_data_dict)
Here is the full sample code in one chunk:
column_a_list = []
column_b_list = []
column_c_list = []
column_d_list = []
for child in self.treeview.get_children():
column_a_list.append(self.treeview.item(child)["values"][0])
column_b_list.append(self.treeview.item(child)["values"][1])
column_c_list.append(self.treeview.item(child)["values"][2])
column_d_list.append(self.treeview.item(child)["values"][3])
full_treeview_data_dict = {'HEADER A': column_a_list, 'HEADER B': column_b_list, 'HEADER C': column_c_list, 'HEADER D': column_d_list,}
treeview_df = pd.DataFrame.from_dict(full_treeview_data_dict)
I hope it helps.
You can also do this:
row_list = []
columns = ('name', 'school', 'c3', 'c4')
for row in treeview.get_children():
row_list.append(treeview.item(row)["values"])
treeview_df = pd.DataFrame(row_list, columns = columns)
The current answer is good, I just wanted to add my two cents here:
self.treeview_columns = [] # list of names here
# initialize empty df
# if too big you can preallocate but probably not needed
treeview_df = pd.DataFrame(None, columns=self.treeview_columns)
for row in self.treeview.get_children():
# each row will come as a list under name "values"
values = pd.DataFrame([self.treeview.item(row)["values"]],
columns=self.treeview_columns)
# print(values)
treeview_df = treeview_df.append(values)
This way you grow your df row by row using append and you reduce the number of subsets that you need to do.
Problem Statement:
Disable specific columns and enable specific row on bases of current row index.
I am working on Qtablewidget i tried following code this working fine for disable.
i wanted to enable tablewidget row contents on bases of row index .
when i clicked pushbutton that row should be enable.I am new to the stackoverflow please guide me.I am tring to enable tablewidget cell,pushbutton,combobox i am not getting please guide me how to enble particular row on bases of index.
Code :
self.tableWidget = QtGui.QTableWidget(self.centralwidget)
self.tableWidget.setColumnCount(4)
myresult = [(u'sandeep', u'checkbox'), (u'shivaraj', u'checkbox')]
for row, result in enumerate(myresult):
self.tableWidget.insertRow(self.tableWidget.rowCount())
for column, value in enumerate(result):
item = QtGui.QTableWidgetItem(str(value))
if column == 1:
if (value == "textbox"):
self.cb = QtGui.QComboBox()
lis = ("---select---", "description", "multiple_input")
self.cb.addItems(lis)
self.cb.setCurrentIndex(1)
self.tableWidget.setCellWidget(row, column, self.cb)
self.cb.setEnabled(False)#this is for combobox disable
elif (value == "checkbox"):
self.cb = QtGui.QComboBox()
lis = ("---select---", "description", "multiple_input")
self.cb.addItems(lis)
self.cb.setCurrentIndex(2)
self.tableWidget.setCellWidget(row, column, self.cb)
self.cb.setEnabled(False)#this is for combobox disable
self.tableWidget.setItem(row, column, item)
item.setFlags(QtCore.Qt.ItemIsEnabled)#this is for text non editable
self.btn_sell = QtGui.QPushButton('Edit')
self.btn_sell1 = QtGui.QPushButton('Delete')
self.btn_sell1.setEnabled(False)#this for button disble
self.tableWidget.setCellWidget(row, 2, self.btn_sell)
self.tableWidget.setCellWidget(row, 3, self.btn_sell1)
self.btn_sell.clicked.connect(self.edit)
def edit(self):
index = self.tableWidget.currentRow()
print index
self.table = QtGui.QTableWidget()
self.table.setGeometry(QtCore.QRect(220, 100, 881, 100))
self.table.setColumnCount(4)
self.table.setRowCount(1)
self.table.setColumnWidth(0, 120)
self.table.setColumnWidth(1, 500)
self.table.setColumnWidth(2, 120)
self.table.setColumnWidth(3, 120)
indexes = self.tableWidget.currentRow()
widget = self.tableWidget.cellWidget(indexes, 2)
# print widget
if isinstance(widget, QtGui.QComboBox):
h = str(widget.currentText())
if (h == "multiple_input"):
j = "checkbox"
elif (h == "description"):
j = "textbox"
if (j == "textbox"):
self.cb = QtGui.QComboBox()
lis = ("---select---", "description", "multiple_input")
self.cb.addItems(lis)
self.cb.setCurrentIndex(1)
self.table.setCellWidget(0, 2, self.cb)
[enter image description here][1]elif (j == "checkbox"):
self.cb = QtGui.QComboBox()
lis = ("---select---", "description", "multiple_input")
self.cb.addItems(lis)
self.cb.setCurrentIndex(2)
self.table.setCellWidget(0, 2, self.cb)
n = [str(self.tableWidget.item(indexes, 0).text())]
for x in n:
f = ''.join(map(str, x))
self.table.setItem(0, 0, QtGui.QTableWidgetItem(f))
n1 = [str(self.tableWidget.item(indexes, 1).text())]
# print n1
for i in n1:
s = ''.join(i)
self.table.setItem(0, 1, QtGui.QTableWidgetItem(s))
self.li = QtGui.QPushButton("Update")
self.table.setCellWidget(0, 3, self.li)
self.li.clicked.connect(self.edit_data)
self.table.show()
click on below link has image.
Try the above code:
Select row and click on edit button it will take the current index row values into the separate table `where we can edit and update the values.This is the one way i have tried to update the value it works fine.