writeexcel 0.1.0 → 0.3.0

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