]> Creatis software - CreaPhase.git/blobdiff - octave_packages/io-1.0.19/xlsopen.m
Add a useful package (from Source forge) for octave
[CreaPhase.git] / octave_packages / io-1.0.19 / xlsopen.m
diff --git a/octave_packages/io-1.0.19/xlsopen.m b/octave_packages/io-1.0.19/xlsopen.m
new file mode 100644 (file)
index 0000000..13c83e9
--- /dev/null
@@ -0,0 +1,647 @@
+## Copyright (C) 2009,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 Foundation; either version 2 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 Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} @var{xls} = xlsopen (@var{filename})
+## @deftypefnx {Function File} @var{xls} = xlsopen (@var{filename}, @var{readwrite})
+## @deftypefnx {Function File} @var{xls} = xlsopen (@var{filename}, @var{readwrite}, @var{reqintf})
+## Get a pointer to an Excel spreadsheet in the form of return argument
+## (file pointer struct) @var{xls}. After processing the spreadsheet,
+## the file pointer must be explicitly closed by calling xlsclose().
+##
+## Calling xlsopen without specifying a return argument is fairly useless!
+##
+## To make this function work at all, you need MS-Excel (95 - 2003), and/or
+## the Java package >= 1.2.8 plus Apache POI >= 3.5 and/or JExcelAPI and/or
+## OpenXLS and/or OpenOffice.org (or clones) installed on your computer +
+## proper javaclasspath set. These interfaces are referred to as COM, POI,
+## JXL, OXS, and UNO, resp., and are preferred in that order by default
+## (depending on their presence).
+## For OOXML support, in addition to Apache POI support you also need the
+## following jars in your javaclasspath: poi-ooxml-schemas-3.5.jar,
+## xbean.jar and dom4j-1.6.1.jar (or later versions). Later OpenOffice.org
+## versions (UNO) have support for OOXML as well.
+## Excel'95 spreadsheets can only be read by JExcelAPI and OpenOffice.org.
+##
+## @var{filename} should be a valid .xls or xlsx Excel file name (including
+## extension). But if you use the COM interface you can specify any extension
+## that your installed Excel version can read AND write; the same goes for UNO
+## (OpenOffice.org). Using the other Java interfaces, only .xls or .xlsx are
+## allowed. If @var{filename} does not contain any directory path, the file
+## is saved in the current directory.
+##
+## If @var{readwrite} is set to 0 (default value) or omitted, the Excel file
+## is opened for reading. If @var{readwrite} is set to True or 1, an Excel
+## file is opened (or created) for reading & writing.
+##
+## Optional input argument @var{reqintf} can be used to override the Excel
+## interface that otherwise is automatically selected by xlsopen. Currently
+## implemented interfaces (in order of preference) are 'COM' (Excel/COM),
+## 'POI' (Java/Apache POI), 'JXL' (Java/JExcelAPI), 'OXS' (Java/OpenXLS), or
+## 'UNO' (Java/OpenOffice.org - EXPERIMENTAL!).
+## In most situations this parameter is unneeded as xlsopen automatically
+## selects the most useful interface present.
+##
+## Beware: Excel invocations may be left running invisibly in case of COM
+## errors or forgetting to close the file pointer. Similarly for OpenOffice.org
+## which may even prevent Octave from being closed.
+##
+## Examples:
+##
+## @example
+##   xls = xlsopen ('test1.xls');
+##   (get a pointer for reading from spreadsheet test1.xls)
+##
+##   xls = xlsopen ('test2.xls', 1, 'POI');
+##   (as above, indicate test2.xls will be written to; in this case using Java
+##    and the Apache POI interface are requested)
+## @end example
+##
+## @seealso {xlsclose, xlsread, xlswrite, xls2oct, oct2xls, xlsfinfo}
+##
+## @end deftypefn
+
+## Author: Philip Nienhuis
+## Created: 2009-11-29
+## Updates:
+## 2010-01-03 Added OOXML support
+## 2010-01-10 Changed (java) interface preference order to COM->POI->JXL
+## 2010-01-16 Removed echoeing debug info in POI stanza
+## 2010-03-01 Removed javaclasspath check for rt.jar
+## 2010-03-14 Fixed check on xwrite flag lines 204+, if xlsopen fails xls ptr
+##            should be []
+## 2010-08-25 Improved help text
+## 2010-09-27 Improved POI help message for unrecognized .xls format to hint for BIFF5/JXL
+## 2010-10-20 Improved code for tracking changes to new/existing files
+##     ''     Lots of code cleanup, improved error checking and catching
+##     ''     Implemented fallback to JXL if POI can't read a file.
+## 2010-10-30 More fine-grained file existence/writable checks
+## 2010-11-01 Added <COM>.Application.DisplayAlerts=0 in COM section to avoid Excel pop-ups
+## 2010-11-05 Option for multiple requested interface types (cell array)
+##     ''     Bug fix: JXL fallback from POI for BIFF5 is only useful for reading
+## 2010-11-05 Slight change to reporting to screen
+## 2010-11-08 Tested with POI 3.7 (OK)
+## 2010-11-10 Texinfo header updated
+## 2010-12-01 Small bugfix - reset xlssupport in l. 102
+## 2010-12-06 Textual changes to info header 
+## 2011-03-26 OpenXLS support added
+## 2011-05-18 Experimental UNO support added, incl. creating new spreadsheets
+## 2011-05-22 Textual changes in header
+## 2011-05-29 Cleanup of comments & messages
+## 2011-09-03 Reset chkintf to [] if no xls support was discovered (to allow
+##            rediscovery of interfaces between xlsopen calls, e.g. javaclasspath changes)
+## 2011-09-08 Minor code cleanup
+## 2012-01-26 Fixed "seealso" help string
+## 2012-06-06 Improved interface detection logic. No more messages if same interface is
+##            requested & used consecutively
+## 2012-06-07 Fixed mixed-up lastintf assignments for POI and JXL
+##
+## Latest subfunction update: 2012-06-06
+
+function [ xls ] = xlsopen (filename, xwrite=0, reqinterface=[])
+
+  persistent xlsinterfaces; persistent chkintf; persistent lastintf;
+  # xlsinterfaces.<intf> = [] (not yet checked), 0 (found to be unsupported) or 1 (OK)
+  if (isempty (chkintf));
+      chkintf = 1;
+      xlsinterfaces = struct ('COM', [], 'POI', [], 'JXL', [], 'OXS', [], 'UNO', []);
+  endif
+  if (isempty (lastintf))
+    lastintf = "---";
+  endif
+
+  xlssupport = 0;
+
+  if (nargout < 1)
+      usage ("XLS = xlsopen (Xlfile [, Rw] [, reqintf]). But no return argument specified!"); 
+  endif
+
+  if (~(islogical (xwrite) || isnumeric (xwrite)))
+      usage ("Numerical or logical value expected for arg # 2")
+  endif
+
+  if (~isempty (reqinterface))
+    if ~(ischar (reqinterface) || iscell (reqinterface)), usage ("Arg # 3 not recognized"); endif
+    # Turn arg3 into cell array if needed
+    if (~iscell (reqinterface)), reqinterface = {reqinterface}; endif
+    ## Check if previously used interface matches a requested interface
+    if (isempty (regexpi (reqinterface, lastintf, 'once'){1}))
+      ## New interface requested
+      xlsinterfaces.COM = 0; xlsinterfaces.POI = 0; xlsinterfaces.JXL = 0;
+      xlsinterfaces.OXS = 0; xlsinterfaces.UNO = 0;
+      for ii=1:numel (reqinterface)
+        reqintf = toupper (reqinterface {ii});
+        # Try to invoke requested interface(s) for this call. Check if it
+        # is supported anyway by emptying the corresponding var.
+        if     (strcmpi (reqintf, 'COM'))
+          xlsinterfaces.COM = [];
+        elseif (strcmpi (reqintf, 'POI'))
+          xlsinterfaces.POI = [];
+        elseif (strcmpi (reqintf, 'JXL'))
+          xlsinterfaces.JXL = [];
+        elseif (strcmpi (reqintf, 'OXS'))
+          xlsinterfaces.OXS = [];
+        elseif (strcmpi (reqintf, 'UNO'))
+          xlsinterfaces.UNO = [];
+        else 
+          usage (sprintf ("Unknown .xls interface \"%s\" requested. Only COM, POI, JXL, OXS or UNO supported\n", reqinterface{}));
+        endif
+      endfor
+      printf ("Checking requested interface(s):\n");
+      xlsinterfaces = getxlsinterfaces (xlsinterfaces);
+      # Well, is/are the requested interface(s) supported on the system?
+      # FIXME check for multiple interfaces
+      xlsintf_cnt = 0;
+      for ii=1:numel (reqinterface)
+        if (~xlsinterfaces.(toupper (reqinterface{ii})))
+          # No it aint
+          printf ("%s is not supported.\n", upper (reqinterface{ii}));
+        else
+          ++xlsintf_cnt;
+        endif
+      endfor
+      # Reset interface check indicator if no requested support found
+      if (~xlsintf_cnt)
+        chkintf = [];
+        xls = [];
+        return
+      endif
+    endif
+  endif
+
+  # Var xwrite is really used to avoid creating files when wanting to read, or
+  # not finding not-yet-existing files when wanting to write.
+
+  # Check if Excel file exists. Adapt file open mode for readwrite argument
+  if (xwrite), fmode = 'r+b'; else fmode = 'rb'; endif
+  fid = fopen (filename, fmode);
+  if (fid < 0)            # File doesn't exist...
+    if (~xwrite)        # ...which obviously is fatal for reading...
+      error ( sprintf ("File %s not found\n", filename));
+    else              # ...but for writing, we need more info:
+      fid = fopen (filename, 'rb');  # Check if it exists at all...
+      if (fid < 0)      # File didn't exist yet. Simply create it
+        printf ("Creating file %s\n", filename);
+        xwrite = 3;
+      else            # File exists, but is not writable => Error
+        fclose (fid);  # Do not forget to close the handle neatly
+        error (sprintf ("Write mode requested but file %s is not writable\n", filename))
+      endif
+    endif
+  else
+    # Close file anyway to avoid COM or Java errors
+    fclose (fid);
+  endif
+  
+  # Check for the various Excel interfaces. No problem if they've already
+  # been checked, getxlsinterfaces (far below) just returns immediately then.
+  xlsinterfaces = getxlsinterfaces (xlsinterfaces);
+
+  # Supported interfaces determined; Excel file type check moved to seperate interfaces.
+  chk1 = strcmpi (filename(end-3:end), '.xls');      # Regular (binary) BIFF 
+  chk2 = strcmpi (filename(end-4:end-1), '.xls');    # Zipped XML / OOXML
+  
+  # Initialize file ptr struct
+  xls = struct ("xtype", 'NONE', "app", [], "filename", [], "workbook", [], "changed", 0, "limits", []); 
+
+  # Keep track of which interface is selected
+  xlssupport = 0;
+
+  # Interface preference order is defined below: currently COM -> POI -> JXL -> OXS -> UNO
+  if (xlsinterfaces.COM && ~xlssupport)
+    # Excel functioning has been tested above & file exists, so we just invoke it
+    app = actxserver ("Excel.Application");
+    try      # Because Excel itself can still crash on file formats etc.
+      app.Application.DisplayAlerts = 0;
+      if (xwrite < 2)
+        # Open workbook
+        wb = app.Workbooks.Open (canonicalize_file_name (filename));
+      elseif (xwrite > 2)
+        # Create a new workbook
+        wb = app.Workbooks.Add ();
+        ### Uncommenting the below statement can be useful in multi-user environments.
+        ### Be sure to uncomment correspondig stanza in xlsclose to avoid zombie Excels
+        # wb.SaveAs (canonicalize_file_name (filename))
+      endif
+      xls.app = app;
+      xls.xtype = 'COM';
+      xls.workbook = wb;
+      xls.filename = filename;
+      xlssupport += 1;
+      lastintf = 'COM';
+    catch
+      warning ( sprintf ("ActiveX error trying to open or create file %s\n", filename));
+      app.Application.DisplayAlerts = 1;
+      app.Quit ();
+      delete (app);
+    end_try_catch
+  endif
+  
+  if (xlsinterfaces.POI && ~xlssupport)
+    if ~(chk1 || chk2)
+      error ("Unsupported file format for Apache POI.")
+    endif
+    # Get handle to workbook
+    try
+      if (xwrite > 2)
+        if (chk1)
+          wb = java_new ('org.apache.poi.hssf.usermodel.HSSFWorkbook');
+        elseif (chk2)
+          wb = java_new ('org.apache.poi.xssf.usermodel.XSSFWorkbook');
+        endif
+          xls.app = 'new_POI';
+      else
+        xlsin = java_new ('java.io.FileInputStream', filename);
+        wb = java_invoke ('org.apache.poi.ss.usermodel.WorkbookFactory', 'create', xlsin);
+        xls.app = xlsin;
+      endif
+      xls.xtype = 'POI';
+      xls.workbook = wb;
+      xls.filename = filename;
+      xlssupport += 2;
+      lastintf = 'POI';
+    catch
+      clear xlsin;
+      if (xlsinterfaces.JXL)
+        printf ('Couldn''t open file %s using POI; trying Excel''95 format with JXL...\n', filename);
+      endif
+    end_try_catch
+  endif
+      
+  if (xlsinterfaces.JXL && ~xlssupport)
+    if (~chk1)
+      error ("JXL can only read reliably from .xls files")
+    endif
+    try
+      xlsin = java_new ('java.io.File', filename);
+      if (xwrite > 2)
+        # Get handle to new xls-file
+        wb = java_invoke ('jxl.Workbook', 'createWorkbook', xlsin);
+      else
+        # Open existing file
+        wb = java_invoke ('jxl.Workbook', 'getWorkbook', xlsin);
+      endif
+      xls.xtype = 'JXL';
+      xls.app = xlsin;
+      xls.workbook = wb;
+      xls.filename = filename;
+      xlssupport += 4;
+      lastintf = 'JXL';
+    catch
+      clear xlsin;
+      if (xlsinterfaces.POI)
+        printf ('... No luck with JXL either, unsupported file format.\n', filename);
+      endif
+    end_try_catch
+  endif
+
+  if (xlsinterfaces.OXS && ~xlssupport)
+    if (~chk1)
+      error ("OXS can only read from .xls files")
+    endif
+    try
+      wb = javaObject ('com.extentech.ExtenXLS.WorkBookHandle', filename);
+      xls.xtype = 'OXS';
+      xls.app = 'void - OpenXLS';
+      xls.workbook = wb;
+      xls.filename = filename;
+      xlssupport += 8;
+      lastintf = 'OXS';
+    catch
+      printf ('Unsupported file format for OpenXLS - %s\n');
+    end_try_catch
+  endif
+
+  if (xlsinterfaces.UNO && ~xlssupport)
+    # First, the file name must be transformed into a URL
+    if (~isempty (strmatch ("file:///", filename)) || ~isempty (strmatch ("http:///", filename))...
+      || ~isempty (strmatch ("ftp:///", filename)) || ~isempty (strmatch ("www:///", filename)))
+      # Seems in proper shape for OOo (at first sight)
+    else
+      # Transform into URL form
+      fname = canonicalize_file_name (strsplit (filename, filesep){end});
+      # On Windows, change backslash file separator into forward slash
+      if (strcmp (filesep, "\\"))
+        tmp = strsplit (fname, filesep);
+        flen = numel (tmp);
+        tmp(2:2:2*flen) = tmp;
+        tmp(1:2:2*flen) = '/';
+        fname = [ tmp{:} ];
+      endif
+      filename = [ 'file://' fname ];
+    endif
+    try
+      xContext = java_invoke ("com.sun.star.comp.helper.Bootstrap", "bootstrap");
+      xMCF = xContext.getServiceManager ();
+      oDesktop = xMCF.createInstanceWithContext ("com.sun.star.frame.Desktop", xContext);
+      # Workaround for <UNOruntime>.queryInterface():
+      unotmp = java_new ('com.sun.star.uno.Type', 'com.sun.star.frame.XComponentLoader');
+      aLoader = oDesktop.queryInterface (unotmp);
+      # Some trickery as Octave Java cannot create initialized arrays
+      lProps = javaArray ('com.sun.star.beans.PropertyValue', 1);
+      lProp = java_new ('com.sun.star.beans.PropertyValue', "Hidden", 0, true, []);
+      lProps(1) = lProp;
+      if (xwrite > 2)
+        xComp = aLoader.loadComponentFromURL ("private:factory/scalc", "_blank", 0, lProps);
+      else
+        xComp = aLoader.loadComponentFromURL (filename, "_blank", 0, lProps);
+      endif
+      # Workaround for <UNOruntime>.queryInterface():
+      unotmp = java_new ('com.sun.star.uno.Type', 'com.sun.star.sheet.XSpreadsheetDocument');
+      xSpdoc = xComp.queryInterface (unotmp);
+      # save in ods struct:
+      xls.xtype = 'UNO';
+      xls.workbook = xSpdoc;        # Needed to be able to close soffice in odsclose()
+      xls.filename = filename;
+      xls.app.xComp = xComp;        # Needed to be able to close soffice in odsclose()
+      xls.app.aLoader = aLoader;      # Needed to be able to close soffice in odsclose()
+      xls.odfvsn = 'UNO';
+      xlssupport += 16;
+      lastintf = 'UNO';
+    catch
+      error ('Couldn''t open file %s using UNO', filename);
+    end_try_catch
+  endif
+
+  # if 
+  #  ---- other interfaces
+  # endif
+
+  # Rounding up. If none of the xlsinterfaces is supported we're out of luck.
+  if (~xlssupport)
+    if (isempty (reqinterface))
+      printf ("None.\n");
+      warning ("No support for Excel .xls I/O"); 
+    else
+      warning ("File type not supported by %s %s %s %s %s", reqinterface{:});
+    endif
+    xls = [];
+    # Reset found interfaces for re-testing in the next call. Add interfaces if needed.
+    chkintf = [];
+  else
+    # From here on xwrite is tracked via xls.changed in the various lower
+    # level r/w routines and it is only used to determine if an informative
+    # message is to be given when saving a newly created xls file.
+    xls.changed = xwrite;
+
+    # Until something was written to existing files we keep status "unchanged".
+    # xls.changed = 0 (existing/only read from), 1 (existing/data added), 2 (new,
+    # data added) or 3 (pristine, no data added).
+    if (xls.changed == 1), xls.changed = 0; endif
+  endif
+  
+endfunction
+
+
+## Copyright (C) 2009,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 Foundation; either version 2 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 Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} @var{xlsinterfaces} = getxlsinterfaces (@var{xlsinterfaces})
+## Get supported Excel .xls file read/write interfaces from the system.
+## Each interface for which the corresponding field is set to empty
+## will be checked. So by manipulating the fields of input argument
+## @var{xlsinterfaces} it is possible to specify which
+## interface(s) should be checked.
+##
+## Currently implemented interfaces comprise:
+## - ActiveX / COM (native Excel in the background)
+## - Java & Apache POI
+## - Java & JExcelAPI
+## - Java & OpenXLS (only JRE >= 1.4 needed)
+## - Java & UNO bridge (native OpenOffice.org in background) - EXPERIMENTAL!!
+##
+## Examples:
+##
+## @example
+##   xlsinterfaces = getxlsinterfaces (xlsinterfaces);
+## @end example
+
+## Author: Philip Nienhuis
+## Created: 2009-11-29
+## Last updates: 
+## 2009-12-27 Make sure proper dimensions are checked in parsed javaclasspath
+## 2010-09-11 Rearranged code and clarified messages about missing classes
+## 2010-09-27 More code cleanup
+## 2010-10-20 Added check for minimum Java version (should be >= 6 / 1.6)
+## 2010-11-05 Slight change to reporting to screen
+## 2011-02-15 Adapted to javaclasspath calling style of java-1.2.8 pkg
+## 2011-03-26 OpenXLS support added
+##      ''    Bug fix: javaclasspath change wasn't picked up between calls with req.intf
+## 2011-05-18 Experimental UNO support added
+## 2011-05-29 Reduced verbosity
+## 2011-06-06 Fix for javaclasspath format in *nix w java-1.2.8 pkg
+## 2011-06-13 Fixed potentially faulty tests for java classlib presence
+## 2011-09-03 Fixed order of xlsinterfaces.<member> statements in Java detection try-catch
+##      ''    Reset tmp1 (always allow interface rediscovery) for empty xlsinterfaces arg
+## 2011-09-08 Minor code cleanup
+## 2011-09-18 Added temporary warning about UNO interface
+## 2012-03-01 Changed UNO warning so that it is suppressed when UNO is not yet chosen
+## 2012-03-07 Only check for COM if run on Windows
+## 2012-03-21 Print newline if COM found but no Java support
+##     ''     Improved logic for finding out what interfaces to check
+##     ''     Fixed bugs with Java interface checking (tmp1 initialization)
+## 2012-06-06 Improved & simplified Java check code
+
+function [xlsinterfaces] = getxlsinterfaces (xlsinterfaces)
+
+  # tmp1 = [] (not initialized), 0 (No Java detected), or 1 (Working Java found)
+  persistent tmp1 = []; persistent jcp;  # Java class path
+  persistent uno_1st_time = 0;
+
+  if (isempty (xlsinterfaces.COM) && isempty (xlsinterfaces.POI) && isempty (xlsinterfaces.JXL)
+   && isempty (xlsinterfaces.OXS) && isempty (xlsinterfaces.UNO))
+    # Looks like first call to xlsopen. Check Java support
+    printf ("Detected XLS interfaces: ");
+    tmp1 = [];
+  elseif (isempty (xlsinterfaces.POI) || isempty (xlsinterfaces.JXL)
+       || isempty (xlsinterfaces.OXS) || isempty (xlsinterfaces.UNO))
+    # Can't be first call. Here one of the Java interfaces is requested
+    if (~tmp1)
+      # Check Java support again
+      tmp1 = [];
+    endif
+  endif
+  deflt = 0;
+
+  # Check if MS-Excel COM ActiveX server runs (only on Windows!)
+  if (isempty (xlsinterfaces.COM))
+    xlsinterfaces.COM = 0;
+    if (ispc)
+      try
+        app = actxserver ("Excel.application");
+        # If we get here, the call succeeded & COM works.
+        xlsinterfaces.COM = 1;
+        # Close Excel. Yep this is inefficient when we need only one r/w action,
+        # but it quickly pays off when we need to do more with the same file
+        # (+, MS-Excel code is in OS cache anyway after this call so no big deal)
+        app.Quit();
+        delete(app);
+        printf ("COM");
+        if (deflt), printf ("; "); else, printf ("*; "); deflt = 1; endif
+      catch
+        # COM non-existent. Only print message if COM is explicitly requested (tmp1==[])
+        if (~isempty (tmp1))
+          printf ("ActiveX not working; no Excel installed?\n"); 
+        endif
+      end_try_catch
+    endif
+  endif
+
+  if (isempty (tmp1))
+    # Check Java support. First try javaclasspath
+    try
+      jcp = javaclasspath ('-all');              # For java pkg > 1.2.7
+      if (isempty (jcp)), jcp = javaclasspath; endif  # For java pkg < 1.2.8
+      # If we get here, at least Java works. Now check for proper version (>= 1.6)
+      jver = char (java_invoke ('java.lang.System', 'getProperty', 'java.version'));
+      cjver = strsplit (jver, '.');
+      if (sscanf (cjver{2}, '%d') < 6)
+        warning ("\nJava version might be too old - you need at least Java 6 (v. 1.6.x.x)\n");
+        return
+      endif
+      # Now check for proper entries in class path. Under *nix the classpath
+      # must first be split up. In java 1.2.8+ javaclasspath is already a cell array
+      if (isunix && ~iscell (jcp)); jcp = strsplit (char (jcp), ":"); endif
+      tmp1 = 1;
+    catch
+      # No Java support found
+      tmp1 = 0;
+      if (isempty (xlsinterfaces.POI) || isempty (xlsinterfaces.JXL)...
+        || isempty (xlsinterfaces.OXS) || isempty (xlsinterfaces.UNO))
+        # Some or all Java-based interface(s) explicitly requested but no Java support
+        warning (' No Java support found (no Java JRE? no Java pkg installed AND loaded?');
+      endif
+      # Set Java interfaces to 0 anyway as there's no Java support
+      xlsinterfaces.POI = 0;
+      xlsinterfaces.JXL = 0;
+      xlsinterfaces.OXS = 0;
+      xlsinterfaces.UNO = 0;
+      printf ("\n");
+      # No more need to try any Java interface
+      return
+    end_try_catch
+  endif
+
+  # Try Java & Apache POI
+  if (isempty (xlsinterfaces.POI))
+    xlsinterfaces.POI = 0;
+    # Check basic .xls (BIFF8) support
+    jpchk1 = 0; entries1 = {"poi-3", "poi-ooxml-3"};
+    # Only under *nix we might use brute force: e.g., strfind (classname, classpath);
+    # under Windows we need the following more subtle, platform-independent approach:
+    for ii=1:length (jcp)
+      for jj=1:length (entries1)
+        if (isempty (strfind (tolower (jcp{ii}), entries1{jj}))), ++jpchk1; endif
+      endfor
+    endfor
+    if (jpchk1 > 1)
+      xlsinterfaces.POI = 1;
+      printf ("POI");
+    endif
+    # Check OOXML support
+    jpchk2 = 0; entries2 = {"xbean", "poi-ooxml-schemas", "dom4j"};
+    for ii=1:length (jcp)
+      for jj=1:length (entries2)
+        if (isempty (strfind (lower (jcp{ii}), entries2{jj}))), ++jpchk2; endif
+      endfor
+    endfor
+    if (jpchk2 > 2), printf (" (& OOXML)"); endif
+    if (xlsinterfaces.POI)
+      if (deflt), printf ("; "); else, printf ("*; "); deflt = 1; endif
+    endif
+  endif
+
+  # Try Java & JExcelAPI
+  if (isempty (xlsinterfaces.JXL))
+    xlsinterfaces.JXL = 0;
+    jpchk = 0; entries = {"jxl"};
+    for ii=1:length (jcp)
+      for jj=1:length (entries)
+        if (isempty (strfind (lower (jcp{ii}), entries{jj}))), ++jpchk; endif
+      endfor
+    endfor
+    if (jpchk > 0)
+      xlsinterfaces.JXL = 1;
+      printf ("JXL");
+      if (deflt), printf ("; "); else, printf ("*; "); deflt = 1; endif
+    endif
+  endif
+
+  # Try Java & OpenXLS
+  if (isempty (xlsinterfaces.OXS))
+    xlsinterfaces.OXS = 0;
+    jpchk = 0; entries = {"openxls"};
+    for ii=1:length (jcp)
+      for jj=1:length (entries)
+        if (isempty (strfind (lower (jcp{ii}), entries{jj}))), ++jpchk; endif
+      endfor
+    endfor
+    if (jpchk > 0)
+      xlsinterfaces.OXS = 1;
+      printf ("OXS");
+      if (deflt), printf ("; "); else, printf ("*; "); deflt = 1; endif
+    endif
+  endif
+
+  # Try Java & UNO
+  if (isempty (xlsinterfaces.UNO))
+    xlsinterfaces.UNO = 0;
+    # entries0(1) = not a jar but a directory (<00o_install_dir/program/>)
+    jpchk = 0; entries = {'program', 'unoil', 'jurt', 'juh', 'unoloader', 'ridl'};
+    for jj=1:numel (entries)
+      for ii=1:numel (jcp)
+        jcplst = strsplit (jcp{ii}, filesep);
+        jcpentry = jcplst {end};
+        if (~isempty (strfind (lower (jcpentry), lower (entries{jj})))); ++jpchk; endif
+      endfor
+    endfor
+    if (jpchk >= numel (entries))
+      xlsinterfaces.UNO = 1;
+      printf ('UNO');
+      if (deflt), printf ("; "); else, printf ("*; "); deflt = 1; uno_1st_time = min (++uno_1st_time, 2); endif
+    endif
+  endif
+
+  # ---- Other interfaces here, similar to the ones above
+
+  if (deflt), printf ("(* = active interface)\n"); endif
+
+  ## FIXME the below stanza should be dropped once UNO is stable.
+  # Echo a suitable warning about experimental status:
+  if (uno_1st_time == 1)
+    ++uno_1st_time;
+    printf ("\nPLEASE NOTE: UNO (=OpenOffice.org-behind-the-scenes) is EXPERIMENTAL\n");
+    printf ("After you've opened a spreadsheet file using the UNO interface,\n");
+    printf ("xlsclose on that file will kill ALL OpenOffice.org invocations,\n");
+    printf ("also those that were started outside and/or before Octave!\n");
+    printf ("Trying to quit Octave w/o invoking xlsclose will only hang Octave.\n\n");
+  endif
+
+endfunction