[Libreoffice-commits] mso-dumper.git: msodumper/xlsrecord.py

Kohei Yoshida kohei.yoshida at gmail.com
Fri Jul 11 17:53:54 PDT 2014


 msodumper/xlsrecord.py |   95 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 95 insertions(+)

New commits:
commit 15cd2bd8ff914a764bf0c6b5f0d39da5b58b2b03
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Fri Jul 11 20:53:21 2014 -0400

    Handle boolean, error, string, and formula values in cell change record.
    
    Still for change tracking.

diff --git a/msodumper/xlsrecord.py b/msodumper/xlsrecord.py
index 181a2a8..81c42f1 100644
--- a/msodumper/xlsrecord.py
+++ b/msodumper/xlsrecord.py
@@ -15,6 +15,46 @@ class RecordError(Exception): pass
 # -------------------------------------------------------------------
 # record handler classes
 
+class Bes(object):
+    """Boolean or error value"""
+
+    ErrorValues = {
+        0x00: "#NULL!",
+        0x07: "#DIV/0!",
+        0x0F: "#VALUE!",
+        0x17: "#REF!",
+        0x1D: "#NAME?",
+        0x24: "#NUM!",
+        0x2A: "#N/A",
+        0x2B: "#GETTING_DATA"
+    }
+
+    def __init__ (self, strm):
+        self.bBoolErr = strm.readUnsignedInt(1)
+        self.fError = strm.readUnsignedInt(1) != 0
+
+    def toString (self):
+        if self.fError:
+            return "(error:%s)"%globals.getValueOrUnknown(Bes.ErrorValues,self.bBoolErr,"???")
+        elif self.bBoolErr:
+            return "(boolean:true)"
+        else:
+            return "(boolean:false)"
+
+
+class CellParsedFormula(object):
+
+    def __init__ (self, strm):
+        cce = strm.readUnsignedInt(2)
+        bytes = strm.readBytes(cce)
+        parser = formula.FormulaParser(strm.header, bytes)
+        parser.parse()
+        self.text = parser.getText()
+
+    def toString (self):
+        return self.text
+
+
 class ColRelU(object):
 
     def __init__ (self, strm):
@@ -417,6 +457,37 @@ Like parseBytes(), the derived classes must overwrite this method."""
     def readXLUnicodeStringNoCch (self, cch):
         return self.readUnicodeString(cch)
 
+    def readXLUnicodeRichExtendedString (self):
+        cch = self.readUnsignedInt(2)
+        flags = self.readUnsignedInt(1)
+        fHighByte = (flags & 0x01) != 0  # double byte string
+        fExtSt    = (flags & 0x04) != 0  # phonetic string data
+        fRichSt   = (flags & 0x08) != 0  # rich text
+
+        cRun = 0
+        if fRichSt:
+            cRun = self.readUnsignedInt(2) # number of elemetns in rgRun
+
+        cbExtRst = 0
+        if fExtSt:
+            cbExtRst = self.readSignedInt(4) # byte count of ExtRst
+
+        if fHighByte:
+            rgb = unicode(self.readBytes(2*cch), 'UTF-16LE', errors='replace')
+        elif globals.params.utf8:
+            # Compressed Unicode-> latin1
+            rgb = self.readBytes(cch).decode('cp1252')
+        else:
+            # Old behaviour with hex dump
+            rgb = self.readBytes(cch)
+
+        # optional FormatRun array.  Ignore this for now.
+        self.readBytes(cRun*4) # Each FormatRun is 4-byte long.
+
+        # optional ExtRst.  Ignore this for now.
+        self.readBytes(cbExtRst)
+        return rgb
+
     def readLongRGB (self):
         r = self.readUnsignedInt(1)
         g = self.readUnsignedInt(1)
@@ -4164,6 +4235,12 @@ class RRDChgCell(BaseRecordHandler):
             self.rkOld = decodeRK(self.readUnsignedInt(4))
         elif self.vtOld == RRDChgCell.CellType.Xnum:
             self.numOld = self.readDouble()
+        elif self.vtOld == RRDChgCell.CellType.XLUnicodeRichExtendedString:
+            self.stOld = self.readXLUnicodeRichExtendedString()
+        elif self.vtOld == RRDChgCell.CellType.Bes:
+            self.besOld = Bes(self)
+        elif self.vtOld == RRDChgCell.CellType.CellParsedFormula:
+            self.xpeOld = CellParsedFormula(self)
         else:
             # TODO : Handle other value types.
             return
@@ -4174,6 +4251,12 @@ class RRDChgCell(BaseRecordHandler):
             self.rk = decodeRK(self.readUnsignedInt(4))
         elif self.vt == RRDChgCell.CellType.Xnum:
             self.num = self.readDouble()
+        elif self.vt == RRDChgCell.CellType.XLUnicodeRichExtendedString:
+            self.st = self.readXLUnicodeRichExtendedString()
+        elif self.vt == RRDChgCell.CellType.Bes:
+            self.bes = Bes(self)
+        elif self.vt == RRDChgCell.CellType.CellParsedFormula:
+            self.xpe = CellParsedFormula(self)
         else:
             # TODO : Handle other value types.
             return
@@ -4208,6 +4291,12 @@ class RRDChgCell(BaseRecordHandler):
             self.appendLine("old value: %g"%self.rkOld)
         elif self.vtOld == RRDChgCell.CellType.Xnum:
             self.appendLine("old value: %g"%self.numOld)
+        elif self.vtOld == RRDChgCell.CellType.XLUnicodeRichExtendedString:
+            self.appendLineString("old value", self.stOld)
+        elif self.vtOld == RRDChgCell.CellType.Bes:
+            self.appendLineString("old value", self.besOld.toString())
+        elif self.vtOld == RRDChgCell.CellType.CellParsedFormula:
+            self.appendLineString("old value", self.xpeOld.toString())
         else:
             return
 
@@ -4217,6 +4306,12 @@ class RRDChgCell(BaseRecordHandler):
             self.appendLine("new value: %g"%self.rk)
         elif self.vt == RRDChgCell.CellType.Xnum:
             self.appendLine("new value: %g"%self.num)
+        elif self.vt == RRDChgCell.CellType.XLUnicodeRichExtendedString:
+            self.appendLineString("new value", self.st)
+        elif self.vt == RRDChgCell.CellType.Bes:
+            self.appendLineString("new value", self.bes.toString())
+        elif self.vt == RRDChgCell.CellType.CellParsedFormula:
+            self.appendLineString("new value", self.xpe.toString())
         else:
             return
 


More information about the Libreoffice-commits mailing list