Class: Workbook::SharedStringTable
- Inherits:
-
Object
- Object
- Workbook::SharedStringTable
- Defined in:
- lib/writeexcel/shared_string_table.rb
Instance Attribute Summary collapse
-
#str_total ⇒ Object
readonly
Returns the value of attribute str_total.
Instance Method Summary collapse
- #<<(string) ⇒ Object
- #block_sizes ⇒ Object
-
#calculate_block_sizes ⇒ Object
Handling of the SST continue blocks is complicated by the need to include an additional continuation byte depending on whether the string is split between blocks or whether it starts at the beginning of the block.
- #has_string?(string) ⇒ Boolean
- #id(string) ⇒ Object
-
#initialize ⇒ SharedStringTable
constructor
A new instance of SharedStringTable.
- #str_unique ⇒ Object
- #strings ⇒ Object
Constructor Details
#initialize ⇒ SharedStringTable
Returns a new instance of SharedStringTable.
16 17 18 19 20 |
# File 'lib/writeexcel/shared_string_table.rb', line 16 def initialize @shared_string_table = [] @string_to_shared_string = {} @str_total = 0 end |
Instance Attribute Details
#str_total ⇒ Object (readonly)
Returns the value of attribute str_total.
14 15 16 |
# File 'lib/writeexcel/shared_string_table.rb', line 14 def str_total @str_total end |
Instance Method Details
#<<(string) ⇒ Object
26 27 28 29 30 31 32 33 34 |
# File 'lib/writeexcel/shared_string_table.rb', line 26 def <<(string) @str_total += 1 unless has_string?(string) shared_string = SharedString.new(string, str_unique) @shared_string_table << shared_string @string_to_shared_string[string] = shared_string end id(string) end |
#block_sizes ⇒ Object
48 49 50 |
# File 'lib/writeexcel/shared_string_table.rb', line 48 def block_sizes @block_sizes ||= calculate_block_sizes end |
#calculate_block_sizes ⇒ Object
Handling of the SST continue blocks is complicated by the need to include an additional continuation byte depending on whether the string is split between blocks or whether it starts at the beginning of the block. (There are also additional complications that will arise later when/if Rich Strings are supported). As such we cannot use the simple CONTINUE mechanism provided by the add_continue() method in BIFFwriter.pm. Thus we have to make two passes through the strings data. The first is to calculate the required block sizes and the second, in store_shared_strings(), is to write the actual strings. The first pass through the data is also used to calculate the size of the SST and CONTINUE records for use in setting the BOUNDSHEET record offsets. The downside of this is that the same algorithm repeated in store_shared_strings.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/writeexcel/shared_string_table.rb', line 65 def calculate_block_sizes # Iterate through the strings to calculate the CONTINUE block sizes. # # The SST blocks requires a specialised CONTINUE block, so we have to # ensure that the maximum data block size is less than the limit used by # add_continue() in BIFFwriter.pm. For simplicity we use the same size # for the SST and CONTINUE records: # 8228 : Maximum Excel97 block size # -4 : Length of block header # -8 : Length of additional SST header information # -8 : Arbitrary number to keep within add_continue() limit # = 8208 # continue_limit = 8208 block_length = 0 written = 0 block_sizes = [] continue = 0 strings.each do |string| string_length = string.bytesize # Block length is the total length of the strings that will be # written out in a single SST or CONTINUE block. # block_length += string_length # We can write the string if it doesn't cross a CONTINUE boundary if block_length < continue_limit written += string_length next end # Deal with the cases where the next string to be written will exceed # the CONTINUE boundary. If the string is very long it may need to be # written in more than one CONTINUE record. encoding = string.unpack("xx C")[0] split_string = 0 while block_length >= continue_limit header_length, space_remaining, align, split_string = Workbook.split_string_setup(encoding, split_string, continue_limit, written, continue) if space_remaining > header_length # Write as much as possible of the string in the current block written += space_remaining # Reduce the current block length by the amount written block_length -= continue_limit - continue - align # Store the max size for this block block_sizes.push(continue_limit - align) # If the current string was split then the next CONTINUE block # should have the string continue flag (grbit) set unless the # split string fits exactly into the remaining space. # if block_length > 0 continue = 1 else continue = 0 end else # Store the max size for this block block_sizes.push(written + continue) # Not enough space to start the string in the current block block_length -= continue_limit - space_remaining - continue continue = 0 end # If the string (or substr) is small enough we can write it in the # new CONTINUE block. Else, go through the loop again to write it in # one or more CONTINUE blocks # if block_length < continue_limit written = block_length else written = 0 end end end # Store the max size for the last block unless it is empty block_sizes.push(written + continue) if written + continue != 0 block_sizes end |
#has_string?(string) ⇒ Boolean
22 23 24 |
# File 'lib/writeexcel/shared_string_table.rb', line 22 def has_string?(string) !!@string_to_shared_string[string] end |
#id(string) ⇒ Object
40 41 42 |
# File 'lib/writeexcel/shared_string_table.rb', line 40 def id(string) @string_to_shared_string[string].str_id end |
#str_unique ⇒ Object
44 45 46 |
# File 'lib/writeexcel/shared_string_table.rb', line 44 def str_unique @shared_string_table.size end |
#strings ⇒ Object
36 37 38 |
# File 'lib/writeexcel/shared_string_table.rb', line 36 def strings @shared_string_table.collect { |shared_string| shared_string.string } end |