Use cell array contents to name new cell array
11 views (last 30 days)
Show older comments
David du Preez
on 25 Jun 2018
Edited: Walter Roberson
on 25 Jun 2018
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
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.
Accepted Answer
More Answers (1)
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
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
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.
See Also
Categories
Find more on Spreadsheets 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!