How to save a table in a file
-
Replace
out<<ui->tableWidget->item(i, j)->text();
without<<ui->tableWidget->model()->index(i, j).data().tostring();
to prevent segfaultsThe problems I highlighted are still present though
@VRonin said in How to save a table in a file:
In your code above you are not:
- Writing any new line to separate rows.
- Writing any column separator
- Escaping column separators inside the data
-
@VRonin In a previous version I've added both ";" and "\n", but I forgot to write them again.
However I forgot one case: what happen if I did not create/delete/modify any file, folder, or other?
The cells (i, 2) might be empty and here is where the program fails.
I resolved by editing some code:void MainWindow::on_pushButton_2_clicked() { QFile csv(f_name); if(!csv.open(QFile::WriteOnly)) return; QTextStream out(&csv); int tmp_column = 0; for(int i = 0; i < ui->tableWidget->rowCount(); ++i){ for (int j = 1; j < ui->tableWidget->columnCount(); ++j){ if(ui->tableWidget->item(i, j) != 0) out<<ui->tableWidget->item(i, j)->text(); out<<";"; tmp_column = j; } if(ui->tableWidget->item(i, tmp_column) != 0) out<<"\n"; } out.flush(); csv.close(); }
It may not be quite good-looking but it works:
I've also prevented segmentation faults like this for example:
ui->tableWidget->setItem(index_delete, 0, itm); if(ui->tableWidget->item(index_delete, 2) != 0 && ui->tableWidget->item(index_delete, 2)->text() != "Deleted") ui->tableWidget->setItem(index_delete, 3, new QTableWidgetItem(QDateTime::currentDateTime().toString()));
-
P.S.
new QTableWidgetItem(QDateTime::currentDateTime().toString())
see https://bugreports.qt.io/browse/QTBUG-65555this should be separated in 3 lines:
QTableWidgetItem* tableItem = new QTableWidgetItem; tableItem->setData(Qt::EditRole,QDateTime::currentDateTime()); ui->tableWidget->setItem(index_delete, 3,tableItem);
-
Say I want to order the items of the table by name or date once I push Save, but without sorting the table itself (just the output in the file.csv). What can I do? Should I create a temporary table, order it and then store in the file?
Tell me if the question is not clear. -
Not a temporary table, you can use a
QSortFilterProxyModel
and then serialise the proxy rather than the original model.
Since your current architecture relies on theQStandardItem
interface rether than theQAbstractItemModel
one you'll need to do some rewriting.To give you an idea, being
QString m_csvSeparator
the column separator:#include <QStringBuilder> QString escapedCSV(QString unexc) const { if (!unexc.contains(m_csvSeparator)) return unexc; unexc.replace(QLatin1Char('\"'), QStringLiteral("\"\"")); return '\"' % unexc % '\"'; } bool writeCsv(QTextStream& writer, const QAbstractItemModel* constModel) const { if (!constModel) return false; for (int i = 0, maxRow = constModel->rowCount(); i < maxRow ; ++i) { for (int j = 0, maxCol = constModel->columnCount(); j < maxCol ; ++j) { const QString roleData = constModel->index(i, j).data().toString(); if (j>0) writer << m_csvSeparator; if (!roleData.isEmpty()) writer << escapedCSV(roleData); } writer << '\n'; } return writer.status() == QTextStream::Ok; }