ricardoo27-writeexcel 0.6.12.1

Sign up to get free protection for your applications and to get access to all the features.
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