QTableView output save as .csv or .txt - c++

I wrote the below code for a qt gui to view the query output in a QTableView(Model oriented). now i want to save this output as a .csv or .txt file. There were suggestions to use QTableWidget(Item oriented) but I would like to stick to the model based approach.
void MainWindow::on_pushButton_clicked()
{
db = QSqlDatabase::addDatabase("QOCI");
db.setHostName("host");
db.setDatabaseName("db");
db.setUserName("uid");
db.setPassword("pw");
db.setPort(port);
QString MyQuery = ui->lineEdit->text();
if (db.open())
{
qDebug()<<QDateTime::currentDateTime()<<"QUERY DONE SUCCESSFULLY ";
this->model=new QSqlQueryModel();
model->setQuery(MyQuery);
ui->tableView->setModel(model);
}
else
{
qDebug()<<QDateTime::currentDateTime()<<"YOU FORGOT THE QUERY "<<db.lastError().text();
}
}
any guidelines ???

You may customize it according to your actual needs:
// [Collect model data to QString]
QString textData;
int rows = model->rowCount();
int columns = model->columnCount();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
textData += model->data(model->index(i,j)).toString();
textData += ", " // for .csv file format
}
textData += "\n"; // (optional: for new line segmentation)
}
// [Save to file] (header file <QFile> needed)
// .csv
QFile csvFile("test.csv");
if(csvFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
QTextStream out(&csvFile);
out << textData;
csvFile.close();
}
// .txt
QFile txtFile("test.txt");
if(txtFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
QTextStream out(&txtFile);
out << textData;
txtFile.close();
}

You can save your model to a text file by :
QFile f( "table.txt" );
if( f.open( QIODevice::WriteOnly ) )
{
QTextStream ts( &f );
QStringList strList;
for (int i=0; i<model->rowCount(); i++)
{
strList.clear();
for (int j=0; j<model->columnCount(); j++)
strList << model->data(model->index(i,j)).toString();
ts << strList.join(" ") + "\n";
}
f.close();
}
Here the model data are saved one row in each line separated by space. If you want to separate them by some other character like comma you can just replace the parameter on the join like :
ts << strList.join(",") + "\n";

here is a way to export a qtableview to a csv, including the column names using qt
void staticmethods::exportTableViewToCSV(QTableView *table) {
QString filters("CSV files (*.csv);;All files (*.*)");
QString defaultFilter("CSV files (*.csv)");
QString fileName = QFileDialog::getSaveFileName(0, "Save file", QCoreApplication::applicationDirPath(),
filters, &defaultFilter);
QFile file(fileName);
QAbstractItemModel *model = table->model();
if (file.open(QFile::WriteOnly | QFile::Truncate)) {
QTextStream data(&file);
QStringList strList;
for (int i = 0; i < model->columnCount(); i++) {
if (model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString().length() > 0)
strList.append("\"" + model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString() + "\"");
else
strList.append("");
}
data << strList.join(";") << "\n";
for (int i = 0; i < model->rowCount(); i++) {
strList.clear();
for (int j = 0; j < model->columnCount(); j++) {
if (model->data(model->index(i, j)).toString().length() > 0)
strList.append("\"" + model->data(model->index(i, j)).toString() + "\"");
else
strList.append("");
}
data << strList.join(";") + "\n";
}
file.close();
}
}

Related

Program not responding when export more than 10000 data to csv. QT C++

I'm exporting data to csv. I can export if datas around 8K or 10K but when I try to export data around 100K I get a warning "program not responding".
void MainWindow::exportArraysToCSV(QStringList labelList, QList < QList < double >> dataColums, QChar sep) {
QString filters("CSV files (*.csv);;All files (*.*)");
QString defaultFilter("CSVi files (*.csv)");
QString fileName = QFileDialog::getSaveFileName(0, "Save file", QCoreApplication::applicationDirPath(),
filters, & defaultFilter);
QFile file(fileName);
if (file.open(QFile::WriteOnly | QFile::Append)) {
QTextStream data( & file);
QStringList strList;
QString formula;
foreach(auto label, labelList) {
if (label.length() > 0){
strList.append("," + label + ",");
}
else
strList.append("");
}
data << strList.join(",") << "\n";
int maxRowCount = 0;
foreach(auto column, dataColums)
maxRowCount = qMax(maxRowCount, column.count());
for (int i = 5; i < maxRowCount; ++i) // rows
{
strList.clear();
for (int j = 0; j < 2; ++j) // columns
{
if (i < dataColums[j].count())
strList.append(QString::number(dataColums[j][i], 'f'));
else
strList.append("\"\" ");
}
data << strList.join(",") + "\n";
}
data << "=SUM(A2:A1255)";
file.close();
}
}

Error when try to read from a QFile

I want to read some data from a file with QT and then show data in a QTableWidget through a QComboBox.
void DemoDataView::on_comboBox_activated(const QString &arg1)
{
ui->tableWidget->setColumnCount(5);
ui->tableWidget->setRowCount(21);
ui->tableWidget->verticalHeader()->setVisible(false);
ui->tableWidget->setHorizontalHeaderLabels(QString("Age Range ; Male Population ; Male Percentage ; Female Population ; Female Percentage").split(";"));
ui->tableWidget->resizeColumnsToContents();
ui->tableWidget->resizeRowsToContents();
QFile inputFile("./data.txt");
if(!inputFile.open(QIODevice::ReadOnly))
{
QMessageBox::information(0, "Error", inputFile.errorString());
}
QTextStream in(&inputFile);
int rows = 0;
while(!in.atEnd()) {
QString mLine = in.readLine();
QStringList fields = mLine.split(" ");
QStringList::iterator it = fields.begin();
QString regName = *it;
ui->label->setText(arg1);
if(regName != "<END>" && QString::compare(regName, arg1) == 0) {
ui->label->setText(regName);
it++;
QString ageRange = *it;
it++;
QString nMale = *it;
double male = nMale.toDouble();
it++;
QString nFemale = *it;
double female = nFemale.toDouble();
ui->tableWidget->setItem(rows, 0, new QTableWidgetItem(ageRange));
ui->tableWidget->setItem(rows, 1, new QTableWidgetItem(nMale));
ui->tableWidget->setItem(rows, 3, new QTableWidgetItem(nFemale));
ui->tableWidget->setItem(rows, 2, new QTableWidgetItem(malePercCalc(male, female)));
ui->tableWidget->setItem(rows, 4, new QTableWidgetItem(femalePercCalc(male, female)));
rows++;
}
inputFile.close();
}
}
The file is in both the project folder and the build project folder.
When I run the application everything works good but in the Application Output tab I have this error message:
"QIODevice:: read (QFile, "./data.txt"): device not open"
Every time I click on a QComboBox item.
If it can be useful, this is the filling code of the QComboBox:
void DemoDataView::setComboBoxRegion() {
QFile inputFile("./data.txt");
if(!inputFile.open(QIODevice::ReadOnly))
{
QMessageBox::information(0, "Error", inputFile.errorString());
}
QTextStream in(&inputFile);
while(!in.atEnd()) {
QString mLine = in.readLine();
QStringList fields = mLine.split(" ");
QStringList::iterator it = fields.begin();
QString regName = *it;
if(regName != "<END>") {
if(ui->comboBox->findText(regName) == -1){
ui->comboBox->addItem(regName);
}
}
}
inputFile.close();
}
Your problem is that you are calling:
inputFile.close();
INSIDE of your loop, which means it is closed in the first loop. I can't really think of any cases that this would be the desired thing to happen;
To solve this, you should move it to the outside of the loop.

Progress bar for copying files

I am trying to create a progress bar for a file copy in Qt. This is as close as I could find, however I believe this doesn't work because according to the Qt class documentation:
Unlike other QIODevice implementations, such as QTcpSocket, QFile does
not emit the aboutToClose(), bytesWritten(), or readyRead() signals.
This implementation detail means that QFile is not suitable for
reading and writing certain types of files, such as device files on
Unix platforms.
How can I do something like this? I don't know how to implement my own signals.
Here is my code:
void Replicator::anotbaandbFile(QDir source, QDir target)
{
source.setFilter(QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks);
target.setFilter(QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks);
qDebug() << "Scanning: " << source.path();
QStringList sourceFileList = source.entryList();
QStringList targetFileList = target.entryList();
for (int aCount = 0; aCount < sourceFileList.count(); aCount++)
{
bool found = false;
for (int bCount = 0; bCount < targetFileList.count(); bCount++)
if (sourceFileList.at(aCount) == targetFileList.at(bCount))
found = true;
if (found == false)
{
sourceFile = new QFile(source.absolutePath()+"/"+sourceFileList.at(aCount));
targetFile = new QFile(target.absolutePath()+"/"+sourceFileList.at(aCount));
progressBar->setMinimum(0);
progressBar->setMaximum(sourceFile->size());
written = 0;
connect(sourceFile,SIGNAL(bytesWritten(qint64)),SLOT(onWrite(qint64)));
sourceFile->copy(targetFile->fileName());
//QFile::copy(source.absolutePath()+"/"+sourceFileList.at(aCount), target.absolutePath()+"/"+sourceFileList.at(aCount));
qDebug() << source.absolutePath()+"/"+sourceFileList.at(aCount) << " " << target.absolutePath()+"/"+sourceFileList.at(aCount);
}
}
}
and
void Replicator::onWrite(qint64 w)
{
written += w;
progressBar->setValue( written );
}
new code modified from above
if (found == false)
{
sourceFile = new QFile(source.absolutePath()+"/"+sourceFileList.at(aCount));
targetFile = new QFile(target.absolutePath()+"/"+sourceFileList.at(aCount));
progressBar->setMinimum(0);
progressBar->setMaximum(sourceFile->size());
QByteArray buffer;
for (int count = 0; !(buffer = sourceFile->read(1000000)).isEmpty(); count+=1000000)
{
targetFile->write(buffer);
progressBar->setValue(count);
}
//targetFile->write(buffer);
//QFile::copy(source.absolutePath()+"/"+sourceFileList.at(aCount), target.absolutePath()+"/"+sourceFileList.at(aCount));
qDebug() << "copying " << sourceFile->fileName() << " to " << targetFile->fileName();
}
You can simply copy large files by portions of fixed size, than count portions already copied and callculate of percentage of work by dividing it to overal count of portions.
int iWorkPercentage = (int)(((float)iPortionsProcessed / (float)iOveralPortions) * 100);

QT File writing with arrays

Im trying to read from csv file into another file. There aren't any errors, I just don't understand why it is not writing into the file. Any help is appreciated. Im very new to QT.
QString arr[581][6];
while (!file.atEnd()) {
QByteArray line = file.readLine();
for (int i=0; i<581; i++){
for(int j=0; j<6; j++){
arr[i][j]=line;
}
}
}
QString Hfilename="c:\Data.txt";
QFile fileH( Hfilename );
if ( fileH.open(QIODevice::ReadWrite) )
{
QTextStream stream( &fileH );
for (int i=0; i<581; i++){
for(int j=0; j<6; j++){
stream<<arr[i][j]<<endl;
}
}
}
Based on the code you provided, please find a working example for the write step (you specified that the read step is alrady working):
#include <QCoreApplication>
#include <QFile>
#include <QTextStream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString arr[3];
arr[0] = "xxxxxx";
arr[1] = "yyyy";
arr[2] = "zzzz";
QString Hfilename="/home/jhondoe/toto.txt";
QFile fileH( Hfilename );
if ( fileH.open(QIODevice::ReadWrite) )
{
QTextStream stream( &fileH );
for (int i=0; i<3; i++){
stream << arr[i] << endl;
}
}
return a.exec();
}
What changed:
I (my user account) has sufficient rights to write into the output file
If you work on Windows, as #igor-tandetnik said, you have to use double backslashes as separator. You can also use QDir::separator() as native separator for your file path.

QTableView printing

I am new on QT an I try to print out from QTableView
How can I do this?
Thank a lot
Here is a variation of the first answer that gets rid of the intermediate file.
QString strStream;
QTextStream out(&strStream);
const int rowCount = pPublic->tableView->model()->rowCount();
const int columnCount = pPublic->tableView->model()->columnCount();
out << "<html>\n"
"<head>\n"
"<meta Content=\"Text/html; charset=Windows-1251\">\n"
<< QString("<title>%1</title>\n").arg(strTitle)
<< "</head>\n"
"<body bgcolor=#ffffff link=#5000A0>\n"
"<table border=1 cellspacing=0 cellpadding=2>\n";
// headers
out << "<thead><tr bgcolor=#f0f0f0>";
for (int column = 0; column < columnCount; column++)
if (!pPublic->tableView->isColumnHidden(column))
out << QString("<th>%1</th>").arg(pPublic->tableView->model()->headerData(column, Qt::Horizontal).toString());
out << "</tr></thead>\n";
// data table
for (int row = 0; row < rowCount; row++) {
out << "<tr>";
for (int column = 0; column < columnCount; column++) {
if (!pPublic->tableView->isColumnHidden(column)) {
QString data = pPublic->tableView->model()->data(pPublic->tableView->model()->index(row, column)).toString().simplified();
out << QString("<td bkcolor=0>%1</td>").arg((!data.isEmpty()) ? data : QString(" "));
}
}
out << "</tr>\n";
}
out << "</table>\n"
"</body>\n"
"</html>\n";
QTextDocument *document = new QTextDocument();
document->setHtml(strStream);
QPrinter printer;
QPrintDialog *dialog = new QPrintDialog(&printer, NULL);
if (dialog->exec() == QDialog::Accepted) {
document->print(&printer);
}
delete document;
here is my solution of a problem. May be it's too complex... But here you could find more solutions!
1). first I have saved table data to HTML page file:
bool CRefViewerDlg::createHtmlTableFromModel() {
// make a html-dump of table view
if (tableView) {
const QString htmlFileName = QString("%1/%2").arg(qApp->applicationDirPath()).arg("myTable.html");
QFile file(htmlFileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
MSG(QString("Can`t create file %1").arg(htmlFileName));
return false;
}
QTextStream out(&file);
const xbLong rowCount = tableView->model()->rowCount();
const xbLong columnCount = tableView->model()->columnCount();
out << "<html>\n"
"<head>\n"
"<meta Content=\"Text/html; charset=Windows-1251\">\n"
<< QString("<title>%1</title>\n").arg(refTitleName)
<< "</head>\n"
"<body bgcolor=#ffffff link=#5000A0>\n"
"<table border=1 cellspacing=0 cellpadding=2>\n";
// headers
out << "<tr bgcolor=#f0f0f0>";
for (xbLong column = 0; column < columnCount; column++)
if (!tableView->isColumnHidden(column))
out << QString("<th>%1</th>").arg(tableView->model()->headerData(column, Qt::Horizontal).toString());
out << "</tr>\n";
file.flush();
// data table
for (xbLong row = 0; row < rowCount; row++) {
out << "<tr>";
for (xbLong column = 0; column < columnCount; column++) {
if (!tableView->isColumnHidden(column)) {
QString data = tableView->model()->data(tableView->model()->index(row, column)).toString().simplified();
out << QString("<td bkcolor=0>%1</td>").arg((!data.isEmpty()) ? data : QString(" "));
}
}
out << "</tr>\n";
}
out << "</table>\n"
"</body>\n"
"</html>\n";
file.close();
}
return true;
}
2). after I have saved html content to file, it was opened in html view window, where I could print the document with QTextBrowser class:
void CLiveListDlg::on_printPageToolButton_clicked() {
#ifndef QT_NO_PRINTER
QTextBrowser *editor = static_cast<QTextBrowser* >(textBrowser);
QPrinter printer;
QPrintDialog *dialog = new QPrintDialog(&printer, this);
dialog->setWindowTitle(tr("Print Document"));
if (editor->textCursor().hasSelection())
dialog->addEnabledOption(QAbstractPrintDialog::PrintSelection);
if (dialog->exec() != QDialog::Accepted)
return;
editor->print(&printer);
#endif
}
How about this one?
Traverse through the model of your QTableView let's say QStandardItemModel. Obtain the each and individual texts of the items available in the QStandardItemModel.
Now using QTextCursor, insert the obtained texts from your model into QTextDocument. You can make use of the examples given here to insert text into QTextDocument.
After the completion of inserting into QTextDocument, you can print the contents available in the QTextDocument through
void QTextDocument::print ( QPrinter * printer ) const
The thing you have to make sure is that you should be able to traverse through each items so that you can able obtain all the item text from the model.
Hope it helps..