]> Creatis software - CreaPhase.git/blob - octave_packages/io-1.0.19/getusedrange.m
Add a useful package (from Source forge) for octave
[CreaPhase.git] / octave_packages / io-1.0.19 / getusedrange.m
1 ## Copyright (C) 2010,2011,2012 Philip Nienhuis <pr.nienhuis@users.sf.net>
2 ##
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
6 ## version.
7 ##
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
11 ## details.
12 ##
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/>.
15
16 ## -*- texinfo -*-
17 ## @deftypefn {Function File} [ @var{toprow#}, @var{bottomrow#}, @var{leftcol#}, @var{rightcol#} ] = getusedrange (@var{spptr}, @var{shindex#})
18 ## Find occupied data range in worksheet @var{shindex#} in a spreadsheet
19 ## pointed to in struct @var{spptr} (either MS-Excel or
20 ## OpenOffice_org Calc).
21 ##
22 ## @var{shindex#} must be numeric and is 1-based. @var{spptr} can either
23 ## refer to an MS-Excel spreadsheet (spptr returned by xlsopen) or an
24 ## OpenOffice.org Calc spreadsheet (spptr returned by odsopen).
25 ## None of these inputs are checked!
26 ##
27 ## Be aware that especially for OpenOffice.org Calc (ODS) spreadsheets 
28 ## the results can only be obtained by counting all cells in all rows;
29 ## this can be fairly time-consuming. Reliable ods data size results can
30 ## only be obtained using UNO interface.
31 ## For the ActiveX (COM) interface the underlying Visual Basic call relies
32 ## on cached range values and counts empty cells with only formatting too,
33 ## so COM returns only approximate (but then usually too big) range values.
34 ##
35 ## Examples:
36 ##
37 ## @example
38 ##   [trow, brow, lcol, rcol] = getusedrange (ods2, 3);
39 ##   (which returns the outermost row & column numbers of the rectangle
40 ##    enveloping the occupied cells in the third sheet of an OpenOffice_org
41 ##    Calc spreadsheet pointedto in struct ods2)
42 ## @end example
43 ##
44 ## @example
45 ##   [trow, brow, lcol, rcol] = getusedrange (xls3, 3);
46 ##   (which returns the outermost row & column numbers of the rectangle
47 ##    enveloping the occupied cells in the third sheet of an Excel
48 ##    spreadsheet pointed to in struct xls3)
49 ## @end example
50 ##
51 ## @seealso {xlsopen, xlsclose, odsopen, odsclose, xlsfinfo, odsfinfo}
52 ##
53 ## @end deftypefn
54
55 ## Author: Philip Nienhuis <philip@JVC741>
56 ## Created: 2010-03-18 (First usable version) for ODS (java/OTK)
57 ## Updates:
58 ## 2010-03-20 Added Excel support (Java/POI)
59 ## 2010-05-23 Added in support for jOpenDocument ODS
60 ## 2010-05-31 Fixed bugs in getusedrange_jod.m
61 ## 2010-08-24 Added support for odfdom 0.8.6 (ODF Toolkit)
62 ## 2010-08-27 Added checks for input arguments
63 ##     ''     Indentation changed from tab to doublespace
64 ## 2010-10-07 Added COM support (at last!)
65 ## 2011-05-06 Experimental support for Java/UNO bridge
66 ## 2011-06-13 OpenXLS support added
67 ## 2011-09-08 Style & layout updates
68 ## 2012-01-26 Fixed "seealso" help string
69 ## 2012-06-08 Replaced tabs by double space
70 ##     ''     Added COM and OXS to message about supported interfaces
71 ##
72 ## Last subfunc update: 2012-06-08 (OTK)
73
74 function [ trow, lrow, lcol, rcol ] = getusedrange (spptr, ii)
75
76   # Some checks
77   if ~isstruct (spptr), error ("Illegal spreadsheet pointer argument"); endif
78
79   if (strcmp (spptr.xtype, 'OTK'))
80     [ trow, lrow, lcol, rcol ] = getusedrange_otk (spptr, ii);
81   elseif (strcmp (spptr.xtype, 'JOD'))
82     [ trow, lrow, lcol, rcol ] = getusedrange_jod (spptr, ii);
83   elseif (strcmp (spptr.xtype, 'UNO'))
84     [ trow, lrow, lcol, rcol ] = getusedrange_uno (spptr, ii);
85   elseif (strcmp (spptr.xtype, 'COM'))
86     [ trow, lrow, lcol, rcol ] = getusedrange_com (spptr, ii);
87   elseif (strcmp (spptr.xtype, 'POI'))
88     [ trow, lrow, lcol, rcol ] = getusedrange_poi (spptr, ii);
89   elseif (strcmp (spptr.xtype, 'JXL'))
90     [ trow, lrow, lcol, rcol ] = getusedrange_jxl (spptr, ii);
91   elseif (strcmp (spptr.xtype, 'OXS'))
92     [ trow, lrow, lcol, rcol ] = getusedrange_oxs (spptr, ii);
93   else
94     error ("Only OTK, JOD, COM, POI, JXL and OXS interface implemented");
95   endif
96
97 endfunction
98
99
100 ## Copyright (C) 2010,2011,2012 Philip Nienhuis, pr.nienhuis -at- users.sf.net
101 ##
102 ## This program is free software; you can redistribute it and/or modify it under
103 ## the terms of the GNU General Public License as published by the Free Software
104 ## Foundation; either version 3 of the License, or (at your option) any later
105 ## version.
106 ##
107 ## This program is distributed in the hope that it will be useful, but WITHOUT
108 ## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
109 ## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
110 ## details.
111 ##
112 ## You should have received a copy of the GNU General Public License along with
113 ## this program; if not, see <http://www.gnu.org/licenses/>.
114
115 ## getusedrange_otk - get used range from ODS spreadsheet using ODF Toolkit
116
117 ## Author: Philip Nienhuis <philip@JVC741>
118 ## Created: 2010-03-18 (First usable version)
119 ## Updates:
120 ## 2010-08-24 Support for odfdom (ODF Toolkit) 0.8.6 checked; we still need 
121 ##            => TableTable API because 0.8.6 is fooled by empty lowermost
122 ##            filler rows comprising number-rows-repeated table attribute :-(
123 ##     ''     Indentation changed from tab to double space
124 ## 2010-11-13 Catched jOpenDocument bug (1.2bx) where string cells have no office:value-type
125 ##            attrib set (by JOD). Somehow OTK is more robust as it catches these cells;
126 ##            Currently this fix is just commented.
127 ## 2011-06-06 Fixed wrong if clause for finding last filler cells (L.160 & L.176)
128 ## 2011-09-12 Support for odfdom-0.8.7 added (API change for XPATH)
129 ## 2012-06-08 Support for odsfdom-0.8.8-incubator
130
131 function [ trow, lrow, lcol, rcol ] = getusedrange_otk (ods, ii)
132
133   odfcont = ods.workbook;  # Local copy just in case
134
135   if (isfield (ods, 'odfvsn'))
136     if (strcmp (ods.odfvsn, '0.8.6') || strcmp (ods.odfvsn, '0.7.5'))
137       xpath = ods.app.getXPath;
138     else
139       # API changed in odfdom-0.8.7
140       xpath = ods.workbook.getXPath;
141     endif
142   else
143     error ("ODS file ptr struct for OTK interface seems broken.");
144   endif
145   
146   # Create an instance of type NODESET for use in subsequent statement
147   NODESET = java_get ('javax.xml.xpath.XPathConstants', 'NODESET');
148   # Get table-rows in sheet no. wsh. Sheet count = 1-based (!)
149   str = sprintf ("//table:table[%d]/table:table-row", ii);
150   sh = xpath.evaluate (str, odfcont, NODESET);
151   nr_of_trows = sh.getLength();
152
153   jj = 0;                  # Table row counter
154   trow = 0; drows = 0;     # Top data row, actual data row range
155   nrows = 0; reprows = 0;  # Scratch counter
156   rcol = 0; lcol = 1024;   # Rightmost and leftmost data column
157   while jj < nr_of_trows
158     row = sh.item(jj);
159     # Check for data rows
160     rw_char = char (row) (1:min(500, length (char (row))));
161     if (findstr ('office:value-type', rw_char) || findstr ('<text:', rw_char))
162       ++drows;
163       # Check for uppermost data row
164       if (~trow) 
165         trow = nrows + 1;
166         nrows = 0;
167       else
168         drows = drows + reprows;
169         reprows = 0;
170       endif
171
172     # Get leftmost cell column number
173       lcell = row.getFirstChild ();
174       cl_char = char (lcell);
175     # Swap the following lines into comment to catch a jOpenDocument bug which foobars OTK
176     # (JOD doesn't set <office:value-type='string'> attribute when writing strings
177       #if (isempty (findstr ('office:value-type', cl_char)) || isempty (findstr ('<text:', cl_char)))
178       if (isempty (findstr ('office:value-type', cl_char)))
179         lcol = min (lcol, lcell.getTableNumberColumnsRepeatedAttribute () + 1);
180       else
181         lcol = 1;
182       endif
183
184       # if rcol is already 1024 no more exploring for rightmost column is needed
185       if ~(rcol == 1024)
186         # Get rightmost cell column number by counting....
187         rc = 0;
188         for kk=1:row.getLength()
189           lcell = row.item(kk - 1);
190           rc = rc + lcell.getTableNumberColumnsRepeatedAttribute ();
191         endfor
192         # Watch out for filler tablecells
193         if (isempty (findstr ('office:value-type', char (lcell))) || isempty (findstr ('<text:', char (lcell))))
194           rc = rc - lcell.getTableNumberColumnsRepeatedAttribute ();
195         endif
196         rcol = max (rcol, rc);
197       endif
198     else
199       # Check for repeated tablerows
200       nrows = nrows + row.getTableNumberRowsRepeatedAttribute ();
201       if (trow)
202         reprows = reprows + row.getTableNumberRowsRepeatedAttribute ();
203       endif
204     endif
205     ++jj;
206   endwhile
207
208   if (trow)
209     lrow = trow + drows - 1;
210   else
211     # Empty sheet
212     lrow = 0; lcol = 0; rcol = 0;
213   endif
214
215 endfunction
216
217 ## Copyright (C) 2010,2011,2012 Philip Nienhuis <prnienhuis -aT- users.sf.net>
218 ##
219 ## This program is free software; you can redistribute it and/or modify it under
220 ## the terms of the GNU General Public License as published by the Free Software
221 ## Foundation; either version 3 of the License, or (at your option) any later
222 ## version.
223 ##
224 ## This program is distributed in the hope that it will be useful, but WITHOUT
225 ## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
226 ## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
227 ## details.
228 ##
229 ## You should have received a copy of the GNU General Public License along with
230 ## this program; if not, see <http://www.gnu.org/licenses/>.
231
232 ## getusedrange_jod
233
234 ## Author: Philip <Philip@DESKPRN>
235 ## Created: 2010-05-25
236 ## Last updates:
237 ## 2010-05-31 Fixed ignoring table-covered-cells; fixed count of sheets comprising just A1:A1
238 ##            Added option for wsh being a string argument 
239 ## 2010-08-12 Little textual adaptations
240 ## 2010-11-13 Catched jOpenDocument bug (1.2bx) where string cells have no office:value-type
241 ##     ''     attrb set (by JOD). Somehow OTK is more robust as it catches these cells
242 ## 2012-04-09 Fixed rowrepcnt (str2num not applied to tablerow)
243 ## 2012-04-18 Added getUsedRange() method for JOD 1.3x and above 
244
245 function [ trow, brow, lcol, rcol ] = getusedrange_jod (ods, wsh)
246
247   # This function works by virtue of sheets in JOD actually being a Java string.
248   # It works outside of the Java memory/heap space which is an added benefit...
249   # (Read: this is one big dirty hack...... prone to crash Java on BIG spreadsheets)
250
251   if (isnumeric (wsh))
252     sh = char (ods.workbook.getSheet (wsh - 1));
253   else
254     sh = char (ods.workbook.getSheet (wsh));
255   endif
256
257   try
258     # Let's see if we have JOD v. 1.3x. If not, next call fails & we'll fall back to the old hack
259     sh_rng = char (sh.getUsedRange ());
260     if (isempty (sh_rng))
261       # Empty sheet
262       trow = brow = lcol = rcol = 0;
263     else
264       # Strip sheet name
265       sh_rng = sh_rng(length (sh.getName) + 2 : end);
266       # Get rid of period
267       sh_rng = strrep (sh_rng, '.', '');
268       [~, nr, nc, trow, lcol] = parse_sp_range (sh_rng);
269       brow = trow + nr - 1;
270       rcol = lcol + nc - 1;
271     endif
272   
273   catch
274     # Fall back to the old hack :-(
275     sh = char (sh);
276
277     # 1. Get table-row pointers
278     id_trow = strfind (sh, '<table:table-row');
279     id = strfind (sh, '</table:table>') - 1;
280     id_trow = [id_trow id];
281
282     trow = rcol = 0;
283     lcol = 1024; brow = 0;
284     if (~isempty (id))
285       # 2. Loop over all table-rows
286       rowrepcnt = 0;
287       for irow = 1:length (id_trow)-1
288         # Isolate single table-row
289         tablerow = sh(id_trow(irow):id_trow(irow+1)-1);
290         # Search table-cells. table-c covers both table-cell & table-covered-cell
291         id_tcell = strfind (tablerow, '<table:table-c'); 
292         id_tcell = [id_tcell id];
293         rowl = length (tablerow);
294         if (isempty (id_tcell(1:end-1)))
295           rowend = rowl;
296         else
297           rowend = id_tcell(1);
298         endif
299         # Add in table-number-rows-repeated attribute values
300         rowrept = strfind (tablerow(1:rowend), 'number-rows-repeated');
301         if (~isempty (rowrept))
302           [st, en] = regexp (tablerow(rowrept:min (rowend, rowrept+30)), '\d+');
303           rowrepcnt += str2num (tablerow(rowrept+st-1:min (rowend, rowrept+en-1))) - 1;
304         endif
305
306         # 3. Search table-cells. table-c is a table-covered-cell that is considered empty
307         id_tcell = strfind (tablerow, '<table:table-c');
308         if (~isempty (id_tcell))
309           # OK, this row has a value cell. Now table-covered-cells must be included.
310           id_tcell2 = strfind (tablerow, '<table:covered-t');
311           if (~isempty (id_tcell2)) id_tcell = sort ([id_tcell id_tcell2]); endif
312           id_tcell = [id_tcell rowl];
313           # Search for non-empty cells (i.e., with an office:value-type attribute). But:
314           # jOpenDocument 1.2b3 has a bug: it often doesn't set this attr for string cells
315           id_valtcell = strfind (tablerow, 'office:value-type=');
316           id_textonlycell = strfind (tablerow, '<text:');
317           id_valtcell = sort ([id_valtcell id_textonlycell]);
318           id_valtcell = [id_valtcell rowl];
319           if (~isempty (id_valtcell(1:end-1)))
320             brow = irow + rowrepcnt;
321             # First set trow if it hadn't already been found
322             if (~trow) trow = irow; endif
323             # Search for repeated table-cells
324             id_reptcell = strfind (tablerow, 'number-columns-repeated');
325             id_reptcell = [id_reptcell rowl];
326             # Search for leftmost non-empty table-cell. llcol = counter for this table-row
327             llcol = 1;
328             while (id_tcell (llcol) < id_valtcell(1) && llcol <= length (id_tcell) - 1)
329               ++llcol;
330             endwhile
331             --llcol;
332             # Compensate for repeated cells. First count all repeats left of llcol
333             ii = 1;
334             repcnt = 0;
335             if (~isempty (id_reptcell(1:end-1)))
336               # First try lcol
337               while (ii <= length (id_reptcell) - 1 && id_reptcell(ii) < id_valtcell(1))
338                 # Add all repeat counts left of leftmost data tcell minus 1 for each
339                 [st, en] = regexp (tablerow(id_reptcell(ii):id_reptcell(ii)+30), '\d+');
340                 repcnt += str2num (tablerow(id_reptcell(ii)+st-1:id_reptcell(ii)+en-1)) - 1;
341                 ++ii;
342               endwhile
343               # Next, add current repcnt value to llcol and update lcol
344               lcol = min (lcol, llcol + repcnt);
345               # Get last value table-cell in table-cell idx
346               jj = 1;
347               while (id_tcell (jj) < id_valtcell(length (id_valtcell)-1))
348                 ++jj;
349               endwhile
350
351               # Get rest of column repeat counts in value table-cell range
352               while (ii < length (id_reptcell) && id_reptcell(ii) < id_tcell(jj))
353                 # Add all repeat counts minus 1 for each tcell in value tcell range
354                 [st, en] = regexp (tablerow(id_reptcell(ii):id_reptcell(ii)+30), '\d+');
355                 repcnt += str2num (tablerow(id_reptcell(ii)+st-1:id_reptcell(ii)+en-1)) - 1;
356                 ++ii;
357               endwhile
358             else
359               # In case left column = A
360               lcol = min (lcol, llcol);
361             endif
362             # Count all table-cells in value table-cell-range
363             ii = 1;       # Indexes cannot be negative
364             while (ii < length (id_tcell) && id_tcell(ii) < id_valtcell(length (id_valtcell) - 1))
365               ++ii;
366             endwhile
367             --ii;
368             rcol = max (rcol, ii + repcnt);
369           endif
370         endif
371       endfor
372     else
373       # No data found, empty sheet
374       lcol = rcol = brow = trow = 0;
375     endif
376
377   end_try_catch
378
379 endfunction
380
381
382 ## Copyright (C) 2011,2012 Philip Nienhuis
383 ##
384 ## This program is free software; you can redistribute it and/or modify it under
385 ## the terms of the GNU General Public License as published by the Free Software
386 ## Foundation; either version 3 of the License, or (at your option) any later
387 ## version.
388 ##
389 ## This program is distributed in the hope that it will be useful, but WITHOUT
390 ## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
391 ## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
392 ## details.
393 ##
394 ## You should have received a copy of the GNU General Public License along with
395 ## this program; if not, see <http://www.gnu.org/licenses/>.
396
397 ## getusedrange_uno
398
399 ## Author: Philip Nienhuis <prnienhuis@users.sf.net>
400 ## Created: 2011-05-06
401 ## Updates:
402 ## 2011-06-29 Fixed wrong address range inference in case of sheet names containing period(s)
403 ## 2012-03-02 Adapted code to assess nr of range blocks to ';' separator fo LO3.5+
404
405 function [ srow, erow, scol, ecol ] = getusedrange_uno (ods, ii)
406
407   # Get desired sheet
408   sheets = ods.workbook.getSheets ();
409   sh_names = sheets.getElementNames ();
410   unotmp = java_new ('com.sun.star.uno.Type', 'com.sun.star.sheet.XSpreadsheet');
411   sh = sheets.getByName(sh_names(ii)).getObject.queryInterface (unotmp);
412
413   # Prepare cell range query
414   unotmp = java_new ('com.sun.star.uno.Type', 'com.sun.star.sheet.XCellRangesQuery');
415   xRQ = sh.queryInterface (unotmp);
416   Cellflgs = javaObject ("java.lang.Short", "23");
417   ccells = xRQ.queryContentCells (Cellflgs);
418
419   # Get addresses of all blocks containing data
420   addrs = ccells.getRangeAddressesAsString ();
421
422   # Strip sheet name from addresses. Watch out, in LO3.5 they changed
423   # the separator from ',' to ';' (without telling me!)
424   # 1. Get nr of range blocks
425   nblks = numel (strfind (addrs, sh_names(ii)));
426   # 2. First try with ',' separator...
427   adrblks = strsplit (addrs, ',');
428   if (numel (adrblks) < nblks)
429     # Apparently we have a ';' separator, so try with semicolon
430     adrblks = strsplit (addrs, ';');
431   endif
432   if (isempty (adrblks))
433     srow = erow = scol = ecol = 0;
434     return
435   endif
436
437   # Find leftmost & rightmost columns, and highest and lowest row with data
438   srow = scol = 1e10;
439   erow = ecol = 0;
440   for ii=1:numel (adrblks)
441     # Check if address contains a sheet name in quotes (happens if name contains a period)
442     if (int8 (adrblks{ii}(1)) == 39)
443       # Strip sheet name part
444       idx = findstr (adrblks{ii}, "'.");
445       range = adrblks{ii}(idx+2 : end);
446     else
447       # Same, but tru strsplit()
448       range = strsplit (adrblks{ii}, '.'){2};
449     endif
450     [dummy, nrows, ncols, trow, lcol] = parse_sp_range (range);
451     brow = trow + nrows - 1;
452     rcol = lcol + ncols - 1;
453     srow = min (srow, trow);
454     scol = min (scol, lcol);
455     erow = max (erow, brow);
456     ecol = max (ecol, rcol);
457   endfor
458
459 endfunction
460
461
462 ## Copyright (C) 2010,2011,2012 Philip Nienhuis
463 ##
464 ## This program is free software; you can redistribute it and/or modify it under
465 ## the terms of the GNU General Public License as published by the Free Software
466 ## Foundation; either version 3 of the License, or (at your option) any later
467 ## version.
468 ##
469 ## This program is distributed in the hope that it will be useful, but WITHOUT
470 ## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
471 ## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
472 ## details.
473 ##
474 ## You should have received a copy of the GNU General Public License along with
475 ## this program; if not, see <http://www.gnu.org/licenses/>.
476
477 ## getusedrange_com
478
479 ## Author: Philip Nienhuis <prnienhuis@users.sf.net>
480 ## Created: 2010-10-07
481
482 function [ trow, brow, lcol, rcol ] = getusedrange_com (xls, ii)
483
484   sh = xls.workbook.Worksheets (ii);
485   
486   # Decipher used range. Beware, UsedRange() returns *cached* rectangle of
487   # all spreadsheet cells containing *anything*, including just formatting
488   # (i.e., empty cells are included too). ==> This is an approximation only
489   allcells = sh.UsedRange;
490   
491   # Get top left cell as a Range object
492   toplftcl = allcells.Columns(1).Rows(1);
493   
494   # Count number of rows & cols in virtual range from A1 to top left cell
495   lcol = sh.Range ("A1", toplftcl).columns.Count;
496   trow = sh.Range ("A1", toplftcl).rows.Count;
497   
498   # Add real occupied rows & cols to obtain end row & col
499   brow = trow + allcells.rows.Count() - 1;
500   rcol = lcol + allcells.columns.Count() - 1;
501   
502   # Check if there are real data
503   if ((lcol == rcol) && (trow = brow))
504     if (isempty (toplftcl.Value))
505       trow = brow = lcol = rcol = 0;
506     endif
507   endif
508
509 endfunction
510
511
512 ## Copyright (C) 2010,2011,2012 Philip Nienhuis, prnienhuis at users.sf.net
513 ##
514 ## This program is free software; you can redistribute it and/or modify it under
515 ## the terms of the GNU General Public License as published by the Free Software
516 ## Foundation; either version 3 of the License, or (at your option) any later
517 ## version.
518 ##
519 ## This program is distributed in the hope that it will be useful, but WITHOUT
520 ## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
521 ## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
522 ## details.
523 ##
524 ## You should have received a copy of the GNU General Public License along with
525 ## this program; if not, see <http://www.gnu.org/licenses/>.
526
527 ## getusedrange_poi - get range of occupied data cells from Excel using java/POI
528
529 ## Author: Philip <Philip@DESKPRN>
530 ## Created: 2010-03-20
531
532 function [ trow, brow, lcol, rcol ] = getusedrange_poi (xls, ii)
533
534   persistent cblnk; cblnk = java_get ('org.apache.poi.ss.usermodel.Cell', 'CELL_TYPE_BLANK');
535
536   sh = xls.workbook.getSheetAt (ii-1);         # Java POI starts counting at 0 
537
538   trow = sh.getFirstRowNum ();                 # 0-based
539   brow = sh.getLastRowNum ();                  # 0-based
540   # Get column range
541   lcol = 1048577;  # OOXML (xlsx) max. + 1
542   rcol = 0;
543   botrow = brow;
544   for jj=trow:brow
545     irow = sh.getRow (jj);
546     if (~isempty (irow))
547       scol = (irow.getFirstCellNum).intValue ();
548       lcol = min (lcol, scol);
549       ecol = (irow.getLastCellNum).intValue () - 1;
550       rcol = max (rcol, ecol);
551       # Keep track of lowermost non-empty row as getLastRowNum() is unreliable
552       if ~(irow.getCell(scol).getCellType () == cblnk && irow.getCell(ecol).getCellType () == cblnk)
553         botrow = jj;
554       endif
555     endif
556   endfor
557   if (lcol > 1048576)
558     # Empty sheet
559     trow = 0; brow = 0; lcol = 0; rcol = 0;
560   else
561     brow = min (brow, botrow) + 1; ++trow; ++lcol; ++rcol;    # 1-based return values
562   endif
563
564 endfunction
565
566
567 ## Copyright (C) 2010,2011,2012 Philip Nienhuis, prnienhuis at users.sf.net
568 ##
569 ## This program is free software; you can redistribute it and/or modify it under
570 ## the terms of the GNU General Public License as published by the Free Software
571 ## Foundation; either version 3 of the License, or (at your option) any later
572 ## version.
573 ##
574 ## This program is distributed in the hope that it will be useful, but WITHOUT
575 ## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
576 ## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
577 ## details.
578 ##
579 ## You should have received a copy of the GNU General Public License along with
580 ## this program; if not, see <http://www.gnu.org/licenses/>.
581
582 ## getusedrange_jxl - get occupied data cell range from Excel sheet
583 ## using java/JExcelAPI
584
585 ## Author: Philip <Philip@DESKPRN>
586 ## Created: 2010-03-20
587
588 function [ trow, brow, lcol, rcol ] = getusedrange_jxl (xls, wsh)
589
590   persistent emptycell = (java_get ('jxl.CellType', 'EMPTY')).toString ();
591
592   sh = xls.workbook.getSheet (wsh - 1);      # JXL sheet count 0-based
593
594   brow = sh.getRows ();
595   rcol = sh.getColumns ();
596   
597   if (brow == 0 || rcol == 0)
598     # Empty sheet
599     trow = 0; lcol = 0; brow = 0; rcol = 0;
600   else
601     trow = brow + 1;
602     lcol = rcol + 1;
603     for ii=0:brow-1    # For loop coz we must check ALL rows for leftmost column
604       emptyrow = 1;
605       jj = 0;
606       while (jj < rcol && emptyrow)   # While loop => only til first non-empty cell
607         cell = sh.getCell (jj, ii);
608         if ~(strcmp (char (cell.getType ()), emptycell))
609           lcol = min (lcol, jj + 1);
610           emptyrow = 0;
611         endif
612         ++jj;
613       endwhile
614       if ~(emptyrow) trow = min (trow, ii + 1); endif
615     endfor
616   endif
617
618 endfunction
619
620
621 ## Copyright (C) 2010,2011,2012 Philip Nienhuis, <prnienhuis at users.sf.net>
622 ##
623 ## This program is free software; you can redistribute it and/or modify it under
624 ## the terms of the GNU General Public License as published by the Free Software
625 ## Foundation; either version 3 of the License, or (at your option) any later
626 ## version.
627 ##
628 ## This program is distributed in the hope that it will be useful, but WITHOUT
629 ## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
630 ## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
631 ## details.
632 ##
633 ## You should have received a copy of the GNU General Public License along with
634 ## this program; if not, see <http://www.gnu.org/licenses/>.
635
636 ## getusedrange_oxs
637
638 ## Author: Philip <Philip@DESKPRN>
639 ## Created: 2011-06-13
640 ## Updates:
641 ## 2011-06-29 try-catch to be able to skip non-data (e.g., graph) sheets
642
643 function [ trow, brow, lcol, rcol ] = getusedrange_oxs (xls, wsh)
644
645   sh = xls.workbook.getWorkSheet (wsh - 1);
646   try
647     # Intriguing:  sh.getFirst<> is off by one, sh.getLast<> = OK.... 8-Z 
648     trow = sh.getFirstRow () + 1;
649     brow = sh.getLastRow ();
650     lcol = sh.getFirstCol () + 1;
651     rcol = sh.getLastCol ();
652   catch
653     # Might be an empty sheet
654     trow = brow = lcol = rcol = 0;
655   end_try_catch
656   # Check for empty sheet
657   if ((trow > brow) || (lcol > rcol)), trow = brow = lcol = rcol = 0; endif
658
659 endfunction