writeexcel 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. data/README +26 -31
  2. data/examples/a_simple.rb +42 -42
  3. data/examples/{autofilters.rb → autofilter.rb} +264 -266
  4. data/examples/bigfile.rb +29 -0
  5. data/examples/chart_area.rb +120 -0
  6. data/examples/chart_bar.rb +119 -0
  7. data/examples/chart_column.rb +119 -0
  8. data/examples/chart_line.rb +119 -0
  9. data/examples/chart_pie.rb +107 -0
  10. data/examples/chart_scatter.rb +120 -0
  11. data/examples/chart_stock.rb +147 -0
  12. data/examples/copyformat.rb +51 -51
  13. data/examples/data_validate.rb +278 -278
  14. data/examples/date_time.rb +86 -86
  15. data/examples/defined_name.rb +31 -0
  16. data/examples/demo.rb +120 -118
  17. data/examples/diag_border.rb +35 -35
  18. data/examples/formats.rb +489 -489
  19. data/examples/header.rb +136 -136
  20. data/examples/hidden.rb +28 -28
  21. data/examples/hyperlink.rb +42 -42
  22. data/examples/images.rb +52 -52
  23. data/examples/merge1.rb +39 -39
  24. data/examples/merge2.rb +44 -44
  25. data/examples/merge3.rb +65 -65
  26. data/examples/merge4.rb +82 -82
  27. data/examples/merge5.rb +79 -79
  28. data/examples/properties.rb +33 -0
  29. data/examples/properties_jp.rb +32 -0
  30. data/examples/protection.rb +46 -46
  31. data/examples/regions.rb +52 -52
  32. data/examples/repeat.rb +42 -42
  33. data/examples/stats.rb +75 -75
  34. data/examples/stocks.rb +80 -80
  35. data/examples/tab_colors.rb +30 -30
  36. data/examples/write_arrays.rb +82 -0
  37. data/lib/writeexcel.rb +1134 -18
  38. data/lib/writeexcel/biffwriter.rb +273 -260
  39. data/lib/writeexcel/chart.rb +2306 -217
  40. data/lib/writeexcel/charts/area.rb +152 -0
  41. data/lib/writeexcel/charts/bar.rb +177 -0
  42. data/lib/writeexcel/charts/column.rb +156 -0
  43. data/lib/writeexcel/charts/external.rb +61 -0
  44. data/lib/writeexcel/charts/line.rb +152 -0
  45. data/lib/writeexcel/charts/pie.rb +169 -0
  46. data/lib/writeexcel/charts/scatter.rb +192 -0
  47. data/lib/writeexcel/charts/stock.rb +211 -0
  48. data/lib/writeexcel/excelformulaparser.rb +208 -195
  49. data/lib/writeexcel/format.rb +1697 -1108
  50. data/lib/writeexcel/formula.rb +1050 -986
  51. data/lib/writeexcel/olewriter.rb +322 -322
  52. data/lib/writeexcel/properties.rb +251 -250
  53. data/lib/writeexcel/storage_lite.rb +968 -0
  54. data/lib/writeexcel/workbook.rb +3294 -2630
  55. data/lib/writeexcel/worksheet.rb +9012 -6377
  56. data/test/excelfile/Chart1.xls +0 -0
  57. data/test/excelfile/Chart2.xls +0 -0
  58. data/test/excelfile/Chart3.xls +0 -0
  59. data/test/excelfile/Chart4.xls +0 -0
  60. data/test/excelfile/Chart5.xls +0 -0
  61. data/test/perl_output/Chart1.xls.data +0 -0
  62. data/test/perl_output/Chart2.xls.data +0 -0
  63. data/test/perl_output/Chart3.xls.data +0 -0
  64. data/test/perl_output/Chart4.xls.data +0 -0
  65. data/test/perl_output/Chart5.xls.data +0 -0
  66. data/test/perl_output/a_simple.xls +0 -0
  67. data/test/perl_output/autofilter.xls +0 -0
  68. data/test/perl_output/chart_area.xls +0 -0
  69. data/test/perl_output/chart_bar.xls +0 -0
  70. data/test/perl_output/chart_column.xls +0 -0
  71. data/test/perl_output/chart_line.xls +0 -0
  72. data/test/perl_output/data_validate.xls +0 -0
  73. data/test/perl_output/date_time.xls +0 -0
  74. data/test/perl_output/demo.xls +0 -0
  75. data/test/perl_output/demo101.bin +0 -0
  76. data/test/perl_output/demo201.bin +0 -0
  77. data/test/perl_output/demo301.bin +0 -0
  78. data/test/perl_output/demo401.bin +0 -0
  79. data/test/perl_output/demo501.bin +0 -0
  80. data/test/perl_output/diag_border.xls +0 -0
  81. data/test/perl_output/headers.xls +0 -0
  82. data/test/perl_output/hyperlink.xls +0 -0
  83. data/test/perl_output/images.xls +0 -0
  84. data/test/perl_output/merge1.xls +0 -0
  85. data/test/perl_output/merge2.xls +0 -0
  86. data/test/perl_output/merge3.xls +0 -0
  87. data/test/perl_output/merge4.xls +0 -0
  88. data/test/perl_output/merge5.xls +0 -0
  89. data/test/perl_output/protection.xls +0 -0
  90. data/test/perl_output/regions.xls +0 -0
  91. data/test/perl_output/stats.xls +0 -0
  92. data/test/perl_output/stocks.xls +0 -0
  93. data/test/perl_output/tab_colors.xls +0 -0
  94. data/test/perl_output/unicode_cyrillic.xls +0 -0
  95. data/test/perl_output/workbook1.xls +0 -0
  96. data/test/perl_output/workbook2.xls +0 -0
  97. data/test/tc_all.rb +32 -31
  98. data/test/tc_biff.rb +104 -104
  99. data/test/tc_chart.rb +22 -22
  100. data/test/tc_example_match.rb +1944 -1280
  101. data/test/tc_format.rb +1254 -1267
  102. data/test/tc_formula.rb +63 -63
  103. data/test/tc_ole.rb +110 -110
  104. data/test/tc_storage_lite.rb +149 -0
  105. data/test/tc_workbook.rb +140 -115
  106. data/test/tc_worksheet.rb +115 -115
  107. data/test/test_00_IEEE_double.rb +14 -14
  108. data/test/test_01_add_worksheet.rb +12 -12
  109. data/test/test_02_merge_formats.rb +58 -58
  110. data/test/test_04_dimensions.rb +397 -397
  111. data/test/test_05_rows.rb +182 -182
  112. data/test/test_06_extsst.rb +80 -80
  113. data/test/test_11_date_time.rb +484 -484
  114. data/test/test_12_date_only.rb +506 -506
  115. data/test/test_13_date_seconds.rb +486 -486
  116. data/test/test_21_escher.rb +642 -629
  117. data/test/test_22_mso_drawing_group.rb +750 -739
  118. data/test/test_23_note.rb +78 -78
  119. data/test/test_24_txo.rb +80 -80
  120. data/test/test_25_position_object.rb +82 -0
  121. data/test/test_26_autofilter.rb +327 -327
  122. data/test/test_27_autofilter.rb +144 -144
  123. data/test/test_28_autofilter.rb +174 -174
  124. data/test/test_29_process_jpg.rb +681 -131
  125. data/test/test_30_validation_dval.rb +82 -82
  126. data/test/test_31_validation_dv_strings.rb +131 -131
  127. data/test/test_32_validation_dv_formula.rb +211 -211
  128. data/test/test_40_property_types.rb +191 -191
  129. data/test/test_41_properties.rb +238 -238
  130. data/test/test_42_set_properties.rb +442 -419
  131. data/test/test_50_name_stored.rb +305 -0
  132. data/test/test_51_name_print_area.rb +363 -0
  133. data/test/test_52_name_print_titles.rb +460 -0
  134. data/test/test_53_autofilter.rb +209 -0
  135. data/test/test_60_chart_generic.rb +576 -0
  136. data/test/test_61_chart_subclasses.rb +97 -0
  137. data/test/test_62_chart_formats.rb +270 -0
  138. data/test/test_63_chart_area_formats.rb +647 -0
  139. data/test/test_chartex.rb +35 -0
  140. data/test/ts_all.rb +46 -34
  141. data/writeexcel.gemspec +18 -0
  142. data/writeexcel.rdoc +583 -0
  143. metadata +162 -108
@@ -1,250 +1,251 @@
1
- ###############################################################################
2
- #
3
- # Properties - A module for creating Excel property sets.
4
- #
5
- #
6
- # Used in conjunction with Spreadsheet::WriteExcel
7
- #
8
- # Copyright 2000-2008, John McNamara.
9
- #
10
- # original written in Perl by John McNamara
11
- # converted to Ruby by Hideo Nakamura, cxn03651@msj.biglobe.ne.jp
12
- #
13
-
14
- require 'date'
15
-
16
- ###############################################################################
17
- #
18
- # create_summary_property_set().
19
- #
20
- # Create the SummaryInformation property set. This is mainly used for the
21
- # Title, Subject, Author, Keywords, Comments, Last author keywords and the
22
- # creation date.
23
- #
24
- def create_summary_property_set(properties)
25
- byte_order = [0xFFFE].pack('v')
26
- version = [0x0000].pack('v')
27
- system_id = [0x00020105].pack('V')
28
- class_id = ['00000000000000000000000000000000'].pack('H*')
29
- num_property_sets = [0x0001].pack('V')
30
- format_id = ['E0859FF2F94F6810AB9108002B27B3D9'].pack('H*')
31
- offset = [0x0030].pack('V')
32
- num_property = [properties.size].pack('V')
33
- property_offsets = ''
34
-
35
- # Create the property set data block and calculate the offsets into it.
36
- property_data, offsets = pack_property_data(properties)
37
-
38
- # Create the property type and offsets based on the previous calculation.
39
- 0.upto(properties.size-1) do |i|
40
- property_offsets = property_offsets + [properties[i][0], offsets[i]].pack('VV')
41
- end
42
-
43
- # Size of size (4 bytes) + num_property (4 bytes) + the data structures.
44
- size = 8 + (property_offsets).length + property_data.length
45
- size = [size].pack('V')
46
-
47
- return byte_order +
48
- version +
49
- system_id +
50
- class_id +
51
- num_property_sets +
52
- format_id +
53
- offset +
54
- size +
55
- num_property +
56
- property_offsets +
57
- property_data
58
- end
59
-
60
-
61
- ###############################################################################
62
- #
63
- # Create the DocSummaryInformation property set. This is mainly used for the
64
- # Manager, Company and Category keywords.
65
- #
66
- # The DocSummary also contains a stream for user defined properties. However
67
- # this is a little arcane and probably not worth the implementation effort.
68
- #
69
- def create_doc_summary_property_set(properties)
70
- byte_order = [0xFFFE].pack('v')
71
- version = [0x0000].pack('v')
72
- system_id = [0x00020105].pack('V')
73
- class_id = ['00000000000000000000000000000000'].pack('H*')
74
- num_property_sets = [0x0002].pack('V')
75
-
76
- format_id_0 = ['02D5CDD59C2E1B10939708002B2CF9AE'].pack('H*')
77
- format_id_1 = ['05D5CDD59C2E1B10939708002B2CF9AE'].pack('H*')
78
- offset_0 = [0x0044].pack('V')
79
- num_property_0 = [properties.size].pack('V')
80
- property_offsets_0 = ''
81
-
82
- # Create the property set data block and calculate the offsets into it.
83
- property_data_0, offsets = pack_property_data(properties)
84
-
85
- # Create the property type and offsets based on the previous calculation.
86
- 0.upto(properties.size-1) do |i|
87
- property_offsets_0 = property_offsets_0 + [properties[i][0], offsets[i]].pack('VV')
88
- end
89
-
90
- # Size of size (4 bytes) + num_property (4 bytes) + the data structures.
91
- data_len = 8 + (property_offsets_0).length + property_data_0.length
92
- size_0 = [data_len].pack('V')
93
-
94
- # The second property set offset is at the end of the first property set.
95
- offset_1 = [0x0044 + data_len].pack('V')
96
-
97
- # We will use a static property set stream rather than try to generate it.
98
- property_data_1 = [%w(
99
- 98 00 00 00 03 00 00 00 00 00 00 00 20 00 00 00
100
- 01 00 00 00 36 00 00 00 02 00 00 00 3E 00 00 00
101
- 01 00 00 00 02 00 00 00 0A 00 00 00 5F 50 49 44
102
- 5F 47 55 49 44 00 02 00 00 00 E4 04 00 00 41 00
103
- 00 00 4E 00 00 00 7B 00 31 00 36 00 43 00 34 00
104
- 42 00 38 00 33 00 42 00 2D 00 39 00 36 00 35 00
105
- 46 00 2D 00 34 00 42 00 32 00 31 00 2D 00 39 00
106
- 30 00 33 00 44 00 2D 00 39 00 31 00 30 00 46 00
107
- 41 00 44 00 46 00 41 00 37 00 30 00 31 00 42 00
108
- 7D 00 00 00 00 00 00 00 2D 00 39 00 30 00 33 00
109
- ).join('')].pack('H*')
110
-
111
- return byte_order +
112
- version +
113
- system_id +
114
- class_id +
115
- num_property_sets +
116
- format_id_0 +
117
- offset_0 +
118
- format_id_1 +
119
- offset_1 +
120
-
121
- size_0 +
122
- num_property_0 +
123
- property_offsets_0 +
124
- property_data_0 +
125
-
126
- property_data_1
127
- end
128
-
129
-
130
- ###############################################################################
131
- #
132
- # _pack_property_data().
133
- #
134
- # Create a packed property set structure. Strings are null terminated and
135
- # padded to a 4 byte boundary. We also use this function to keep track of the
136
- # property offsets within the data structure. These offsets are used by the
137
- # calling functions. Currently we only need to handle 4 property types:
138
- # VT_I2, VT_LPSTR, VT_FILETIME.
139
- #
140
- def pack_property_data(properties, offset = 0)
141
- packed_property = ''
142
- data = ''
143
- offsets = []
144
-
145
- # Get the strings codepage from the first property.
146
- codepage = properties[0][2]
147
-
148
- # The properties start after 8 bytes for size + num_properties + 8 bytes
149
- # for each propety type/offset pair.
150
- offset += 8 * (properties.size + 1)
151
-
152
- properties.each do |property|
153
- offsets.push(offset)
154
-
155
- property_type = property[1]
156
-
157
- if property_type == 'VT_I2'
158
- packed_property = pack_VT_I2(property[2])
159
- elsif property_type == 'VT_LPSTR'
160
- packed_property = pack_VT_LPSTR(property[2], codepage)
161
- elsif property_type == 'VT_FILETIME'
162
- packed_property = pack_VT_FILETIME(property[2])
163
- else
164
- raise "Unknown property type: '#{property_type}'\n"
165
- end
166
-
167
- offset += packed_property.length
168
- data = data + packed_property
169
- end
170
-
171
- return [data, offsets]
172
- end
173
-
174
- ###############################################################################
175
- #
176
- # _pack_VT_I2().
177
- #
178
- # Pack an OLE property type: VT_I2, 16-bit signed integer.
179
- #
180
- def pack_VT_I2(value)
181
- type = 0x0002
182
- data = [type, value].pack('VV')
183
- end
184
-
185
- ###############################################################################
186
- #
187
- # _pack_VT_LPSTR().
188
- #
189
- # Pack an OLE property type: VT_LPSTR, String in the Codepage encoding.
190
- # The strings are null terminated and padded to a 4 byte boundary.
191
- #
192
- def pack_VT_LPSTR(str, codepage)
193
- type = 0x001E
194
- string = str + "\0"
195
-
196
- if codepage == 0x04E4
197
- # Latin1
198
- byte_string = string
199
- length = byte_string.length
200
- elsif codepage == 0xFDE9
201
- # UTF-8
202
- nonAscii = /[^!"#\$%&'\(\)\*\+,\-\.\/\:\;<=>\?@0-9A-Za-z_\[\\\]^` ~\0\n]/
203
- if string =~ nonAscii
204
- require 'jcode'
205
- byte_string = string
206
- length = byte_string.jlength
207
- else
208
- byte_string = string
209
- length = byte_string.length
210
- end
211
- else
212
- raise "Unknown codepage: codepage\n"
213
- end
214
-
215
- # Pack the data.
216
- data = [type, length].pack('VV')
217
- data = data + byte_string
218
-
219
- # The packed data has to null padded to a 4 byte boundary.
220
- if (extra = length % 4) != 0
221
- data = data + "\0" * (4 - extra)
222
- end
223
- return data
224
- end
225
-
226
- ###############################################################################
227
- #
228
- # _pack_VT_FILETIME().
229
- #
230
- # Pack an OLE property type: VT_FILETIME.
231
- #
232
- def pack_VT_FILETIME(localtime)
233
- type = 0x0040
234
-
235
- epoch = DateTime.new(1601, 1, 1)
236
-
237
- datetime = DateTime.new(
238
- localtime.year,
239
- localtime.mon,
240
- localtime.mday,
241
- localtime.hour,
242
- localtime.min,
243
- localtime.sec,
244
- localtime.usec
245
- )
246
- bignum = (datetime - epoch) * 86400 * 1e7.to_i
247
- high, low = bignum.divmod 1 << 32
248
-
249
- [type].pack('V') + [low, high].pack('V2')
250
- end
1
+ ###############################################################################
2
+ #
3
+ # Properties - A module for creating Excel property sets.
4
+ #
5
+ #
6
+ # Used in conjunction with WriteExcel
7
+ #
8
+ # Copyright 2000-2010, John McNamara.
9
+ #
10
+ # original written in Perl by John McNamara
11
+ # converted to Ruby by Hideo Nakamura, cxn03651@msj.biglobe.ne.jp
12
+ #
13
+
14
+ require 'date'
15
+
16
+ ###############################################################################
17
+ #
18
+ # create_summary_property_set().
19
+ #
20
+ # Create the SummaryInformation property set. This is mainly used for the
21
+ # Title, Subject, Author, Keywords, Comments, Last author keywords and the
22
+ # creation date.
23
+ #
24
+ def create_summary_property_set(properties) #:nodoc:
25
+ byte_order = [0xFFFE].pack('v')
26
+ version = [0x0000].pack('v')
27
+ system_id = [0x00020105].pack('V')
28
+ class_id = ['00000000000000000000000000000000'].pack('H*')
29
+ num_property_sets = [0x0001].pack('V')
30
+ format_id = ['E0859FF2F94F6810AB9108002B27B3D9'].pack('H*')
31
+ offset = [0x0030].pack('V')
32
+ num_property = [properties.size].pack('V')
33
+ property_offsets = ''
34
+
35
+ # Create the property set data block and calculate the offsets into it.
36
+ property_data, offsets = pack_property_data(properties)
37
+
38
+ # Create the property type and offsets based on the previous calculation.
39
+ 0.upto(properties.size-1) do |i|
40
+ property_offsets = property_offsets + [properties[i][0], offsets[i]].pack('VV')
41
+ end
42
+
43
+ # Size of size (4 bytes) + num_property (4 bytes) + the data structures.
44
+ size = 8 + (property_offsets).length + property_data.length
45
+ size = [size].pack('V')
46
+
47
+ return byte_order +
48
+ version +
49
+ system_id +
50
+ class_id +
51
+ num_property_sets +
52
+ format_id +
53
+ offset +
54
+ size +
55
+ num_property +
56
+ property_offsets +
57
+ property_data
58
+ end
59
+
60
+
61
+ ###############################################################################
62
+ #
63
+ # Create the DocSummaryInformation property set. This is mainly used for the
64
+ # Manager, Company and Category keywords.
65
+ #
66
+ # The DocSummary also contains a stream for user defined properties. However
67
+ # this is a little arcane and probably not worth the implementation effort.
68
+ #
69
+ def create_doc_summary_property_set(properties) #:nodoc:
70
+ byte_order = [0xFFFE].pack('v')
71
+ version = [0x0000].pack('v')
72
+ system_id = [0x00020105].pack('V')
73
+ class_id = ['00000000000000000000000000000000'].pack('H*')
74
+ num_property_sets = [0x0002].pack('V')
75
+
76
+ format_id_0 = ['02D5CDD59C2E1B10939708002B2CF9AE'].pack('H*')
77
+ format_id_1 = ['05D5CDD59C2E1B10939708002B2CF9AE'].pack('H*')
78
+ offset_0 = [0x0044].pack('V')
79
+ num_property_0 = [properties.size].pack('V')
80
+ property_offsets_0 = ''
81
+
82
+ # Create the property set data block and calculate the offsets into it.
83
+ property_data_0, offsets = pack_property_data(properties)
84
+
85
+ # Create the property type and offsets based on the previous calculation.
86
+ 0.upto(properties.size-1) do |i|
87
+ property_offsets_0 = property_offsets_0 + [properties[i][0], offsets[i]].pack('VV')
88
+ end
89
+
90
+ # Size of size (4 bytes) + num_property (4 bytes) + the data structures.
91
+ data_len = 8 + (property_offsets_0).length + property_data_0.length
92
+ size_0 = [data_len].pack('V')
93
+
94
+ # The second property set offset is at the end of the first property set.
95
+ offset_1 = [0x0044 + data_len].pack('V')
96
+
97
+ # We will use a static property set stream rather than try to generate it.
98
+ property_data_1 = [%w(
99
+ 98 00 00 00 03 00 00 00 00 00 00 00 20 00 00 00
100
+ 01 00 00 00 36 00 00 00 02 00 00 00 3E 00 00 00
101
+ 01 00 00 00 02 00 00 00 0A 00 00 00 5F 50 49 44
102
+ 5F 47 55 49 44 00 02 00 00 00 E4 04 00 00 41 00
103
+ 00 00 4E 00 00 00 7B 00 31 00 36 00 43 00 34 00
104
+ 42 00 38 00 33 00 42 00 2D 00 39 00 36 00 35 00
105
+ 46 00 2D 00 34 00 42 00 32 00 31 00 2D 00 39 00
106
+ 30 00 33 00 44 00 2D 00 39 00 31 00 30 00 46 00
107
+ 41 00 44 00 46 00 41 00 37 00 30 00 31 00 42 00
108
+ 7D 00 00 00 00 00 00 00 2D 00 39 00 30 00 33 00
109
+ ).join('')].pack('H*')
110
+
111
+ return byte_order +
112
+ version +
113
+ system_id +
114
+ class_id +
115
+ num_property_sets +
116
+ format_id_0 +
117
+ offset_0 +
118
+ format_id_1 +
119
+ offset_1 +
120
+
121
+ size_0 +
122
+ num_property_0 +
123
+ property_offsets_0 +
124
+ property_data_0 +
125
+
126
+ property_data_1
127
+ end
128
+
129
+
130
+ ###############################################################################
131
+ #
132
+ # _pack_property_data().
133
+ #
134
+ # Create a packed property set structure. Strings are null terminated and
135
+ # padded to a 4 byte boundary. We also use this function to keep track of the
136
+ # property offsets within the data structure. These offsets are used by the
137
+ # calling functions. Currently we only need to handle 4 property types:
138
+ # VT_I2, VT_LPSTR, VT_FILETIME.
139
+ #
140
+ def pack_property_data(properties, offset = 0) #:nodoc:
141
+ packed_property = ''
142
+ data = ''
143
+ offsets = []
144
+
145
+ # Get the strings codepage from the first property.
146
+ codepage = properties[0][2]
147
+
148
+ # The properties start after 8 bytes for size + num_properties + 8 bytes
149
+ # for each propety type/offset pair.
150
+ offset += 8 * (properties.size + 1)
151
+
152
+ properties.each do |property|
153
+ offsets.push(offset)
154
+
155
+ property_type = property[1]
156
+
157
+ if property_type == 'VT_I2'
158
+ packed_property = pack_VT_I2(property[2])
159
+ elsif property_type == 'VT_LPSTR'
160
+ packed_property = pack_VT_LPSTR(property[2], codepage)
161
+ elsif property_type == 'VT_FILETIME'
162
+ packed_property = pack_VT_FILETIME(property[2])
163
+ else
164
+ raise "Unknown property type: '#{property_type}'\n"
165
+ end
166
+
167
+ offset += packed_property.length
168
+ data = data + packed_property
169
+ end
170
+
171
+ return [data, offsets]
172
+ end
173
+
174
+ ###############################################################################
175
+ #
176
+ # _pack_VT_I2().
177
+ #
178
+ # Pack an OLE property type: VT_I2, 16-bit signed integer.
179
+ #
180
+ def pack_VT_I2(value) #:nodoc:
181
+ type = 0x0002
182
+ data = [type, value].pack('VV')
183
+ end
184
+
185
+ ###############################################################################
186
+ #
187
+ # _pack_VT_LPSTR().
188
+ #
189
+ # Pack an OLE property type: VT_LPSTR, String in the Codepage encoding.
190
+ # The strings are null terminated and padded to a 4 byte boundary.
191
+ #
192
+ def pack_VT_LPSTR(str, codepage) #:nodoc:
193
+ type = 0x001E
194
+ string = str + "\0"
195
+
196
+ if codepage == 0x04E4
197
+ # Latin1
198
+ byte_string = string
199
+ length = byte_string.length
200
+ elsif codepage == 0xFDE9
201
+ # UTF-8
202
+ nonAscii = /[^!"#\$%&'\(\)\*\+,\-\.\/\:\;<=>\?@0-9A-Za-z_\[\\\]^` ~\0\n]/
203
+ if string =~ nonAscii
204
+ # $KCODE = 'u'
205
+ require 'jcode'
206
+ byte_string = string
207
+ length = byte_string.jlength
208
+ else
209
+ byte_string = string
210
+ length = byte_string.length
211
+ end
212
+ else
213
+ raise "Unknown codepage: codepage\n"
214
+ end
215
+
216
+ # Pack the data.
217
+ data = [type, length].pack('VV')
218
+ data = data + byte_string
219
+
220
+ # The packed data has to null padded to a 4 byte boundary.
221
+ if (extra = length % 4) != 0
222
+ data = data + "\0" * (4 - extra)
223
+ end
224
+ return data
225
+ end
226
+
227
+ ###############################################################################
228
+ #
229
+ # _pack_VT_FILETIME().
230
+ #
231
+ # Pack an OLE property type: VT_FILETIME.
232
+ #
233
+ def pack_VT_FILETIME(localtime) #:nodoc:
234
+ type = 0x0040
235
+
236
+ epoch = DateTime.new(1601, 1, 1)
237
+
238
+ datetime = DateTime.new(
239
+ localtime.year,
240
+ localtime.mon,
241
+ localtime.mday,
242
+ localtime.hour,
243
+ localtime.min,
244
+ localtime.sec,
245
+ localtime.usec
246
+ )
247
+ bignum = (datetime - epoch) * 86400 * 1e7.to_i
248
+ high, low = bignum.divmod 1 << 32
249
+
250
+ [type].pack('V') + [low, high].pack('V2')
251
+ end