2
$\begingroup$

At various times though use of extensive trial-and-error I have gotten results I want out of TableHeadings. More often I give up. For example, given two columns, (a) how does one make the first left-justified and the second right-justified? And (b) is there any elegant way of aligning to the decimal point?

inTable={{"one","two","three","four","five"},{1.2,3.21,.43,5.,23}};

problem (a), output like this:

one     1.2
two    3.21
three   .43
four     5.
five     23

problem (b), output like this:

one      1.2
two      3.21
three     .43
four     5.
five    23
$\endgroup$
4
  • $\begingroup$ Have you tried anything? Grid seems like a good option: Grid[Transpose@inTable, Alignment -> {{Left, Right}}] $\endgroup$
    – Öskå
    Mar 31, 2016 at 20:44
  • $\begingroup$ @Öskå If I use Grid, I lose access to TableHeadings, and this approach doesn't solve the decimal alignment problem. $\endgroup$ Mar 31, 2016 at 20:46
  • 3
    $\begingroup$ Yes it does: Grid[Transpose@inTable, Alignment -> {{Left, "."}}]. And you can just add the heading manually in the list. $\endgroup$
    – Öskå
    Mar 31, 2016 at 20:47
  • 1
    $\begingroup$ In other words, just look at Grid with the Alignment and Dividers options. Then you might need Prepend to insert headings manually. $\endgroup$
    – Öskå
    Mar 31, 2016 at 21:04

1 Answer 1

6
$\begingroup$

I haven't revised this code for 5 years but think it should do what you need for a):

sortableTable[Transpose@inTable, Alignment -> {{Left,Right}, Center}]

and for b)

sortableTable[Transpose@inTable, Alignment -> {{Right, "."}, Center}]

enter image description here

Clear[sortableTable];

Options[sortableTable] = 
  Flatten[{TableHeadings -> {None, None}, Options[Grid]}];

SyntaxInformation[
   sortableTable] = {"ArgumentsPattern" -> {_, OptionsPattern[]}};

sortableTable::usage = "\!\(\*
StyleBox[\"sortableTable\", \"MB\"]\)[\!\(\*
StyleBox[\"data\",\nFontSlant->\"Italic\"]\)] takes a list of data \
and returns a table which can be sorted by clicking on column \
headers. Styling options are the saem as for \!\(\*
StyleBox[\"Grid\", \"MB\"]\). Table headings are entered by \
specifying values for teh option TableHeadings. This option functions \
identically to the same option to \!\(\*
StyleBox[\"TableForm\", \"MB\"]\).";

sortableTable::header = "Headers need to be entered as a list.";
sortableTable::row = "Row labels  need to be entered as a list.";
sortableTable::opts = 
  "TableHeadings must be a list with a maximum length 2, containing \
specifications for row and column headings.";

sortableTable[data_List, opts : OptionsPattern[]] := 
  DynamicModule[{gridOptions, rows, columns, rowOptions, 
    columnOptions, headings, labels, tmp, i = 1, 
    tableOptions = OptionValue[TableHeadings]},

   If[Length[tableOptions] === 1, 
    tableOptions = {None, tableOptions[[1]]}];
   If[tableOptions === {}, tableOptions = {None, None}];
   If[Length[tableOptions] > 2, Message[sortableTable::opts]; Abort[]];

   gridOptions = FilterRules[{opts}, Options[Grid]];

   {rows, columns} = Dimensions[data];

   (* get the value of the TableHeadings options *)
   {rowOptions, 
     columnOptions} = tableOptions;

   (* if the user doesn't want headers then make a blank list *)

   If[columnOptions === None, headings = Table[" ", {j, columns}]];

   (* if the value of the header option is not None then check to \
ensure it is a list *)

   If[columnOptions =!= None && ! VectorQ[columnOptions], 
    Message[sortableTable::header]; Abort[]];

   (* if the value of the header option is not None, 
   and was entered as a list then check the list length *)

   If[columnOptions =!= None && VectorQ[columnOptions],
    Which[
     Length[columnOptions] === columns, headings = columnOptions,
     Length[columnOptions] >= columns, 
     headings = columnOptions[[1 ;; columns]],
     Length[columnOptions] < columns, 
     headings = 
      Flatten[{columnOptions, 
        Table[" ", {columns - Length[columnOptions]}]}]
     ]
    ];

   (* if the value of the row option is not None then check to ensure \
it is a list *)

   If[rowOptions =!= None && ! VectorQ[rowOptions], 
    Message[sortableTable::row]; Abort[]];

   (* if the value of the row option is not None, 
   and was entered as a list then check the list length *)

   If[rowOptions =!= None && VectorQ[rowOptions],
    Which[
     Length[rowOptions] === rows, labels = rowOptions,
     Length[rowOptions] >= rows, labels = rowOptions[[1 ;; rows]],
     Length[rowOptions] < rows, 
     labels = 
      Flatten[{rowOptions, Table[" ", {rows - Length[rowOptions]}]}]
     ]
    ];

   Which[
    rowOptions === None && columnOptions === None, 
    Grid[data, gridOptions],
    rowOptions === None,
    (* no row labels *)
    Dynamic[
     tmp = SortBy[data, #[[i]] &];
     Deploy@
      Grid[Join[{Table[
          With[{j = j}, 
           EventHandler[
            headings[[j]], {"MouseClicked" :> (i = j)}]], {j, 
           columns}]}, tmp], gridOptions],
     TrackedSymbols :> {i}],

    rowOptions =!= None && columnOptions =!= None,
    (* else add row labels *)
    Dynamic[
     tmp = 
      SortBy[Transpose[Join[{labels}, Transpose[data]]], #[[i]] &];
     Deploy@Grid[
       Join[
        {Join[{EventHandler["     ", {"MouseClicked" :> (i = 1)}]}, 
          Table[With[{j = j}, 
            EventHandler[
             headings[[j]], {"MouseClicked" :> (i = j + 1)}]], {j, 
            columns}]]}, tmp],
       gridOptions],
     TrackedSymbols :> {i}]
    ]
   ];

Now a test showing the use of table headings:

data2 = RandomInteger[{1, 20}, {5, 4}];

(* some Grid options *)

opts = {Background -> {None, {GrayLevel[0.75], {White, 
       GrayLevel[0.9]}}},
   BaseStyle -> Directive[FontFamily -> "Helvetica", 11],
   Dividers -> {{GrayLevel[1], {GrayLevel[.9]}, 
      GrayLevel[1]}, {GrayLevel[.2], GrayLevel[.2], {False}, 
      GrayLevel[.2]}},
   Alignment -> {{Left, {Right}}},
   ItemSize -> {{6, {7}}},
   ItemStyle -> {{Directive[FontFamily -> "Helvetica", Bold, 
       12]}, {Directive[FontFamily -> "Helvetica", 
       12], {1 -> 
        Directive[FontFamily -> "Helvetica", Bold, 13, White]}}},
   Spacings -> {1, 1}};

enter image description here

In this version I did not sort on the first column but that can be added.

$\endgroup$
1
  • $\begingroup$ Above and beyond. Thank you. $\endgroup$ Apr 1, 2016 at 1:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.