# Saving data directly in notebooks

Posted 4 years ago
11791 Views
|
8 Replies
|
19 Total Likes
|
 Do you ever wish you could save data directly into a notebook instead of having to export it? I sometimes do things like mydata = {1,2,3, ...}; just to be able to use this data next time I open the notebook. This could be data I pasted from the web, or something that just took several minutes to generate.But saving it like this is inconvenient, and often takes up a lot of space.Today I published a blog post about a better method that I have been using recently. I thought people here may be interested: The idea is to use first Compress the data, then use Interpretation to create a compact display for it. Here's a small function that packages all of this up: ClearAll[SaveToCell] SaveToCell::usage = "SaveToCell[variable] creates an input cell that reassigns the current value of variable.\n" <> "SaveToCell[variables, display] shows 'display' on the right-hand-side of the assignment."; SetAttributes[SaveToCell, HoldFirst] SaveToCell[var_, name : Except[_?OptionQ] : "data", opt : OptionsPattern[]] := With[{data = Compress[var], panel = ToBoxes@Tooltip[Panel[name, FrameMargins -> Small], DateString[]]}, CellPrint@Cell[ BoxData@RowBox[{ MakeBoxes[var], "=", InterpretationBox[panel, Uncompress[data]], ";" }], "Input", (* prevent deletion by Cell > Delete All Output: *) GeneratedCell -> False, (* CellLabel is special: last occrrence takes precedence, so it comes before opt: *) CellLabel -> "(saved)", opt, CellLabelAutoDelete -> False ] ] If you have your data in the variable var, simply run SaveToCell[var], which will create an input cell that re-assign the value of var. It looks like this:We can also customize the display: var = Range[1000]; SaveToCell[var, Short[var]] Hovering the display will show the date when the data was saved.SaveToCell also takes arbitrary Cell options, and passes them down to the generated cell. Something strange I observed while writing this function is that with some options, such as CellLabel, it is not the first but the last occurrence of the option that takes precedence. Does anyone know why?We can use this functionality to change the cell style, add a different label, or to protect the cell against accidental deletion: SaveToCell[var, Deletable -> False].I have been using this little function for a while, and I hope that others will find it useful too.Do be careful though: notebooks are not designed for storing large data. I would avoid storing data as large as several tens of megabytes within notebooks.
8 Replies
Sort By:
Posted 4 years ago
 Very neat! Thanks for sharing!
Posted 4 years ago
 - Congratulations! This post is now a Staff Pick! Thank you for your wonderful contributions. Please, keep them coming!
Posted 4 years ago
 I think that this functionality should be built into Wolfram Language. It is similar to static variables or #defines in c and other languages.
Posted 4 years ago
 I wonder if a user can make his own iconography thingy like the one in Out[3] in https://reference.wolfram.com/language/ref/TimeSeries.html? It has more features like myFunctionHead[ ] around the icon and the + button, etc.
Posted 4 years ago
 Yes. They are called summary boxes. See here: See István's answer on how to create summary boxes that are just like the builtin ones. This requires using some undocumented things (but I don't expect that to be problematic in this case). See my answer on how to imitate them by using only documented constructs.
Posted 4 years ago
 I forgot to say that when you create summary boxes, you must be extremely careful not to introduce evaluation leaks. Here's a naive way to do it, which will then cause problems: ClearAll[date] date /: MakeBoxes[expr : date[{y_, m_, d_}], form : StandardForm | TraditionalForm] := With[{boxes = ToBoxes[Panel@Grid[{{"year:", y}, {"month:", m}, {"day:", d}}], form]}, InterpretationBox[boxes, expr] ] All good so far.Now let's make a function that creates a date: make2017Date[{m_, d_}] := date[{2017, m, d}] And see its definition:Still looking good. But now define: m = 12; Oops! Evaluation leak!Something much worse could happen too. What if m contains code, like m := Print["Boo!"]?The simple way to fix it is to put checks on your values: date /: MakeBoxes[expr : date[{y_Integer, m_Integer, d_Integer}], ...] := ...