MATLAB Answers


Create variable from an excel entry

Asked by Victor Saouma on 12 Sep 2019
Latest activity Answered by Steven Lord
on 13 Sep 2019
I have an excel file say 3 rows 2 columns such as
I want to read this file with Matlab and then define a new structure data such that
Plot.Shift=20; Plot.MarkerSize=6; and Plot.MarkerColor='black
so I can use them in my subsequent code (i.e. should be able to do also operations such as Plot.Shift+Plot.Shift=40)


Sign in to comment.




4 Answers

Answer by Bob Nbob
on 12 Sep 2019

Hmm, I normally wouldn't recommend anybody do this, and others might still disagree, but I think eval will do what you're looking for. Just load the excel values as strings instead of actual values and then combine as appropriate before using eval.
I do not recommend doing this to create a large group of sequential variables. I can understand the use for creating different fields in a structure, but I strongly recommend against using it to create large groups of variables, instead of putting data into arrays.


Show 1 older comment
Yeah, I saw that, which is why I think it's a reasonably justified application of eval, I just have to give the standard warning as well. What I'm trying to deter you from though is not setting all of the plot settings, but avoiding doing something like:
eval('y1 = 1;')
eval('y2 = 2;')
eval('y3 = 3;')
because it would simply be more efficient to set y = [1;2;3] instead of creating multiple variables.
That being said, because you're looking at having 10-15 different values for each of the settings, I would probably recommend still using a regular array. This will help prevent problems if you end up with a misnamed variable or the like.
[~,~,data] = xlsread('filename.xlsx');
for i = 1:size(data,2)
Plot.Shift = data{2,i};
Plot.MarkerSize = data{3,i};
Plot.MarkerColor = data{4,i};
Sure, this was my first attempt, but I then lose the flexibility of adding variables "on the fly" I do not want to be constrained to have a set order for the variables in the excel file
Advice to use eval fails to consider the problem of how the variable Plot will actually be used in the code, and fails to consider the risks of overwriting/shadowing any variable or function.
Consider the situation that those names instead start with MyPlot, either intentionally or otherwise. Then you run your code, everything works fine.. .until you get an error on the first line where you refer to the (very badly named) variable Plot, which clearly does not exist. An error is thrown five hundred lines later, at an unrelated point in the code where the user will think "but this line has always worked... what is the problem?". There will be no particular help from eval nor from any static code checking, because actually the code is doing exactly what it was written to do: import that data into a magically-named variable. Such code is buggy by design.
Consider if the names are plot instead of Plot... what would happen when you then try to call the plot function? This is exactly why code should never rely on the users data for its correct operation: it would be trivial to store the string 'plot' as data in some variable, and the rest of the code would work perfectly. But code that uses eval can overwrite/shadow anything. Such code is buggy by design.
There are two situations to consider:
  1. The Plot name is always the same (or should be): in this case there is no point in magically creating a variable, because the Plot variable can easily be created as a normal structure (sans eval) in the code and then the file's fields are simply added to that structure. Also any name/field/data checks can be trivially made at that point.
  2. The Plot name changes between files: in this case the name encodes meta-data. Meta-data is data. Data should be stored in variables, not in variable names. Once again a structure would neatly hold this data: the Plot name (or whatever it might be called), and then the fieldname and data. Using eval in this case is almost entirely pointless: what am I supposed to do with a structure named Xs632k if I cannot refer to it explicitly in my code? To refer to it requires magically accessing variables in the workspace... and so the bad code continues...
Using eval just hides bugs in the code, it is not a solution.

Sign in to comment.

Answer by MA
on 12 Sep 2019

% you may need something like the following
Plot.Shift=xlsread('filename.xlsx',1,'B1'); %file name, row number, column number
[n_data, Plot.MarkerColor, all_data] = xlsread('filename.xlsx',1,'B3')

  1 Comment

You would be able to use the second output of xlsread though to capture the field name as well though and could loop through all of the fields in a single loop, instead of needing to name them specifically.
[~,data,~] = xlsread('filename.xlsx');
for i = 2:size(data,1)
eval([data(i,1),' = ',data(i,2)]);
Using this method is generally frowned upon though to make multiple variables that are a series (i.e. y1 = 1, y2 = 2, y3 = 3).

Sign in to comment.

Answer by Stephen Cobeldick on 13 Sep 2019
Edited by Stephen Cobeldick on 13 Sep 2019

This should get you started (note that I named the variable out rather than Plot, as it is bad practice to use names which only differ in character-case from an existing function/variable name):
>> [~,~,raw] = xlsread('test.xlsx');
>> fld = regexp(raw(2:end,1),'(?<=^Plot\.)\w+$','once','match');
>> out = cell2struct(raw(2:end,2),fld,1)
out =
Shift: 20
MarkerSize: 6
MarkerColor: 'black'
Note that the order of the fields in the file is irrelevant:
>> out.Shift
ans =
Note that you can easily add checks on the Plot name/field/data, as required, or allow for names other than Plot. Ask if you want help with any of this!


Sign in to comment.

Answer by Steven Lord
on 13 Sep 2019

Are you required to store this data in an Excel spreadsheet? I'd prefer storing this in a plain text file.
If you were to do this, you could even give it an extension other than .txt -- perhaps the extension .m?
Alternately if you do need to store this in a spreadsheet, storing it without the "Plot." prefix would make your task easier. Read the data into a string array or cell array of text and use dynamic field names to construct your struct array using the element of the string or cell array.
myPlot = struct();
name = 'Shift';
value = 20;
myPlot.(name) = value


Sign in to comment.