check what is being written to our log files.
[Pman.Core] / Pman.Gnumeric.js
index e0c329e..d581916 100644 (file)
@@ -58,7 +58,7 @@ Pman.Gnumeric = function (cfg)
             * Fires when source document has been loaded
             * @param {Pman.Gnumerci} this
             */
-           "load" : true
+           'load' : true
     }); 
     
     Roo.util.Observable.call(this,cfg);
@@ -126,7 +126,10 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
      * @type {Object} rowInfo - list of row sizes
      */
     rowInfo : false,
-    
+     /**
+     * @type {Object} rowInfoDom - dom elements with sizes
+     */
+    rowInfoDom : false,
     /**
      * @type {Number} cmax - maximum number of columns
      */
@@ -145,6 +148,13 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
     
     rowOffset : 0,
     
+    /**
+     * @type {String} format - either XLSX (if images are used) or XLS - as ssconvert does not do images that well.
+     */
+    
+    format : 'xlsx',
+    
+    
     /**
      * load:
      * run the connection, parse document and fire load event..
@@ -163,7 +173,9 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
         this.sheet = false;
         this.grid = false;
         this.colInfo = false;
+        this.colInfoDom = false;
         this.rowInfo = false;
+        this.rowInfoDom = false;
         this.cmax = false;
         this.rmax = false;
         
@@ -207,8 +219,8 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
         var top = Math.floor(c/26);
         var bot = c % 26;
         var cc = top > 0 ? String.fromCharCode('A'.charCodeAt(0) + top) : '';
-        cc += String.fromCharCode('A'.charCodeAt(0) ) + bot;
-        return c+r;
+        cc += String.fromCharCode('A'.charCodeAt(0)  + bot);
+        return cc+'' +r;
         
     },
     
@@ -306,21 +318,22 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
 
         Roo.each(merge, function(c) {
             var rc = _t.rangeToRC(c.textContent);
-            //Roo.log(JSON.stringify(rc))
+            //Roo.log(JSON.stringify(rc));
             if (typeof(_t.grid[rc[0].r][rc[0].c]) == 'undefined') {
-                _t.grid[rc[0].r][rc[0].c] =  Roo.applyIf({ r : rc[0].r, c : rc[0].c }, _t.defaultCell);
+                //Roo.log(["creating empty cell for  ",rc[0].r,  rc[0].c ]);
+                 _t.createCell(rc[0].r,  rc[0].c );
+                //_t.grid[rc[0].r][rc[0].c] =  //Roo.applyIf({ r : rc[0].r, c : rc[0].c }, _t.defaultCell);
             }
                 
             _t.grid[rc[0].r][rc[0].c].colspan = (rc[1].c - rc[0].c) + 1;
             _t.grid[rc[0].r][rc[0].c].rowspan = (rc[1].r - rc[0].r) + 1;
             for(var r = (rc[0].r); r < (rc[1].r+1); r++) {
-               for(var c = rc[0].c; c < (rc[1].c+1); c++) {
+               for(var cc = rc[0].c; cc < (rc[1].c+1); cc++) {
                     //Roo.log('adding alias : ' + r+','+c);
-                   _t.grid[r][c] = _t.grid[rc[0].r][rc[0].c];
+                   _t.grid[r][cc] = _t.grid[rc[0].r][rc[0].c];
                }
            }
             
-            
         });
         // read colinfo..
         var ci = this.sheet.getElementsByTagNameNS('*','ColInfo');
@@ -340,10 +353,12 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
         ci = this.sheet.getElementsByTagNameNS('*','RowInfo');
         
         this.rowInfo = {};
+        this.rowInfoDom = {};
         Roo.each(ci, function(c) {
             var count = c.getAttribute('Count') || 1;
             var s =  c.getAttribute('No')*1;
             for(var i =0; i < count; i++) {
+                _t.rowInfoDom[s+i] = c;
                 _t.rowInfo[s+i] = Math.floor(c.getAttribute('Unit')*1);
             }
         });
@@ -371,15 +386,22 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
                    continue;
                 }
                 for (var c = s.c; c < s.c1;c++) {
-                    if (c > _t.cmax) continue;
+                    if (c > _t.cmax) {
+                        continue;
+                    }
     
-                    if (typeof(_t.grid[r][c]) == 'undefined') _t.grid[r][c] = Roo.applyIf({ r: r , c : c }, _t.defaultCell);
+                    if (typeof(_t.grid[r][c]) == 'undefined') {
+                        _t.createCell(r,c);
+                        //_t.grid[r][c] = Roo.applyIf({ r: r , c : c }, _t.defaultCell);
+                    }
                     var g=_t.grid[r][c];
                     if (typeof(g.cls) =='undefined') {
                         g.cls = [];
                         g.styles = [];
                     }
-                    if (g.cls.indexOf(s.name)  > -1) continue;
+                    if (g.cls.indexOf(s.name)  > -1) {
+                       continue;
+                    }
                     g.cls.push(s.name);
                     g.styles.push(s.dom);
                     
@@ -405,27 +427,27 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
                 ent['text-align'] = { '1' : 'left', '8': 'center', '4' : 'right'}[v] || 'left';
             },
             VAlign : function(ent,v) { 
-                ent['vertical-align'] = { '1' : 'top', '4': 'middel', '8' : 'bottom'}[v]  || 'top'
+                ent['vertical-align'] = { '1' : 'top', '4': 'middle', '8' : 'bottom'}[v]  || 'top'
             },
             Fore : function(ent,v) { 
                 var col=[];
-                Roo.each(v.split(':'), function(c) { col.push(Math.round(parseInt(c,16)/256)); })
+                Roo.each(v.split(':'), function(c) { col.push(Math.round(parseInt(c,16)/256)); });
                 ent['color'] = 'rgb(' + col.join(',') + ')';
             },
             Back : function(ent,v) { 
                 var col=[];
-                Roo.each(v.split(':'), function(c) { col.push(Math.round(parseInt(c,16)/256)); })
+                Roo.each(v.split(':'), function(c) { col.push(Math.round(parseInt(c,16)/256)); });
                 ent['background-color'] = 'rgb(' + col.join(',') + ')';
             },
             FontUnit : function(ent,v) { 
                 ent['font-size'] = v + 'px';
             },
             FontBold : function(ent,v) { 
-                if (v*1 < 1) return;
+                if (v*1 < 1) { return; }
                 ent['font-weight'] = 'bold';
             },
             FontItalic : function(ent,v) { 
-                if (v*0 < 1) return;
+                if (v*0 < 1) { return; }
                 //ent['font-weight'] = 'bold';
             },
             FontName : function(ent,v) { 
@@ -439,10 +461,10 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
             BorderColor : function(ent,v) { 
                 var vv  = v.split('-');
                 var col=[];
-                Roo.each(vv[1].split(':'), function(c) { col.push(Math.round(parseInt(c,16)/256)); })
+                Roo.each(vv[1].split(':'), function(c) { col.push(Math.round(parseInt(c,16)/256)); });
                 ent['border-'+vv[0]+'-color'] = 'rgb(' + col.join(',') + ')';
             }
-        }
+        };
         function add(e, k, v) {
             //Roo.log(k,v);
             e.gstyle[k] = v;
@@ -502,6 +524,9 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
         Roo.util.CSS.createStyleSheet(css, sid);
     },
 
+    
+    
+    
     /* ---------------------------------------  AFTER LOAD METHODS... ----------------------- */
     /**
      * set: 
@@ -519,7 +544,9 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
     set : function(cell, v, vt, vf) {
         
         var cs= typeof(cell) == 'string' ? this.toRC(cell) : cell;
-        //Roo.log( cs.r+ ',' + cs.c + ' = '+ v);
+        
+        
+        Roo.log( cs.r+ ',' + cs.c + ' = '+ v);
         // need to generate clell if it doe
         if (typeof(this.grid[cs.r]) == 'undefined') {
             Roo.log('no row:' + cell);
@@ -530,13 +557,20 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
             Roo.log('cell not defined:' + cell);
             this.createCell(cs.r,cs.c);
         }
+        // cell might not be rendered yet... so if we try and create a cell, it overrides the default formating..
+        
         if (typeof(this.grid[cs.r][cs.c].dom) == 'undefined') {
             Roo.log('no default content for cell:' + cell);
-            this.createCell(cs.r,cs.c);
+            Roo.log(this.grid[cs.r][cs.c]);
+            //this.createCell(cs.r,cs.c);
             //return;
         }
         this.grid[cs.r][cs.c].value=  v;
-        this.grid[cs.r][cs.c].dom.textContent=  v;
+        if (this.grid[cs.r][cs.c].dom) {
+            this.grid[cs.r][cs.c].dom.textContent=  v;
+        }
+        
+        
         if (typeof(vt) != 'undefined') {
             this.grid[cs.r][cs.c].valueType = vt;
             this.grid[cs.r][cs.c].dom.setAttribute('ValueType', vt);
@@ -672,7 +706,9 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
         
         data = data || this.data;
         for (var r = 0; r < this.rmax;r++) {
-            if (typeof(this.grid[r]) == 'undefined') continue;
+            if (typeof(this.grid[r]) == 'undefined') {
+                continue;
+            }
             for (var c = 0; c < this.cmax;c++) {  
                 if (typeof(this.grid[r][c]) == 'undefined') {
                     continue;
@@ -697,6 +733,60 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
         }
             
     },
+    
+    readTableData : function(table)
+    {
+        // read the first row.
+        var tds = Roo.get(table).select('tr').item(0).select('td');
+        var maxnc = 0;
+        
+        Roo.get(table).select('tr').each(function(trs) {
+            var nc = 0;
+           
+            trs.select('td').each(function(td) {
+                var cs = td.dom.getAttribute('colspan');
+                cs = cs ? cs * 1 : 1;
+                nc += cs;
+            });
+            maxnc = Math.max(nc, maxnc);
+        });
+        
+        var tr = document.createElement('tr');
+        table.appendChild(tr);
+        var ar = {};
+        for (i =0; i < maxnc; i++) {
+            ar[i] = document.createElement('td');
+            tr.appendChild(ar[i]);
+        }
+        // find the left.
+        var ret = { cols : maxnc, pos : {} };
+        for (i =0; i < maxnc; i++) {
+            ret.pos[ Roo.get(ar[i]).getLeft()] =i;
+        }
+        ret.near = function(p) {
+            // which one is nearest..
+            
+            if (this.pos[p]) {
+                return this.pos[p];
+            }
+            var prox = 100000;
+            var match = 0;
+            for(var i in this.pos) {
+                var dis = Math.abs(p-i);
+                if (dis < prox) {
+                    prox = dis;
+                    match = this.pos[i];
+                }
+            }
+            return match;
+            
+        }
+        table.removeChild(tr);
+        return ret;
+    },
+    
+     
+   
      
     /**
      * importTable: 
@@ -716,93 +806,76 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
         xoff = xoff || 0;
         yoff = yoff || 0;
         
+        
+        var table_data = this.readTableData(datagrid);
+        
+        // oroginally this cleaned line breaks, but we acutally need them..
         var cleanHTML = function (str) {
             
-             var ret = str;
-            ret = ret.replace(/&nbsp;/g,'.');
-            ret = ret.replace(/\n/g,'.');
-            ret = ret.replace(/\r/g,'.');
+            var ret = str;
+            ret = ret.replace(/&nbsp;/g,' ');
+           // ret = ret.replace(/\n/g,'.');
+          //  ret = ret.replace(/\r/g,'.');
             var i;
-            while (-1 != (i = ret.indexOf(unescape('%A0')))) {
-                ret = ret.substring(0,i) + ' ' + ret.substring(i+1,str.length);
-            }
+             
             return ret;
         };
 
         
         // <cell col="A" row="1">Test< / cell>
         // <cell col="B" row="2" type="Number" format="test1">30< / cell>
-        var rowOffsets = [];
+        var rowOffsets = {};
         var rows = datagrid.getElementsByTagName('tr');
         //alert(rows.length);
         
+        
         for(var row=0;row<rows.length;row++) {
-            //var style = document.defaultView.getComputedStyle(rows[row], "");
             
-            //if (rows[row].getAttribute('xls:height')) {
-            //    this.setRowHeight(row+y_offset, 0 + rows[row].getAttribute('xls:height'));
-            //} else {
-            //    this.setRowHeight(row+y_offset, 0 + style.height.replace(/[^0-9.]+/g,''));
-           // }
+            // let's see what affect this has..
+            // it might mess things up..
             
-            var coloffset = 0;
-           // if (rowOffsets[row]) {
-           //     coloffset += rowOffsets[row];
-           // }
-            var cols = rows[row].getElementsByTagName('td');
+            if (rows[row].getAttribute('xls:height')) {
+                this.setRowHeight(row + yoff +1, 1* rows[row].getAttribute('xls:height'));
+            } else {
+                this.setRowHeight( row + yoff +1, Roo.get(rows[row]).getHeight());
+            }
             
+            var cols = rows[row].getElementsByTagName('td');
             
             for(var col=0;col < cols.length; col++) {
                 
+                if (cols[col].getAttribute('xls:width')) {
+                    this.setColumnWidth(col, 1 * cols[col].getAttribute('xls:width'));
+                }
+                
+                var colspan = cols[col].getAttribute('colspan');
+                colspan  = colspan ? colspan *1 : 1;
+                
+                var rowspan = cols[col].getAttribute('rowspan');
+                rowspan = rowspan ? rowspan * 1 : 1;
+                
+                var realcol = table_data.near( Roo.get(cols[col]).getLeft() );
                 
-                //var colat = col + coloffset;
-                coloffsetadd = 0;
-                if (cols[col].getAttribute('colspan') && (cols[col].getAttribute('colspan') > 1)) {
+                
+                
+                if (colspan > 1 || rowspan > 1) {
                     
-                   //row + yoff, c : col + xoff + coloffset
+                    // getting thisese right is tricky..
                     this.mergeRegion(
-                        col + xoff + coloffset,
-                        row + yoff,
-                        col + xoff + coloffset + (cols[col].getAttribute('colspan') - 1), 
-                        row + yoff /*+ (
-                                (cols[col].getAttribute('rowspan') > 1) ?
-                                    (cols[col].getAttribute('rowspan') - 1) : 0
-                                )*/
+                        realcol + xoff,
+                        row + yoff +1,
+                        realcol+ xoff + (colspan -1),
+                        row + yoff + rowspan 
                     );
-                    coloffsetadd  = (cols[col].getAttribute('colspan')*1) - 1;
-                    
-                }
-                /*
-                if (cols[col].getAttribute('rowspan') && (cols[col].getAttribute('rowspan') > 1)) {
-                    // this should really do a merge, but it's pretty damn complex...
-                    //this.mergeRegion(colat,row +y_offset,colat + (cols[col].getAttribute('colspan') - 1), row+y_offset);
-                    var rroff = cols[col].getAttribute('colspan')  ? (cols[col].getAttribute('colspan') -0): 1;
-                    var rr = 0;
-                    for (rr = 0; rr < cols[col].getAttribute('rowspan');rr++) {
-                        rowOffsets[rr + row] = col + rroff;
-                    }
                     
-                }
-                 */
-               
-                /*
-                var style = this.newStyle();
-                if (style.setFrom(cols[col])) {
-                    style.add(
-                        colat+x_offset,
-                        row+y_offset,
-                        
-                        colat+x_offset + ((cols[col].getAttribute('colspan') > 1) ?
-                                    (cols[col].getAttribute('colspan') - 1) : 0),
-                        row+y_offset  + ((cols[col].getAttribute('rowspan') > 1) ?
-                                    (cols[col].getAttribute('rowspan') - 1) : 0) 
-                    );
                 }
                 
-                 */
                 // skip blank cells
+                // set the style first..
+                this.parseHtmlStyle( cols[col], row + yoff, realcol + xoff   , colspan, rowspan);
+                
                 if (!cols[col].childNodes.length) {
-                    coloffset += coloffsetadd;
+                     
                     continue;
                 }
                 
@@ -841,28 +914,13 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
                        
                         break;
                 }
-                /*
-                if (cols[col].getAttribute('xls:src')) {
-                    //alert(cols[col].childNodes[0].width);
-                    if (this.writeImage(
-                        row+y_offset, 
-                        colat+x_offset+coloffset, 
-                        cols[col].getAttribute('xls:src'), 
-                        cols[col].childNodes[0].width, 
-                        cols[col].childNodes[0].height
-                        )) {
-                       
-                    }
-                    continue;
-                }
-                */
-                 
+               
                 if (!cols[col].childNodes[0].nodeValue) {
-                    coloffset += coloffsetadd;
+                   
                     continue;
                 }
                 if (!cols[col].childNodes[0].nodeValue.replace(/^\s*|\s*$/g,"").length) {
-                    coloffset += coloffsetadd;
+                  
                     continue;
                 }
                 // strip me.!
@@ -885,12 +943,9 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
                     vt = '';
                     cell_value_text = s.replace(/#row#/g,(row + yoff + 1));
                 }
-                this.set({ r: row + yoff, c : col + xoff + coloffset }, cell_value_text, vt, vf);
+                this.set({ r: row + yoff, c : realcol + xoff }, cell_value_text, vt, vf);
                  
-                coloffset += coloffsetadd;
-                
-                
-                
+                  
                 
                 
                 
@@ -900,26 +955,307 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
         
     },
     
+    
+    
+    parseHtmlStyle : function(dom, row, col, colspan, rowspan) {
+        
+        function toCol (rgb) {
+            
+            var ar = rgb.replace(/rgb[a]?\(/, '').replace(/\)/, '').replace(/ /, '').split(',');
+            var rcs = [];
+            ar = ar.slice(0,3);
+            Roo.each(ar, function(c) { 
+                rcs.push((c*c).toString(16)) ;   
+            });
+            return rcs.join(':');
+            
+        }
+        
+        var el = Roo.get(dom);
+        var map =  {
+            'text-align'  : function(ent,v) { 
+                ent['HAlign'] = { 'left' : '1', 'center' : '8' ,  'right' : '4' }[v] || '1';
+            },
+            'vertical-align': function(ent,v) { 
+                ent['VAlign'] = { 'top' : '1', 'middel' : '8' ,  'bottom' : '4' }[v] || '1';
+            },
+            
+            'color': function(ent,v) { 
+                ent['Fore'] = toCol(v);
+                // this is a bit dumb.. we assume that if it's not black text, then it's shaded..
+                if (ent['Fore'] != '0:0:0') {
+                    ent['Shade'] = 1;
+                }
+                
+            },
+            'background-color' : function(ent,v) { 
+                ent['Back'] = toCol(v);
+                 
+            }
+            
+        };
+       
+        var ent = {
+                HAlign:"1",
+                VAlign:"2",
+                WrapText:"0",
+                ShrinkToFit:"0",
+                Rotation:"0",
+                Shade:"0",
+                Indent:"0",
+                Locked:"0",
+                Hidden:"0",
+                Fore:"0:0:0",
+                Back:"FFFF:FFFF:FFFF",
+                PatternColor:"0:0:0",
+                Format:"General"
+        };
+           
+        for(var k in map) {
+            var val = el.getStyle(k);
+            if (!val || !val.length) {
+               continue;
+            }
+            map[k](ent,val);
+        }
+        // special flags..
+        if (el.dom.getAttribute('xls:wraptext')) {
+            ent.WrapText = 1;
+        }
+        if (el.dom.getAttribute('xls:valign')) {
+            ent.VAlign= 1;
+        }
+        if (el.dom.getAttribute('xls:halign')) {
+            ent.HAlign= 1;
+        }
+        // fonts..
+        var fmap = {
+            
+           
+            'font-size' : function(ent,v) { 
+                ent['Unit'] = v.replace(/px/, '');
+            },
+            'font-weight' : function(ent,v) { 
+                if (v != 'bold') {
+                   return;
+                }
+                ent['Bold'] = 1;
+            },
+            'font-style' : function(ent,v) { 
+                if (v != 'italic') {
+                    return;
+                }
+                ent['Italic'] = 1;
+            } 
+        };
+       
+        var fent = {
+            Unit:"10",
+            Bold:"0",
+            Italic:"0",
+            Underline:"0",
+            StrikeThrough:"0"
+        };
+        
+        for(var k in fmap) {
+            var val = el.getStyle(k);
+            if (!val || !val.length) {
+               continue;
+            }
+            fmap[k](fent,val);
+        }
+        var font = el.getStyle('font-family') || 'Sans';
+        if (font.split(',').length > 1) {
+            font = font.split(',')[1].replace(/\s+/, '');
+        }
+        
+        
+        /// -- now create elements..
+        
+        var objs = this.sheet.getElementsByTagNameNS('*','Styles')[0];
+        
+        //<gnm:StyleRegion startCol="0" startRow="0" endCol="255" endRow="65535"
+        var sr = this.doc.createElementNS('http://www.gnumeric.org/v10.dtd', 'gnm:StyleRegion');
+        objs.appendChild(sr);
+        objs.appendChild(this.doc.createTextNode("\n"));// add a line break..
+
+        sr.setAttribute('startCol', col);
+        sr.setAttribute('endCol', col+ colspan-1);
+        sr.setAttribute('startRow', row);
+        sr.setAttribute('endRow', row + rowspan -1);
+        
+        
+        var st = this.doc.createElementNS('http://www.gnumeric.org/v10.dtd', 'gnm:Style');
+        sr.appendChild(st);
+        // do we need some defaults..
+        for(var k in ent) {
+            //Roo.log(k);
+            st.setAttribute(k, ent[k]);
+        }
+        
+        var fo = this.doc.createElementNS('http://www.gnumeric.org/v10.dtd', 'gnm:Font');
+        st.appendChild(fo);
+        // do we need some defaults..
+        for(var k in fent) {
+            fo.setAttribute(k, fent[k]);
+        }
+        fo.textContent  = font;
+        
+        var sb = false;
+        // borders..
+        Roo.each(['top','left','bottom','right'], function(p) {
+            var w = el.getStyle('border-' + p + '-width').replace(/px/, '');
+            if (!w || !w.length || (w*1) < 1) {
+                return;
+            }
+            if (!sb) {
+                sb= this.doc.createElementNS('http://www.gnumeric.org/v10.dtd', 'gnm:StyleBorder');
+            }
+            var be = this.doc.createElementNS('http://www.gnumeric.org/v10.dtd', 'gnm:' + p[0].toUpperCase() + p.substring(1));
+            be.setAttribute('Style', '1');
+            be.setAttribute('Color', '0:0:0'); // fixme..
+            sb.appendChild(be);
+            
+        }, this);
+        // start adding them all together..
+        
+        if (sb) {
+            st.appendChild(sb);
+        }
+        
+        
+        
+        
+    },
+    
+    /**
+     * writeImageOld:
+     * write an image in old gnumberic format (needs base64 data to write it)
+     * 
+     * 
+     * @param {Number} row  row to put it in (rows start at 0)
+     * @param {Number} col  column to put it in
+     * @param {Number} data  the base64 description of the images
+     * @param {Number} width image width
+     * @param {Number} width image height
+     * 
+     */
+    writeImageOld : function (row, col, data, width, height, type, size) 
+    {
+        
+        if (!data) {
+            throw "write Image called with missing data";
+        }
+        
+        row*=1;
+        col*=1;
+        height*=1;
+        width*=1;
+        var objs = this.sheet.getElementsByTagNameNS('*','Objects')[0];
+        var soi = this.doc.createElementNS('http://www.gnumeric.org/v10.dtd', 'gnm:SheetObjectImage');
+        
+        var colwidth = 0;
+        var endcol=col;
+        for ( endcol=col;endcol <100; endcol++) {
+            if (!this.colInfo[endcol]) {
+                this.colInfo[endcol] = 100; // eak fudge
+            }
+            colwidth += this.colInfo[endcol];
+            if (colwidth > width) {
+                break;
+            }
+        }
+        
+        soi.setAttribute('ObjectBound', this.RCtoCell(row,col) + ':' + this.RCtoCell(row,endcol));
+     
+        var ww = 0.01; // offset a bit...
+        var hh = 0.01; //
+        
+        var rowHeight = typeof(this.rowInfoDom[row]) == 'undefined' ? 100 : 
+               this.rowInfoDom[row].getAttribute('Unit')*1;
+       
+       
+        var ww2 = 1 - ((colwidth - width) / this.colInfo[endcol]);
+        var hh2 = 1 - ((rowHeight - height) /    rowHeight);
+        
+        var offset_str = ww + ' '  + hh + ' ' + ww2 + ' '+hh2;
+        
+       // offset string 0.01 0.01 0.01 0.392 << last one needs to be calculated based on proportions.
+       // so what are our dimentions..
+       
+       
+       
+       
+       
+        //alert(offset_str);
+        soi.setAttribute('ObjectOffset', offset_str);
+        soi.setAttribute('ObjectAnchorType','16 16 16 16');
+        soi.setAttribute('Direction','17');
+        soi.setAttribute('crop-top','0.000000');
+        soi.setAttribute('crop-bottom','0.000000');
+        soi.setAttribute('crop-left','0.000000');
+        soi.setAttribute('crop-right','0.000000');
+        
+       
+       
+       
+       
+        var content = this.doc.createElement('Content');
+        content.setAttribute('image-type', type ? type : 'jpeg');
+        content.setAttribute('size-bytes', size);
+       content.appendChild( this.doc.createTextNode(data));
+        soi.appendChild(content);
+        objs.appendChild(soi);
+        
+        if (typeof(this.grid[row]) == 'undefined') {
+            this.grid[row] = [];
+        }
+        if (typeof(this.grid[row][col]) == 'undefined') {
+            this.createCell(row,col);
+        }
+        
+        this.grid[row][col].value=  data;
+        this.grid[row][col].valueFormat = 'image';
+        this.grid[row][col].imageType = type;
+        this.grid[row][col].width = width;
+        this.grid[row][col].height = height;
+        
+        var godoc = this.doc.getElementsByTagNameNS('*','GODoc')[0];
+        
+        if(godoc && godoc.parentNode) {
+            godoc.parentNode.removeChild(godoc);
+        }
+        
+        return true;
+    },
+    
     /**
      * writeImage:
      * write an image (needs base64 data to write it)
      * 
      * 
-     * @param {Number} row  row to put it in
+     * @param {Number} row  row to put it in (rows start at 0)
      * @param {Number} col  column to put it in
      * @param {Number} data  the base64 description of the images
-     * @param {Number} row2  to row
+     * @param {Number} width image width
+     * @param {Number} width image height
      * 
      */
     
-    
-    writeImage : function (row, col, data, width, height) 
+    writeImage : function (row, col, data, width, height, type) 
     {
         
+        if (!data) {
+            throw "write Image called with missing data";
+        }
         // our default height width is 50/50 ?!
         //console.log('w='+width+',height='+height);
                 //        <gmr:Objects>
-        var objs = this.doc.getElementsByTagNameNS('*','Objects')[0];
+        row*=1;
+        col*=1;
+        height*=1;
+        width*=1;
+        var objs = this.sheet.getElementsByTagNameNS('*','Objects')[0];
         var soi = this.doc.createElementNS('http://www.gnumeric.org/v10.dtd', 'gnm:SheetObjectImage');
         
         //<gmr:SheetObjectImage 
@@ -944,8 +1280,8 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
         // step 1 - work out how many columns it will span..
         // lets hope the spreadsheet is big enought..
         var colwidth = 0;
-        
-        for (var endcol=col;endcol <100; endcol++) {
+        var endcol=col;
+        for ( endcol=col;endcol <100; endcol++) {
             if (!this.colInfo[endcol]) {
                 this.colInfo[endcol] = 100; // eak fudge
             }
@@ -954,20 +1290,23 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
                 break;
             }
         }
-       
         
         soi.setAttribute('ObjectBound',
             //gnumeric_colRowToName(row,col) + ':' + gnumeric_colRowToName(row+1,col+1));
-            this.RCtoCell(row,col) + ':' + this.RCtoCell(row,col));
+            this.RCtoCell(row,col) + ':' + this.RCtoCell(row,endcol));
      
         var ww = 0.01; // offset a bit...
         var hh = 0.01; //
         
+       var rowHeight = typeof(this.rowInfoDom[row]) == 'undefined' ? 100 : 
+               this.rowInfoDom[row].getAttribute('Unit')*1;
+       
+       
         var ww2 = 1 - ((colwidth - width) / this.colInfo[endcol]);
-        var hh2 = 0.99;
+        var hh2 = 1 - ((rowHeight - height) /    rowHeight);
         
         var offset_str = ww + ' '  + hh + ' ' + ww2 + ' '+hh2;
-        //console.log(offset_str );
+        
         //alert(offset_str);
         soi.setAttribute('ObjectOffset', offset_str);
         soi.setAttribute('ObjectAnchorType','16 16 16 16');
@@ -977,19 +1316,165 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
         soi.setAttribute('crop-left','0.000000');
         soi.setAttribute('crop-right','0.000000');
                 // <Content image-type="jpeg" size-bytes="3900">......  < / Content>
+                
+        var name = 'Image' + Math.random().toString(36).substring(2);
         var content = this.doc.createElement('Content');
-        content.setAttribute('image-type','jpeg');
-        //alert(imgsrc);
-        
-        content.setAttribute('size-bytes',data.length);
-        content.textContent = data;
+        content.setAttribute('image-type', type ? type : 'jpeg');
+        content.setAttribute('name', name);
         soi.appendChild(content);
         objs.appendChild(soi);
+        
+        var godoc = this.doc.getElementsByTagNameNS('*','GODoc')[0];
+        
+        var goimage = this.doc.createElement('GOImage');
+        goimage.setAttribute('image-type', type ? type : 'jpeg');
+        goimage.setAttribute('name', name);
+        goimage.setAttribute('type', 'GOPixbuf');
+        goimage.setAttribute('width', width);
+        goimage.setAttribute('height', height);
+        goimage.textContent = data;
+        
+        godoc.appendChild(goimage);
+        
+        if (typeof(this.grid[row]) == 'undefined') {
+            this.grid[row] = [];
+        }
+        if (typeof(this.grid[row][col]) == 'undefined') {
+            this.createCell(row,col);
+        }
+        
+        this.grid[row][col].value=  data;
+        this.grid[row][col].valueFormat = 'image';
+        this.grid[row][col].imageType = type;
+        this.grid[row][col].width = width;
+        this.grid[row][col].height = height;
+        
         return true;
                 //< /gnm:SheetObjectImage>
                 // < /gnm:Objects>
 
     },
+    
+    /**
+     * writeFixedImageOld:
+     * write an image in old gnumberic format (needs base64 data to write it)
+     */
+    writeFixedImageOld : function (startCol, startRow, endCol, endRow, type, data, width, height, size) 
+    {
+        if (!data) {
+            throw "write Image called with missing data";
+        }
+        
+        startCol = startCol * 1;
+        startRow = startRow * 1;
+        endCol = endCol * 1;
+        endRow = endRow * 1;
+        width = width * 1;
+        height = height * 1;
+        
+        var objs = this.sheet.getElementsByTagNameNS('*','Objects')[0];
+        var soi = this.doc.createElementNS('http://www.gnumeric.org/v10.dtd', 'gnm:SheetObjectImage');
+        
+        soi.setAttribute('ObjectBound',this.RCtoCell(startRow, startCol) + ':' + this.RCtoCell(endRow, endCol));
+        
+        soi.setAttribute('ObjectOffset', '0 0 0 0');
+        soi.setAttribute('ObjectAnchorType','16 16 16 16');
+        soi.setAttribute('Direction','17');
+        soi.setAttribute('crop-top','0.000000');
+        soi.setAttribute('crop-bottom','0.000000');
+        soi.setAttribute('crop-left','0.000000');
+        soi.setAttribute('crop-right','0.000000');
+        
+        var content = this.doc.createElement('Content');
+        content.setAttribute('image-type', type ? type : 'jpeg');
+        content.setAttribute('size-bytes', size);
+        content.appendChild( this.doc.createTextNode(data));
+        soi.appendChild(content);
+        objs.appendChild(soi);
+        
+        if (typeof(this.grid[startRow]) == 'undefined') {
+            this.grid[startRow] = [];
+        }
+        if (typeof(this.grid[startRow][startCol]) == 'undefined') {
+            this.createCell(startRow,startCol);
+        }
+        
+        this.grid[startRow][startCol].value=  data;
+        this.grid[startRow][startCol].valueFormat = 'image';
+        this.grid[startRow][startCol].imageType = type;
+        this.grid[startRow][startCol].width = width;
+        this.grid[startRow][startCol].height = height;
+        
+        var godoc = this.doc.getElementsByTagNameNS('*','GODoc')[0];
+        
+        if(godoc && godoc.parentNode) {
+            godoc.parentNode.removeChild(godoc);
+        }
+        
+        return true;
+    },
+    
+    writeFixedImage : function (startCol, startRow, endCol, endRow, type, data, width, height) 
+    {
+        if (!data) {
+            throw "write Image called with missing data";
+        }
+        
+        startCol = startCol * 1;
+        startRow = startRow * 1;
+        endCol = endCol * 1;
+        endRow = endRow * 1;
+        width = width * 1;
+        height = height * 1;
+        
+        var objs = this.sheet.getElementsByTagNameNS('*','Objects')[0];
+        var soi = this.doc.createElementNS('http://www.gnumeric.org/v10.dtd', 'gnm:SheetObjectImage');
+        
+        soi.setAttribute('ObjectBound',this.RCtoCell(startRow, startCol) + ':' + this.RCtoCell(endRow, endCol));
+        
+        soi.setAttribute('ObjectOffset', '0 0 0 0');
+        soi.setAttribute('ObjectAnchorType','16 16 16 16');
+        soi.setAttribute('Direction','17');
+        soi.setAttribute('crop-top','0.000000');
+        soi.setAttribute('crop-bottom','0.000000');
+        soi.setAttribute('crop-left','0.000000');
+        soi.setAttribute('crop-right','0.000000');
+        
+        var name = 'Image' + Math.random().toString(36).substring(2);
+        var content = this.doc.createElement('Content');
+        content.setAttribute('image-type', type ? type : 'jpeg');
+        content.setAttribute('name', name);
+       
+        soi.appendChild(content);
+        objs.appendChild(soi);
+        
+        var godoc = this.doc.getElementsByTagNameNS('*','GODoc')[0];
+        
+        var goimage = this.doc.createElement('GOImage');
+        goimage.setAttribute('image-type', type ? type : 'jpeg');
+        goimage.setAttribute('name', name);
+        goimage.setAttribute('type', 'GOPixbuf');
+        goimage.setAttribute('width', width);
+        goimage.setAttribute('height', height);
+        goimage.textContent = data;
+        
+        godoc.appendChild(goimage);
+        
+        if (typeof(this.grid[startRow]) == 'undefined') {
+            this.grid[startRow] = [];
+        }
+        if (typeof(this.grid[startRow][startCol]) == 'undefined') {
+            this.createCell(startRow,startCol);
+        }
+        
+        this.grid[startRow][startCol].value=  data;
+        this.grid[startRow][startCol].valueFormat = 'image';
+        this.grid[startRow][startCol].imageType = type;
+        this.grid[startRow][startCol].width = width;
+        this.grid[startRow][startCol].height = height;
+        
+        return true;
+    },
  
     /**
      * mergeRegion:
@@ -1008,7 +1493,7 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
        //     return;
         //}
         
-        cell.textContent = this.RCtoCell(row1,col1) + ':' + this.RCtoCell(row2,col2)
+        cell.textContent = this.RCtoCell(row1,col1) + ':' + this.RCtoCell(row2,col2);
         
         //var merges = this.gnumeric.getElementsByTagNameNS('*','MergedRegions');
         var merges = this.sheet.getElementsByTagNameNS('*','MergedRegions');
@@ -1018,7 +1503,7 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
             this.sheet.insertBefore(merges,sl);
         } else {
             merges = merges[0];
-           }
+        }
         merges.appendChild(cell);
     
     },
@@ -1026,23 +1511,33 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
      * setRowHeight:
      * Sets the height of a row.
      * 
-     * @param {Number} row  the row to set the height of.
+     * @param {Number} r  the row to set the height of. (rows start at 0)
      * @param {Number} height (in pixels)
      */
-    setRowHeight : function (row,height)
+    setRowHeight : function (r,height)
     {
+        
         //<gmr:Rows DefaultSizePts="12.75">
         //   <gmr:RowInfo No="2" Unit="38.25" MarginA="0" MarginB="0" HardSize="1"/>
     //  < /gmr:Rows>
-        var rows = this.doc.getElementsByTagNameNS('*','Rows')[0]; // assume this exists..
-        var ri = this.doc.createElementNS('http://www.gnumeric.org/v10.dtd','gnm:MRowInfo');
+        
+        // this doesnt handle row ranges very well.. - with 'count in them..'
+        
+        if (this.rowInfoDom[r]) {
+            this.rowInfoDom[r].setAttribute('Unit', height);
+            return;
+        }
+    
+        var rows = this.sheet.getElementsByTagNameNS('*','Rows')[0]; // assume this exists..
+        var ri = this.doc.createElementNS('http://www.gnumeric.org/v10.dtd','gnm:RowInfo');
         // assume we have no rows..
-        ri.setAttribute('No', row);
+        ri.setAttribute('No', r-1);
         ri.setAttribute('Unit', height);
         ri.setAttribute('MarginA', 0);
         ri.setAttribute('MarginB', 0);
         ri.setAttribute('HardSize', 1);
         rows.appendChild(ri);
+        this.rowInfoDom[r] = ri;
     },
      
     /**
@@ -1071,7 +1566,7 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
             sheetnames = this.doc.getElementsByTagNameNS('*','Sheet');
             sheetnames[0].parentNode.appendChild(sheetnames[sheetnames.length-1].cloneNode(true));
             var sn = this.doc.getElementsByTagNameNS('*','Sheet')[sheet];
-            var cls = sn.getElementsByTagNameNS('*','Cells')[0]
+            var cls = sn.getElementsByTagNameNS('*','Cells')[0];
             while (cls.childNodes.length) {
                 cls.removeChild(cls.firstChild);
             }
@@ -1099,7 +1594,7 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
         column = column *1; 
         width= width*1;
         if (typeof(this.colInfoDom[column]) == 'undefined') {
-            var cols = this.doc.getElementsByTagNameNS('*','Cols')[0];
+            var cols = this.sheet.getElementsByTagNameNS('*','Cols')[0];
             var ri = this.doc.createElementNS('http://www.gnumeric.org/v10.dtd', 'gnm:ColInfo');
             ri.setAttribute('No', column);
             ri.setAttribute('Unit', width);
@@ -1142,12 +1637,52 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
         for (var r = 0; r < this.rmax;r++) {
             out += '<tr style="height:'+this.rowInfo[r]+'px;">';
             for (var c = 0; c < this.cmax;c++) {
-                var g = (typeof(grid[r][c]) == 'undefined') ? defaultCell  : grid[r][c];
+                if (typeof(grid[r][c]) == 'undefined')  {
+                    this.createCell(r,c);
+                    
+                }
+                var g = grid[r][c];
                 
-                if (typeof(g.cls) =='undefined') g.cls = [];
+                if (typeof(g.cls) =='undefined') {
+                    g.cls = [];
+                }
                 var w= calcWidth(c,g.colspan);
+                
+                var value = g.value[0] == '=' ? 'CALCULATED' : g.value;
+                
+                try {
+                    if(
+                        g.styles[0].firstElementChild.getAttribute('Format') == "D\\-MMM\\-YYYY;@" &&
+                        g.value[0] != '=' &&
+                        !isNaN(value * 1) && 
+                        value != 0
+                    ){
+                        value = new Date(value * 24 * 60 * 60 * 1000 + new Date('1899-12-30').getTime()).format('d-M-Y');
+                    }
+                    
+                } catch(e) {
+                    
+                }
+                
+                if(g.valueFormat == 'image') {
+                
+                    out+=String.format('<td colspan="{0}" rowspan="{1}"  class="{2}"><div style="{3}"><img src="data:image/{4};base64, {5}" width="{6}" height="{7}"></div></td>', 
+                        g.colspan, g.rowspan, g.cls.join(' '),
+                        'overflow:hidden;' + 
+                        'width:'+g.width+'px;' +
+
+                        'text-overflow:ellipsis;' +
+                        'white-space:nowrap;',
+                         g.imageType,
+                         value, g.width, g.height
+
+                    );
+                    c+=(g.colspan-1);
+                    continue;
+                }
+                
                 out+=String.format('<td colspan="{0}" rowspan="{1}"  class="{4}"><div style="{3}">{2}</div></td>', 
-                    g.colspan, g.rowspan, g.value,
+                    g.colspan, g.rowspan, value,
                     'overflow:hidden;' + 
                     'width:'+w+'px;' +
                    
@@ -1176,26 +1711,33 @@ Roo.extend(Pman.Gnumeric, Roo.util.Observable, {
     {
         name = name || "Missing_download_filename";
         
-        if (this.downloadURL && this.downloadURL.charAt(this.downloadURL .length-1) != '/') {
+        if (this.downloadURL && this.downloadURL.charAt(this.downloadURL.length-1) != '/') {
             this.downloadURL += '/';
         }
         
         var ser = new XMLSerializer();
+       Roo.get(document.body).mask("Downloading");
         var x = new Pman.Download({
             method: 'POST',
+            timeout : 120000, // quite a long wait.. 2 minutes.
             params : {
                xml : ser.serializeToString(this.doc),
-               format : 'xls', //xml
+               format : this.format,
                debug : 0
                
             },
             url : (this.downloadURL || (baseURL + '/GnumericToExcel/')) + name + '.xls',
             success : function() {
+               Roo.get(document.body).unmask();
                 Roo.MessageBox.alert("Alert", "File should have downloaded now");
                 if (callback) {
                     callback();
                 }
-            }
+            },
+           failure : function() {
+               Roo.get(document.body).unmask();
+               Roo.MessageBox.alert("Alert", "Download failed");
+           }
         });
          
     }