Mercurial > forge
changeset 12461:f87e10495905 octave-forge
Preliminary gnumeric write support
author | prnienhuis |
---|---|
date | Wed, 30 Apr 2014 22:30:26 +0000 |
parents | 6373318c2af8 |
children | c39154770a99 |
files | main/io/inst/private/__OCT_oct2gnm__.m main/io/inst/private/__OCT_spsh_close__.m main/io/inst/private/__OCT_spsh_open__.m |
diffstat | 3 files changed, 80 insertions(+), 49 deletions(-) [+] |
line wrap: on
line diff
--- a/main/io/inst/private/__OCT_oct2gnm__.m Wed Apr 30 22:29:37 2014 +0000 +++ b/main/io/inst/private/__OCT_oct2gnm__.m Wed Apr 30 22:30:26 2014 +0000 @@ -23,7 +23,7 @@ ## Author: Philip Nienhuis <prnienhuis at users . sf .net> ## Created: 2014-04-20 -function [xls, status] = __OCT_oct2gnm__ (arr, xls, wsh, crange, spsh_opts=0) +function [xls, status] = __OCT_oct2gnm__ (obj, xls, wsh, crange, spsh_opts=0, obj_dims) ## A. Find out if we write to existing or new sheet new_sh = 0; @@ -47,32 +47,36 @@ endif wsh = idx; endif - ## Check if we made a new file from template + + ## Check if we made a new file from template, add a new sheet, or add data to a sheet if (strcmpi (xls.sheets.sh_names{1}, " ") && numel (xls.sheets.sh_names) == 2 && new_sh) + ## Completely new file. Clean up and copy a few things xls.sheets.sh_names(1) = []; - new_sh = 0; wsh--; + idx_s = xls.sheets.shtidx(wsh); + idx_e = xls.sheets.shtidx(wsh+1) - 1; xls.changed = 2; - endif - - ## B. Update sheet info in file pointer struct - if (new_sh) + lims = [obj_dims.lc, obj_dims.rc; obj_dims.tr, obj_dims.br]; + rawarr = obj; + elseif (new_sh) + ## New sheet. Provisionally update sheet info in file pointer struct wsh = numel (xls.sheets.sh_names); idx_s = xls.sheets.shtidx(wsh) ; ## First position after last sheet idx_e = idx_s - 1; - raw = {}; - lims = []; + xls.changed = 1; + lims = [obj_dims.lc, obj_dims.rc; obj_dims.tr, obj_dims.br]; + rawarr = obj; else + ## Just write new data into an existing sheet idx_s = xls.sheets.shtidx(wsh); idx_e = xls.sheets.shtidx(wsh+1) - 1; - ## Get all data in sheet and row/column limits - [raw, xls] = __OCT_gnm2oct__ (xls, wsh, "", struct ("formulas_as_text", 1)); + ## Get all current data in sheet and current row/column limits + [rawarr, xls] = __OCT_gnm2oct__ (xls, wsh, "", struct ("formulas_as_text", 1)); lims = xls.limits; + ## C. Merge old and new data. Provisionally allow empty new data to wipe old data + [rawarr, lims] = __OCT_merge_data__ (rawarr, lims, obj, obj_dims); endif - ## C. Merge old and new data. Provisionally allow empty new data to wipe old data - [arr, lims, onr, onc] = __OCT_merge_data__ (raw, lims, obj, obj_dims); - #============================================================================== ## D. Create a temporary file to hold the new sheet xml @@ -84,27 +88,35 @@ endif ## Write data to sheet - status = __OCT__oct2gnm_sh__ (fid, rawarr, wsh, lims, onc, onr); + status = __OCT__oct2gnm_sh__ (fid, rawarr, xls.sheets.sh_names{wsh}, lims); ## E. Merge new/updated sheet into gnumeric file ## Read first chunk until sht_idx<xx> - fidc = fopen (xls.workbook), "r+"); - ## Go to start of requested sheet -# fseek (fidc, 0, 'bof'); + fidc = fopen (xls.workbook, "r+"); ## Read and concatenate just adapted/created sheet/table:table gnm_xml = fread (fidc, idx_s - 1, "char=>char")'; ## F. Optionally update SheetName Index node - if new_sh) - [shtidxnode, ss, ee] = getxmlnode (gnm_xml, "gnm:SheetNameIndex"); - sh_node = sprintf('><gnm:SheetName gnm:Cols="1024" gnm:Rows="65536">%s</gnm:SheetName>', - xls.sheets.sh_names{wsh}); - ## Add close tag to ease up next strrep - sh_node = [ sh_node "</gnm:SheetNameIndex>" ]; - shtidxnode = strrep (shtidxnode, "></gnm:SheetNameIndex>", sh_node); - ## Replace SheetNameIndex node - gnm_xml = [gnm_xml(1:ss-1) shtidxnode gnm_xml(ee+1:end) ]; + if (new_sh) + if (wsh == 1) + ## New file,existing sheet. Find then (only) gnm:SheetName node + [shtnmnode, ss, ee] = getxmlnode (gnm_xml, "gnm:SheetName"); + ipos = index (shtnmnode, "> </gnm:SheetName>"); + shtnmnode = [ shtnmnode(1:ipos) xls.sheets.sh_names{1} shtnmnode(ipos+2:end) ]; + ## Replace SheetName node + gnm_xml = [ gnm_xml(1:ss-1) shtnmnode gnm_xml(ee+1:end) ]; + else + ## Existing file, append new SheetName node to end of SheetName nodes list + [shtidxnode, ss, ee] = getxmlnode (gnm_xml, "gnm:SheetNameIndex"); + sh_node = sprintf('><gnm:SheetName gnm:Cols="1024" gnm:Rows="65536">%s</gnm:SheetName>', + xls.sheets.sh_names{wsh}); + ## Add close tag to ease up next strrep + sh_node = [ sh_node "</gnm:SheetNameIndex>" ]; + shtidxnode = strrep (shtidxnode, "</gnm:SheetNameIndex>", sh_node); + ## Replace SheetNameIndex node + gnm_xml = [ gnm_xml(1:ss-1) shtidxnode gnm_xml(ee+1:end) ]; + endif endif ## Rewind tmp sheet and read it behind gnm_xml @@ -124,7 +136,7 @@ fprintf (fidc, "%s", gnm_xml); fclose (fidc); - ## G. Update sheet pointers in ods file pointer + ## G. Update sheet pointers in ods/xls file pointer if (new_sh) xls.sheets.shtidx(wsh+1) = idx_s + lsheet; xls.changed = 2; @@ -137,18 +149,18 @@ endfunction -function [ status ] = __OCT__oct2gnm_sh__ (fid, raw, wsh, lims, onc, onr) +function [ status ] = __OCT__oct2gnm_sh__ (fid, raw, wsh, lims) ## Write out the lot to requested sheet ## 1. Sheet open tags - tag = 'gnm:Sheet DisplayFormulas="0" HideZero="0" HideGrid="0"'; + tag = '<gnm:Sheet DisplayFormulas="0" HideZero="0" HideGrid="0"'; tag = [ tag ' HideColHeader="0" HideRowHeader="0" DisplayOutlines="1"' ]; tag = [ tag ' OutlineSymbolsBelow="1" OutlineSymbolsRight="1"' ]; tag = [ tag ' Visibility="GNM_SHEET_VISIBILITY_VISIBLE" GridColor="0:0:0">' ]; fprintf (fid, "%s", tag); - fprintf (fid, "<gnm:Name>Sheet%d</gnm:Name>", wsh); + fprintf (fid, "<gnm:Name>%s</gnm:Name>", wsh); fprintf (fid, "<gnm:MaxCol>%d</gnm:MaxCol><gnm:MaxRow>%d</gnm:MaxRow>", ... lims(1, 2) - 1, lims(2, 2) - 1); @@ -163,30 +175,33 @@ for jj=1:size (raw, 2) # lims(##, ##):lims(##, ##) ## Column # in gnumeric = 0-based - irow = lims(1, 2) - 2 + ii; - if (islogical (raw{ii, jj})) + icol = lims(2, 1) - 2 + jj; + if (isempty (raw{ii, jj})) + ## Do nothing + + elseif (islogical (raw{ii, jj})) ## BOOLEAN. Convert to acceptable format for gnumeric - val = FALSE; + val = "FALSE"; if (raw{ii, jj}) - val = TRUE; + val = "TRUE"; endif - fprintf (fid, '<gnm:Cell Row="%d" Col="%d" ValueType="20"></gnm:Cell>', ... + fprintf (fid, '<gnm:Cell Row="%d" Col="%d" ValueType="20">%s</gnm:Cell>', ... irow, icol, val) elseif (isnumeric (raw{ii, jj})) - ## Any numric value; gnumeric only has FLOAT type + ## Any numeric value; gnumeric only has FLOAT type fprintf (fid, '<gnm:Cell Row="%d" Col="%d" ValueType="40">%f</gnm:Cell>', ... irow, icol, raw{ii, jj}); elseif (ischar (raw{ii, jj})) ## STRING - fprintf (fid, '<gnm:Cell Row="%d" Col="%d" ValueType="20">%s</gnm:Cell>', ... + fprintf (fid, '<gnm:Cell Row="%d" Col="%d" ValueType="60">%s</gnm:Cell>', ... irow, icol, raw{ii, jj}); else ## Do nothing, just skip - endswitch + endif endfor endfor
--- a/main/io/inst/private/__OCT_spsh_close__.m Wed Apr 30 22:29:37 2014 +0000 +++ b/main/io/inst/private/__OCT_spsh_close__.m Wed Apr 30 22:30:26 2014 +0000 @@ -1,4 +1,4 @@ -## Copyright (C) 2013 Philip Nienhuis +## Copyright (C) 2013,2014 Philip Nienhuis ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -33,7 +33,8 @@ ## 2014-01-28 Zip both .ods & xlsx, gzip .gnumeric ## '' Reorganize code a bit ## 2014-04-06 Fix filename arg in error msg -## '' cd out of tmp dir before removing it +## '' cd out of tmp dir before removing it +## 2014-04-30 Gnumeric write support function [xls] = __OCT_spsh_close__ (xls) @@ -56,14 +57,27 @@ system (sprintf ("zip -q -r %s *.* .", filename)); xls.changed = 0; catch - printf ("odsclose: could not zip ods contents in %s to %s\n", xls.workbook, filename); + printf ("odsclose: could not zip ods contents in %s to %s\n", ... + xls.workbook, filename); end_try_catch; endif elseif (strcmpi (xls.filename(end-8:end), ".gnumeric")) - ## gnumeric files are gzipped - ## Delete temporary file - unlink (xls.workbook); + ## gnumeric files are gzipped + try + status = system (sprintf ("gzip -c -S=gnumeric %s > %s", ... + xls.workbook, filename)); + if (! status) + ## Delete temporary file + unlink (xls.workbook); + endif + catch + status = 1; + end_try_catch + if (status) + printf ("odsclose: could not gzip gnumeric contents in %s to %s\n", ... + xls.workbook, filename); + endif endif @@ -74,6 +88,5 @@ confirm_recursive_rmdir (0, "local"); rmdir (xls.workbook, "s"); endif - endfunction
--- a/main/io/inst/private/__OCT_spsh_open__.m Wed Apr 30 22:29:37 2014 +0000 +++ b/main/io/inst/private/__OCT_spsh_open__.m Wed Apr 30 22:30:26 2014 +0000 @@ -44,7 +44,8 @@ ## 2014-02-08 Fix wrong function name in error msg (couldn't be unzipped) ## 2014-03-17 Simplify sheet names discovery ## '' Ignore SheetId (nowhere used) -## 2014-03-18 Reinstate SheetId (was used somewhere after all) +## 2014-03-18 Reinstate SheetId (was used somewhere after all) +## 2014-04-30 Close file handle for gnumeric files function [ xls, xlssupport, lastintf] = __OCT_spsh_open__ (xls, xwrite, filename, xlssupport, ftype) @@ -61,7 +62,7 @@ elseif (ftype == 5) ext = ".gnumeric"; endif - ## New file, get it from template + ## New file, get it from template. Use odsopen.m to find it templ = strrep (which ("odsopen"), "odsopen.m", ["templates" filesep "template" ext]); else templ = filename; @@ -71,7 +72,9 @@ ## Gnumeric xml files are gzipped system (sprintf ("gzip -d -c -S=gnumeric %s > %s", templ, tmpdir)); fid = fopen (tmpdir, 'r'); - xml = fread (fid, "char=>char").'; + xml = fread (fid, "char=>char").'; + ## Close file handle, don't delete file + fclose (fid); else ## xlsx and ods are zipped try