5
$\begingroup$

I have written the following code to generate the table that is shown below.

(* Titles and colors *)
TableFormatting[headers_,data_] := 
 DynamicModule[{rows=Range@Length@data,cols=Flatten@{"",headers}}, 
  Grid[Prepend[Transpose@Prepend[Transpose@data,rows],cols], 
   Frame->All, FrameStyle->GrayLevel[.9],Alignment->{Center,Center}, 
   Background->{{GrayLevel[0.8],None},{GrayLevel[0.8],None}}, Spacings->{2,Automatic}]]

(* InputFields and buttons to add/remove rows *)
table[titles_, initData_] := 
 Manipulate[TableFormatting[titles,Array[
  InputField[Dynamic[mat[[#1,#2]]],FieldSize->{{2.5,\[Infinity]},{1,\[Infinity]}}]&,Dimensions[mat]]], 
  {{mat, initData}, ControlType->None}, 
  ButtonBar[{" + ":>AppendTo[mat,Null&/@Range[Length[titles]]]," - ":>If[Dimensions[mat][[1]]>1,mat=Delete[mat,-1]]}],ControlPlacement->Right]

(* Example *)
table[{"Title1","Title2","Title3","Title4"},{{a,b,c,d},{1,2,3,4},{x,y,z,w}}]

enter image description here

However, I would like to improve it to auto-adjust the width of the InputFields so that all the cells in a column get resized to the width of the longest input in that column. e.g. In this picture, the width of the "xxxxxxxxx" cell should define the width of all the fields in that column.

enter image description here

$\endgroup$

2 Answers 2

3
$\begingroup$
ClearAll[fieldSize, table2]
fieldSize[m_ : 2.5, h_ : 1] := 
  {{Max[{Map[StringLength @* ToString, #, {-1}] CurrentValue[
    "ControlsFontSize"]/CurrentValue["FontMWidth"], m}], ∞}, {h, ∞}} &

table2[titles_, initData_] := 
  Manipulate[TableFormatting[titles, 
    Array[
       InputField[Dynamic[mat[[#1, #2]]], 
         FieldSize -> fieldSize[] @ mat[[All, #2]]] &, 
       Dimensions[mat]]],
    {{mat, initData}, ControlType -> None}, 
    ButtonBar[{" + " :> AppendTo[mat, Null & /@ Range[Length[titles]]], 
      " - " :> If[Dimensions[mat][[1]] > 1, mat = Delete[mat, -1]]}], 
    ControlPlacement -> Right]

Examples:

table2[{"Title1", "Title2", "Title3", "Title4"},
  {{a, b, c, d}, {1, 2, 3, 4}, {x, y, z, w}}]

enter image description here

Edit to replace 2 with 222222 and z with zzzzzzzzzzzz:

enter image description here

Add another row:

enter image description here

Delete the last 2 rows:

enter image description here

$\endgroup$
3
  • 1
    $\begingroup$ @JuanC97, please try the updated version. $\endgroup$
    – kglr
    Feb 11 at 1:18
  • 1
    $\begingroup$ It works smoothly @kglr, thanks a lot. Also, StringLength works exponentially better than Rasterize. That was a nice idea. $\endgroup$
    – JuanC97
    Feb 12 at 22:28
  • $\begingroup$ I included a factor of 0.6 here: (0.6)CurrentValue["ControlsFontSize"]/CurrentValue["FontMWidth"]. It seems to fit a little bit better the contents of the boxes after clicking out of the table. Do you experience the same behaviour? $\endgroup$
    – JuanC97
    Feb 12 at 22:31
1
$\begingroup$
InputField[x, FieldSize -> n]

And compute the FieldSize based on your inputs.

$\endgroup$
1
  • $\begingroup$ Following your comment and taking into account that the widths of the inputs may change, I've computed the max width per column using community.wolfram.com/groups/-/m/t/1862449 (up to a factor of 1/3 or so, to convert from pixels to ems). However, FieldSize seems to fail to auto-adjust the widths of the columns based on the user's input because of the way Dynamic[] is called in my previous code (note that it'd only lets us modify the width of the cell where the user is writing). $\endgroup$
    – JuanC97
    Aug 15, 2023 at 0:05

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.