ricardoo27-writeexcel 0.6.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. data/.document +5 -0
  2. data/.gitattributes +1 -0
  3. data/README.rdoc +136 -0
  4. data/Rakefile +52 -0
  5. data/VERSION +1 -0
  6. data/charts/chartex.rb +316 -0
  7. data/charts/demo1.rb +46 -0
  8. data/charts/demo101.bin +0 -0
  9. data/charts/demo2.rb +65 -0
  10. data/charts/demo201.bin +0 -0
  11. data/charts/demo3.rb +117 -0
  12. data/charts/demo301.bin +0 -0
  13. data/charts/demo4.rb +119 -0
  14. data/charts/demo401.bin +0 -0
  15. data/charts/demo5.rb +48 -0
  16. data/charts/demo501.bin +0 -0
  17. data/examples/a_simple.rb +43 -0
  18. data/examples/autofilter.rb +265 -0
  19. data/examples/bigfile.rb +30 -0
  20. data/examples/chart_area.rb +121 -0
  21. data/examples/chart_bar.rb +120 -0
  22. data/examples/chart_column.rb +120 -0
  23. data/examples/chart_line.rb +120 -0
  24. data/examples/chart_pie.rb +108 -0
  25. data/examples/chart_scatter.rb +121 -0
  26. data/examples/chart_stock.rb +148 -0
  27. data/examples/chess.rb +142 -0
  28. data/examples/colors.rb +129 -0
  29. data/examples/comments1.rb +27 -0
  30. data/examples/comments2.rb +352 -0
  31. data/examples/copyformat.rb +52 -0
  32. data/examples/data_validate.rb +279 -0
  33. data/examples/date_time.rb +87 -0
  34. data/examples/defined_name.rb +32 -0
  35. data/examples/demo.rb +124 -0
  36. data/examples/diag_border.rb +36 -0
  37. data/examples/formats.rb +490 -0
  38. data/examples/formula_result.rb +30 -0
  39. data/examples/header.rb +137 -0
  40. data/examples/hide_sheet.rb +29 -0
  41. data/examples/hyperlink.rb +43 -0
  42. data/examples/images.rb +63 -0
  43. data/examples/indent.rb +31 -0
  44. data/examples/merge1.rb +40 -0
  45. data/examples/merge2.rb +45 -0
  46. data/examples/merge3.rb +66 -0
  47. data/examples/merge4.rb +83 -0
  48. data/examples/merge5.rb +80 -0
  49. data/examples/merge6.rb +67 -0
  50. data/examples/outline.rb +255 -0
  51. data/examples/outline_collapsed.rb +209 -0
  52. data/examples/panes.rb +113 -0
  53. data/examples/password_protection.rb +33 -0
  54. data/examples/properties.rb +34 -0
  55. data/examples/properties_jp.rb +33 -0
  56. data/examples/protection.rb +47 -0
  57. data/examples/regions.rb +53 -0
  58. data/examples/repeat.rb +43 -0
  59. data/examples/republic.png +0 -0
  60. data/examples/right_to_left.rb +27 -0
  61. data/examples/row_wrap.rb +53 -0
  62. data/examples/set_first_sheet.rb +14 -0
  63. data/examples/stats.rb +74 -0
  64. data/examples/stocks.rb +81 -0
  65. data/examples/store_formula.rb +15 -0
  66. data/examples/tab_colors.rb +31 -0
  67. data/examples/utf8.rb +15 -0
  68. data/examples/write_arrays.rb +83 -0
  69. data/html/en/doc_en.html +5946 -0
  70. data/html/images/a_simple.jpg +0 -0
  71. data/html/images/area1.jpg +0 -0
  72. data/html/images/bar1.jpg +0 -0
  73. data/html/images/chart_area.xls +0 -0
  74. data/html/images/column1.jpg +0 -0
  75. data/html/images/data_validation.jpg +0 -0
  76. data/html/images/line1.jpg +0 -0
  77. data/html/images/pie1.jpg +0 -0
  78. data/html/images/regions.jpg +0 -0
  79. data/html/images/scatter1.jpg +0 -0
  80. data/html/images/stats.jpg +0 -0
  81. data/html/images/stock1.jpg +0 -0
  82. data/html/images/stocks.jpg +0 -0
  83. data/html/index.html +16 -0
  84. data/html/style.css +433 -0
  85. data/lib/writeexcel.rb +1159 -0
  86. data/lib/writeexcel/biffwriter.rb +223 -0
  87. data/lib/writeexcel/caller_info.rb +12 -0
  88. data/lib/writeexcel/cell_range.rb +332 -0
  89. data/lib/writeexcel/chart.rb +1968 -0
  90. data/lib/writeexcel/charts/area.rb +154 -0
  91. data/lib/writeexcel/charts/bar.rb +177 -0
  92. data/lib/writeexcel/charts/column.rb +156 -0
  93. data/lib/writeexcel/charts/external.rb +66 -0
  94. data/lib/writeexcel/charts/line.rb +154 -0
  95. data/lib/writeexcel/charts/pie.rb +169 -0
  96. data/lib/writeexcel/charts/scatter.rb +192 -0
  97. data/lib/writeexcel/charts/stock.rb +213 -0
  98. data/lib/writeexcel/col_info.rb +87 -0
  99. data/lib/writeexcel/colors.rb +68 -0
  100. data/lib/writeexcel/comments.rb +460 -0
  101. data/lib/writeexcel/compatibility.rb +65 -0
  102. data/lib/writeexcel/convert_date_time.rb +117 -0
  103. data/lib/writeexcel/data_validations.rb +370 -0
  104. data/lib/writeexcel/debug_info.rb +41 -0
  105. data/lib/writeexcel/embedded_chart.rb +35 -0
  106. data/lib/writeexcel/excelformula.y +139 -0
  107. data/lib/writeexcel/excelformulaparser.rb +587 -0
  108. data/lib/writeexcel/format.rb +1575 -0
  109. data/lib/writeexcel/formula.rb +987 -0
  110. data/lib/writeexcel/helper.rb +78 -0
  111. data/lib/writeexcel/image.rb +218 -0
  112. data/lib/writeexcel/olewriter.rb +305 -0
  113. data/lib/writeexcel/outline.rb +24 -0
  114. data/lib/writeexcel/properties.rb +242 -0
  115. data/lib/writeexcel/shared_string_table.rb +153 -0
  116. data/lib/writeexcel/storage_lite.rb +984 -0
  117. data/lib/writeexcel/workbook.rb +2478 -0
  118. data/lib/writeexcel/worksheet.rb +6925 -0
  119. data/lib/writeexcel/worksheets.rb +25 -0
  120. data/lib/writeexcel/write_file.rb +63 -0
  121. data/test/excelfile/Chart1.xls +0 -0
  122. data/test/excelfile/Chart2.xls +0 -0
  123. data/test/excelfile/Chart3.xls +0 -0
  124. data/test/excelfile/Chart4.xls +0 -0
  125. data/test/excelfile/Chart5.xls +0 -0
  126. data/test/helper.rb +31 -0
  127. data/test/perl_output/Chart1.xls.data +0 -0
  128. data/test/perl_output/Chart2.xls.data +0 -0
  129. data/test/perl_output/Chart3.xls.data +0 -0
  130. data/test/perl_output/Chart4.xls.data +0 -0
  131. data/test/perl_output/Chart5.xls.data +0 -0
  132. data/test/perl_output/README +31 -0
  133. data/test/perl_output/a_simple.xls +0 -0
  134. data/test/perl_output/autofilter.xls +0 -0
  135. data/test/perl_output/biff_add_continue_testdata +0 -0
  136. data/test/perl_output/chart_area.xls +0 -0
  137. data/test/perl_output/chart_bar.xls +0 -0
  138. data/test/perl_output/chart_column.xls +0 -0
  139. data/test/perl_output/chart_line.xls +0 -0
  140. data/test/perl_output/chess.xls +0 -0
  141. data/test/perl_output/colors.xls +0 -0
  142. data/test/perl_output/comments0.xls +0 -0
  143. data/test/perl_output/comments1.xls +0 -0
  144. data/test/perl_output/comments2.xls +0 -0
  145. data/test/perl_output/data_validate.xls +0 -0
  146. data/test/perl_output/date_time.xls +0 -0
  147. data/test/perl_output/defined_name.xls +0 -0
  148. data/test/perl_output/demo.xls +0 -0
  149. data/test/perl_output/demo101.bin +0 -0
  150. data/test/perl_output/demo201.bin +0 -0
  151. data/test/perl_output/demo301.bin +0 -0
  152. data/test/perl_output/demo401.bin +0 -0
  153. data/test/perl_output/demo501.bin +0 -0
  154. data/test/perl_output/diag_border.xls +0 -0
  155. data/test/perl_output/f_font_biff +0 -0
  156. data/test/perl_output/f_font_key +1 -0
  157. data/test/perl_output/f_xf_biff +0 -0
  158. data/test/perl_output/file_font_biff +0 -0
  159. data/test/perl_output/file_font_key +1 -0
  160. data/test/perl_output/file_xf_biff +0 -0
  161. data/test/perl_output/formula_result.xls +0 -0
  162. data/test/perl_output/headers.xls +0 -0
  163. data/test/perl_output/hidden.xls +0 -0
  164. data/test/perl_output/hide_zero.xls +0 -0
  165. data/test/perl_output/hyperlink.xls +0 -0
  166. data/test/perl_output/images.xls +0 -0
  167. data/test/perl_output/indent.xls +0 -0
  168. data/test/perl_output/merge1.xls +0 -0
  169. data/test/perl_output/merge2.xls +0 -0
  170. data/test/perl_output/merge3.xls +0 -0
  171. data/test/perl_output/merge4.xls +0 -0
  172. data/test/perl_output/merge5.xls +0 -0
  173. data/test/perl_output/merge6.xls +0 -0
  174. data/test/perl_output/ole_write_header +0 -0
  175. data/test/perl_output/outline.xls +0 -0
  176. data/test/perl_output/outline_collapsed.xls +0 -0
  177. data/test/perl_output/panes.xls +0 -0
  178. data/test/perl_output/password_protection.xls +0 -0
  179. data/test/perl_output/protection.xls +0 -0
  180. data/test/perl_output/regions.xls +0 -0
  181. data/test/perl_output/right_to_left.xls +0 -0
  182. data/test/perl_output/set_first_sheet.xls +0 -0
  183. data/test/perl_output/stats.xls +0 -0
  184. data/test/perl_output/stocks.xls +0 -0
  185. data/test/perl_output/store_formula.xls +0 -0
  186. data/test/perl_output/tab_colors.xls +0 -0
  187. data/test/perl_output/unicode_cyrillic.xls +0 -0
  188. data/test/perl_output/utf8.xls +0 -0
  189. data/test/perl_output/workbook1.xls +0 -0
  190. data/test/perl_output/workbook2.xls +0 -0
  191. data/test/perl_output/ws_colinfo +1 -0
  192. data/test/perl_output/ws_store_colinfo +0 -0
  193. data/test/perl_output/ws_store_dimensions +0 -0
  194. data/test/perl_output/ws_store_filtermode +0 -0
  195. data/test/perl_output/ws_store_filtermode_off +0 -0
  196. data/test/perl_output/ws_store_filtermode_on +0 -0
  197. data/test/perl_output/ws_store_selection +0 -0
  198. data/test/perl_output/ws_store_window2 +1 -0
  199. data/test/republic.png +0 -0
  200. data/test/test_00_IEEE_double.rb +13 -0
  201. data/test/test_01_add_worksheet.rb +10 -0
  202. data/test/test_02_merge_formats.rb +49 -0
  203. data/test/test_04_dimensions.rb +388 -0
  204. data/test/test_05_rows.rb +175 -0
  205. data/test/test_06_extsst.rb +74 -0
  206. data/test/test_11_date_time.rb +475 -0
  207. data/test/test_12_date_only.rb +525 -0
  208. data/test/test_13_date_seconds.rb +477 -0
  209. data/test/test_21_escher.rb +624 -0
  210. data/test/test_22_mso_drawing_group.rb +741 -0
  211. data/test/test_23_note.rb +57 -0
  212. data/test/test_24_txo.rb +74 -0
  213. data/test/test_25_position_object.rb +80 -0
  214. data/test/test_26_autofilter.rb +309 -0
  215. data/test/test_27_autofilter.rb +126 -0
  216. data/test/test_28_autofilter.rb +156 -0
  217. data/test/test_29_process_jpg.rb +670 -0
  218. data/test/test_30_validation_dval.rb +74 -0
  219. data/test/test_31_validation_dv_strings.rb +123 -0
  220. data/test/test_32_validation_dv_formula.rb +203 -0
  221. data/test/test_40_property_types.rb +188 -0
  222. data/test/test_41_properties.rb +235 -0
  223. data/test/test_42_set_properties.rb +434 -0
  224. data/test/test_50_name_stored.rb +295 -0
  225. data/test/test_51_name_print_area.rb +353 -0
  226. data/test/test_52_name_print_titles.rb +450 -0
  227. data/test/test_53_autofilter.rb +199 -0
  228. data/test/test_60_chart_generic.rb +574 -0
  229. data/test/test_61_chart_subclasses.rb +84 -0
  230. data/test/test_62_chart_formats.rb +268 -0
  231. data/test/test_63_chart_area_formats.rb +645 -0
  232. data/test/test_biff.rb +71 -0
  233. data/test/test_big_workbook.rb +17 -0
  234. data/test/test_compatibility.rb +12 -0
  235. data/test/test_example_match.rb +3246 -0
  236. data/test/test_format.rb +1189 -0
  237. data/test/test_formula.rb +61 -0
  238. data/test/test_ole.rb +102 -0
  239. data/test/test_storage_lite.rb +116 -0
  240. data/test/test_workbook.rb +146 -0
  241. data/test/test_worksheet.rb +106 -0
  242. data/utils/add_magic_comment.rb +80 -0
  243. data/writeexcel.gemspec +278 -0
  244. data/writeexcel.rdoc +1425 -0
  245. metadata +292 -0
@@ -0,0 +1,1968 @@
1
+ # -*- coding: utf-8 -*-
2
+ ###############################################################################
3
+ #
4
+ # Chart - A writer class for Excel Charts.
5
+ #
6
+ #
7
+ # Used in conjunction with WriteExcel
8
+ #
9
+ # Copyright 2000-2010, John McNamara, jmcnamara@cpan.org
10
+ #
11
+ # original written in Perl by John McNamara
12
+ # converted to Ruby by Hideo Nakamura, cxn03651@msj.biglobe.ne.jp
13
+ #
14
+
15
+ require 'writeexcel/worksheet'
16
+ require 'writeexcel/colors'
17
+
18
+ ###############################################################################
19
+ #
20
+ # Formatting information.
21
+ #
22
+ # perltidy with options: -mbl=2 -pt=0 -nola
23
+ #
24
+ # Any camel case Hungarian notation style variable names in the BIFF record
25
+ # writing sub-routines below are for similarity with names used in the Excel
26
+ # documentation. Otherwise lowercase underscore style names are used.
27
+ #
28
+
29
+
30
+ ###############################################################################
31
+ #
32
+ # The chart class hierarchy is as follows. Chart.pm acts as a factory for the
33
+ # sub-classes.
34
+ #
35
+ #
36
+ # BIFFwriter
37
+ # ^
38
+ # |
39
+ # Writeexcel::Worksheet
40
+ # ^
41
+ # |
42
+ # Writeexcel::Chart
43
+ # ^
44
+ # |
45
+ # Writeexcel::Chart::* (sub-types)
46
+ #
47
+
48
+ #
49
+ # = Chart
50
+ # Chart - A writer class for Excel Charts.
51
+ #
52
+ module Writeexcel
53
+
54
+ class Chart < Worksheet
55
+ require 'writeexcel/helper'
56
+
57
+ #
58
+ # Factory method for returning chart objects based on their class type.
59
+ #
60
+ def self.factory(type, *args) #:nodoc:
61
+ klass =
62
+ case type
63
+ when 'Chart::Column'
64
+ Chart::Column
65
+ when 'Chart::Bar'
66
+ Chart::Bar
67
+ when 'Chart::Line'
68
+ Chart::Line
69
+ when 'Chart::Area'
70
+ Chart::Area
71
+ when 'Chart::Pie'
72
+ Chart::Pie
73
+ when 'Chart::Scatter'
74
+ Chart::Scatter
75
+ when 'Chart::Stock'
76
+ Chart::Stock
77
+ end
78
+
79
+ klass.new(*args)
80
+ end
81
+
82
+ #
83
+ # :call-seq:
84
+ # new(filename, name, index, encoding, activesheet, firstsheet, external_bin = nil)
85
+ #
86
+ # Default constructor for sub-classes.
87
+ #
88
+ def initialize(*args) #:nodoc:
89
+ super
90
+
91
+ @type = 0x0200
92
+ @orientation = 0x0
93
+ @series = []
94
+ @embedded = false
95
+
96
+ @external_bin = false
97
+ @x_axis_formula = nil
98
+ @x_axis_name = nil
99
+ @y_axis_formula = nil
100
+ @y_axis_name = nil
101
+ @title_name = nil
102
+ @title_formula = nil
103
+ @vary_data_color = 0
104
+ set_default_properties
105
+ set_default_config_data
106
+ end
107
+
108
+ #
109
+ # Add a series and it's properties to a chart.
110
+ #
111
+ # In an Excel chart a "series" is a collection of information such as values,
112
+ # x-axis labels and the name that define which data is plotted. These
113
+ # settings are displayed when you select the Chart -> Source Data... menu
114
+ # option.
115
+ #
116
+ # With a WriteExcel chart object the add_series() method is used to set the
117
+ # properties for a series:
118
+ #
119
+ # chart.add_series(
120
+ # :categories => '=Sheet1!$A$2:$A$10',
121
+ # :values => '=Sheet1!$B$2:$B$10',
122
+ # :name => 'Series name',
123
+ # :name_formula => '=Sheet1!$B$1'
124
+ # )
125
+ #
126
+ # The properties that can be set are:
127
+ #
128
+ # :values (required)
129
+ # :categories (optional for most chart types)
130
+ # :name (optional)
131
+ # :name_formula (optional)
132
+ #
133
+ # * :values
134
+ #
135
+ # This is the most important property of a series and must be set for
136
+ # every chart object. It links the chart with the worksheet data that
137
+ # it displays.
138
+ #
139
+ # chart.add_series(:values => '=Sheet1!$B$2:$B$10')
140
+ #
141
+ # Note the format that should be used for the formula. It is the same
142
+ # as is used in Excel. You must also add the worksheet that you are
143
+ # referring to before you link to it, via the workbook
144
+ # add_worksheet() method.
145
+ #
146
+ # * :categories
147
+ #
148
+ # This sets the chart category labels. The category is more or less
149
+ # the same as the X-axis. In most chart types the categories property
150
+ # is optional and the chart will just assume a sequential series
151
+ # from 1 .. n.
152
+ #
153
+ # chart.add_series(
154
+ # :categories => '=Sheet1!$A$2:$A$10',
155
+ # :values => '=Sheet1!$B$2:$B$10'
156
+ # )
157
+ #
158
+ # * :name
159
+ #
160
+ # Set the name for the series. The name is displayed in the chart
161
+ # legend and in the formula bar. The name property is optional and
162
+ # if it isn't supplied will default to Series 1 .. n.
163
+ #
164
+ # chart.add_series(
165
+ # ...
166
+ # :name => 'Series name'
167
+ # )
168
+ #
169
+ # * :name_formula
170
+ #
171
+ # Optional, can be used to link the name to a worksheet cell.
172
+ # See "Chart names and links".
173
+ #
174
+ # chart.add_series(
175
+ # ...
176
+ # :name => 'Series name',
177
+ # :name_formula => '=Sheet1!$B$1'
178
+ # )
179
+ #
180
+ # You can add more than one series to a chart. The series numbering and
181
+ # order in the final chart is the same as the order in which that are added.
182
+ #
183
+ # # Add the first series.
184
+ # chart.add_series(
185
+ # :categories => '=Sheet1!$A$2:$A$7',
186
+ # :values => '=Sheet1!$B$2:$B$7',
187
+ # :name => 'Test data series 1'
188
+ # )
189
+ #
190
+ # # Add another series. Category is the same but values are different.
191
+ # chart.add_series(
192
+ # :categories => '=Sheet1!$A$2:$A$7',
193
+ # :values => '=Sheet1!$C$2:$C$7',
194
+ # :name => 'Test data series 2'
195
+ # )
196
+ #
197
+ def add_series(params)
198
+ raise "Must specify 'values' in add_series()" if params[:values].nil?
199
+
200
+ # Parse the ranges to validate them and extract salient information.
201
+ value_data = parse_series_formula(params[:values])
202
+ category_data = parse_series_formula(params[:categories])
203
+ name_formula = parse_series_formula(params[:name_formula])
204
+
205
+ # Default category count to the same as the value count if not defined.
206
+ category_data[1] = value_data[1] if category_data.size < 2
207
+
208
+ # Add the parsed data to the user supplied data.
209
+ params[:values] = value_data
210
+ params[:categories] = category_data
211
+ params[:name_formula] = name_formula
212
+
213
+ # Encode the Series name.
214
+ name, encoding = encode_utf16(params[:name], params[:name_encoding])
215
+
216
+ params[:name] = name
217
+ params[:name_encoding] = encoding
218
+
219
+ @series << params
220
+ end
221
+
222
+ #
223
+ # Set the properties of the X-axis.
224
+ #
225
+ # The set_x_axis() method is used to set properties of the X axis.
226
+ #
227
+ # chart.set_x_axis(:name => 'Sample length (m)' )
228
+ #
229
+ # The properties that can be set are:
230
+ #
231
+ # :name (optional)
232
+ # :name_formula (optional)
233
+ #
234
+ # * :name
235
+ #
236
+ # Set the name (title or caption) for the axis. The name is displayed
237
+ # below the X axis. This property is optional. The default is to have
238
+ # no axis name.
239
+ #
240
+ # chart.set_x_axis( :name => 'Sample length (m)' )
241
+ #
242
+ # * :name_formula
243
+ #
244
+ # Optional, can be used to link the name to a worksheet cell.
245
+ # See "Chart names and links".
246
+ #
247
+ # chart.set_x_axis(
248
+ # :name => 'Sample length (m)',
249
+ # :name_formula => '=Sheet1!$A$1'
250
+ # )
251
+ #
252
+ # Additional axis properties such as range, divisions and ticks will be made
253
+ # available in later releases.
254
+ def set_x_axis(params)
255
+ name, encoding = encode_utf16(params[:name], params[:name_encoding])
256
+ formula = parse_series_formula(params[:name_formula])
257
+
258
+ @x_axis_name = name
259
+ @x_axis_encoding = encoding
260
+ @x_axis_formula = formula
261
+ end
262
+
263
+ #
264
+ # Set the properties of the Y-axis.
265
+ #
266
+ # The set_y_axis() method is used to set properties of the Y axis.
267
+ #
268
+ # chart.set_y_axis(:name => 'Sample weight (kg)' )
269
+ #
270
+ # The properties that can be set are:
271
+ #
272
+ # :name (optional)
273
+ # :name_formula (optional)
274
+ #
275
+ # * :name
276
+ #
277
+ # Set the name (title or caption) for the axis. The name is displayed
278
+ # to the left of the Y axis. This property is optional. The default
279
+ # is to have no axis name.
280
+ #
281
+ # chart.set_y_axis(:name => 'Sample weight (kg)' )
282
+ #
283
+ # * :name_formula
284
+ #
285
+ # Optional, can be used to link the name to a worksheet cell.
286
+ # See "Chart names and links".
287
+ #
288
+ # chart.set_y_axis(
289
+ # :name => 'Sample weight (kg)',
290
+ # :name_formula => '=Sheet1!$B$1'
291
+ # )
292
+ #
293
+ # Additional axis properties such as range, divisions and ticks will be made
294
+ # available in later releases.
295
+ #
296
+ def set_y_axis(params)
297
+ name, encoding = encode_utf16(params[:name], params[:name_encoding])
298
+ formula = parse_series_formula(params[:name_formula])
299
+
300
+ @y_axis_name = name
301
+ @y_axis_encoding = encoding
302
+ @y_axis_formula = formula
303
+ end
304
+
305
+ #
306
+ # The set_title() method is used to set properties of the chart title.
307
+ #
308
+ # chart.set_title(:name => 'Year End Results')
309
+ #
310
+ # The properties that can be set are:
311
+ #
312
+ # :name (optional)
313
+ # :name_formula (optional)
314
+ #
315
+ # * :name
316
+ #
317
+ # Set the name (title) for the chart. The name is displayed above the
318
+ # chart. This property is optional. The default is to have no chart
319
+ # title.
320
+ #
321
+ # chart.set_title(:name => 'Year End Results')
322
+ #
323
+ # * :name_formula
324
+ #
325
+ # Optional, can be used to link the name to a worksheet cell.
326
+ # See "Chart names and links".
327
+ #
328
+ # chart.set_title(
329
+ # :name => 'Year End Results',
330
+ # :name_formula => '=Sheet1!$C$1'
331
+ # )
332
+ #
333
+ def set_title(params)
334
+ name, encoding = encode_utf16( params[:name], params[:name_encoding])
335
+
336
+ formula = parse_series_formula(params[:name_formula])
337
+
338
+ @title_name = name
339
+ @title_encoding = encoding
340
+ @title_formula = formula
341
+ end
342
+
343
+ #
344
+ # Set the properties of the chart legend.
345
+ #
346
+ def set_legend(params = {})
347
+ if params.has_key?(:position)
348
+ if params[:position].downcase == 'none'
349
+ legend[:visible] = 0
350
+ end
351
+ end
352
+ end
353
+
354
+ #
355
+ # Set the properties of the chart plotarea.
356
+ #
357
+ def set_plotarea(params = {})
358
+ return if params.empty?
359
+
360
+ area = @plotarea
361
+
362
+ # Set the plotarea visibility.
363
+ if params.has_key?(:visible)
364
+ area[:visible] = params[:visible]
365
+ return if area[:visible] == 0
366
+ end
367
+
368
+ # TODO. could move this out of if statement.
369
+ area[:bg_color_index] = 0x08
370
+
371
+ # Set the chart background colour.
372
+ if params.has_key?(:color)
373
+ index, rgb = get_color_indices(params[:color])
374
+ if !index.nil?
375
+ area[:fg_color_index] = index
376
+ area[:fg_color_rgb] = rgb
377
+ area[:bg_color_index] = 0x08
378
+ area[:bg_color_rgb] = 0x000000
379
+ end
380
+ end
381
+
382
+ # Set the border line colour.
383
+ if params.has_key?(:line_color)
384
+ index, rgb = get_color_indices(params[:line_color])
385
+ if !index.nil?
386
+ area[:line_color_index] = index
387
+ area[:line_color_rgb] = rgb
388
+ end
389
+ end
390
+
391
+ # Set the border line pattern.
392
+ if params.has_key?(:line_pattern)
393
+ pattern = get_line_pattern(params[:line_pattern])
394
+ area[:line_pattern] = pattern
395
+ end
396
+
397
+ # Set the border line weight.
398
+ if params.has_key?(:line_weight)
399
+ weight = get_line_weight(params[:line_weight])
400
+ area[:line_weight] = weight
401
+ end
402
+ end
403
+
404
+ #
405
+ # Set the properties of the chart chartarea.
406
+ #
407
+ def set_chartarea(params = {})
408
+ return if params.empty?
409
+
410
+ area = @chartarea
411
+
412
+ # Embedded automatic line weight has a different default value.
413
+ area[:line_weight] = 0xFFFF if @embedded
414
+
415
+ # Set the chart background colour.
416
+ if params.has_key?(:color)
417
+ index, rgb = get_color_indices(params[:color])
418
+ if !index.nil?
419
+ area[:fg_color_index] = index
420
+ area[:fg_color_rgb] = rgb
421
+ area[:bg_color_index] = 0x08
422
+ area[:bg_color_rgb] = 0x000000
423
+ area[:area_pattern] = 1
424
+ area[:area_options] = 0x0000 if @embedded
425
+ area[:visible] = 1
426
+ end
427
+ end
428
+
429
+ # Set the border line colour.
430
+ if params.has_key?(:line_color)
431
+ index, rgb = get_color_indices(params[:line_color])
432
+ if !index.nil?
433
+ area[:line_color_index] = index
434
+ area[:line_color_rgb] = rgb
435
+ area[:line_pattern] = 0x00
436
+ area[:line_options] = 0x0000
437
+ area[:visible] = 1
438
+ end
439
+ end
440
+
441
+ # Set the border line pattern.
442
+ if params.has_key?(:line_pattern)
443
+ pattern = get_line_pattern(params[:line_pattern])
444
+ area[:line_pattern] = pattern
445
+ area[:line_options] = 0x0000
446
+ area[:line_color_index] = 0x4F unless params.has_key?(:line_color)
447
+ area[:visible] = 1
448
+ end
449
+
450
+ # Set the border line weight.
451
+ if params.has_key?(:line_weight)
452
+ weight = get_line_weight(params[:line_weight])
453
+ area[:line_weight] = weight
454
+ area[:line_options] = 0x0000
455
+ area[:line_pattern] = 0x00 unless params.has_key?(:line_pattern)
456
+ area[:line_color_index] = 0x4F unless params.has_key?(:line_color)
457
+ area[:visible] = 1
458
+ end
459
+ end
460
+
461
+
462
+
463
+ def using_tmpfile=(val) # :nodoc:
464
+ @using_tmpfile = val
465
+ end
466
+
467
+ def data=(val) # :nodoc:
468
+ @data = val
469
+ end
470
+
471
+ def embedded # :nodoc:
472
+ @embedded
473
+ end
474
+
475
+ def embedded=(val) # :nodoc:
476
+ @embedded = val
477
+ end
478
+
479
+ #
480
+ # Setup the default configuration data for an embedded chart.
481
+ #
482
+ def set_embedded_config_data # :nodoc:
483
+ @embedded = true
484
+
485
+ @chartarea = {
486
+ :visible => 1,
487
+ :fg_color_index => 0x4E,
488
+ :fg_color_rgb => 0xFFFFFF,
489
+ :bg_color_index => 0x4D,
490
+ :bg_color_rgb => 0x000000,
491
+ :area_pattern => 0x0001,
492
+ :area_options => 0x0001,
493
+ :line_pattern => 0x0000,
494
+ :line_weight => 0x0000,
495
+ :line_color_index => 0x4D,
496
+ :line_color_rgb => 0x000000,
497
+ :line_options => 0x0009,
498
+ }
499
+
500
+ @config = default_config_data.merge({
501
+ :axisparent => [ 0, 0x01D8, 0x031D, 0x0D79, 0x07E9 ],
502
+ :axisparent_pos => [ 2, 2, 0x010C, 0x0292, 0x0E46, 0x09FD ],
503
+ :chart => [ 0x0000, 0x0000, 0x01847FE8, 0x00F47FE8 ],
504
+ :font_numbers => [ 5, 10, 0x1DC4, 0x1284, 0x0000 ],
505
+ :font_series => [ 6, 10, 0x1DC4, 0x1284, 0x0001 ],
506
+ :font_title => [ 7, 12, 0x1DC4, 0x1284, 0x0000 ],
507
+ :font_axes => [ 8, 10, 0x1DC4, 0x1284, 0x0001 ],
508
+ :legend => [ 0x044E, 0x0E4A, 0x088D, 0x0123, 0x0, 0x1, 0xF ],
509
+ :legend_pos => [ 5, 2, 0x044E, 0x0E4A, 0, 0 ],
510
+ :legend_text => [ 0xFFFFFFD9, 0xFFFFFFC1, 0, 0, 0x00B1, 0x0000 ],
511
+ :series_text => [ 0xFFFFFFD9, 0xFFFFFFC1, 0, 0, 0x00B1, 0x1020 ],
512
+ :title_text => [ 0x060F, 0x004C, 0x038A, 0x016F, 0x0081, 0x1030 ],
513
+ :x_axis_text => [ 0x07EF, 0x0C8F, 0x153, 0x123, 0x81, 0x00 ],
514
+ :y_axis_text => [ 0x0057, 0x0564, 0xB5, 0x035D, 0x0281, 0x00, 90 ],
515
+ })
516
+ end
517
+
518
+ #
519
+ # Create and store the Chart data structures.
520
+ #
521
+ def close # :nodoc:
522
+ # Ignore any data that has been written so far since it is probably
523
+ # from unwanted Worksheet method calls.
524
+ @data = ''
525
+
526
+ # TODO. Check for charts without a series?
527
+
528
+ # Store the chart BOF.
529
+ store_bof(0x0020)
530
+
531
+ # Store the page header
532
+ store_header
533
+
534
+ # Store the page footer
535
+ store_footer
536
+
537
+ # Store the page horizontal centering
538
+ store_hcenter
539
+
540
+ # Store the page vertical centering
541
+ store_vcenter
542
+
543
+ # Store the left margin
544
+ store_margin_left
545
+
546
+ # Store the right margin
547
+ store_margin_right
548
+
549
+ # Store the top margin
550
+ store_margin_top
551
+
552
+ # Store the bottom margin
553
+ store_margin_bottom
554
+
555
+ # Store the page setup
556
+ store_setup
557
+
558
+ # Store the sheet password
559
+ store_password
560
+
561
+ # Start of Chart specific records.
562
+
563
+ # Store the FBI font records.
564
+ store_fbi(*@config[:font_numbers])
565
+ store_fbi(*@config[:font_series])
566
+ store_fbi(*@config[:font_title])
567
+ store_fbi(*@config[:font_axes])
568
+
569
+ # Ignore UNITS record.
570
+
571
+ # Store the Chart sub-stream.
572
+ store_chart_stream
573
+
574
+ # Append the sheet dimensions
575
+ store_dimensions
576
+
577
+ # TODO add SINDEX and NUMBER records.
578
+
579
+ store_window2 unless @embedded
580
+
581
+ store_eof
582
+ end
583
+
584
+ private
585
+
586
+ #
587
+ # The parent Worksheet class needs to store some data in memory and some in
588
+ # temporary files for efficiency. The Chart* classes don't need to do this
589
+ # since they are dealing with smaller amounts of data so we override
590
+ # _prepend() to turn it into an _append() method. This allows for a more
591
+ # natural method calling order.
592
+ #
593
+ def prepend(*args) # :nodoc:
594
+ @using_tmpfile = false
595
+ append(*args)
596
+ end
597
+
598
+
599
+ #
600
+ # Write BIFF record Window2. Note, this overrides the parent Worksheet
601
+ # record because the Chart version of the record is smaller and is used
602
+ # mainly to indicate if the chart tab is selected or not.
603
+ #
604
+ def store_window2 # :nodoc:
605
+ record = 0x023E # Record identifier
606
+ length = 0x000A # Number of bytes to follow
607
+ grbit = 0x0000 # Option flags
608
+ rwTop = 0x0000 # Top visible row
609
+ colLeft = 0x0000 # Leftmost visible column
610
+ rgbHdr = 0x0000 # Row/col heading, grid color
611
+
612
+ # The options flags that comprise grbit
613
+ fDspFmla = 0 # 0 - bit
614
+ fDspGrid = 0 # 1
615
+ fDspRwCol = 0 # 2
616
+ fFrozen = 0 # 3
617
+ fDspZeros = 0 # 4
618
+ fDefaultHdr = 0 # 5
619
+ fArabic = 0 # 6
620
+ fDspGuts = 0 # 7
621
+ fFrozenNoSplit = 0 # 0 - bit
622
+ fSelected = selected? ? 1 : 0 # 1
623
+ fPaged = 0 # 2
624
+ fBreakPreview = 0 # 3
625
+
626
+ #<<< Perltidy ignore this.
627
+ grbit = fDspFmla
628
+ grbit |= fDspGrid << 1
629
+ grbit |= fDspRwCol << 2
630
+ grbit |= fFrozen << 3
631
+ grbit |= fDspZeros << 4
632
+ grbit |= fDefaultHdr << 5
633
+ grbit |= fArabic << 6
634
+ grbit |= fDspGuts << 7
635
+ grbit |= fFrozenNoSplit << 8
636
+ grbit |= fSelected << 9
637
+ grbit |= fPaged << 10
638
+ grbit |= fBreakPreview << 11
639
+ #>>>
640
+
641
+ header = [record, length].pack("vv")
642
+ data = [grbit, rwTop, colLeft, rgbHdr].pack("vvvV")
643
+
644
+ append(header, data)
645
+ end
646
+
647
+ #
648
+ # Parse the formula used to define a series. We also extract some range
649
+ # information required for _store_series() and the SERIES record.
650
+ #
651
+ def parse_series_formula(formula) # :nodoc:
652
+ encoding = 0
653
+ length = 0
654
+ count = 0
655
+ tokens = []
656
+
657
+ return [''] if formula.nil?
658
+
659
+ # Strip the = sign at the beginning of the formula string
660
+ formula = formula.sub(/^=/, '')
661
+
662
+ # In order to raise formula errors from the point of view of the calling
663
+ # program we use an eval block and re-raise the error from here.
664
+ #
665
+ tokens = parser.parse_formula(formula)
666
+
667
+ # Force ranges to be a reference class.
668
+ tokens.collect! { |t| t.gsub(/_ref3d/, '_ref3dR') }
669
+ tokens.collect! { |t| t.gsub(/_range3d/, '_range3dR') }
670
+ tokens.collect! { |t| t.gsub(/_name/, '_nameR') }
671
+
672
+ # Parse the tokens into a formula string.
673
+ formula = parser.parse_tokens(tokens)
674
+
675
+ # Return formula for a single cell as used by title and series name.
676
+ return formula if formula.ord == 0x3A
677
+
678
+ # Extract the range from the parse formula.
679
+ if formula.ord == 0x3B
680
+ ptg, ext_ref, row_1, row_2, col_1, col_2 = formula.unpack('Cv5')
681
+
682
+ # TODO. Remove high bit on relative references.
683
+ count = row_2 - row_1 + 1
684
+ end
685
+
686
+ [formula, count]
687
+ end
688
+
689
+ #
690
+ # Convert UTF8 strings used in the chart to UTF16.
691
+ #
692
+ def encode_utf16(str, encoding = 0) # :nodoc:
693
+ # Exit if the $string isn't defined, i.e., hasn't been set by user.
694
+ return [nil, nil] if str.nil?
695
+
696
+ string = str.dup
697
+ # Return if encoding is set, i.e., string has been manually encoded.
698
+ #return ( undef, undef ) if $string == 1;
699
+
700
+ ruby_19 { string = convert_to_ascii_if_ascii(string) }
701
+
702
+ # Handle utf8 strings.
703
+ if is_utf8?(string)
704
+ string = utf8_to_16be(string)
705
+ encoding = 1
706
+ end
707
+
708
+ # Chart strings are limited to 255 characters.
709
+ limit = encoding != 0 ? 255 * 2 : 255
710
+
711
+ if string.bytesize >= limit
712
+ # truncate the string and raise a warning.
713
+ string = string[0, limit]
714
+ end
715
+
716
+ [string, encoding]
717
+ end
718
+
719
+ #
720
+ # Convert the user specified colour index or string to an colour index and
721
+ # RGB colour number.
722
+ #
723
+ def get_color_indices(color) # :nodoc:
724
+ invalid = 0x7FFF # return from Colors#get_color when color is invalid
725
+
726
+ index = Colors.new.get_color(color)
727
+ index = invalid if color.respond_to?(:coerce) && (color < 8 || color > 63)
728
+ if index == invalid
729
+ [nil, nil]
730
+ else
731
+ [index, get_color_rbg(index)]
732
+ end
733
+ end
734
+
735
+ #
736
+ # Get the RedGreenBlue number for the colour index from the Workbook palette.
737
+ #
738
+ def get_color_rbg(index) # :nodoc:
739
+ # Adjust colour index from 8-63 (user range) to 0-55 (Excel range).
740
+ index -= 8
741
+
742
+ red_green_blue = palette[index]
743
+ red_green_blue.pack('C*').unpack('V')[0]
744
+ end
745
+
746
+ def palette
747
+ @workbook.palette
748
+ end
749
+
750
+ #
751
+ # Get the Excel chart index for line pattern that corresponds to the user
752
+ # defined value.
753
+ #
754
+ def get_line_pattern(value) # :nodoc:
755
+ value = value.downcase if value.respond_to?(:to_str)
756
+ default = 0
757
+
758
+ patterns = {
759
+ 0 => 5,
760
+ 1 => 0,
761
+ 2 => 1,
762
+ 3 => 2,
763
+ 4 => 3,
764
+ 5 => 4,
765
+ 6 => 7,
766
+ 7 => 6,
767
+ 8 => 8,
768
+ 'solid' => 0,
769
+ 'dash' => 1,
770
+ 'dot' => 2,
771
+ 'dash-dot' => 3,
772
+ 'dash-dot-dot' => 4,
773
+ 'none' => 5,
774
+ 'dark-gray' => 6,
775
+ 'medium-gray' => 7,
776
+ 'light-gray' => 8,
777
+ }
778
+
779
+ if patterns.has_key?(value)
780
+ patterns[value]
781
+ else
782
+ default
783
+ end
784
+ end
785
+
786
+ #
787
+ # Get the Excel chart index for line weight that corresponds to the user
788
+ # defined value.
789
+ #
790
+ def get_line_weight(value) # :nodoc:
791
+ value = value.downcase if value.respond_to?(:to_str)
792
+ default = 0
793
+
794
+ weights = {
795
+ 1 => -1,
796
+ 2 => 0,
797
+ 3 => 1,
798
+ 4 => 2,
799
+ 'hairline' => -1,
800
+ 'narrow' => 0,
801
+ 'medium' => 1,
802
+ 'wide' => 2,
803
+ }
804
+
805
+ if weights.has_key?(value)
806
+ weights[value]
807
+ else
808
+ default
809
+ end
810
+ end
811
+
812
+ #
813
+ # Store the CHART record and it's substreams.
814
+ #
815
+ def store_chart_stream # :nodoc:
816
+ store_chart(*@config[:chart])
817
+ store_begin
818
+
819
+ # Store the chart SCL record.
820
+ store_plotgrowth
821
+
822
+ if @chartarea[:visible] != 0
823
+ store_chartarea_frame_stream
824
+ end
825
+
826
+ # Store SERIES stream for each series.
827
+ index = 0
828
+ @series.each do |series|
829
+ store_series_stream(
830
+ :index => index,
831
+ :value_formula => series[:values][0],
832
+ :value_count => series[:values][1],
833
+ :category_count => series[:categories][1],
834
+ :category_formula => series[:categories][0],
835
+ :name => series[:name],
836
+ :name_encoding => series[:name_encoding],
837
+ :name_formula => series[:name_formula]
838
+ )
839
+ index += 1
840
+ end
841
+
842
+ store_shtprops
843
+
844
+ # Write the TEXT streams.
845
+ (5..6).each do |font_index|
846
+ store_defaulttext
847
+ store_series_text_stream(font_index)
848
+ end
849
+
850
+ store_axesused(1)
851
+ store_axisparent_stream
852
+
853
+ if !@title_name.nil? || !@title_formula.nil?
854
+ store_title_text_stream
855
+ end
856
+
857
+ store_end
858
+ end
859
+
860
+ def _formula_type_from_param(t, f, params, key) # :nodoc:
861
+ if params.has_key?(key)
862
+ v = params[key]
863
+ (v.nil? || v == [""] || v == '' || v == 0) ? f : t
864
+ end
865
+ end
866
+
867
+ #
868
+ # Write the SERIES chart substream.
869
+ #
870
+ def store_series_stream(params) # :nodoc:
871
+ name_type = _formula_type_from_param(2, 1, params, :name_formula)
872
+ value_type = _formula_type_from_param(2, 0, params, :value_formula)
873
+ category_type = _formula_type_from_param(2, 0, params, :category_formula)
874
+
875
+ store_series(params[:value_count], params[:category_count])
876
+
877
+ store_begin
878
+
879
+ # Store the Series name AI record.
880
+ store_ai(0, name_type, params[:name_formula])
881
+ unless params[:name].nil?
882
+ store_seriestext(params[:name], params[:name_encoding])
883
+ end
884
+
885
+ store_ai(1, value_type, params[:value_formula])
886
+ store_ai(2, category_type, params[:category_formula])
887
+ store_ai(3, 1, '' )
888
+
889
+ store_dataformat_stream(params[:index])
890
+ store_sertocrt
891
+ store_end
892
+ end
893
+
894
+ #
895
+ # Write the DATAFORMAT chart substream.
896
+ #
897
+ def store_dataformat_stream(series_index) # :nodoc:
898
+ store_dataformat(series_index, series_index, 0xFFFF)
899
+
900
+ store_begin
901
+ store_3dbarshape
902
+ store_end
903
+ end
904
+
905
+ #
906
+ # Write the series TEXT substream.
907
+ #
908
+ def store_series_text_stream(font_index) # :nodoc:
909
+ store_text(*@config[:series_text])
910
+
911
+ store_begin
912
+ store_pos(*@config[:series_text_pos])
913
+ store_fontx( font_index )
914
+ store_ai( 0, 1, '' )
915
+ store_end
916
+ end
917
+
918
+ def _formula_type(t, f, formula) # :nodoc:
919
+ (formula.nil? || formula == [""] || formula == '' || formula == 0) ? f : t
920
+ end
921
+
922
+ #
923
+ # Write the X-axis TEXT substream.
924
+ #
925
+ def store_x_axis_text_stream # :nodoc:
926
+ formula = @x_axis_formula.nil? ? '' : @x_axis_formula
927
+ ai_type = _formula_type(2, 1, formula)
928
+
929
+ store_text(*@config[:x_axis_text])
930
+
931
+ store_begin
932
+ store_pos(*@config[:x_axis_text_pos])
933
+ store_fontx(8)
934
+ store_ai(0, ai_type, formula)
935
+
936
+ unless @x_axis_name.nil?
937
+ store_seriestext(@x_axis_name, @x_axis_encoding)
938
+ end
939
+
940
+ store_objectlink(3)
941
+ store_end
942
+ end
943
+
944
+ #
945
+ # Write the Y-axis TEXT substream.
946
+ #
947
+ def store_y_axis_text_stream # :nodoc:
948
+ formula = @y_axis_formula
949
+ ai_type = _formula_type(2, 1, formula)
950
+
951
+ store_text(*@config[:y_axis_text])
952
+
953
+ store_begin
954
+ store_pos(*@config[:y_axis_text_pos])
955
+ store_fontx(8)
956
+ store_ai(0, ai_type, formula)
957
+
958
+ unless @y_axis_name.nil?
959
+ store_seriestext(@y_axis_name, @y_axis_encoding)
960
+ end
961
+
962
+ store_objectlink(2)
963
+ store_end
964
+ end
965
+
966
+ #
967
+ # Write the legend TEXT substream.
968
+ #
969
+ def store_legend_text_stream # :nodoc:
970
+ store_text(*@config[:legend_text])
971
+
972
+ store_begin
973
+ store_pos(*@config[:legend_text_pos])
974
+ store_ai(0, 1, '')
975
+
976
+ store_end
977
+ end
978
+
979
+ #
980
+ # Write the title TEXT substream.
981
+ #
982
+ def store_title_text_stream # :nodoc:
983
+ formula = @title_formula
984
+ ai_type = _formula_type(2, 1, formula)
985
+
986
+ store_text(*@config[:title_text])
987
+
988
+ store_begin
989
+ store_pos(*@config[:title_text_pos])
990
+ store_fontx(7)
991
+ store_ai(0, ai_type, formula)
992
+
993
+ unless @title_name.nil?
994
+ store_seriestext(@title_name, @title_encoding)
995
+ end
996
+
997
+ store_objectlink(1)
998
+ store_end
999
+ end
1000
+
1001
+ #
1002
+ # Write the AXISPARENT chart substream.
1003
+ #
1004
+ def store_axisparent_stream # :nodoc:
1005
+ store_axisparent(*@config[:axisparent])
1006
+
1007
+ store_begin
1008
+ store_pos(*@config[:axisparent_pos])
1009
+ store_axis_category_stream
1010
+ store_axis_values_stream
1011
+
1012
+ if !@x_axis_name.nil? || !@x_axis_formula.nil?
1013
+ store_x_axis_text_stream
1014
+ end
1015
+
1016
+ if !@y_axis_name.nil? || !@y_axis_formula.nil?
1017
+ store_y_axis_text_stream
1018
+ end
1019
+
1020
+ if @plotarea[:visible] != 0
1021
+ store_plotarea
1022
+ store_plotarea_frame_stream
1023
+ end
1024
+ store_chartformat_stream
1025
+ store_end
1026
+ end
1027
+
1028
+ #
1029
+ # Write the AXIS chart substream for the chart category.
1030
+ #
1031
+ def store_axis_category_stream # :nodoc:
1032
+ store_axis(0)
1033
+
1034
+ store_begin
1035
+ store_catserrange
1036
+ store_axcext
1037
+ store_tick
1038
+ store_end
1039
+ end
1040
+
1041
+ #
1042
+ # Write the AXIS chart substream for the chart values.
1043
+ #
1044
+ def store_axis_values_stream # :nodoc:
1045
+ store_axis(1)
1046
+
1047
+ store_begin
1048
+ store_valuerange
1049
+ store_tick
1050
+ store_axislineformat
1051
+ store_lineformat(0x00000000, 0x0000, 0xFFFF, 0x0009, 0x004D)
1052
+ store_end
1053
+ end
1054
+
1055
+ #
1056
+ # Write the FRAME chart substream.
1057
+ #
1058
+ def store_plotarea_frame_stream # :nodoc:
1059
+ store_area_frame_stream_common(:plot)
1060
+ end
1061
+
1062
+ #
1063
+ # Write the FRAME chart substream for and embedded chart.
1064
+ #
1065
+ def store_chartarea_frame_stream # :nodoc:
1066
+ store_area_frame_stream_common(:chart)
1067
+ end
1068
+
1069
+ def store_area_frame_stream_common(type)
1070
+ if type == :plot
1071
+ area = @plotarea
1072
+ grbit = 0x03
1073
+ else
1074
+ area = @chartarea
1075
+ grbit = 0x02
1076
+ end
1077
+
1078
+ store_frame(0x00, grbit)
1079
+ store_begin
1080
+
1081
+ store_lineformat(
1082
+ area[:line_color_rgb], area[:line_pattern],
1083
+ area[:line_weight], area[:line_options],
1084
+ area[:line_color_index]
1085
+ )
1086
+
1087
+ store_areaformat(
1088
+ area[:fg_color_rgb], area[:bg_color_rgb],
1089
+ area[:area_pattern], area[:area_options],
1090
+ area[:fg_color_index], area[:bg_color_index]
1091
+ )
1092
+
1093
+ store_end
1094
+ end
1095
+
1096
+ #
1097
+ # Write the CHARTFORMAT chart substream.
1098
+ #
1099
+ def store_chartformat_stream # :nodoc:
1100
+ # The _vary_data_color is set by classes that need it, like Pie.
1101
+ store_chartformat(@vary_data_color)
1102
+
1103
+ store_begin
1104
+
1105
+ # Store the BIFF record that will define the chart type.
1106
+ store_chart_type
1107
+
1108
+ # Note, the CHARTFORMATLINK record is only written by Excel.
1109
+
1110
+ if @legend[:visible]
1111
+ store_legend_stream
1112
+ end
1113
+
1114
+ store_marker_dataformat_stream
1115
+ store_end
1116
+ end
1117
+
1118
+ #
1119
+ # This is an abstract method that is overridden by the sub-classes to define
1120
+ # the chart types such as Column, Line, Pie, etc.
1121
+ #
1122
+ def store_chart_type # :nodoc:
1123
+
1124
+ end
1125
+
1126
+ #
1127
+ # This is an abstract method that is overridden by the sub-classes to define
1128
+ # properties of markers, linetypes, pie formats and other.
1129
+ #
1130
+ def store_marker_dataformat_stream # :nodoc:
1131
+
1132
+ end
1133
+
1134
+ #
1135
+ # Write the LEGEND chart substream.
1136
+ #
1137
+ def store_legend_stream # :nodoc:
1138
+ store_legend(*@config[:legend])
1139
+
1140
+ store_begin
1141
+ store_pos(*@config[:legend_pos])
1142
+ store_legend_text_stream
1143
+ store_end
1144
+ end
1145
+
1146
+ ###############################################################################
1147
+ #
1148
+ # BIFF Records.
1149
+ #
1150
+ ###############################################################################
1151
+
1152
+ #
1153
+ # Write the 3DBARSHAPE chart BIFF record.
1154
+ #
1155
+ def store_3dbarshape # :nodoc:
1156
+ record = 0x105F # Record identifier.
1157
+ length = 0x0002 # Number of bytes to follow.
1158
+ riser = 0x00 # Shape of base.
1159
+ taper = 0x00 # Column taper type.
1160
+
1161
+ header = [record, length].pack('vv')
1162
+ data = [riser].pack('C')
1163
+ data += [taper].pack('C')
1164
+
1165
+ append(header, data)
1166
+ end
1167
+
1168
+ #
1169
+ # Write the AI chart BIFF record.
1170
+ #
1171
+ def store_ai(id, type, formula, format_index = 0) # :nodoc:
1172
+ formula = '' if formula == [""]
1173
+
1174
+ record = 0x1051 # Record identifier.
1175
+ length = 0x0008 # Number of bytes to follow.
1176
+ # id # Link index.
1177
+ # type # Reference type.
1178
+ # formula # Pre-parsed formula.
1179
+ # format_index # Num format index.
1180
+ grbit = 0x0000 # Option flags.
1181
+
1182
+ ruby_19 { formula = convert_to_ascii_if_ascii(formula) }
1183
+
1184
+ formula_length = formula.bytesize
1185
+ length += formula_length
1186
+
1187
+ header = [record, length].pack('vv')
1188
+ data = [id].pack('C')
1189
+ data += [type].pack('C')
1190
+ data += [grbit].pack('v')
1191
+ data += [format_index].pack('v')
1192
+ data += [formula_length].pack('v')
1193
+ if formula.respond_to?(:to_array)
1194
+ data +=
1195
+ ruby_18 { formula[0] } ||
1196
+ ruby_19 { formula[0].encode('BINARY') }
1197
+ else
1198
+ data +=
1199
+ ruby_18 { formula unless formula.nil? } ||
1200
+ ruby_19 { formula.encode('BINARY') unless formula.nil? }
1201
+ end
1202
+
1203
+ append(header, data)
1204
+ end
1205
+
1206
+ #
1207
+ # Write the AREAFORMAT chart BIFF record. Contains the patterns and colours
1208
+ # of a chart area.
1209
+ #
1210
+ def store_areaformat(rgbFore, rgbBack, pattern, grbit, indexFore, indexBack) # :nodoc:
1211
+ record = 0x100A # Record identifier.
1212
+ length = 0x0010 # Number of bytes to follow.
1213
+ # rgbFore # Foreground RGB colour.
1214
+ # rgbBack # Background RGB colour.
1215
+ # pattern # Pattern.
1216
+ # grbit # Option flags.
1217
+ # indexFore # Index to Foreground colour.
1218
+ # indexBack # Index to Background colour.
1219
+
1220
+ header = [record, length].pack('vv')
1221
+ data = [rgbFore].pack('V')
1222
+ data += [rgbBack].pack('V')
1223
+ data += [pattern].pack('v')
1224
+ data += [grbit].pack('v')
1225
+ data += [indexFore].pack('v')
1226
+ data += [indexBack].pack('v')
1227
+
1228
+ append(header, data)
1229
+ end
1230
+
1231
+ #
1232
+ # Write the AXCEXT chart BIFF record.
1233
+ #
1234
+ def store_axcext # :nodoc:
1235
+ record = 0x1062 # Record identifier.
1236
+ length = 0x0012 # Number of bytes to follow.
1237
+ catMin = 0x0000 # Minimum category on axis.
1238
+ catMax = 0x0000 # Maximum category on axis.
1239
+ catMajor = 0x0001 # Value of major unit.
1240
+ unitMajor = 0x0000 # Units of major unit.
1241
+ catMinor = 0x0001 # Value of minor unit.
1242
+ unitMinor = 0x0000 # Units of minor unit.
1243
+ unitBase = 0x0000 # Base unit of axis.
1244
+ catCrossDate = 0x0000 # Crossing point.
1245
+ grbit = 0x00EF # Option flags.
1246
+
1247
+ store_simple(record, length, catMin, catMax, catMajor, unitMajor,
1248
+ catMinor, unitMinor, unitBase, catCrossDate, grbit)
1249
+ end
1250
+
1251
+ #
1252
+ # Write the AXESUSED chart BIFF record.
1253
+ #
1254
+ def store_axesused(num_axes) # :nodoc:
1255
+ record = 0x1046 # Record identifier.
1256
+ length = 0x0002 # Number of bytes to follow.
1257
+ # num_axes # Number of axes used.
1258
+
1259
+ store_simple(record, length, num_axes)
1260
+ end
1261
+
1262
+ #
1263
+ # Write the AXIS chart BIFF record to define the axis type.
1264
+ #
1265
+ def store_axis(type) # :nodoc:
1266
+ record = 0x101D # Record identifier.
1267
+ length = 0x0012 # Number of bytes to follow.
1268
+ # type # Axis type.
1269
+ reserved1 = 0x00000000 # Reserved.
1270
+ reserved2 = 0x00000000 # Reserved.
1271
+ reserved3 = 0x00000000 # Reserved.
1272
+ reserved4 = 0x00000000 # Reserved.
1273
+
1274
+ header = [record, length].pack('vv')
1275
+ data = [type].pack('v')
1276
+ data += [reserved1].pack('V')
1277
+ data += [reserved2].pack('V')
1278
+ data += [reserved3].pack('V')
1279
+ data += [reserved4].pack('V')
1280
+
1281
+ append(header, data)
1282
+ end
1283
+
1284
+ #
1285
+ # Write the AXISLINEFORMAT chart BIFF record.
1286
+ #
1287
+ def store_axislineformat # :nodoc:
1288
+ record = 0x1021 # Record identifier.
1289
+ length = 0x0002 # Number of bytes to follow.
1290
+ line_format = 0x0001 # Axis line format.
1291
+
1292
+ store_simple(record, length, line_format)
1293
+ end
1294
+
1295
+ #
1296
+ # Write the AXISPARENT chart BIFF record.
1297
+ #
1298
+ def store_axisparent(iax, x, y, dx, dy) # :nodoc:
1299
+ record = 0x1041 # Record identifier.
1300
+ length = 0x0012 # Number of bytes to follow.
1301
+ # iax # Axis index.
1302
+ # x # X-coord.
1303
+ # y # Y-coord.
1304
+ # dx # Length of x axis.
1305
+ # dy # Length of y axis.
1306
+
1307
+ header = [record, length].pack('vv')
1308
+ data = [iax].pack('v')
1309
+ data += [x].pack('V')
1310
+ data += [y].pack('V')
1311
+ data += [dx].pack('V')
1312
+ data += [dy].pack('V')
1313
+
1314
+ append(header, data)
1315
+ end
1316
+
1317
+ #
1318
+ # Write the BEGIN chart BIFF record to indicate the start of a sub stream.
1319
+ #
1320
+ def store_begin # :nodoc:
1321
+ record = 0x1033 # Record identifier.
1322
+ length = 0x0000 # Number of bytes to follow.
1323
+
1324
+ store_simple(record, length)
1325
+ end
1326
+
1327
+ #
1328
+ # Write the CATSERRANGE chart BIFF record.
1329
+ #
1330
+ def store_catserrange # :nodoc:
1331
+ record = 0x1020 # Record identifier.
1332
+ length = 0x0008 # Number of bytes to follow.
1333
+ catCross = 0x0001 # Value/category crossing.
1334
+ catLabel = 0x0001 # Frequency of labels.
1335
+ catMark = 0x0001 # Frequency of ticks.
1336
+ grbit = 0x0001 # Option flags.
1337
+
1338
+ store_simple(record, length, catCross, catLabel, catMark, grbit)
1339
+ end
1340
+
1341
+ #
1342
+ # Write the CHART BIFF record. This indicates the start of the chart sub-stream
1343
+ # and contains dimensions of the chart on the display. Units are in 1/72 inch
1344
+ # and are 2 byte integer with 2 byte fraction.
1345
+ #
1346
+ def store_chart(x_pos, y_pos, dx, dy) # :nodoc:
1347
+ record = 0x1002 # Record identifier.
1348
+ length = 0x0010 # Number of bytes to follow.
1349
+ # x_pos # X pos of top left corner.
1350
+ # y_pos # Y pos of top left corner.
1351
+ # dx # X size.
1352
+ # dy # Y size.
1353
+
1354
+ header = [record, length].pack('vv')
1355
+ data = [x_pos].pack('V')
1356
+ data += [y_pos].pack('V')
1357
+ data += [dx].pack('V')
1358
+ data += [dy].pack('V')
1359
+
1360
+ append(header, data)
1361
+ end
1362
+
1363
+ #
1364
+ # Write the CHARTFORMAT chart BIFF record. The parent record for formatting
1365
+ # of a chart group.
1366
+ #
1367
+ def store_chartformat(grbit = 0) # :nodoc:
1368
+ record = 0x1014 # Record identifier.
1369
+ length = 0x0014 # Number of bytes to follow.
1370
+ reserved1 = 0x00000000 # Reserved.
1371
+ reserved2 = 0x00000000 # Reserved.
1372
+ reserved3 = 0x00000000 # Reserved.
1373
+ reserved4 = 0x00000000 # Reserved.
1374
+ # grbit # Option flags.
1375
+ icrt = 0x0000 # Drawing order.
1376
+
1377
+ header = [record, length].pack('vv')
1378
+ data = [reserved1].pack('V')
1379
+ data += [reserved2].pack('V')
1380
+ data += [reserved3].pack('V')
1381
+ data += [reserved4].pack('V')
1382
+ data += [grbit].pack('v')
1383
+ data += [icrt].pack('v')
1384
+
1385
+ append(header, data)
1386
+ end
1387
+
1388
+ #
1389
+ # Write the CHARTLINE chart BIFF record.
1390
+ #
1391
+ def store_chartline # :nodoc:
1392
+ record = 0x101C # Record identifier.
1393
+ length = 0x0002 # Number of bytes to follow.
1394
+ type = 0x0001 # Drop/hi-lo line type.
1395
+
1396
+ store_simple(record, length, type)
1397
+ end
1398
+
1399
+ #
1400
+ # Write the TEXT chart BIFF record.
1401
+ #
1402
+ def store_charttext # :nodoc:
1403
+ record = 0x1025 # Record identifier.
1404
+ length = 0x0020 # Number of bytes to follow.
1405
+ horz_align = 0x02 # Horizontal alignment.
1406
+ vert_align = 0x02 # Vertical alignment.
1407
+ bg_mode = 0x0001 # Background display.
1408
+ text_color_rgb = 0x00000000 # Text RGB colour.
1409
+ text_x = 0xFFFFFF46 # Text x-pos.
1410
+ text_y = 0xFFFFFF06 # Text y-pos.
1411
+ text_dx = 0x00000000 # Width.
1412
+ text_dy = 0x00000000 # Height.
1413
+ grbit1 = 0x00B1 # Options
1414
+ text_color_index = 0x004D # Auto Colour.
1415
+ grbit2 = 0x0000 # Data label placement.
1416
+ rotation = 0x0000 # Text rotation.
1417
+
1418
+ header = [record, length].pack('vv')
1419
+ data = [horz_align].pack('C')
1420
+ data += [vert_align].pack('C')
1421
+ data += [bg_mode].pack('v')
1422
+ data += [text_color_rgb].pack('V')
1423
+ data += [text_x].pack('V')
1424
+ data += [text_y].pack('V')
1425
+ data += [text_dx].pack('V')
1426
+ data += [text_dy].pack('V')
1427
+ data += [grbit1].pack('v')
1428
+ data += [text_color_index].pack('v')
1429
+ data += [grbit2].pack('v')
1430
+ data += [rotation].pack('v')
1431
+
1432
+ append(header, data)
1433
+ end
1434
+
1435
+ #
1436
+ # Write the DATAFORMAT chart BIFF record. This record specifies the series
1437
+ # that the subsequent sub stream refers to.
1438
+ #
1439
+ def store_dataformat(series_index, series_number, point_number) # :nodoc:
1440
+ record = 0x1006 # Record identifier.
1441
+ length = 0x0008 # Number of bytes to follow.
1442
+ # series_index # Series index.
1443
+ # series_number # Series number. (Same as index).
1444
+ # point_number # Point number.
1445
+ grbit = 0x0000 # Format flags.
1446
+
1447
+ store_simple(record, length, point_number, series_index, series_number, grbit)
1448
+ end
1449
+
1450
+ #
1451
+ # Write the DEFAULTTEXT chart BIFF record. Identifier for subsequent TEXT
1452
+ # record.
1453
+ #
1454
+ def store_defaulttext # :nodoc:
1455
+ record = 0x1024 # Record identifier.
1456
+ length = 0x0002 # Number of bytes to follow.
1457
+ type = 0x0002 # Type.
1458
+
1459
+ store_simple(record, length, type)
1460
+ end
1461
+
1462
+ #
1463
+ # Write the DROPBAR chart BIFF record.
1464
+ #
1465
+ def store_dropbar # :nodoc:
1466
+ record = 0x103D # Record identifier.
1467
+ length = 0x0002 # Number of bytes to follow.
1468
+ percent_gap = 0x0096 # Drop bar width gap (%).
1469
+
1470
+ store_simple(record, length, percent_gap)
1471
+ end
1472
+
1473
+ #
1474
+ # Write the END chart BIFF record to indicate the end of a sub stream.
1475
+ #
1476
+ def store_end # :nodoc:
1477
+ record = 0x1034 # Record identifier.
1478
+ length = 0x0000 # Number of bytes to follow.
1479
+
1480
+ store_simple(record, length)
1481
+ end
1482
+
1483
+ #
1484
+ # Write the FBI chart BIFF record. Specifies the font information at the time
1485
+ # it was applied to the chart.
1486
+ #
1487
+ def store_fbi(index, height, width_basis, height_basis, scale_basis) # :nodoc:
1488
+ record = 0x1060 # Record identifier.
1489
+ length = 0x000A # Number of bytes to follow.
1490
+ # index # Font index.
1491
+ height = height * 20 # Default font height in twips.
1492
+ # width_basis # Width basis, in twips.
1493
+ # height_basis # Height basis, in twips.
1494
+ # scale_basis # Scale by chart area or plot area.
1495
+
1496
+ store_simple(record, length, width_basis, height_basis, height, scale_basis, index)
1497
+ end
1498
+
1499
+ #
1500
+ # Write the FONTX chart BIFF record which contains the index of the FONT
1501
+ # record in the Workbook.
1502
+ #
1503
+ def store_fontx(index) # :nodoc:
1504
+ record = 0x1026 # Record identifier.
1505
+ length = 0x0002 # Number of bytes to follow.
1506
+ # index # Font index.
1507
+
1508
+ store_simple(record, length, index)
1509
+ end
1510
+
1511
+ #
1512
+ # Write the FRAME chart BIFF record.
1513
+ #
1514
+ def store_frame(frame_type, grbit) # :nodoc:
1515
+ record = 0x1032 # Record identifier.
1516
+ length = 0x0004 # Number of bytes to follow.
1517
+ # frame_type # Frame type.
1518
+ # grbit # Option flags.
1519
+
1520
+ store_simple(record, length, frame_type, grbit)
1521
+ end
1522
+
1523
+ #
1524
+ # Write the LEGEND chart BIFF record. The Marcus Horan method.
1525
+ #
1526
+ def store_legend(x, y, width, height, wType, wSpacing, grbit) # :nodoc:
1527
+ record = 0x1015 # Record identifier.
1528
+ length = 0x0014 # Number of bytes to follow.
1529
+ # x # X-position.
1530
+ # y # Y-position.
1531
+ # width # Width.
1532
+ # height # Height.
1533
+ # wType # Type.
1534
+ # wSpacing # Spacing.
1535
+ # grbit # Option flags.
1536
+
1537
+ header = [record, length].pack('vv')
1538
+ data = [x].pack('V')
1539
+ data += [y].pack('V')
1540
+ data += [width].pack('V')
1541
+ data += [height].pack('V')
1542
+ data += [wType].pack('C')
1543
+ data += [wSpacing].pack('C')
1544
+ data += [grbit].pack('v')
1545
+
1546
+ append(header, data)
1547
+ end
1548
+
1549
+ #
1550
+ # Write the LINEFORMAT chart BIFF record.
1551
+ #
1552
+ def store_lineformat(rgb, lns, we, grbit, index) # :nodoc:
1553
+ record = 0x1007 # Record identifier.
1554
+ length = 0x000C # Number of bytes to follow.
1555
+ # rgb # Line RGB colour.
1556
+ # lns # Line pattern.
1557
+ # we # Line weight.
1558
+ # grbit # Option flags.
1559
+ # index # Index to colour of line.
1560
+
1561
+ header = [record, length].pack('vv')
1562
+ data = [rgb].pack('V')
1563
+ data += [lns].pack('v')
1564
+ data += [we].pack('v')
1565
+ data += [grbit].pack('v')
1566
+ data += [index].pack('v')
1567
+
1568
+ append(header, data)
1569
+ end
1570
+
1571
+ #
1572
+ # Write the MARKERFORMAT chart BIFF record.
1573
+ #
1574
+ def store_markerformat(rgbFore, rgbBack, marker, grbit, icvFore, icvBack, miSize)# :nodoc:
1575
+ record = 0x1009 # Record identifier.
1576
+ length = 0x0014 # Number of bytes to follow.
1577
+ # rgbFore # Foreground RGB color.
1578
+ # rgbBack # Background RGB color.
1579
+ # marker # Type of marker.
1580
+ # grbit # Format flags.
1581
+ # icvFore # Color index marker border.
1582
+ # icvBack # Color index marker fill.
1583
+ # miSize # Size of line markers.
1584
+
1585
+ header = [record, length].pack('vv')
1586
+ data = [rgbFore].pack('V')
1587
+ data += [rgbBack].pack('V')
1588
+ data += [marker].pack('v')
1589
+ data += [grbit].pack('v')
1590
+ data += [icvFore].pack('v')
1591
+ data += [icvBack].pack('v')
1592
+ data += [miSize].pack('V')
1593
+
1594
+ append(header, data)
1595
+ end
1596
+
1597
+ #
1598
+ # Write the OBJECTLINK chart BIFF record.
1599
+ #
1600
+ def store_objectlink(link_type) # :nodoc:
1601
+ record = 0x1027 # Record identifier.
1602
+ length = 0x0006 # Number of bytes to follow.
1603
+ # link_type # Object text link type.
1604
+ link_index1 = 0x0000 # Link index 1.
1605
+ link_index2 = 0x0000 # Link index 2.
1606
+
1607
+ store_simple(record, length, link_type, link_index1, link_index2)
1608
+ end
1609
+
1610
+ #
1611
+ # Write the PIEFORMAT chart BIFF record.
1612
+ #
1613
+ def store_pieformat # :nodoc:
1614
+ record = 0x100B # Record identifier.
1615
+ length = 0x0002 # Number of bytes to follow.
1616
+ percent = 0x0000 # Distance % from center.
1617
+
1618
+ store_simple(record, length, percent)
1619
+ end
1620
+
1621
+ #
1622
+ # Write the PLOTAREA chart BIFF record. This indicates that the subsequent
1623
+ # FRAME record belongs to a plot area.
1624
+ #
1625
+ def store_plotarea # :nodoc:
1626
+ record = 0x1035 # Record identifier.
1627
+ length = 0x0000 # Number of bytes to follow.
1628
+
1629
+ store_simple(record, length)
1630
+ end
1631
+
1632
+ #
1633
+ # Write the PLOTGROWTH chart BIFF record.
1634
+ #
1635
+ def store_plotgrowth # :nodoc:
1636
+ record = 0x1064 # Record identifier.
1637
+ length = 0x0008 # Number of bytes to follow.
1638
+ dx_plot = 0x00010000 # Horz growth for font scale.
1639
+ dy_plot = 0x00010000 # Vert growth for font scale.
1640
+
1641
+ header = [record, length].pack('vv')
1642
+ data = [dx_plot].pack('V')
1643
+ data += [dy_plot].pack('V')
1644
+
1645
+ append(header, data)
1646
+ end
1647
+
1648
+ #
1649
+ # Write the POS chart BIFF record. Generally not required when using
1650
+ # automatic positioning.
1651
+ #
1652
+ def store_pos(mdTopLt, mdBotRt, x1, y1, x2, y2) # :nodoc:
1653
+ record = 0x104F # Record identifier.
1654
+ length = 0x0014 # Number of bytes to follow.
1655
+ # mdTopLt # Top left.
1656
+ # mdBotRt # Bottom right.
1657
+ # x1 # X coordinate.
1658
+ # y1 # Y coordinate.
1659
+ # x2 # Width.
1660
+ # y2 # Height.
1661
+
1662
+ header = [record, length].pack('vv')
1663
+ data = [mdTopLt].pack('v')
1664
+ data += [mdBotRt].pack('v')
1665
+ data += [x1].pack('V')
1666
+ data += [y1].pack('V')
1667
+ data += [x2].pack('V')
1668
+ data += [y2].pack('V')
1669
+
1670
+ append(header, data)
1671
+ end
1672
+
1673
+ #
1674
+ # Write the SERAUXTREND chart BIFF record.
1675
+ #
1676
+ def store_serauxtrend(reg_type, poly_order, equation, r_squared) # :nodoc:
1677
+ record = 0x104B # Record identifier.
1678
+ length = 0x001C # Number of bytes to follow.
1679
+ # reg_type # Regression type.
1680
+ # poly_order # Polynomial order.
1681
+ # equation # Display equation.
1682
+ # r_squared # Display R-squared.
1683
+ # intercept # Forced intercept.
1684
+ # forecast # Forecast forward.
1685
+ # backcast # Forecast backward.
1686
+
1687
+ # TODO. When supported, intercept needs to be NAN if not used.
1688
+ # Also need to reverse doubles.
1689
+ intercept = ['FFFFFFFF0001FFFF'].pack('H*')
1690
+ forecast = ['0000000000000000'].pack('H*')
1691
+ backcast = ['0000000000000000'].pack('H*')
1692
+
1693
+ header = [record, length].pack('vv')
1694
+ data = [reg_type].pack('C')
1695
+ data += [poly_order].pack('C')
1696
+ data += intercept
1697
+ data += [equation].pack('C')
1698
+ data += [r_squared].pack('C')
1699
+ data += forecast
1700
+ data += backcast
1701
+
1702
+ append(header, data)
1703
+ end
1704
+
1705
+ #
1706
+ # Write the SERIES chart BIFF record.
1707
+ #
1708
+ def store_series(category_count, value_count) # :nodoc:
1709
+ record = 0x1003 # Record identifier.
1710
+ length = 0x000C # Number of bytes to follow.
1711
+ category_type = 0x0001 # Type: category.
1712
+ value_type = 0x0001 # Type: value.
1713
+ # category_count # Num of categories.
1714
+ # value_count # Num of values.
1715
+ bubble_type = 0x0001 # Type: bubble.
1716
+ bubble_count = 0x0000 # Num of bubble values.
1717
+
1718
+ store_simple(record, length, category_type, value_type,
1719
+ category_count, value_count, bubble_type, bubble_count)
1720
+ end
1721
+
1722
+ #
1723
+ # Write the SERIESTEXT chart BIFF record.
1724
+ #
1725
+ def store_seriestext(str, encoding) # :nodoc:
1726
+ ruby_19 { str = convert_to_ascii_if_ascii(str) }
1727
+
1728
+ record = 0x100D # Record identifier.
1729
+ length = 0x0000 # Number of bytes to follow.
1730
+ id = 0x0000 # Text id.
1731
+ # str # Text.
1732
+ # encoding # String encoding.
1733
+ cch = str.bytesize # String length.
1734
+
1735
+ encoding ||= 0
1736
+
1737
+ # Character length is num of chars not num of bytes
1738
+ cch /= 2 if encoding != 0
1739
+
1740
+ # Change the UTF-16 name from BE to LE
1741
+ str = str.unpack('v*').pack('n*') if encoding != 0
1742
+
1743
+ length = 4 + str.bytesize
1744
+
1745
+ header = [record, length].pack('vv')
1746
+ data = [id].pack('v')
1747
+ data += [cch].pack('C')
1748
+ data += [encoding].pack('C')
1749
+
1750
+ append(header, data, str)
1751
+ end
1752
+
1753
+ #
1754
+ # Write the SERPARENT chart BIFF record.
1755
+ #
1756
+ def store_serparent(series) # :nodoc:
1757
+ record = 0x104A # Record identifier.
1758
+ length = 0x0002 # Number of bytes to follow.
1759
+ # series # Series parent.
1760
+
1761
+ store_simple(record, length, series)
1762
+ end
1763
+
1764
+ #
1765
+ # Write the SERTOCRT chart BIFF record to indicate the chart group index.
1766
+ #
1767
+ def store_sertocrt # :nodoc:
1768
+ record = 0x1045 # Record identifier.
1769
+ length = 0x0002 # Number of bytes to follow.
1770
+ chartgroup = 0x0000 # Chart group index.
1771
+
1772
+ store_simple(record, length, chartgroup)
1773
+ end
1774
+
1775
+ #
1776
+ # Write the SHTPROPS chart BIFF record.
1777
+ #
1778
+ def store_shtprops # :nodoc:
1779
+ record = 0x1044 # Record identifier.
1780
+ length = 0x0004 # Number of bytes to follow.
1781
+ grbit = 0x000E # Option flags.
1782
+ empty_cells = 0x0000 # Empty cell handling.
1783
+
1784
+ grbit = 0x000A if @embedded
1785
+
1786
+ store_simple(record, length, grbit, empty_cells)
1787
+ end
1788
+
1789
+ #
1790
+ # Write the TEXT chart BIFF record.
1791
+ #
1792
+ def store_text(x, y, dx, dy, grbit1, grbit2, rotation = 0x00)# :nodoc:
1793
+ record = 0x1025 # Record identifier.
1794
+ length = 0x0020 # Number of bytes to follow.
1795
+ at = 0x02 # Horizontal alignment.
1796
+ vat = 0x02 # Vertical alignment.
1797
+ wBkgMode = 0x0001 # Background display.
1798
+ rgbText = 0x0000 # Text RGB colour.
1799
+ # x # Text x-pos.
1800
+ # y # Text y-pos.
1801
+ # dx # Width.
1802
+ # dy # Height.
1803
+ # grbit1 # Option flags.
1804
+ icvText = 0x004D # Auto Colour.
1805
+ # grbit2 # Show legend.
1806
+ # rotation # Show value.
1807
+
1808
+ header = [record, length].pack('vv')
1809
+ data = [at].pack('C')
1810
+ data += [vat].pack('C')
1811
+ data += [wBkgMode].pack('v')
1812
+ data += [rgbText].pack('V')
1813
+ data += [x].pack('V')
1814
+ data += [y].pack('V')
1815
+ data += [dx].pack('V')
1816
+ data += [dy].pack('V')
1817
+ data += [grbit1].pack('v')
1818
+ data += [icvText].pack('v')
1819
+ data += [grbit2].pack('v')
1820
+ data += [rotation].pack('v')
1821
+
1822
+ append(header, data)
1823
+ end
1824
+
1825
+ #
1826
+ # Write the TICK chart BIFF record.
1827
+ #
1828
+ def store_tick # :nodoc:
1829
+ record = 0x101E # Record identifier.
1830
+ length = 0x001E # Number of bytes to follow.
1831
+ tktMajor = 0x02 # Type of major tick mark.
1832
+ tktMinor = 0x00 # Type of minor tick mark.
1833
+ tlt = 0x03 # Tick label position.
1834
+ wBkgMode = 0x01 # Background mode.
1835
+ rgb = 0x00000000 # Tick-label RGB colour.
1836
+ reserved1 = 0x00000000 # Reserved.
1837
+ reserved2 = 0x00000000 # Reserved.
1838
+ reserved3 = 0x00000000 # Reserved.
1839
+ reserved4 = 0x00000000 # Reserved.
1840
+ grbit = 0x0023 # Option flags.
1841
+ index = 0x004D # Colour index.
1842
+ reserved5 = 0x0000 # Reserved.
1843
+
1844
+ header = [record, length].pack('vv')
1845
+ data = [tktMajor].pack('C')
1846
+ data += [tktMinor].pack('C')
1847
+ data += [tlt].pack('C')
1848
+ data += [wBkgMode].pack('C')
1849
+ data += [rgb].pack('V')
1850
+ data += [reserved1].pack('V')
1851
+ data += [reserved2].pack('V')
1852
+ data += [reserved3].pack('V')
1853
+ data += [reserved4].pack('V')
1854
+ data += [grbit].pack('v')
1855
+ data += [index].pack('v')
1856
+ data += [reserved5].pack('v')
1857
+
1858
+ append(header, data)
1859
+ end
1860
+
1861
+ #
1862
+ # Write the VALUERANGE chart BIFF record.
1863
+ #
1864
+ def store_valuerange # :nodoc:
1865
+ record = 0x101F # Record identifier.
1866
+ length = 0x002A # Number of bytes to follow.
1867
+ numMin = 0x00000000 # Minimum value on axis.
1868
+ numMax = 0x00000000 # Maximum value on axis.
1869
+ numMajor = 0x00000000 # Value of major increment.
1870
+ numMinor = 0x00000000 # Value of minor increment.
1871
+ numCross = 0x00000000 # Value where category axis crosses.
1872
+ grbit = 0x011F # Format flags.
1873
+
1874
+ # TODO. Reverse doubles when they are handled.
1875
+
1876
+ header = [record, length].pack('vv')
1877
+ data = [numMin].pack('d')
1878
+ data += [numMax].pack('d')
1879
+ data += [numMajor].pack('d')
1880
+ data += [numMinor].pack('d')
1881
+ data += [numCross].pack('d')
1882
+ data += [grbit].pack('v')
1883
+
1884
+ append(header, data)
1885
+ end
1886
+
1887
+
1888
+ ###############################################################################
1889
+ #
1890
+ # Config data.
1891
+ #
1892
+ ###############################################################################
1893
+
1894
+ #
1895
+ # Setup the default properties for a chart.
1896
+ #
1897
+ def set_default_properties # :nodoc:
1898
+ @legend = {
1899
+ :visible => 1,
1900
+ :position => 0,
1901
+ :vertical => 0,
1902
+ }
1903
+
1904
+ @chartarea = {
1905
+ :visible => 0,
1906
+ :fg_color_index => 0x4E,
1907
+ :fg_color_rgb => 0xFFFFFF,
1908
+ :bg_color_index => 0x4D,
1909
+ :bg_color_rgb => 0x000000,
1910
+ :area_pattern => 0x0000,
1911
+ :area_options => 0x0000,
1912
+ :line_pattern => 0x0005,
1913
+ :line_weight => 0xFFFF,
1914
+ :line_color_index => 0x4D,
1915
+ :line_color_rgb => 0x000000,
1916
+ :line_options => 0x0008,
1917
+ }
1918
+
1919
+ @plotarea = {
1920
+ :visible => 1,
1921
+ :fg_color_index => 0x16,
1922
+ :fg_color_rgb => 0xC0C0C0,
1923
+ :bg_color_index => 0x4F,
1924
+ :bg_color_rgb => 0x000000,
1925
+ :area_pattern => 0x0001,
1926
+ :area_options => 0x0000,
1927
+ :line_pattern => 0x0000,
1928
+ :line_weight => 0x0000,
1929
+ :line_color_index => 0x17,
1930
+ :line_color_rgb => 0x808080,
1931
+ :line_options => 0x0000,
1932
+ }
1933
+ end
1934
+
1935
+ #
1936
+ # Setup the default configuration data for a chart.
1937
+ #
1938
+ def set_default_config_data # :nodoc:
1939
+ @config = default_config_data
1940
+ end
1941
+
1942
+ def default_config_data # :nodoc:
1943
+ {
1944
+ :axisparent => [ 0, 0x00F8, 0x01F5, 0x0E7F, 0x0B36 ],
1945
+ :axisparent_pos => [ 2, 2, 0x008C, 0x01AA, 0x0EEA, 0x0C52 ],
1946
+ :chart => [ 0x0000, 0x0000, 0x02DD51E0, 0x01C2B838 ],
1947
+ :font_numbers => [ 5, 10, 0x38B8, 0x22A1, 0x0000 ],
1948
+ :font_series => [ 6, 10, 0x38B8, 0x22A1, 0x0001 ],
1949
+ :font_title => [ 7, 12, 0x38B8, 0x22A1, 0x0000 ],
1950
+ :font_axes => [ 8, 10, 0x38B8, 0x22A1, 0x0001 ],
1951
+ :legend => [ 0x05F9, 0x0EE9, 0x047D, 0x9C, 0x00, 0x01, 0x0F ],
1952
+ :legend_pos => [ 5, 2, 0x05F9, 0x0EE9, 0, 0 ],
1953
+ :legend_text => [ 0xFFFFFF46, 0xFFFFFF06, 0, 0, 0x00B1, 0x0000 ],
1954
+ :legend_text_pos => [ 2, 2, 0, 0, 0, 0 ],
1955
+ :series_text => [ 0xFFFFFF46, 0xFFFFFF06, 0, 0, 0x00B1, 0x1020 ],
1956
+ :series_text_pos => [ 2, 2, 0, 0, 0, 0 ],
1957
+ :title_text => [ 0x06E4, 0x0051, 0x01DB, 0x00C4, 0x0081, 0x1030 ],
1958
+ :title_text_pos => [ 2, 2, 0, 0, 0x73, 0x1D ],
1959
+ :x_axis_text => [ 0x07E1, 0x0DFC, 0xB2, 0x9C, 0x0081, 0x0000 ],
1960
+ :x_axis_text_pos => [ 2, 2, 0, 0, 0x2B, 0x17 ],
1961
+ :y_axis_text => [ 0x002D, 0x06AA, 0x5F, 0x1CC, 0x0281, 0x00, 90 ],
1962
+ :y_axis_text_pos => [ 2, 2, 0, 0, 0x17, 0x44 ],
1963
+ }
1964
+ end
1965
+
1966
+ end # class Chart
1967
+
1968
+ end # module Writeexcel