Sign up ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

The common problem in my work is a need to import some experimental data to work with. This means that my notebook depends on some external files which makes it difficult to share it with others and inconvenient when I return to it after time.

What I wish is to have a way to store the data inside the Notebook in collapsible CellGroups in order to have an ability to view the data in human-readable tabular form and to re-import the data file manually if I change it.

Generally, the data inside of the notebook should look as on the screenshot:


The output Сells are regenerated by pressing Shift + Enter when the data files change. What I need is a way to retrieve the data sets from the output cells in the section "The data cells". Something like this:

dataSet1 = getData["Data set 1"];
dataSet2 = getData["Data set 2"];

where "Data set 1" and "Data set 2" are the text strings in the Subsubsection cells from the section "The data cells".

How to achieve this?

share|improve this question
No finished product, but I´d use a Button to import the data and generate an assignment cell that is output below that. – Yves Klett Apr 11 '13 at 7:10
I don't understand very well. You have written "The output cells are regenerated manually when the data files change". Do you confirm the word "manually" or is it a error ? – andre Apr 11 '13 at 12:24
@andre Yes, the output cells with the data will be generated manually by evaluating the above "Input" cells with the Import statements as showed on the screenshot. – Alexey Popkov Apr 11 '13 at 12:58
@andre Probably the word "manually" is not the best choice. I just mean that the cells with Import statements must not be Initialization cells because I wish do not depend on the external files. At the same time, if the external files are changed it should be possible to regenerate the cells with the data by Importing the external files. So the output cells are generated automatically by Mathematica but manually in the sence that they are not Initialization cells. Sorry for confusion. – Alexey Popkov Apr 11 '13 at 13:05

5 Answers 5

I use buttons for this purpose. Imagine that your data is stored in a variable called data. Then you can do the following:

With[{i = Compress[data]}, 
  Button["Retrieve Data", data = Uncompress[i]; 
  Print[Style["Data has successfully been loaded into variable \"data\"",Blue,Italic,14]]]

This creates a button. When pressed, data is populated with your original data.

A warning: If you have a separate variable data already as part of your notebook, it will be overwritten.

An alternative:

Create initiialization cells somewhere in your notebook containing

data1 = <your data 1>;
data2 = <your data 2>;

To save space you can also do

data1 = Uncompress[Compress[<your data 1>]];

Then, highlight Compress[<your data 1>] and evaluate it in place (Ctrl-Shift-Enter)

share|improve this answer
You might also mention that the data is stored across sessions because of the way Button works. – Yves Klett Apr 11 '13 at 11:05
@YvesKlett That's right. In fact, you can select the cell containing the button, and press Ctrl-Shift-E to see the underlying Cell code. you will see the (compressed version of) your data there. That's the reason why you need the With[...] construct, without it, it would not work. – Thomas Apr 11 '13 at 11:11
@Thomas As I stated in the question, I wish to store data in readable form, as tables. I need not to compress it since the data have small size. – Alexey Popkov Apr 11 '13 at 11:56
@AlexeyPopkov you can simply print out data as well within the same With. – Yves Klett Apr 11 '13 at 13:04
I know it but the goal is to store data in obvious and readable form, not just to display them. And at the same time the cells with the data should be generated by Importing external files. – Alexey Popkov Apr 11 '13 at 13:16

I put in a defer because of your question here. Maybe you have symbols in your data and this will be useful, who knows. getData succesfully gets the data from the generated cell.

int = 1;
  {string = "@#$kill me" <> ToString[int]}
  NotebookDelete[Cells[CellTags -> string]]; 
    Defer[{{1 + 1, 2}, {1 + 1, 2}, {1 + 1, 2}} // TableForm], 
    "Output", GeneratedCell -> True, Evaluatable -> True, 
    CellTags -> string]]

getDataHeldComplete[int_] := 
  {string = "@#$kill me" <> ToString[int]}
  MakeExpression @@ {NotebookRead[Cells[CellTags -> string][[1]]][[
     1]], StandardForm}

getData[int_] := getDataHeldComplete[1][[1]];

Then evaluate evaluate in a new cell

share|improve this answer

You may use TableForm (you're already using this), CellTags, NotebookLocate, and NotebookRead to do this.

For your Import "Output" cell add a CellTag that will be your reference.

  ImportString["1,2,3,4,5,6,7,8,9", "CSV"] // TableForm,
  CellTags -> "Data1"]]

This can be re-executed at any time going forward without having to manually adjust. Of course you will use Import and not ImportString.

The cell can be located in the notebook with NotebookLocate and its contents read with NotebookRead. When this is done you will see that the data is in a GridBox command. getCellTableFormData finds the first occurrence of this and returns the first argument; which is the data array.

getCellTableFormData[tag_String] :=
  With[{cell = NotebookRead[EvaluationNotebook[]]},
   ToExpression@First@Extract[cell, FirstPosition[cell, GridBox[__]]]

Now getCellTableFormData can be used to assign a variable to the data collected from the tagged cell of TableForm output.

dat = getCellTableFormData["Data1"]
(* {{"1", "2", "3", "4", "5", "6", "7", "8", "9"}} *)

Even after you close and reopen the notebook the tagged cell is still there. So all that is need is to run the getCellTtableFormData definition (initialisation cell or a package) so that the variables can be set from the tagged cell data.

Hope this helps.


Here is a version that does not change the selected cell to the tagged cell when the data is assigned to the variable. It is also a more concise.

getCellTableFormData2[tag_String] :=
 With[{cell = NotebookRead@First@Cells[CellTags -> tag]},
  ToExpression@First@Extract[cell, FirstPosition[cell, GridBox[__]]]

It does not use NotebookLocate which sets the selected cell to the tagged cell.

share|improve this answer
I appreciate the idea but the NotebookLocate method opens closed CellGroup containing the Cell with the data what is not appropriate. Both the CellGroup with initialization Cell and the CellGroup with the data Cells should remain closed in the course of initialization. – Alexey Popkov Sep 19 at 12:07
@AlexeyPopkov I've added another version that does not use NotebookLocate. See update. I added a 2 onto the name so don't forget to change the call. Maybe I should not have done that. – Edmund Sep 19 at 12:09
(+1) Yes, the Cells method works as desired. I think that CellID is even better than CellTags for my purpose because two Cells with the same CellID are not allowed. The only problem is that the Cells function is absent in version 8 with which I still have to work because of insufficiently stable FrontEnds of versions 9 and 10. – Alexey Popkov Sep 19 at 12:19
Both your solutions extract numbers as Strings. Instead of First@Extract[...] one can use ToExpression[cell[[1]]] for extraction numbers as numbers. – Alexey Popkov Sep 19 at 12:31
CellID is only guaranteed to be unique when created by the Wolfram System. You are programming the notebook so you can be certain that the CellTags do not repeat for your data cells. Does CellID persist on closing and reopening the notebook? If they do then you might need to set negative number ids to be certain that the ids generated when executing the notebook don't overlap. – Edmund Sep 19 at 12:33

Are you aware that you can write data= before your table and evaluate ? :

enter image description here

share|improve this answer
up vote 1 down vote accepted

Here is the solution which I currently use. It isn't perfect but serves quite well for my purposes.

In the Notebook I define an auxiliary function which takes a variable where a data array is stored and prints an initialization Cell with two-dimensional human-readable representation of that array which will be assigned to the input variable on initialization:

SetAttributes[printInitCell, HoldAll];
printInitCell[array_] := 
    BoxData[RowBox[{ToString[Unevaluated[array]], "=", 
       GridBox[Map[ToBoxes, array, {-1}], 
        GridBoxFrame -> {"Columns" -> {{True}}, "Rows" -> {{True}}}], ";"}]], "Output", 
    InitializationCell -> True, Evaluatable -> True];

Here is an example of use:

dataset1 = Prepend[RandomReal[1, {5, 3}], {"Head1", "Head2", "Head3"}];


It is important that after initialization the variable dataset1 contains two-dimensional array which is not wrapped by Grid:


The only drawback of this approach is that when I need to re-generate the initialization Cell, I have to remove the previous Cell manually.


With AutoIndent -> False and the variable placed above the data table the data Cells are more readable:

SetAttributes[printInitCell, HoldAll];
printInitCell[array_] := 
    BoxData[RowBox[{ToString[Unevaluated[array]], " ", "=", " ", "\n", 
       GridBox[Map[ToBoxes, array, {-1}], 
        GridBoxFrame -> {"Columns" -> {{True}}, "Rows" -> {{True}}}, 
        BaseStyle -> (FontWeight -> Plain)], ";"}]], "Output", InitializationCell -> True,
     Evaluatable -> True, AutoIndent -> False, Background -> GrayLevel[0.95], 
    FontWeight -> Bold];




Here is Mathematica 8 - compatible solution which auto-overwrites previous version of the data Cell (if present) before printing of the new version.

At first, it checks whether the next Cell is a previous version by comparing the CellTags. If the latter is true it sets the Evaluatable -> False option what turns on automatic overwriting. Then it prints the new version and collapses the CellGroup hiding everything except to the newly printed initialization cell.

SetAttributes[printInitCell, HoldAll];
printInitCell[var_] := With[{tag = ToString[Unevaluated[var]], nb = EvaluationNotebook[]},
   SelectionMove[nb, After, EvaluationCell, AutoScroll -> False];
   SelectionMove[nb, Next, Cell, AutoScroll -> False];
   If[CurrentValue[NotebookSelection[], CellTags] === {tag, "CellType=DataCell"}, 
    SetOptions[NotebookSelection[], Evaluatable -> False]];
      RowBox[{ToString[Unevaluated[var]], " ", "=", " ", "\n", 
        GridBox[Map[ToBoxes, var, {-1}], 
         GridBoxFrame -> {"Columns" -> {{True}}, "Rows" -> {{True}}}, 
         BaseStyle -> (FontWeight -> Plain)], ";"}]], "Output", 
     InitializationCell -> True, Evaluatable -> True, AutoIndent -> False, 
     Background -> GrayLevel[0.95], FontWeight -> Bold, 
     CellTags -> {tag, "CellType=DataCell"}];
   SelectionMove[nb, Previous, Cell];
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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