Class: BIFFWriter
- Inherits:
-
Object
- Object
- BIFFWriter
- Defined in:
- lib/writeexcel/biffwriter.rb
Overview
:nodoc:
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).
-
#clear_data_for_test ⇒ Object
:nodoc:.
-
#get_data ⇒ Object
get_data().
-
#initialize ⇒ BIFFWriter
constructor
The args here aren’t used by BIFFWriter, but they are needed by its subclasses.
- #not_using_tmpfile ⇒ Object
-
#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.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/writeexcel/biffwriter.rb', line 28 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.
21 22 23 |
# File 'lib/writeexcel/biffwriter.rb', line 21 def byte_order @byte_order end |
#data ⇒ Object (readonly)
Returns the value of attribute data.
21 22 23 |
# File 'lib/writeexcel/biffwriter.rb', line 21 def data @data end |
#datasize ⇒ Object (readonly)
Returns the value of attribute datasize.
21 22 23 |
# File 'lib/writeexcel/biffwriter.rb', line 21 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.
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 233 234 235 236 237 |
# File 'lib/writeexcel/biffwriter.rb', line 203 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.
253 254 255 256 257 258 259 260 261 262 |
# File 'lib/writeexcel/biffwriter.rb', line 253 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
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/writeexcel/biffwriter.rb', line 96 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 "append\n" if defined?($debug) print d.unpack('C*').map! {|c| sprintf("%02X", c) }.join(' ') + "\n\n" if defined?($debug) return d end |
#clear_data_for_test ⇒ Object
:nodoc:
270 271 272 |
# File 'lib/writeexcel/biffwriter.rb', line 270 def clear_data_for_test # :nodoc: @data = '' end |
#get_data ⇒ Object
get_data().
Retrieves data from memory in one chunk, or from disk in $buffer sized chunks.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/writeexcel/biffwriter.rb', line 120 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 |
#not_using_tmpfile ⇒ Object
264 265 266 267 268 |
# File 'lib/writeexcel/biffwriter.rb', line 264 def not_using_tmpfile @filehandle.close(true) if @filehandle @filehandle = nil @using_tmpfile = nil end |
#prepend(*args) ⇒ Object
_prepend($data)
General storage function
78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/writeexcel/biffwriter.rb', line 78 def prepend(*args) d = args.join d = add_continue(d) if d.length > @limit @datasize += d.length @data = d + @data print "prepend\n" if defined?($debug) print d.unpack('C*').map! {|c| sprintf("%02X", c) }.join(' ') + "\n\n" if defined?($debug) 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().
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/writeexcel/biffwriter.rb', line 53 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 $type = 0x0020, Chart
Writes Excel BOF record to indicate the beginning of a stream or sub-stream in the BIFF file.
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/writeexcel/biffwriter.rb', line 154 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") print "store_bof in #{__FILE__}\n" if defined?($debug) prepend(header, data) end |
#store_eof ⇒ Object
_store_eof()
Writes Excel EOF record to indicate the end of a BIFF stream.
180 181 182 183 184 185 186 187 |
# File 'lib/writeexcel/biffwriter.rb', line 180 def store_eof record = 0x000A length = 0x0000 header = [record,length].pack("vv") print "store_eof in #{__FILE__}\n" if defined?($debug) append(header) end |