MATLAB Answers

Create variable from an excel entry

21 views (last 30 days)
Victor Saouma
Victor Saouma on 12 Sep 2019
Answered: 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)

Answers (4)

Bob Thompson
Bob Thompson 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.
  4 Comments
Stephen Cobeldick
Stephen Cobeldick on 13 Sep 2019
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.


MA
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
Plot.MarkerSize=xlsread('filename.xlsx',1,'B2');
[n_data, Plot.MarkerColor, all_data] = xlsread('filename.xlsx',1,'B3')
  1 Comment
Bob Thompson
Bob Thompson on 12 Sep 2019
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)]);
end
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.


Stephen Cobeldick
Stephen Cobeldick on 13 Sep 2019
Edited: 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 =
20
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!

Steven Lord
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.
Plot.Shift=20;
Plot.MarkerSize=6;
Plot.MarkerColor='black';
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

Products


Release

R2019a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!