8
$\begingroup$

I am trying to write the code for doing the following:

  1. by clicking a button, import specific data from an Excel file which I select through a dialog window;
  2. input a name for the imported data set through an input field;
  3. store the imported data permanently under the given name (for example a variable with that name), so that I don't have to import it again next time I open Mathematica;
  4. repeat 1. - 3. , etc.

The idea is to be able to have several data sets imported from several Excel files, assign specific names to them and store all of them inside the notebook permanently.

Could someone please guide me to achieve this?

$\endgroup$
8
  • 1
    $\begingroup$ Conrad, could you share what you attempted? Typically questions are better received here if you show your initial efforts, rather than just asking for somebody to code your task for you. $\endgroup$
    – MarcoB
    Jun 30, 2015 at 14:23
  • $\begingroup$ @MarcoB yes, of course, sorry... ClearAll; InitializationCell; ExcelFile = SystemDialogInput["FileOpen"] impdatas = {}; AppendTo[impdatas, Import[ExcelFile, {"Data", 5, Table[i, {i, 4, 24}], {1, 2}}]] $\endgroup$
    – Conrad
    Jun 30, 2015 at 14:34
  • $\begingroup$ Have you also looked to similar posts by typing in the search box (right up corner) "Import excel" ? $\endgroup$
    – SquareOne
    Jun 30, 2015 at 14:38
  • $\begingroup$ Do you want to keep the data in the notebook, or a separate external file? You may want to look at Put and Get. $\endgroup$ Jun 30, 2015 at 14:41
  • $\begingroup$ As I wrote, I would like to keep the data in the notebook, for portability reasons. $\endgroup$
    – Conrad
    Jun 30, 2015 at 14:42

2 Answers 2

5
$\begingroup$

My approach to this task would be to create new Input Cells within the notebook, that have the same structure as newly typed in symbol definition.

createNewSymbol[] :=
 Module[{importFileName = SystemDialogInput["FileOpen", ".txt"]},
  With[{importedData = If[StringQ@importFileName, Import[importFileName, "Table"]],
        symName = If[StringQ@importFileName, Input["Enter Symbol Name"]]},
   If[ListQ@importedData && ! MatchQ[symName, $Canceled], 
    CellPrint@ExpressionCell[Defer[symName = importedData;], "Input", 
      InitializationCell -> True]];
   If[StringQ@importFileName, createNewSymbol[]];
   ]]

Button["Create New Symbols with Imported Data", createNewSymbol[], Method -> "Queued"]

I used the following .txt files for testing

Export["aTest.txt", RandomInteger[10, 100]];
Export["bTest.txt", RandomReal[1, 100]];
Export["cTest.txt", RandomPrime[100, 100]];

therefore you will have to adapt my code for your Excel files.

$\endgroup$
5
  • $\begingroup$ @Karsten.7 Testing the code I observed that, after closing the file and re-opening it, the variables created (I named them a, b and c) are empty... $\endgroup$
    – Conrad
    Jul 1, 2015 at 9:09
  • $\begingroup$ @Conrad After re-opening the notebook file there still should be the created Input Cells (e.g., something like a={{3}, {5}, ...}). After evaluation of these cells the variables shouldn't be empty. No values are set before evaluating these variable definitions, but all information is stored in the notebook file and no new import is needed. I thought that's what you wanted. $\endgroup$
    – Karsten7
    Jul 1, 2015 at 10:38
  • $\begingroup$ @Conrad If you prefer that the values are set after opening the notebook without the need to explicitly evaluate the cells, you could right-click on the cell bracket and select Initialization Cell. $\endgroup$
    – Karsten7
    Jul 1, 2015 at 10:42
  • $\begingroup$ @Karsten.7 This was exactly my intention: after opening the file again to have the last created symbols set with the corresponding values, without needing to re-evaluate the (resulted) cell. Can I add in the code a specific InitializationCell for the resulting cell for that? $\endgroup$
    – Conrad
    Jul 2, 2015 at 15:48
  • 1
    $\begingroup$ @Conrad Yes, see my edit. I added InitializationCell -> True as an option for ExpressionCell. $\endgroup$
    – Karsten7
    Jul 2, 2015 at 16:11
7
$\begingroup$

it is not etirely clear for what you need that, but I think the best way to store data within a Notebook so that it is available in the next session is the TaggingRules option. This is how you could store data for a there:

 CurrentValue[EvaluationNotebook[],{TaggingRules,"dataset-name"}] = data;

And this is how you can read it:

 data = CurrentValue[EvaluationNotebook[],{TaggingRules,"dataset-name"}];

for most applications it will be fast enough to just use that. To make it more convenient you could define e.g.:

saveDataset[name_String,data_] := saveDataset[name_String,data_] := (
  CurrentValue[EvaluationNotebook[],{TaggingRules,name}] = data
);
getDataset[name_String] := (
  CurrentValue[EvaluationNotebook[],{TaggingRules,name}]
);

if the access via frontend would be too slow you could cache the data in the kernel:

getDataset[name_String] := getDataset[name] = (
  CurrentValue[EvaluationNotebook[],{TaggingRules,name}]
);

but that would mean you should also redefine when the data changes, so you'll also need to update the cached value if a dataset ever should change:

saveDataset[name_String,data_] := (
  getDataset[name] = 
    CurrentValue[EvaluationNotebook[],{TaggingRules,name}] = data;
);
$\endgroup$

Your Answer

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

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