Class: BIFFWriter
- Inherits:
-
Object
- Object
- BIFFWriter
- Defined in:
- lib/WriteExcel/biffwriter.rb
Overview
require ‘tempfile’
Direct Known Subclasses
Constant Summary collapse
- BIFF_Version =
0x0600
- BigEndian =
[1].pack("I") == [1].pack("N")
Instance Attribute Summary collapse
-
#byte_order ⇒ Object
readonly
Returns the value of attribute byte_order.
-
#data ⇒ Object
readonly
Returns the value of attribute data.
-
#datasize ⇒ Object
readonly
Returns the value of attribute datasize.
Instance Method Summary collapse
-
#add_continue(data) ⇒ Object
_add_continue().
- #add_mso_generic(type, version, instance, data, length = nil) ⇒ Object
-
#append(*args) ⇒ Object
_append($data).
-
#get_data ⇒ Object
get_data().
-
#initialize ⇒ BIFFWriter
constructor
The args here aren’t used by BIFFWriter, but they are needed by its subclasses.
-
#prepend(*args) ⇒ Object
_prepend($data).
-
#set_byte_order ⇒ Object
_set_byte_order().
-
#store_bof(type = 0x0005) ⇒ Object
_store_bof($type).
-
#store_eof ⇒ Object
_store_eof().
Constructor Details
#initialize ⇒ BIFFWriter
The args here aren’t used by BIFFWriter, but they are needed by its subclasses. I don’t feel like creating multiple constructors.
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/WriteExcel/biffwriter.rb', line 27 def initialize set_byte_order @data = '' @datasize = 0 @limit = 8224 @ignore_continue = 0 # Open a tmp file to store the majority of the Worksheet data. If this fails, # for example due to write permissions, store the data in memory. This can be # slow for large files. @filehandle = Tempfile.new('spreadsheetWriteExcel') @filehandle.binmode # failed. store temporary data in memory. @using_tmpfile = @filehandle ? true : false end |
Instance Attribute Details
#byte_order ⇒ Object (readonly)
Returns the value of attribute byte_order.
20 21 22 |
# File 'lib/WriteExcel/biffwriter.rb', line 20 def byte_order @byte_order end |
#data ⇒ Object (readonly)
Returns the value of attribute data.
20 21 22 |
# File 'lib/WriteExcel/biffwriter.rb', line 20 def data @data end |
#datasize ⇒ Object (readonly)
Returns the value of attribute datasize.
20 21 22 |
# File 'lib/WriteExcel/biffwriter.rb', line 20 def datasize @datasize end |
Instance Method Details
#add_continue(data) ⇒ Object
_add_continue()
Excel limits the size of BIFF records. In Excel 5 the limit is 2084 bytes. In Excel 97 the limit is 8228 bytes. Records that are longer than these limits must be split up into CONTINUE blocks.
This function take a long BIFF record and inserts CONTINUE records as necessary.
Some records have their own specialised Continue blocks so there is also an option to bypass this function.
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/WriteExcel/biffwriter.rb', line 198 def add_continue(data) record = 0x003C # Record identifier # Skip this if another method handles the continue blocks. return data if @ignore_continue != 0 # The first 2080/8224 bytes remain intact. However, we have to change # the length field of the record. # # in perl # $tmp = substr($data, 0, $limit, ""); if data.length > @limit tmp = data[0, @limit] data[0, @limit] = '' else tmp = data.dup data = '' end tmp[2, 2] = [@limit-4].pack('v') # Strip out chunks of 2080/8224 bytes +4 for the header. while (data.length > @limit) header = [record, @limit].pack("vv") tmp = tmp + header + data[0, @limit] data[0, @limit] = '' end # Mop up the last of the data header = [record, data.length].pack("vv") tmp = tmp + header + data return tmp end |
#add_mso_generic(type, version, instance, data, length = nil) ⇒ Object
_add_mso_generic()
my $type = $_[0];
my $version = $_[1];
my $instance = $_[2];
my $data = $_[3];
Create a mso structure that is part of an Escher drawing object. These are are used for images, comments and filters. This generic method is used by other methods to create specific mso records.
Returns the packed record.
248 249 250 251 252 253 254 255 256 257 |
# File 'lib/WriteExcel/biffwriter.rb', line 248 def add_mso_generic(type, version, instance, data, length = nil) length = length.nil? ? data.length : length # The header contains version and instance info packed into 2 bytes. header = version | (instance << 4) record = [header, type, length].pack('vvV') + data return record end |
#append(*args) ⇒ Object
_append($data)
General storage function
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/WriteExcel/biffwriter.rb', line 95 def append(*args) d = args.join # Add CONTINUE records if necessary d = add_continue(d) if d.length > @limit if @using_tmpfile @filehandle.write d @datasize += d.length else @datasize += d.length @data = @data + d end #print "apend\n" #print d.unpack('C*').map! {|c| sprintf("%02X", c) }.join(' ') + "\n\n" return d end |
#get_data ⇒ Object
get_data().
Retrieves data from memory in one chunk, or from disk in $buffer sized chunks.
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/WriteExcel/biffwriter.rb', line 118 def get_data buflen = 4096 # Return data stored in memory unless @data.nil? tmp = @data @data = nil if @using_tmpfile @filehandle.open @filehandle.binmode end return tmp end # Return data stored on disk if @using_tmpfile return @filehandle.read(buflen) end # No data to return return nil end |
#prepend(*args) ⇒ Object
_prepend($data)
General storage function
77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/WriteExcel/biffwriter.rb', line 77 def prepend(*args) d = args.join d = add_continue(d) if d.length > @limit @datasize += d.length @data = d + @data #print "prepend\n" #print d.unpack('C*').map! {|c| sprintf("%02X", c) }.join(' ') + "\n\n" return d end |
#set_byte_order ⇒ Object
_set_byte_order()
Determine the byte order and store it as class data to avoid recalculating it for each call to new().
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/WriteExcel/biffwriter.rb', line 52 def set_byte_order # Check if "pack" gives the required IEEE 64bit float teststr = [1.2345].pack("d") hexdata = [0x8D, 0x97, 0x6E, 0x12, 0x83, 0xC0, 0xF3, 0x3F] number = hexdata.pack("C8") if number == teststr @byte_order = 0 # Little Endian elsif number == teststr.reverse @byte_order = 1 # Big Endian else # Give up. I'll fix this in a later version. raise( "Required floating point format not supported " + "on this platform. See the portability section " + "of the documentation." ) end end |
#store_bof(type = 0x0005) ⇒ Object
_store_bof($type)
$type = 0x0005, Workbook $type = 0x0010, Worksheet
Writes Excel BOF record to indicate the beginning of a stream or sub-stream in the BIFF file.
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/WriteExcel/biffwriter.rb', line 151 def store_bof(type = 0x0005) record = 0x0809 # Record identifier length = 0x0010 # Number of bytes to follow # According to the SDK $build and $year should be set to zero. # However, this throws a warning in Excel 5. So, use these # magic numbers. build = 0x0DBB year = 0x07CC bfh = 0x00000041 sfo = 0x00000006 header = [record,length].pack("vv") data = [BIFF_Version,type,build,year,bfh,sfo].pack("vvvvVV") prepend(header, data) end |
#store_eof ⇒ Object
_store_eof()
Writes Excel EOF record to indicate the end of a BIFF stream.
176 177 178 179 180 181 182 |
# File 'lib/WriteExcel/biffwriter.rb', line 176 def store_eof record = 0x000A length = 0x0000 header = [record,length].pack("vv") append(header) end |