## Copyright (C) 2009-2020 Philip Nienhuis ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {Function File} @var{interfaces} = getinterfaces (@var{interfaces}) ## 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{interfaces} it is possible to specify which ## interface(s) should be checked. ## ## Currently implemented interfaces comprise: ## - ActiveX / COM (native Excel in the background) ## - Java & JExcelAPI (.xls) ## - Java & jOpendocument (.ods, .sxc) ## - Java & ODFtoolkit (.ods) ## - Java & OpenXLS (only JRE >= 1.4 needed) (.xls) ## - Java & Apache POI (.xls, .xlsx) ## - Java & UNO bridge (native OpenOffice.org in background) - EXPERIMENTAL!! ## - native Octave, only for .xlsx (OOXML), .ODS1.2, . gnumeric ## ## Examples: ## ## @example ## interfaces = getinterfaces (interfaces); ## @end example ## Author: Philip Nienhuis ## Created: 2009-11-29 function [interfaces] = getinterfaces (interfaces, verbose=true) ## tmp1 = [] (not initialized), 0 (No Java detected), or 1 (Working Java found) persistent tmp1 = []; persistent tmp2 = []; persistent has_java = []; ## Built-in Java support persistent jcp; ## Java class path persistent uno_1st_time = 0; if (isempty (has_java)) has_java = __have_feature__ ("JAVA"); endif if (isempty (interfaces.COM) && isempty (interfaces.JXL) ... && isempty (interfaces.JOD) && isempty (interfaces.POI) ... && isempty (interfaces.OTK) && isempty (interfaces.OXS) ... && isempty (interfaces.UNO)) ## Looks like first call to xlsopen. Check Java support if (verbose) printf ("Detected interfaces: "); endif tmp1 = []; elseif (isempty (interfaces.COM) || isempty (interfaces.JXL) ... || isempty (interfaces.JOD) || isempty (interfaces.POI) ... || isempty (interfaces.OTK) || isempty (interfaces.OXS) ... || isempty (interfaces.UNO)) ## Can't be first call. Here one of the Java interfaces may be requested if (! tmp1) ## Check Java support again tmp1 = []; elseif (has_java) ## Renew jcp (javaclasspath) as it may have been updated since last call jcp = javaclasspath ("-all"); if (isunix && ! iscell (jcp)); jcp = strsplit (char (jcp), pathsep ()); endif endif endif ## Check if MS-Excel COM ActiveX server runs (only on Windows!) if (ispc && isempty (interfaces.COM)) interfaces.COM = 0; try app = actxserver ("Excel.application"); ## 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); if (verbose) printf ("COM; "); endif ## If we get here, the call succeeded & COM works. interfaces.COM = 1; catch ## COM non-existent. Only print message if COM is explicitly requested (tmp1==[]) if (! isempty (tmp1) && verbose) printf ("ActiveX not working; no Excel installed?\n"); endif end_try_catch endif if (has_java) if (isempty (tmp1)) ## Check Java support [tmp1, jcp] = __chk_java_sprt__ (); if (! tmp1) ## No Java support found tmp1 = 0; if (isempty (interfaces.JXL) || isempty (interfaces.JOD)... || isempty (interfaces.OTK) || isempty (interfaces.OXS)... || isempty (interfaces.POI) || isempty (interfaces.UNO)) ## Some or all Java-based interface(s) explicitly requested but no Java support if (verbose) printf (" no Java support found (no Java JRE or JDK ?)"); endif endif ## Set Java-based interfaces to 0 anyway as there's no Java support interfaces.JOD = 0; interfaces.JXL = 0; interfaces.OTK = 0; interfaces.OXS = 0; interfaces.POI = 0; interfaces.UNO = 0; if (verbose) printf ("\n"); endif ## No more need to try any Java interface return endif endif ## Try Java & Apache POI if (isempty (interfaces.POI)) interfaces.POI = 0; ## Check basic .xls (BIFF8) support [chk, ~, missing2] = __POI_chk_sprt__ (jcp); if (chk > 0) interfaces.POI = chk; if (verbose) printf ("POI"); if (isempty (missing2)) printf (" (& OOXML)"); endif printf ("; "); endif endif endif ## Try Java & JExcelAPI if (isempty (interfaces.JXL)) interfaces.JXL = 0; chk = __JXL_chk_sprt__ (jcp); if (chk) interfaces.JXL = 1; if (verbose) printf ("JXL; "); endif endif endif ## Try Java & OpenXLS if (isempty (interfaces.OXS)) interfaces.OXS = 0; chk = __OXS_chk_sprt__ (jcp); ## Beware of unsupported openxls jar versions (chk must be > 0) if (chk >= 1) interfaces.OXS = 1; if (verbose) printf ("OXS; "); endif endif endif ## Try Java & jOpenDocument if (isempty (interfaces.JOD)) interfaces.JOD = 0; chk = __JOD_chk_sprt__ (jcp); if (chk) interfaces.JOD = 1; if (verbose) printf ("JOD; "); endif endif endif ## Try Java & ODF toolkit if (isempty (interfaces.OTK)) interfaces.OTK = 0; [chk, missing5] = __OTK_chk_sprt__ (jcp); ## Beware of unsupported odfdom jar versions if (chk >= 1) interfaces.OTK = 1; if (verbose) printf ("OTK; "); endif endif endif ## Try Java & UNO if (isempty (interfaces.UNO)) interfaces.UNO = 0; chk = __UNO_chk_sprt__ (jcp); if (chk) interfaces.UNO = 1; if (verbose) printf ("UNO; "); endif if (verbose) uno_1st_time = min (++uno_1st_time, 2); endif endif endif else ## Set Java-based interfaces to 0 anyway as there's no Java support interfaces.JOD = 0; interfaces.JXL = 0; interfaces.OTK = 0; interfaces.OXS = 0; interfaces.POI = 0; interfaces.UNO = 0; endif ## Native Octave. Nothing to check, always supported if (isempty (interfaces.OCT)) interfaces.OCT = 1; if (verbose) printf ("OCT"); endif endif if (verbose) printf ("\n"); endif ## ---- Other interfaces here, similar to the ones above. ## Java interfaces should be in the has-java if-block ## FIXME the below stanza should be dropped once UNO is stable. # Echo a suitable warning about experimental status: if (uno_1st_time == 1 && verbose) ++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