You are not logged in.

1

Friday, April 30th 2010, 9:37am

store data of a table in csv

Hi,

is it possible to stora data of a tablewidget in a .csv file?
How to write into and read from a csv file? I haven't found any tutorials.

Table looks like this:
2010.05.01. kill joe 13:30
2010.05.01. meeitng 16:00
2010.05.02. get kid from school 16:15
etc.

Thanks, in advance.

subin007

Trainee

  • "subin007" is male

Posts: 88

Location: INDIA

Occupation: Student

  • Send private message

2

Friday, April 30th 2010, 9:58am

write csv file -this link will help you

3

Friday, April 30th 2010, 1:57pm

It seems to me that csv files store data as streams.
So the table would like like this (all columns are in column A):

2010.05.01.;kill joe;13:30;...
2010.05.01.;meeitng;16:00;...
2010.05.02.;get kid from school;16:15;...

am i right?

how can i work with e.g. the third data in a row?
like if table(1,2) == sg then...
Or if there's only the excel way,I image sg like this (i don't how to do it):
QString item1 = before first ";"
QString item2 = between first and second ";"
QString item3 = between second and third ";"
QString item = after third ";"

This post has been edited 1 times, last edit by "bfarago" (Apr 30th 2010, 2:03pm)


Junior

Professional

  • "Junior" is male

Posts: 1,613

Location: San Antonio, TX USA

Occupation: Senior Secure Systems Engineer

  • Send private message

4

Friday, April 30th 2010, 3:14pm

.csv files are (comma separated files); and not always does it mean it has to be a comma. But the main point is that it is a flat file (ascii) that consists of a rows of data in columnar format.
How you manipulate the information between the file and your table is really based on your logic you have during the read and write operations to the file.
for example:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void MainWindow::saveAsCSV()
{
    QFile f( "table.csv" );  // #include <QtCore/QFile>

    if( f.open( QIODevice::WriteOnly ) ){
        QTextStream ts( &f );  // #include <QtCore/QTextStream>
        QStringList strList;
        
        for( int r = 0; r < tableWidget->rowCount(); ++r ){
            strList.clear();
            for( int c = 0; c < tableWidget->columnCount(); ++c ){
                strList << "\""+tableWidget->item( r, c )->text()+"\"";
            }
            ts << strList.join( "," )+"\n";
        }
        f.close();
    }
}


You will have to edit above code to your specs.

Hope this is helpful.

5

Friday, April 30th 2010, 6:45pm

Wonderful! You are my hero.
How can i read the data from the csv into the tablewidget?
I began do some code on my own, but i am lost.

Junior

Professional

  • "Junior" is male

Posts: 1,613

Location: San Antonio, TX USA

Occupation: Senior Secure Systems Engineer

  • Send private message

6

Friday, April 30th 2010, 7:56pm

Something like this would work.

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
void MainWindow::load()
{
    QFile f( "table.csv" );  // #include <QtCore/QFile>

    if( f.open( QIODevice::ReadOnly ) ){
        QTextStream ts( &f );  // #include <QtCore/QTextStream>
        QList<QStringList> list;
        int row = 0, col = 0;
 
        // read entire file and parse lines into list of stringlist's
        while( !ts.atEnd() ){
            list << ts.readLine().split( "," );
        }
        
        f.close();  // done with file

        // prep table
        tableWidget->setRowCount( list.count() );  // number of stringlists give row count
        tableWidget->setColumnCount( list[0].count() );  // count of entries from intial stringlist for column count

        tableWidget->setUpdatesEnabled( false );  // for faster processing of large lists
        foreach( QStringList l, list ){
            foreach( QString str, l ){
                // remove quotes if str quoted
                if( str.endsWith( '"' ) ) str.chop(1);
                if( str.startsWith( '"' ) ) str.remove(0,1);
                tableWidget->setItem( row, col++, new QTableWidgetItem( str ));
            }
            row++; col=0;
        }
        tableWidget->setUpdatesEnabled( true );  // done with load 
    }
}


You may have to make changes to this based on your specs.
Hope this is helpful.

7

Friday, April 30th 2010, 9:53pm

Thank you so much, you've helped me a lot!
I am going further.
Apart from strings the table can contain images(.png) and time.
Storing and loading time is okay, as it is converted to QString when being put into the table. But what about if a cell contains an image?

Can i modify your write algorithm, or do sg else (maybe creating a temporary table)?

I would most likely to handle the image this way: if a cell contains an image, the value in the csv file would be .e.g "img". If it doesn't,
value would be null.
Idk if it is possible to put a condition into the 11-13 lines of your saveAsCSV() function.
It can be a good idea, to create a hidden column in the table where I store "img" if there's an image in that row..then the saving procedure would look like this:

Source code

1
2
3
4
5
6
for( int r = 0; r < tableWidget->rowCount(); ++r ){
            strList.clear();
            strList << "\""+tableWidget->item( r, 0 )->text()+"\"";
            strList << "\""+tableWidget->item( r, 1 )->text()+"\"";
            strList << "\""+tableWidget->item( r, 3 )->text()+"\""; //let's suppose the image is in the third column (that's why (...)->item(r,2)... is missing, and the fourth column (this one) is  the hidden one storing "img".
           }



What do you suggest?

This post has been edited 1 times, last edit by "bfarago" (Apr 30th 2010, 10:10pm)


Junior

Professional

  • "Junior" is male

Posts: 1,613

Location: San Antonio, TX USA

Occupation: Senior Secure Systems Engineer

  • Send private message

8

Saturday, May 1st 2010, 1:18pm

Thank you so much, you've helped me a lot!
I am going further.
Apart from strings the table can contain images(.png) and time.
Storing and loading time is okay, as it is converted to QString when being put into the table. But what about if a cell contains an image?

Images weren't part of the original examples nor mentioned and really don't fall into saving with the csv format unless you can reference the image by filename or rcc ref.

Can i modify your write algorithm, or do sg else (maybe creating a temporary table)?

You can do whatever you want with the provided code.

I would most likely to handle the image this way: if a cell contains an image, the value in the csv file would be .e.g "img". If it doesn't, value would be null.
Idk if it is possible to put a condition into the 11-13 lines of your saveAsCSV() function.
It can be a good idea, to create a hidden column in the table where I store "img" if there's an image in that row..then the saving procedure would look like this:

I'm not sure why you are hidding columns with images, but that is your design and if it works for you then good.

What do you suggest?

I don't know enough about your task and design to comment either way. I would use a model with TableView, maybe even a sql db if needed. In anycase, I would take the time to design before writing code to work out any flow/logic issues. If your going to be heavy in graphics, then rcc and pixmap cache would be helpful, then you could ref by cache key verse loading/saving thus rendering would be quicker as well. Just some thoughts.

9

Sunday, May 2nd 2010, 10:25am

Quoted

I'm not sure why you are hidding columns with images, but that is your design and if it works for you then good.

I managed to do it on my own. I am a man of thinking :) What i did is this:
I have 3 columns: task, tick image, alarm image. A tick jpg is shown in the row, when i clcik ready, and an alarm jpg when i set an alarm
for the task. I added two columns, where I hold a_img and r_img az strings. E.g. when i set an alarm for a task, in the column the a_img is shown (as well as the image). This way I put the a_img and r_img columns into the stringlist and into the csv what look like this:
task, a_img, r_img. And about the load part: When an a_img or r_img is in a row, the appropriate jpg files are added to the table. All this help columns are hidden, so what the user see is only the tasks and the jpg-s. Wonderful, isn't it? :)

I think I'll have 1-2 questions in the near future, but you have done the large part of the code for me. Thank you.

This post has been edited 1 times, last edit by "bfarago" (May 2nd 2010, 11:00am)


10

Tuesday, May 4th 2010, 6:05pm

Hi,
here again. I have a question about modifying your save() function.
I don't want to empty the stringlist. Every time i save the table i want the rows to be added to the stringlist. How would you do that?

With the modifications here is my save() function:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void todolist::saveClicked()
{
    QFile f( "table.csv" );
        if( f.open( QIODevice::WriteOnly ) )
        {
            QTextStream ts( &f );
            QStringList strList;
            for (int i=0; i<ui->tableWidget->rowCount(); i++)
            {
               strList.clear();
                   strList << "\""+ui->tableWidget->item(i,0)->text()+"\"";
                   strList << "\""+ui->tableWidget->item(i,1)->text()+"\"";
                   strList << "\""+ui->tableWidget->item(i,2)->text()+"\"";
                   strList << "\""+ui->tableWidget->item(i,3)->text()+"\"";
                   strList << "\""+ui->tableWidget->item(i,4)->text()+"\"";
                   strList << "\""+ui->tableWidget->item(i,5)->text()+"\"";
                   strList << "\""+ui->tableWidget->item(i,6)->text()+"\"";
                   strList << "\""+ui->tableWidget->item(i,7)->text()+"\"";
                ts << strList.join(",") + "\n";
            }
         f.close();
        }
}

Junior

Professional

  • "Junior" is male

Posts: 1,613

Location: San Antonio, TX USA

Occupation: Senior Secure Systems Engineer

  • Send private message

11

Tuesday, May 4th 2010, 6:20pm

I'm not sure what you mean. The strList is just a stage for writing to the stream. If you mean you want to just append to the file then:
if( f.open( QIODevice::WriteOnly ) ) // shud be // if( f.open( QIODevice::Append ) )

12

Tuesday, May 4th 2010, 7:44pm

Yeah, that's what i was looking for.
My prog works like this:
1.there's a tablewidget i can add rows to, remove rows from etc.
2. the save function saves the rows into the stringlist and through that into a .csv file.
3. the load function loads all rows from the .csv into tablwidget_2, which is a hidden table (it is used as a help obejct for the time being). Later the data will be loaded back to tablewidget.

To make my prog more understandable:
I have a dateEdit also. When i change date, the tablewidget is cleared so i can add new rows. When change to a date - if i already added some rows to - the program loads them. E.g. I add some rows (tasks) to 06th May. Then i change date to 07th. The table is empty now, i add 2 tasks. I change then to 09th, add new tasks. Then i change it back to 06th, and i can see the tasks I already added. Are you following me?

With your help, now i am not overwriting the csv file but storing every newly added row. Problem is now: I add 3 rows at a certain date and save it. Then i decide to add a fourth row (task) and save it again. This results in 7 rows in the .csv file, as i the rows already stored are not overwritten, but added again..

Is it possible to delete the existing rows in the save function, or is it ok to have a redundant .csv file with duplicated rows and delete the existing rows from tablewidget_2 after loading all of them?

I think the program is beyond my knowledge for the time being. I have to examine and duplicated rows and defining what is duplicated and what is to be overwritten is hard as there are a lot of situations.

I think i'll take my time to think this over before i start to more coding.

Junior

Professional

  • "Junior" is male

Posts: 1,613

Location: San Antonio, TX USA

Occupation: Senior Secure Systems Engineer

  • Send private message

13

Tuesday, May 4th 2010, 9:47pm

Well if you don't mind using memory. Something like this would always append new entries other than what is stored in the table.
I will let you figure out how to remove old entries.

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
void todolist::saveClicked()
{
    QFile f( "table.csv" );
        if( f.open( QIODevice::ReadWrite ) )
        {
            QTextStream ts( &f );
            QStringList tmpList;
            QStringList strList;

           while( !ts.atEnd() ){
               tmpList << ts.readLine();
          }

           QString tmpStr;
            for (int i=0; i<ui->tableWidget->rowCount(); i++)
            {
               strList.clear();
                   strList << "\""+ui->tableWidget->item(i,0)->text()+"\"";
                   strList << "\""+ui->tableWidget->item(i,1)->text()+"\"";
                   strList << "\""+ui->tableWidget->item(i,2)->text()+"\"";
                   strList << "\""+ui->tableWidget->item(i,3)->text()+"\"";
                   strList << "\""+ui->tableWidget->item(i,4)->text()+"\"";
                   strList << "\""+ui->tableWidget->item(i,5)->text()+"\"";
                   strList << "\""+ui->tableWidget->item(i,6)->text()+"\"";
                   strList << "\""+ui->tableWidget->item(i,7)->text()+"\"";
                tmpStr << strList.join(",");

                if( !tmpList.contains( tmpStr ) ){
                      ts << tmpStr << "\n";
                }
            }
         f.close();
        }
}


Just a pattern match from one list against another.

14

Wednesday, May 5th 2010, 6:11am

Wow, this is fantastic. Now i can save my table any time without getting duplicated rows (only if i add them, but that's not a problem).
I think I need one last thing (i hope).
Like i said i can change dates. Now, when i change date I can see the rows added to that date. Let's suppose there haven't been added any rows to other dates. I add rows to this (empty) table and save them, and only the new rows are stored. Example:

I add tasks to 07th May:
meeting
get kid from school
meeting

Save, and load them as testing, OK.

Now i change date to 08th May where i haven't added any rows so the tablewidget is cleared and add some rows:
go to post 11:00
lunch with Tim

Now i save and load them as testing and I only got these two new rows.

I want all rows of all dates loaded into the second (hidden) table. (From here, when changing date i will load rows into the first table that has that selected date in it's row.)

How can i do that?

15

Thursday, May 6th 2010, 7:23pm

Hello Junior,

the solution was unbelievably simple! I put every day's data into separate files! What's more i don't have to bother with duplication examination, as the rows in the files are always overwritten!

Thanks for the help, without you i would have never been able to put this together.

bfarago