/trunk/octave-forge/main/io/inst/xlsopen.m

# · Objective C · 639 lines · 597 code · 42 blank · 0 comment · 157 complexity · 6e94c6385a38c1a8f94ec63d7ef96ef7 MD5 · raw file

  1. ## Copyright (C) 2009,2010,2011,2012 Philip Nienhuis <prnienhuis at users.sf.net>
  2. ##
  3. ## This program is free software; you can redistribute it and/or modify
  4. ## it under the terms of the GNU General Public License as published by
  5. ## the Free Software Foundation; either version 2 of the License, or
  6. ## (at your option) any later version.
  7. ##
  8. ## This program is distributed in the hope that it will be useful,
  9. ## but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. ## GNU General Public License for more details.
  12. ##
  13. ## You should have received a copy of the GNU General Public License
  14. ## along with Octave; see the file COPYING. If not, see
  15. ## <http://www.gnu.org/licenses/>.
  16. ## -*- texinfo -*-
  17. ## @deftypefn {Function File} @var{xls} = xlsopen (@var{filename})
  18. ## @deftypefnx {Function File} @var{xls} = xlsopen (@var{filename}, @var{readwrite})
  19. ## @deftypefnx {Function File} @var{xls} = xlsopen (@var{filename}, @var{readwrite}, @var{reqintf})
  20. ## Get a pointer to an Excel spreadsheet in the form of return argument
  21. ## (file pointer struct) @var{xls}. After processing the spreadsheet,
  22. ## the file pointer must be explicitly closed by calling xlsclose().
  23. ##
  24. ## Calling xlsopen without specifying a return argument is fairly useless!
  25. ##
  26. ## To make this function work at all, you need MS-Excel (95 - 2003), and/or
  27. ## the Java package >= 1.2.8 plus Apache POI >= 3.5 and/or JExcelAPI and/or
  28. ## OpenXLS and/or OpenOffice.org (or clones) installed on your computer +
  29. ## proper javaclasspath set. These interfaces are referred to as COM, POI,
  30. ## JXL, OXS, and UNO, resp., and are preferred in that order by default
  31. ## (depending on their presence).
  32. ## For OOXML support, in addition to Apache POI support you also need the
  33. ## following jars in your javaclasspath: poi-ooxml-schemas-3.5.jar,
  34. ## xbean.jar and dom4j-1.6.1.jar (or later versions). Later OpenOffice.org
  35. ## versions (UNO) have support for OOXML as well.
  36. ## Excel'95 spreadsheets can only be read by JExcelAPI and OpenOffice.org.
  37. ##
  38. ## @var{filename} should be a valid .xls or xlsx Excel file name (including
  39. ## extension). But if you use the COM interface you can specify any extension
  40. ## that your installed Excel version can read AND write; the same goes for UNO
  41. ## (OpenOffice.org). Using the other Java interfaces, only .xls or .xlsx are
  42. ## allowed. If @var{filename} does not contain any directory path, the file
  43. ## is saved in the current directory.
  44. ##
  45. ## If @var{readwrite} is set to 0 (default value) or omitted, the Excel file
  46. ## is opened for reading. If @var{readwrite} is set to True or 1, an Excel
  47. ## file is opened (or created) for reading & writing.
  48. ##
  49. ## Optional input argument @var{reqintf} can be used to override the Excel
  50. ## interface that otherwise is automatically selected by xlsopen. Currently
  51. ## implemented interfaces (in order of preference) are 'COM' (Excel/COM),
  52. ## 'POI' (Java/Apache POI), 'JXL' (Java/JExcelAPI), 'OXS' (Java/OpenXLS), or
  53. ## 'UNO' (Java/OpenOffice.org - EXPERIMENTAL!).
  54. ## In most situations this parameter is unneeded as xlsopen automatically
  55. ## selects the most useful interface present.
  56. ##
  57. ## Beware: Excel invocations may be left running invisibly in case of COM
  58. ## errors or forgetting to close the file pointer. Similarly for OpenOffice.org
  59. ## which may even prevent Octave from being closed.
  60. ##
  61. ## Examples:
  62. ##
  63. ## @example
  64. ## xls = xlsopen ('test1.xls');
  65. ## (get a pointer for reading from spreadsheet test1.xls)
  66. ##
  67. ## xls = xlsopen ('test2.xls', 1, 'POI');
  68. ## (as above, indicate test2.xls will be written to; in this case using Java
  69. ## and the Apache POI interface are requested)
  70. ## @end example
  71. ##
  72. ## @seealso {xlsclose, xlsread, xlswrite, xls2oct, oct2xls, xlsfinfo}
  73. ##
  74. ## @end deftypefn
  75. ## Author: Philip Nienhuis
  76. ## Created: 2009-11-29
  77. ## Updates:
  78. ## 2010-01-03 Added OOXML support
  79. ## 2010-01-10 Changed (java) interface preference order to COM->POI->JXL
  80. ## 2010-01-16 Removed echoeing debug info in POI stanza
  81. ## 2010-03-01 Removed javaclasspath check for rt.jar
  82. ## 2010-03-14 Fixed check on xwrite flag lines 204+, if xlsopen fails xls ptr
  83. ## should be []
  84. ## 2010-08-25 Improved help text
  85. ## 2010-09-27 Improved POI help message for unrecognized .xls format to hint for BIFF5/JXL
  86. ## 2010-10-20 Improved code for tracking changes to new/existing files
  87. ## '' Lots of code cleanup, improved error checking and catching
  88. ## '' Implemented fallback to JXL if POI can't read a file.
  89. ## 2010-10-30 More fine-grained file existence/writable checks
  90. ## 2010-11-01 Added <COM>.Application.DisplayAlerts=0 in COM section to avoid Excel pop-ups
  91. ## 2010-11-05 Option for multiple requested interface types (cell array)
  92. ## '' Bug fix: JXL fallback from POI for BIFF5 is only useful for reading
  93. ## 2010-11-05 Slight change to reporting to screen
  94. ## 2010-11-08 Tested with POI 3.7 (OK)
  95. ## 2010-11-10 Texinfo header updated
  96. ## 2010-12-01 Small bugfix - reset xlssupport in l. 102
  97. ## 2010-12-06 Textual changes to info header
  98. ## 2011-03-26 OpenXLS support added
  99. ## 2011-05-18 Experimental UNO support added, incl. creating new spreadsheets
  100. ## 2011-05-22 Textual changes in header
  101. ## 2011-05-29 Cleanup of comments & messages
  102. ## 2011-09-03 Reset chkintf to [] if no xls support was discovered (to allow
  103. ## rediscovery of interfaces between xlsopen calls, e.g. javaclasspath changes)
  104. ## 2011-09-08 Minor code cleanup
  105. ## 2012-01-26 Fixed "seealso" help string
  106. ##
  107. ## Latest subfunction update: 2012-03-21
  108. function [ xls ] = xlsopen (filename, xwrite=0, reqinterface=[])
  109. persistent xlsinterfaces; persistent chkintf;
  110. # xlsinterfaces.<intf> = [] (not yet checked), 0 (found to be unsupported) or 1 (OK)
  111. if (isempty (chkintf));
  112. chkintf = 1;
  113. xlsinterfaces = struct ('COM', [], 'POI', [], 'JXL', [], 'OXS', [], 'UNO', []);
  114. endif
  115. xlssupport = 0;
  116. if (nargout < 1)
  117. usage ("XLS = xlsopen (Xlfile [, Rw] [, reqintf]). But no return argument specified!");
  118. endif
  119. if (~(islogical (xwrite) || isnumeric (xwrite)))
  120. usage ("Numerical or logical value expected for arg # 2")
  121. endif
  122. if (~isempty (reqinterface))
  123. if ~(ischar (reqinterface) || iscell (reqinterface)), usage ("Arg # 3 not recognized"); endif
  124. # Turn arg3 into cell array if needed
  125. if (~iscell (reqinterface)), reqinterface = {reqinterface}; endif
  126. xlsinterfaces.COM = 0; xlsinterfaces.POI = 0; xlsinterfaces.JXL = 0;
  127. xlsinterfaces.OXS = 0; xlsinterfaces.UNO = 0;
  128. for ii=1:numel (reqinterface)
  129. reqintf = toupper (reqinterface {ii});
  130. # Try to invoke requested interface(s) for this call. Check if it
  131. # is supported anyway by emptying the corresponding var.
  132. if (strcmp (reqintf, 'COM'))
  133. xlsinterfaces.COM = [];
  134. elseif (strcmp (reqintf, 'POI'))
  135. xlsinterfaces.POI = [];
  136. elseif (strcmp (reqintf, 'JXL'))
  137. xlsinterfaces.JXL = [];
  138. elseif (strcmp (reqintf, 'OXS'))
  139. xlsinterfaces.OXS = [];
  140. elseif (strcmp (reqintf, 'UNO'))
  141. xlsinterfaces.UNO = [];
  142. else
  143. usage (sprintf ("Unknown .xls interface \"%s\" requested. Only COM, POI, JXL, OXS or UNO supported\n", reqinterface{}));
  144. endif
  145. endfor
  146. printf ("Checking requested interface(s):\n");
  147. xlsinterfaces = getxlsinterfaces (xlsinterfaces);
  148. # Well, is/are the requested interface(s) supported on the system?
  149. # FIXME check for multiple interfaces
  150. xlsintf_cnt = 0;
  151. for ii=1:numel (reqinterface)
  152. if (~xlsinterfaces.(toupper (reqinterface{ii})))
  153. # No it aint
  154. printf ("%s is not supported.\n", upper (reqinterface{ii}));
  155. else
  156. ++xlsintf_cnt;
  157. endif
  158. endfor
  159. # Reset interface check indicator if no requested support found
  160. if (~xlsintf_cnt)
  161. chkintf = [];
  162. xls = [];
  163. return
  164. endif
  165. endif
  166. # Var xwrite is really used to avoid creating files when wanting to read, or
  167. # not finding not-yet-existing files when wanting to write.
  168. # Check if Excel file exists. Adapt file open mode for readwrite argument
  169. if (xwrite), fmode = 'r+b'; else fmode = 'rb'; endif
  170. fid = fopen (filename, fmode);
  171. if (fid < 0) # File doesn't exist...
  172. if (~xwrite) # ...which obviously is fatal for reading...
  173. error ( sprintf ("File %s not found\n", filename));
  174. else # ...but for writing, we need more info:
  175. fid = fopen (filename, 'rb'); # Check if it exists at all...
  176. if (fid < 0) # File didn't exist yet. Simply create it
  177. printf ("Creating file %s\n", filename);
  178. xwrite = 3;
  179. else # File exists, but is not writable => Error
  180. fclose (fid); # Do not forget to close the handle neatly
  181. error (sprintf ("Write mode requested but file %s is not writable\n", filename))
  182. endif
  183. endif
  184. else
  185. # Close file anyway to avoid COM or Java errors
  186. fclose (fid);
  187. endif
  188. # Check for the various Excel interfaces. No problem if they've already
  189. # been checked, getxlsinterfaces (far below) just returns immediately then.
  190. xlsinterfaces = getxlsinterfaces (xlsinterfaces);
  191. # Supported interfaces determined; Excel file type check moved to seperate interfaces.
  192. chk1 = strcmpi (filename(end-3:end), '.xls'); # Regular (binary) BIFF
  193. chk2 = strcmpi (filename(end-4:end-1), '.xls'); # Zipped XML / OOXML
  194. # Initialize file ptr struct
  195. xls = struct ("xtype", 'NONE', "app", [], "filename", [], "workbook", [], "changed", 0, "limits", []);
  196. # Keep track of which interface is selected
  197. xlssupport = 0;
  198. # Interface preference order is defined below: currently COM -> POI -> JXL -> OXS -> UNO
  199. if (xlsinterfaces.COM && ~xlssupport)
  200. # Excel functioning has been tested above & file exists, so we just invoke it
  201. app = actxserver ("Excel.Application");
  202. try # Because Excel itself can still crash on file formats etc.
  203. app.Application.DisplayAlerts = 0;
  204. if (xwrite < 2)
  205. # Open workbook
  206. wb = app.Workbooks.Open (canonicalize_file_name (filename));
  207. elseif (xwrite > 2)
  208. # Create a new workbook
  209. wb = app.Workbooks.Add ();
  210. ### Uncommenting the below statement can be useful in multi-user environments.
  211. ### Be sure to uncomment correspondig stanza in xlsclose to avoid zombie Excels
  212. # wb.SaveAs (canonicalize_file_name (filename))
  213. endif
  214. xls.app = app;
  215. xls.xtype = 'COM';
  216. xls.workbook = wb;
  217. xls.filename = filename;
  218. xlssupport += 1;
  219. catch
  220. warning ( sprintf ("ActiveX error trying to open or create file %s\n", filename));
  221. app.Application.DisplayAlerts = 1;
  222. app.Quit ();
  223. delete (app);
  224. end_try_catch
  225. endif
  226. if (xlsinterfaces.POI && ~xlssupport)
  227. if ~(chk1 || chk2)
  228. error ("Unsupported file format for Apache POI.")
  229. endif
  230. # Get handle to workbook
  231. try
  232. if (xwrite > 2)
  233. if (chk1)
  234. wb = java_new ('org.apache.poi.hssf.usermodel.HSSFWorkbook');
  235. elseif (chk2)
  236. wb = java_new ('org.apache.poi.xssf.usermodel.XSSFWorkbook');
  237. endif
  238. xls.app = 'new_POI';
  239. else
  240. xlsin = java_new ('java.io.FileInputStream', filename);
  241. wb = java_invoke ('org.apache.poi.ss.usermodel.WorkbookFactory', 'create', xlsin);
  242. xls.app = xlsin;
  243. endif
  244. xls.xtype = 'POI';
  245. xls.workbook = wb;
  246. xls.filename = filename;
  247. xlssupport += 2;
  248. catch
  249. clear xlsin;
  250. if (xlsinterfaces.JXL)
  251. printf ('Couldn''t open file %s using POI; trying Excel''95 format with JXL...\n', filename);
  252. endif
  253. end_try_catch
  254. endif
  255. if (xlsinterfaces.JXL && ~xlssupport)
  256. if (~chk1)
  257. error ("JXL can only read reliably from .xls files")
  258. endif
  259. try
  260. xlsin = java_new ('java.io.File', filename);
  261. if (xwrite > 2)
  262. # Get handle to new xls-file
  263. wb = java_invoke ('jxl.Workbook', 'createWorkbook', xlsin);
  264. else
  265. # Open existing file
  266. wb = java_invoke ('jxl.Workbook', 'getWorkbook', xlsin);
  267. endif
  268. xls.xtype = 'JXL';
  269. xls.app = xlsin;
  270. xls.workbook = wb;
  271. xls.filename = filename;
  272. xlssupport += 4;
  273. catch
  274. clear xlsin;
  275. if (xlsinterfaces.POI)
  276. printf ('... No luck with JXL either, unsupported file format.\n', filename);
  277. endif
  278. end_try_catch
  279. endif
  280. if (xlsinterfaces.OXS && ~xlssupport)
  281. if (~chk1)
  282. error ("OXS can only read from .xls files")
  283. endif
  284. try
  285. wb = javaObject ('com.extentech.ExtenXLS.WorkBookHandle', filename);
  286. xls.xtype = 'OXS';
  287. xls.app = 'void - OpenXLS';
  288. xls.workbook = wb;
  289. xls.filename = filename;
  290. xlssupport += 8;
  291. catch
  292. printf ('Unsupported file format for OpenXLS - %s\n');
  293. end_try_catch
  294. endif
  295. if (xlsinterfaces.UNO && ~xlssupport)
  296. # First, the file name must be transformed into a URL
  297. if (~isempty (strmatch ("file:///", filename)) || ~isempty (strmatch ("http:///", filename))...
  298. || ~isempty (strmatch ("ftp:///", filename)) || ~isempty (strmatch ("www:///", filename)))
  299. # Seems in proper shape for OOo (at first sight)
  300. else
  301. # Transform into URL form
  302. fname = canonicalize_file_name (strsplit (filename, filesep){end});
  303. # On Windows, change backslash file separator into forward slash
  304. if (strcmp (filesep, "\\"))
  305. tmp = strsplit (fname, filesep);
  306. flen = numel (tmp);
  307. tmp(2:2:2*flen) = tmp;
  308. tmp(1:2:2*flen) = '/';
  309. fname = [ tmp{:} ];
  310. endif
  311. filename = [ 'file://' fname ];
  312. endif
  313. try
  314. xContext = java_invoke ("com.sun.star.comp.helper.Bootstrap", "bootstrap");
  315. xMCF = xContext.getServiceManager ();
  316. oDesktop = xMCF.createInstanceWithContext ("com.sun.star.frame.Desktop", xContext);
  317. # Workaround for <UNOruntime>.queryInterface():
  318. unotmp = java_new ('com.sun.star.uno.Type', 'com.sun.star.frame.XComponentLoader');
  319. aLoader = oDesktop.queryInterface (unotmp);
  320. # Some trickery as Octave Java cannot create initialized arrays
  321. lProps = javaArray ('com.sun.star.beans.PropertyValue', 1);
  322. lProp = java_new ('com.sun.star.beans.PropertyValue', "Hidden", 0, true, []);
  323. lProps(1) = lProp;
  324. if (xwrite > 2)
  325. xComp = aLoader.loadComponentFromURL ("private:factory/scalc", "_blank", 0, lProps);
  326. else
  327. xComp = aLoader.loadComponentFromURL (filename, "_blank", 0, lProps);
  328. endif
  329. # Workaround for <UNOruntime>.queryInterface():
  330. unotmp = java_new ('com.sun.star.uno.Type', 'com.sun.star.sheet.XSpreadsheetDocument');
  331. xSpdoc = xComp.queryInterface (unotmp);
  332. # save in ods struct:
  333. xls.xtype = 'UNO';
  334. xls.workbook = xSpdoc; # Needed to be able to close soffice in odsclose()
  335. xls.filename = filename;
  336. xls.app.xComp = xComp; # Needed to be able to close soffice in odsclose()
  337. xls.app.aLoader = aLoader; # Needed to be able to close soffice in odsclose()
  338. xls.odfvsn = 'UNO';
  339. xlssupport += 16;
  340. catch
  341. error ('Couldn''t open file %s using UNO', filename);
  342. end_try_catch
  343. endif
  344. # if
  345. # ---- other interfaces
  346. # endif
  347. if (~xlssupport)
  348. if (isempty (reqinterface))
  349. printf ("None.\n");
  350. warning ("No support for Excel .xls I/O");
  351. else
  352. warning ("File type not supported by %s %s %s %s %s", reqinterface{:});
  353. endif
  354. xls = [];
  355. else
  356. # From here on xwrite is tracked via xls.changed in the various lower
  357. # level r/w routines and it is only used to determine if an informative
  358. # message is to be given when saving a newly created xls file.
  359. xls.changed = xwrite;
  360. # Until something was written to existing files we keep status "unchanged".
  361. # xls.changed = 0 (existing/only read from), 1 (existing/data added), 2 (new,
  362. # data added) or 3 (pristine, no data added).
  363. if (xls.changed == 1), xls.changed = 0; endif
  364. endif
  365. # Rounding up. If none of the xlsinterfaces is supported we're out of luck.
  366. if (~isempty (reqinterface) || ~xlssupport)
  367. # Reset found interfaces for re-testing in the next call. Add interfaces if needed.
  368. chkintf = [];
  369. endif
  370. endfunction
  371. ## Copyright (C) 2009,2010,2011,2012 Philip Nienhuis <prnienhuis at users.sf.net>
  372. ##
  373. ## This program is free software; you can redistribute it and/or modify
  374. ## it under the terms of the GNU General Public License as published by
  375. ## the Free Software Foundation; either version 2 of the License, or
  376. ## (at your option) any later version.
  377. ##
  378. ## This program is distributed in the hope that it will be useful,
  379. ## but WITHOUT ANY WARRANTY; without even the implied warranty of
  380. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  381. ## GNU General Public License for more details.
  382. ##
  383. ## You should have received a copy of the GNU General Public License
  384. ## along with Octave; see the file COPYING. If not, see
  385. ## <http://www.gnu.org/licenses/>.
  386. ## -*- texinfo -*-
  387. ## @deftypefn {Function File} @var{xlsinterfaces} = getxlsinterfaces (@var{xlsinterfaces})
  388. ## Get supported Excel .xls file read/write interfaces from the system.
  389. ## Each interface for which the corresponding field is set to empty
  390. ## will be checked. So by manipulating the fields of input argument
  391. ## @var{xlsinterfaces} it is possible to specify which
  392. ## interface(s) should be checked.
  393. ##
  394. ## Currently implemented interfaces comprise:
  395. ## - ActiveX / COM (native Excel in the background)
  396. ## - Java & Apache POI
  397. ## - Java & JExcelAPI
  398. ## - Java & OpenXLS (only JRE >= 1.4 needed)
  399. ## - Java & UNO bridge (native OpenOffice.org in background) - EXPERIMENTAL!!
  400. ##
  401. ## Examples:
  402. ##
  403. ## @example
  404. ## xlsinterfaces = getxlsinterfaces (xlsinterfaces);
  405. ## @end example
  406. ## Author: Philip Nienhuis
  407. ## Created: 2009-11-29
  408. ## Last updates:
  409. ## 2009-12-27 Make sure proper dimensions are checked in parsed javaclasspath
  410. ## 2010-09-11 Rearranged code and clarified messages about missing classes
  411. ## 2010-09-27 More code cleanup
  412. ## 2010-10-20 Added check for minimum Java version (should be >= 6 / 1.6)
  413. ## 2010-11-05 Slight change to reporting to screen
  414. ## 2011-02-15 Adapted to javaclasspath calling style of java-1.2.8 pkg
  415. ## 2011-03-26 OpenXLS support added
  416. ## '' Bug fix: javaclasspath change wasn't picked up between calls with req.intf
  417. ## 2011-05-18 Experimental UNO support added
  418. ## 2011-05-29 Reduced verbosity
  419. ## 2011-06-06 Fix for javaclasspath format in *nix w java-1.2.8 pkg
  420. ## 2011-06-13 Fixed potentially faulty tests for java classlib presence
  421. ## 2011-09-03 Fixed order of xlsinterfaces.<member> statements in Java detection try-catch
  422. ## '' Reset tmp1 (always allow interface rediscovery) for empty xlsinterfaces arg
  423. ## 2011-09-08 Minor code cleanup
  424. ## 2011-09-18 Added temporary warning about UNO interface
  425. ## 2012-03-01 Changed UNO warning so that it is suppressed when UNO is not yet chosen
  426. ## 2012-03-07 Only check for COM if run on Windows
  427. ## 2012-03-21 Print newline if COM found but no Java support
  428. ## '' Improved logic for finding out what interfaces to check
  429. ## '' Fixed bugs with Java interface checking (tmp1 initialization)
  430. function [xlsinterfaces] = getxlsinterfaces (xlsinterfaces)
  431. # tmp1 = [] (not initialized), 0 (No Java detected), or 1 (Working Java found)
  432. persistent tmp1 = []; persistent jcp; # Java class path
  433. persistent uno_1st_time = 0;
  434. if (isempty (xlsinterfaces.COM) && isempty (xlsinterfaces.POI) && isempty (xlsinterfaces.JXL)
  435. && isempty (xlsinterfaces.OXS) && isempty (xlsinterfaces.UNO))
  436. # Looks like first call to xlsopen. Check Java support
  437. printf ("Detected XLS interfaces: ");
  438. tmp1 = [];
  439. elseif (isempty (xlsinterfaces.POI) || isempty (xlsinterfaces.JXL)
  440. || isempty (xlsinterfaces.OXS) || isempty (xlsinterfaces.UNO))
  441. # Can't be first call. Here one of the Java interfaces is requested
  442. if (~tmp1)
  443. # Check Java support again
  444. tmp1 = [];
  445. endif
  446. endif
  447. deflt = 0;
  448. # Check if MS-Excel COM ActiveX server runs (only on Windows!)
  449. if (isempty (xlsinterfaces.COM))
  450. xlsinterfaces.COM = 0;
  451. if (ispc)
  452. try
  453. app = actxserver ("Excel.application");
  454. # If we get here, the call succeeded & COM works.
  455. xlsinterfaces.COM = 1;
  456. # Close Excel. Yep this is inefficient when we need only one r/w action,
  457. # but it quickly pays off when we need to do more with the same file
  458. # (+, MS-Excel code is in OS cache anyway after this call so no big deal)
  459. app.Quit();
  460. delete(app);
  461. printf ("COM");
  462. if (deflt), printf ("; "); else, printf ("*; "); deflt = 1; endif
  463. catch
  464. # COM non-existent. Only print message if COM is explicitly requested (tmp1==[])
  465. if (~isempty (tmp1))
  466. printf ("ActiveX not working; no Excel installed?\n");
  467. endif
  468. end_try_catch
  469. endif
  470. endif
  471. if (isempty (tmp1))
  472. # Check Java support. First try javaclasspath
  473. try
  474. jcp = javaclasspath ('-all'); # For java pkg > 1.2.7
  475. if (isempty (jcp)), jcp = javaclasspath; endif # For java pkg < 1.2.8
  476. # If we get here, at least Java works. Now check for proper version (>= 1.6)
  477. jver = char (java_invoke ('java.lang.System', 'getProperty', 'java.version'));
  478. cjver = strsplit (jver, '.');
  479. if (sscanf (cjver{2}, '%d') < 6)
  480. warning ("\nJava version might be too old - you need at least Java 6 (v. 1.6.x.x)\n");
  481. return
  482. endif
  483. # Now check for proper entries in class path. Under *nix the classpath
  484. # must first be split up. In java 1.2.8+ javaclasspath is already a cell array
  485. if (isunix && ~iscell (jcp)); jcp = strsplit (char (jcp), ":"); endif
  486. tmp1 = 1;
  487. catch
  488. # No Java support found
  489. tmp1 = 0;
  490. if ~(isempty (xlsinterfaces.POI) && isempty (xlsinterfaces.JXL)...
  491. && isempty (xlsinterfaces.OXS) && isempty (xlsinterfaces.UNO))
  492. # Some Java-based interface explicitly requested but Java support is absent
  493. xlsinterfaces.POI = 0;
  494. xlsinterfaces.JXL = 0;
  495. xlsinterfaces.OXS = 0;
  496. xlsinterfaces.UNO = 0;
  497. warning (' No Java support found (no Java JRE? no Java pkg installed AND loaded?');
  498. else
  499. # No specific Java-based interface requested (first call?)
  500. xlsinterfaces.POI = 0;
  501. xlsinterfaces.JXL = 0;
  502. xlsinterfaces.OXS = 0;
  503. xlsinterfaces.UNO = 0;
  504. printf ("\n");
  505. return;
  506. endif
  507. end_try_catch
  508. endif
  509. # Try Java & Apache POI
  510. if (isempty (xlsinterfaces.POI))
  511. xlsinterfaces.POI = 0;
  512. # Check basic .xls (BIFF8) support
  513. jpchk1 = 0; entries1 = {"poi-3", "poi-ooxml-3"};
  514. # Only under *nix we might use brute force: e.g., strfind (classname, classpath);
  515. # under Windows we need the following more subtle, platform-independent approach:
  516. for ii=1:length (jcp)
  517. for jj=1:length (entries1)
  518. if (isempty (strfind (tolower (jcp{ii}), entries1{jj}))), ++jpchk1; endif
  519. endfor
  520. endfor
  521. if (jpchk1 > 1)
  522. xlsinterfaces.POI = 1;
  523. printf ("POI");
  524. endif
  525. # Check OOXML support
  526. jpchk2 = 0; entries2 = {"xbean", "poi-ooxml-schemas", "dom4j"};
  527. for ii=1:length (jcp)
  528. for jj=1:length (entries2)
  529. if (isempty (strfind (lower (jcp{ii}), entries2{jj}))), ++jpchk2; endif
  530. endfor
  531. endfor
  532. if (jpchk2 > 2), printf (" (& OOXML)"); endif
  533. if (xlsinterfaces.POI)
  534. if (deflt), printf ("; "); else, printf ("*; "); deflt = 1; endif
  535. endif
  536. endif
  537. # Try Java & JExcelAPI
  538. if (isempty (xlsinterfaces.JXL))
  539. xlsinterfaces.JXL = 0;
  540. jpchk = 0; entries = {"jxl"};
  541. for ii=1:length (jcp)
  542. for jj=1:length (entries)
  543. if (isempty (strfind (lower (jcp{ii}), entries{jj}))), ++jpchk; endif
  544. endfor
  545. endfor
  546. if (jpchk > 0)
  547. xlsinterfaces.JXL = 1;
  548. printf ("JXL");
  549. if (deflt), printf ("; "); else, printf ("*; "); deflt = 1; endif
  550. endif
  551. endif
  552. # Try Java & OpenXLS
  553. if (isempty (xlsinterfaces.OXS))
  554. xlsinterfaces.OXS = 0;
  555. jpchk = 0; entries = {"openxls"};
  556. for ii=1:length (jcp)
  557. for jj=1:length (entries)
  558. if (isempty (strfind (lower (jcp{ii}), entries{jj}))), ++jpchk; endif
  559. endfor
  560. endfor
  561. if (jpchk > 0)
  562. xlsinterfaces.OXS = 1;
  563. printf ("OXS");
  564. if (deflt), printf ("; "); else, printf ("*; "); deflt = 1; endif
  565. endif
  566. endif
  567. # Try Java & UNO
  568. if (isempty (xlsinterfaces.UNO))
  569. xlsinterfaces.UNO = 0;
  570. # entries0(1) = not a jar but a directory (<00o_install_dir/program/>)
  571. jpchk = 0; entries = {'program', 'unoil', 'jurt', 'juh', 'unoloader', 'ridl'};
  572. for jj=1:numel (entries)
  573. for ii=1:numel (jcp)
  574. jcplst = strsplit (jcp{ii}, filesep);
  575. jcpentry = jcplst {end};
  576. if (~isempty (strfind (lower (jcpentry), lower (entries{jj})))); ++jpchk; endif
  577. endfor
  578. endfor
  579. if (jpchk >= numel (entries))
  580. xlsinterfaces.UNO = 1;
  581. printf ('UNO');
  582. if (deflt), printf ("; "); else, printf ("*; "); deflt = 1; uno_1st_time = min (++uno_1st_time, 2); endif
  583. endif
  584. endif
  585. # ---- Other interfaces here, similar to the ones above
  586. if (deflt), printf ("(* = active interface)\n"); endif
  587. ## FIXME the below stanza should be dropped once UNO is stable.
  588. # Echo a suitable warning about experimental status:
  589. if (uno_1st_time == 1)
  590. ++uno_1st_time;
  591. printf ("\nPLEASE NOTE: UNO (=OpenOffice.org-behind-the-scenes) is EXPERIMENTAL\n");
  592. printf ("After you've opened a spreadsheet file using the UNO interface,\n");
  593. printf ("xlsclose on that file will kill ALL OpenOffice.org invocations,\n");
  594. printf ("also those that were started outside and/or before Octave!\n");
  595. printf ("Trying to quit Octave w/o invoking xlsclose will only hang Octave.\n\n");
  596. endif
  597. endfunction