Top Level Namespace
Defined Under Namespace
Classes: BIFFWriter, Chart, ExcelFormulaParser, ExcelFormulaParserError, Format, Formula, FuncallNode, MaxSizeError, Node, NumberNode, OLEStorageLite, OLEStorageLitePPS, OLEStorageLitePPSFile, OLEStorageLitePPSRoot, OLEWriter, OperateNode, RootNode, Spreadsheet, Worksheet
Instance Method Summary collapse
-
#create_doc_summary_property_set(properties) ⇒ Object
Create the DocSummaryInformation property set.
-
#create_summary_property_set(properties) ⇒ Object
create_summary_property_set().
-
#pack_property_data(properties, offset = 0) ⇒ Object
_pack_property_data().
-
#pack_VT_FILETIME(localtime) ⇒ Object
_pack_VT_FILETIME().
-
#pack_VT_I2(value) ⇒ Object
_pack_VT_I2().
-
#pack_VT_LPSTR(str, codepage) ⇒ Object
_pack_VT_LPSTR().
Instance Method Details
#create_doc_summary_property_set(properties) ⇒ Object
Create the DocSummaryInformation property set. This is mainly used for the Manager, Company and Category keywords.
The DocSummary also contains a stream for user defined properties. However this is a little arcane and probably not worth the implementation effort.
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 |
# File 'lib/WriteExcel/properties.rb', line 69 def create_doc_summary_property_set(properties) byte_order = [0xFFFE].pack('v') version = [0x0000].pack('v') system_id = [0x00020105].pack('V') class_id = ['00000000000000000000000000000000'].pack('H*') num_property_sets = [0x0002].pack('V') format_id_0 = ['02D5CDD59C2E1B10939708002B2CF9AE'].pack('H*') format_id_1 = ['05D5CDD59C2E1B10939708002B2CF9AE'].pack('H*') offset_0 = [0x0044].pack('V') num_property_0 = [properties.size].pack('V') property_offsets_0 = '' # Create the property set data block and calculate the offsets into it. property_data_0, offsets = pack_property_data(properties) # Create the property type and offsets based on the previous calculation. 0.upto(properties.size-1) do |i| property_offsets_0 = property_offsets_0 + [properties[i][0], offsets[i]].pack('VV') end # Size of size (4 bytes) + num_property (4 bytes) + the data structures. data_len = 8 + (property_offsets_0).length + property_data_0.length size_0 = [data_len].pack('V') # The second property set offset is at the end of the first property set. offset_1 = [0x0044 + data_len].pack('V') # We will use a static property set stream rather than try to generate it. property_data_1 = [%w( 98 00 00 00 03 00 00 00 00 00 00 00 20 00 00 00 01 00 00 00 36 00 00 00 02 00 00 00 3E 00 00 00 01 00 00 00 02 00 00 00 0A 00 00 00 5F 50 49 44 5F 47 55 49 44 00 02 00 00 00 E4 04 00 00 41 00 00 00 4E 00 00 00 7B 00 31 00 36 00 43 00 34 00 42 00 38 00 33 00 42 00 2D 00 39 00 36 00 35 00 46 00 2D 00 34 00 42 00 32 00 31 00 2D 00 39 00 30 00 33 00 44 00 2D 00 39 00 31 00 30 00 46 00 41 00 44 00 46 00 41 00 37 00 30 00 31 00 42 00 7D 00 00 00 00 00 00 00 2D 00 39 00 30 00 33 00 ).join('')].pack('H*') return byte_order + version + system_id + class_id + num_property_sets + format_id_0 + offset_0 + format_id_1 + offset_1 + size_0 + num_property_0 + property_offsets_0 + property_data_0 + property_data_1 end |
#create_summary_property_set(properties) ⇒ Object
create_summary_property_set().
Create the SummaryInformation property set. This is mainly used for the Title, Subject, Author, Keywords, Comments, Last author keywords and the creation date.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/WriteExcel/properties.rb', line 24 def create_summary_property_set(properties) byte_order = [0xFFFE].pack('v') version = [0x0000].pack('v') system_id = [0x00020105].pack('V') class_id = ['00000000000000000000000000000000'].pack('H*') num_property_sets = [0x0001].pack('V') format_id = ['E0859FF2F94F6810AB9108002B27B3D9'].pack('H*') offset = [0x0030].pack('V') num_property = [properties.size].pack('V') property_offsets = '' # Create the property set data block and calculate the offsets into it. property_data, offsets = pack_property_data(properties) # Create the property type and offsets based on the previous calculation. 0.upto(properties.size-1) do |i| property_offsets = property_offsets + [properties[i][0], offsets[i]].pack('VV') end # Size of size (4 bytes) + num_property (4 bytes) + the data structures. size = 8 + (property_offsets).length + property_data.length size = [size].pack('V') return byte_order + version + system_id + class_id + num_property_sets + format_id + offset + size + num_property + property_offsets + property_data end |
#pack_property_data(properties, offset = 0) ⇒ Object
_pack_property_data().
Create a packed property set structure. Strings are null terminated and padded to a 4 byte boundary. We also use this function to keep track of the property offsets within the data structure. These offsets are used by the calling functions. Currently we only need to handle 4 property types: VT_I2, VT_LPSTR, VT_FILETIME.
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/WriteExcel/properties.rb', line 140 def pack_property_data(properties, offset = 0) packed_property = '' data = '' offsets = [] # Get the strings codepage from the first property. codepage = properties[0][2] # The properties start after 8 bytes for size + num_properties + 8 bytes # for each propety type/offset pair. offset += 8 * (properties.size + 1) properties.each do |property| offsets.push(offset) property_type = property[1] if property_type == 'VT_I2' packed_property = pack_VT_I2(property[2]) elsif property_type == 'VT_LPSTR' packed_property = pack_VT_LPSTR(property[2], codepage) elsif property_type == 'VT_FILETIME' packed_property = pack_VT_FILETIME(property[2]) else raise "Unknown property type: '#{property_type}'\n" end offset += packed_property.length data = data + packed_property end return [data, offsets] end |
#pack_VT_FILETIME(localtime) ⇒ Object
_pack_VT_FILETIME().
Pack an OLE property type: VT_FILETIME.
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
# File 'lib/WriteExcel/properties.rb', line 232 def pack_VT_FILETIME(localtime) type = 0x0040 epoch = DateTime.new(1601, 1, 1) datetime = DateTime.new( localtime.year, localtime.mon, localtime.mday, localtime.hour, localtime.min, localtime.sec, localtime.usec ) bignum = (datetime - epoch) * 86400 * 1e7.to_i high, low = bignum.divmod 1 << 32 [type].pack('V') + [low, high].pack('V2') end |
#pack_VT_I2(value) ⇒ Object
_pack_VT_I2().
Pack an OLE property type: VT_I2, 16-bit signed integer.
180 181 182 183 |
# File 'lib/WriteExcel/properties.rb', line 180 def pack_VT_I2(value) type = 0x0002 data = [type, value].pack('VV') end |
#pack_VT_LPSTR(str, codepage) ⇒ Object
_pack_VT_LPSTR().
Pack an OLE property type: VT_LPSTR, String in the Codepage encoding. The strings are null terminated and padded to a 4 byte boundary.
192 193 194 195 196 197 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 |
# File 'lib/WriteExcel/properties.rb', line 192 def pack_VT_LPSTR(str, codepage) type = 0x001E string = str + "\0" if codepage == 0x04E4 # Latin1 byte_string = string length = byte_string.length elsif codepage == 0xFDE9 # UTF-8 nonAscii = /[^!"#\$%&'\(\)\*\+,\-\.\/\:\;<=>\?@0-9A-Za-z_\[\\\]^` ~\0\n]/ if string =~ nonAscii require 'jcode' byte_string = string length = byte_string.jlength else byte_string = string length = byte_string.length end else raise "Unknown codepage: codepage\n" end # Pack the data. data = [type, length].pack('VV') data = data + byte_string # The packed data has to null padded to a 4 byte boundary. if (extra = length % 4) != 0 data = data + "\0" * (4 - extra) end return data end |