Subscribe Bookmark RSS Feed

Shading blocks of rows in a Table Box

dqr2

Community Trekker

Joined:

Jun 19, 2015

Hi,

I have a Table Box which contains a large number of rows that group naturally into blocks of three rows each (because rows 1 to 3 relate to one chemical compound, rows 4 to 6 relate to another, rows 7 to 9 relate to a third one, and so on).  I'd like to shade the rows to make the blocks of compounds visually easier to distinguish - so I want to shade rows 1 to 3, then leave rows 4 to 6 white, then shade rows 7 to 9, then leave rows 10 to 12 white etc.  (The requirement for shading of three rows at a time means I can't just use the "<< shade alternate rows" property.)

I can pre-select every alternate block of three rows with the "<< set selected rows()" property, but that coloring pattern would then be lost if the user were subsequently to click on any of the rows or otherwise select/deselect them.  I've therefore applied the same property within the "<< set row change function" property - so if the user clicks anywhere on the table, the shading is immediately reapplied.  I end up with something like this:

nameList = repeat({"A"}, 3) || repeat({"B"}, 3) || repeat({"C"}, 3) || repeat({"D"}, 3) || repeat({"E"}, 3) || repeat({"F"}, 3) || repeat({"G"}, 3) || repeat({"H"}, 3);

threeList = {1, 2, 3, 7, 8, 9, 13, 14, 15, 19, 20, 21};

tb = Table Box(

  String Col Box("Name", nameList),

  Number Col Box("First", index(1, 24)),

  Number Col Box("Second", index(25, 48)),

  Number Col Box("Third", index(49, 72)),

  << set selected row color("cyan"),

  << set selected rows(threeList),

  << set row change function(tb << set selected rows(threeList)),

  << set scrollable(1),

  << set column borders(1),

  << set underline headings(1)

  );

new window("My Window", tb);

This works, but seems a bit convoluted.  Can anyone suggest an easier way to do it?

Many thanks.

1 ACCEPTED SOLUTION

Accepted Solutions
Solution

The way that I handle this is to use a New Data Box() function and to not use a Table Box(), but rather a data table.  With that, you can color the cells, etc. and take full advantage of all of the editing capabilities of a data table.

Here is a script to illustrate what I am talking about:

Names Default To Here( 1 );

dt = Open( "$SAMPLE_DATA/Big Class.jmp",invisible);

// Select groups of 3 rows

For( k = 1, k <= 3, k++,

       For( i = k, i <= N Rows( dt ), i = i + 6,

              Row State( i ) = Selected State( 1 )

       )

);

thelist = As List( dt << get selected rows );

dt << Clear Select;

// Loop across all columns and set the cell colors

collist = dt << get column names( "string" );

For( i = 1, i <= N Items( collist ), i++,

       Eval(

              Substitute(

                           Expr(

                                  Column( dt, collist[i] ) << color cells( {"Red", _thelist_} )

                           ),

                     Expr( _thelist_ ), thelist

              )

       )

);

// Setup the Display Window

Nw=New Window("Display",

       V List Box(

              tb=Text Box("   The Example"),

              vlb=V List Box()

       )

);

ndb = dt << New Data Box();

vlb << append(ndb);

ndb << close side panels(1);

tb << set font size(20);


It produces the following Display Window

11432_pastedImage_1.png

Jim
4 REPLIES
vince_faller

Super User

Joined:

Mar 17, 2015

Could do something like this.

index = 1::99;

new window("Window", tb = TableBox(NumberColBox("Column", index)));

n=3;//You can change this to whatever number your group is

rows = loc( mod(floor((index-1)/n), 2) );//just gives alternating groups of n bursts together

tb << Set selected rows(rows);


Hope this helps.  Cheers.



*Edit*  Just realized this isn't the part you were probably asking about.  Sorry. 


Could you just select the rows, then make them unselectable?


tb << Set Selectable rows(0);

Solution

The way that I handle this is to use a New Data Box() function and to not use a Table Box(), but rather a data table.  With that, you can color the cells, etc. and take full advantage of all of the editing capabilities of a data table.

Here is a script to illustrate what I am talking about:

Names Default To Here( 1 );

dt = Open( "$SAMPLE_DATA/Big Class.jmp",invisible);

// Select groups of 3 rows

For( k = 1, k <= 3, k++,

       For( i = k, i <= N Rows( dt ), i = i + 6,

              Row State( i ) = Selected State( 1 )

       )

);

thelist = As List( dt << get selected rows );

dt << Clear Select;

// Loop across all columns and set the cell colors

collist = dt << get column names( "string" );

For( i = 1, i <= N Items( collist ), i++,

       Eval(

              Substitute(

                           Expr(

                                  Column( dt, collist[i] ) << color cells( {"Red", _thelist_} )

                           ),

                     Expr( _thelist_ ), thelist

              )

       )

);

// Setup the Display Window

Nw=New Window("Display",

       V List Box(

              tb=Text Box("   The Example"),

              vlb=V List Box()

       )

);

ndb = dt << New Data Box();

vlb << append(ndb);

ndb << close side panels(1);

tb << set font size(20);


It produces the following Display Window

11432_pastedImage_1.png

Jim
dqr2

Community Trekker

Joined:

Jun 19, 2015

Thanks everyone - that's been extremely helpful all round, and I'm going to tick the problem as having been solved, as I've now got enough to resolve my original query.

I tried Vince's suggestion of setting the "<< set selectable rows(0)" property after creating the table box with the required selection, unfortunately however it seems that doing this actually clears the selection before taking effect.

I've taken a copy of Jim's script, as I invariably have difficulties with the syntax of combinations of eval(), substitute() and expr() constructions, and having working examples to adapt makes life a lot easier!  I'm actually going to stay with my Table Box at least for the time being, as the structure of the report I'm creating is better suited to that output format - but the New Data Box route is something I'd not previously considered, and could well be useful in the future.

It's also been pointed out to me in a private communication that I might need to consider the impact on my own solution of a user subsequently trying to sort the Table Box by one of its columns (which they could easily do with a right-click).  Actually this wouldn't be an issue in this instance, as the Table Box is part of a final report in which sorting it further would serve no useful purpose, but the point is well-taken.

Finally, I've noted in passing that the "<< set row change function()" property won't actually work unless either one or more rows have been explicitly selected by the "<< set selected rows()" property, or a "<< set selectable rows(1)" property has been included in the list of property settings.  It's just a small thing, but it confused me until I realised that at least one of these was necessary before I could do what I was trying to do.

Again, many thanks everyone.

txnelson

Super User

Joined:

Jun 22, 2012

Just to address some of your concerns about using a New Data View:

All that you need to do to address the users actions, is to add a Row State Handler.  It will detect the changes and branch to a function, in which you can programatically address the issue.  Such as in this case, if the view was sorted, you could reset the cell colors to the new order

f = function({a},<reset cell colors>);

rs = dt<<make rowstate handler(f);

Jim