ooo-build r11419 - in trunk: . scratch/sc-xlsutil scratch/sc-xlsutil/src
- From: kyoshida svn gnome org
- To: svn-commits-list gnome org
- Subject: ooo-build r11419 - in trunk: . scratch/sc-xlsutil scratch/sc-xlsutil/src
- Date: Sat, 26 Jan 2008 07:31:04 +0000 (GMT)
Author: kyoshida
Date: Sat Jan 26 07:31:04 2008
New Revision: 11419
URL: http://svn.gnome.org/viewvc/ooo-build?rev=11419&view=rev
Log:
2008-01-26 Kohei Yoshida <kyoshida novell com>
* scratch/sc-xlsutil/src/formula.py: added formula parser.
* scratch/sc-xlsutil/src/globals.py: a little cleanup.
* scratch/sc-xlsutil/src/record.py:
* scratch/sc-xlsutil/src/stream.py: added FORMULA record handler.
* scratch/sc-xlsutil/xls_dump.py: added rudimentary usage output and
command line option framework.
Added:
trunk/scratch/sc-xlsutil/src/formula.py
Modified:
trunk/ChangeLog
trunk/scratch/sc-xlsutil/src/globals.py
trunk/scratch/sc-xlsutil/src/record.py
trunk/scratch/sc-xlsutil/src/stream.py
trunk/scratch/sc-xlsutil/xls_dump.py
Added: trunk/scratch/sc-xlsutil/src/formula.py
==============================================================================
--- (empty file)
+++ trunk/scratch/sc-xlsutil/src/formula.py Sat Jan 26 07:31:04 2008
@@ -0,0 +1,112 @@
+
+import globals
+
+
+class TokenBase(object):
+ def __init__ (self, tokens):
+ self.tokens = tokens
+
+ def parse (self, i):
+ return i
+
+ def getText (self):
+ return ''
+
+class Add(TokenBase): pass
+class Sub(TokenBase): pass
+class Mul(TokenBase): pass
+class Div(TokenBase): pass
+class Power(TokenBase): pass
+class Concat(TokenBase): pass
+class LT(TokenBase): pass
+class LE(TokenBase): pass
+class EQ(TokenBase): pass
+class GE(TokenBase): pass
+class GT(TokenBase): pass
+class NE(TokenBase): pass
+class Isect(TokenBase): pass
+class List(TokenBase): pass
+class Range(TokenBase): pass
+
+class Plus(TokenBase): pass
+class Minus(TokenBase): pass
+class Percent(TokenBase): pass
+
+class NameX(TokenBase):
+ """external name"""
+
+ def parse (self, i):
+ i += 1
+ self.refID = globals.getSignedInt(self.tokens[i:i+2])
+ i += 2
+ self.nameID = globals.getSignedInt(self.tokens[i:i+2])
+ i += 2
+ return i
+
+ def getText (self):
+ return "<externname externsheet ID: %d; name ID: %d>"%(self.refID, self.nameID)
+
+
+tokenMap = {
+ # binary operator
+ 0x03: Add,
+ 0x04: Sub,
+ 0x05: Mul,
+ 0x06: Div,
+ 0x07: Power,
+ 0x08: Concat,
+ 0x09: LT,
+ 0x0A: LE,
+ 0x0B: EQ,
+ 0x0C: GE,
+ 0x0D: GT,
+ 0x0E: NE,
+ 0x0F: Isect,
+ 0x10: List,
+ 0x11: Range,
+
+ # unary operator
+ 0x12: Plus,
+ 0x13: Minus,
+ 0x14: Percent,
+
+ # operand tokens
+ 0x39: NameX,
+ 0x59: NameX,
+ 0x79: NameX,
+
+ # last item
+ 0xFF: None
+}
+
+class FormulaParser(object):
+ def __init__ (self, tokens):
+ self.tokens = tokens
+ self.text = ''
+
+ def parse (self):
+ # first 2-bytes contain the length of the formula tokens
+ length = globals.getSignedInt(self.tokens[0:2])
+ if length <= 0:
+ return
+
+ ftokens = self.tokens[2:2+length]
+ i = 0
+ while i < length:
+ tk = ftokens[i]
+ if type(tk) == type('c'):
+ # get the ordinal of the character.
+ tk = ord(tk)
+ if not tokenMap.has_key(tk):
+ i += 1
+ continue
+
+ o = tokenMap[tk](ftokens)
+ i = o.parse(i)
+ self.text += o.getText() + ' '
+
+ i += 1
+
+
+ def getText (self):
+ return self.text
Modified: trunk/scratch/sc-xlsutil/src/globals.py
==============================================================================
--- trunk/scratch/sc-xlsutil/src/globals.py (original)
+++ trunk/scratch/sc-xlsutil/src/globals.py Sat Jan 26 07:31:04 2008
@@ -6,6 +6,8 @@
def output (msg):
sys.stdout.write(msg)
+def error (msg):
+ sys.stderr.write(msg)
def dumpBytes (chars, subDivide=None):
line = 0
@@ -28,14 +30,7 @@
return 512 + secID*secSize
-def char2byte (chars):
- bytes = []
- for c in chars:
- bytes.append(ord(c))
- return bytes
-
-
-def getRawBytes (bytes, spaced=True):
+def getRawBytes (bytes, spaced=True, reverse=True):
text = ''
for b in bytes:
if type(b) == type(''):
@@ -43,25 +38,36 @@
if len(text) == 0:
text = "%2.2X"%b
elif spaced:
- text = "%2.2X "%b + text
+ if reverse:
+ text = "%2.2X "%b + text
+ else:
+ text += " %2.2X"%b
else:
- text = "%2.2X"%b + text
+ if reverse:
+ text = "%2.2X"%b + text
+ else:
+ text += "%2.2X"%b
return text
-def getSignedInt (bytes):
- # little endian
+def toTextBytes (bytes):
n = len(bytes)
- if n == 0:
- return 0
-
text = ''
for i in xrange(0, n):
b = bytes[i]
if type(b) == type(0x00):
b = struct.pack('B', b)
text += b
+ return text
+
+
+def getSignedInt (bytes):
+ # little endian
+ n = len(bytes)
+ if n == 0:
+ return 0
+ text = toTextBytes(bytes)
if n == 1:
# byte - 1 byte
return struct.unpack('b', text)[0]
@@ -79,12 +85,8 @@
n = len(bytes)
if n == 0:
return 0.0
- text = ''
- for i in xrange(0, n):
- b = bytes[i]
- if type(b) == type(0x00):
- b = struct.pack('B', b)
- text += b
+
+ text = toTextBytes(bytes)
return struct.unpack('d', text)[0]
Modified: trunk/scratch/sc-xlsutil/src/record.py
==============================================================================
--- trunk/scratch/sc-xlsutil/src/record.py (original)
+++ trunk/scratch/sc-xlsutil/src/record.py Sat Jan 26 07:31:04 2008
@@ -1,5 +1,5 @@
-import globals
+import globals, formula
# -------------------------------------------------------------------
# record handler classes
@@ -13,6 +13,12 @@
self.lines = []
def parseBytes (self):
+ """Parse the original bytes and generate human readable output.
+
+The derived class should only worry about overwriting this function. The
+bytes are given as self.bytes, and call self.appendLine([new line]) to
+append a line to be displayed.
+"""
pass
def output (self):
@@ -53,6 +59,33 @@
self.appendLine("lowest Excel version: %d"%lowestExcelVer)
+class Formula(BaseRecordHandler):
+
+ def parseBytes (self):
+ row = globals.getSignedInt(self.bytes[0:2])
+ col = globals.getSignedInt(self.bytes[2:4])
+ xf = globals.getSignedInt(self.bytes[4:6])
+ fval = globals.getDouble(self.bytes[6:14])
+
+ flags = globals.getSignedInt(self.bytes[14:16])
+ recalc = (flags & 0x0001) != 0
+ calcOnOpen = (flags & 0x0002) != 0
+ sharedFormula = (flags & 0x0008) != 0
+
+ tokens = self.bytes[20:]
+ fparser = formula.FormulaParser(tokens)
+ fparser.parse()
+ ftext = fparser.getText()
+
+ self.appendLine("cell position: (col: %d; row: %d)"%(col, row))
+ self.appendLine("XF record ID: %d"%xf)
+ self.appendLine("formula result: %g"%fval)
+ self.appendLine("recalculate always: %d"%recalc)
+ self.appendLine("calculate on open: %d"%calcOnOpen)
+ self.appendLine("shared formula: %d"%sharedFormula)
+ self.appendLine("tokens: "+ftext)
+
+
class Number(BaseRecordHandler):
def parseBytes (self):
@@ -62,7 +95,7 @@
fval = globals.getDouble(self.bytes[6:14])
self.appendLine("cell position: (col: %d; row: %d)"%(col, row))
self.appendLine("XF record ID: %d"%xf)
- self.appendLine("value (IEEE 754): %g"%fval)
+ self.appendLine("value: %g"%fval)
# -------------------------------------------------------------------
# CT - Change Tracking
Modified: trunk/scratch/sc-xlsutil/src/stream.py
==============================================================================
--- trunk/scratch/sc-xlsutil/src/stream.py (original)
+++ trunk/scratch/sc-xlsutil/src/stream.py Sat Jan 26 07:31:04 2008
@@ -8,7 +8,7 @@
# opcode: [canonical name, description, handler (optional)]
recData = {
- 0x0006: ["FORMULA", "Formula Token Array and Result"],
+ 0x0006: ["FORMULA", "Formula Token Array and Result", record.Formula],
0x000A: ["EOF", "End of File"],
0x000C: ["CALCCOUNT", "Iteration Count"],
0x000D: ["CALCMODE", "Calculation Mode"],
@@ -176,7 +176,6 @@
0x0236: ["TABLE", "Data Table"],
0x023E: ["WINDOW2", "Sheet Window Information"],
0x0293: ["STYLE", "Style Information"],
- 0x0406: ["FORMULA", "Cell Formula"],
0x041E: ["FORMAT", "Number Format"],
0x0809: ["BOF", "Beginning of File", record.BOF],
0x0862: ["SHEETLAYOUT", "Tab Color below Sheet Name"],
Modified: trunk/scratch/sc-xlsutil/xls_dump.py
==============================================================================
--- trunk/scratch/sc-xlsutil/xls_dump.py (original)
+++ trunk/scratch/sc-xlsutil/xls_dump.py Sat Jan 26 07:31:04 2008
@@ -1,9 +1,21 @@
#!/usr/bin/env python
-import sys, os.path
+import sys, os.path, getopt
sys.path.append(sys.path[0]+"/src")
import ole, stream, globals
+from globals import error
+
+def usage (exname):
+ exname = os.path.basename(exname)
+ msg = """Usage: %s [options] [xls file]
+
+Options:
+ --help displays this help message.
+"""%exname
+ print msg
+
+
class XLDumper(object):
def __init__ (self, filepath):
@@ -62,17 +74,31 @@
except stream.EndOfStream:
return False
-def usage ():
- pass
def main (args):
+ exname, args = args[0], args[1:]
if len(args) < 1:
print("takes at least one argument")
- usage()
+ usage(exname)
+ return
+
+ try:
+ opts, args = getopt.getopt(args, "h", ["help"])
+ for opt, arg in opts:
+ if opt in ['-h', '--help']:
+ usage(exname)
+ return
+ else:
+ error("unknown option %s\n"%opt)
+ usage()
+
+ except getopt.GetoptError:
+ error("error parsing input options\n")
+ usage(exname)
return
dumper = XLDumper(args[0])
dumper.dump()
if __name__ == '__main__':
- main(sys.argv[1:])
+ main(sys.argv)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]