OLEWriter.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 » OLEWriter.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)
#
# 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 was written/ported from PERL Spreadsheet::WriteExcel module
# The author of the PERL Spreadsheet::WriteExcel module is John McNamara
# <jmcnamara@cpan.org>
#----------------------------------------------------------------------------
# See the README.txt distributed with pyXLWriter for more details.

"""pyXLWriter.OLEWriter

Used in conjunction with Spreadsheet::WriteExcel

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

from struct import pack


class OLEWriter:
    """OLEwriter - A writer class to store BIFF data in a OLE compound
    storage file.

    """

    def __init__(self, olefile=None):
        """Constructor."""
        self._olefile = olefile
        self._filehandle = None
        self._fileclosed = False
        self._internal_fh = False
        self._biff_only = 0
        self._size_allowed = 0
        self._biffsize = 0
        self._booksize = 0
        self._big_blocks = 0
        self._list_blocks = 0
        self._root_start = 0
        self._block_count = 4
        self._initialize()

    def _initialize(self):
        """Check for a valid filename and store the filehandle."""
        if isinstance(self._olefile, str):
            # Create a new file, open for writing
            self._internal_fh = True
            self._filehandle = file(self._olefile, "wb")
        else:
            self._internal_fh = False
            self._filehandle = self._olefile

    def set_size(self, biffsize):
        """Set the size of the data to be written to the OLE stream

        big_blocks - (109 depot block x (128 -1 marker word)
                       - (1 x end words)) = 13842
        maxsize - big_blocks * 512 bytes = 7087104

        """
        maxsize = 7087104  # Use Spreadsheet::WriteExcel::Big to exceed this
        if biffsize > maxsize:
            self._size_allowed = False
            raise Exception("Max size error")
        self._biffsize = biffsize
        # Set the min file size to 4k to avoid having to use small blocks
        self._booksize = max(biffsize, 4096)
        self._size_allowed = True

    def _calculate_sizes(self):
        """Calculate various sizes needed for the OLE stream"""
        datasize = self._booksize
        if datasize % 512 == 0:
            self._big_blocks = datasize // 512
        else:
            self._big_blocks = datasize // 512 + 1
        # There are 127 list blocks and 1 marker blocks for each big block
        # depot + 1 end of chain block
        self._list_blocks = self._big_blocks // 127 + 1
        self._root_start = self._big_blocks

    def close(self):
        """ Write root entry, big block list and close the filehandle.
        This routine is used to explicitly close the open filehandle without
        having to wait for DESTROY.

        """
        if not self._size_allowed:
            return
        if not self._biff_only:
            self._write_padding()
        if not self._biff_only:
            self._write_property_storage()
        if not self._biff_only:
            self._write_big_block_depot()
        # Close the filehandle if it was created internally.
        if self._internal_fh:
            self._filehandle.close()
        self._fileclosed = True

    #~ def __del__(self):
        #~ """Close the filehandle if it hasn't already been explicitly closed."""
        #~ if not self._fileclosed:
            #~ self.close()

    def write(self, data):
        """Write BIFF data to OLE file."""
        self._filehandle.write(data)

    def write_header(self):
        """Write OLE header block."""
        fh = self._filehandle
        if self._biff_only:
            return
        self._calculate_sizes()
        root_start = self._root_start
        num_lists = self._list_blocks
        id = pack("<8B", 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1)
        unknown1 = pack("<LLLL", 0x00, 0x00, 0x00, 0x00)
        unknown2 = pack("<HH", 0x3E, 0x03)
        unknown3 = pack("<H", -2)
        unknown4 = pack("<H", 0x09)
        unknown5 = pack("<LLL", 0x06, 0x00, 0x00)
        num_bbd_blocks = pack("<L", num_lists)
        root_startblock = pack("<L", root_start)
        unknown6 = pack("<LL", 0x00, 0x1000)
        sbd_startblock = pack("<L", -2)
        unknown7 = pack("<LLL", 0x00, -2 ,0x00)
        unused = pack("<L", -1)
        fh.write(id)
        fh.write(unknown1)
        fh.write(unknown2)
        fh.write(unknown3)
        fh.write(unknown4)
        fh.write(unknown5)
        fh.write(num_bbd_blocks)
        fh.write(root_startblock)
        fh.write(unknown6)
        fh.write(sbd_startblock)
        fh.write(unknown7)
        for i in xrange(num_lists):
            root_start += 1
            fh.write(pack("<L", root_start))
        for i in xrange(num_lists, 108 + 1):
            fh.write(unused)

    def _write_big_block_depot(self):
        """Write big block depot."""
        fh = self._filehandle
        num_blocks = self._big_blocks
        num_lists = self._list_blocks
        total_blocks = num_lists * 128
        used_blocks = num_blocks + num_lists + 2
        marker = pack("<L", -3)
        end_of_chain = pack("<L", -2)
        unused = pack("<L", -1)
        for i in xrange(1, num_blocks):
            fh.write(pack("<L", i))
        fh.write(end_of_chain)
        fh.write(end_of_chain)
        for i in xrange(1, num_lists+1):
            fh.write(marker)
        for i in xrange(used_blocks, total_blocks+1):
            fh.write(unused)

    def _write_property_storage(self):
        """Write property storage. TODO: add summary sheets"""
        rootsize = -2
        booksize = self._booksize
        #                name         type   dir start size
        self._write_pps('Root Entry', 0x05,   1,   -2, 0x00)
        self._write_pps('Book',       0x02,  -1, 0x00, booksize)
        self._write_pps('',           0x00,  -1, 0x00, 0x0000)
        self._write_pps('',           0x00,  -1, 0x00, 0x0000)

    def _write_pps(self, name, type_, dir, sb, size):
        """Write property sheet in property storage"""
        fh = self._filehandle
        length = 0
        if name:
            name  = name + "\0"
            length = len(name) * 2
        # Simulate a Unicode string
        if name:
            rawname = "\x00".join(name) + "\x00"
        else:
            rawname = ""
        zero = pack("<B", 0)
        pps_sizeofname = pack("<H", length)    #0x40
        pps_type = pack("<H", type_)           #0x42
        pps_prev = pack("<L", -1)              #0x44
        pps_next = pack("<L", -1)              #0x48
        pps_dir = pack("<L", dir)              #0x4c
        unknown1 = pack("<L", 0)
        pps_ts1s = pack("<L", 0)               #0x64
        pps_ts1d = pack("<L", 0)               #0x68
        pps_ts2s = pack("<L", 0)               #0x6c
        pps_ts2d = pack("<L", 0)               #0x70
        pps_sb = pack("<L", sb)                #0x74
        pps_size = pack("<L", size)            #0x78
        fh.write(rawname)
        fh.write(zero * (64 - length))
        fh.write(pps_sizeofname)
        fh.write(pps_type)
        fh.write(pps_prev)
        fh.write(pps_next)
        fh.write(pps_dir)
        fh.write(unknown1 * 5)
        fh.write(pps_ts1s)
        fh.write(pps_ts1d)
        fh.write(pps_ts2d)
        fh.write(pps_ts2d)
        fh.write(pps_sb)
        fh.write(pps_size)
        fh.write(unknown1)

    def _write_padding(self):
        """Pad the end of the file"""
        biffsize = self._biffsize
        if biffsize < 4096:
            min_size = 4096
        else:
            min_size = 512
        if biffsize % min_size:
            padding = min_size - (biffsize % min_size)
            self._filehandle.write("\0" * padding)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.