Notes in Tables

I am looking for the best way to format a table that contains general notes on the data as well as the data itself. for example, the data could have typical column headers and each row would have corresponding entries. However, the notes could be text sentences, and could only occupy one row. I am trying to avoid a clumsy orgainization

Thanks

1 Like
  • approach 1

    • in grid view show the table without notes,
    • in record view show the notes
  • approach 2

    • grid view ONLY
      but make a record ( row ) selectable
      • and show overlay the note on click row.
  • approach 3

    • grid view only
      show note as a small ( reduced ) column
      on click on that NOTE CELL
      open !edit! window with complete note text,
      can use G4P textField or even textArea
2 Likes

Similar with mouse over

using the text() command with 5 parameters cuts longer text off

on mouse over, the complete text is shown


// class with tools 
Tools tools = new Tools(); 

// the table
Table tResources; 

void setup() {
  size(1600, 660);
  background(tools.WHITE);

  // setting up table (column names / headlines)
  tResources = tools.newTable("Item", "brick", "wood", "sheep", "wheat", "ore", "points");
  // adding data (must match headlines)
  tResources = tools.tableAddData ( tResources, "Street", "1x", "1x", "", "", "", "0" );  
  tResources = tools.tableAddData ( tResources, "Settlement", "1x", "1x", "1x", "1x", "", "1" );  
  tResources = tools.tableAddData ( tResources, "City", "", "", "", "2x", "3x", "2");  
  tResources = tools.tableAddData ( tResources, "Dev Card mn,m,m,mn, eewewrrew ooppopopoi pooopopoo ölööölöllökölk ,m.m..,.,m,m..,m", "", "", "1x", "1x", "1x", "?"  );  

  // ------------------------------
}

void draw() {
  background(0); 
  tools.showTable(tResources, 
    22, 22);
  fill(tools.WHITE); 
  text("use mouse over to show full text", 
    22, height/2-110);
}

//===============================================================================
// Tools collection 

class Tools {

  // class not like a car class Car for an object but a collection of tools. 

  final color RED   = color(255, 0, 0); 
  final color GREEN = color(0, 255, 0); 
  final color BLUE  = color(0, 0, 255); 

  final color WHITE = color(255); 
  final color BLACK = color(0); 
  final color GRAY  = color(255/2); 

  boolean cursorSignShowFlag=false; 

  // ----------------------------------------------------------------

  void showTable(Table tableBtn, 
    int x, int y) { 

    int factorX=78; // column width 

    // rect
    stroke(WHITE);
    noFill();
    rect( x, y, 
      tableBtn.getColumnCount()*78-6, (tableBtn.getRowCount()+1) * 22 + 10 );

    // headline 
    showTableHeadline(tableBtn, x+6, y+19, factorX);

    // horizontal line 
    stroke(WHITE);
    line( x+2, y+5+19, 
      6+x+(tableBtn.getColumnCount())*factorX-13, y+5+19);

    // grid 
    // loop over rows (y)
    for (int i=0; i<tableBtn.getRowCount(); i++) {

      // current data row
      TableRow row = tableBtn.getRow(i);

      // loop over columns in that row (i2 is for x) 
      for (int i2=0; i2<tableBtn.getColumnCount(); i2++) {

        fill(WHITE);
        text(row.getString(i2), 
          i2*factorX+x+6, 25+ i * 22 +y+8, 
          factorX-8, 15);

        if (mouseInside(i2*factorX+x+6, 25+ i * 22 +y+8, 
          factorX-8, 15)) {
          text (row.getString(i2), 
            20, height-22);
        }//if

        // vertical line 
        line( i2*factorX+x, +y, 
          i2*factorX+x, tableBtn.getRowCount() * 22 + y + 31);
      }//for
    }//for
  }// method 

  boolean mouseInside( float x_, float y_, 
    float w_, float h_) {
    return mouseX>x_ &&
      mouseX<x_+w_ &&
      mouseY>y_ &&
      mouseY<y_+h_;
  }

  void showTableHeadline(Table tableBtn, 
    int x, int y, 
    int factorX) { 
    // headline for table 
    TableRow row0 = tableBtn.getRow(0);
    for (int i=0; i<tableBtn.getColumnCount(); i++) {
      // headline 
      fill(GREEN);
      text(row0.getColumnTitle(i), 
        i*factorX+x, y-2);
    }
  }//method 

  // ---
  // make table 

  Table newTable (String... listColumnNames) { 

    Table newT = new Table();

    // make columns
    for (String s1 : listColumnNames) {
      newT.addColumn(s1);
    }

    return newT;
  }//method

  Table tableAddData(  Table table1, String... data1  ) {

    // add rows with data 
    TableRow newRow = table1.addRow();

    // add rows with data 
    int i=0; 
    for (String s1 : data1) {
      newRow.setString(newRow.getColumnTitle(i), s1);
      i++;
    }


    return table1;
  }//method

  // --- 

  void printlnTable(Table tableBtn) { 

    // rect
    stroke(WHITE);
    noFill();

    println("------------------------------------");

    // headline 
    printlnTableHeadline(tableBtn);

    // grid 
    // loop over rows (y)
    for (int i=0; i<tableBtn.getRowCount(); i++) {

      // current data row
      TableRow row = tableBtn.getRow(i);

      // loop over columns in that row (i2 is for x)
      String s1="";
      for (int i2=0; i2<tableBtn.getColumnCount(); i2++) {
        s1+="   "+row.getString(i2);
        //
      }//for
      println(s1);
    }//for
    println("===========================================");
    //
  } // method 

  void printlnTableHeadline(Table tableBtn ) { 
    // headline for table 
    TableRow row0 = tableBtn.getRow(0);
    for (int i=0; i<tableBtn.getColumnCount(); i++) {
      // headline 
      print("   "+row0.getColumnTitle(i));
    }
    println("");
  }//method 

  // ------------------------------------------------------------------

  String cursorSign() {
    // blinking cursor sign | for Input Box 
    if (frameCount % 13 == 0)
      cursorSignShowFlag= ! cursorSignShowFlag;
    if (cursorSignShowFlag)
      return"|";
    else return"";
  }//method

  //
}//class
//
3 Likes

Thanks. I thought of another approach after seeing your’s and Chrisir’s replies. The notes that I was thinking of, were setup parameters for the process that provided the data in the table. In this case, i could just add rows above the data that contained the name of the parameter and its value.

  • Column headers could be made compatible with both the data and the parameter information.

  • One of the parameters should be the table row of the beginning of the data. This provides an index for subsequent processing of the data

1 Like

i think about that from the view of data files,
and to be open / not restricted / regarding columns and rows
best would be to have 2 CSV files with same structure.
one with the data, one with the notes for each data cell.

this version not have the edit function like @Chrisir
or my editgrid ( see my picture approach 3 )

// TABLE_NOTE

/*    need test files
 data/data.csv
 ________________________
 head1,head2,head3
 1a,1b,1c
 2a,2b,2c
 ________________________
 data/data_note,csv
 ________________________
 head1p,head2p,head3p
 1ap,1bp,1cp
 2ap,2bp,2cp
 ________________________
 */

Table data, data_note;
String data_fn = "data/data.csv", data_note_fn = "data/data_note.csv";
int dc = 60, dx = 10, dr =20;
float posx, posy;

void setup() {
  size(500, 500);
  noFill(); 
  stroke(0, 300, 200); 
  data      = loadTable(data_fn, "header");
  data_note = loadTable(data_note_fn, "header");
}

void draw() {
  background(80, 80, 0);
  for (int c =0; c < data.getColumnCount(); c++)     text(data.getColumnTitle(c), dx+c*dc, dr);  
  for (int r = 0; r < data.getRowCount(); r++)   for (int c =0; c < data.getColumnCount(); c++) {  
    text(data.getString(r, c), dx+c*dc, (r+2)*dr);
    show_note(r, c);
  }
}

void show_note(int row, int col) {
  posx = dx+col*dc;
  posy = (row+1)*dr;
  if (mouseX > posx && mouseX < posx + dc && mouseY > posy && mouseY < posy+dr) {          // MOUSE OVER
    rect(posx, posy, dc, dr);                              // rect for cell select
    rect(10, height-25, width-20, 22);                     // rect for note filed
    text(data_note.getString(row, col), 15, height-8);     // note for selected cell
  }
}

for a very basic look ( no rectangles… ) a snappy version

Table data, data_note;
String data_fn = "data/data.csv", data_note_fn = "data/data_note.csv";
int dc = 60, dx = 10, dr =20, posx, posy;

void setup() {
  size(500, 500);
  data      = loadTable(data_fn, "header");
  data_note = loadTable(data_note_fn, "header");
}

void draw() {
  background(80, 80, 0);
  for (int c =0; c < data.getColumnCount(); c++)     text(data.getColumnTitle(c), dx+c*dc, dr);     // data Column Header
  for (int r = 0; r < data.getRowCount(); r++)   for (int c =0; c < data.getColumnCount(); c++) {   // data
    posx = dx+c*dc;      
    posy = (r+1)*dr;
    text(data.getString(r, c), posx, dr + posy);                                                    // data cell content
    if (mouseX > posx && mouseX < posx + dc && mouseY > posy && mouseY < posy+dr) text(data_note.getString(r, c), 15, height-8); // note for selected cell
  }
}

2 Likes

This is elegant and facilitates pinpointing notes to specific cell. Best for multi users of same data.

My application is more personal and, I find it simpler to export the CSV file to a spreadsheet such as numbers. In Numbers (I’m on a Mac), I can view the information as well as use all of the charting, statistical, etc functions to process my data. Furthermore, I can directly insert these charts into my word processor for reports. In this case, I would prefer to have all the setup information as well as the data on the same CSV file.

Thank you for your inputs, they have been helpful.

@poppanona

you described your setup/layout of your special table with nested comments and One of the parameters being the table row of the beginning of the data

have you done this already? Can you share it?

1 Like

I have not done this yet, I am still in the planning stages. However, I am now driven to go beyond my current method of collecting the data in an array and manually processing it. When I have working code, I will most certainly share it.

sorry, i not get that comment

  • if use one CSV file ( with your data && data_parameter nested )
    or two CSV, no problem.
  • the CSV file is read to a “table”
  • and you can save the table ( like after change ) again as a CSV file
  • i not know of a tool to write it as XLS file type, but might exist

what does that mean ( i only play Windows and Raspbian OS )
i expect any spreadsheet program to be able to import/export CSV files.
while the delimiter ( tsv … ) can even be language dependent
( i learned CSV as “;” separated )

1 Like

As a result of this discussion, I have decided to create two independent CSV files, one for the data and the other for the notes. Each of these files will have it’s own structure. I will subsequently import these two files into a spreadsheet template specifically formatted to process the information in these files.

Thanks for the discussion

3 Likes

I think this is a good idea.

If you had it all in one table and you want to have a String description/ comment/ explanation for the first column but the first column would otherwise be of type float that is hard to handle.

With 2 csv you are better off.

Are you planning to do it in numbers or in processing?

1 Like

The CSV files will be created in Processing where the program for my project that I am collecting data on resides. I will do all of the data processing in my Numbers spreadsheet.

When I double-click on these CSV files in my data folder, they automatically open as separate Numbers files. It is just a matter of dragging and dropping them into my final spreadsheet template, to complete the process.

1 Like

In this code, you referred to the parameter (String…list ColumnNames) in one way, and used it in your for loop as (String s1 : listColumnNames). I don’t fully understand the syntax. ls the first use another way of saying, stringList? and if so, why don’t you have to declare it as such?

Or, is it another way of saying {" string1", “string2”…} like filling in a string array.

2 Likes

That ellipsis is the syntax for variable arguments (varargs). For your purposes (String... listColumnNames) is the same as (String[] listColumnNames).

The “…” form handles being passed a single string or no strings – that is, a variable number of arguments (0, 1, 2 or more) and it can also be called with strings separated by commas, as well as pre-packed into an array. Here is a discussion if you are curious:

It is not related to StringList. StringList is a class – String… gives a varargs interface to String[] , a primitive array of Strings

2 Likes

Very recently I’ve made 2 functions using the variadic ellipses ... parameter: :smile_cat:

1 Like