From: <prn...@us...> - 2012-06-08 15:28:36
|
Revision: 10592 http://octave.svn.sourceforge.net/octave/?rev=10592&view=rev Author: prnienhuis Date: 2012-06-08 15:28:27 +0000 (Fri, 08 Jun 2012) Log Message: ----------- Support for odfdom-0.8.8-incubator; tabs replaced by double space Modified Paths: -------------- trunk/octave-forge/main/io/inst/getusedrange.m trunk/octave-forge/main/io/inst/oct2ods.m trunk/octave-forge/main/io/inst/ods2oct.m trunk/octave-forge/main/io/inst/odsclose.m trunk/octave-forge/main/io/inst/odsfinfo.m trunk/octave-forge/main/io/inst/odsopen.m trunk/octave-forge/main/io/inst/odsread.m trunk/octave-forge/main/io/inst/odswrite.m Modified: trunk/octave-forge/main/io/inst/getusedrange.m =================================================================== --- trunk/octave-forge/main/io/inst/getusedrange.m 2012-06-08 14:11:42 UTC (rev 10591) +++ trunk/octave-forge/main/io/inst/getusedrange.m 2012-06-08 15:28:27 UTC (rev 10592) @@ -66,8 +66,10 @@ ## 2011-06-13 OpenXLS support added ## 2011-09-08 Style & layout updates ## 2012-01-26 Fixed "seealso" help string +## 2012-06-08 Replaced tabs by double space +## '' Added COM and OXS to message about supported interfaces ## -## Last subfunc update: 2012-04-18 (JOD) +## Last subfunc update: 2012-06-08 (OTK) function [ trow, lrow, lcol, rcol ] = getusedrange (spptr, ii) @@ -89,7 +91,7 @@ elseif (strcmp (spptr.xtype, 'OXS')) [ trow, lrow, lcol, rcol ] = getusedrange_oxs (spptr, ii); else - error ('Only OTK, JOD, POI and JXL interface implemented'); + error ("Only OTK, JOD, COM, POI, JXL and OXS interface implemented"); endif endfunction @@ -124,10 +126,11 @@ ## Currently this fix is just commented. ## 2011-06-06 Fixed wrong if clause for finding last filler cells (L.160 & L.176) ## 2011-09-12 Support for odfdom-0.8.7 added (API change for XPATH) +## 2012-06-08 Support for odsfdom-0.8.8-incubator function [ trow, lrow, lcol, rcol ] = getusedrange_otk (ods, ii) - odfcont = ods.workbook; # Local copy just in case + odfcont = ods.workbook; # Local copy just in case if (isfield (ods, 'odfvsn')) if (strcmp (ods.odfvsn, '0.8.6') || strcmp (ods.odfvsn, '0.7.5')) @@ -166,11 +169,11 @@ reprows = 0; endif - # Get leftmost cell column number + # Get leftmost cell column number lcell = row.getFirstChild (); cl_char = char (lcell); - # Swap the following lines into comment to catch a jOpenDocument bug which foobars OTK - # (JOD doesn't set <office:value-type='string'> attribute when writing strings + # Swap the following lines into comment to catch a jOpenDocument bug which foobars OTK + # (JOD doesn't set <office:value-type='string'> attribute when writing strings #if (isempty (findstr ('office:value-type', cl_char)) || isempty (findstr ('<text:', cl_char))) if (isempty (findstr ('office:value-type', cl_char))) lcol = min (lcol, lcell.getTableNumberColumnsRepeatedAttribute () + 1); @@ -232,7 +235,7 @@ ## Created: 2010-05-25 ## Last updates: ## 2010-05-31 Fixed ignoring table-covered-cells; fixed count of sheets comprising just A1:A1 -## '' Added option for wsh being a string argument +## Added option for wsh being a string argument ## 2010-08-12 Little textual adaptations ## 2010-11-13 Catched jOpenDocument bug (1.2bx) where string cells have no office:value-type ## '' attrb set (by JOD). Somehow OTK is more robust as it catches these cells @@ -241,15 +244,15 @@ function [ trow, brow, lcol, rcol ] = getusedrange_jod (ods, wsh) - # This function works by virtue of sheets in JOD actually being a Java string. - # It works outside of the Java memory/heap space which is an added benefit... - # (Read: this is one big dirty hack...... prone to crash Java on BIG spreadsheets) + # This function works by virtue of sheets in JOD actually being a Java string. + # It works outside of the Java memory/heap space which is an added benefit... + # (Read: this is one big dirty hack...... prone to crash Java on BIG spreadsheets) - if (isnumeric (wsh)) - sh = ods.workbook.getSheet (wsh - 1); - else - sh = ods.workbook.getSheet (wsh); - endif + if (isnumeric (wsh)) + sh = char (ods.workbook.getSheet (wsh - 1)); + else + sh = char (ods.workbook.getSheet (wsh)); + endif try # Let's see if we have JOD v. 1.3x. If not, next call fails & we'll fall back to the old hack @@ -266,16 +269,12 @@ brow = trow + nr - 1; rcol = lcol + nc - 1; endif - return catch - # This function works by virtue of sheets in JOD actually being a Java string. - # It works outside of the Java memory/heap space which is an added benefit... - # (Read: this is one big dirty hack...... prone to crash Java on BIG spreadsheets) - + # Fall back to the old hack :-( sh = char (sh); - # Get table-row pointers + # 1. Get table-row pointers id_trow = strfind (sh, '<table:table-row'); id = strfind (sh, '</table:table>') - 1; id_trow = [id_trow id]; @@ -283,96 +282,96 @@ trow = rcol = 0; lcol = 1024; brow = 0; if (~isempty (id)) - # Loop over all table-rows - rowrepcnt = 0; - for irow = 1:length (id_trow)-1 - # Isolate single table-row - tablerow = sh(id_trow(irow):id_trow(irow+1)-1); - # Search table-cells. table-c covers both table-cell & table-covered-cell - id_tcell = strfind (tablerow, '<table:table-c'); - id_tcell = [id_tcell id]; - rowl = length (tablerow); - if (isempty (id_tcell(1:end-1))) - rowend = rowl; - else - rowend = id_tcell(1); - endif - # Add in table-number-rows-repeated attribute values - rowrept = strfind (tablerow(1:rowend), 'number-rows-repeated'); - if (~isempty (rowrept)) - [st, en] = regexp (tablerow(rowrept:min (rowend, rowrept+30)), '\d+'); - rowrepcnt += str2num (tablerow(rowrept+st-1:min (rowend, rowrept+en-1))) - 1; - endif + # 2. Loop over all table-rows + rowrepcnt = 0; + for irow = 1:length (id_trow)-1 + # Isolate single table-row + tablerow = sh(id_trow(irow):id_trow(irow+1)-1); + # Search table-cells. table-c covers both table-cell & table-covered-cell + id_tcell = strfind (tablerow, '<table:table-c'); + id_tcell = [id_tcell id]; + rowl = length (tablerow); + if (isempty (id_tcell(1:end-1))) + rowend = rowl; + else + rowend = id_tcell(1); + endif + # Add in table-number-rows-repeated attribute values + rowrept = strfind (tablerow(1:rowend), 'number-rows-repeated'); + if (~isempty (rowrept)) + [st, en] = regexp (tablerow(rowrept:min (rowend, rowrept+30)), '\d+'); + rowrepcnt += str2num (tablerow(rowrept+st-1:min (rowend, rowrept+en-1))) - 1; + endif - # Search table-cells. table-c is a table-covered-cell that is considered empty - id_tcell = strfind (tablerow, '<table:table-c'); - if (~isempty (id_tcell)) - # OK, this row has a value cell. Now table-covered-cells must be included. - id_tcell2 = strfind (tablerow, '<table:covered-t'); - if (~isempty (id_tcell2)) id_tcell = sort ([id_tcell id_tcell2]); endif - id_tcell = [id_tcell rowl]; - # Search for non-empty cells (i.e., with an office:value-type attribute). But: - # jOpenDocument 1.2b3 has a bug: it often doesn't set this attr for string cells - id_valtcell = strfind (tablerow, 'office:value-type='); - id_textonlycell = strfind (tablerow, '<text:'); - id_valtcell = sort ([id_valtcell id_textonlycell]); - id_valtcell = [id_valtcell rowl]; - if (~isempty (id_valtcell(1:end-1))) - brow = irow + rowrepcnt; - # First set trow if it hadn't already been found - if (~trow) trow = irow; endif - # Search for repeated table-cells - id_reptcell = strfind (tablerow, 'number-columns-repeated'); - id_reptcell = [id_reptcell rowl]; - # Search for leftmost non-empty table-cell. llcol = counter for this table-row - llcol = 1; - while (id_tcell (llcol) < id_valtcell(1) && llcol <= length (id_tcell) - 1) - ++llcol; - endwhile - --llcol; - # Compensate for repeated cells. First count all repeats left of llcol - ii = 1; - repcnt = 0; - if (~isempty (id_reptcell(1:end-1))) - # First try lcol - while (ii <= length (id_reptcell) - 1 && id_reptcell(ii) < id_valtcell(1)) - # Add all repeat counts left of leftmost data tcell minus 1 for each - [st, en] = regexp (tablerow(id_reptcell(ii):id_reptcell(ii)+30), '\d+'); - repcnt += str2num (tablerow(id_reptcell(ii)+st-1:id_reptcell(ii)+en-1)) - 1; - ++ii; - endwhile - # Next, add current repcnt value to llcol and update lcol - lcol = min (lcol, llcol + repcnt); - # Get last value table-cell in table-cell idx - jj = 1; - while (id_tcell (jj) < id_valtcell(length (id_valtcell)-1)) - ++jj; - endwhile + # 3. Search table-cells. table-c is a table-covered-cell that is considered empty + id_tcell = strfind (tablerow, '<table:table-c'); + if (~isempty (id_tcell)) + # OK, this row has a value cell. Now table-covered-cells must be included. + id_tcell2 = strfind (tablerow, '<table:covered-t'); + if (~isempty (id_tcell2)) id_tcell = sort ([id_tcell id_tcell2]); endif + id_tcell = [id_tcell rowl]; + # Search for non-empty cells (i.e., with an office:value-type attribute). But: + # jOpenDocument 1.2b3 has a bug: it often doesn't set this attr for string cells + id_valtcell = strfind (tablerow, 'office:value-type='); + id_textonlycell = strfind (tablerow, '<text:'); + id_valtcell = sort ([id_valtcell id_textonlycell]); + id_valtcell = [id_valtcell rowl]; + if (~isempty (id_valtcell(1:end-1))) + brow = irow + rowrepcnt; + # First set trow if it hadn't already been found + if (~trow) trow = irow; endif + # Search for repeated table-cells + id_reptcell = strfind (tablerow, 'number-columns-repeated'); + id_reptcell = [id_reptcell rowl]; + # Search for leftmost non-empty table-cell. llcol = counter for this table-row + llcol = 1; + while (id_tcell (llcol) < id_valtcell(1) && llcol <= length (id_tcell) - 1) + ++llcol; + endwhile + --llcol; + # Compensate for repeated cells. First count all repeats left of llcol + ii = 1; + repcnt = 0; + if (~isempty (id_reptcell(1:end-1))) + # First try lcol + while (ii <= length (id_reptcell) - 1 && id_reptcell(ii) < id_valtcell(1)) + # Add all repeat counts left of leftmost data tcell minus 1 for each + [st, en] = regexp (tablerow(id_reptcell(ii):id_reptcell(ii)+30), '\d+'); + repcnt += str2num (tablerow(id_reptcell(ii)+st-1:id_reptcell(ii)+en-1)) - 1; + ++ii; + endwhile + # Next, add current repcnt value to llcol and update lcol + lcol = min (lcol, llcol + repcnt); + # Get last value table-cell in table-cell idx + jj = 1; + while (id_tcell (jj) < id_valtcell(length (id_valtcell)-1)) + ++jj; + endwhile - # Get rest of column repeat counts in value table-cell range - while (ii < length (id_reptcell) && id_reptcell(ii) < id_tcell(jj)) - # Add all repeat counts minus 1 for each tcell in value tcell range - [st, en] = regexp (tablerow(id_reptcell(ii):id_reptcell(ii)+30), '\d+'); - repcnt += str2num (tablerow(id_reptcell(ii)+st-1:id_reptcell(ii)+en-1)) - 1; - ++ii; - endwhile - else - # In case left column = A - lcol = min (lcol, llcol); - endif - # Count all table-cells in value table-cell-range - ii = 1; # Indexes cannot be negative - while (ii < length (id_tcell) && id_tcell(ii) < id_valtcell(length (id_valtcell) - 1)) - ++ii; - endwhile - --ii; - rcol = max (rcol, ii + repcnt); - endif - endif - endfor + # Get rest of column repeat counts in value table-cell range + while (ii < length (id_reptcell) && id_reptcell(ii) < id_tcell(jj)) + # Add all repeat counts minus 1 for each tcell in value tcell range + [st, en] = regexp (tablerow(id_reptcell(ii):id_reptcell(ii)+30), '\d+'); + repcnt += str2num (tablerow(id_reptcell(ii)+st-1:id_reptcell(ii)+en-1)) - 1; + ++ii; + endwhile + else + # In case left column = A + lcol = min (lcol, llcol); + endif + # Count all table-cells in value table-cell-range + ii = 1; # Indexes cannot be negative + while (ii < length (id_tcell) && id_tcell(ii) < id_valtcell(length (id_valtcell) - 1)) + ++ii; + endwhile + --ii; + rcol = max (rcol, ii + repcnt); + endif + endif + endfor else - # No data found, empty sheet - lcol = rcol = brow = trow = 0; + # No data found, empty sheet + lcol = rcol = brow = trow = 0; endif end_try_catch @@ -482,30 +481,30 @@ function [ trow, brow, lcol, rcol ] = getusedrange_com (xls, ii) - sh = xls.workbook.Worksheets (ii); - - # Decipher used range. Beware, UsedRange() returns *cached* rectangle of - # all spreadsheet cells containing *anything*, including just formatting - # (i.e., empty cells are included too). ==> This is an approximation only - allcells = sh.UsedRange; - - # Get top left cell as a Range object - toplftcl = allcells.Columns(1).Rows(1); - - # Count number of rows & cols in virtual range from A1 to top left cell - lcol = sh.Range ("A1", toplftcl).columns.Count; - trow = sh.Range ("A1", toplftcl).rows.Count; - - # Add real occupied rows & cols to obtain end row & col - brow = trow + allcells.rows.Count() - 1; - rcol = lcol + allcells.columns.Count() - 1; - - # Check if there are real data - if ((lcol == rcol) && (trow = brow)) - if (isempty (toplftcl.Value)) - trow = brow = lcol = rcol = 0; - endif + sh = xls.workbook.Worksheets (ii); + + # Decipher used range. Beware, UsedRange() returns *cached* rectangle of + # all spreadsheet cells containing *anything*, including just formatting + # (i.e., empty cells are included too). ==> This is an approximation only + allcells = sh.UsedRange; + + # Get top left cell as a Range object + toplftcl = allcells.Columns(1).Rows(1); + + # Count number of rows & cols in virtual range from A1 to top left cell + lcol = sh.Range ("A1", toplftcl).columns.Count; + trow = sh.Range ("A1", toplftcl).rows.Count; + + # Add real occupied rows & cols to obtain end row & col + brow = trow + allcells.rows.Count() - 1; + rcol = lcol + allcells.columns.Count() - 1; + + # Check if there are real data + if ((lcol == rcol) && (trow = brow)) + if (isempty (toplftcl.Value)) + trow = brow = lcol = rcol = 0; endif + endif endfunction @@ -532,35 +531,35 @@ function [ trow, brow, lcol, rcol ] = getusedrange_poi (xls, ii) - persistent cblnk; cblnk = java_get ('org.apache.poi.ss.usermodel.Cell', 'CELL_TYPE_BLANK'); + persistent cblnk; cblnk = java_get ('org.apache.poi.ss.usermodel.Cell', 'CELL_TYPE_BLANK'); - sh = xls.workbook.getSheetAt (ii-1); # Java POI starts counting at 0 + sh = xls.workbook.getSheetAt (ii-1); # Java POI starts counting at 0 - trow = sh.getFirstRowNum (); # 0-based - brow = sh.getLastRowNum (); # 0-based - # Get column range - lcol = 1048577; # OOXML (xlsx) max. + 1 - rcol = 0; - botrow = brow; - for jj=trow:brow - irow = sh.getRow (jj); - if (~isempty (irow)) - scol = (irow.getFirstCellNum).intValue (); - lcol = min (lcol, scol); - ecol = (irow.getLastCellNum).intValue () - 1; - rcol = max (rcol, ecol); - # Keep track of lowermost non-empty row as getLastRowNum() is unreliable - if ~(irow.getCell(scol).getCellType () == cblnk && irow.getCell(ecol).getCellType () == cblnk) - botrow = jj; - endif - endif - endfor - if (lcol > 1048576) - # Empty sheet - trow = 0; brow = 0; lcol = 0; rcol = 0; - else - brow = min (brow, botrow) + 1; ++trow; ++lcol; ++rcol; # 1-based return values + trow = sh.getFirstRowNum (); # 0-based + brow = sh.getLastRowNum (); # 0-based + # Get column range + lcol = 1048577; # OOXML (xlsx) max. + 1 + rcol = 0; + botrow = brow; + for jj=trow:brow + irow = sh.getRow (jj); + if (~isempty (irow)) + scol = (irow.getFirstCellNum).intValue (); + lcol = min (lcol, scol); + ecol = (irow.getLastCellNum).intValue () - 1; + rcol = max (rcol, ecol); + # Keep track of lowermost non-empty row as getLastRowNum() is unreliable + if ~(irow.getCell(scol).getCellType () == cblnk && irow.getCell(ecol).getCellType () == cblnk) + botrow = jj; + endif endif + endfor + if (lcol > 1048576) + # Empty sheet + trow = 0; brow = 0; lcol = 0; rcol = 0; + else + brow = min (brow, botrow) + 1; ++trow; ++lcol; ++rcol; # 1-based return values + endif endfunction @@ -588,33 +587,33 @@ function [ trow, brow, lcol, rcol ] = getusedrange_jxl (xls, wsh) - persistent emptycell = (java_get ('jxl.CellType', 'EMPTY')).toString (); + persistent emptycell = (java_get ('jxl.CellType', 'EMPTY')).toString (); - sh = xls.workbook.getSheet (wsh - 1); # JXL sheet count 0-based + sh = xls.workbook.getSheet (wsh - 1); # JXL sheet count 0-based - brow = sh.getRows (); - rcol = sh.getColumns (); - - if (brow == 0 || rcol == 0) - # Empty sheet - trow = 0; lcol = 0; brow = 0; rcol = 0; - else - trow = brow + 1; - lcol = rcol + 1; - for ii=0:brow-1 # For loop coz we must check ALL rows for leftmost column - emptyrow = 1; - jj = 0; - while (jj < rcol && emptyrow) # While loop => only til first non-empty cell - cell = sh.getCell (jj, ii); - if ~(strcmp (char (cell.getType ()), emptycell)) - lcol = min (lcol, jj + 1); - emptyrow = 0; - endif - ++jj; - endwhile - if ~(emptyrow) trow = min (trow, ii + 1); endif - endfor - endif + brow = sh.getRows (); + rcol = sh.getColumns (); + + if (brow == 0 || rcol == 0) + # Empty sheet + trow = 0; lcol = 0; brow = 0; rcol = 0; + else + trow = brow + 1; + lcol = rcol + 1; + for ii=0:brow-1 # For loop coz we must check ALL rows for leftmost column + emptyrow = 1; + jj = 0; + while (jj < rcol && emptyrow) # While loop => only til first non-empty cell + cell = sh.getCell (jj, ii); + if ~(strcmp (char (cell.getType ()), emptycell)) + lcol = min (lcol, jj + 1); + emptyrow = 0; + endif + ++jj; + endwhile + if ~(emptyrow) trow = min (trow, ii + 1); endif + endfor + endif endfunction @@ -643,18 +642,18 @@ function [ trow, brow, lcol, rcol ] = getusedrange_oxs (xls, wsh) - sh = xls.workbook.getWorkSheet (wsh - 1); - try - # Intriguing: sh.getFirst<> is off by one, sh.getLast<> = OK.... 8-Z - trow = sh.getFirstRow () + 1; - brow = sh.getLastRow (); - lcol = sh.getFirstCol () + 1; - rcol = sh.getLastCol (); - catch - # Might be an empty sheet - trow = brow = lcol = rcol = 0; - end_try_catch - # Check for empty sheet - if ((trow > brow) || (lcol > rcol)), trow = brow = lcol = rcol = 0; endif + sh = xls.workbook.getWorkSheet (wsh - 1); + try + # Intriguing: sh.getFirst<> is off by one, sh.getLast<> = OK.... 8-Z + trow = sh.getFirstRow () + 1; + brow = sh.getLastRow (); + lcol = sh.getFirstCol () + 1; + rcol = sh.getLastCol (); + catch + # Might be an empty sheet + trow = brow = lcol = rcol = 0; + end_try_catch + # Check for empty sheet + if ((trow > brow) || (lcol > rcol)), trow = brow = lcol = rcol = 0; endif endfunction Modified: trunk/octave-forge/main/io/inst/oct2ods.m =================================================================== --- trunk/octave-forge/main/io/inst/oct2ods.m 2012-06-08 14:11:42 UTC (rev 10591) +++ trunk/octave-forge/main/io/inst/oct2ods.m 2012-06-08 15:28:27 UTC (rev 10592) @@ -115,98 +115,96 @@ ## 2012-02-20 Fixed range parameter to be default empty string rather than empty numeral ## 2012-02-27 More range arg fixes ## 2012-03-07 Updated texinfo help text -## 2012-05-22 Cast all numeric data in input array to double +## 2012-06-08 Support for odfdom-incubator-0.8.8 +## '' Tabs replaced by double space ## -## Last update of subfunctions below: 2012-02-26 +## Last update of subfunctions below: 2012-06-08 function [ ods, rstatus ] = oct2ods (c_arr, ods, wsh=1, crange='', spsh_opts=[]) - if (nargin < 2) error ("oct2xls needs a minimum of 2 arguments."); endif + if (nargin < 2) error ("oct2xls needs a minimum of 2 arguments."); endif - # Check if input array is cell - if (isempty (c_arr)) - warning ("Request to write empty matrix - ignored."); - rstatus = 1; - return; - elseif (isnumeric (c_arr)) - c_arr = num2cell (c_arr); - elseif (ischar(c_arr)) - c_arr = {c_arr}; - printf ("(oct2ods: input character array converted to 1x1 cell)\n"); - elseif (~iscell (c_arr)) - error ("oct2ods: input array neither cell nor numeric array"); - endif - if (ndims (c_arr) > 2), error ("Only 2-dimensional arrays can be written to spreadsheet"); endif - # Cast all numerical values to double as spreadsheets only have double/boolean/text type - idx = cellfun (@isnumeric, obj, "UniformOutput", true); - obj(idx) = cellfun (@double, obj(idx), "UniformOutput", false); + # Check if input array is cell + if (isempty (c_arr)) + warning ("Request to write empty matrix - ignored."); + rstatus = 1; + return; + elseif (isnumeric (c_arr)) + c_arr = num2cell (c_arr); + elseif (ischar(c_arr)) + c_arr = {c_arr}; + printf ("(oct2ods: input character array converted to 1x1 cell)\n"); + elseif (~iscell (c_arr)) + error ("oct2ods: input array neither cell nor numeric array"); + endif + if (ndims (c_arr) > 2), error ("Only 2-dimensional arrays can be written to spreadsheet"); endif # Check ods file pointer struct - test1 = ~isfield (ods, "xtype"); - test1 = test1 || ~isfield (ods, "workbook"); - test1 = test1 || isempty (ods.workbook); - test1 = test1 || isempty (ods.app); - if test1 - error ("Arg #2: Invalid ods file pointer struct"); - endif + test1 = ~isfield (ods, "xtype"); + test1 = test1 || ~isfield (ods, "workbook"); + test1 = test1 || isempty (ods.workbook); + test1 = test1 || isempty (ods.app); + if test1 + error ("Arg #2: Invalid ods file pointer struct"); + endif - # Check worksheet ptr - if (~(ischar (wsh) || isnumeric (wsh))), error ("Integer (index) or text (wsh name) expected for arg # 3"); endif + # Check worksheet ptr + if (~(ischar (wsh) || isnumeric (wsh))), error ("Integer (index) or text (wsh name) expected for arg # 3"); endif - # Check range - if (~isempty (crange) && ~ischar (crange)) + # Check range + if (~isempty (crange) && ~ischar (crange)) error ("Character string (range) expected for arg # 4"); elseif (isempty (crange)) crange = ''; endif - # Various options - if (isempty (spsh_opts)) - spsh_opts.formulas_as_text = 0; - # other options to be implemented here - elseif (isstruct (spsh_opts)) - if (~isfield (spsh_opts, 'formulas_as_text')), spsh_opts.formulas_as_text = 0; endif - # other options to be implemented here - else - error ("Structure expected for arg # 5"); - endif - - if (nargout < 1) printf ("Warning: no output spreadsheet file pointer specified.\n"); endif + # Various options + if (isempty (spsh_opts)) + spsh_opts.formulas_as_text = 0; + # other options to be implemented here + elseif (isstruct (spsh_opts)) + if (~isfield (spsh_opts, 'formulas_as_text')), spsh_opts.formulas_as_text = 0; endif + # other options to be implemented here + else + error ("Structure expected for arg # 5"); + endif + + if (nargout < 1) printf ("Warning: no output spreadsheet file pointer specified.\n"); endif - if (strcmp (ods.xtype, 'OTK')) - # Write ods file tru Java & ODF toolkit. - switch ods.odfvsn - case "0.7.5" - [ ods, rstatus ] = oct2jotk2ods (c_arr, ods, wsh, crange, spsh_opts); - case {"0.8.6", "0.8.7"} - [ ods, rstatus ] = oct3jotk2ods (c_arr, ods, wsh, crange, spsh_opts); - otherwise - error ("Unsupported odfdom version"); - endswitch + if (strcmp (ods.xtype, 'OTK')) + # Write ods file tru Java & ODF toolkit. + switch ods.odfvsn + case "0.7.5" + [ ods, rstatus ] = oct2jotk2ods (c_arr, ods, wsh, crange, spsh_opts); + case {"0.8.6", "0.8.7", "0.8.8"} + [ ods, rstatus ] = oct3jotk2ods (c_arr, ods, wsh, crange, spsh_opts); + otherwise + error ("Unsupported odfdom version"); + endswitch - elseif (strcmp (ods.xtype, 'JOD')) - # Write ods file tru Java & jOpenDocument. API still leaves lots to be wished... - [ ods, rstatus ] = oct2jod2ods (c_arr, ods, wsh, crange); + elseif (strcmp (ods.xtype, 'JOD')) + # Write ods file tru Java & jOpenDocument. API still leaves lots to be wished... + [ ods, rstatus ] = oct2jod2ods (c_arr, ods, wsh, crange); - elseif (strcmp (ods.xtype, 'UNO')) - # Write ods file tru Java & UNO bridge (OpenOffice.org & clones) - [ ods, rstatus ] = oct2uno2ods (c_arr, ods, wsh, crange, spsh_opts); + elseif (strcmp (ods.xtype, 'UNO')) + # Write ods file tru Java & UNO bridge (OpenOffice.org & clones) + [ ods, rstatus ] = oct2uno2ods (c_arr, ods, wsh, crange, spsh_opts); -# elseif - # ---- < Other interfaces here > +# elseif + # ---- < Other interfaces here > - else - error (sprintf ("ods2oct: unknown OpenOffice.org .ods interface - %s.", ods.xtype)); - endif + else + error (sprintf ("ods2oct: unknown OpenOffice.org .ods interface - %s.", ods.xtype)); + endif - if (rstatus), ods.limits = []; endif + if (rstatus), ods.limits = []; endif endfunction #============================================================================= -## Copyright (C) 2010,2011 Philip Nienhuis <prn...@us...> +## Copyright (C) 2010,2011,2012 Philip Nienhuis <prn...@us...> ## ## This program is free software; you can redistribute it and/or modify it under ## the terms of the GNU General Public License as published by the Free Software @@ -253,401 +251,401 @@ function [ ods, rstatus ] = oct2jotk2ods (c_arr, ods, wsh, crange, spsh_opts) - persistent ctype; - if (isempty (ctype)) - # Number, Boolean, String, Formula, Empty, Date, Time (last 2 are ignored) - ctype = [1, 2, 3, 4, 5, 6, 7]; - endif + persistent ctype; + if (isempty (ctype)) + # Number, Boolean, String, Formula, Empty, Date, Time (last 2 are ignored) + ctype = [1, 2, 3, 4, 5, 6, 7]; + endif - rstatus = 0; f_errs = 0; + rstatus = 0; f_errs = 0; - # Get some basic spreadsheet data from the pointer using ODFtoolkit - odfcont = ods.workbook; - xpath = ods.app.getXPath (); - offsprdsh = ods.app.getContentRoot(); - autostyles = odfcont.getOrCreateAutomaticStyles(); - officestyles = ods.app.getOrCreateDocumentStyles(); + # Get some basic spreadsheet data from the pointer using ODFtoolkit + odfcont = ods.workbook; + xpath = ods.app.getXPath (); + offsprdsh = ods.app.getContentRoot(); + autostyles = odfcont.getOrCreateAutomaticStyles(); + officestyles = ods.app.getOrCreateDocumentStyles(); - # Create an instance of type NODESET for use in subsequent statements - NODESET = java_get ('javax.xml.xpath.XPathConstants', 'NODESET'); + # Create an instance of type NODESET for use in subsequent statements + NODESET = java_get ('javax.xml.xpath.XPathConstants', 'NODESET'); - # Parse sheets ("tables") from ODS file - sheets = xpath.evaluate ("//table:table", odfcont, NODESET); - nr_of_sheets = sheets.getLength (); - newsh = 0; # Assume existing sheet - if isempty (wsh) wsh = 1; endif - if (~isnumeric (wsh)) # Sheet name specified - # Search in sheet names, match sheet name to sheet number. - # Beware, 0-based index, 1-based count! - ii = 0; - while (++ii <= nr_of_sheets && ischar (wsh)) - # Look in first part of the sheet nodeset - sh_name = sheets.item(ii-1).getTableNameAttribute (); - if (strcmp (sh_name, wsh)) - # Convert local copy of wsh into a number (pointer) - wsh = ii - 1; - endif - endwhile - if (ischar (wsh) && nr_of_sheets < 256) newsh = 1; endif - else # Sheet index specified - if ((ods.changed > 2) || (wsh > nr_of_sheets && wsh < 256)) # Max nr of sheets = 256 - # Create a new sheet - newsh = 1; - elseif (wsh <=nr_of_sheets && wsh > 0) - # Existing sheet. Count = 1-based, index = 0-based - --wsh; sh = sheets.item(wsh); - printf ("Writing to sheet %s\n", sh.getTableNameAttribute()); - else - error ("oct2ods: illegal sheet number."); - endif - endif + # Parse sheets ("tables") from ODS file + sheets = xpath.evaluate ("//table:table", odfcont, NODESET); + nr_of_sheets = sheets.getLength (); + newsh = 0; # Assume existing sheet + if isempty (wsh) wsh = 1; endif + if (~isnumeric (wsh)) # Sheet name specified + # Search in sheet names, match sheet name to sheet number. + # Beware, 0-based index, 1-based count! + ii = 0; + while (++ii <= nr_of_sheets && ischar (wsh)) + # Look in first part of the sheet nodeset + sh_name = sheets.item(ii-1).getTableNameAttribute (); + if (strcmp (sh_name, wsh)) + # Convert local copy of wsh into a number (pointer) + wsh = ii - 1; + endif + endwhile + if (ischar (wsh) && nr_of_sheets < 256) newsh = 1; endif + else # Sheet index specified + if ((ods.changed > 2) || (wsh > nr_of_sheets && wsh < 256)) # Max nr of sheets = 256 + # Create a new sheet + newsh = 1; + elseif (wsh <=nr_of_sheets && wsh > 0) + # Existing sheet. Count = 1-based, index = 0-based + --wsh; sh = sheets.item(wsh); + printf ("Writing to sheet %s\n", sh.getTableNameAttribute()); + else + error ("oct2ods: illegal sheet number."); + endif + endif # Check size of data array & range / capacity of worksheet & prepare vars - [nr, nc] = size (c_arr); - [topleft, nrows, ncols, trow, lcol] = spsh_chkrange (crange, nr, nc, ods.xtype, ods.filename); - --trow; --lcol; # Zero-based row # & col # - if (nrows < nr || ncols < nc) - warning ("Array truncated to fit in range"); - c_arr = c_arr(1:nrows, 1:ncols); - endif - + [nr, nc] = size (c_arr); + [topleft, nrows, ncols, trow, lcol] = spsh_chkrange (crange, nr, nc, ods.xtype, ods.filename); + --trow; --lcol; # Zero-based row # & col # + if (nrows < nr || ncols < nc) + warning ("Array truncated to fit in range"); + c_arr = c_arr(1:nrows, 1:ncols); + endif + # Parse data array, setup typarr and throw out NaNs to speed up writing; - typearr = spsh_prstype (c_arr, nrows, ncols, ctype, spsh_opts, 0); - if ~(spsh_opts.formulas_as_text) - # Find formulas (designated by a string starting with "=" and ending in ")") - fptr = cellfun (@(x) ischar (x) && strncmp (x, "=", 1) && strncmp (x(end:end), ")", 1), c_arr); - typearr(fptr) = ctype(4); # FORMULA - endif + typearr = spsh_prstype (c_arr, nrows, ncols, ctype, spsh_opts, 0); + if ~(spsh_opts.formulas_as_text) + # Find formulas (designated by a string starting with "=" and ending in ")") + fptr = cellfun (@(x) ischar (x) && strncmp (x, "=", 1) && strncmp (x(end:end), ")", 1), c_arr); + typearr(fptr) = ctype(4); # FORMULA + endif # Prepare worksheet for writing. If needed create new sheet - if (newsh) - if (ods.changed > 2) - # New spreadsheet. Prepare to use the default 1x1 first sheet. - sh = sheets.item(0); - else - # Other sheets exist, create a new sheet. First the basics - sh = java_new ('org.odftoolkit.odfdom.doc.table.OdfTable', odfcont); - # Append sheet to spreadsheet ( contentRoot) - offsprdsh.appendChild (sh); - # Rebuild sheets nodes - sheets = xpath.evaluate ("//table:table", odfcont, NODESET); - endif + if (newsh) + if (ods.changed > 2) + # New spreadsheet. Prepare to use the default 1x1 first sheet. + sh = sheets.item(0); + else + # Other sheets exist, create a new sheet. First the basics + sh = java_new ('org.odftoolkit.odfdom.doc.table.OdfTable', odfcont); + # Append sheet to spreadsheet ( contentRoot) + offsprdsh.appendChild (sh); + # Rebuild sheets nodes + sheets = xpath.evaluate ("//table:table", odfcont, NODESET); + endif - # Sheet name - if (isnumeric (wsh)) - # Give sheet a name - str = sprintf ("Sheet%d", wsh); - sh.setTableNameAttribute (str); - else - # Assign name to sheet and change wsh into numeric pointer - sh.setTableNameAttribute (wsh); - wsh = sheets.getLength () - 1; - endif - # Fixup wsh pointer in case of new spreadsheet - if (ods.changed > 2) wsh = 0; endif + # Sheet name + if (isnumeric (wsh)) + # Give sheet a name + str = sprintf ("Sheet%d", wsh); + sh.setTableNameAttribute (str); + else + # Assign name to sheet and change wsh into numeric pointer + sh.setTableNameAttribute (wsh); + wsh = sheets.getLength () - 1; + endif + # Fixup wsh pointer in case of new spreadsheet + if (ods.changed > 2) wsh = 0; endif - # Add table-column entry for style etc - col = sh.addTableColumn (); - col.setTableDefaultCellStyleNameAttribute ("Default"); - col.setTableNumberColumnsRepeatedAttribute (lcol + ncols + 1); - col.setTableStyleNameAttribute ("co1"); + # Add table-column entry for style etc + col = sh.addTableColumn (); + col.setTableDefaultCellStyleNameAttribute ("Default"); + col.setTableNumberColumnsRepeatedAttribute (lcol + ncols + 1); + col.setTableStyleNameAttribute ("co1"); - # Build up the complete row & cell structure to cover the data array. - # This will speed up processing later + # Build up the complete row & cell structure to cover the data array. + # This will speed up processing later - # 1. Build empty table row template - row = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableRow', odfcont); - # Create an empty tablecell & append it to the row - scell = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableCell', odfcont); - scell = row.appendCell (scell); - scell.setTableNumberColumnsRepeatedAttribute (1024); - # 2. If needed add empty filler row above the data rows & if needed add repeat count - if (trow > 0) - sh.appendRow (row); - if (trow > 1) row.setTableNumberRowsRepeatedAttribute (trow); endif - endif - # 3. Add data rows; first one serves as a template - drow = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableRow', odfcont); - if (lcol > 0) - scell = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableCell', odfcont); - drow.appendCell (scell); - if (lcol > 1) scell.setTableNumberColumnsRepeatedAttribute (lcol); endif - endif - # 4. Add data cell placeholders - scell = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableCell', odfcont); - drow.appendCell (scell); - for jj=2:ncols - dcell = scell.cloneNode (1); # Deep copy - drow.appendCell (dcell); - endfor - # 5. Last cell is remaining column counter - rest = max (1024 - lcol - ncols); - if (rest) - dcell = scell.cloneNode (1); # Deep copy - drow.appendCell (dcell); - if (rest > 1) dcell.setTableNumberColumnsRepeatedAttribute (rest); endif - endif - # Only now add drow as otherwise for each cell an empty table-column is - # inserted above the rows (odftoolkit bug?) - sh.appendRow (drow); - if (ods.changed > 2) - # In case of a completely new spreadsheet, delete the first initial 1-cell row - # But check if it *is* a row... - try - sh.removeChild (drow.getPreviousRow ()); - catch - # Nothing. Apparently there was only the just appended row. - end_try_catch - endif - # 6. Row template ready. Copy row template down to cover future array - for ii=2:nrows - nrow = drow.cloneNode (1); # Deep copy - sh.appendRow (nrow); - endfor - ods.changed = min (ods.changed, 2); # Keep 2 for new spshsht, 1 for existing + changed + # 1. Build empty table row template + row = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableRow', odfcont); + # Create an empty tablecell & append it to the row + scell = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableCell', odfcont); + scell = row.appendCell (scell); + scell.setTableNumberColumnsRepeatedAttribute (1024); + # 2. If needed add empty filler row above the data rows & if needed add repeat count + if (trow > 0) + sh.appendRow (row); + if (trow > 1) row.setTableNumberRowsRepeatedAttribute (trow); endif + endif + # 3. Add data rows; first one serves as a template + drow = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableRow', odfcont); + if (lcol > 0) + scell = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableCell', odfcont); + drow.appendCell (scell); + if (lcol > 1) scell.setTableNumberColumnsRepeatedAttribute (lcol); endif + endif + # 4. Add data cell placeholders + scell = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableCell', odfcont); + drow.appendCell (scell); + for jj=2:ncols + dcell = scell.cloneNode (1); # Deep copy + drow.appendCell (dcell); + endfor + # 5. Last cell is remaining column counter + rest = max (1024 - lcol - ncols); + if (rest) + dcell = scell.cloneNode (1); # Deep copy + drow.appendCell (dcell); + if (rest > 1) dcell.setTableNumberColumnsRepeatedAttribute (rest); endif + endif + # Only now add drow as otherwise for each cell an empty table-column is + # inserted above the rows (odftoolkit bug?) + sh.appendRow (drow); + if (ods.changed > 2) + # In case of a completely new spreadsheet, delete the first initial 1-cell row + # But check if it *is* a row... + try + sh.removeChild (drow.getPreviousRow ()); + catch + # Nothing. Apparently there was only the just appended row. + end_try_catch + endif + # 6. Row template ready. Copy row template down to cover future array + for ii=2:nrows + nrow = drow.cloneNode (1); # Deep copy + sh.appendRow (nrow); + endfor + ods.changed = min (ods.changed, 2); # Keep 2 for new spshsht, 1 for existing + changed - else - # Existing sheet. We must be prepared for all situations, incomplete rows, - # number-rows/columns-repeated, merged (spanning) cells, you name it. - # First explore row buildup of existing sheet using an XPath - sh = sheets.item(wsh); # 0 - based - str = sprintf ("//table:table[%d]/table:table-row", wsh + 1); # 1 - based - trows = xpath.evaluate (str, odfcont, NODESET); - nr_of_trows = trows.getLength(); # Nr. of existing table-rows, not data rows! + else + # Existing sheet. We must be prepared for all situations, incomplete rows, + # number-rows/columns-repeated, merged (spanning) cells, you name it. + # First explore row buildup of existing sheet using an XPath + sh = sheets.item(wsh); # 0 - based + str = sprintf ("//table:table[%d]/table:table-row", wsh + 1); # 1 - based + trows = xpath.evaluate (str, odfcont, NODESET); + nr_of_trows = trows.getLength(); # Nr. of existing table-rows, not data rows! - # For the first rows we do some preprocessing here. Similar stuff for cells - # i.e. table-cells (columns) is done in the loops below. - # Make sure the upper data array row doesn't end up in a nr-rows-repeated row + # For the first rows we do some preprocessing here. Similar stuff for cells + # i.e. table-cells (columns) is done in the loops below. + # Make sure the upper data array row doesn't end up in a nr-rows-repeated row - # Provisionally! set start table-row in case "while" & "if" (split) are skipped - drow = trows.item(0); - rowcnt = 0; trowcnt = 0; # Spreadsheet/ table-rows, resp; - while (rowcnt < trow && trowcnt < nr_of_trows) - # Count rows & table-rows UNTIL we reach trow - ++trowcnt; # Nr of table-rows - row = drow; - drow = row.getNextSibling (); - repcnt = row.getTableNumberRowsRepeatedAttribute(); - rowcnt = rowcnt + repcnt; # Nr of spreadsheet rows - endwhile - rsplit = rowcnt - trow; - if (rsplit > 0) - # Apparently a nr-rows-repeated top table-row must be split, as the - # first data row seems to be projected in it (1st while condition above!) - row.removeAttribute ('table:number-rows-repeated'); - row.getCellAt (0).removeAttribute ('table:number-columns-repeated'); - nrow = row.cloneNode (1); - drow = nrow; # Future upper data array row - if (repcnt > 1) - row.setTableNumberRowsRepeatedAttribute (repcnt - rsplit); - else - row.removeAttribute ('table:number-rows-repeated'); - endif - rrow = row.getNextSibling (); - sh.insertBefore (nrow, rrow); - for jj=2:rsplit - nrow = nrow.cloneNode (1); - sh.insertBefore (nrow, rrow); - endfor - elseif (rsplit < 0) - # New data rows to be added below existing data & table(!) rows, i.e. - # beyond lower end of the current sheet. Add filler row and 1st data row - row = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableRow', odfcont); - drow = row.cloneNode (1); # First data row - row.setTableNumberRowsRepeatedAttribute (-rsplit); # Filler row - scell = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableCell', odfcont); - dcell = scell.cloneNode (1); - scell.setTableNumberColumnsRepeatedAttribute (COL_CAP); # Filler cell - row.appendCell (scell); - sh.appendRow (row); - drow.appendCell (dcell); - sh.appendRow (drow); - endif - endif + # Provisionally! set start table-row in case "while" & "if" (split) are skipped + drow = trows.item(0); + rowcnt = 0; trowcnt = 0; # Spreadsheet/ table-rows, resp; + while (rowcnt < trow && trowcnt < nr_of_trows) + # Count rows & table-rows UNTIL we reach trow + ++trowcnt; # Nr of table-rows + row = drow; + drow = row.getNextSibling (); + repcnt = row.getTableNumberRowsRepeatedAttribute(); + rowcnt = rowcnt + repcnt; # Nr of spreadsheet rows + endwhile + rsplit = rowcnt - trow; + if (rsplit > 0) + # Apparently a nr-rows-repeated top table-row must be split, as the + # first data row seems to be projected in it (1st while condition above!) + row.removeAttribute ('table:number-rows-repeated'); + row.getCellAt (0).removeAttribute ('table:number-columns-repeated'); + nrow = row.cloneNode (1); + drow = nrow; # Future upper data array row + if (repcnt > 1) + row.setTableNumberRowsRepeatedAttribute (repcnt - rsplit); + else + row.removeAttribute ('table:number-rows-repeated'); + endif + rrow = row.getNextSibling (); + sh.insertBefore (nrow, rrow); + for jj=2:rsplit + nrow = nrow.cloneNode (1); + sh.insertBefore (nrow, rrow); + endfor + elseif (rsplit < 0) + # New data rows to be added below existing data & table(!) rows, i.e. + # beyond lower end of the current sheet. Add filler row and 1st data row + row = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableRow', odfcont); + drow = row.cloneNode (1); # First data row + row.setTableNumberRowsRepeatedAttribute (-rsplit); # Filler row + scell = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableCell', odfcont); + dcell = scell.cloneNode (1); + scell.setTableNumberColumnsRepeatedAttribute (COL_CAP); # Filler cell + row.appendCell (scell); + sh.appendRow (row); + drow.appendCell (dcell); + sh.appendRow (drow); + endif + endif # For each row, for each cell, add the data. Expand row/column-repeated nodes - row = drow; # Start row; pointer still exists from above stanzas - for ii=1:nrows - if (~newsh) # Only for existing sheets the next checks should be made - # While processing next data rows, fix table-rows if needed - if (isempty (row) || (row.getLength () < 1)) - # Append an empty row with just one empty cell - row = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableRow', odfcont); - scell = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableCell', odfcont); - scell.setTableNumberColumnsRepeatedAttribute (lcol + 1); - row.appendCell (scell); - sh.appendRow (row); - else - # If needed expand nr-rows-repeated - repcnt = row.getTableNumberRowsRepeatedAttribute (); - if (repcnt > 1) - row.removeAttribute ('table:number-rows-repeated'); - # Insert new table-rows above row until our new data space is complete. - # Keep handle of upper new table-row as that's where data are added 1st - drow = row.cloneNode (1); - sh.insertBefore (drow, row); - for kk=1:min (repcnt, nrows-ii) - nrow = row.cloneNode (1); - sh.insertBefore (nrow, row); - endfor - if (repcnt > nrows-ii+1) - row.setTableNumberRowsRepeatedAttribute (repcnt - nrows +ii - 1); - endif - row = drow; - endif - endif + row = drow; # Start row; pointer still exists from above stanzas + for ii=1:nrows + if (~newsh) # Only for existing sheets the next checks should be made + # While processing next data rows, fix table-rows if needed + if (isempty (row) || (row.getLength () < 1)) + # Append an empty row with just one empty cell + row = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableRow', odfcont); + scell = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableCell', odfcont); + scell.setTableNumberColumnsRepeatedAttribute (lcol + 1); + row.appendCell (scell); + sh.appendRow (row); + else + # If needed expand nr-rows-repeated + repcnt = row.getTableNumberRowsRepeatedAttribute (); + if (repcnt > 1) + row.removeAttribute ('table:number-rows-repeated'); + # Insert new table-rows above row until our new data space is complete. + # Keep handle of upper new table-row as that's where data are added 1st + drow = row.cloneNode (1); + sh.insertBefore (drow, row); + for kk=1:min (repcnt, nrows-ii) + nrow = row.cloneNode (1); + sh.insertBefore (nrow, row); + endfor + if (repcnt > nrows-ii+1) + row.setTableNumberRowsRepeatedAttribute (repcnt - nrows +ii - 1); + endif + row = drow; + endif + endif - # Check if leftmost cell ends up in nr-cols-repeated cell - colcnt = 0; tcellcnt = 0; rcellcnt = row.getLength(); - dcell = row.getCellAt (0); - while (colcnt < lcol && tcellcnt < rcellcnt) - # Count columns UNTIL we hit lcol - ++tcellcnt; # Nr of table-cells counted - scell = dcell; - dcell = scell.getNextSibling (); - repcnt = scell.getTableNumberColumnsRepeatedAttribute (); - colcnt = colcnt + repcnt; # Nr of spreadsheet cell counted - endwhile - csplit = colcnt - lcol; - if (csplit > 0) - # Apparently a nr-columns-repeated cell must be split - scell.removeAttribute ('table:number-columns-repeated'); - ncell = scell.cloneNode (1); - if (repcnt > 1) - scell.setTableNumberColumnsRepeatedAttribute (repcnt - csplit); - else - scell.removeAttribute ('table:number-columns-repeated'); - endif - rcell = scell.getNextSibling (); - row.insertBefore (ncell, rcell); - for jj=2:csplit - ncell = ncell.cloneNode (1); - row.insertBefore (ncell, rcell); - endfor - elseif (csplit < 0) - # New cells to be added beyond current last cell & table-cell in row - dcell = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableCell', odfcont); - scell = dcell.cloneNode (1); - dcell.setTableNumberColumnsRepeatedAttribute (-csplit); - row.appendCell (dcell); - row.appendCell (scell); - endif - endif + # Check if leftmost cell ends up in nr-cols-repeated cell + colcnt = 0; tcellcnt = 0; rcellcnt = row.getLength(); + dcell = row.getCellAt (0); + while (colcnt < lcol && tcellcnt < rcellcnt) + # Count columns UNTIL we hit lcol + ++tcellcnt; # Nr of table-cells counted + scell = dcell; + dcell = scell.getNextSibling (); + repcnt = scell.getTableNumberColumnsRepeatedAttribute (); + colcnt = colcnt + repcnt; # Nr of spreadsheet cell counted + endwhile + csplit = colcnt - lcol; + if (csplit > 0) + # Apparently a nr-columns-repeated cell must be split + scell.removeAttribute ('table:number-columns-repeated'); + ncell = scell.cloneNode (1); + if (repcnt > 1) + scell.setTableNumberColumnsRepeatedAttribute (repcnt - csplit); + else + scell.removeAttribute ('table:number-columns-repeated'); + endif + rcell = scell.getNextSibling (); + row.insertBefore (ncell, rcell); + for jj=2:csplit + ncell = ncell.cloneNode (1); + row.insertBefore (ncell, rcell); + endfor + elseif (csplit < 0) + # New cells to be added beyond current last cell & table-cell in row + dcell = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableCell', odfcont); + scell = dcell.cloneNode (1); + dcell.setTableNumberColumnsRepeatedAttribute (-csplit); + row.appendCell (dcell); + row.appendCell (scell); + endif + endif - # Write a row of data from data array, column by column - - for jj=1:ncols - scell = row.getCellAt (lcol + jj - 1); - if (~newsh) - if (isempty (scell)) - # Apparently end of row encountered. Add cell - scell = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableCell', odfcont); - scell = row.appendCell (scell); - else - # If needed expand nr-cols-repeated - repcnt = scell.getTableNumberColumnsRepeatedAttribute (); - if (repcnt > 1) - scell.removeAttribute ('table:number-columns-repeated'); - for kk=2:repcnt - ncell = scell.cloneNode (1); - row.insertBefore (ncell, scell.getNextSibling ()); - endfor - endif - endif - # Clear text contents - while (scell.hasChildNodes ()) - tmp = scell.getFirstChild (); - scell.removeChild (tmp); - endwhile - scell.removeAttribute ('table:formula'); - endif + # Write a row of data from data array, column by column + + for jj=1:ncols + scell = row.getCellAt (lcol + jj - 1); + if (~newsh) + if (isempty (scell)) + # Apparently end of row encountered. Add cell + scell = java_new ('org.odftoolkit.odfdom.doc.table.OdfTableCell', odfcont); + scell = row.appendCell (scell); + else + # If needed expand nr-cols-repeated + repcnt = scell.getTableNumberColumnsRepeatedAttribute (); + if (repcnt > 1) + scell.removeAttribute ('table:number-columns-repeated'); + for kk=2:repcnt + ncell = scell.cloneNode (1); + row.insertBefore (ncell, scell.getNextSibling ()); + endfor + endif + endif + # Clear text contents + while (scell.hasChildNodes ()) + tmp = scell.getFirstChild (); + scell.removeChild (tmp); + endwhile + scell.removeAttribute ('table:formula'); + endif - # Empty cell count stuff done. At last we can add the data - switch (typearr (ii, jj)) - case 1 # float - scell.setOfficeValueTypeAttribute ('float'); - scell.setOfficeValueAttribute (c_arr{ii, jj}); - case 2 # boolean - # Beware, for unpatched-for-booleans java-1.2.7- we must resort to floats - try - # First try the preferred java-boolean way - scell.setOfficeValueTypeAttribute ('boolean'); - scell.removeAttribute ('office:value'); - if (c_arr{ii, jj}) - scell.setOfficeBooleanValueAttribute (1); - else - scell.setOfficeBooleanValueAttribute (0); - endif - catch - # Unpatched java package. Fall back to transferring a float - scell.setOfficeValueTypeAttribute ('float'); - if (c_arr{ii, jj}) - scell.setOfficeValueAttribute (1); - else - scell.setOfficeValueAttribute (0); - endif - end_try_catch - case 3 # string - scell.setOfficeValueTypeAttribute ('string'); - pe = java_new ('org.odftoolkit.odfdom.doc.text.OdfTextParagraph', odfcont,'', c_arr{ii, jj}); - scell.appendChild (pe); - case 4 # Formula. - # As we don't know the result type, simply remove previous type info. - # Once OOo Calc reads it, it'll add the missing attributes - scell.removeAttribute ('office:value'); - scell.removeAttribute ('office:value-type'); - # Try-catch not strictly needed, there's no formula validator yet - try - scell.setTableFormulaAttribute (c_arr{ii, jj}); - scell.setOfficeValueTypeAttribute ('string'); - pe = java_new ('org.odftoolkit.odfdom.doc.text.OdfTextParagraph', odfcont,'', '#Recalc Formula#'); - scell.appendChild (pe); - catch - ++f_errs; - scell.setOfficeValueTypeAttribute ('string'); - pe = java_new ('org.odftoolkit.odfdom.doc.text.OdfTextParagraph', odfcont,'', c_arr{ii, jj}); - scell.appendChild (pe); - end_try_catch - case {0 5} # Empty. Clear value attributes - if (~newsh) - scell.removeAttribute ('office:value-type'); - scell.removeAttribute ('office:value'); - endif - case 6 # Date (implemented but Octave has no "date" data type - yet?) - scell.setOfficeValueTypeAttribute ('date'); - [hh mo dd hh mi ss] = datevec (c_arr{ii,jj}); - str = sprintf ("%4d-%2d-%2dT%2d:%2d:%2d", yy, mo, dd, hh, mi, ss); - scell.setOfficeDateValueAttribute (str); - case 7 # Time (implemented but Octave has no "time" data type) - scell.setOfficeValueTypeAttribute ('time'); - [hh mo dd hh mi ss] = datevec (c_arr{ii,jj}); - str = sprintf ("PT%2d:%2d:%2d", hh, mi, ss); - scell.setOfficeTimeValuettribute (str); - otherwise - # Nothing - endswitch + # Empty cell count stuff done. At last we can add the data + switch (typearr (ii, jj)) + case 1 # float + scell.setOfficeValueTypeAttribute ('float'); + scell.setOfficeValueAttribute (c_arr{ii, jj}); + case 2 # boolean + # Beware, for unpatched-for-booleans java-1.2.7- we must resort to floats + try + # First try the preferred java-boolean way + scell.setOfficeValueTypeAttribute ('boolean'); + scell.removeAttribute ('office:value'); + if (c_arr{ii, jj}) + scell.setOfficeBooleanValueAttribute (1); + else + scell.setOfficeBooleanValueAttribute (0); + endif + catch + # Unpatched java package. Fall back to transferring a float + scell.setOfficeValueTypeAttribute ('float'); + if (c_arr{ii, jj}) + scell.setOfficeValueAttribute (1); + else + scell.setOfficeValueAttribute (0); + endif + end_try_catch + case 3 # string + scell.setOfficeValueTypeAttribute ('string'); + pe = java_new ('org.odftoolkit.odfdom.doc.text.OdfTextParagraph', odfcont,'', c_arr{ii, jj}); + scell.appendChild (pe); + case 4 # Formula. + # As we don't know the result type, simply remove previous type info. + # Once OOo Calc reads it, it'll add the missing attributes + scell.removeAttribute ('office:value'); + scell.removeAttribute ('office:value-type'); + # Try-catch not strictly needed, there's no formula validator yet + try + scell.setTableFormulaAttribute (c_arr{ii, jj}); + scell.setOfficeValueTypeAttribute ('string'); + pe = java_new ('org.odftoolkit.odfdom.doc.text.OdfTextParagraph', odfcont,'', '#Recalc Formula#'); + scell.appendChild (pe); + catch + ++f_errs; + scell.setOfficeValueTypeAttribute ('string'); + pe = java_new ('org.odftoolkit.odfdom.doc.text.OdfTextParagraph', odfcont,'', c_arr{ii, jj}); + scell.appendChild (pe); + end_try_catch + case {0 5} # Empty. Clear value attributes + if (~newsh) + scell.removeAttribute ('office:value-type'); + scell.removeAttribute ('office:value'); + endif + case 6 # Date (implemented but Octave has no "date" data type - yet?) + scell.setOfficeValueTypeAttribute ('date'); + [hh mo dd hh mi ss] = datevec (c_arr{ii,jj}); + str = sprintf ("%4d-%2d-%2dT%2d:%2d:%2d", yy, mo, dd, hh, mi, ss); + scell.setOfficeDateValueAttribute (str); + case 7 # Time (implemented but Octave has no "time" data type) + scell.setOfficeValueTypeAttribute ('time'); + [hh mo dd hh mi ss] = datevec (c_arr{ii,jj}); + str = sprintf ("PT%2d:%2d:%2d", hh, mi, ss); + scell.setOfficeTimeValuettribute (str); + otherwise + # Nothing + endswitch - scell = scell.getNextSibling (); + scell = scell.getNextSibling (); - endfor + endfor - row = row.getNextSibling (); + row = row.getNextSibling (); - endfor + endfor - if (f_errs) - printf ("%d formula errors encountered - please check input array\n", f_errs); - endif - ods.changed = max (min (ods.changed, 2), changed); # Preserve 2 (new file), 1 (existing) - rstatus = 1; - + if (f_errs) + printf ("%d formula errors encountered - please check input array\n", f_errs); + endif + ods.changed = max (min (ods.changed, 2), changed); # Preserve 2 (new file), 1 (existing) + rstatus = 1; + endfunction #============================================================================= -## Copyright (C) 2010,2011 Philip Nienhuis <prnienhuis _at- users.sf.net> +## Copyright (C) 2010,2011,2012 Philip Nienhuis <prnienhuis _at- users.sf.net> ## ## This program is free software; you can redistribute it and/or modify it under ## the terms of the GNU General Public License as published by the Free Software @@ -662,9 +660,9 @@ ## You should have received a copy of the GNU General Public License along with ## this program; if not, see <http://www.gnu.org/licenses/>. -## odf3jotk2oct - read ODS spreadsheet data using Java & odftoolkit v 0.8.6. -## You need proper java-for-octave & odfdom.jar 0.8.6 + xercesImpl.jar -## in your javaclasspath. For reliable writing odfdom-0.8.6 is still +## odf3jotk2oct - read ODS spreadsheet data using Java & odftoolkit v 0.8.6+. +## You need proper java-for-octave & odfdom.jar 0.8.6+ & xercesImpl.jar 2.9.1 +## in your javaclasspath. For reliable writing odfdom-0.8.6+ is still ## experimental :-( v. 0.7.5 has been tested much more ## ## Author: Philip Nenhuis <pr.nienhuis at users.sf.net> @@ -684,167 +682,168 @@ ## 2010-11-12 Improved file change tracking tru ods.changed ## 2010-12-08 Bugfixes (obj -> arg L.715; removed stray arg in call to spsh_prstype L.719) ## 2011-03-23 First try of odfdom 0.8.7 +## 2012-06-08 Support for odfdom-incubator-0.8.8 function [ ods, rstatus ] = oct3jotk2ods (c_arr, ods, wsh, crange, spsh_opts) - persistent ctype; - if (isempty (ctype)) - # Number, Boolean, String, Formula, Empty; Date, Time - last two aren't used - ctype = [1, 2, 3, 4, 5, 6, 7]; - endif + persistent ctype; + if (isempty (ctype)) + # Number, Boolean, String, Formula, Empty; Date, Time - last two aren't used + ctype = [1, 2, 3, 4, 5, 6, 7]; + endif - rstatus = 0; changed = 0; newsh = 0; + rstatus = 0; changed = 0; newsh = 0; - # Get... [truncated message content] |