changeset 12340:055e10a4f964 octave-forge

Integrated empty upper rows & empty upper data rows; fix temp file name
author prnienhuis
date Fri, 24 Jan 2014 21:53:37 +0000
parents 25c6cc557c31
children f9f064cebe35
files main/io/inst/private/__OCT_oct2ods__.m
diffstat 1 files changed, 104 insertions(+), 74 deletions(-) [+]
line wrap: on
line diff
--- a/main/io/inst/private/__OCT_oct2ods__.m	Fri Jan 24 21:51:43 2014 +0000
+++ b/main/io/inst/private/__OCT_oct2ods__.m	Fri Jan 24 21:53:37 2014 +0000
@@ -24,6 +24,10 @@
 ## Created: 2014-01-18
 ## Updates:
 ## 2014-01-23 Fix writing repeated empty cells
+##     ''     Added writing deafult style names in document
+## 2014-01-24 Integrated empty left columns with empty left vals in rawarr
+##     ''     Same for empty upper rows & empty upper data rows
+##     ''     Fix temp file name
 
 function [ ods, status ] = __OCT_oct2ods__ (obj, ods, wsh, crange, spsh_opts=0)
 
@@ -140,32 +144,57 @@
   endif
 
 
-  ## D. Create a temporary file to hold the new sheet xml
+  ## D. Get default table/row/column styles
+  ##    Open file content.xml
+  fids = fopen (sprintf ("%s/content.xml", ods.workbook), "r");
+  ## Get first part, til first sheet
+  contnt = fread (fids, ods.sheets.shtidx(1)-1, "char=>char").';
+  fclose (fids);
+  ## Get default styles stuff
+  contnt = getxmlnode (contnt, "office:automatic-styles");
+  is = 1; 
+  stylenode = " ";                                ## Any non-empty value
+  ## Usual default style names
+  styles = struct ("tbl", "ta1", "row", "ro1", "col", "co1");
+  ## Get actual default styles
+  while (! isempty (stylenode))
+    [stylenode, ~, is] = getxmlnode (contnt, "style:style", is, 1);
+    stylefam = getxmlattv (stylenode, "style:family");
+    if     (strcmpi (stylefam, "table-column"))
+      style.col = stylefam;
+    elseif (strcmpi (stylefam, "table"))
+      styles.tbl = stylefam;
+    elseif (strcmpi (stylefam, "table-row"))
+      styles.row = stylefam;
+    endif
+  endwhile
+
+  ## E. Create a temporary file to hold the new sheet xml
   ## Open sheet file (new or old)
   tmpfil = tmpnam;
-  fid = fopen (tmpnam, "w+");
+  fid = fopen (tmpfil, "w+");
   if (fid < 0)
     error ("oct2ods: unable to write to file %s", tmpfil);
   endif
+  ## Write data to sheet (actually table:table section in content.xml)
+  status  = __OCT__oct2ods_sh__ (fid, rawarr, wsh, lims, onc, onr, ...
+            ods.sheets.sh_names{wsh}, styles);
 
-  ## Write data to sheet (actually table:table section in content.xml)
-  status  = __OCT__oct2ods_sh__ (fid, rawarr, wsh, lims, onc, onr, ods.sheets.sh_names{wsh});
-
-  ## E. Merge new/updated sheet into content.xml
+  ## F. Merge new/updated sheet into content.xml
   ## Read first chunk of content.xml until sht_idx<xx>
   fidc = fopen (sprintf ("%s/content.xml", ods.workbook), "r+");
   ## Go to start of requested sheet
   fseek (fidc, 0, 'bof');
+
   ## Read and concatenate just adapted/created sheet/table:table
   content_xml = fread (fidc, idx_s - 1, "char=>char").';
-
   ## Rewind sheet and read it behind content_xml
   fseek (fid, 0, "bof");
   sheet = fread (fid, Inf, "char=>char").';
   lsheet = length (sheet);
   ## Close & delete sheet file
   fclose (fid);
-  unlink (tmpfil);
+  delete (tmpfil);
   content_xml = [ content_xml  sheet] ;
 
   ## Read rest of content.xml, optionally delete overwritten sheet/table:table
@@ -186,94 +215,92 @@
   endif
   ods.changed = max (ods.changed, 1);
 
+  ## FIXME: Perhaps we'd need to update the metadata in meta.xml
+
 endfunction
 
 
 ## ===========================================================================
-function [ status ] = __OCT__oct2ods_sh__ (fid, rawarr, wsh, lims, onc, onr, tname)
+function [ status ] = __OCT__oct2ods_sh__ (fid, rawarr, wsh, lims, onc, onr, tname, styles)
 
   ## Write out the lot to requested sheet
 
   ## 1. Sheet open tag
-  fprintf (fid, '<table:table table:name="%s" table:style-name="ta1">', tname);
+  fprintf (fid, '<table:table table:name="%s" table:style-name="%s">', tname, styles.tbl);
 
-  ## 2. Default column styles
-  fprintf (fid, '<table:table-column table-style-name="co1" table:number-columns-repeated="%d" table:default-cell-style-name="Default" />', lims(1, 2));
-  
-  ## 3. Optional empty rows before data are copied
-  ## FIXME actually these empty rows should be combined with upper empty rows in rawarr
-  if (lims(2, 1) > 1)
-    if (lims(2, 1) > 2)
-      tnrr = sprintf (' table:number-rows-repeated="%d"', lims(2, 1) - 1);
-    else
-      tnrr = "";
-    endif
+  ## 2. Default column styles. If required add columns repeated tag
+  if (lims(1, 2) > 1)
+    tncr = sprintf (' table:number-columns-repeated="%d"', lims(1, 2));
+  else
     tncr = "";
-    if (lims(1, 2) > 1)
-      tncr = sprintf (' table:number-columns-repeated="%d"', lims(1, 2));
-    endif
-    fprintf (fid, '<table:table-row%s><table:table-cell%s /></table:table-row>', tnrr, tncr);
   endif
+  fprintf (fid, '<table:table-column table-style-name="%s"%s table:default-cell-style-name="Default" />', ...
+          styles.col, tncr);
 
-  ## 4. Spreadsheet rows
+  ## 3. Spreadsheet rows
   ii = 1;
   while (ii <= onr)
-    ## Check for empty rows
-    ## FIXME should actually be combined with empty rows above data (see above)
-    if (all (cellfun ("isempty", rawarr(ii, :))))
-      tnrr = 1;
-      while ((ii + tnrr - 1) < onr && all (cellfun ("isempty", rawarr(++ii, :))))
-        ++tnrr;
-      endwhile
-      if (tnrr > 1)
-        tnrr = sprintf (' table:number-rows-repeated="%d"', tnrr);
-        ii += tnrr - 1;
-      else
-        tnrr = "";
+    ## 3.1 Check for empty rows
+    if (ii == 1)
+      tnrr = lims(2, 1) - 1;
+    else
+      tnrr = 0;
+    endif
+    ## Check for consecutive empty rows
+    while (ii <= onr && all (cellfun ("isempty", rawarr(ii, :))))
+      ++tnrr;
+      ++ii;
+    endwhile
+    if (tnrr > 1)
+      tnrrt = sprintf (' table:number-rows-repeated="%d"', tnrr);
+    else
+      tnrrt = "";
+    endif
+    if (tnrr)
+      ## Write empty row, optionally with row repeat tag
+      if (lims (1, 2) > 1)
+        ## Add number of empty columns repeat tag
+        tcell = sprintf ('<table:table-cell table:number-columns-repeated="%d" />', ...
+                        lims(1, 2));
       endif
-      tcell = sprintf ('<table:table-cell table:number-columns-repeated="%d" />', lims(1, 2));
-      fprintf (fid, '<table:table-row%s>%s', tnrr, tcell);
-      ## Row closing tag is written below matching endif below next while loop
-    else
+      fprintf (fid, '<table:table-row%s>%s</table:table-row>', tnrrt, tcell);
+    endif
+    if (ii <= onr)
       ## Write table row opening tag
-      fprintf (fid, '<table:table-row table:style-name="ro1">');
-      ## 4.1 Optional empty left spreadsheet columns
-      if (lims(1, 1) > 1)
-        if (lims(1, 1) > 2)
-          fprintf (fid, '<table:table-cell table:number-columns-repeated="%d" />', lims(1, 1) - 1);
-        else
-          fprintf (fid, '<table:table-cell />')
-        endif
-      endif
-      ## 4.2 Value cells
+      fprintf (fid, '<table:table-row table:style-name="%s">', styles.row);
+
+      ## 3.2 Value cells
       jj = 1;
       while (jj <= onc)
-        ## 4.2.1 Check if empty
-        if (isempty (rawarr{ii, jj}))
-          ## if empty determine consecutive empty & adapt ncr attr and write
-          tncr = 1; 
-          while ((jj + tncr - 1) < onc && isempty (rawarr{ii, jj+tncr}))
-            ++tncr;
-          endwhile
-          if (tncr > 1)
-%            tncr = sprintf (' table:number-columns-repeated="%d"', tncr);
-            fprintf (fid, '<table:table-cell table:number-columns-repeated="%d" />', tncr);
-            jj += tncr - 1;
-          else
-            fprintf (fid, '<table:table-cell />');
-          endif
+        ## 3.2.1 Check if empty. Include empty columns left of rawarr
+        if (jj == 1)
+          tncr = lims(1, 1) - 1;
         else
-          ## 4.2.2 Determine value class. Set formula attribute to empty
+          tncr = 0;
+        endif
+        ## Check consecutive empty cells & adapt ncr attr, write empty cells
+        while (jj <= onc && isempty (rawarr{ii, jj}))
+          ++tncr;
+          ++jj;
+        endwhile
+        if (tncr > 1)
+          fprintf (fid, '<table:table-cell table:number-columns-repeated="%d" />', tncr);
+        elseif (tncr == 1)
+          fprintf (fid, '<table:table-cell />');
+        endif
+        ## Process non-empty data cells
+        if (jj <= onc)
+          ## 3.2.2 Non-empty cell. Determine value type. Set formula attr = empty
           of = "";
           switch class (rawarr{ii, jj})
             case {"double", "single"}
               ovt = ' office:value-type="float"';
-              val = strtrim (sprintf ("%17.4f", rawarr{ii, jj}));
+              val = sprintf ("%.4f", rawarr{ii, jj});
               txt = sprintf ('<text:p>%s</text:p>', val);
               ## Convert to attribute
-              val = sprintf (' office:value="%17.10f"', rawarr{ii, jj});
+              val = sprintf (' office:value="%.10f"', rawarr{ii, jj});
             case {"int64", "int32", "int16", "int8", "uint64", "uint32", "uint16", "uint8"}
-              ovt = "integer";
+              ovt = ' office:value-type="integer"';
               val = strtrim (sprintf ("%d15", rawarr{ii, jj}));
               txt = sprintf ('<text:p>%s</text:p>', val);
               ## Convert to attribute
@@ -307,19 +334,22 @@
             otherwise
               ## Unknown, illegal or otherwise unrecognized value
               ovt = "";
+              val = "";
+              txt = "";
           endswitch
           # write out table-cell w office-value-type / office:value
-          fprintf (fid, '<table:table-cell%s%s%s>%s</table:table-cell>', of, ovt, val, txt);
+          fprintf (fid, '<table:table-cell%s%s%s>%s</table:table-cell>',
+                   of, ovt, val, txt);
         endif
         ++jj;
       endwhile
+      ## Write table row closing tag
+      fprintf (fid, '</table:table-row>');
     endif
-    ## Write table row closing tag
-    fprintf (fid, '</table:table-row>');
     ++ii;
   endwhile
 
-  ## 5. Closing tag
+  ## 4. Closing tag
   fprintf (fid, '</table:table>');
 
   status = 1;