ooo-build r11433 - in trunk: . scratch/sc-xlsutil scratch/sc-xlsutil/src
- From: kyoshida svn gnome org
- To: svn-commits-list gnome org
- Subject: ooo-build r11433 - in trunk: . scratch/sc-xlsutil scratch/sc-xlsutil/src
- Date: Tue, 29 Jan 2008 01:10:27 +0000 (GMT)
Author: kyoshida
Date: Tue Jan 29 01:10:26 2008
New Revision: 11433
URL: http://svn.gnome.org/viewvc/ooo-build?rev=11433&view=rev
Log:
2008-01-28 Kohei Yoshida <kyoshida novell com>
* scratch/sc-xlsutil/src/formula.py:
* scratch/sc-xlsutil/src/globals.py:
* scratch/sc-xlsutil/src/record.py:
* scratch/sc-xlsutil/src/stream.py:
* scratch/sc-xlsutil/xls_dump.py: more work on handling external
reference related records.
Modified:
trunk/ChangeLog
trunk/scratch/sc-xlsutil/src/formula.py
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
Modified: trunk/scratch/sc-xlsutil/src/formula.py
==============================================================================
--- trunk/scratch/sc-xlsutil/src/formula.py (original)
+++ trunk/scratch/sc-xlsutil/src/formula.py Tue Jan 29 01:10:26 2008
@@ -1,6 +1,77 @@
+import struct, sys
import globals
+class InvalidCellAddress(Exception): pass
+
+def toColName (colID):
+ if colID > 255:
+ raise InvalidCellAddress
+ n1 = colID % 26
+ n2 = int(colID/26)
+ name = struct.pack('b', n1 + ord('A'))
+ if n2 > 0:
+ name += struct.pack('b', n2 + ord('A'))
+ return name
+
+class CellAddress(object):
+ def __init__ (self, col=0, row=0, colRel=False, rowRel=False):
+ self.col = col
+ self.row = row
+ self.isColRelative = colRel
+ self.isRowRelative = rowRel
+
+ def getName (self):
+ colName = toColName(self.col)
+ rowName = "%d"%(self.row+1)
+ if not self.isColRelative:
+ colName = '$' + colName
+ if not self.isRowRelative:
+ rowName = '$' + rowName
+ return colName + rowName
+
+class CellRange(object):
+ def __init__ (self):
+ self.firstRow = 0
+ self.lastRow = 0
+ self.firstCol = 0
+ self.lastCol = 0
+ self.isFirstRowRelative = False
+ self.isLastRowRelative = False
+ self.isFirstColRelative = False
+ self.isLastColRelative = False
+
+def parseCellAddress (bytes):
+ if len(bytes) != 4:
+ raise InvalidCellAddress
+
+ row = globals.getSignedInt(bytes[0:2])
+ col = globals.getSignedInt(bytes[2:4])
+ colRelative = ((col & 0x4000) != 0)
+ rowRelative = ((col & 0x8000) != 0)
+ col = (col & 0x00FF)
+ obj = CellAddress(col, row)
+ return obj
+
+def parseCellRangeAddress (bytes):
+ if len(bytes) != 8:
+ raise InvalidCellAddress
+
+ obj = CellRange()
+ obj.firstRow = globals.getSignedInt(bytes[0:2])
+ obj.lastRow = globals.getSignedInt(bytes[2:4])
+ obj.firstCol = globals.getSignedInt(bytes[4:6])
+ obj.lastCol = globals.getSignedInt(bytes[6:8])
+
+ obj.isFirstColRelative = ((firstCol & 0x4000) != 0)
+ obj.isFirstRowRelative = ((firstCol & 0x8000) != 0)
+ obj.firstCol = (firstCol & 0x00FF)
+
+ obj.isLastColRelative = ((lastCol & 0x4000) != 0)
+ obj.isLastRowRelative = ((lastCol & 0x8000) != 0)
+ obj.lastCol = (lastCol & 0x00FF)
+ return obj
+
class TokenBase(object):
"""base class for token handler
@@ -55,8 +126,23 @@
return i
def getText (self):
- return "<externname externsheet ID: %d; name ID: %d>"%(self.refID, self.nameID)
+ return "<externname externSheetID='%d' nameID='%d'>"%(self.refID, self.nameID)
+
+
+class Ref3d(TokenBase):
+ """3D reference or external reference to a cell"""
+
+ def parse (self, i):
+ i += 1
+ self.refEntryId = globals.getSignedInt(self.tokens[i:i+2])
+ i += 2
+ self.cell = parseCellAddress(self.tokens[i:i+4])
+ i += 4
+ return i
+ def getText (self):
+ cellName = self.cell.getName()
+ return "<3dref externSheetID='%d' cellAddress='%s'>"%(self.refEntryId, cellName)
tokenMap = {
# binary operator
@@ -86,6 +172,11 @@
0x59: NameX,
0x79: NameX,
+ # 3d reference
+ 0x3A: Ref3d,
+ 0x5A: Ref3d,
+ 0x7A: Ref3d,
+
# last item
0xFF: None
}
@@ -97,17 +188,21 @@
the constructor. That series of bytes must also include the formula length
which is usually the first 2 bytes.
"""
- def __init__ (self, tokens):
+ def __init__ (self, tokens, sizeField=True):
self.tokens = tokens
self.text = ''
+ self.sizeField = sizeField
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
+ length = len(ftokens)
+ if self.sizeField:
+ # 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]
- ftokens = self.tokens[2:2+length]
i = 0
while i < length:
tk = ftokens[i]
Modified: trunk/scratch/sc-xlsutil/src/globals.py
==============================================================================
--- trunk/scratch/sc-xlsutil/src/globals.py (original)
+++ trunk/scratch/sc-xlsutil/src/globals.py Tue Jan 29 01:10:26 2008
@@ -9,6 +9,53 @@
def error (msg):
sys.stderr.write(msg)
+
+def decodeName (name):
+ """decode name that contains unprintable characters."""
+
+ if len(name) == 0:
+ return name
+
+ if ord(name[0]) <= 5:
+ name = "<%2.2Xh>"%ord(name[0]) + name[1:]
+
+ return name
+
+
+def getRichText (bytes, textLen=None):
+ """parse a string of the rich-text format that Excel uses."""
+
+ flags = bytes[0]
+ if type(flags) == type('c'):
+ flags = ord(flags)
+ is16Bit = (flags & 0x01)
+ isFarEast = (flags & 0x04)
+ isRich = (flags & 0x08)
+
+ i = 1
+ formatRuns = 0
+ if isRich:
+ formatRuns = getSignedInt(bytes[i:i+2])
+ i += 2
+
+ extInfo = 0
+ if isFarEast:
+ extInfo = getSignedInt(bytes[i:i+4])
+ i += 4
+
+ extraBytes = 0
+ if textLen == None:
+ extraBytes = formatRuns*4 + extInfo
+ textLen = len(bytes) - extraBytes - i
+
+ totalByteLen = i + textLen + extraBytes
+ if is16Bit:
+ return ("<16-bit strings not supported yet>", totalByteLen)
+
+ text = toTextBytes(bytes[i:i+textLen])
+ return (text, totalByteLen)
+
+
def dumpBytes (chars, subDivide=None):
line = 0
subDivideLine = None
@@ -50,6 +97,10 @@
return text
+def getTextBytes (bytes):
+ return toTextBytes(bytes)
+
+
def toTextBytes (bytes):
n = len(bytes)
text = ''
Modified: trunk/scratch/sc-xlsutil/src/record.py
==============================================================================
--- trunk/scratch/sc-xlsutil/src/record.py (original)
+++ trunk/scratch/sc-xlsutil/src/record.py Tue Jan 29 01:10:26 2008
@@ -165,6 +165,192 @@
self.appendLine("row height type: custom")
+
+class Name(BaseRecordHandler):
+ """internal defined name"""
+
+ def __getInt (self, offset, size):
+ return globals.getSignedInt(self.bytes[offset:offset+size])
+
+ def __parseOptionFlags (self, flags):
+ self.appendLine("option flags:")
+ isHidden = (flags & 0x0001) != 0
+ isFuncMacro = (flags & 0x0002) != 0
+ isVBMacro = (flags & 0x0004) != 0
+ isMacroName = (flags & 0x0008) != 0
+ isComplFormula = (flags & 0x0010) != 0
+ isBuiltinName = (flags & 0x0020) != 0
+ funcGrp = (flags & 0x0FC0) / 64
+ isBinary = (flags & 0x1000) != 0
+
+ if isHidden:
+ self.appendLine(" hidden")
+ else:
+ self.appendLine(" visible")
+
+ if isMacroName:
+ self.appendLine(" macro name")
+ if isFuncMacro:
+ self.appendLine(" function macro")
+ self.appendLine(" function group: %d"%funcGrp)
+ else:
+ self.appendLine(" command macro")
+ if isVBMacro:
+ self.appendLine(" visual basic macro")
+ else:
+ self.appendLine(" sheet macro")
+ else:
+ self.appendLine(" standard name")
+
+ if isComplFormula:
+ self.appendLine(" complex formula")
+ else:
+ self.appendLine(" simple formula")
+ if isBuiltinName:
+ self.appendLine(" built-in name")
+ else:
+ self.appendLine(" user-defined name")
+ if isBinary:
+ self.appendLine(" binary data")
+ else:
+ self.appendLine(" formula definition")
+
+
+ def parseBytes (self):
+ optionFlags = self.__getInt(0, 2)
+
+ keyShortCut = self.__getInt(2, 1)
+ nameLen = self.__getInt(3, 1)
+ formulaLen = self.__getInt(4, 2)
+ sheetId = self.__getInt(8, 2)
+
+ # these optional texts may come after the formula token bytes.
+ menuTextLen = self.__getInt(10, 1)
+ descTextLen = self.__getInt(11, 1)
+ helpTextLen = self.__getInt(12, 1)
+ statTextLen = self.__getInt(13, 1)
+
+ name, byteLen = globals.getRichText(self.bytes[14:], nameLen)
+ tokenPos = 14 + byteLen
+ tokenText = globals.getRawBytes(self.bytes[tokenPos:tokenPos+formulaLen], True, False)
+ o = formula.FormulaParser(self.bytes[tokenPos:tokenPos+formulaLen], False)
+ o.parse()
+ self.appendLine("name: %s"%name)
+ self.__parseOptionFlags(optionFlags)
+
+ self.appendLine("sheet ID: %d"%sheetId)
+ self.appendLine("menu text length: %d"%menuTextLen)
+ self.appendLine("description length: %d"%descTextLen)
+ self.appendLine("help tip text length: %d"%helpTextLen)
+ self.appendLine("status bar text length: %d"%statTextLen)
+ self.appendLine("formula length: %d"%formulaLen)
+ self.appendLine("formula bytes: " + tokenText)
+ self.appendLine("formula: " + o.getText())
+
+
+
+class SupBook(BaseRecordHandler):
+ """Supporting workbook"""
+
+ def __parseSpecial (self):
+ if self.bytes[2:4] == [0x01, 0x04]:
+ # internal reference
+ num = globals.getSignedInt(self.bytes[0:2])
+ self.appendLine("sheet name count: %d (internal reference)"%num)
+ elif self.bytes[0:4] == [0x00, 0x01, 0x01, 0x3A]:
+ # add-in function
+ self.appendLine("add-in function name stored in the following EXERNNAME record.")
+
+ def __parseDDE (self):
+ # not implemented yet.
+ pass
+
+ def parseBytes (self):
+ if self.size == 4:
+ self.__parseSpecial()
+ return
+
+ if self.bytes[0:2] == [0x00, 0x00]:
+ self.__parseDDE()
+ return
+
+ num = globals.getSignedInt(self.bytes[0:2])
+ self.appendLine("sheet name count: %d"%num)
+ i = 2
+ isFirst = True
+ while i < self.size:
+ nameLen = globals.getSignedInt(self.bytes[i:i+2])
+ i += 2
+ flags = globals.getSignedInt(self.bytes[i:i+1])
+ i += 1
+ name = globals.getTextBytes(self.bytes[i:i+nameLen])
+ name = globals.decodeName(name)
+ i += nameLen
+ if isFirst:
+ isFirst = False
+ self.appendLine("document URL: %s"%name)
+ else:
+ self.appendLine("sheet name: %s"%name)
+
+
+class ExternSheet(BaseRecordHandler):
+
+ def parseBytes (self):
+ num = globals.getSignedInt(self.bytes[0:2])
+ for i in xrange(0, num):
+ offset = 2 + i*6
+ book = globals.getSignedInt(self.bytes[offset:offset+2])
+ firstSheet = globals.getSignedInt(self.bytes[offset+2:offset+4])
+ lastSheet = globals.getSignedInt(self.bytes[offset+4:offset+6])
+ self.appendLine("SUPBOOK record ID: %d (sheet ID range: %d - %d)"%(book, firstSheet, lastSheet))
+
+
+class ExternName(BaseRecordHandler):
+
+ def __parseOptionFlags (self, flags):
+ self.isBuiltinName = (flags & 0x0001) != 0
+ self.isAutoDDE = (flags & 0x0002) != 0
+ self.isStdDocName = (flags & 0x0008) != 0
+ self.isOLE = (flags & 0x0010) != 0
+ # 5 - 14 bits stores last successful clip format
+ self.lastClipFormat = (flags & 0x7FE0)
+
+ def parseBytes (self):
+ # first 2 bytes are option flags for external name.
+ optionFlags = globals.getSignedInt(self.bytes[0:2])
+ self.__parseOptionFlags(optionFlags)
+
+ if self.isOLE:
+ # next 4 bytes are 32-bit storage ID
+ storageID = globals.getSignedInt(self.bytes[2:6])
+ nameLen = globals.getSignedInt(self.bytes[6:7])
+ name, byteLen = globals.getRichText(self.bytes[7:], nameLen)
+ self.appendLine("type: OLE")
+ self.appendLine("storage ID: %d"%storageID)
+ self.appendLine("name: %s"%name)
+ else:
+ # assume external defined name (could be DDE link).
+ # TODO: differentiate DDE link from external defined name.
+
+ supbookID = globals.getSignedInt(self.bytes[2:4])
+ nameLen = globals.getSignedInt(self.bytes[6:7])
+ name, byteLen = globals.getRichText(self.bytes[7:], nameLen)
+ tokenText = globals.getRawBytes(self.bytes[7+byteLen:], True, False)
+ self.appendLine("type: defined name")
+ if supbookID == 0:
+ self.appendLine("sheet ID: 0 (global defined names)")
+ else:
+ self.appendLine("sheet ID: %d"%supbookID)
+ self.appendLine("name: %s"%name)
+ self.appendLine("formula bytes: %s"%tokenText)
+
+ # parse formula tokens
+ o = formula.FormulaParser(self.bytes[7+byteLen:])
+ o.parse()
+ ftext = o.getText()
+ self.appendLine("formula: %s"%ftext)
+
+
# -------------------------------------------------------------------
# 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 Tue Jan 29 01:10:26 2008
@@ -21,13 +21,15 @@
0x0014: ["HEADER", "Print Header on Each Page"],
0x0015: ["FOOTER", "Print Footer on Each Page"],
0x0016: ["EXTERNCOUNT", "Number of External References"],
- 0x0017: ["EXTERNSHEET", "External Reference"],
+ 0x0017: ["EXTERNSHEET", "External Reference", record.ExternSheet],
+ 0x0018: ["NAME", "Internal Defined Name", record.Name],
0x0019: ["WINDOWPROTECT", "Windows Are Protected"],
0x001A: ["VERTICALPAGEBREAKS", "Explicit Column Page Breaks"],
0x001B: ["HORIZONTALPAGEBREAKS", "Explicit Row Page Breaks"],
0x001C: ["NOTE", "Comment Associated with a Cell"],
0x001D: ["SELECTION", "Current Selection"],
0x0022: ["DATEMODE", "Base Date for Displaying Date Values"],
+ 0x0023: ["EXTERNNAME", "Externally Defined Name", record.ExternName],
0x0026: ["LEFTMARGIN", "Left Margin Measurement"],
0x0027: ["RIGHTMARGIN", "Right Margin Measurement"],
0x0028: ["TOPMARGIN", "Top Margin Measurement"],
@@ -147,7 +149,7 @@
0x01AA: ["USERSVIEWBEGIN", "Custom View Settings"],
0x01AB: ["USERSVIEWEND", "End of Custom View Records"],
0x01AD: ["QSI", "External Data Range"],
- 0x01AE: ["SUPBOOK", "Supporting Workbook"],
+ 0x01AE: ["SUPBOOK", "Supporting Workbook", record.SupBook],
0x01AF: ["PROT4REV", "Shared Workbook Protection Flag"],
0x01B0: ["CONDFMT", "Conditional Formatting Range Information"],
0x01B1: ["CF", "Conditional Formatting Conditions"],
Modified: trunk/scratch/sc-xlsutil/xls_dump.py
==============================================================================
--- trunk/scratch/sc-xlsutil/xls_dump.py (original)
+++ trunk/scratch/sc-xlsutil/xls_dump.py Tue Jan 29 01:10:26 2008
@@ -22,8 +22,7 @@
self.filepath = filepath
def __printDirHeader (self, dirname, byteLen):
- if ord(dirname[0]) <= 5:
- dirname = "<%2.2Xh>%s"%(ord(dirname[0]), dirname[1:])
+ dirname = globals.decodeName(dirname)
print("")
print("="*68)
print("%s (size: %d bytes)"%(dirname, byteLen))
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]