
% Wrapper for the xlsread function so that it works on a non-pc platform
% using the open document format. Do not specify the extension on the input
% file, as .xls or .ods is automatically appended depending on the
% platform. Other arugments and outputs are the same as for the xlsread
% command.
%
% xxx - currently all input arguments must be specified (one could add
% nargin checking and such).
%
% Requires import of the odfdom library (java). Modify the static
% javaclasspath so that it includes odfdom.jar
% http://odftoolkit.org/projects/odfdom/pages/Home
%
% odfdom is dependent on xerces-j libraries as well for parsing xml, but 
% as of matlab 2008b these are already included automatically by matlab.
%
function [num str] = myxlsread(infile,wksht,rng)

% call function as normal with xls on a pc using excel COM interface.
if ispc
  infile = [infile '.xls'];
  [num str] = xlsread(infile,wksht,rng);
  return;
end

% on a mac, use the odfdom interface to read the ods file
num = []; str = {}; infile = [infile '.ods'];

import org.odftoolkit.odfdom.doc.*;
import org.odftoolkit.odfdom.doc.table.*;
import org.odftoolkit.odfdom.doc.office.*;

try
  odsDoc = OdfSpreadsheetDocument.loadDocument(infile);
  odsSpreadSheet = odsDoc.getContentRoot();
  odsTables = odsSpreadSheet.getChildNodes();
catch ME
  error(['Can not read ' infile]);
end

% iterate over the tables until we find the worksheet that we want.
len = odsTables.getLength(); found = 0;
for i=1:len
  child = odsTables.item(i-1);
  if strcmpi(child.getLocalName(),'table')
    odsTable = OdfTable.getInstance(child);
    if strcmp(odsTable.getTableName(),wksht), found = 1; break; end
  end
end
if ~found, return; end

% get the range of cells specified
i = strfind(rng,':'); brng = rng(1:i(1)-1); erng = rng(i(1)+1:end);
odsCells = odsTable.getCellRangeByPosition(brng,erng);

% iterate over the range and assign string and numeric values to outputs.
% only assign "float" and "string" types.
m = odsCells.getRowNumber(); n = odsCells.getColumnNumber(); 
for r=1:m
  for c=1:n
    odsCell = odsCells.getCellByPosition(c-1,r-1);
    type = char(odsCell.getValueType());
    if isempty(type), continue; end
    switch lower(type)
      case 'float'
        num(r,c) = odsCell.getDoubleValue();
        str{r,c} = '';
      case 'string'
        str{r,c} = char(odsCell.getStringValue());
        num(r,c) = NaN;
      otherwise
    end
  end
end
