Inserting data from sqlite database to QTableWidget using PyQt in Python - python

I want to insert my data which is stored in a sqlite table, to a QTableWidget. I use two for loop to find the data and index. after each iteration I print the data in console and it is OK but when it displays the table widget there is only the first row and the last row filled with the data.
Any idea to solve this problem?
It's obvious that tblTable is a QTableWidget!
Here is this part of the code:
cursor.execute('''SELECT * FROM MyTable''')
for index , form in enumerate(cursor.fetchall()):
i = 0
for item in form:
print(str(item))
self.tblTable.setItem(index, i, QtGui.QTableWidgetItem(str(item)))
i = i + 1
self.tblTable.insertRow(1)

You keep inserting your new row at position 1. What happens is that the previously entered data is then moved up one row, at which point you overwrite that data in the next loop.
So, first iteration everything is inserted in row 0, you add a row at index 1. Then you update row 1 with data, and insert another row at position 1, making the previously modified row move to row 2. Next loop, you overwrite the data on row 2, insert another empty row at position 1, moving the row with data to position 3 and you overwrite it again, etc., etc.
Set the row-count to 0 at the start, and insert rows as you need them before you insert your column data:
cursor.execute('''SELECT * FROM MyTable''')
self.tblTable.setRowCount(0)
for row, form in enumerate(cursor):
self.tblTable.insertRow(row)
for column, item in enumerate(form):
print(str(item))
self.tblTable.setItem(row, column, QtGui.QTableWidgetItem(str(item)))
I am not that familiar with the QtTableWidget, it could be that continually adding rows in not going to perform as well as setting the number of rows up front.
If sqlite's cursor.rowcount attribute is properly updated on your query (it not always is), you'd be better off calling .setRowCount with that value:
cursor.execute('''SELECT * FROM MyTable''')
self.tblTable.setRowCount(cursor.rowcount)
for row, form in enumerate(cursor):
for column, item in enumerate(form):
self.tblTable.setItem(row, column, QtGui.QTableWidgetItem(str(item)))
If the .rowcount value is not available (set to 1 or similar), perhaps first asking the database for the number of rows can help:
rowcount = cursor.execute('''SELECT COUNT(*) FROM MyTable''').fetchone()[0]
self.tblTable.setRowCount(rowcount)
cursor.execute('''SELECT * FROM MyTable''')
for row, form in enumerate(cursor):
for column, item in enumerate(form):
self.tblTable.setItem(row, column, QtGui.QTableWidgetItem(str(item)))
In all examples above, I also renamed you variables to something a little closer to their use, and used enumerate on the item loop as well. Last, but not least, the cursor can act as an iterator, meaning you can loop over rows directly without calling .fetchall() and rows will be fetched as needed.

Related

SQLite AUTO_INCREMENT id field is upside down on the program

here a pic to a better understand
[1]: https://i.stack.imgur.com/S6tpl.png
def consult(self):
book = self.cuadro_blanco_cliente.get_children()
for elementos in book:
self.cuadro_blanco_cliente.delete(elementos)
query = "SELECT Nro, codigo, nombre, nfc, telefono, celular,direccion FROM clientes"#
rows = self.run_query(query)#query
for row in rows:
self.cuadro_blanco_cliente.insert('',0, text=row[1],values=row)
The problem isn't on the id field, is in the way you are using to add the rows on the display. You are traversing the array from id 1 to n, but adding the rows always to the beginning, making it look like the ids go from n to 1.
Try adding this at the end of your query clause:
"... ORDER BY id DESC"
This way, you will insert first, the last element, and then insert the other rows before the last, and so on, securing the fetched rows are ordered by id.
I added some lines to the code, and fixed the problem, begin from 1 now
for row in rows:
id = row[0]
self.cuadro_blanco_cliente.insert("",END, id, text=id, values=row)

I'm trying to print QTableWidget as pdf in PyQt5, but i'm getting this glitch

While trying to print QTableWidget I'm getting this glitch where last row is inserted into last column of the 2nd last row, I don't know why is this happening.
I tried a lot of solutions but nothing worked.
Here is the code:
document = QTextDocument()
cursor = QTextCursor(document)
table = cursor.insertTable(
self.students_reports_table.rowCount(), self.students_reports_table.columnCount())
for col in range(table.columns()):
cursor.insertText(self.students_reports_table.horizontalHeaderItem(col).text())
cursor.movePosition(QTextCursor.NextCell)
for row in range(table.rows()):
for col in range(table.columns()):
cursor.insertText(self.students_reports_table.item(row, col).text())
cursor.movePosition(QTextCursor.NextCell)
document.print_(printer)
And here is the output. As you can see clearly in this image last row is in last column of 2nd row:
In your code you create the table with a same amount of rows that in your table widget. Then you immediately fill one of those rows with the header labels. So when you go to fill in the table with data from the widget, there is one less row than needed to fit all the data.
Try setting up the table with students_reports_table.rowCount() + 1.
table = cursor.insertTable(
self.students_reports_table.rowCount() + 1, # use rowCount + 1
self.students_reports_table.columnCount()
)

Using Python, how would I return the row # along with the description in my SQLite DB?

I have a simple function to get all items from my sqlite database:
def get_items(self):
stmt = "SELECT description FROM items"
return [x[0] for x in self.conn.execute(stmt)]
It works well but I cannot figure out how to also print the row numbers along with each row's description. Right now it just prints description (which is a row with some text in it). How would I get the print output to be something like this?
1: the text in row 1
2: the text in row 2
3: etc etc etc
This is needed because eventually I will need to call upon a row number to delete a row entirely. So if Python receives input to delete row 10 in the sqlite database, I would need to be able to easily identify row 10. Kind of like if you right click + delete a row in excel and then the rest of the rows move up and become the previous number. I would like my program to work exactly like that.
Right now I think my table is only 1 column (the description column with the text). Do I need to add another column to identify row number? When I do SHOW TABLE in VSCode, I actually do see a column with the numbers labeled "#", but I'm not sure if that's really a part of the table or if it's just VSCode adding that for aesthetics.
If you want to select the 101th row, you can use SELECT description FROM items LIMIT 1 OFFSET 101 and use DELETE FROM items LIMIT 1 OFFSET 101 for deleting it.

sqlite - return all columns for max of one column without repeats

Im using Python to query a SQL database. I'm fairly new with databases. I've tried looking up this question, but I can't find a similar enough question to get the right answer.
I have a table with multiple columns/rows. I want to find the MAX of a single column, I want ALL columns returned (the entire ROW), and I want only one instance of the MAX. Right now I'm getting ten ROWS returned, because the MAX is repeated ten times. I only want one ROW returned.
The query strings I've tried so far:
sql = 'select max(f) from cbar'
# this returns one ROW, but only a single COLUMN (a single value)
sql = 'select * from cbar where f = (select max(f) from cbar)'
# this returns all COLUMNS, but it also returns multiple ROWS
I've tried a bunch more, but they returned nothing. They weren't right somehow. That's the problem, I'm too new to find the middle ground between my two working query statements.
In SQLite 3.7.11 or later, you can just retrieve all columns together with the maximum value:
SELECT *, max(f) FROM cbar;
But your Python might be too old. In the general case, you can sort the table by that column, and then just read the first row:
SELECT * FROM cbar ORDER BY f DESC LIMIT 1;

Delete first X rows of MySQL table once the number of rows is greater than N

I have an insert-only table in MySQL named word. Once the number of rows exceeds 1000000, I would like to delete the first 100000 rows of the table.
I am using mysqldb in python, so I have a global variable:
wordcount = cursor.execute("select * from word")
will return the number of rows in the table in the python environment. I then increment the wordcount by 1 everytime I insert a new row. Then I check if the number of rows are greater than 1000000, if it is, I want to delete the first 100000 rows:
if wordcount > 1000000:
cursor.execute("delete from word limit 100000")
I got this idea from this thread:
Delete first X lines of a database
However, this SQL ends of deleting my ENTIRE table, what am I missing here?
Thank you.
I don't think that's the right way of getting the number of rows. You need to change your statement to have a count(*) and then use MySQLs cursor.fetchone() to get a tuple of the results, where the first position (kinda like wordcount = cursor.fetchone()[0]) will have the correct row count.
Your delete statement looks right, maybe you have explicit transactions? in which case you'd have to call commit() on your db object after the delete.
If your table "word" have ID field (key auto_increment field) you may write some stored procedure of deleting first 100000-rows. The key part of stored procedure is:
drop temporary table if exists tt_ids;
create temporary table tt_ids (id int not null);
insert into tt_ids -- taking first 100000 rows
select id from word
order by ID
limit 100000;
delete w
from word w
join tt_ids ids on w.ID = ids.ID;
drop temporary table if exists tt_ids;
Also you may build some indexes on tt_ids on ID-field for a speed-UP your query.

Categories

Resources