1 ## Copyright (C) 2009,2010,2011,2012 Philip Nienhuis <prnienhuis at users.sf.net>
3 ## This program is free software; you can redistribute it and/or modify it under
4 ## the terms of the GNU General Public License as published by the Free Software
5 ## Foundation; either version 3 of the License, or (at your option) any later
8 ## This program is distributed in the hope that it will be useful, but WITHOUT
9 ## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 ## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 ## You should have received a copy of the GNU General Public License along with
14 ## this program; if not, see <http://www.gnu.org/licenses/>.
17 ## @deftypefn {Function File} [ @var{numarr}, @var{txtarr}, @var{lim} ] = parsecell (@var{rawarr})
18 ## @deftypefnx {Function File} [ @var{numarr}, @var{txtarr}, @var{lim} ] = parsecell (@var{rawarr}, @var{limits})
20 ## Divide a heterogeneous 2D cell array into a 2D numeric array and a
21 ## 2D cell array containing only strings. Both returned arrays are
22 ## trimmed from empty outer rows and columns.
23 ## This function is particularly useful for parsing cell arrays returned
24 ## by functions reading spreadsheets (e.g., xlsread, odsread).
26 ## Optional return argument @var{lim} contains two field with the outer
27 ## column and row numbers of @var{numarr} and @var{txtarr} in the
28 ## original array @var{rawarr}.
29 ## Optional input argument @var{limits} can either be the spreadsheet
30 ## data limits returned in the spreadsheet file pointer struct
31 ## (field xls.limits or ods.limits), or the file ptr struct itself.
32 ## If one of these is specified, optional return argument @var{lim}
33 ## will contain the real spreadsheet row & column numbers enclosing
34 ## the origins of the numerical and text data returned in @var{numarr}
40 ## [An, Tn] = parsecell (Rn);
41 ## (which returns the numeric contents of Rn into array An and the
42 ## text data into array Tn)
46 ## [An, Tn, lims] = parsecell (Rn, xls.limits);
47 ## (which returns the numeric contents of Rn into array An and the
48 ## text data into array Tn.)
51 ## @seealso {xlsread, odsread, xls2oct, ods2oct}
55 ## Author: Philip Nienhuis
56 ## Created: 2009-12-13
59 ## 2010-08-25 Added option for second argument to be a file ptr
60 ## 2010-10-15 Simplified code for numerical array
61 ## 2011-05-17 Fixed subscript indexing bug in cropping section when rawarr is
63 ## 2011-09-08 Copyright string updated
64 ## 2012-01-26 Fixed "seealso" help string
66 function [ numarr, txtarr, lim ] = parsecell (rawarr, arg2=[])
69 # Assume a file ptr has been supplied
70 if (isfield (arg2, 'limits'))
71 rawlimits = arg2.limits;
73 warning ("Invalid file ptr supplied to parsecell() - limits ignored.");
79 lim = struct ( "numlimits", [], "txtlimits", []);
84 if (~isempty (rawarr))
85 # Valid data returned. Divide into numeric & text arrays
86 no_txt = 0; no_num = 0;
87 if (isnumeric ([rawarr{:}]))
88 numarr = num2cell (rawarr);
90 elseif (iscellstr (rawarr))
91 txtarr = cellstr (rawarr);
95 [nrows, ncols] = size (rawarr);
97 # Find text entries in raw data cell array
98 txtptr = cellfun ('isclass', rawarr, 'char');
100 # Prepare text array. Create placeholder for text cells
101 txtarr = cell (size (rawarr));
103 if (any (any (txtptr)))
104 # Copy any text cells found into place holder
105 txtarr(txtptr) = rawarr(txtptr);
106 # Clean up text array (find leading / trailing empty
109 while (~any (txtptr(irowt, :))) irowt++; endwhile
111 while (~any (txtptr(irowb, :))) irowb--; endwhile
113 while (~any (txtptr(:, icoll))) icoll++; endwhile
115 while (~any (txtptr(:, icolr))) icolr--; endwhile
117 txtarr = txtarr(irowt:irowb, icoll:icolr);
118 lim.txtlimits = [icoll, icolr; irowt, irowb];
119 if (~isempty (rawlimits))
121 lim.txtlimits (:,1) = lim.txtlimits(:,1) + rawlimits(:,1) - correction;
122 lim.txtlimits (:,2) = lim.txtlimits(:,2) + rawlimits(:,1) - correction;
125 # If no text cells found return empty text array
131 # Prepare numeric array. Set all text & empty cells to
132 # NaN. First get their locations
133 emptr = cellfun ('isempty', rawarr);
134 emptr(find (txtptr)) = 1;
135 if (all (all (emptr)))
138 # Find leading & trailing empty rows
140 while (all(emptr(irowt, :))) irowt++; endwhile
142 while (all(emptr(irowb, :))) irowb--; endwhile
144 while (all(emptr(:, icoll))) icoll++; endwhile
146 while (all(emptr(:, icolr))) icolr--; endwhile
149 rawarr = rawarr (irowt:irowb, icoll:icolr);
150 # Build numerical array
151 numarr = zeros (irowb-irowt+1, icolr-icoll+1);
152 # Watch out for scalar (non-empty) numarr where emptr = 0
153 if (sum (emptr(:)) > 0)
154 numarr (emptr(irowt:irowb, icoll:icolr)) = NaN;
156 numarr(~emptr(irowt:irowb, icoll:icolr)) = cell2mat (rawarr(~emptr(irowt:irowb, icoll:icolr)));
158 lim.numlimits = [icoll, icolr; irowt, irowb];
159 if (~isempty (rawlimits))
161 lim.numlimits(:,1) = lim.numlimits(:,1) + rawlimits(:,1) - correction(:);
162 lim.numlimits(:,2) = lim.numlimits(:,2) + rawlimits(:,1) - correction(:);
167 lim.rawlimits = rawlimits;