10

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 ???

Nejat
  • 31,784
  • 12
  • 106
  • 138
RicoRicochet
  • 2,249
  • 9
  • 28
  • 53

3 Answers3

14

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();
} 
Tay2510
  • 5,748
  • 7
  • 39
  • 58
  • 1
    thank you for providing with this thought process, i tried to use this but it threw some errors during build time--- /usr/local/Trolltech/Qt-4.8.4/include/QtGui/qwidget.h:812: error: ‘QWidgetData* QWidget::data’ is private /home/aj/MY_QT_WORK/table_test/mainwindow.cpp:62: error: within this context /home/aj/MY_QT_WORK/table_test/mainwindow.cpp:62: error: invalid operands of types ‘QWidgetData*’ and ‘const char [2]’ to binary ‘operator+’ /home/aj/MY_QT_WORK/table_test/mainwindow.cpp:62: error: in evaluation of ‘operator+=(class QWidgetData*, const char [2])’ – RicoRicochet Dec 08 '14 at 07:41
  • 1
    @AmarjitBiswas There were some syntax errors, and I've just corrected them. Please try the latest update. – Tay2510 Dec 08 '14 at 07:42
  • 1
    is the reverse also possible ?? that is using this .csv or .txt to populate a QTableView ??? any code-snippet / documentation-link will be very helpful. thanks again. – RicoRicochet Dec 08 '14 at 08:21
  • 1
    @AmarjitBiswas It's of course possible, but you have to "parse" the file no matter it's `.csv` or `.txt`. In other words, you have to determine the mapping methods of sequential data (.csv file for example) to your data model of `QTableView`. I would suggest you ask a new question and specify your needs, since the reverse approach would require you determine the file format first. Otherwise, it will be too board to answer. – Tay2510 Dec 08 '14 at 08:28
  • 1
    @AmarjitBiswas Ehh... I just found you have asked a similar question [**here**](http://stackoverflow.com/questions/27351546/import-csv-file-to-sqlite3-database-table-on-qt-gui), does that make any difference? – Tay2510 Dec 08 '14 at 08:44
  • 1
    actually my previous plan was to directly import to sqlite3 database but since sqlite3 .dot-commands can not be directly integrated to qt-c++ I am trying to follow a long process. for my purpose speed of execution doesnt matter, so i am thinking to use .csv or .txt files to keep copies of retrieved data and then use a scheduler to keep them loading in the sqlite database. – RicoRicochet Dec 08 '14 at 08:48
  • 1
    i posted my doubts in a separate question as suggested, http://stackoverflow.com/questions/27354200/uploading-csv-or-txt-file-to-populate-qtableview thank you... – RicoRicochet Dec 08 '14 at 09:27
4

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";
Nejat
  • 31,784
  • 12
  • 106
  • 138
4

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();
            }

        }
momor10
  • 478
  • 3
  • 11
  • Just to note that although this calls its output .csv, the separator it uses is ";"... – Clare Macrae Nov 08 '19 at 22:50
  • The output csv file merge all columns of one row in one cell, but what i expexted is each column occupys one cell, so i modify above code by replacing `data << strList.join(";") << "\n";` with `data << strList.join(",") << "\n";`. – Wade Wang May 03 '21 at 04:10
  • I tried this code for export some datas coming from serial port. It works well but all datas shown on first row. How can I add tab for jump to next culumn. Here is [question](https://stackoverflow.com/questions/73155255/qt-c-all-datas-shown-on-same-column-when-export-csv?noredirect=1#comment129206802_73155255) I asked. But I couldnt find solution. – ysncck Jul 30 '22 at 08:24