Use cell array contents to name new cell array

13 views (last 30 days)
I can import data from an excel file with 58 sheets. Each sheet has a different number of rows.
%Gives sheet names and rows with data
[~,sheet_name]=xlsfinfo('Teco.xlsx');
for k=1:numel(sheet_name);
data{k}=xlsread('Teco.xlsx',sheet_name{k});
end
%Import data from specific sheet and only show rows with data
for i=4:58;
[~,~,raw]=xlsread('Teco.xlsx',sheet_name{i},'B:C');
raw(any(cellfun(@(x) any(isnan(x)),raw),2),:) = [];
end
The cell array "sheet_name" gives the name of each sheet and the cell array "raw" gives the data from each sheet.
I want to rename the cell array "raw" using the contents of the "sheet_name" so that the data is not written over within each loop.
  1 Comment
Stephen23
Stephen23 on 25 Jun 2018
Edited: Stephen23 on 25 Jun 2018
"I want to rename the cell array "raw" using the contents of the "sheet_name" so that the data is not written over within each loop."
Dynamically naming/accessing variable names is one way that beginners force themselves into writing slow, complex, buggy code that is hard to debug. For example note that worksheets names are not necessarily valid variable names, so your code would be susceptible to bugs even though the Excel workbook is perfectly okay. For this and other reasons, dynamically naming/accessing variables is not recommended. You can read this to know why:
Much simpler, easier, more efficient, and less buggy is to use indexing. You can easily use indexing.

Sign in to comment.

Accepted Answer

Walter Roberson
Walter Roberson on 25 Jun 2018

More Answers (1)

Stephen23
Stephen23 on 25 Jun 2018
Edited: Stephen23 on 25 Jun 2018
It is much simpler to use indexing:
%Gives sheet names and rows with data
[~,sheets] = xlsfinfo('Teco.xlsx');
N = numel(sheets);
data = cell(1,N); % preallocate.
for k = 1:N
data{k} = xlsread('Teco.xlsx',sheets{k});
end
%Import data from specific sheet and only show rows with data
out = cell(1,N-3);
for k = 1+3:N
[~,~,raw] = xlsread('Teco.xlsx',sheets{i},'B:C');
raw(any(cellfun(@(x) any(isnan(x)),raw),2),:) = [];
out{k-3} = raw;
end
Note that it is not robust to assume anything about the order of the sheets: hidden sheets and changes to the sheet order could easily break your code. You could filter the sheets names, e.g. using regexp or strncmp or the like.
  2 Comments
Steven Lord
Steven Lord on 25 Jun 2018
A similar but slightly different approach to Stephen's suggestion is to store the data in a struct array where each field name is based on the name of the sheet.
Use matlab.lang.makeValidName and matlab.lang.makeUniqueStrings to ensure the sheet names are converted to unique valid identifiers as per the first example on the Tips section of the documentation for matlab.lang.makeValidName.
Walter Roberson
Walter Roberson on 25 Jun 2018
Edited: Walter Roberson on 25 Jun 2018
I think it was a mistake for Mathworks to hide the variable name handling down in matlab.lang.* where you have to pretty much already know the full three-component identifier in order to find the functionality. I tend to think of matlab.* routines as being either internal or as "okay, we documented them, but you probably should not count on them; we do not recommend that you use them."
I am also not convinced that it properly belongs in the matlab.lang namespace, but I guess that is arguable.
>> lookfor makevalidname
genvarname - will be removed in a future release. Use MATLAB.LANG.MAKEVALIDNAME and MATLAB.LANG.MAKEUNIQUESTRINGS instead.
lookfor doesn't even find the routine itself -- and MATLAB is case sensitive so those are the wrong routine names to cite.

Sign in to comment.

Categories

Find more on Cell Arrays in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!