Mercurial > forge
changeset 11533:761eecba969d octave-forge
Fixed bug in finding existing sheetnames i.c.o. numeric sheet name arg
author | prnienhuis |
---|---|
date | Sun, 10 Mar 2013 20:21:15 +0000 |
parents | c0bf85c65b80 |
children | 382b39bdbf61 |
files | main/io/inst/private/__UNO_oct2spsh__.m |
diffstat | 1 files changed, 171 insertions(+), 170 deletions(-) [+] |
line wrap: on
line diff
--- a/main/io/inst/private/__UNO_oct2spsh__.m Sun Mar 10 13:02:11 2013 +0000 +++ b/main/io/inst/private/__UNO_oct2spsh__.m Sun Mar 10 20:21:15 2013 +0000 @@ -1,170 +1,171 @@ -## Copyright (C) 2011,2012,2013 Philip Nienhuis <prnienhuis@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 -## Foundation; either version 3 of the License, or (at your option) any later -## version. -## -## This program is distributed in the hope that it will be useful, but WITHOUT -## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -## details. -## -## You should have received a copy of the GNU General Public License along with -## this program; if not, see <http://www.gnu.org/licenses/>. - -## oct2uno2xls - Internal function: write to spreadsheet file using UNO-Java bridge - -## Author: Philip Nienhuis <prnienhuis@users.sf.net> -## Created: 2011-05-18 -## 2011-09-18 Adapted sh_names type to LO 3.4.1 -## 2011-09-23 Removed stray debug statements -## 2012-02-25 Fixed wrong var name in L.933 -## 2012-02-25 Catch stray Java RuntimeException when deleting sheets -## 2012-02-26 Bug fix when adding sheets near L.994 (wrong if-else-end construct). -## 2012-02-27 Copyright strings updated -## 2012-05-21 "Double" cast added when writing numeric values -## 2012-05-21 "Double" cast moved into main func oct2xls -## 2012-10-12 Renamed & moved into ./private -## 2012-10-24 Style fixes -## 2012-12-21 Search for exact match when searching sheet names -## 2013-01-20 Adapted to ML-compatible Java calls - -function [ xls, rstatus ] = __UNO_oct2spsh__ (c_arr, xls, wsh, crange, spsh_opts) - - changed = 0; - newsh = 0; - ctype = [1, 2, 3, 4, 5]; ## Float, Logical, String, Formula, Empty - - ## Get handle to sheet, create a new one if needed - sheets = xls.workbook.getSheets (); - sh_names = sheets.getElementNames (); - if (! iscell (sh_names)) - ## Java array (LibreOffice 3.4.+); convert to cellstr - sh_names = char (sh_names); - else - sh_names = {sh_names}; - endif - - ## Clear default 2 last sheets in case of a new spreadsheet file - if (xls.changed > 2) - ii = numel (sh_names); - while (ii > 1) - shnm = sh_names{ii}; - try - ## Catch harmless Java RuntimeException "out of range" in LibreOffice 3.5rc1 - sheets.removeByName (shnm); - end_try_catch - --ii; - endwhile - ## Give remaining sheet a name - unotmp = javaObject ("com.sun.star.uno.Type", "com.sun.star.sheet.XSpreadsheet"); - sh = sheets.getByName (sh_names{1}).getObject.queryInterface (unotmp); - if (isnumeric (wsh)); wsh = sprintf ("Sheet%d", wsh); endif - unotmp = javaObject ("com.sun.star.uno.Type", "com.sun.star.container.XNamed"); - sh.queryInterface (unotmp).setName (wsh); - else - - ## Check sheet pointer - ## FIXME sheet capacity check needed - if (isnumeric (wsh)) - if (wsh < 1) - error ("Illegal sheet index: %d", wsh); - elseif (wsh > numel (sh_names)) - ## New sheet to be added. First create sheet name but check if it already exists - shname = sprintf ("Sheet%d", numel (sh_names) + 1); - jj = strmatch (wsh, sh_names, "exact"); - if (~isempty (jj)) - ## New sheet name already in file, try to create a unique & reasonable one - ii = 1; filler = ""; maxtry = 5; - while (ii <= maxtry) - shname = sprintf ("Sheet%s%d", [filler "_"], numel (sh_names + 1)); - if (isempty (strmatch (wsh, sh_names, "exact"))) - ii = 10; - else - ++ii; - endif - endwhile - if (ii > maxtry + 1) - error ("Could not add sheet with a unique name to file %s"); - endif - endif - wsh = shname; - newsh = 1; - else - ## turn wsh index into the associated sheet name - wsh = sh_names (wsh); - endif - else - ## wsh is a sheet name. See if it exists already - if (isempty (strmatch (wsh, sh_names, "exact"))) - ## Not found. New sheet to be added - newsh = 1; - endif - endif - if (newsh) - ## Add a new sheet. Sheet index MUST be a Java Short object - shptr = javaObject ("java.lang.Short", sprintf ("%d", numel (sh_names) + 1)); - sh = sheets.insertNewByName (wsh, shptr); - endif - ## At this point we have a valid sheet name. Use it to get a sheet handle - unotmp = javaObject ("com.sun.star.uno.Type", "com.sun.star.sheet.XSpreadsheet"); - sh = sheets.getByName (wsh).getObject.queryInterface (unotmp); - 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, xls.xtype, xls.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), c_arr); - typearr(fptr) = ctype(4); ## FORMULA - endif - - ## Transfer data to sheet - for ii=1:nrows - for jj=1:ncols - try - XCell = sh.getCellByPosition (lcol+jj-1, trow+ii-1); - switch typearr(ii, jj) - case 1 ## Float - XCell.setValue (c_arr{ii, jj}); - case 2 ## Logical. Convert to float as OOo has no Boolean type - XCell.setValue (double (c_arr{ii, jj})); - case 3 ## String - unotmp = javaObject ("com.sun.star.uno.Type", "com.sun.star.text.XText"); - XCell.queryInterface (unotmp).setString (c_arr{ii, jj}); - case 4 ## Formula - if (spsh_opts.formulas_as_text) - unotmp = javaObject ("com.sun.star.uno.Type", "com.sun.star.text.XText"); - XCell.queryInterface (unotmp).setString (c_arr{ii, jj}); - else - XCell.setFormula (c_arr{ii, jj}); - endif - otherwise - ## Empty cell - endswitch - changed = 1; - catch - printf ("Error writing cell %s (typearr() = %d)\n",... - calccelladdress(trow+ii, lcol+jj), typearr(ii, jj)); - end_try_catch - endfor - endfor - - if (changed) - ## Preserve 2 (new file), 1 (existing) - xls.changed = max (min (xls.changed, 2), changed); - rstatus = 1; - endif - -endfunction +## Copyright (C) 2011,2012,2013 Philip Nienhuis <prnienhuis@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 +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see <http://www.gnu.org/licenses/>. + +## oct2uno2xls - Internal function: write to spreadsheet file using UNO-Java bridge + +## Author: Philip Nienhuis <prnienhuis@users.sf.net> +## Created: 2011-05-18 +## 2011-09-18 Adapted sh_names type to LO 3.4.1 +## 2011-09-23 Removed stray debug statements +## 2012-02-25 Fixed wrong var name in L.933 +## 2012-02-25 Catch stray Java RuntimeException when deleting sheets +## 2012-02-26 Bug fix when adding sheets near L.994 (wrong if-else-end construct). +## 2012-02-27 Copyright strings updated +## 2012-05-21 "Double" cast added when writing numeric values +## 2012-05-21 "Double" cast moved into main func oct2xls +## 2012-10-12 Renamed & moved into ./private +## 2012-10-24 Style fixes +## 2012-12-21 Search for exact match when searching sheet names +## 2013-01-20 Adapted to ML-compatible Java calls +## 2013-03-10 Fixed bug in finding existing sheetnames i.c.o. numeric sheet name arg + +function [ xls, rstatus ] = __UNO_oct2spsh__ (c_arr, xls, wsh, crange, spsh_opts) + + changed = 0; + newsh = 0; + ctype = [1, 2, 3, 4, 5]; ## Float, Logical, String, Formula, Empty + + ## Get handle to sheet, create a new one if needed + sheets = xls.workbook.getSheets (); + sh_names = sheets.getElementNames (); + if (! iscell (sh_names)) + ## Java array (LibreOffice 3.4.+); convert to cellstr + sh_names = char (sh_names); + else + sh_names = {sh_names}; + endif + + ## Clear default 2 last sheets in case of a new spreadsheet file + if (xls.changed > 2) + ii = numel (sh_names); + while (ii > 1) + shnm = sh_names{ii}; + try + ## Catch harmless Java RuntimeException "out of range" in LibreOffice 3.5rc1 + sheets.removeByName (shnm); + end_try_catch + --ii; + endwhile + ## Give remaining sheet a name + unotmp = javaObject ("com.sun.star.uno.Type", "com.sun.star.sheet.XSpreadsheet"); + sh = sheets.getByName (sh_names{1}).getObject.queryInterface (unotmp); + if (isnumeric (wsh)); wsh = sprintf ("Sheet%d", wsh); endif + unotmp = javaObject ("com.sun.star.uno.Type", "com.sun.star.container.XNamed"); + sh.queryInterface (unotmp).setName (wsh); + else + + ## Check sheet pointer + ## FIXME sheet capacity check needed + if (isnumeric (wsh)) + if (wsh < 1) + error ("Illegal sheet index: %d", wsh); + elseif (wsh > numel (sh_names)) + ## New sheet to be added. First create sheet name but check if it already exists + shname = sprintf ("Sheet%d", numel (sh_names) + 1); + jj = strmatch (shname, sh_names, "exact"); + if (~isempty (jj)) + ## New sheet name already in file, try to create a unique & reasonable one + ii = 1; filler = ""; maxtry = 5; + while (ii <= maxtry) + shname = sprintf ("Sheet%s%d", [filler "_"], numel (sh_names + 1)); + if (isempty (strmatch (shname, sh_names, "exact"))) + ii = 10; + else + ++ii; + endif + endwhile + if (ii > maxtry + 1) + error ("Could not add sheet with a unique name to file %s"); + endif + endif + wsh = shname; + newsh = 1; + else + ## turn wsh index into the associated sheet name + wsh = sh_names (wsh); + endif + else + ## wsh is a sheet name. See if it exists already + if (isempty (strmatch (wsh, sh_names, "exact"))) + ## Not found. New sheet to be added + newsh = 1; + endif + endif + if (newsh) + ## Add a new sheet. Sheet index MUST be a Java Short object + shptr = javaObject ("java.lang.Short", sprintf ("%d", numel (sh_names) + 1)); + sh = sheets.insertNewByName (wsh, shptr); + endif + ## At this point we have a valid sheet name. Use it to get a sheet handle + unotmp = javaObject ("com.sun.star.uno.Type", "com.sun.star.sheet.XSpreadsheet"); + sh = sheets.getByName (wsh).getObject.queryInterface (unotmp); + 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, xls.xtype, xls.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), c_arr); + typearr(fptr) = ctype(4); ## FORMULA + endif + + ## Transfer data to sheet + for ii=1:nrows + for jj=1:ncols + try + XCell = sh.getCellByPosition (lcol+jj-1, trow+ii-1); + switch typearr(ii, jj) + case 1 ## Float + XCell.setValue (c_arr{ii, jj}); + case 2 ## Logical. Convert to float as OOo has no Boolean type + XCell.setValue (double (c_arr{ii, jj})); + case 3 ## String + unotmp = javaObject ("com.sun.star.uno.Type", "com.sun.star.text.XText"); + XCell.queryInterface (unotmp).setString (c_arr{ii, jj}); + case 4 ## Formula + if (spsh_opts.formulas_as_text) + unotmp = javaObject ("com.sun.star.uno.Type", "com.sun.star.text.XText"); + XCell.queryInterface (unotmp).setString (c_arr{ii, jj}); + else + XCell.setFormula (c_arr{ii, jj}); + endif + otherwise + ## Empty cell + endswitch + changed = 1; + catch + printf ("Error writing cell %s (typearr() = %d)\n",... + calccelladdress(trow+ii, lcol+jj), typearr(ii, jj)); + end_try_catch + endfor + endfor + + if (changed) + ## Preserve 2 (new file), 1 (existing) + xls.changed = max (min (xls.changed, 2), changed); + rstatus = 1; + endif + +endfunction