# HG changeset patch
# User Markus Muetzel <markus.muetzel@gmx.de>
# Date 1500929200 -7200
#      Mon Jul 24 22:46:40 2017 +0200
# Node ID a0c5e0a748c0599e1524ca77fa6a91da59ea0900
# Parent  dd67750b3394322c699f4d26fb9e412de4d7686b
Read string formula results and correct types for Boolean and numeric formulas (bug #51512).

* __OCT_xlsx2oct__.m: Read and interpret Boolean type attributes (t="b") from
numeric values and formulas. Read string formula results from files from Excel
2013 (no s-tag). Don't interpret numeric formula results (t="n") as string (in
files from LibreOffice 5.2 or 5.3). Minor code simplification.

diff -r dd67750b3394 -r a0c5e0a748c0 inst/private/__OCT_xlsx2oct__.m
--- a/inst/private/__OCT_xlsx2oct__.m	Wed Jul 19 12:10:54 2017 +0200
+++ b/inst/private/__OCT_xlsx2oct__.m	Mon Jul 24 22:46:40 2017 +0200
@@ -93,11 +93,23 @@
   ## a "vm" tag immediately after <t> tag. As soon as we hit them in the wild
   ## these can be added (at the cost of speed performance).
 
-  ## 1. Get pure numbers, including booleans, double and boolean formula
+  ## 1.a Get pure numbers, excluding Booleans, and double formula results
   ## results, from cells w/o 's=""' tag
-  val = cell2mat (regexp (rawdata, '<c r="\w+"(?: t="[bn]+")?>(?:<f.+?(?:</f>|/>))?<v(?:.*?)>(.*?)</v>', "tokens"));
+  val = cell2mat (regexp (rawdata, '<c r="\w+"(?: t="n+")?>(?:<f.+?(?:</f>|/>))?<v(?:.*?)>(.*?)</v>', "tokens"));
+  valraw = {};
+  valbool = [];
   if (! isempty (val))
-    valraw = cell2mat (regexp (rawdata, '<c r="(\w+)"(?: t="[bn]+")?>(?:<f.+?(?:</f>|/>))?<v(?:.*?)>.*?</v>', "tokens"));
+    valraw = cell2mat (regexp (rawdata, '<c r="(\w+)"(?: t="n+")?>(?:<f.+?(?:</f>|/>))?<v(?:.*?)>.*?</v>', "tokens"));
+  endif
+
+  ## 1.b Get pure Boolean values and Boolean formula results
+  ## results, from cells w/o 's=""' tag
+  valb = cell2mat (regexp (rawdata, '<c r="\w+" t="b">(?:<f.+?(?:</f>|/>))?<v(?:.*?)>(.*?)</v>', "tokens"));
+  if (! isempty (val))
+    valrawb = cell2mat (regexp (rawdata, '<c r="(\w+)" t="b">(?:<f.+?(?:</f>|/>))?<v(?:.*?)>.*?</v>', "tokens"));
+    valbool = numel (val) + (1:numel (valb));
+    val =     [val     valb];
+    valraw =  [valraw  valrawb];
   endif
 
   ## If val is still empty, try another regexpression (PRN: will this ever
@@ -112,24 +124,22 @@
   ## If 'val' exist, check if there are tagged s="NUMBERS" values
   if (numel (regexp (rawdata, ' s="', "once")) > 0)
     ## Time/date values. Exclude formulas (having <f> </f>  of <f  /> tags),
-    ## strings  ('t="s"') and error results ('t="e"')
-    valp =            cell2mat (regexp (rawdata, '<c r="\w+" s="\d+"(?: t="[^se]*")?><v(?:.*?)>(.*?)</v>', "tokens"));
+    ## strings  ('t="s"') and error results ('t="e"').
+    valp = cell2mat (regexp (rawdata, '<c r="\w+" s="\d+"(?: t="[^se]*")?><v(?:.*?)>(.*?)</v>', "tokens"));
     if (! isempty (valp))
-      valrawp = cell2mat(regexp (rawdata, '<c r="(\w+)" s="\d+"(?: t="[^se]*")?><v(?:.*?)>.*?</v>', "tokens"));
-      if (! isempty (val))
-        val =    [val    valp];
-        valraw = [valraw valrawp];
-      else
-        val = valp;
-        valraw = valrawp;
-        clear valp valrawp ;
-      endif
+      valrawp = cell2mat (regexp (rawdata, '<c r="(\w+)" s="\d+"(?: t="[^se]*")?><v(?:.*?)>.*?</v>', "tokens"));
+      val =     [val     valp];
+      valraw =  [valraw  valrawp];
     endif
   endif
   ## Turn strings into numbers
   if (! isempty (val))
     val = num2cell (str2double (val));
+  else
+    val = {};
   endif
+  # Turn Boolean values into logicals.
+  val(valbool) = cellfun (@logical, val(valbool), "UniformOutput", false);
 
   ## 2. String / text formulas (cached results are in this sheet; fixed strings
   ## in <sharedStrings.xml>)
@@ -140,42 +150,29 @@
     valf1 = cell2mat (regexp (rawdata,     '<c r="\w+"(?: s="\d+")?(?: t="\w+")?><f(?: .*?)*(>.*?)</f>(?:<v(?:.*?)>.*?</v>)?', "tokens"));
     if (! isempty (valf1))
       valf1 = regexprep (valf1, '^>', '=');
-      valrawf1 = cell2mat(regexp (rawdata, '<c r="(\w+)"(?: s="\d+")?(?: t="\w+")?><f(?: .*?)*>.*?</f>(?:<v(?:.*?)>.*?</v>)?', "tokens"));
-      if (isempty (val))
-        val = valf1;
-      else
-        ##  Formulas start with '=' so:
-        val = [val valf1];
-        valraw = [valraw valrawf1];
-      endif
+      valrawf1 = cell2mat (regexp (rawdata, '<c r="(\w+)"(?: s="\d+")?(?: t="\w+")?><f(?: .*?)*>.*?</f>(?:<v(?:.*?)>.*?</v>)?', "tokens"));
+      ##  Formulas start with '=' so:
+      val = [val valf1];
+      valraw = [valraw valrawf1];
     endif
     clear valf1 valrawf1 ;
   else
-    ## Get (cached) formula results. Watch out! as soon as a "t" attibute equals "b" or is missing it is a number
+    ## Get (cached) formula results. Watch out! as soon as a "t" attribute
+    ## equals "b", "n" or is missing it is a number
     ## First the non-numeric formula results
-    valf2 = cell2mat (regexp (rawdata, '<c r="\w+" s="\d+" t="(?:[^sb]?|str)">(?:<f.+?(?:</f>|/>))<v(?:.*?)>(.*?)</v>', "tokens"));
+    valf2 = cell2mat (regexp (rawdata, '<c r="\w+" (?:s="\d+" )?t="(?:[^sbn]?|str)">(?:<f.+?(?:</f>|/>))<v(?:.*?)>(.*?)</v>', "tokens"));
     if (! isempty (valf2))
-      valrawf2 = cell2mat(regexp (rawdata, '<c r="(\w+)" s="\d+" t="(?:[^sb]?|str)">(?:<f.+?(?:</f>|/>))<v(?:.*?)>.*?</v>', "tokens"));
-      if (isempty (val))
-        val = valf2;
-        valraw = valrawf2;
-      else
-        val = [val valf2];
-        valraw = [valraw valrawf2];
-      endif
+      valrawf2 = cell2mat (regexp (rawdata, '<c r="(\w+)" (?:s="\d+" )?t="(?:[^sbn]?|str)">(?:<f.+?(?:</f>|/>))<v(?:.*?)>.*?</v>', "tokens"));
+      val = [val valf2];
+      valraw = [valraw valrawf2];
     endif
     clear valf2 valrawf2 ;
     ## Next the numeric formula results. These need additional conversion
-    valf3 = cell2mat (regexp (rawdata, '<c r="\w+" s="\d+"(?: t="b")?>(?:<f.+?(?:</f>|/>))<v(?:.*?)>(.*?)</v>', "tokens"));
+    valf3 = cell2mat (regexp (rawdata, '<c r="\w+" s="\d+"(?: t="[bn]")?>(?:<f.+?(?:</f>|/>))<v(?:.*?)>(.*?)</v>', "tokens"));
     if (! isempty (valf3))
-      valrawf3 = cell2mat(regexp (rawdata, '<c r="(\w+)" s="\d+"(?: t="b")?>(?:<f.+?(?:</f>|/>))<v(?:.*?)>.*?</v>', "tokens"));
-      if (isempty (val))
-        val = num2cell(str2double (valf3));
-        valraw = valrawf3;
-      else
-        val = [val num2cell(str2double (valf3))];
-        valraw = [valraw valrawf3];
-      endif
+      valrawf3 = cell2mat (regexp (rawdata, '<c r="(\w+)" s="\d+"(?: t="[bn]")?>(?:<f.+?(?:</f>|/>))<v(?:.*?)>.*?</v>', "tokens"));
+      val = [val num2cell(str2double (valf3))];
+      valraw = [valraw valrawf3];
     endif
     clear valf3 valrawf3 ;
   endif
@@ -200,13 +197,8 @@
         endif
         ## Cell addresses
         valraws = cell2mat (regexp (rawdata, '<c r="(\w+)"(?: s="\d+")? t="s"><v(?:.*?)>\d+</v>', "tokens"));
-        if (isempty (val))
-          val = vals;
-          valraw = valraws;
-        else
-          val = [val vals];
-          valraw = [valraw valraws];
-        endif
+        val = [val vals];
+        valraw = [valraw valraws];
       endif
     endif
     clear vals valraws ;
