# HG changeset patch
# User Markus Muetzel <markus.muetzel@gmx.de>
# Date 1500500237 -7200
#      Wed Jul 19 23:37:17 2017 +0200
# Node ID 22d81af0cfec2f15173c8ad37e2bb8e0dc9b611d
# Parent  5b5b31fa402016d27ec8d6f9931e245419a85c80
Read string formula results and correct types for 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 5b5b31fa4020 -r 22d81af0cfec inst/private/__OCT_xlsx2oct__.m
--- a/inst/private/__OCT_xlsx2oct__.m	Tue Jul 18 22:02:41 2017 +0200
+++ b/inst/private/__OCT_xlsx2oct__.m	Wed Jul 19 23:37:17 2017 +0200
@@ -96,8 +96,12 @@
   ## 1. Get pure numbers, including booleans, double and boolean formula
   ## results, from cells w/o 's=""' tag
   val = cell2mat (regexp (rawdata, '<c r="\w+"(?: t="[bn]+")?>(?:<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_bn = regexp (rawdata, '<c r="(\w+)"(?: t="([bn]+)")?>(?:<f.+?(?:</f>|/>))?<v(?:.*?)>.*?</v>', "tokens");
+    valraw = cellfun (@(x) x(1), valraw_bn);
+    valbool = find (cellfun (@is_bool_value, valraw_bn));
   endif
 
   ## If val is still empty, try another regexpression (PRN: will this ever
@@ -113,22 +117,21 @@
   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"));
+    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_bn = regexp (rawdata, '<c r="(\w+)" s="\d+"(?: t="([^se]*)")?><v(?:.*?)>.*?</v>', "tokens");
+      valrawp = cellfun (@(x) x(1), valrawp_bn);
+      valboolp = find (cellfun (@is_bool_value, valrawp_bn)) + numel (val);
+      val =     [val     valp];
+      valraw =  [valraw  valrawp];
+      valbool = [valbool valboolp];
     endif
   endif
   ## Turn strings into numbers
   if (! isempty (val))
     val = num2cell (str2double (val));
+  else
+    val = {};
   endif
 
   ## 2. String / text formulas (cached results are in this sheet; fixed strings
@@ -141,44 +144,36 @@
     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
+      ##  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_bn = regexp (rawdata, '<c r="(\w+)" s="\d+"(?: t="([bn])")?>(?:<f.+?(?:</f>|/>))<v(?:.*?)>.*?</v>', "tokens");
+      valrawf3 = cellfun (@(x) x(1), valrawf3_bn);
+      valboolf3 = find (cellfun (@is_bool_value, valrawf3_bn)) + numel (val);
+      val = [val num2cell(str2double (valf3))];
+      valraw = [valraw valrawf3];
+      valbool = [valbool valboolf3];
     endif
     clear valf3 valrawf3 ;
   endif
+  # Turn boolean values into logicals.
+  val(valbool) = cellfun (@logical, val(valbool), "UniformOutput", false);
 
   ## 2.B. Strings
   if (! isempty (strings))
@@ -200,13 +195,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 ;
@@ -287,3 +277,12 @@
   endif
 
 endfunction
+
+function y = is_bool_value (x)
+## If "t=" is omitted, cell has double value
+  if length(x) > 1
+    y = strcmpi(x{2}, "b");
+  else
+    y = false;
+  endif
+endfunction
