OLEWriterBig.py :  » XML » pyXLWriter » pyXLWriter-0.4a3 » pyXLWriter » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » XML » pyXLWriter 
pyXLWriter » pyXLWriter 0.4a3 » pyXLWriter » OLEWriterBig.py
# pyXLWriter: A library for generating Excel Spreadsheets
# Copyright (c) 2004 Evgeny Filatov <fufff@users.sourceforge.net>
# Copyright (c) 2002-2004 John McNamara (Perl Spreadsheet::WriteExcel, ver .42)
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#----------------------------------------------------------------------------
# This module based on PERL OLE::Storage_Lite module.
# The author of the PERL OLE::Storage_Lite module is Kawai Takanori 
# <kwitknr@cpan.org>
#----------------------------------------------------------------------------
# See the README.txt distributed with pyXLWriter for more details.

"""pyXLWriter.OLEWriterBig

"""
__revision__ = """$Id: OLEWriterBig.py,v 1.8 2004/08/20 05:16:16 fufff Exp $"""

from struct import pack


__all__ = ["OLEWriterBig"]


_BIG_BLOCK_SIZE = 0x200
_SMALL_BLOCK_SIZE = 0x40
_PPS_SIZE = 0x80
_SMALL_SIZE = 0x1000
_LONG_INT_SIZE = 4


def _ceil_div(a, b):
    """Return ceil(a/b).
    
    int(a / b) + (a % b)?(1):(0)
    
    """
    return (a-1) // b + 1
    

class _PPS:

    def __init__(self, fh, name="", type=0, dir=0, start=0, size=0):
        self._fh = fh
        self.name = self._asc2ucs(name)
        self.type = type
        self.dir = dir
        self.start_block = start
        self.size = size
        
    def save_pps_wk(self):
        fh = self._fh
        # 1. Write _PPS
        fh.write(self.name)
        fh.write("\x00" * (64 - len(self.name)))    #64
        fh.write(pack("<H", len(self.name) + 2))    #66
        fh.write(pack("<B", self.type))             #67
        fh.write(pack("<B", 0x00))           # UK   #68
        fh.write(pack("<L", 0xFFFFFFFFL))    # Prev #72
        fh.write(pack("<L", 0xFFFFFFFFL))    # Next #76
        fh.write(pack("<L", self.dir))              # Dir  #80
        fh.write("\x00\x09\x02\x00")                #84
        fh.write("\x00\x00\x00\x00")                #88
        fh.write("\xc0\x00\x00\x00")                #92
        fh.write("\x00\x00\x00\x46")                #96
        fh.write("\x00\x00\x00\x00")                #100
        fh.write("\x00" * 8)              # time1st #108
        fh.write("\x00" * 8)              # time2nd #116
        fh.write(pack("<L", self.start_block))      #116
        fh.write(pack("<L", self.size))             #124
        fh.write(pack("<L", 0))                     #128

    def _asc2ucs(self, s):
        """Convert ascii strring to unicode."""
        if s:
            return "\x00".join(s) + "\x00" 
        else:
            return ""


class OLEWriterBig:
    """A writer class to store BIFF data in a OLE compound
    storage file.
    
    """
    
    def __init__(self, olefile=None):
        """Constructor."""
        self._olefile = olefile
        self._booksize = None       # Isn't initialized
        self._fh = None
        self._fh_internal = False
        self._fileclosed = False
        self._initialize()
        self._ppsroot = None
        self._ppsfile = None 
        self._sbdcnt = 0
        self._bbcnt = 0
        self._ppscnt = 0
        self._initialize()
        
    def _initialize(self):
        """Initialize file handle and pps objects."""
        if isinstance(self._olefile, str):
            # Create a new file, open for writing
            self._fh_internal = True
            self._fh = file(self._olefile, "wb")
        else:
            self._fh_internal = False
            self._fh = self._olefile
        self._ppsroot = _PPS(self._fh, "Root Entry", 5, 1)
        self._ppsfile = _PPS(self._fh, "Book", 2, 0xFFFFFFFFL)

    def set_size(self, biffsize):
        self._booksize = biffsize

    def write_header(self):
        # 1. Make an array of _PPS (for Save)
        fh = self._fh
        ppsfile = self._ppsfile
        ppsroot = self._ppsroot
        sbdcnt, bbcnt, ppscnt = self._calc_sizes()
        # 2. Save Header
        self._save_header()
        # 3. Make Small Data string and set it to RootEntry Data
        self._make_small_data() 
        
    def write(self, data):
        self._fh.write(data)

    def _calc_sizes(self):
        size = self._booksize        
        bbcnt = 0
        sbcnt = 0
        self._ppsfile.size = size
        rtsize = 0
        if size < _SMALL_SIZE:
            sbcnt += _ceil_div(size, _SMALL_BLOCK_SIZE)
            ftlen = 0
            if size % _SMALL_BLOCK_SIZE:
                ftlen = (_SMALL_BLOCK_SIZE - (size % _SMALL_BLOCK_SIZE))
            rtsize = size + ftlen 
        else:
            bbcnt += _ceil_div(size, _BIG_BLOCK_SIZE)
        self._ppsroot.size = rtsize
        slcnt = _BIG_BLOCK_SIZE // _LONG_INT_SIZE
        sbdcnt = _ceil_div(sbcnt, slcnt)
        smllen = sbcnt * _SMALL_BLOCK_SIZE        
        bbcnt += _ceil_div(smllen, _BIG_BLOCK_SIZE)
        bdcnt = _BIG_BLOCK_SIZE // _PPS_SIZE
        ppscnt = _ceil_div(2, bdcnt)
        self._sbdcnt, self._bbcnt, self._ppscnt = sbdcnt, bbcnt, ppscnt
        return sbdcnt, bbcnt, ppscnt

    def _write_footer(self):
        self._save_smbg()
        # 5. Write _PPS
        self._save_pps()
        # 6. Write BD and BDList and Adding Header informations
        self._save_bbd()

    def _save_header(self):
        fh = self._fh
        sbdcnt, bbcnt, ppscnt = self._sbdcnt, self._bbcnt, self._ppscnt
        
        # 0. Calculate Basic Setting
        blcnt = _BIG_BLOCK_SIZE // _LONG_INT_SIZE
        fstbdl = (_BIG_BLOCK_SIZE - 0x4C) // _LONG_INT_SIZE
        fstbd_max = fstbdl * blcnt - fstbdl
        bdexl = 0
        all = bbcnt + ppscnt + sbdcnt
        allw = all
        bdcntw = _ceil_div(allw, blcnt)
        bdcnt = 0
        
        # 0.1 Calculate BD count
        blcnt -= 1  #the BlCnt is reduced in the count of the last sect is used for a pointer the next Bl
        bbleftover = all - fstbd_max
        if all > fstbd_max:
            while True:
                bdcnt = _ceil_div(bbleftover, blcnt)
                bdexl = _ceil_div(bdcnt, blcnt)
                bbleftover += bdexl
                if bdcnt == _ceil_div(bbleftover, blcnt):
                    break
        bdcnt += fstbdl
        
        # 1.Save Header
        fh.write("\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1")
        fh.write("\x00\x00\x00\x00" * 4)
        fh.write(pack("<H", 0x3b))
        fh.write(pack("<H", 0x03))
        fh.write(pack("<H", -2))
        fh.write(pack("<H", 9))
        fh.write(pack("<H", 6))
        fh.write(pack("<H", 0))
        fh.write("\x00\x00\x00\x00" * 2)
        fh.write(pack("<L", bdcnt))
        fh.write(pack("<L", bbcnt + sbdcnt))  # ROOT START
        fh.write(pack("<L", 0))
        fh.write(pack("<L", 0x1000))
        fh.write(pack("<L", 0))                 # Small Block Depot
        fh.write(pack("<L", 1))
        
        # 2. Extra BDList Start, Count
        if all < fstbd_max:
            fh.write(pack("<L", -2))        # Extra BDList Start
            fh.write(pack("<L", 0))         # Extra BDList Count
        else:
            fh.write(pack("<L", all+bdcnt))
            fh.write(pack("<L", bdexl))
            
        # 3. BDList
        i = 0
        while i < fstbdl and i < bdcnt:
            fh.write(pack("<L", all+i))
            i += 1
        if i < fstbdl:
            fh.write((pack("<L", -1)) * (fstbdl-i)) 

    def _make_small_data(self):
        fh = self._fh
        pps = self._ppsfile
        size = self._booksize
        # 1. Make SBD, small data string
        if size < _SMALL_SIZE:
            smbcnt = _ceil_div(size, _SMALL_BLOCK_SIZE)
            # 1.1 Add to SBD
            for i in xrange(smbcnt-1):
                fh.write(pack("<L", i+1))
            fh.write(pack("<L", -2))
            smblk = smbcnt
            sbcnt = _BIG_BLOCK_SIZE // _LONG_INT_SIZE
            if smblk % sbcnt:
                fh.write(pack("<L", -1) * (sbcnt - (smblk % sbcnt)))

    def _save_smbg(self):
        fh = self._fh
        size = self._booksize
        # Save small
        if size < _SMALL_SIZE:
            if size % _SMALL_BLOCK_SIZE:
                ftlen = (_SMALL_BLOCK_SIZE - (size % _SMALL_BLOCK_SIZE))
                fh.write("\x00" * ftlen)
            pps = self._ppsroot
        else:
            pps = self._ppsfile
        # Save big ?
        if pps.size % _BIG_BLOCK_SIZE:
            ftlen = _BIG_BLOCK_SIZE - (pps.size % _BIG_BLOCK_SIZE)
            fh.write("\x00" * ftlen) 
            pps.start_block = self._sbdcnt

    def _save_pps(self):
        fh = self._fh
        # 1. Save _PPS
        ppsroot = self._ppsroot
        ppsfile = self._ppsfile
        ppsroot.save_pps_wk()
        ppsfile.save_pps_wk()
        # 2. Adjust for Block
        cnt = 2
        bcnt = _BIG_BLOCK_SIZE // _PPS_SIZE
        if cnt % bcnt:
            count = (bcnt - (cnt % bcnt)) * _PPS_SIZE
            fh.write("\x00" * count)

    def _save_bbd(self):
        fh = self._fh
        sbdsize, bsize, ppscnt = self._sbdcnt, self._bbcnt, self._ppscnt
        
        # 0. Calculate Basic Setting
        bbcnt = _BIG_BLOCK_SIZE // _LONG_INT_SIZE
        blcnt = bbcnt - 1
        fstbdl = (_BIG_BLOCK_SIZE - 0x4C) // _LONG_INT_SIZE
        fstbd_max = fstbdl * bbcnt - fstbdl
        bdexl = 0
        all = bsize + ppscnt + sbdsize
        allw = all
        bdcntw = _ceil_div(allw, bbcnt)
        bdcnt = 0 #_ceil_div(all + bdcntw, ibdcnt)
        
        # 0.1 Calculate BD count
        bbleftover = all - fstbd_max;
        if all > fstbd_max:
            while True:
                bdcnt = _ceil_div(bbleftover, blcnt)
                bdexl = _ceil_div(bdcnt, blcnt)
                bbleftover += bdexl;
                if bdcnt == _ceil_div(bbleftover, blcnt):
                    break
        allw += bdexl
        bdcnt += fstbdl

        # 1. Making BD
        # 1.1 Set for SBD
        if sbdsize > 0:
            for i in xrange(sbdsize-1):
                fh.write(pack("<L", i+1))
            fh.write(pack("<L", -2))
            
        # 1.2 Set for B
        for i in xrange(bsize-1):
            fh.write(pack("<L", i + sbdsize + 1))
        fh.write(pack("<L", -2))
        
        # 1.3 Set for _PPS
        for i in xrange(ppscnt-1):
            fh.write(pack("<L", i + sbdsize + bsize + 1))
        fh.write(pack("<L", -2))
        
        # 1.4 Set for BBD itself ( 0xFFFFFFFD : BBD)
        for i in xrange(bdcnt):
            fh.write(pack("<L", 0xFFFFFFFDL))
            
        # 1.5 Set for ExtraBDList
        for i in xrange(bdexl):
            fh.write(pack("<L", 0xFFFFFFFCL))
            
        # 1.6 Adjust for Block
        if (allw + bdcnt) % bbcnt:
            fh.write(pack("<L", -1) * (bbcnt - ((allw + bdcnt) % bbcnt)))
            
        # 2.Extra BDList
        if bdcnt > fstbdl:
            n = 0
            nb = 0
            i = fstbdl
            while i < bdcnt: 
                if n >= (bbcnt-1):
                    n = 0
                    nb += 1
                    fh.write(pack("<L", all + bdcnt + nb))
                fh.write(pack("<L", bsize + sbdsize + ppscnt + i))
                i += 1
                n += 1
            if (bdcnt-fstbdl) % (bbcnt-1):
                fh.write(pack("<L", -1) * (bbcnt - 1 - ((bdcnt-fstbdl) % (bbcnt-1)))) 
            fh.write(pack("<L", -2))

    def close(self):
        self._write_footer()
        if self._fh_internal:
            self._fh.close()
        self._fileclosed = True
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.