write_xlsx 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitattributes +1 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +82 -0
- data/Rakefile +78 -0
- data/VERSION +1 -0
- data/examples/a_simple.rb +45 -0
- data/examples/array_formula.rb +33 -0
- data/examples/autofilter.rb +235 -0
- data/examples/chart_area.rb +59 -0
- data/examples/chart_bar.rb +59 -0
- data/examples/chart_column.rb +58 -0
- data/examples/chart_line.rb +59 -0
- data/examples/chart_pie.rb +49 -0
- data/examples/chart_scatter.rb +59 -0
- data/examples/chart_stock.rb +65 -0
- data/examples/colors.rb +130 -0
- data/examples/comments1.rb +12 -0
- data/examples/comments2.rb +335 -0
- data/examples/conditional_format.rb +67 -0
- data/examples/data_validate.rb +279 -0
- data/examples/defined_name.rb +28 -0
- data/examples/demo.rb +104 -0
- data/examples/diag_border.rb +26 -0
- data/examples/headers.rb +119 -0
- data/examples/hide_sheet.rb +30 -0
- data/examples/hyperlink1.rb +58 -0
- data/examples/indent.rb +28 -0
- data/examples/merge1.rb +38 -0
- data/examples/merge2.rb +48 -0
- data/examples/merge3.rb +43 -0
- data/examples/merge4.rb +82 -0
- data/examples/merge5.rb +70 -0
- data/examples/merge6.rb +48 -0
- data/examples/outline.rb +252 -0
- data/examples/properties.rb +33 -0
- data/examples/protection.rb +34 -0
- data/examples/rich_strings.rb +42 -0
- data/examples/right_to_left.rb +24 -0
- data/examples/tab_colors.rb +26 -0
- data/lib/write_xlsx.rb +77 -0
- data/lib/write_xlsx/chart.rb +3027 -0
- data/lib/write_xlsx/chart/area.rb +52 -0
- data/lib/write_xlsx/chart/bar.rb +126 -0
- data/lib/write_xlsx/chart/column.rb +132 -0
- data/lib/write_xlsx/chart/line.rb +51 -0
- data/lib/write_xlsx/chart/pie.rb +210 -0
- data/lib/write_xlsx/chart/scatter.rb +252 -0
- data/lib/write_xlsx/chart/stock.rb +134 -0
- data/lib/write_xlsx/chartsheet.rb +173 -0
- data/lib/write_xlsx/colors.rb +65 -0
- data/lib/write_xlsx/compatibility.rb +71 -0
- data/lib/write_xlsx/drawing.rb +547 -0
- data/lib/write_xlsx/format.rb +683 -0
- data/lib/write_xlsx/package/app.rb +218 -0
- data/lib/write_xlsx/package/comments.rb +221 -0
- data/lib/write_xlsx/package/content_types.rb +189 -0
- data/lib/write_xlsx/package/core.rb +196 -0
- data/lib/write_xlsx/package/packager.rb +510 -0
- data/lib/write_xlsx/package/relationships.rb +98 -0
- data/lib/write_xlsx/package/shared_strings.rb +96 -0
- data/lib/write_xlsx/package/styles.rb +705 -0
- data/lib/write_xlsx/package/theme.rb +45 -0
- data/lib/write_xlsx/package/vml.rb +386 -0
- data/lib/write_xlsx/package/xml_writer_simple.rb +90 -0
- data/lib/write_xlsx/utility.rb +113 -0
- data/lib/write_xlsx/workbook.rb +1488 -0
- data/lib/write_xlsx/worksheet.rb +6578 -0
- data/lib/write_xlsx/zip_file_utils.rb +98 -0
- data/test/chart/test_add_series.rb +113 -0
- data/test/chart/test_process_names.rb +27 -0
- data/test/chart/test_write_auto.rb +15 -0
- data/test/chart/test_write_ax_id.rb +15 -0
- data/test/chart/test_write_ax_pos.rb +15 -0
- data/test/chart/test_write_chart_space.rb +15 -0
- data/test/chart/test_write_cross_ax.rb +15 -0
- data/test/chart/test_write_crosses.rb +15 -0
- data/test/chart/test_write_format_code.rb +15 -0
- data/test/chart/test_write_idx.rb +15 -0
- data/test/chart/test_write_label_align.rb +15 -0
- data/test/chart/test_write_label_offset.rb +15 -0
- data/test/chart/test_write_lang.rb +15 -0
- data/test/chart/test_write_layout.rb +15 -0
- data/test/chart/test_write_legend.rb +16 -0
- data/test/chart/test_write_legend_pos.rb +15 -0
- data/test/chart/test_write_major_gridlines.rb +15 -0
- data/test/chart/test_write_marker.rb +17 -0
- data/test/chart/test_write_marker_size.rb +15 -0
- data/test/chart/test_write_marker_value.rb +16 -0
- data/test/chart/test_write_num_cache.rb +16 -0
- data/test/chart/test_write_num_fmt.rb +16 -0
- data/test/chart/test_write_number_format.rb +15 -0
- data/test/chart/test_write_order.rb +15 -0
- data/test/chart/test_write_orientation.rb +15 -0
- data/test/chart/test_write_page_margins.rb +15 -0
- data/test/chart/test_write_page_setup.rb +15 -0
- data/test/chart/test_write_plot_vis_only.rb +15 -0
- data/test/chart/test_write_pt.rb +16 -0
- data/test/chart/test_write_pt_count.rb +16 -0
- data/test/chart/test_write_series_formula.rb +16 -0
- data/test/chart/test_write_style.rb +41 -0
- data/test/chart/test_write_symbol.rb +16 -0
- data/test/chart/test_write_tick_lbl_pos.rb +16 -0
- data/test/chart/test_write_v.rb +16 -0
- data/test/drawing/test_drawing_chart_01.rb +50 -0
- data/test/drawing/test_drawing_image_01.rb +59 -0
- data/test/helper.rb +90 -0
- data/test/package/app/test_app01.rb +44 -0
- data/test/package/app/test_app02.rb +46 -0
- data/test/package/app/test_app03.rb +53 -0
- data/test/package/comments/test_comments01.rb +36 -0
- data/test/package/comments/test_write_text_t.rb +44 -0
- data/test/package/content_types/test_content_types.rb +35 -0
- data/test/package/content_types/test_write_default.rb +13 -0
- data/test/package/content_types/test_write_override.rb +13 -0
- data/test/package/core/test_core01.rb +28 -0
- data/test/package/core/test_core02.rb +42 -0
- data/test/package/relationships/test_relationships.rb +28 -0
- data/test/package/relationships/test_sheet_rels.rb +22 -0
- data/test/package/shared_strings/test_shared_strings01.rb +30 -0
- data/test/package/shared_strings/test_shared_strings02.rb +30 -0
- data/test/package/shared_strings/test_write_si.rb +13 -0
- data/test/package/shared_strings/test_write_sst.rb +15 -0
- data/test/package/styles/test_styles_01.rb +69 -0
- data/test/package/styles/test_styles_02.rb +104 -0
- data/test/package/styles/test_styles_03.rb +90 -0
- data/test/package/styles/test_styles_04.rb +216 -0
- data/test/package/styles/test_styles_05.rb +150 -0
- data/test/package/styles/test_styles_06.rb +104 -0
- data/test/package/styles/test_styles_07.rb +104 -0
- data/test/package/styles/test_styles_08.rb +109 -0
- data/test/package/styles/test_styles_09.rb +95 -0
- data/test/package/vml/test_vml_01.rb +42 -0
- data/test/package/vml/test_write_anchor.rb +14 -0
- data/test/package/vml/test_write_auto_fill.rb +14 -0
- data/test/package/vml/test_write_column.rb +14 -0
- data/test/package/vml/test_write_div.rb +14 -0
- data/test/package/vml/test_write_fill.rb +14 -0
- data/test/package/vml/test_write_idmap.rb +14 -0
- data/test/package/vml/test_write_move_with_cells.rb +14 -0
- data/test/package/vml/test_write_path.rb +22 -0
- data/test/package/vml/test_write_row.rb +14 -0
- data/test/package/vml/test_write_shadow.rb +14 -0
- data/test/package/vml/test_write_shapelayout.rb +14 -0
- data/test/package/vml/test_write_shapetype.rb +14 -0
- data/test/package/vml/test_write_size_with_cells.rb +14 -0
- data/test/package/vml/test_write_stroke.rb +14 -0
- data/test/package/vml/test_write_textbox.rb +14 -0
- data/test/perl_output/a_simple.xlsx +0 -0
- data/test/perl_output/array_formula.xlsx +0 -0
- data/test/perl_output/autofilter.xlsx +0 -0
- data/test/perl_output/chart_area.xlsx +0 -0
- data/test/perl_output/chart_bar.xlsx +0 -0
- data/test/perl_output/chart_column.xlsx +0 -0
- data/test/perl_output/chart_line.xlsx +0 -0
- data/test/perl_output/chart_pie.xlsx +0 -0
- data/test/perl_output/chart_scatter.xlsx +0 -0
- data/test/perl_output/chart_stock.xlsx +0 -0
- data/test/perl_output/comments1.xlsx +0 -0
- data/test/perl_output/comments2.xlsx +0 -0
- data/test/perl_output/conditional_format.xlsx +0 -0
- data/test/perl_output/data_validate.xlsx +0 -0
- data/test/perl_output/defined_name.xlsx +0 -0
- data/test/perl_output/demo.xlsx +0 -0
- data/test/perl_output/diag_border.xlsx +0 -0
- data/test/perl_output/fit_to_pages.xlsx +0 -0
- data/test/perl_output/headers.xlsx +0 -0
- data/test/perl_output/hide_sheet.xlsx +0 -0
- data/test/perl_output/hyperlink.xlsx +0 -0
- data/test/perl_output/indent.xlsx +0 -0
- data/test/perl_output/merge1.xlsx +0 -0
- data/test/perl_output/merge2.xlsx +0 -0
- data/test/perl_output/merge3.xlsx +0 -0
- data/test/perl_output/merge4.xlsx +0 -0
- data/test/perl_output/merge5.xlsx +0 -0
- data/test/perl_output/merge6.xlsx +0 -0
- data/test/perl_output/outline.xlsx +0 -0
- data/test/perl_output/print_scale.xlsx +0 -0
- data/test/perl_output/properties.xlsx +0 -0
- data/test/perl_output/protection.xlsx +0 -0
- data/test/perl_output/rich_strings.xlsx +0 -0
- data/test/perl_output/right_to_left.xlsx +0 -0
- data/test/perl_output/tab_colors.xlsx +0 -0
- data/test/test_delete_files.rb +37 -0
- data/test/test_example_match.rb +2281 -0
- data/test/test_xml_writer_simple.rb +63 -0
- data/test/workbook/test_get_chart_range.rb +59 -0
- data/test/workbook/test_sort_defined_names.rb +77 -0
- data/test/workbook/test_workbook_01.rb +29 -0
- data/test/workbook/test_workbook_02.rb +31 -0
- data/test/workbook/test_workbook_03.rb +31 -0
- data/test/workbook/test_workbook_new.rb +18 -0
- data/test/workbook/test_write_defined_name.rb +17 -0
- data/test/workbook/test_write_defined_names.rb +41 -0
- data/test/worksheet/test_calculate_spans.rb +58 -0
- data/test/worksheet/test_convert_date_time_01.rb +439 -0
- data/test/worksheet/test_convert_date_time_02.rb +478 -0
- data/test/worksheet/test_convert_date_time_03.rb +435 -0
- data/test/worksheet/test_extract_filter_tokens.rb +109 -0
- data/test/worksheet/test_parse_filter_expression.rb +143 -0
- data/test/worksheet/test_position_object.rb +50 -0
- data/test/worksheet/test_repeat_formula.rb +55 -0
- data/test/worksheet/test_worksheet_01.rb +32 -0
- data/test/worksheet/test_worksheet_02.rb +38 -0
- data/test/worksheet/test_worksheet_03.rb +44 -0
- data/test/worksheet/test_worksheet_04.rb +45 -0
- data/test/worksheet/test_write_array_formula_01.rb +99 -0
- data/test/worksheet/test_write_autofilter.rb +260 -0
- data/test/worksheet/test_write_brk.rb +18 -0
- data/test/worksheet/test_write_cell.rb +49 -0
- data/test/worksheet/test_write_cell_value.rb +33 -0
- data/test/worksheet/test_write_col_breaks.rb +27 -0
- data/test/worksheet/test_write_col_info.rb +95 -0
- data/test/worksheet/test_write_conditional_formatting.rb +72 -0
- data/test/worksheet/test_write_custom_filter.rb +18 -0
- data/test/worksheet/test_write_custom_filters.rb +25 -0
- data/test/worksheet/test_write_data_validation_01.rb +113 -0
- data/test/worksheet/test_write_data_validation_02.rb +528 -0
- data/test/worksheet/test_write_dimension.rb +94 -0
- data/test/worksheet/test_write_ext.rb +18 -0
- data/test/worksheet/test_write_ext_lst.rb +18 -0
- data/test/worksheet/test_write_filter.rb +18 -0
- data/test/worksheet/test_write_filter_column.rb +18 -0
- data/test/worksheet/test_write_filters.rb +32 -0
- data/test/worksheet/test_write_header_footer.rb +53 -0
- data/test/worksheet/test_write_hyperlink.rb +39 -0
- data/test/worksheet/test_write_hyperlinks.rb +27 -0
- data/test/worksheet/test_write_legacy_drawing.rb +19 -0
- data/test/worksheet/test_write_merge_cell.rb +18 -0
- data/test/worksheet/test_write_merge_cells.rb +192 -0
- data/test/worksheet/test_write_methods.rb +353 -0
- data/test/worksheet/test_write_mx_plv.rb +19 -0
- data/test/worksheet/test_write_page_margins.rb +98 -0
- data/test/worksheet/test_write_page_set_up_pr.rb +19 -0
- data/test/worksheet/test_write_page_setup.rb +54 -0
- data/test/worksheet/test_write_pane.rb +123 -0
- data/test/worksheet/test_write_phonetic_pr.rb +19 -0
- data/test/worksheet/test_write_print_options.rb +77 -0
- data/test/worksheet/test_write_row_breaks.rb +27 -0
- data/test/worksheet/test_write_row_element.rb +69 -0
- data/test/worksheet/test_write_selection.rb +18 -0
- data/test/worksheet/test_write_sheet_calc_pr.rb +18 -0
- data/test/worksheet/test_write_sheet_data.rb +18 -0
- data/test/worksheet/test_write_sheet_format_pr.rb +18 -0
- data/test/worksheet/test_write_sheet_pr.rb +36 -0
- data/test/worksheet/test_write_sheet_protection.rb +174 -0
- data/test/worksheet/test_write_sheet_view.rb +62 -0
- data/test/worksheet/test_write_sheet_view1.rb +64 -0
- data/test/worksheet/test_write_sheet_view2.rb +56 -0
- data/test/worksheet/test_write_sheet_view3.rb +83 -0
- data/test/worksheet/test_write_sheet_view4.rb +83 -0
- data/test/worksheet/test_write_sheet_view5.rb +74 -0
- data/test/worksheet/test_write_sheet_view6.rb +51 -0
- data/test/worksheet/test_write_sheet_view7.rb +71 -0
- data/test/worksheet/test_write_sheet_view8.rb +51 -0
- data/test/worksheet/test_write_sheet_view9.rb +51 -0
- data/test/worksheet/test_write_tab_color.rb +23 -0
- data/test/worksheet/test_write_worksheet.rb +19 -0
- data/write_xlsx.gemspec +308 -0
- metadata +363 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
##############################################################################
|
5
|
+
#
|
6
|
+
# An example of adding document properties to a Excel::Writer::XLSX file.
|
7
|
+
#
|
8
|
+
# reverse('©'), August 2008, John McNamara, jmcnamara@cpan.org
|
9
|
+
# convert to ruby by Hideo NAKAMURA, cxn03651@msj.biglobe.ne.jp
|
10
|
+
#
|
11
|
+
|
12
|
+
require 'rubygems'
|
13
|
+
require 'write_xlsx'
|
14
|
+
|
15
|
+
workbook = WriteXLSX.new('properties.xlsx')
|
16
|
+
worksheet = workbook.add_worksheet
|
17
|
+
|
18
|
+
workbook.set_properties(
|
19
|
+
:title => 'This is an example spreadsheet',
|
20
|
+
:subject => 'With document properties',
|
21
|
+
:author => 'John McNamara',
|
22
|
+
:manager => 'Dr. Heinz Doofenshmirtz',
|
23
|
+
:company => 'of Wolves',
|
24
|
+
:category => 'Example spreadsheets',
|
25
|
+
:keywords => 'Sample, Example, Properties',
|
26
|
+
:comments => 'Created with Perl and Excel::Writer::XLSX',
|
27
|
+
:status => 'Quo'
|
28
|
+
)
|
29
|
+
|
30
|
+
worksheet.set_column('A:A', 70)
|
31
|
+
worksheet.write('A1', "Select 'Office Button -> Prepare -> Properties' to see the file properties.")
|
32
|
+
|
33
|
+
workbook.close
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'write_xlsx'
|
6
|
+
|
7
|
+
workbook = WriteXLSX.new('protection.xlsx')
|
8
|
+
worksheet = workbook.add_worksheet
|
9
|
+
|
10
|
+
# Create some format objects
|
11
|
+
unlocked = workbook.add_format(:locked => 0)
|
12
|
+
hidden = workbook.add_format(:hidden => 1)
|
13
|
+
|
14
|
+
# Format the columns
|
15
|
+
worksheet.set_column('A:A', 45)
|
16
|
+
worksheet.set_selection('B3')
|
17
|
+
|
18
|
+
# Protect the worksheet
|
19
|
+
worksheet.protect
|
20
|
+
|
21
|
+
# Examples of cell locking and hiding.
|
22
|
+
worksheet.write('A1', 'Cell B1 is locked. It cannot be edited.')
|
23
|
+
worksheet.write_formula('B1', '=1+2', nil, 3) # Locked by default.
|
24
|
+
|
25
|
+
worksheet.write('A2', 'Cell B2 is unlocked. It can be edited.')
|
26
|
+
worksheet.write_formula('B2', '=1+2', unlocked, 3)
|
27
|
+
|
28
|
+
worksheet.write('A3', "Cell B3 is hidden. The formula isn't visible.")
|
29
|
+
worksheet.write_formula('B3', '=1+2', hidden, 3)
|
30
|
+
|
31
|
+
worksheet.write('A5', 'Use Menu->Tools->Protection->Unprotect Sheet')
|
32
|
+
worksheet.write('A6', 'to remove the worksheet protection.')
|
33
|
+
|
34
|
+
workbook.close
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
#######################################################################
|
5
|
+
#
|
6
|
+
# An Excel::Writer::XLSX example showing how to use "rich strings", i.e.,
|
7
|
+
# strings with multiple formatting.
|
8
|
+
#
|
9
|
+
# reverse(c), February 2011, John McNamara, jmcnamara@cpan.org
|
10
|
+
# convert to ruby by Hideo NAKAMURA, cxn03651@msj.biglobe.ne.jp
|
11
|
+
#
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'write_xlsx'
|
15
|
+
|
16
|
+
workbook = WriteXLSX.new('rich_strings.xlsx')
|
17
|
+
worksheet = workbook.add_worksheet
|
18
|
+
|
19
|
+
worksheet.set_column('A:A', 30)
|
20
|
+
|
21
|
+
# Set some formats to use.
|
22
|
+
bold = workbook.add_format(:bold => 1)
|
23
|
+
italic = workbook.add_format(:italic => 1)
|
24
|
+
red = workbook.add_format(:color => 'red')
|
25
|
+
blue = workbook.add_format(:color => 'blue')
|
26
|
+
center = workbook.add_format(:align => 'center')
|
27
|
+
superc = workbook.add_format(:font_script => 1)
|
28
|
+
|
29
|
+
# Write some strings with multiple formats.
|
30
|
+
worksheet.write_rich_string('A1',
|
31
|
+
'This is ', bold, 'bold', ' and this is ', italic, 'italic')
|
32
|
+
|
33
|
+
worksheet.write_rich_string('A3',
|
34
|
+
'This is ', red, 'red', ' and this is ', blue, 'blue')
|
35
|
+
|
36
|
+
worksheet.write_rich_string('A5',
|
37
|
+
'Some ', bold, 'bold text', ' centered', center)
|
38
|
+
|
39
|
+
worksheet.write_rich_string('A7',
|
40
|
+
italic, 'j = k', superc, '(n-1)', center)
|
41
|
+
|
42
|
+
workbook.close
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#######################################################################
|
4
|
+
#
|
5
|
+
# Example of how to change the default worksheet direction from
|
6
|
+
# left-to-right to right-to-left as required by some eastern verions
|
7
|
+
# of Excel.
|
8
|
+
#
|
9
|
+
# reverse(c), January 2006, John McNamara, jmcnamara@cpan.org
|
10
|
+
# convert to ruby by Hideo NAKAMURA, cxn03651@msj.biglobe.ne.jp
|
11
|
+
#
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'write_xlsx'
|
15
|
+
|
16
|
+
workbook = WriteXLSX.new('right_to_left.xlsx')
|
17
|
+
worksheet1 = workbook.add_worksheet
|
18
|
+
worksheet2 = workbook.add_worksheet
|
19
|
+
|
20
|
+
worksheet2.right_to_left
|
21
|
+
|
22
|
+
worksheet1.write(0, 0, 'Hello') # A1, B1, C1, ...
|
23
|
+
worksheet2.write(0, 0, 'Hello') # ..., C1, B1, A1
|
24
|
+
workbook.close
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#######################################################################
|
4
|
+
#
|
5
|
+
# Example of how to set Excel worksheet tab colours.
|
6
|
+
#
|
7
|
+
# reverse(c), May 2006, John McNamara, jmcnamara@cpan.org
|
8
|
+
# convert to ruby by Hideo NAKAMURA, cxn03651@msj.biglobe.ne.jp
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'rubygems'
|
12
|
+
require 'write_xlsx'
|
13
|
+
|
14
|
+
workbook = Excel::Writer::XLSX.new('tab_colors.xlsx')
|
15
|
+
|
16
|
+
worksheet1 = workbook.add_worksheet
|
17
|
+
worksheet2 = workbook.add_worksheet
|
18
|
+
worksheet3 = workbook.add_worksheet
|
19
|
+
worksheet4 = workbook.add_worksheet
|
20
|
+
|
21
|
+
# Worksheet1 will have the default tab colour.
|
22
|
+
worksheet2.set_tab_color('red')
|
23
|
+
worksheet3.set_tab_color('green')
|
24
|
+
worksheet4.set_tab_color(0x35) # Orange
|
25
|
+
|
26
|
+
workbook.close
|
data/lib/write_xlsx.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'write_xlsx/workbook'
|
4
|
+
|
5
|
+
#
|
6
|
+
# write_xlsx is gem to create a new file in the Excel 2007+ XLSX format,
|
7
|
+
# and you can use the same interface as writeexcel gem.
|
8
|
+
# write_xlsx is converted from Perl’s module github.com/jmcnamara/excel-writer-xlsx .
|
9
|
+
#
|
10
|
+
# == Description
|
11
|
+
# The WriteXLSX supports the following features:
|
12
|
+
#
|
13
|
+
# Multiple worksheets
|
14
|
+
# Strings and numbers
|
15
|
+
# Unicode text
|
16
|
+
# Rich string formats
|
17
|
+
# Formulas (including array formats)
|
18
|
+
# cell formatting
|
19
|
+
# Embedded images
|
20
|
+
# Charts
|
21
|
+
# Autofilters
|
22
|
+
# Data validation
|
23
|
+
# Hyperlinks
|
24
|
+
# Defined names
|
25
|
+
# Grouping/Outlines
|
26
|
+
# Cell comments
|
27
|
+
# Panes
|
28
|
+
# Page set-up and printing options
|
29
|
+
# WriteXLSX uses the same interface as WriteExcel gem.
|
30
|
+
#
|
31
|
+
# == Synopsis
|
32
|
+
# To write a string, a formatted string, a number and a formula to the
|
33
|
+
# first worksheet in an Excel XMLX spreadsheet called ruby.xlsx:
|
34
|
+
#
|
35
|
+
# require 'rubygems'
|
36
|
+
# require 'write_xlsx'
|
37
|
+
#
|
38
|
+
# # Create a new Excel workbook
|
39
|
+
# workbook = WriteXLSX.new('ruby.xlsx')
|
40
|
+
#
|
41
|
+
# # Add a worksheet
|
42
|
+
# worksheet = workbook.add_worksheet
|
43
|
+
#
|
44
|
+
# # Add and define a format
|
45
|
+
# format = workbook.add_format # Add a format
|
46
|
+
# format.set_bold
|
47
|
+
# format.set_color('red')
|
48
|
+
# format.set_align('center')
|
49
|
+
#
|
50
|
+
# # Write a formatted and unformatted string, row and column notation.
|
51
|
+
# col = row = 0
|
52
|
+
# worksheet.write(row, col, "Hi Excel!", format)
|
53
|
+
# worksheet.write(1, col, "Hi Excel!")
|
54
|
+
#
|
55
|
+
# # Write a number and a formula using A1 notation
|
56
|
+
# worksheet.write('A3', 1.2345)
|
57
|
+
# worksheet.write('A4', '=SIN(PI()/4)')
|
58
|
+
# workbook.close
|
59
|
+
#
|
60
|
+
# == Other Methods
|
61
|
+
#
|
62
|
+
# see Writexlsx::Workbook, Writexlsx::Worksheet, Writexlsx::Chart etc.
|
63
|
+
#
|
64
|
+
class WriteXLSX < Writexlsx::Workbook
|
65
|
+
if RUBY_VERSION < '1.9'
|
66
|
+
$KCODE = 'u'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class WriteXLSXInsufficientArgumentError < StandardError
|
71
|
+
end
|
72
|
+
|
73
|
+
class WriteXLSXDimensionError < StandardError
|
74
|
+
end
|
75
|
+
|
76
|
+
class WriteXLSXOptionParameterError < StandardError
|
77
|
+
end
|
@@ -0,0 +1,3027 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'write_xlsx/package/xml_writer_simple'
|
3
|
+
require 'write_xlsx/utility'
|
4
|
+
|
5
|
+
module Writexlsx
|
6
|
+
# ==SYNOPSIS
|
7
|
+
#
|
8
|
+
# To create a simple Excel file with a chart using WriteXLSX:
|
9
|
+
#
|
10
|
+
# require 'rubygems'
|
11
|
+
# require 'write_xlsx'
|
12
|
+
#
|
13
|
+
# workbook = WriteXLSX.new( 'chart.xlsx' )
|
14
|
+
# worksheet = workbook.add_worksheet
|
15
|
+
#
|
16
|
+
# # Add the worksheet data the chart refers to.
|
17
|
+
# data = [
|
18
|
+
# [ 'Category', 2, 3, 4, 5, 6, 7 ],
|
19
|
+
# [ 'Value', 1, 4, 5, 2, 1, 5 ]
|
20
|
+
# ]
|
21
|
+
#
|
22
|
+
# worksheet.write( 'A1', data )
|
23
|
+
#
|
24
|
+
# # Add a worksheet chart.
|
25
|
+
# chart = workbook.add_chart( type => 'column' )
|
26
|
+
#
|
27
|
+
# # Configure the chart.
|
28
|
+
# chart.add_series(
|
29
|
+
# :categories => '=Sheet1!$A$2:$A$7',
|
30
|
+
# :values => '=Sheet1!$B$2:$B$7'
|
31
|
+
# )
|
32
|
+
#
|
33
|
+
# workbook.close
|
34
|
+
#
|
35
|
+
# ==DESCRIPTION
|
36
|
+
#
|
37
|
+
# The Chart module is an abstract base class for modules that implement
|
38
|
+
# charts in WriteXLSX. The information below is applicable to all of
|
39
|
+
# the available subclasses.
|
40
|
+
#
|
41
|
+
# The Chart module isn't used directly. A chart object is created via
|
42
|
+
# the Workbook add_chart() method where the chart type is specified:
|
43
|
+
#
|
44
|
+
# chart = workbook.add_chart( :type => 'column' )
|
45
|
+
#
|
46
|
+
# Currently the supported chart types are:
|
47
|
+
#
|
48
|
+
# ===area
|
49
|
+
# Creates an Area (filled line) style chart. See Writexlsx::Chart::Area.
|
50
|
+
#
|
51
|
+
# ===bar
|
52
|
+
# Creates a Bar style (transposed histogram) chart. See Writexlsx::Chart::Bar.
|
53
|
+
#
|
54
|
+
# ===column
|
55
|
+
# Creates a column style (histogram) chart. See Writexlsx::Chart::Column.
|
56
|
+
#
|
57
|
+
# ===line
|
58
|
+
# Creates a Line style chart. See Writexlsx::Chart::Line.
|
59
|
+
#
|
60
|
+
# ===pie
|
61
|
+
# Creates an Pie style chart. See Writexlsx::Chart::Pie.
|
62
|
+
#
|
63
|
+
# ===scatter
|
64
|
+
# Creates an Scatter style chart. See Writexlsx::Chart::Scatter.
|
65
|
+
#
|
66
|
+
# ===stock
|
67
|
+
# Creates an Stock style chart. See Writexlsx::Chart::Stock.
|
68
|
+
#
|
69
|
+
# ==CHART FORMATTING
|
70
|
+
#
|
71
|
+
# The following chart formatting properties can be set for any chart object
|
72
|
+
# that they apply to (and that are supported by Excel::Writer::XLSX) such
|
73
|
+
# as chart lines, column fill areas, plot area borders, markers and other
|
74
|
+
# chart elements documented above.
|
75
|
+
#
|
76
|
+
# line
|
77
|
+
# border
|
78
|
+
# fill
|
79
|
+
# marker
|
80
|
+
# trendline
|
81
|
+
# data_labels
|
82
|
+
# Chart formatting properties are generally set using hash refs.
|
83
|
+
#
|
84
|
+
# chart.add_series(
|
85
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
86
|
+
# :line => { color => 'blue' }
|
87
|
+
# )
|
88
|
+
# In some cases the format properties can be nested. For example a marker
|
89
|
+
# may contain border and fill sub-properties.
|
90
|
+
#
|
91
|
+
# chart.add_series(
|
92
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
93
|
+
# :line => { color => 'blue' },
|
94
|
+
# :marker => {
|
95
|
+
# :type => 'square',
|
96
|
+
# :size => 5,
|
97
|
+
# :border => { color => 'red' },
|
98
|
+
# :fill => { color => 'yellow' }
|
99
|
+
# }
|
100
|
+
# )
|
101
|
+
# ===Line
|
102
|
+
#
|
103
|
+
# The line format is used to specify properties of line objects that appear
|
104
|
+
# in a chart such as a plotted line on a chart or a border.
|
105
|
+
#
|
106
|
+
# The following properties can be set for line formats in a chart.
|
107
|
+
#
|
108
|
+
# none
|
109
|
+
# color
|
110
|
+
# width
|
111
|
+
# dash_type
|
112
|
+
# The none property is uses to turn the line off (it is always on by default
|
113
|
+
# except in Scatter charts). This is useful if you wish to plot a series
|
114
|
+
# with markers but without a line.
|
115
|
+
#
|
116
|
+
# chart.add_series(
|
117
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
118
|
+
# :line => { none => 1 }
|
119
|
+
# )
|
120
|
+
# The color property sets the color of the line.
|
121
|
+
#
|
122
|
+
# chart.add_series(
|
123
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
124
|
+
# :line => { color => 'red' }
|
125
|
+
# )
|
126
|
+
# The available colors are shown in the main WriteXLSX documentation.
|
127
|
+
# It is also possible to set the color of a line with a HTML style RGB color:
|
128
|
+
#
|
129
|
+
# chart.add_series(
|
130
|
+
# :line => { color => '#FF0000' }
|
131
|
+
# )
|
132
|
+
# The width property sets the width of the line. It should be specified
|
133
|
+
# in increments of 0.25 of a point as in Excel.
|
134
|
+
#
|
135
|
+
# chart.add_series(
|
136
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
137
|
+
# :line => { width => 3.25 }
|
138
|
+
# )
|
139
|
+
# The dash_type property sets the dash style of the line.
|
140
|
+
#
|
141
|
+
# chart->add_series(
|
142
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
143
|
+
# :line => { dash_type => 'dash_dot' }
|
144
|
+
# )
|
145
|
+
# The following dash_type values are available. They are shown in the
|
146
|
+
# order that they appear in the Excel dialog.
|
147
|
+
#
|
148
|
+
# solid
|
149
|
+
# round_dot
|
150
|
+
# square_dot
|
151
|
+
# dash
|
152
|
+
# dash_dot
|
153
|
+
# long_dash
|
154
|
+
# long_dash_dot
|
155
|
+
# long_dash_dot_dot
|
156
|
+
# The default line style is solid.
|
157
|
+
#
|
158
|
+
# More than one line property can be specified at time:
|
159
|
+
#
|
160
|
+
# chart.add_series(
|
161
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
162
|
+
# :line => {
|
163
|
+
# :color => 'red',
|
164
|
+
# :width => 1.25,
|
165
|
+
# :dash_type => 'square_dot'
|
166
|
+
# }
|
167
|
+
# )
|
168
|
+
# ===Border
|
169
|
+
#
|
170
|
+
# The border property is a synonym for line.
|
171
|
+
#
|
172
|
+
# It can be used as a descriptive substitute for line in chart types such
|
173
|
+
# as Bar and Column that have a border and fill style rather than a line
|
174
|
+
# style. In general chart objects with a border property will also have a
|
175
|
+
# fill property.
|
176
|
+
#
|
177
|
+
# ===Fill
|
178
|
+
#
|
179
|
+
# The fill format is used to specify filled areas of chart objects such
|
180
|
+
# as the interior of a column or the background of the chart itself.
|
181
|
+
#
|
182
|
+
# The following properties can be set for fill formats in a chart.
|
183
|
+
#
|
184
|
+
# none
|
185
|
+
# color
|
186
|
+
# The none property is uses to turn the fill property off (it is
|
187
|
+
# generally on by default).
|
188
|
+
#
|
189
|
+
# chart.add_series(
|
190
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
191
|
+
# :fill => { none => 1 }
|
192
|
+
# )
|
193
|
+
# The color property sets the color of the fill area.
|
194
|
+
#
|
195
|
+
# chart.add_series(
|
196
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
197
|
+
# :fill => { color => 'red' }
|
198
|
+
# )
|
199
|
+
# The available colors are shown in the main WriteXLSX documentation.
|
200
|
+
# It is also possible to set the color of a fill with a HTML style RGB color:
|
201
|
+
#
|
202
|
+
# chart.add_series(
|
203
|
+
# :fill => { color => '#FF0000' }
|
204
|
+
# )
|
205
|
+
# The fill format is generally used in conjunction with a border format
|
206
|
+
# which has the same properties as a line format.
|
207
|
+
#
|
208
|
+
# chart.add_series(
|
209
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
210
|
+
# :border => { color => 'red' },
|
211
|
+
# :fill => { color => 'yellow' }
|
212
|
+
# )
|
213
|
+
# ===Marker
|
214
|
+
#
|
215
|
+
# The marker format specifies the properties of the markers used to
|
216
|
+
# distinguish series on a chart. In general only Line and Scatter
|
217
|
+
# chart types and trendlines use markers.
|
218
|
+
#
|
219
|
+
# The following properties can be set for marker formats in a chart.
|
220
|
+
#
|
221
|
+
# type
|
222
|
+
# size
|
223
|
+
# border
|
224
|
+
# fill
|
225
|
+
# The type property sets the type of marker that is used with a series.
|
226
|
+
#
|
227
|
+
# chart.add_series(
|
228
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
229
|
+
# :marker => { type => 'diamond' }
|
230
|
+
# )
|
231
|
+
# The following type properties can be set for marker formats in a chart.
|
232
|
+
# These are shown in the same order as in the Excel format dialog.
|
233
|
+
#
|
234
|
+
# automatic
|
235
|
+
# none
|
236
|
+
# square
|
237
|
+
# diamond
|
238
|
+
# triangle
|
239
|
+
# x
|
240
|
+
# star
|
241
|
+
# short_dash
|
242
|
+
# long_dash
|
243
|
+
# circle
|
244
|
+
# plus
|
245
|
+
# The automatic type is a special case which turns on a marker using the
|
246
|
+
# default marker style for the particular series number.
|
247
|
+
#
|
248
|
+
# chart.add_series(
|
249
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
250
|
+
# :marker => { type => 'automatic' }
|
251
|
+
# )
|
252
|
+
# If automatic is on then other marker properties such as size,
|
253
|
+
# border or fill cannot be set.
|
254
|
+
#
|
255
|
+
# The size property sets the size of the marker and is generally used in
|
256
|
+
# conjunction with type.
|
257
|
+
#
|
258
|
+
# chart.add_series(
|
259
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
260
|
+
# :marker => { type => 'diamond', size => 7 }
|
261
|
+
# )
|
262
|
+
# Nested border and fill properties can also be set for a marker.
|
263
|
+
# These have the same sub-properties as shown above.
|
264
|
+
#
|
265
|
+
# chart.add_series(
|
266
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
267
|
+
# :marker => {
|
268
|
+
# :type => 'square',
|
269
|
+
# :size => 5,
|
270
|
+
# :border => { color => 'red' },
|
271
|
+
# :fill => { color => 'yellow' }
|
272
|
+
# }
|
273
|
+
# )
|
274
|
+
# ===Trendline
|
275
|
+
#
|
276
|
+
# A trendline can be added to a chart series to indicate trends in the data
|
277
|
+
# such as a moving average or a polynomial fit.
|
278
|
+
#
|
279
|
+
# The following properties can be set for trendline formats in a chart.
|
280
|
+
#
|
281
|
+
# type
|
282
|
+
# order (for polynomial trends)
|
283
|
+
# period (for moving average)
|
284
|
+
# forward (for all except moving average)
|
285
|
+
# backward (for all except moving average)
|
286
|
+
# name
|
287
|
+
# line
|
288
|
+
# The type property sets the type of trendline in the series.
|
289
|
+
#
|
290
|
+
# chart.add_series(
|
291
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
292
|
+
# :trendline => { type => 'linear' }
|
293
|
+
# )
|
294
|
+
# The available trendline types are:
|
295
|
+
#
|
296
|
+
# exponential
|
297
|
+
# linear
|
298
|
+
# log
|
299
|
+
# moving_average
|
300
|
+
# polynomial
|
301
|
+
# power
|
302
|
+
# A polynomial trendline can also specify the order of the polynomial.
|
303
|
+
# The default value is 2.
|
304
|
+
#
|
305
|
+
# chart.add_series(
|
306
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
307
|
+
# :trendline => {
|
308
|
+
# :type => 'polynomial',
|
309
|
+
# :order => 3
|
310
|
+
# }
|
311
|
+
# )
|
312
|
+
# A moving_average trendline can also the period of the moving average.
|
313
|
+
# The default value is 2.
|
314
|
+
#
|
315
|
+
# chart.add_series(
|
316
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
317
|
+
# :trendline => {
|
318
|
+
# :type => 'moving_average',
|
319
|
+
# :period => 3
|
320
|
+
# }
|
321
|
+
# )
|
322
|
+
# The forward and backward properties set the forecast period of the
|
323
|
+
# trendline.
|
324
|
+
#
|
325
|
+
# chart.add_series(
|
326
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
327
|
+
# :trendline => {
|
328
|
+
# :type => 'linear',
|
329
|
+
# :forward => 0.5,
|
330
|
+
# :backward => 0.5
|
331
|
+
# }
|
332
|
+
# )
|
333
|
+
# The name property sets an optional name for the trendline that will
|
334
|
+
# appear in the chart legend. If it isn't specified the Excel default
|
335
|
+
# name will be displayed. This is usually a combination of the trendline
|
336
|
+
# type and the series name.
|
337
|
+
#
|
338
|
+
# chart.add_series(
|
339
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
340
|
+
# :trendline => {
|
341
|
+
# :type => 'linear',
|
342
|
+
# :name => 'Interpolated trend'
|
343
|
+
# }
|
344
|
+
# )
|
345
|
+
# Several of these properties can be set in one go:
|
346
|
+
#
|
347
|
+
# chart.add_series(
|
348
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
349
|
+
# :trendline => {
|
350
|
+
# :type => 'linear',
|
351
|
+
# :name => 'My trend name',
|
352
|
+
# :forward => 0.5,
|
353
|
+
# :backward => 0.5,
|
354
|
+
# :line => {
|
355
|
+
# :color => 'red',
|
356
|
+
# :width => 1,
|
357
|
+
# :dash_type => 'long_dash'
|
358
|
+
# }
|
359
|
+
# }
|
360
|
+
# )
|
361
|
+
# Trendlines cannot be added to series in a stacked chart or pie chart or
|
362
|
+
# (when implemented) to 3-D, radar, surface, or doughnut charts.
|
363
|
+
#
|
364
|
+
# ==Data Labels
|
365
|
+
#
|
366
|
+
# Data labels can be added to a chart series to indicate the values of
|
367
|
+
# the plotted data points.
|
368
|
+
#
|
369
|
+
# The following properties can be set for data_labels formats in a chart.
|
370
|
+
#
|
371
|
+
# value
|
372
|
+
# category
|
373
|
+
# series_name
|
374
|
+
# The value property turns on the Value data label for a series.
|
375
|
+
#
|
376
|
+
# chart.add_series(
|
377
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
378
|
+
# :data_labels => { value => 1 }
|
379
|
+
# )
|
380
|
+
# The category property turns on the Category Name data label for a series.
|
381
|
+
#
|
382
|
+
# chart.add_series(
|
383
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
384
|
+
# :data_labels => { category => 1 }
|
385
|
+
# )
|
386
|
+
# The series_name property turns on the Series Name data label for a series.
|
387
|
+
#
|
388
|
+
# chart.add_series(
|
389
|
+
# :values => '=Sheet1!$B$1:$B$5',
|
390
|
+
# :data_labels => { series_name => 1 }
|
391
|
+
# )
|
392
|
+
# Other formatting options
|
393
|
+
#
|
394
|
+
# Other formatting options will be added in time. If there is a feature that
|
395
|
+
# you would like to see included drop me a line.
|
396
|
+
#
|
397
|
+
class Chart
|
398
|
+
include Writexlsx::Utility
|
399
|
+
|
400
|
+
attr_accessor :id # :nodoc:
|
401
|
+
attr_writer :index, :palette # :nodoc:
|
402
|
+
attr_reader :embedded, :formula_ids, :formula_data # :nodoc:
|
403
|
+
|
404
|
+
#
|
405
|
+
# Factory method for returning chart objects based on their class type.
|
406
|
+
#
|
407
|
+
def self.factory(chart_subclass) # :nodoc:
|
408
|
+
case chart_subclass.downcase.capitalize
|
409
|
+
when 'Area'
|
410
|
+
require 'write_xlsx/chart/area'
|
411
|
+
Chart::Area.new
|
412
|
+
when 'Bar'
|
413
|
+
require 'write_xlsx/chart/bar'
|
414
|
+
Chart::Bar.new
|
415
|
+
when 'Column'
|
416
|
+
require 'write_xlsx/chart/column'
|
417
|
+
Chart::Column.new
|
418
|
+
when 'Line'
|
419
|
+
require 'write_xlsx/chart/line'
|
420
|
+
Chart::Line.new
|
421
|
+
when 'Pie'
|
422
|
+
require 'write_xlsx/chart/pie'
|
423
|
+
Chart::Pie.new
|
424
|
+
when 'Scatter'
|
425
|
+
require 'write_xlsx/chart/scatter'
|
426
|
+
Chart::Scatter.new
|
427
|
+
when 'Stock'
|
428
|
+
require 'write_xlsx/chart/stock'
|
429
|
+
Chart::Stock.new
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
def initialize(subtype) # :nodoc:
|
434
|
+
@writer = Package::XMLWriterSimple.new
|
435
|
+
|
436
|
+
@subtype = subtype
|
437
|
+
@sheet_type = 0x0200
|
438
|
+
@orientation = 0x0
|
439
|
+
@series = []
|
440
|
+
@embedded = 0
|
441
|
+
@id = ''
|
442
|
+
@style_id = 2
|
443
|
+
@axis_ids = []
|
444
|
+
@has_category = 0
|
445
|
+
@requires_category = 0
|
446
|
+
@legend_position = 'right'
|
447
|
+
@cat_axis_position = 'b'
|
448
|
+
@val_axis_position = 'l'
|
449
|
+
@formula_ids = {}
|
450
|
+
@formula_data = []
|
451
|
+
@horiz_cat_axis = 0
|
452
|
+
@horiz_val_axis = 1
|
453
|
+
@protection = 0
|
454
|
+
@x_axis = {}
|
455
|
+
@y_axis = {}
|
456
|
+
|
457
|
+
set_default_properties
|
458
|
+
end
|
459
|
+
|
460
|
+
def set_xml_writer(filename) # :nodoc:
|
461
|
+
@writer.set_xml_writer(filename)
|
462
|
+
end
|
463
|
+
|
464
|
+
#
|
465
|
+
# Assemble and write the XML file.
|
466
|
+
#
|
467
|
+
def assemble_xml_file # :nodoc:
|
468
|
+
@writer.xml_decl
|
469
|
+
|
470
|
+
# Write the c:chartSpace element.
|
471
|
+
write_chart_space
|
472
|
+
|
473
|
+
# Write the c:lang element.
|
474
|
+
write_lang
|
475
|
+
|
476
|
+
# Write the c:style element.
|
477
|
+
write_style
|
478
|
+
|
479
|
+
# Write the c:protection element.
|
480
|
+
write_protection
|
481
|
+
|
482
|
+
# Write the c:chart element.
|
483
|
+
write_chart
|
484
|
+
|
485
|
+
# Write the c:printSettings element.
|
486
|
+
write_print_settings if @embedded
|
487
|
+
|
488
|
+
# Close the worksheet tag.
|
489
|
+
@writer.end_tag( 'c:chartSpace')
|
490
|
+
|
491
|
+
# Close the XML writer object and filehandle.
|
492
|
+
@writer.crlf
|
493
|
+
@writer.close
|
494
|
+
end
|
495
|
+
|
496
|
+
#
|
497
|
+
# Add a series and it's properties to a chart.
|
498
|
+
#
|
499
|
+
# In an Excel chart a "series" is a collection of information such as
|
500
|
+
# values, x-axis labels and the formatting that define which data is
|
501
|
+
# plotted.
|
502
|
+
#
|
503
|
+
# With a WriteXLSX chart object the add_series() method is used to
|
504
|
+
# set the properties for a series:
|
505
|
+
#
|
506
|
+
# chart.add_series(
|
507
|
+
# :categories => '=Sheet1!$A$2:$A$10', # Optional.
|
508
|
+
# :values => '=Sheet1!$B$2:$B$10', # Required.
|
509
|
+
# :line => { color => 'blue' }
|
510
|
+
# )
|
511
|
+
#
|
512
|
+
# The properties that can be set are:
|
513
|
+
#
|
514
|
+
# ====:values
|
515
|
+
# This is the most important property of a series and must be set
|
516
|
+
# for every chart object. It links the chart with the worksheet data
|
517
|
+
# that it displays. A formula or array ref can be used for the
|
518
|
+
# data range, see below.
|
519
|
+
#
|
520
|
+
# ====:categories
|
521
|
+
# This sets the chart category labels. The category is more or less
|
522
|
+
# the same as the X-axis. In most chart types the categories property
|
523
|
+
# is optional and the chart will just assume a sequential series
|
524
|
+
# from 1 .. n.
|
525
|
+
#
|
526
|
+
# ====:name
|
527
|
+
# Set the name for the series. The name is displayed in the chart
|
528
|
+
# legend and in the formula bar. The name property is optional and
|
529
|
+
# if it isn't supplied it will default to Series 1 .. n.
|
530
|
+
#
|
531
|
+
# ====:line
|
532
|
+
# Set the properties of the series line type such as colour and
|
533
|
+
# width. See the "CHART FORMATTING" section below.
|
534
|
+
#
|
535
|
+
# ====:border
|
536
|
+
# Set the border properties of the series such as colour and style.
|
537
|
+
# See the "CHART FORMATTING" section below.
|
538
|
+
#
|
539
|
+
# ====:fill
|
540
|
+
# Set the fill properties of the series such as colour. See the
|
541
|
+
# "CHART FORMATTING" section below.
|
542
|
+
#
|
543
|
+
# ====:marker
|
544
|
+
# Set the properties of the series marker such as style and color.
|
545
|
+
# See the "CHART FORMATTING" section below.
|
546
|
+
#
|
547
|
+
# ====:trendline
|
548
|
+
# Set the properties of the series trendline such as linear,
|
549
|
+
# polynomial and moving average types. See the "CHART FORMATTING"
|
550
|
+
# section below.
|
551
|
+
#
|
552
|
+
# ====:data_labels
|
553
|
+
# Set data labels for the series. See the "CHART FORMATTING"
|
554
|
+
# section below.
|
555
|
+
#
|
556
|
+
# ====:invert_if_negative
|
557
|
+
# Invert the fill colour for negative values. Usually only applicable
|
558
|
+
# to column and bar charts.
|
559
|
+
#
|
560
|
+
# The categories and values can take either a range formula such
|
561
|
+
# as =Sheet1!$A$2:$A$7 or, more usefully when generating the range
|
562
|
+
# programmatically, an array ref with zero indexed row/column values:
|
563
|
+
#
|
564
|
+
# [ sheetname, row_start, row_end, col_start, col_end ]
|
565
|
+
# The following are equivalent:
|
566
|
+
#
|
567
|
+
# chart.add_series( categories => '=Sheet1!$A$2:$A$7' ) # Same as ...
|
568
|
+
# chart.add_series( categories => [ 'Sheet1', 1, 6, 0, 0 ] ) # Zero-indexed.
|
569
|
+
#
|
570
|
+
# You can add more than one series to a chart. In fact, some chart
|
571
|
+
# types such as stock require it. The series numbering and order in
|
572
|
+
# the Excel chart will be the same as the order in which that are added
|
573
|
+
# in Excel::Writer::XLSX.
|
574
|
+
#
|
575
|
+
# # Add the first series.
|
576
|
+
# chart.add_series(
|
577
|
+
# :categories => '=Sheet1!$A$2:$A$7',
|
578
|
+
# :values => '=Sheet1!$B$2:$B$7',
|
579
|
+
# :name => 'Test data series 1'
|
580
|
+
# )
|
581
|
+
#
|
582
|
+
# # Add another series. Same categories. Different range values.
|
583
|
+
# chart.add_series(
|
584
|
+
# :categories => '=Sheet1!$A$2:$A$7',
|
585
|
+
# :values => '=Sheet1!$C$2:$C$7',
|
586
|
+
# :name => 'Test data series 2'
|
587
|
+
# )
|
588
|
+
#
|
589
|
+
def add_series(params)
|
590
|
+
# Check that the required input has been specified.
|
591
|
+
unless params.has_key?(:values)
|
592
|
+
raise "Must specify ':values' in add_series"
|
593
|
+
end
|
594
|
+
|
595
|
+
if @requires_category != 0 && !params.has_key?(:categories)
|
596
|
+
raise "Must specify ':categories' in add_series for this chart type"
|
597
|
+
end
|
598
|
+
|
599
|
+
# Convert aref params into a formula string.
|
600
|
+
values = aref_to_formula(params[:values])
|
601
|
+
categories = aref_to_formula(params[:categories])
|
602
|
+
|
603
|
+
# Switch name and name_formula parameters if required.
|
604
|
+
name, name_formula = process_names(params[:name], params[:name_formula])
|
605
|
+
|
606
|
+
# Get an id for the data equivalent to the range formula.
|
607
|
+
cat_id = get_data_id(categories, params[:categories_data])
|
608
|
+
val_id = get_data_id(values, params[:values_data])
|
609
|
+
name_id = get_data_id(name_formula, params[:name_data])
|
610
|
+
|
611
|
+
# Set the line properties for the series.
|
612
|
+
line = get_line_properties(params[:line])
|
613
|
+
|
614
|
+
# Allow 'border' as a synonym for 'line' in bar/column style charts.
|
615
|
+
line = get_line_properties(params[:border]) if params[:border]
|
616
|
+
|
617
|
+
# Set the fill properties for the series.
|
618
|
+
fill = get_fill_properties(params[:fill])
|
619
|
+
|
620
|
+
# Set the marker properties for the series.
|
621
|
+
marker = get_marker_properties(params[:marker])
|
622
|
+
|
623
|
+
# Set the trendline properties for the series.
|
624
|
+
trendline = get_trendline_properties(params[:trendline])
|
625
|
+
|
626
|
+
# Set the labels properties for the series.
|
627
|
+
labels = get_labels_properties(params[:data_labels])
|
628
|
+
|
629
|
+
# Set the "invert if negative" fill property.
|
630
|
+
invert_if_neg = params[:invert_if_negative]
|
631
|
+
|
632
|
+
# Add the user supplied data to the internal structures.
|
633
|
+
@series << {
|
634
|
+
:_values => values,
|
635
|
+
:_categories => categories,
|
636
|
+
:_name => name,
|
637
|
+
:_name_formula => name_formula,
|
638
|
+
:_name_id => name_id,
|
639
|
+
:_val_data_id => val_id,
|
640
|
+
:_cat_data_id => cat_id,
|
641
|
+
:_line => line,
|
642
|
+
:_fill => fill,
|
643
|
+
:_marker => marker,
|
644
|
+
:_trendline => trendline,
|
645
|
+
:_labels => labels,
|
646
|
+
:_invert_if_neg => invert_if_neg
|
647
|
+
}
|
648
|
+
end
|
649
|
+
|
650
|
+
#
|
651
|
+
# Set the properties of the X-axis.
|
652
|
+
#
|
653
|
+
# The set_x_axis() method is used to set properties of the X axis.
|
654
|
+
#
|
655
|
+
# chart.set_x_axis( :name => 'Quarterly results' )
|
656
|
+
#
|
657
|
+
# The properties that can be set are:
|
658
|
+
#
|
659
|
+
# :name
|
660
|
+
# :min
|
661
|
+
# :max
|
662
|
+
# :minor_unit
|
663
|
+
# :major_unit
|
664
|
+
# :crossing
|
665
|
+
# :reverse
|
666
|
+
# :log_base
|
667
|
+
# :label_position
|
668
|
+
#
|
669
|
+
# These are explained below. Some properties are only applicable to value
|
670
|
+
# or category axes, as indicated. See "Value and Category Axes" for an
|
671
|
+
# explanation of Excel's distinction between the axis types.
|
672
|
+
#
|
673
|
+
# ====:name
|
674
|
+
# Set the name (title or caption) for the axis. The name is displayed
|
675
|
+
# below the X axis. The name property is optional. The default is to
|
676
|
+
# have no axis name. (Applicable to category and value axes).
|
677
|
+
#
|
678
|
+
# chart.set_x_axis( :name => 'Quarterly results' )
|
679
|
+
#
|
680
|
+
# The name can also be a formula such as =Sheet1!$A$1.
|
681
|
+
#
|
682
|
+
# ====:min
|
683
|
+
# Set the minimum value for the axis range.
|
684
|
+
# (Applicable to value axes only).
|
685
|
+
#
|
686
|
+
# chart.set_x_axis( :min => 20 )
|
687
|
+
# ====:max
|
688
|
+
# Set the maximum value for the axis range.
|
689
|
+
# (Applicable to value axes only).
|
690
|
+
#
|
691
|
+
# chart.set_x_axis( :max => 80 )
|
692
|
+
# ====:minor_unit
|
693
|
+
# Set the increment of the minor units in the axis range.
|
694
|
+
# (Applicable to value axes only).
|
695
|
+
#
|
696
|
+
# chart.set_x_axis( :minor_unit => 0.4 )
|
697
|
+
# ====:major_unit
|
698
|
+
# Set the increment of the major units in the axis range.
|
699
|
+
# (Applicable to value axes only).
|
700
|
+
#
|
701
|
+
# chart.set_x_axis( :major_unit => 2 )
|
702
|
+
# ====:crossing
|
703
|
+
# Set the position where the y axis will cross the x axis.
|
704
|
+
# (Applicable to category and value axes).
|
705
|
+
#
|
706
|
+
# The crossing value can either be the string 'max' to set the crossing
|
707
|
+
# at the maximum axis value or a numeric value.
|
708
|
+
#
|
709
|
+
# chart.set_x_axis( :crossing => 3 )
|
710
|
+
# # or
|
711
|
+
# chart.set_x_axis( :crossing => 'max' )
|
712
|
+
# For category axes the numeric value must be an integer to represent
|
713
|
+
# the category number that the axis crosses at. For value axes it can
|
714
|
+
# have any value associated with the axis.
|
715
|
+
#
|
716
|
+
# If crossing is omitted (the default) the crossing will be set
|
717
|
+
# automatically by Excel based on the chart data.
|
718
|
+
#
|
719
|
+
# ====:reverse
|
720
|
+
# Reverse the order of the axis categories or values.
|
721
|
+
# (Applicable to category and value axes).
|
722
|
+
#
|
723
|
+
# chart.set_x_axis( :reverse => 1 )
|
724
|
+
# ====:log_base
|
725
|
+
# Set the log base of the axis range.
|
726
|
+
# (Applicable to value axes only).
|
727
|
+
#
|
728
|
+
# chart.set_x_axis( :log_base => 10 )
|
729
|
+
# ====:label_position
|
730
|
+
# Set the "Axis labels" position for the axis.
|
731
|
+
# The following positions are available:
|
732
|
+
#
|
733
|
+
# next_to (the default)
|
734
|
+
# high
|
735
|
+
# low
|
736
|
+
# none
|
737
|
+
# More than one property can be set in a call to set_x_axis:
|
738
|
+
#
|
739
|
+
# chart.set_x_axis(
|
740
|
+
# :name => 'Quarterly results',
|
741
|
+
# :min => 10,
|
742
|
+
# :max => 80
|
743
|
+
# )
|
744
|
+
#
|
745
|
+
def set_x_axis(params)
|
746
|
+
@x_axis = convert_axis_args(params)
|
747
|
+
end
|
748
|
+
|
749
|
+
#
|
750
|
+
# Set the properties of the Y-axis.
|
751
|
+
#
|
752
|
+
# The set_y_axis() method is used to set properties of the Y axis.
|
753
|
+
# The properties that can be set are the same as for set_x_axis,
|
754
|
+
#
|
755
|
+
def set_y_axis(params)
|
756
|
+
@y_axis = convert_axis_args(params)
|
757
|
+
end
|
758
|
+
|
759
|
+
#
|
760
|
+
# Set the properties of the chart title.
|
761
|
+
#
|
762
|
+
# The set_title() method is used to set properties of the chart title.
|
763
|
+
#
|
764
|
+
# chart.set_title( :name => 'Year End Results' )
|
765
|
+
# The properties that can be set are:
|
766
|
+
#
|
767
|
+
# ====:name
|
768
|
+
# Set the name (title) for the chart. The name is displayed above the
|
769
|
+
# chart. The name can also be a formula such as =Sheet1!$A$1. The name
|
770
|
+
# property is optional. The default is to have no chart title.
|
771
|
+
#
|
772
|
+
def set_title(params)
|
773
|
+
name, name_formula = process_names(params[:name], params[:name_formula])
|
774
|
+
|
775
|
+
data_id = get_data_id(name_formula, params[:data])
|
776
|
+
|
777
|
+
@title_name = name
|
778
|
+
@title_formula = name_formula
|
779
|
+
@title_data_id = data_id
|
780
|
+
end
|
781
|
+
|
782
|
+
#
|
783
|
+
# Set the properties of the chart legend.
|
784
|
+
#
|
785
|
+
# The set_legend() method is used to set properties of the chart legend.
|
786
|
+
#
|
787
|
+
# chart.set_legend( :position => 'none' )
|
788
|
+
# The properties that can be set are:
|
789
|
+
#
|
790
|
+
# ====:position
|
791
|
+
# Set the position of the chart legend.
|
792
|
+
#
|
793
|
+
# chart.set_legend( :position => 'bottom' )
|
794
|
+
# The default legend position is right. The available positions are:
|
795
|
+
#
|
796
|
+
# none
|
797
|
+
# top
|
798
|
+
# bottom
|
799
|
+
# left
|
800
|
+
# right
|
801
|
+
# overlay_left
|
802
|
+
# overlay_right
|
803
|
+
# ====:delete_series
|
804
|
+
# This allows you to remove 1 or more series from the the legend
|
805
|
+
# (the series will still display on the chart). This property takes
|
806
|
+
# an array ref as an argument and the series are zero indexed:
|
807
|
+
#
|
808
|
+
# # Delete/hide series index 0 and 2 from the legend.
|
809
|
+
# chart.set_legend( :delete_series => [0, 2] )
|
810
|
+
#
|
811
|
+
def set_legend(params)
|
812
|
+
@legend_position = params[:position] || 'right'
|
813
|
+
@legend_delete_series = params[:delete_series]
|
814
|
+
end
|
815
|
+
|
816
|
+
#
|
817
|
+
# Set the properties of the chart plotarea.
|
818
|
+
#
|
819
|
+
# The set_plotarea() method is used to set properties of the plot area
|
820
|
+
# of a chart.
|
821
|
+
#
|
822
|
+
# This method isn't implemented yet and is only available in
|
823
|
+
# writeexcel gem. However, it can be simulated using the
|
824
|
+
# set_style() method.
|
825
|
+
#
|
826
|
+
def set_plotarea(params)
|
827
|
+
|
828
|
+
# TODO. Need to refactor for XLSX format.
|
829
|
+
return
|
830
|
+
|
831
|
+
return if params.empty?
|
832
|
+
|
833
|
+
area = @plotarea
|
834
|
+
|
835
|
+
# Set the plotarea visibility.
|
836
|
+
if params[:visible]
|
837
|
+
area[:_visible] = params[:visible]
|
838
|
+
return unless area[:_visible]
|
839
|
+
end
|
840
|
+
|
841
|
+
# TODO. could move this out of if statement.
|
842
|
+
area[:_bg_color_index] = 0x08
|
843
|
+
|
844
|
+
# Set the chart background colour.
|
845
|
+
if params[:color]
|
846
|
+
index, rgb = get_color_indices(params[:color])
|
847
|
+
if index
|
848
|
+
area[:_fg_color_index] = index
|
849
|
+
area[:_fg_color_rgb] = rgb
|
850
|
+
area[:_bg_color_index] = 0x08
|
851
|
+
area[:_bg_color_rgb] = 0x000000
|
852
|
+
end
|
853
|
+
|
854
|
+
end
|
855
|
+
|
856
|
+
# Set the border line colour.
|
857
|
+
if params[:line_color]
|
858
|
+
index, rgb = get_color_indices(params[:line_color])
|
859
|
+
if index
|
860
|
+
area[:_line_color_index] = index
|
861
|
+
area[:_line_color_rgb] = rgb
|
862
|
+
end
|
863
|
+
end
|
864
|
+
|
865
|
+
# Set the border line pattern.
|
866
|
+
if params[:line_pattern]
|
867
|
+
pattern = get_line_pattern(params[:line_pattern])
|
868
|
+
area[:_line_pattern] = pattern
|
869
|
+
end
|
870
|
+
|
871
|
+
# Set the border line weight.
|
872
|
+
if params[:line_weight]
|
873
|
+
weight = get_line_weight(params[:line_weight])
|
874
|
+
area[:_line_weight] = weight
|
875
|
+
end
|
876
|
+
end
|
877
|
+
|
878
|
+
#
|
879
|
+
# Set the properties of the chart chartarea.
|
880
|
+
#
|
881
|
+
# The set_chartarea() method is used to set the properties of the chart
|
882
|
+
# area.
|
883
|
+
#
|
884
|
+
# This method isn't implemented yet and is only available in
|
885
|
+
# writeexcel gem. However, it can be simulated using the
|
886
|
+
# set_style() method.
|
887
|
+
#
|
888
|
+
def set_chartarea(params)
|
889
|
+
# TODO. Need to refactor for XLSX format.
|
890
|
+
return
|
891
|
+
|
892
|
+
return if params.empty?
|
893
|
+
|
894
|
+
area = @chartarea
|
895
|
+
|
896
|
+
# Embedded automatic line weight has a different default value.
|
897
|
+
area[:_line_weight] = 0xFFFF if @embedded
|
898
|
+
|
899
|
+
# Set the chart background colour.
|
900
|
+
if params[:color]
|
901
|
+
index, rgb = get_color_indices(params[:color])
|
902
|
+
if index
|
903
|
+
area[:_fg_color_index] = index
|
904
|
+
area[:_fg_color_rgb] = rgb
|
905
|
+
area[:_bg_color_index] = 0x08
|
906
|
+
area[:_bg_color_rgb] = 0x000000
|
907
|
+
area[:_area_pattern] = 1
|
908
|
+
area[:_area_options] = 0x0000 if @embedded
|
909
|
+
area[:_visible] = 1
|
910
|
+
end
|
911
|
+
end
|
912
|
+
|
913
|
+
# Set the border line colour.
|
914
|
+
if params[:line_color]
|
915
|
+
index, rgb = get_color_indices(params[:line_color])
|
916
|
+
if index
|
917
|
+
area[:_line_color_index] = index
|
918
|
+
area[:_line_color_rgb] = rgb
|
919
|
+
area[:_line_pattern] = 0x00
|
920
|
+
area[:_line_options] = 0x0000
|
921
|
+
area[:_visible] = 1
|
922
|
+
end
|
923
|
+
end
|
924
|
+
|
925
|
+
# Set the border line pattern.
|
926
|
+
if params[:line_pattern]
|
927
|
+
pattern = get_line_pattern(params[:line_pattern])
|
928
|
+
area[:_line_pattern] = pattern
|
929
|
+
area[:_line_options] = 0x0000
|
930
|
+
area[:_line_color_index] = 0x4F unless params[:line_color]
|
931
|
+
area[:_visible] = 1
|
932
|
+
end
|
933
|
+
|
934
|
+
# Set the border line weight.
|
935
|
+
if params[:line_weight]
|
936
|
+
weight = get_line_weight(params[:line_weight])
|
937
|
+
area[:_line_weight] = weight
|
938
|
+
area[:_line_options] = 0x0000
|
939
|
+
area[:_line_pattern] = 0x00 unless params[:line_pattern]
|
940
|
+
area[:_line_color_index] = 0x4F unless params[:line_color]
|
941
|
+
area[:_visible] = 1
|
942
|
+
end
|
943
|
+
end
|
944
|
+
|
945
|
+
#
|
946
|
+
# Set on of the 42 built-in Excel chart styles. The default style is 2.
|
947
|
+
#
|
948
|
+
# The set_style() method is used to set the style of the chart to one
|
949
|
+
# of the 42 built-in styles available on the 'Design' tab in Excel:
|
950
|
+
#
|
951
|
+
# chart.set_style( 4 )
|
952
|
+
#
|
953
|
+
def set_style(style_id = 2)
|
954
|
+
style_id = 2 if style_id < 0 || style_id > 42
|
955
|
+
@style_id = style_id
|
956
|
+
end
|
957
|
+
|
958
|
+
#
|
959
|
+
# Setup the default configuration data for an embedded chart.
|
960
|
+
#
|
961
|
+
def set_embedded_config_data
|
962
|
+
@embedded = 1
|
963
|
+
|
964
|
+
# TODO. We may be able to remove this after refactoring.
|
965
|
+
|
966
|
+
@chartarea = {
|
967
|
+
:_visible => 1,
|
968
|
+
:_fg_color_index => 0x4E,
|
969
|
+
:_fg_color_rgb => 0xFFFFFF,
|
970
|
+
:_bg_color_index => 0x4D,
|
971
|
+
:_bg_color_rgb => 0x000000,
|
972
|
+
:_area_pattern => 0x0001,
|
973
|
+
:_area_options => 0x0001,
|
974
|
+
:_line_pattern => 0x0000,
|
975
|
+
:_line_weight => 0x0000,
|
976
|
+
:_line_color_index => 0x4D,
|
977
|
+
:_line_color_rgb => 0x000000,
|
978
|
+
:_line_options => 0x0009
|
979
|
+
}
|
980
|
+
|
981
|
+
end
|
982
|
+
|
983
|
+
private
|
984
|
+
|
985
|
+
#
|
986
|
+
# Convert user defined axis values into private hash values.
|
987
|
+
#
|
988
|
+
def convert_axis_args(params) # :nodoc:
|
989
|
+
name, name_formula = process_names(params[:name], params[:name_formula])
|
990
|
+
|
991
|
+
data_id = get_data_id(name_formula, params[:data])
|
992
|
+
|
993
|
+
axis = {
|
994
|
+
:_name => name,
|
995
|
+
:_formula => name_formula,
|
996
|
+
:_data_id => data_id,
|
997
|
+
:_reverse => params[:reverse],
|
998
|
+
:_min => params[:min],
|
999
|
+
:_max => params[:max],
|
1000
|
+
:_minor_unit => params[:minor_unit],
|
1001
|
+
:_major_unit => params[:major_unit],
|
1002
|
+
:_minor_unit_type => params[:minor_unit_type],
|
1003
|
+
:_major_unit_type => params[:major_unit_type],
|
1004
|
+
:_log_base => params[:log_base],
|
1005
|
+
:_crossing => params[:crossing],
|
1006
|
+
:_position => params[:position],
|
1007
|
+
:_label_position => params[:label_position]
|
1008
|
+
}
|
1009
|
+
|
1010
|
+
# Only use the first letter of bottom, top, left or right.
|
1011
|
+
axis[:_position] = axis[:_position].downcase[0, 1] if axis[:_position]
|
1012
|
+
|
1013
|
+
axis
|
1014
|
+
end
|
1015
|
+
|
1016
|
+
#
|
1017
|
+
# Convert and aref of row col values to a range formula.
|
1018
|
+
#
|
1019
|
+
def aref_to_formula(data) # :nodoc:
|
1020
|
+
# If it isn't an array ref it is probably a formula already.
|
1021
|
+
return data unless data.kind_of?(Array)
|
1022
|
+
xl_range_formula(*data)
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
#
|
1026
|
+
# Switch name and name_formula parameters if required.
|
1027
|
+
#
|
1028
|
+
def process_names(name = nil, name_formula = nil) # :nodoc:
|
1029
|
+
# Name looks like a formula, use it to set name_formula.
|
1030
|
+
if name && name =~ /^=[^!]+!\$/
|
1031
|
+
name_formula = name
|
1032
|
+
name = ''
|
1033
|
+
end
|
1034
|
+
|
1035
|
+
[name, name_formula]
|
1036
|
+
end
|
1037
|
+
|
1038
|
+
#
|
1039
|
+
# Find the overall type of the data associated with a series.
|
1040
|
+
#
|
1041
|
+
# TODO. Need to handle date type.
|
1042
|
+
#
|
1043
|
+
def get_data_type(data) # :nodoc:
|
1044
|
+
# Check for no data in the series.
|
1045
|
+
return 'none' unless data
|
1046
|
+
return 'none' if data.empty?
|
1047
|
+
|
1048
|
+
# If the token isn't a number assume it is a string.
|
1049
|
+
data.each do |token|
|
1050
|
+
next unless token
|
1051
|
+
return 'str' unless token.kind_of?(Numeric)
|
1052
|
+
end
|
1053
|
+
|
1054
|
+
# The series data was all numeric.
|
1055
|
+
'num'
|
1056
|
+
end
|
1057
|
+
|
1058
|
+
#
|
1059
|
+
# Assign an id to a each unique series formula or title/axis formula. Repeated
|
1060
|
+
# formulas such as for categories get the same id. If the series or title
|
1061
|
+
# has user specified data associated with it then that is also stored. This
|
1062
|
+
# data is used to populate cached Excel data when creating a chart.
|
1063
|
+
# If there is no user defined data then it will be populated by the parent
|
1064
|
+
# workbook in Workbook::_add_chart_data
|
1065
|
+
#
|
1066
|
+
def get_data_id(formula, data) # :nodoc:
|
1067
|
+
# Ignore series without a range formula.
|
1068
|
+
return unless formula
|
1069
|
+
|
1070
|
+
# Strip the leading '=' from the formula.
|
1071
|
+
formula = formula.sub(/^=/, '')
|
1072
|
+
|
1073
|
+
# Store the data id in a hash keyed by the formula and store the data
|
1074
|
+
# in a separate array with the same id.
|
1075
|
+
if !@formula_ids.has_key?(formula)
|
1076
|
+
# Haven't seen this formula before.
|
1077
|
+
id = @formula_data.size
|
1078
|
+
|
1079
|
+
@formula_data << data
|
1080
|
+
@formula_ids[formula] = id
|
1081
|
+
else
|
1082
|
+
# Formula already seen. Return existing id.
|
1083
|
+
id = @formula_ids[formula]
|
1084
|
+
|
1085
|
+
# Store user defined data if it isn't already there.
|
1086
|
+
@formula_data[id] = data unless @formula_data[id]
|
1087
|
+
end
|
1088
|
+
|
1089
|
+
id
|
1090
|
+
end
|
1091
|
+
|
1092
|
+
|
1093
|
+
#
|
1094
|
+
# Convert the user specified colour index or string to a rgb colour.
|
1095
|
+
#
|
1096
|
+
def get_color(color) # :nodoc:
|
1097
|
+
# Convert a HTML style #RRGGBB color.
|
1098
|
+
if color and color =~ /^#[0-9a-fA-F]{6}$/
|
1099
|
+
color = color.sub(/^#/, '')
|
1100
|
+
return color.upperca
|
1101
|
+
end
|
1102
|
+
|
1103
|
+
index = Format.get_color(color)
|
1104
|
+
|
1105
|
+
# Set undefined colors to black.
|
1106
|
+
unless index
|
1107
|
+
index = 0x08
|
1108
|
+
raise "Unknown color '#{color}' used in chart formatting."
|
1109
|
+
end
|
1110
|
+
|
1111
|
+
get_palette_color(index)
|
1112
|
+
end
|
1113
|
+
|
1114
|
+
#
|
1115
|
+
# Convert from an Excel internal colour index to a XML style #RRGGBB index
|
1116
|
+
# based on the default or user defined values in the Workbook palette.
|
1117
|
+
# Note: This version doesn't add an alpha channel.
|
1118
|
+
#
|
1119
|
+
def get_palette_color(index) # :nodoc:
|
1120
|
+
palette = @palette
|
1121
|
+
|
1122
|
+
# Adjust the colour index.
|
1123
|
+
index -= 8
|
1124
|
+
|
1125
|
+
# Palette is passed in from the Workbook class.
|
1126
|
+
rgb = palette[index]
|
1127
|
+
|
1128
|
+
sprintf("%02X%02X%02X", *rgb)
|
1129
|
+
end
|
1130
|
+
|
1131
|
+
#
|
1132
|
+
# Get the Excel chart index for line pattern that corresponds to the user
|
1133
|
+
# defined value.
|
1134
|
+
#
|
1135
|
+
def get_line_pattern(value) # :nodoc:
|
1136
|
+
value = value.downcase
|
1137
|
+
default = 0
|
1138
|
+
|
1139
|
+
patterns = {
|
1140
|
+
0 => 5,
|
1141
|
+
1 => 0,
|
1142
|
+
2 => 1,
|
1143
|
+
3 => 2,
|
1144
|
+
4 => 3,
|
1145
|
+
5 => 4,
|
1146
|
+
6 => 7,
|
1147
|
+
7 => 6,
|
1148
|
+
8 => 8,
|
1149
|
+
'solid' => 0,
|
1150
|
+
'dash' => 1,
|
1151
|
+
'dot' => 2,
|
1152
|
+
'dash-dot' => 3,
|
1153
|
+
'dash-dot-dot' => 4,
|
1154
|
+
'none' => 5,
|
1155
|
+
'dark-gray' => 6,
|
1156
|
+
'medium-gray' => 7,
|
1157
|
+
'light-gray' => 8
|
1158
|
+
}
|
1159
|
+
|
1160
|
+
if patterns.has_key(:value)
|
1161
|
+
pattern = patterns[:value]
|
1162
|
+
else
|
1163
|
+
pattern = default
|
1164
|
+
end
|
1165
|
+
|
1166
|
+
pattern
|
1167
|
+
end
|
1168
|
+
|
1169
|
+
#
|
1170
|
+
# Get the Excel chart index for line weight that corresponds to the user
|
1171
|
+
# defined value.
|
1172
|
+
#
|
1173
|
+
def get_line_weight(value) # :nodoc:
|
1174
|
+
value = value.downcase
|
1175
|
+
default = 0
|
1176
|
+
|
1177
|
+
weights = {
|
1178
|
+
1 => -1,
|
1179
|
+
2 => 0,
|
1180
|
+
3 => 1,
|
1181
|
+
4 => 2,
|
1182
|
+
'hairline' => -1,
|
1183
|
+
'narrow' => 0,
|
1184
|
+
'medium' => 1,
|
1185
|
+
'wide' => 2
|
1186
|
+
}
|
1187
|
+
|
1188
|
+
if weights[:value]
|
1189
|
+
weight = weights[:value]
|
1190
|
+
else
|
1191
|
+
weight = default
|
1192
|
+
end
|
1193
|
+
|
1194
|
+
weight
|
1195
|
+
end
|
1196
|
+
|
1197
|
+
#
|
1198
|
+
# Convert user defined line properties to the structure required internally.
|
1199
|
+
#
|
1200
|
+
def get_line_properties(line) # :nodoc:
|
1201
|
+
return { :_defined => 0 } unless line
|
1202
|
+
|
1203
|
+
dash_types = {
|
1204
|
+
:solid => 'solid',
|
1205
|
+
:round_dot => 'sysDot',
|
1206
|
+
:square_dot => 'sysDash',
|
1207
|
+
:dash => 'dash',
|
1208
|
+
:dash_dot => 'dashDot',
|
1209
|
+
:long_dash => 'lgDash',
|
1210
|
+
:long_dash_dot => 'lgDashDot',
|
1211
|
+
:long_dash_dot_dot => 'lgDashDotDot',
|
1212
|
+
:dot => 'dot',
|
1213
|
+
:system_dash_dot => 'sysDashDot',
|
1214
|
+
:system_dash_dot_dot => 'sysDashDotDot'
|
1215
|
+
}
|
1216
|
+
|
1217
|
+
# Check the dash type.
|
1218
|
+
dash_type = line[:dash_type]
|
1219
|
+
|
1220
|
+
if dash_type
|
1221
|
+
if dash_types[dash_type]
|
1222
|
+
line[dash_type] = dash_types[dash_type]
|
1223
|
+
else
|
1224
|
+
raise "Unknown dash type '#{dash_type}'\n"
|
1225
|
+
end
|
1226
|
+
end
|
1227
|
+
|
1228
|
+
line[:_defined] = 1
|
1229
|
+
|
1230
|
+
line
|
1231
|
+
end
|
1232
|
+
|
1233
|
+
#
|
1234
|
+
# Convert user defined fill properties to the structure required internally.
|
1235
|
+
#
|
1236
|
+
def get_fill_properties(fill) # :nodoc:
|
1237
|
+
return { :_defined => 0 } unless fill
|
1238
|
+
|
1239
|
+
fill[:_defined] = 1
|
1240
|
+
|
1241
|
+
fill
|
1242
|
+
end
|
1243
|
+
|
1244
|
+
#
|
1245
|
+
# Convert user defined marker properties to the structure required internally.
|
1246
|
+
#
|
1247
|
+
def get_marker_properties(marker) # :nodoc:
|
1248
|
+
return unless marker
|
1249
|
+
|
1250
|
+
types = {
|
1251
|
+
:automatic => 'automatic',
|
1252
|
+
:none => 'none',
|
1253
|
+
:square => 'square',
|
1254
|
+
:diamond => 'diamond',
|
1255
|
+
:triangle => 'triangle',
|
1256
|
+
:x => 'x',
|
1257
|
+
:star => 'start',
|
1258
|
+
:dot => 'dot',
|
1259
|
+
:short_dash => 'dot',
|
1260
|
+
:dash => 'dash',
|
1261
|
+
:long_dash => 'dash',
|
1262
|
+
:circle => 'circle',
|
1263
|
+
:plus => 'plus',
|
1264
|
+
:picture => 'picture'
|
1265
|
+
}
|
1266
|
+
|
1267
|
+
# Check for valid types.
|
1268
|
+
marker_type = marker[type]
|
1269
|
+
|
1270
|
+
if marker_type
|
1271
|
+
marker[automatic] = 1 if marker_type == 'automatic'
|
1272
|
+
|
1273
|
+
if types[marker_type]
|
1274
|
+
marker[type] = types[marker_type]
|
1275
|
+
else
|
1276
|
+
raise "Unknown marker type '#{marker_type}'\n"
|
1277
|
+
end
|
1278
|
+
end
|
1279
|
+
|
1280
|
+
# Set the line properties for the marker..
|
1281
|
+
line = get_line_properties(marker[line])
|
1282
|
+
|
1283
|
+
# Allow 'border' as a synonym for 'line'.
|
1284
|
+
line = get_line_properties(marker[border]) if marker[border]
|
1285
|
+
|
1286
|
+
# Set the fill properties for the marker.
|
1287
|
+
fill = get_fill_properties(marker[fill])
|
1288
|
+
|
1289
|
+
marker[:_line] = line
|
1290
|
+
marker[:_fill] = fill
|
1291
|
+
|
1292
|
+
marker
|
1293
|
+
end
|
1294
|
+
|
1295
|
+
#
|
1296
|
+
# Convert user defined trendline properties to the structure required internally.
|
1297
|
+
#
|
1298
|
+
def get_trendline_properties(trendline) # :nodoc:
|
1299
|
+
return unless trendline
|
1300
|
+
|
1301
|
+
types = {
|
1302
|
+
:exponential => 'exp',
|
1303
|
+
:linear => 'linear',
|
1304
|
+
:log => 'log',
|
1305
|
+
:moving_average => 'movingAvg',
|
1306
|
+
:polynomial => 'poly',
|
1307
|
+
:power => 'power'
|
1308
|
+
}
|
1309
|
+
|
1310
|
+
# Check the trendline type.
|
1311
|
+
trend_type = trendline[type]
|
1312
|
+
|
1313
|
+
if types[trend_type]
|
1314
|
+
trendline[type] = types[trend_type]
|
1315
|
+
else
|
1316
|
+
raise "Unknown trendline type '#{trend_type}'\n"
|
1317
|
+
end
|
1318
|
+
|
1319
|
+
# Set the line properties for the trendline..
|
1320
|
+
line = get_line_properties(trendline[line])
|
1321
|
+
|
1322
|
+
# Allow 'border' as a synonym for 'line'.
|
1323
|
+
line = get_line_properties(trendline[border]) if trendline[border]
|
1324
|
+
|
1325
|
+
# Set the fill properties for the trendline.
|
1326
|
+
fill = get_fill_properties(trendline[fill])
|
1327
|
+
|
1328
|
+
trendline[:_line] = line
|
1329
|
+
trendline[:_fill] = fill
|
1330
|
+
|
1331
|
+
return trendline
|
1332
|
+
end
|
1333
|
+
|
1334
|
+
#
|
1335
|
+
# Convert user defined labels properties to the structure required internally.
|
1336
|
+
#
|
1337
|
+
def get_labels_properties(labels) # :nodoc:
|
1338
|
+
return nil unless labels
|
1339
|
+
|
1340
|
+
return labels
|
1341
|
+
end
|
1342
|
+
|
1343
|
+
#
|
1344
|
+
# Add a unique id for an axis.
|
1345
|
+
#
|
1346
|
+
def add_axis_id # :nodoc:
|
1347
|
+
chart_id = 1 + @id
|
1348
|
+
axis_count = 1 + @axis_ids.size
|
1349
|
+
|
1350
|
+
axis_id = sprintf('5%03d%04d', chart_id, axis_count)
|
1351
|
+
|
1352
|
+
@axis_ids << axis_id
|
1353
|
+
|
1354
|
+
axis_id
|
1355
|
+
end
|
1356
|
+
|
1357
|
+
#
|
1358
|
+
# Setup the default properties for a chart.
|
1359
|
+
#
|
1360
|
+
def set_default_properties # :nodoc:
|
1361
|
+
@chartarea = {
|
1362
|
+
:_visible => 0,
|
1363
|
+
:_fg_color_index => 0x4E,
|
1364
|
+
:_fg_color_rgb => 0xFFFFFF,
|
1365
|
+
:_bg_color_index => 0x4D,
|
1366
|
+
:_bg_color_rgb => 0x000000,
|
1367
|
+
:_area_pattern => 0x0000,
|
1368
|
+
:_area_options => 0x0000,
|
1369
|
+
:_line_pattern => 0x0005,
|
1370
|
+
:_line_weight => 0xFFFF,
|
1371
|
+
:_line_color_index => 0x4D,
|
1372
|
+
:_line_color_rgb => 0x000000,
|
1373
|
+
:_line_options => 0x0008
|
1374
|
+
}
|
1375
|
+
|
1376
|
+
@plotarea = {
|
1377
|
+
:_visible => 1,
|
1378
|
+
:_fg_color_index => 0x16,
|
1379
|
+
:_fg_color_rgb => 0xC0C0C0,
|
1380
|
+
:_bg_color_index => 0x4F,
|
1381
|
+
:_bg_color_rgb => 0x000000,
|
1382
|
+
:_area_pattern => 0x0001,
|
1383
|
+
:_area_options => 0x0000,
|
1384
|
+
:_line_pattern => 0x0000,
|
1385
|
+
:_line_weight => 0x0000,
|
1386
|
+
:_line_color_index => 0x17,
|
1387
|
+
:_line_color_rgb => 0x808080,
|
1388
|
+
:_line_options => 0x0000
|
1389
|
+
}
|
1390
|
+
end
|
1391
|
+
|
1392
|
+
#
|
1393
|
+
# Write the <c:chartSpace> element.
|
1394
|
+
#
|
1395
|
+
def write_chart_space # :nodoc:
|
1396
|
+
schema = 'http://schemas.openxmlformats.org/'
|
1397
|
+
xmlns_c = schema + 'drawingml/2006/chart'
|
1398
|
+
xmlns_a = schema + 'drawingml/2006/main'
|
1399
|
+
xmlns_r = schema + 'officeDocument/2006/relationships'
|
1400
|
+
|
1401
|
+
attributes = [
|
1402
|
+
'xmlns:c', xmlns_c,
|
1403
|
+
'xmlns:a', xmlns_a,
|
1404
|
+
'xmlns:r', xmlns_r
|
1405
|
+
]
|
1406
|
+
|
1407
|
+
@writer.start_tag('c:chartSpace', attributes)
|
1408
|
+
end
|
1409
|
+
|
1410
|
+
#
|
1411
|
+
# Write the <c:lang> element.
|
1412
|
+
#
|
1413
|
+
def write_lang # :nodoc:
|
1414
|
+
val = 'en-US'
|
1415
|
+
|
1416
|
+
attributes = ['val', val]
|
1417
|
+
|
1418
|
+
@writer.empty_tag('c:lang', attributes)
|
1419
|
+
end
|
1420
|
+
|
1421
|
+
#
|
1422
|
+
# Write the <c:style> element.
|
1423
|
+
#
|
1424
|
+
def write_style # :nodoc:
|
1425
|
+
style_id = @style_id
|
1426
|
+
|
1427
|
+
# Don't write an element for the default style, 2.
|
1428
|
+
return if style_id == 2
|
1429
|
+
|
1430
|
+
attributes = ['val', style_id]
|
1431
|
+
|
1432
|
+
@writer.empty_tag('c:style', attributes)
|
1433
|
+
end
|
1434
|
+
|
1435
|
+
#
|
1436
|
+
# Write the <c:chart> element.
|
1437
|
+
#
|
1438
|
+
def write_chart # :nodoc:
|
1439
|
+
@writer.start_tag('c:chart')
|
1440
|
+
|
1441
|
+
# Write the chart title elements.
|
1442
|
+
if title = @title_formula
|
1443
|
+
write_title_formula(title, @title_data_id)
|
1444
|
+
elsif title = @title_name
|
1445
|
+
write_title_rich(title)
|
1446
|
+
end
|
1447
|
+
|
1448
|
+
# Write the c:plotArea element.
|
1449
|
+
write_plot_area
|
1450
|
+
|
1451
|
+
# Write the c:legend element.
|
1452
|
+
write_legend
|
1453
|
+
|
1454
|
+
# Write the c:plotVisOnly element.
|
1455
|
+
write_plot_vis_only
|
1456
|
+
|
1457
|
+
@writer.end_tag('c:chart')
|
1458
|
+
end
|
1459
|
+
|
1460
|
+
#
|
1461
|
+
# Write the <c:plotArea> element.
|
1462
|
+
#
|
1463
|
+
def write_plot_area # :nodoc:
|
1464
|
+
@writer.start_tag('c:plotArea')
|
1465
|
+
|
1466
|
+
# Write the c:layout element.
|
1467
|
+
write_layout
|
1468
|
+
|
1469
|
+
# Write the subclass chart type element.
|
1470
|
+
write_chart_type
|
1471
|
+
|
1472
|
+
# Write the c:catAx element.
|
1473
|
+
write_cat_axis
|
1474
|
+
|
1475
|
+
# Write the c:catAx element.
|
1476
|
+
write_val_axis
|
1477
|
+
|
1478
|
+
@writer.end_tag('c:plotArea')
|
1479
|
+
end
|
1480
|
+
|
1481
|
+
#
|
1482
|
+
# Write the <c:layout> element.
|
1483
|
+
#
|
1484
|
+
def write_layout # :nodoc:
|
1485
|
+
@writer.empty_tag('c:layout')
|
1486
|
+
end
|
1487
|
+
|
1488
|
+
#
|
1489
|
+
# Write the chart type element. This method should be overridden by the
|
1490
|
+
# subclasses.
|
1491
|
+
#
|
1492
|
+
def write_chart_type # :nodoc:
|
1493
|
+
end
|
1494
|
+
|
1495
|
+
#
|
1496
|
+
# Write the <c:grouping> element.
|
1497
|
+
#
|
1498
|
+
def write_grouping(val) # :nodoc:
|
1499
|
+
attributes = ['val', val]
|
1500
|
+
@writer.empty_tag('c:grouping', attributes)
|
1501
|
+
end
|
1502
|
+
|
1503
|
+
#
|
1504
|
+
# Write the series elements.
|
1505
|
+
#
|
1506
|
+
def write_series # :nodoc:
|
1507
|
+
# Write each series with subelements.
|
1508
|
+
index = 0
|
1509
|
+
@series.each do |series|
|
1510
|
+
write_ser(index, series)
|
1511
|
+
index += 1
|
1512
|
+
end
|
1513
|
+
|
1514
|
+
# Write the c:marker element.
|
1515
|
+
write_marker_value
|
1516
|
+
|
1517
|
+
# Generate the axis ids.
|
1518
|
+
add_axis_id
|
1519
|
+
add_axis_id
|
1520
|
+
|
1521
|
+
# Write the c:axId element.
|
1522
|
+
write_axis_id(@axis_ids[0])
|
1523
|
+
write_axis_id(@axis_ids[1])
|
1524
|
+
end
|
1525
|
+
|
1526
|
+
#
|
1527
|
+
# Write the <c:ser> element.
|
1528
|
+
#
|
1529
|
+
def write_ser(index, series) # :nodoc:
|
1530
|
+
@writer.start_tag('c:ser')
|
1531
|
+
|
1532
|
+
# Write the c:idx element.
|
1533
|
+
write_idx(index)
|
1534
|
+
|
1535
|
+
# Write the c:order element.
|
1536
|
+
write_order(index)
|
1537
|
+
|
1538
|
+
# Write the series name.
|
1539
|
+
write_series_name(series)
|
1540
|
+
|
1541
|
+
# Write the c:spPr element.
|
1542
|
+
write_sp_pr(series)
|
1543
|
+
|
1544
|
+
# Write the c:marker element.
|
1545
|
+
write_marker(series[:_marker])
|
1546
|
+
|
1547
|
+
# Write the c:invertIfNegative element.
|
1548
|
+
write_c_invert_if_negative(series[:_invert_if_neg])
|
1549
|
+
|
1550
|
+
# Write the c:dLbls element.
|
1551
|
+
write_d_lbls(series[:labels])
|
1552
|
+
|
1553
|
+
# Write the c:trendline element.
|
1554
|
+
write_trendline(series[:trendline])
|
1555
|
+
|
1556
|
+
# Write the c:cat element.
|
1557
|
+
write_cat(series)
|
1558
|
+
|
1559
|
+
# Write the c:val element.
|
1560
|
+
write_val(series)
|
1561
|
+
|
1562
|
+
@writer.end_tag('c:ser')
|
1563
|
+
end
|
1564
|
+
|
1565
|
+
#
|
1566
|
+
# Write the <c:idx> element.
|
1567
|
+
#
|
1568
|
+
def write_idx(val) # :nodoc:
|
1569
|
+
attributes = ['val', val]
|
1570
|
+
|
1571
|
+
@writer.empty_tag('c:idx', attributes)
|
1572
|
+
end
|
1573
|
+
|
1574
|
+
#
|
1575
|
+
# Write the <c:order> element.
|
1576
|
+
#
|
1577
|
+
def write_order(val) # :nodoc:
|
1578
|
+
attributes = ['val', val]
|
1579
|
+
|
1580
|
+
@writer.empty_tag('c:order', attributes)
|
1581
|
+
end
|
1582
|
+
|
1583
|
+
#
|
1584
|
+
# Write the series name.
|
1585
|
+
#
|
1586
|
+
def write_series_name(series) # :nodoc:
|
1587
|
+
if name = series[:_name_formula]
|
1588
|
+
write_tx_formula(name, series[:_name_id])
|
1589
|
+
elsif name = series[:_name]
|
1590
|
+
write_tx_value(name)
|
1591
|
+
end
|
1592
|
+
end
|
1593
|
+
|
1594
|
+
#
|
1595
|
+
# Write the <c:cat> element.
|
1596
|
+
#
|
1597
|
+
def write_cat(series) # :nodoc:
|
1598
|
+
|
1599
|
+
formula = series[:_categories]
|
1600
|
+
data_id = series[:_cat_data_id]
|
1601
|
+
|
1602
|
+
data = @formula_data[data_id] if data_id
|
1603
|
+
|
1604
|
+
# Ignore <c:cat> elements for charts without category values.
|
1605
|
+
return unless formula
|
1606
|
+
|
1607
|
+
@has_category = 1
|
1608
|
+
|
1609
|
+
@writer.start_tag('c:cat')
|
1610
|
+
|
1611
|
+
# Check the type of cached data.
|
1612
|
+
type = get_data_type(data)
|
1613
|
+
|
1614
|
+
if type == 'str'
|
1615
|
+
@has_category = 0
|
1616
|
+
|
1617
|
+
# Write the c:numRef element.
|
1618
|
+
write_str_ref(formula, data, type)
|
1619
|
+
else
|
1620
|
+
# Write the c:numRef element.
|
1621
|
+
write_num_ref(formula, data, type)
|
1622
|
+
end
|
1623
|
+
|
1624
|
+
@writer.end_tag('c:cat')
|
1625
|
+
end
|
1626
|
+
|
1627
|
+
#
|
1628
|
+
# Write the <c:val> element.
|
1629
|
+
#
|
1630
|
+
def write_val(series) # :nodoc:
|
1631
|
+
formula = series[:_values]
|
1632
|
+
data_id = series[:_val_data_id]
|
1633
|
+
data = @formula_data[data_id]
|
1634
|
+
|
1635
|
+
@writer.start_tag('c:val')
|
1636
|
+
|
1637
|
+
# Check the type of cached data.
|
1638
|
+
type = get_data_type(data)
|
1639
|
+
|
1640
|
+
if type == 'str'
|
1641
|
+
# Write the c:numRef element.
|
1642
|
+
write_str_ref(formula, data, type)
|
1643
|
+
else
|
1644
|
+
# Write the c:numRef element.
|
1645
|
+
write_num_ref(formula, data, type)
|
1646
|
+
end
|
1647
|
+
|
1648
|
+
@writer.end_tag('c:val')
|
1649
|
+
end
|
1650
|
+
|
1651
|
+
#
|
1652
|
+
# Write the <c:numRef> element.
|
1653
|
+
#
|
1654
|
+
def write_num_ref(formula, data, type) # :nodoc:
|
1655
|
+
@writer.start_tag('c:numRef')
|
1656
|
+
|
1657
|
+
# Write the c:f element.
|
1658
|
+
write_series_formula(formula)
|
1659
|
+
|
1660
|
+
if type == 'num'
|
1661
|
+
# Write the c:numCache element.
|
1662
|
+
write_num_cache(data)
|
1663
|
+
elsif type == 'str'
|
1664
|
+
# Write the c:strCache element.
|
1665
|
+
write_str_cache(data)
|
1666
|
+
end
|
1667
|
+
|
1668
|
+
@writer.end_tag('c:numRef')
|
1669
|
+
end
|
1670
|
+
|
1671
|
+
#
|
1672
|
+
# Write the <c:strRef> element.
|
1673
|
+
#
|
1674
|
+
def write_str_ref(formula, data, type) # :nodoc:
|
1675
|
+
@writer.start_tag('c:strRef')
|
1676
|
+
|
1677
|
+
# Write the c:f element.
|
1678
|
+
write_series_formula(formula)
|
1679
|
+
|
1680
|
+
if type == 'num'
|
1681
|
+
# Write the c:numCache element.
|
1682
|
+
write_num_cache(data)
|
1683
|
+
elsif type == 'str'
|
1684
|
+
# Write the c:strCache element.
|
1685
|
+
write_str_cache(data)
|
1686
|
+
end
|
1687
|
+
|
1688
|
+
@writer.end_tag('c:strRef')
|
1689
|
+
end
|
1690
|
+
|
1691
|
+
#
|
1692
|
+
# Write the <c:f> element.
|
1693
|
+
#
|
1694
|
+
def write_series_formula(formula) # :nodoc:
|
1695
|
+
# Strip the leading '=' from the formula.
|
1696
|
+
formula = formula.sub(/^=/, '')
|
1697
|
+
|
1698
|
+
@writer.data_element('c:f', formula)
|
1699
|
+
end
|
1700
|
+
|
1701
|
+
#
|
1702
|
+
# Write the <c:axId> element.
|
1703
|
+
#
|
1704
|
+
def write_axis_id(val) # :nodoc:
|
1705
|
+
attributes = ['val', val]
|
1706
|
+
|
1707
|
+
@writer.empty_tag('c:axId', attributes)
|
1708
|
+
end
|
1709
|
+
|
1710
|
+
#
|
1711
|
+
# Write the <c:catAx> element. Usually the X axis.
|
1712
|
+
#
|
1713
|
+
def write_cat_axis(position = nil) # :nodoc:
|
1714
|
+
position = @cat_axis_position
|
1715
|
+
horiz = @horiz_cat_axis
|
1716
|
+
x_axis = @x_axis
|
1717
|
+
y_axis = @y_axis
|
1718
|
+
|
1719
|
+
# Overwrite the default axis position with a user supplied value.
|
1720
|
+
position = x_axis[:_position] || position
|
1721
|
+
|
1722
|
+
@writer.start_tag('c:catAx')
|
1723
|
+
|
1724
|
+
write_axis_id(@axis_ids[0])
|
1725
|
+
|
1726
|
+
# Write the c:scaling element.
|
1727
|
+
write_scaling(x_axis[:_reverse])
|
1728
|
+
|
1729
|
+
# Write the c:axPos element.
|
1730
|
+
write_axis_pos(position, y_axis[:_reverse])
|
1731
|
+
|
1732
|
+
# Write the axis title elements.
|
1733
|
+
if title = @x_axis[:_formula]
|
1734
|
+
write_title_formula(title, @x_axis[:_data_id], horiz)
|
1735
|
+
elsif title = @x_axis[:_name]
|
1736
|
+
write_title_rich(title, horiz)
|
1737
|
+
end
|
1738
|
+
|
1739
|
+
# Write the c:numFmt element.
|
1740
|
+
write_num_fmt
|
1741
|
+
|
1742
|
+
# Write the c:tickLblPos element.
|
1743
|
+
write_tick_label_pos(x_axis[:_label_position])
|
1744
|
+
|
1745
|
+
# Write the c:crossAx element.
|
1746
|
+
write_cross_axis(@axis_ids[1])
|
1747
|
+
|
1748
|
+
# Note, the category crossing comes from the value axis.
|
1749
|
+
if y_axis[:_crossing].nil? || y_axis[:_crossing] == 'max'
|
1750
|
+
# Write the c:crosses element.
|
1751
|
+
write_crosses(y_axis[:_crossing])
|
1752
|
+
else
|
1753
|
+
# Write the c:crossesAt element.
|
1754
|
+
write_c_crosses(y_axis[:_crossing])
|
1755
|
+
end
|
1756
|
+
|
1757
|
+
# Write the c:auto element.
|
1758
|
+
write_auto(1)
|
1759
|
+
|
1760
|
+
# Write the c:labelAlign element.
|
1761
|
+
write_label_align('ctr')
|
1762
|
+
|
1763
|
+
# Write the c:labelOffset element.
|
1764
|
+
write_label_offset(100)
|
1765
|
+
|
1766
|
+
@writer.end_tag('c:catAx')
|
1767
|
+
end
|
1768
|
+
|
1769
|
+
#
|
1770
|
+
# Write the <c:valAx> element. Usually the Y axis.
|
1771
|
+
#
|
1772
|
+
# TODO. Maybe should have a _write_cat_val_axis method as well for scatter.
|
1773
|
+
#
|
1774
|
+
def write_val_axis(position = nil, hide_major_gridlines = nil) # :nodoc:
|
1775
|
+
position ||= @val_axis_position
|
1776
|
+
horiz = @horiz_val_axis
|
1777
|
+
x_axis = @x_axis
|
1778
|
+
y_axis = @y_axis
|
1779
|
+
|
1780
|
+
# Overwrite the default axis position with a user supplied value.
|
1781
|
+
position = y_axis[:_position] || position
|
1782
|
+
|
1783
|
+
@writer.start_tag('c:valAx')
|
1784
|
+
|
1785
|
+
write_axis_id(@axis_ids[1])
|
1786
|
+
|
1787
|
+
# Write the c:scaling element.
|
1788
|
+
write_scaling(y_axis[:_reverse], y_axis[:_min], y_axis[:_max], y_axis[:_log_base])
|
1789
|
+
|
1790
|
+
# Write the c:axPos element.
|
1791
|
+
write_axis_pos(position, x_axis[:_reverse])
|
1792
|
+
|
1793
|
+
# Write the c:majorGridlines element.
|
1794
|
+
write_major_gridlines unless hide_major_gridlines
|
1795
|
+
|
1796
|
+
# Write the axis title elements.
|
1797
|
+
if title = @y_axis[:_formula]
|
1798
|
+
write_title_formula(title, @y_axis[:_data_id], horiz)
|
1799
|
+
elsif title = @y_axis[:_name]
|
1800
|
+
write_title_rich(title, horiz)
|
1801
|
+
end
|
1802
|
+
|
1803
|
+
# Write the c:numberFormat element.
|
1804
|
+
write_number_format
|
1805
|
+
|
1806
|
+
# Write the c:tickLblPos element.
|
1807
|
+
write_tick_label_pos(y_axis[:_label_position])
|
1808
|
+
|
1809
|
+
# Write the c:crossAx element.
|
1810
|
+
write_cross_axis(@axis_ids[0])
|
1811
|
+
|
1812
|
+
# Note, the category crossing comes from the value axis.
|
1813
|
+
if x_axis[:crossing].nil? || x_axis[:_crossing] == 'max'
|
1814
|
+
# Write the c:crosses element.
|
1815
|
+
write_crosses(x_axis[:_crossing])
|
1816
|
+
else
|
1817
|
+
# Write the c:crossesAt element.
|
1818
|
+
write_c_crosses_at(x_axis[:_crossing])
|
1819
|
+
end
|
1820
|
+
|
1821
|
+
# Write the c:crossBetween element.
|
1822
|
+
write_cross_between
|
1823
|
+
|
1824
|
+
# Write the c:majorUnit element.
|
1825
|
+
write_c_major_unit(y_axis[:_major_unit])
|
1826
|
+
|
1827
|
+
# Write the c:minorUnit element.
|
1828
|
+
write_c_minor_unit(y_axis[:_minor_unit])
|
1829
|
+
|
1830
|
+
@writer.end_tag('c:valAx')
|
1831
|
+
end
|
1832
|
+
|
1833
|
+
#
|
1834
|
+
# Write the <c:valAx> element. This is for the second valAx in scatter plots.
|
1835
|
+
#
|
1836
|
+
# Usually the X axis.
|
1837
|
+
#
|
1838
|
+
def write_cat_val_axis(position, hide_major_gridlines) # :nodoc:
|
1839
|
+
position ||= @val_axis_position
|
1840
|
+
horiz = @horiz_val_axis
|
1841
|
+
x_axis = @x_axis
|
1842
|
+
y_axis = @y_axis
|
1843
|
+
|
1844
|
+
# Overwrite the default axis position with a user supplied value.
|
1845
|
+
position = x_axis[:_position] || position
|
1846
|
+
|
1847
|
+
@writer.start_tag('c:valAx')
|
1848
|
+
|
1849
|
+
write_axis_id(@axis_ids[0])
|
1850
|
+
|
1851
|
+
# Write the c:scaling element.
|
1852
|
+
write_scaling(x_axis[:_reverse], x_axis[:_min], x_axis[:_max], x_axis[:_log_base])
|
1853
|
+
|
1854
|
+
# Write the c:axPos element.
|
1855
|
+
write_axis_pos(position, y_axis[:_reverse])
|
1856
|
+
|
1857
|
+
# Write the c:majorGridlines element.
|
1858
|
+
write_major_gridlines unless hide_major_gridlines
|
1859
|
+
|
1860
|
+
# Write the axis title elements.
|
1861
|
+
if title = @x_axis[:_formula]
|
1862
|
+
write_title_formula(title, @y_axis[:_data_id], horiz)
|
1863
|
+
elsif title = @x_axis[:_name]
|
1864
|
+
write_title_rich(title, horiz)
|
1865
|
+
end
|
1866
|
+
|
1867
|
+
# Write the c:numberFormat element.
|
1868
|
+
write_number_format
|
1869
|
+
|
1870
|
+
# Write the c:tickLblPos element.
|
1871
|
+
write_tick_label_pos(x_axis[:_label_position])
|
1872
|
+
|
1873
|
+
# Write the c:crossAx element.
|
1874
|
+
write_cross_axis(@axis_ids[1])
|
1875
|
+
|
1876
|
+
# Note, the category crossing comes from the value axis.
|
1877
|
+
if y_axis[:_clossing].nil? || y_axis[:_crossing] == 'max'
|
1878
|
+
# Write the c:crosses element.
|
1879
|
+
write_crosses(y_axis[:_crossing])
|
1880
|
+
else
|
1881
|
+
# Write the c:crossesAt element.
|
1882
|
+
write_c_crosses_at(y_axis[:_crossing])
|
1883
|
+
end
|
1884
|
+
|
1885
|
+
# Write the c:crossBetween element.
|
1886
|
+
write_cross_between
|
1887
|
+
|
1888
|
+
# Write the c:majorunit element.
|
1889
|
+
write_c_major_unit(y_axis[:_major_unit])
|
1890
|
+
|
1891
|
+
# Write the c:minorUnit element.
|
1892
|
+
write_c_minor_unit(y_axis[:_minor_unit])
|
1893
|
+
|
1894
|
+
@writer.end_tag('c:valAx')
|
1895
|
+
end
|
1896
|
+
|
1897
|
+
#
|
1898
|
+
# Write the <c:dateAx> element. Usually the X axis.
|
1899
|
+
#
|
1900
|
+
def write_date_axis(position = nil) # :nodoc:
|
1901
|
+
position = @cat_axis_position
|
1902
|
+
x_axis = @x_axis
|
1903
|
+
y_axis = @y_axis
|
1904
|
+
|
1905
|
+
@writer.start_tag('c:dateAx')
|
1906
|
+
|
1907
|
+
write_axis_id(@axis_ids[0])
|
1908
|
+
|
1909
|
+
# Write the c:scaling element.
|
1910
|
+
write_scaling(x_axis[:reverse], x_axis[:_min], x_axis[:_max], x_axis[:_log_base])
|
1911
|
+
|
1912
|
+
# Write the c:axPos element.
|
1913
|
+
write_axis_pos(position, y_axis[:reverse])
|
1914
|
+
|
1915
|
+
# Write the axis title elements.
|
1916
|
+
if title = x_axis[:_formula]
|
1917
|
+
write_title_formula(title, x_axis[:_data_id])
|
1918
|
+
elsif title = x_axis[:_name]
|
1919
|
+
write_title_rich(title)
|
1920
|
+
end
|
1921
|
+
|
1922
|
+
# Write the c:numFmt element.
|
1923
|
+
write_num_fmt('dd/mm/yyyy')
|
1924
|
+
|
1925
|
+
# Write the c:tickLblPos element.
|
1926
|
+
write_tick_label_pos(x_axis[:_label_position])
|
1927
|
+
|
1928
|
+
# Write the c:crossAx element.
|
1929
|
+
write_cross_axis(@axis_ids[1])
|
1930
|
+
|
1931
|
+
# Note, the category crossing comes from the value axis.
|
1932
|
+
if y_axis[:_crossing].nil? || y_axis[:_crossing] == 'max'
|
1933
|
+
# Write the c:crossing element.
|
1934
|
+
write_crosses(y_axis[:_crossing])
|
1935
|
+
else
|
1936
|
+
# Write the c:crossesAt element.
|
1937
|
+
write_c_crosses_at(y_axis[:_crossing])
|
1938
|
+
end
|
1939
|
+
|
1940
|
+
# Write the c:auto element.
|
1941
|
+
write_auto(1)
|
1942
|
+
|
1943
|
+
# Write the c:labelOffset element.
|
1944
|
+
write_label_offset(100)
|
1945
|
+
|
1946
|
+
# Write the c:majorUnit element.
|
1947
|
+
write_c_major_unit(x_axis[:_major_unit])
|
1948
|
+
|
1949
|
+
# Write the c:majorTimeUnit element.
|
1950
|
+
if !x_axis[:_major_unit].nil?
|
1951
|
+
write_c_major_time_unit(x_axis[:_major_unit_type])
|
1952
|
+
end
|
1953
|
+
|
1954
|
+
# Write the c:minorUnit element.
|
1955
|
+
write_c_minor_unit(x_axis[:_minor_unit])
|
1956
|
+
|
1957
|
+
# Write the c:minorTimeUnit element.
|
1958
|
+
if !x_axis[:_minor_unit].nil?
|
1959
|
+
write_c_minor_time_unit(x_axis[:_minor_unit_type])
|
1960
|
+
end
|
1961
|
+
|
1962
|
+
@writer.end_tag('c:dateAx')
|
1963
|
+
end
|
1964
|
+
|
1965
|
+
#
|
1966
|
+
# Write the <c:scaling> element.
|
1967
|
+
#
|
1968
|
+
def write_scaling(reverse, min = nil, max = nil, log_base = nil) # :nodoc:
|
1969
|
+
@writer.start_tag('c:scaling')
|
1970
|
+
|
1971
|
+
# Write the c:logBase element.
|
1972
|
+
write_c_log_base(log_base)
|
1973
|
+
|
1974
|
+
# Write the c:orientation element.
|
1975
|
+
write_orientation(reverse)
|
1976
|
+
|
1977
|
+
# Write the c:max element.
|
1978
|
+
write_c_max(max)
|
1979
|
+
|
1980
|
+
# Write the c:min element.
|
1981
|
+
write_c_min(min)
|
1982
|
+
|
1983
|
+
@writer.end_tag('c:scaling')
|
1984
|
+
end
|
1985
|
+
|
1986
|
+
#
|
1987
|
+
# Write the <c:orientation> element.
|
1988
|
+
#
|
1989
|
+
def write_orientation(reverse = nil) # :nodoc:
|
1990
|
+
val = reverse ? 'maxMin' : 'minMax'
|
1991
|
+
|
1992
|
+
attributes = ['val', val]
|
1993
|
+
|
1994
|
+
@writer.empty_tag('c:orientation', attributes)
|
1995
|
+
end
|
1996
|
+
|
1997
|
+
#
|
1998
|
+
# Write the <c:logBase> element.
|
1999
|
+
#
|
2000
|
+
def write_c_log_base(val) # :nodoc:
|
2001
|
+
return if val == 0 || val.nil?
|
2002
|
+
|
2003
|
+
attributes = ['val', val]
|
2004
|
+
|
2005
|
+
@writer.empty_tag('c:logBase', attributes)
|
2006
|
+
end
|
2007
|
+
|
2008
|
+
#
|
2009
|
+
# Write the <c:orientation> element.
|
2010
|
+
#
|
2011
|
+
def write_orientation(reverse = 'maxMin') # :nodoc:
|
2012
|
+
val = 'minMax'
|
2013
|
+
|
2014
|
+
attributes = ['val', val]
|
2015
|
+
|
2016
|
+
@writer.empty_tag('c:orientation', attributes)
|
2017
|
+
end
|
2018
|
+
|
2019
|
+
#
|
2020
|
+
# Write the <c:max> element.
|
2021
|
+
#
|
2022
|
+
def write_c_max(max = nil) # :nodoc:
|
2023
|
+
return if max.nil?
|
2024
|
+
|
2025
|
+
attributes = ['val', max]
|
2026
|
+
|
2027
|
+
@writer.empty_tag('c:max', attributes)
|
2028
|
+
end
|
2029
|
+
|
2030
|
+
#
|
2031
|
+
# Write the <c:min> element.
|
2032
|
+
#
|
2033
|
+
def write_c_min(min = nil) # :nodoc:
|
2034
|
+
return if min.nil?
|
2035
|
+
|
2036
|
+
attributes = ['val', min]
|
2037
|
+
|
2038
|
+
@writer.empty_tag('c:min', attributes)
|
2039
|
+
end
|
2040
|
+
|
2041
|
+
#
|
2042
|
+
# Write the <c:axPos> element.
|
2043
|
+
#
|
2044
|
+
def write_axis_pos(val, reverse = false) # :nodoc:
|
2045
|
+
if reverse
|
2046
|
+
val = 'r' if val == 'l'
|
2047
|
+
val = 't' if val == 'b'
|
2048
|
+
end
|
2049
|
+
|
2050
|
+
attributes = ['val', val]
|
2051
|
+
|
2052
|
+
@writer.empty_tag('c:axPos', attributes)
|
2053
|
+
end
|
2054
|
+
|
2055
|
+
#
|
2056
|
+
# Write the <c:numFmt> element.
|
2057
|
+
#
|
2058
|
+
def write_num_fmt(format_code = nil) # :nodoc:
|
2059
|
+
format_code ||= 'General'
|
2060
|
+
source_linked = 1
|
2061
|
+
|
2062
|
+
# These elements are only required for charts with categories.
|
2063
|
+
return unless @has_category
|
2064
|
+
|
2065
|
+
attributes = [
|
2066
|
+
'formatCode', format_code,
|
2067
|
+
'sourceLinked', source_linked
|
2068
|
+
]
|
2069
|
+
|
2070
|
+
@writer.empty_tag('c:numFmt', attributes)
|
2071
|
+
end
|
2072
|
+
|
2073
|
+
#
|
2074
|
+
# Write the <c:tickLblPos> element.
|
2075
|
+
#
|
2076
|
+
def write_tick_label_pos(val) # :nodoc:
|
2077
|
+
val ||= 'nextTo'
|
2078
|
+
val = 'nextTo' if val == 'next_to'
|
2079
|
+
|
2080
|
+
attributes = ['val', val]
|
2081
|
+
|
2082
|
+
@writer.empty_tag('c:tickLblPos', attributes)
|
2083
|
+
end
|
2084
|
+
|
2085
|
+
#
|
2086
|
+
# Write the <c:crossAx> element.
|
2087
|
+
#
|
2088
|
+
def write_cross_axis(val = 'autoZero') # :nodoc:
|
2089
|
+
attributes = ['val', val]
|
2090
|
+
|
2091
|
+
@writer.empty_tag('c:crossAx', attributes)
|
2092
|
+
end
|
2093
|
+
|
2094
|
+
#
|
2095
|
+
# Write the <c:crosses> element.
|
2096
|
+
#
|
2097
|
+
def write_crosses(val) # :nodoc:
|
2098
|
+
val ||= 'autoZero'
|
2099
|
+
|
2100
|
+
attributes = ['val', val]
|
2101
|
+
|
2102
|
+
@writer.empty_tag('c:crosses', attributes)
|
2103
|
+
end
|
2104
|
+
|
2105
|
+
#
|
2106
|
+
# Write the <c:crossesAt> element.
|
2107
|
+
#
|
2108
|
+
def write_c_crosses_at(val) # :nodoc:
|
2109
|
+
attributes = ['val', val]
|
2110
|
+
|
2111
|
+
@writer.empty_tag('c:crossesAt', attributes)
|
2112
|
+
end
|
2113
|
+
|
2114
|
+
#
|
2115
|
+
# Write the <c:auto> element.
|
2116
|
+
#
|
2117
|
+
def write_auto(val) # :nodoc:
|
2118
|
+
attributes = ['val', val]
|
2119
|
+
|
2120
|
+
@writer.empty_tag('c:auto', attributes)
|
2121
|
+
end
|
2122
|
+
|
2123
|
+
#
|
2124
|
+
# Write the <c:labelAlign> element.
|
2125
|
+
#
|
2126
|
+
def write_label_align(val) # :nodoc:
|
2127
|
+
attributes = ['val', val]
|
2128
|
+
|
2129
|
+
@writer.empty_tag('c:lblAlgn', attributes)
|
2130
|
+
end
|
2131
|
+
|
2132
|
+
#
|
2133
|
+
# Write the <c:labelOffset> element.
|
2134
|
+
#
|
2135
|
+
def write_label_offset(val) # :nodoc:
|
2136
|
+
attributes = ['val', val]
|
2137
|
+
|
2138
|
+
@writer.empty_tag('c:lblOffset', attributes)
|
2139
|
+
end
|
2140
|
+
|
2141
|
+
#
|
2142
|
+
# Write the <c:majorGridlines> element.
|
2143
|
+
#
|
2144
|
+
def write_major_gridlines # :nodoc:
|
2145
|
+
@writer.empty_tag('c:majorGridlines')
|
2146
|
+
end
|
2147
|
+
|
2148
|
+
#
|
2149
|
+
# Write the <c:numberFormat> element.
|
2150
|
+
#
|
2151
|
+
# TODO. Merge/replace with _write_num_fmt.
|
2152
|
+
#
|
2153
|
+
def write_number_format # :nodoc:
|
2154
|
+
format_code = 'General'
|
2155
|
+
source_linked = 1
|
2156
|
+
|
2157
|
+
attributes = [
|
2158
|
+
'formatCode', format_code,
|
2159
|
+
'sourceLinked', source_linked
|
2160
|
+
]
|
2161
|
+
|
2162
|
+
@writer.empty_tag('c:numFmt', attributes)
|
2163
|
+
end
|
2164
|
+
|
2165
|
+
#
|
2166
|
+
# Write the <c:crossBetween> element.
|
2167
|
+
#
|
2168
|
+
def write_cross_between # :nodoc:
|
2169
|
+
val = @cross_between || 'between'
|
2170
|
+
|
2171
|
+
attributes = ['val', val]
|
2172
|
+
|
2173
|
+
@writer.empty_tag('c:crossBetween', attributes)
|
2174
|
+
end
|
2175
|
+
|
2176
|
+
#
|
2177
|
+
# Write the <c:majorUnit> element.
|
2178
|
+
#
|
2179
|
+
def write_c_major_unit(val = nil) # :nodoc:
|
2180
|
+
return unless val
|
2181
|
+
|
2182
|
+
attributes = ['val', val]
|
2183
|
+
|
2184
|
+
@writer.empty_tag('c:majorUnit', attributes)
|
2185
|
+
end
|
2186
|
+
|
2187
|
+
#
|
2188
|
+
# Write the <c:minorUnit> element.
|
2189
|
+
#
|
2190
|
+
def write_c_minor_unit(val = nil) # :nodoc:
|
2191
|
+
return unless val
|
2192
|
+
|
2193
|
+
attributes = ['val', val]
|
2194
|
+
|
2195
|
+
@writer.empty_tag('c:minorUnit', attributes)
|
2196
|
+
end
|
2197
|
+
|
2198
|
+
#
|
2199
|
+
# Write the <c:majorTimeUnit> element.
|
2200
|
+
#
|
2201
|
+
def write_c_major_time_unit(val = 'days') # :nodoc:
|
2202
|
+
attributes = ['val', val]
|
2203
|
+
|
2204
|
+
@writer.empty_tag('c:majorTimeUnit', attributes)
|
2205
|
+
end
|
2206
|
+
|
2207
|
+
#
|
2208
|
+
# Write the <c:minorTimeUnit> element.
|
2209
|
+
#
|
2210
|
+
def write_c_minor_time_unit(val = 'days') # :nodoc:
|
2211
|
+
attributes = ['val', val]
|
2212
|
+
|
2213
|
+
@writer.empty_tag('c:minorTimeUnit', attributes)
|
2214
|
+
end
|
2215
|
+
|
2216
|
+
#
|
2217
|
+
# Write the <c:legend> element.
|
2218
|
+
#
|
2219
|
+
def write_legend # :nodoc:
|
2220
|
+
position = @legend_position
|
2221
|
+
overlay = false
|
2222
|
+
|
2223
|
+
if @legend_delete_series && @legend_delete_series.kind_of?(Array)
|
2224
|
+
@delete_series = @legend_delete_series
|
2225
|
+
end
|
2226
|
+
|
2227
|
+
if position =~ /^overlay_/
|
2228
|
+
position.sub!(/^overlay_/, '')
|
2229
|
+
overlay = true if position
|
2230
|
+
end
|
2231
|
+
|
2232
|
+
allowed = {
|
2233
|
+
'right' => 'r',
|
2234
|
+
'left' => 'l',
|
2235
|
+
'top' => 't',
|
2236
|
+
'bottom' => 'b'
|
2237
|
+
}
|
2238
|
+
|
2239
|
+
return if position == 'none'
|
2240
|
+
return unless allowed.has_key?(position)
|
2241
|
+
|
2242
|
+
position = allowed[position]
|
2243
|
+
|
2244
|
+
@writer.start_tag('c:legend')
|
2245
|
+
|
2246
|
+
# Write the c:legendPos element.
|
2247
|
+
write_legend_pos(position)
|
2248
|
+
|
2249
|
+
# Remove series labels from the legend.
|
2250
|
+
@delete_series.each do |index|
|
2251
|
+
# Write the c:legendEntry element.
|
2252
|
+
write_legend_entry(index)
|
2253
|
+
end if @delete_series
|
2254
|
+
|
2255
|
+
# Write the c:layout element.
|
2256
|
+
write_layout
|
2257
|
+
|
2258
|
+
# Write the c:overlay element.
|
2259
|
+
write_overlay if overlay
|
2260
|
+
|
2261
|
+
@writer.end_tag('c:legend')
|
2262
|
+
end
|
2263
|
+
|
2264
|
+
#
|
2265
|
+
# Write the <c:legendPos> element.
|
2266
|
+
#
|
2267
|
+
def write_legend_pos(val) # :nodoc:
|
2268
|
+
attributes = ['val', val]
|
2269
|
+
|
2270
|
+
@writer.empty_tag('c:legendPos', attributes)
|
2271
|
+
end
|
2272
|
+
|
2273
|
+
#
|
2274
|
+
# Write the <c:legendEntry> element.
|
2275
|
+
#
|
2276
|
+
def write_legend_entry(index) # :nodoc:
|
2277
|
+
@writer.start_tag('c:legendEntry')
|
2278
|
+
|
2279
|
+
# Write the c:idx element.
|
2280
|
+
write_idx(index)
|
2281
|
+
|
2282
|
+
# Write the c:delete element.
|
2283
|
+
write_delete(1)
|
2284
|
+
|
2285
|
+
@writer.end_tag('c:legendEntry')
|
2286
|
+
end
|
2287
|
+
|
2288
|
+
#
|
2289
|
+
# Write the <c:overlay> element.
|
2290
|
+
#
|
2291
|
+
def write_overlay # :nodoc:
|
2292
|
+
val = 1
|
2293
|
+
|
2294
|
+
attributes = ['val', val]
|
2295
|
+
|
2296
|
+
@writer.empty_tag('c:overlay', attributes)
|
2297
|
+
end
|
2298
|
+
|
2299
|
+
#
|
2300
|
+
# Write the <c:plotVisOnly> element.
|
2301
|
+
#
|
2302
|
+
def write_plot_vis_only # :nodoc:
|
2303
|
+
val = 1
|
2304
|
+
|
2305
|
+
attributes = ['val', val]
|
2306
|
+
|
2307
|
+
@writer.empty_tag('c:plotVisOnly', attributes)
|
2308
|
+
end
|
2309
|
+
|
2310
|
+
#
|
2311
|
+
# Write the <c:printSettings> element.
|
2312
|
+
#
|
2313
|
+
def write_print_settings # :nodoc:
|
2314
|
+
@writer.start_tag('c:printSettings')
|
2315
|
+
|
2316
|
+
# Write the c:headerFooter element.
|
2317
|
+
write_header_footer
|
2318
|
+
|
2319
|
+
# Write the c:pageMargins element.
|
2320
|
+
write_page_margins
|
2321
|
+
|
2322
|
+
# Write the c:pageSetup element.
|
2323
|
+
write_page_setup
|
2324
|
+
|
2325
|
+
@writer.end_tag('c:printSettings')
|
2326
|
+
end
|
2327
|
+
|
2328
|
+
#
|
2329
|
+
# Write the <c:headerFooter> element.
|
2330
|
+
#
|
2331
|
+
def write_header_footer # :nodoc:
|
2332
|
+
@writer.empty_tag('c:headerFooter')
|
2333
|
+
end
|
2334
|
+
|
2335
|
+
#
|
2336
|
+
# Write the <c:pageMargins> element.
|
2337
|
+
#
|
2338
|
+
def write_page_margins # :nodoc:
|
2339
|
+
b = 0.75
|
2340
|
+
l = 0.7
|
2341
|
+
r = 0.7
|
2342
|
+
t = 0.75
|
2343
|
+
header = 0.3
|
2344
|
+
footer = 0.3
|
2345
|
+
|
2346
|
+
attributes = [
|
2347
|
+
'b', b,
|
2348
|
+
'l', l,
|
2349
|
+
'r', r,
|
2350
|
+
't', t,
|
2351
|
+
'header', header,
|
2352
|
+
'footer', footer
|
2353
|
+
]
|
2354
|
+
|
2355
|
+
@writer.empty_tag('c:pageMargins', attributes)
|
2356
|
+
end
|
2357
|
+
|
2358
|
+
#
|
2359
|
+
# Write the <c:pageSetup> element.
|
2360
|
+
#
|
2361
|
+
def write_page_setup # :nodoc:
|
2362
|
+
@writer.empty_tag('c:pageSetup')
|
2363
|
+
end
|
2364
|
+
|
2365
|
+
#
|
2366
|
+
# Write the <c:title> element for a rich string.
|
2367
|
+
#
|
2368
|
+
def write_title_rich(title, horiz = nil) # :nodoc:
|
2369
|
+
@writer.start_tag('c:title')
|
2370
|
+
|
2371
|
+
# Write the c:tx element.
|
2372
|
+
write_tx_rich(title, horiz)
|
2373
|
+
|
2374
|
+
# Write the c:layout element.
|
2375
|
+
write_layout
|
2376
|
+
|
2377
|
+
@writer.end_tag('c:title')
|
2378
|
+
end
|
2379
|
+
|
2380
|
+
#
|
2381
|
+
# Write the <c:title> element for a rich string.
|
2382
|
+
#
|
2383
|
+
def write_title_formula(title, data_id, horiz) # :nodoc:
|
2384
|
+
@writer.start_tag('c:title')
|
2385
|
+
|
2386
|
+
# Write the c:tx element.
|
2387
|
+
write_tx_formula(title, data_id)
|
2388
|
+
|
2389
|
+
# Write the c:layout element.
|
2390
|
+
write_layout
|
2391
|
+
|
2392
|
+
# Write the c:txPr element.
|
2393
|
+
write_tx_pr(horiz)
|
2394
|
+
|
2395
|
+
@writer.end_tag('c:title')
|
2396
|
+
end
|
2397
|
+
|
2398
|
+
#
|
2399
|
+
# Write the <c:tx> element.
|
2400
|
+
#
|
2401
|
+
def write_tx_rich(title, horiz) # :nodoc:
|
2402
|
+
@writer.start_tag('c:tx')
|
2403
|
+
|
2404
|
+
# Write the c:rich element.
|
2405
|
+
write_rich(title, horiz)
|
2406
|
+
|
2407
|
+
@writer.end_tag('c:tx')
|
2408
|
+
end
|
2409
|
+
|
2410
|
+
#
|
2411
|
+
# Write the <c:tx> element with a simple value such as for series names.
|
2412
|
+
#
|
2413
|
+
def write_tx_value(title) # :nodoc:
|
2414
|
+
@writer.start_tag('c:tx')
|
2415
|
+
|
2416
|
+
# Write the c:v element.
|
2417
|
+
write_v(title)
|
2418
|
+
|
2419
|
+
@writer.end_tag('c:tx')
|
2420
|
+
end
|
2421
|
+
|
2422
|
+
#
|
2423
|
+
# Write the <c:tx> element.
|
2424
|
+
#
|
2425
|
+
def write_tx_formula(title, data_id) # :nodoc:
|
2426
|
+
data = @formula_data[data_id] if data_id
|
2427
|
+
|
2428
|
+
@writer.start_tag('c:tx')
|
2429
|
+
|
2430
|
+
# Write the c:strRef element.
|
2431
|
+
write_str_ref(title, data, 'str')
|
2432
|
+
|
2433
|
+
@writer.end_tag('c:tx')
|
2434
|
+
end
|
2435
|
+
|
2436
|
+
#
|
2437
|
+
# Write the <c:rich> element.
|
2438
|
+
#
|
2439
|
+
def write_rich(title, horiz) # :nodoc:
|
2440
|
+
@writer.start_tag('c:rich')
|
2441
|
+
|
2442
|
+
# Write the a:bodyPr element.
|
2443
|
+
write_a_body_pr(horiz)
|
2444
|
+
|
2445
|
+
# Write the a:lstStyle element.
|
2446
|
+
write_a_lst_style
|
2447
|
+
|
2448
|
+
# Write the a:p element.
|
2449
|
+
write_a_p_rich(title)
|
2450
|
+
|
2451
|
+
@writer.end_tag('c:rich')
|
2452
|
+
end
|
2453
|
+
|
2454
|
+
#
|
2455
|
+
# Write the <a:bodyPr> element.
|
2456
|
+
#
|
2457
|
+
def write_a_body_pr(horiz) # :nodoc:
|
2458
|
+
rot = -5400000
|
2459
|
+
vert = 'horz'
|
2460
|
+
|
2461
|
+
attributes = [
|
2462
|
+
'rot', rot,
|
2463
|
+
'vert', vert
|
2464
|
+
]
|
2465
|
+
|
2466
|
+
attributes = [] if !horiz || horiz == 0
|
2467
|
+
|
2468
|
+
@writer.empty_tag('a:bodyPr', attributes)
|
2469
|
+
end
|
2470
|
+
|
2471
|
+
#
|
2472
|
+
# Write the <a:lstStyle> element.
|
2473
|
+
#
|
2474
|
+
def write_a_lst_style # :nodoc:
|
2475
|
+
@writer.empty_tag('a:lstStyle')
|
2476
|
+
end
|
2477
|
+
|
2478
|
+
#
|
2479
|
+
# Write the <a:p> element for rich string titles.
|
2480
|
+
#
|
2481
|
+
def write_a_p_rich(title) # :nodoc:
|
2482
|
+
@writer.start_tag('a:p')
|
2483
|
+
|
2484
|
+
# Write the a:pPr element.
|
2485
|
+
write_a_p_pr_rich
|
2486
|
+
|
2487
|
+
# Write the a:r element.
|
2488
|
+
write_a_r(title)
|
2489
|
+
|
2490
|
+
@writer.end_tag('a:p')
|
2491
|
+
end
|
2492
|
+
|
2493
|
+
#
|
2494
|
+
# Write the <a:p> element for formula titles.
|
2495
|
+
#
|
2496
|
+
def write_a_p_formula(title) # :nodoc:
|
2497
|
+
@writer.start_tag('a:p')
|
2498
|
+
|
2499
|
+
# Write the a:pPr element.
|
2500
|
+
write_a_p_pr_formula
|
2501
|
+
|
2502
|
+
# Write the a:endParaRPr element.
|
2503
|
+
write_a_end_para_rpr
|
2504
|
+
|
2505
|
+
@writer.end_tag('a:p')
|
2506
|
+
end
|
2507
|
+
|
2508
|
+
#
|
2509
|
+
# Write the <a:pPr> element for rich string titles.
|
2510
|
+
#
|
2511
|
+
def write_a_p_pr_rich # :nodoc:
|
2512
|
+
@writer.start_tag('a:pPr')
|
2513
|
+
|
2514
|
+
# Write the a:defRPr element.
|
2515
|
+
write_a_def_rpr
|
2516
|
+
|
2517
|
+
@writer.end_tag('a:pPr')
|
2518
|
+
end
|
2519
|
+
|
2520
|
+
#
|
2521
|
+
# Write the <a:pPr> element for formula titles.
|
2522
|
+
#
|
2523
|
+
def write_a_p_pr_formula # :nodoc:
|
2524
|
+
@writer.start_tag('a:pPr')
|
2525
|
+
|
2526
|
+
# Write the a:defRPr element.
|
2527
|
+
write_a_def_rpr
|
2528
|
+
|
2529
|
+
@writer.end_tag('a:pPr')
|
2530
|
+
end
|
2531
|
+
|
2532
|
+
#
|
2533
|
+
# Write the <a:defRPr> element.
|
2534
|
+
#
|
2535
|
+
def write_a_def_rpr # :nodoc:
|
2536
|
+
@writer.empty_tag('a:defRPr')
|
2537
|
+
end
|
2538
|
+
|
2539
|
+
#
|
2540
|
+
# Write the <a:endParaRPr> element.
|
2541
|
+
#
|
2542
|
+
def write_a_end_para_rpr # :nodoc:
|
2543
|
+
lang = 'en-US'
|
2544
|
+
|
2545
|
+
attributes = ['lang', lang]
|
2546
|
+
|
2547
|
+
@writer.empty_tag('a:endParaRPr', attributes)
|
2548
|
+
end
|
2549
|
+
|
2550
|
+
#
|
2551
|
+
# Write the <a:r> element.
|
2552
|
+
#
|
2553
|
+
def write_a_r(title) # :nodoc:
|
2554
|
+
@writer.start_tag('a:r')
|
2555
|
+
|
2556
|
+
# Write the a:rPr element.
|
2557
|
+
write_a_r_pr
|
2558
|
+
|
2559
|
+
# Write the a:t element.
|
2560
|
+
write_a_t(title)
|
2561
|
+
|
2562
|
+
@writer.end_tag('a:r')
|
2563
|
+
end
|
2564
|
+
|
2565
|
+
#
|
2566
|
+
# Write the <a:rPr> element.
|
2567
|
+
#
|
2568
|
+
def write_a_r_pr # :nodoc:
|
2569
|
+
lang = 'en-US'
|
2570
|
+
|
2571
|
+
attributes = ['lang', lang]
|
2572
|
+
|
2573
|
+
@writer.empty_tag('a:rPr', attributes)
|
2574
|
+
end
|
2575
|
+
|
2576
|
+
#
|
2577
|
+
# Write the <a:t> element.
|
2578
|
+
#
|
2579
|
+
def write_a_t(title) # :nodoc:
|
2580
|
+
@writer.data_element('a:t', title)
|
2581
|
+
end
|
2582
|
+
|
2583
|
+
#
|
2584
|
+
# Write the <c:txPr> element.
|
2585
|
+
#
|
2586
|
+
def write_tx_pr(horiz) # :nodoc:
|
2587
|
+
@writer.start_tag('c:txPr')
|
2588
|
+
|
2589
|
+
# Write the a:bodyPr element.
|
2590
|
+
write_a_body_pr(horiz)
|
2591
|
+
|
2592
|
+
# Write the a:lstStyle element.
|
2593
|
+
write_a_lst_style
|
2594
|
+
|
2595
|
+
# Write the a:p element.
|
2596
|
+
write_a_p_formula
|
2597
|
+
|
2598
|
+
@writer.end_tag('c:txPr')
|
2599
|
+
end
|
2600
|
+
|
2601
|
+
#
|
2602
|
+
# Write the <c:marker> element.
|
2603
|
+
#
|
2604
|
+
def write_marker(marker = nil) # :nodoc:
|
2605
|
+
marker ||= @default_marker
|
2606
|
+
|
2607
|
+
return if marker.nil? || marker == 0
|
2608
|
+
return if marker[:automatic] && marker[:automatic] != 0
|
2609
|
+
|
2610
|
+
@writer.start_tag('c:marker')
|
2611
|
+
|
2612
|
+
# Write the c:symbol element.
|
2613
|
+
write_symbol(marker[:type])
|
2614
|
+
|
2615
|
+
# Write the c:size element.
|
2616
|
+
size = marker[:size]
|
2617
|
+
write_marker_size(size) if !size.nil? && size != 0
|
2618
|
+
|
2619
|
+
# Write the c:spPr element.
|
2620
|
+
write_sp_pr(marker)
|
2621
|
+
|
2622
|
+
@writer.end_tag('c:marker')
|
2623
|
+
end
|
2624
|
+
|
2625
|
+
#
|
2626
|
+
# Write the <c:marker> element without a sub-element.
|
2627
|
+
#
|
2628
|
+
def write_marker_value # :nodoc:
|
2629
|
+
style = @default_marker
|
2630
|
+
|
2631
|
+
return unless style
|
2632
|
+
|
2633
|
+
attributes = ['val', 1]
|
2634
|
+
|
2635
|
+
@writer.empty_tag('c:marker', attributes)
|
2636
|
+
end
|
2637
|
+
|
2638
|
+
#
|
2639
|
+
# Write the <c:size> element.
|
2640
|
+
#
|
2641
|
+
def write_marker_size(val) # :nodoc:
|
2642
|
+
attributes = ['val', val]
|
2643
|
+
|
2644
|
+
@writer.empty_tag('c:size', attributes)
|
2645
|
+
end
|
2646
|
+
|
2647
|
+
#
|
2648
|
+
# Write the <c:symbol> element.
|
2649
|
+
#
|
2650
|
+
def write_symbol(val) # :nodoc:
|
2651
|
+
attributes = ['val', val]
|
2652
|
+
|
2653
|
+
@writer.empty_tag('c:symbol', attributes)
|
2654
|
+
end
|
2655
|
+
|
2656
|
+
#
|
2657
|
+
# Write the <c:spPr> element.
|
2658
|
+
#
|
2659
|
+
def write_sp_pr(series) # :nodoc:
|
2660
|
+
return if (!series.has_key?(:_line) || series[:_line][:_defined].nil? || series[:_line][:_defined]== 0) &&
|
2661
|
+
(!series.has_key?(:_fill) || series[:_fill][:_defined].nil? || series[:_fill][:_defined]== 0)
|
2662
|
+
|
2663
|
+
@writer.start_tag('c:spPr')
|
2664
|
+
|
2665
|
+
# Write the a:solidFill element for solid charts such as pie and bar.
|
2666
|
+
write_a_solid_fill(series[:_fill]) if series[:_fill] && series[:_fill][:_defined] != 0
|
2667
|
+
|
2668
|
+
# Write the a:ln element.
|
2669
|
+
write_a_ln(series[:_line]) if series[:_line] && series[:_line][:_defined]
|
2670
|
+
|
2671
|
+
@writer.end_tag('c:spPr')
|
2672
|
+
end
|
2673
|
+
|
2674
|
+
#
|
2675
|
+
# Write the <a:ln> element.
|
2676
|
+
#
|
2677
|
+
def write_a_ln(line) # :nodoc:
|
2678
|
+
attributes = []
|
2679
|
+
|
2680
|
+
# Add the line width as an attribute.
|
2681
|
+
if width = line[:width]
|
2682
|
+
# Round width to nearest 0.25, like Excel.
|
2683
|
+
width = ((width + 0.125) * 4).to_i / 4.0
|
2684
|
+
|
2685
|
+
# Convert to internal units.
|
2686
|
+
width = (0.5 + (12700 * width)).to_i
|
2687
|
+
|
2688
|
+
attributes = ['w', width]
|
2689
|
+
end
|
2690
|
+
|
2691
|
+
@writer.start_tag('a:ln', attributes)
|
2692
|
+
|
2693
|
+
# Write the line fill.
|
2694
|
+
if !line[:none].nil? && line[:none] != 0
|
2695
|
+
# Write the a:noFill element.
|
2696
|
+
write_a_no_fill
|
2697
|
+
else
|
2698
|
+
# Write the a:solidFill element.
|
2699
|
+
write_a_solid_fill(line)
|
2700
|
+
end
|
2701
|
+
|
2702
|
+
# Write the line/dash type.
|
2703
|
+
if type = line[:dash_type]
|
2704
|
+
# Write the a:prstDash element.
|
2705
|
+
write_a_prst_dash(type)
|
2706
|
+
end
|
2707
|
+
|
2708
|
+
@writer.end_tag('a:ln')
|
2709
|
+
end
|
2710
|
+
|
2711
|
+
#
|
2712
|
+
# Write the <a:noFill> element.
|
2713
|
+
#
|
2714
|
+
def write_a_no_fill # :nodoc:
|
2715
|
+
@writer.empty_tag('a:noFill')
|
2716
|
+
end
|
2717
|
+
|
2718
|
+
#
|
2719
|
+
# Write the <a:solidFill> element.
|
2720
|
+
#
|
2721
|
+
def write_a_solid_fill(line) # :nodoc:
|
2722
|
+
@writer.start_tag('a:solidFill')
|
2723
|
+
|
2724
|
+
if line[:color]
|
2725
|
+
color = get_color(line[:color])
|
2726
|
+
|
2727
|
+
# Write the a:srgbClr element.
|
2728
|
+
write_a_srgb_clr(color)
|
2729
|
+
end
|
2730
|
+
|
2731
|
+
@writer.end_tag('a:solidFill')
|
2732
|
+
end
|
2733
|
+
|
2734
|
+
#
|
2735
|
+
# Write the <a:srgbClr> element.
|
2736
|
+
#
|
2737
|
+
def write_a_srgb_clr(val) # :nodoc:
|
2738
|
+
attributes = ['val', val]
|
2739
|
+
|
2740
|
+
@writer.empty_tag('a:srgbClr', attributes)
|
2741
|
+
end
|
2742
|
+
|
2743
|
+
#
|
2744
|
+
# Write the <a:prstDash> element.
|
2745
|
+
#
|
2746
|
+
def write_a_prst_dash(val) # :nodoc:
|
2747
|
+
attributes = ['val', val]
|
2748
|
+
|
2749
|
+
@writer.empty_tag('a:prstDash', attributes)
|
2750
|
+
end
|
2751
|
+
|
2752
|
+
#
|
2753
|
+
# Write the <c:trendline> element.
|
2754
|
+
#
|
2755
|
+
def write_trendline(trendline) # :nodoc:
|
2756
|
+
return unless trendline
|
2757
|
+
|
2758
|
+
@writer.start_tag('c:trendline')
|
2759
|
+
|
2760
|
+
# Write the c:name element.
|
2761
|
+
write_name(trendline[name])
|
2762
|
+
|
2763
|
+
# Write the c:spPr element.
|
2764
|
+
write_sp_pr(trendline)
|
2765
|
+
|
2766
|
+
# Write the c:trendlineType element.
|
2767
|
+
write_trendline_type(trendline[type])
|
2768
|
+
|
2769
|
+
# Write the c:order element for polynomial trendlines.
|
2770
|
+
write_trendline_order(trendline[order]) if trendline[type] == 'poly'
|
2771
|
+
|
2772
|
+
# Write the c:period element for moving average trendlines.
|
2773
|
+
write_period(trendline[period]) if trendline[type] == 'movingAvg'
|
2774
|
+
|
2775
|
+
|
2776
|
+
# Write the c:forward element.
|
2777
|
+
write_forward(trendline[forward])
|
2778
|
+
|
2779
|
+
# Write the c:backward element.
|
2780
|
+
write_backward(trendline[backward])
|
2781
|
+
|
2782
|
+
@writer.end_tag('c:trendline')
|
2783
|
+
end
|
2784
|
+
|
2785
|
+
#
|
2786
|
+
# Write the <c:trendlineType> element.
|
2787
|
+
#
|
2788
|
+
def write_trendline_type(val) # :nodoc:
|
2789
|
+
attributes = ['val', val]
|
2790
|
+
|
2791
|
+
@writer.empty_tag('c:trendlineType', attributes)
|
2792
|
+
end
|
2793
|
+
|
2794
|
+
#
|
2795
|
+
# Write the <c:name> element.
|
2796
|
+
#
|
2797
|
+
def write_name(data) # :nodoc:
|
2798
|
+
return unless data
|
2799
|
+
|
2800
|
+
@writer.data_element('c:name', data)
|
2801
|
+
end
|
2802
|
+
|
2803
|
+
#
|
2804
|
+
# Write the <c:order> element.
|
2805
|
+
#
|
2806
|
+
def write_trendline_order(val = 2) # :nodoc:
|
2807
|
+
attributes = ['val', val]
|
2808
|
+
|
2809
|
+
@writer.empty_tag('c:order', attributes)
|
2810
|
+
end
|
2811
|
+
|
2812
|
+
#
|
2813
|
+
# Write the <c:period> element.
|
2814
|
+
#
|
2815
|
+
def write_period(val = 2) # :nodoc:
|
2816
|
+
attributes = ['val', val]
|
2817
|
+
|
2818
|
+
@writer.empty_tag('c:period', attributes)
|
2819
|
+
end
|
2820
|
+
|
2821
|
+
#
|
2822
|
+
# Write the <c:forward> element.
|
2823
|
+
#
|
2824
|
+
def write_forward(val) # :nodoc:
|
2825
|
+
return unless val
|
2826
|
+
|
2827
|
+
attributes = ['val', val]
|
2828
|
+
|
2829
|
+
@writer.empty_tag('c:forward', attributes)
|
2830
|
+
end
|
2831
|
+
|
2832
|
+
#
|
2833
|
+
# Write the <c:backward> element.
|
2834
|
+
#
|
2835
|
+
def write_backward(val) # :nodoc:
|
2836
|
+
return unless val
|
2837
|
+
|
2838
|
+
attributes = ['val', val]
|
2839
|
+
|
2840
|
+
@writer.empty_tag('c:backward', attributes)
|
2841
|
+
end
|
2842
|
+
|
2843
|
+
#
|
2844
|
+
# Write the <c:hiLowLines> element.
|
2845
|
+
#
|
2846
|
+
def write_hi_low_lines # :nodoc:
|
2847
|
+
@writer.empty_tag('c:hiLowLines')
|
2848
|
+
end
|
2849
|
+
|
2850
|
+
#
|
2851
|
+
# Write the <c:overlap> element.
|
2852
|
+
#
|
2853
|
+
def write_overlap # :nodoc:
|
2854
|
+
val = 100
|
2855
|
+
|
2856
|
+
attributes = ['val', val]
|
2857
|
+
|
2858
|
+
@writer.empty_tag('c:overlap', attributes)
|
2859
|
+
end
|
2860
|
+
|
2861
|
+
#
|
2862
|
+
# Write the <c:numCache> element.
|
2863
|
+
#
|
2864
|
+
def write_num_cache(data) # :nodoc:
|
2865
|
+
count = data.size
|
2866
|
+
|
2867
|
+
@writer.start_tag('c:numCache')
|
2868
|
+
|
2869
|
+
# Write the c:formatCode element.
|
2870
|
+
write_format_code('General')
|
2871
|
+
|
2872
|
+
# Write the c:ptCount element.
|
2873
|
+
write_pt_count(count)
|
2874
|
+
|
2875
|
+
(0 .. count - 1).each do |i|
|
2876
|
+
|
2877
|
+
# Write the c:pt element.
|
2878
|
+
write_pt(i, data[i])
|
2879
|
+
end
|
2880
|
+
|
2881
|
+
@writer.end_tag('c:numCache')
|
2882
|
+
end
|
2883
|
+
|
2884
|
+
#
|
2885
|
+
# Write the <c:strCache> element.
|
2886
|
+
#
|
2887
|
+
def write_str_cache(data) # :nodoc:
|
2888
|
+
count = data.size
|
2889
|
+
|
2890
|
+
@writer.start_tag('c:strCache')
|
2891
|
+
|
2892
|
+
# Write the c:ptCount element.
|
2893
|
+
write_pt_count(count)
|
2894
|
+
|
2895
|
+
(0 .. count - 1).each do |i|
|
2896
|
+
|
2897
|
+
# Write the c:pt element.
|
2898
|
+
write_pt(i, data[i])
|
2899
|
+
end
|
2900
|
+
|
2901
|
+
@writer.end_tag('c:strCache')
|
2902
|
+
end
|
2903
|
+
|
2904
|
+
#
|
2905
|
+
# Write the <c:formatCode> element.
|
2906
|
+
#
|
2907
|
+
def write_format_code(data) # :nodoc:
|
2908
|
+
@writer.data_element('c:formatCode', data)
|
2909
|
+
end
|
2910
|
+
|
2911
|
+
#
|
2912
|
+
# Write the <c:ptCount> element.
|
2913
|
+
#
|
2914
|
+
def write_pt_count(val) # :nodoc:
|
2915
|
+
attributes = ['val', val]
|
2916
|
+
|
2917
|
+
@writer.empty_tag('c:ptCount', attributes)
|
2918
|
+
end
|
2919
|
+
|
2920
|
+
#
|
2921
|
+
# Write the <c:pt> element.
|
2922
|
+
#
|
2923
|
+
def write_pt(idx, value) # :nodoc:
|
2924
|
+
return unless value
|
2925
|
+
|
2926
|
+
attributes = ['idx', idx]
|
2927
|
+
|
2928
|
+
@writer.start_tag('c:pt', attributes)
|
2929
|
+
|
2930
|
+
# Write the c:v element.
|
2931
|
+
write_v(value)
|
2932
|
+
|
2933
|
+
@writer.end_tag('c:pt')
|
2934
|
+
end
|
2935
|
+
|
2936
|
+
#
|
2937
|
+
# Write the <c:v> element.
|
2938
|
+
#
|
2939
|
+
def write_v(data) # :nodoc:
|
2940
|
+
@writer.data_element('c:v', data)
|
2941
|
+
end
|
2942
|
+
|
2943
|
+
#
|
2944
|
+
# Write the <c:protection> element.
|
2945
|
+
#
|
2946
|
+
def write_protection # :nodoc:
|
2947
|
+
return if @protection == 0
|
2948
|
+
|
2949
|
+
@writer.empty_tag('c:protection')
|
2950
|
+
end
|
2951
|
+
|
2952
|
+
#
|
2953
|
+
# Write the <c:dLbls> element.
|
2954
|
+
#
|
2955
|
+
def write_d_lbls(labels) # :nodoc:
|
2956
|
+
return unless labels
|
2957
|
+
|
2958
|
+
@writer.start_tag('c:dLbls')
|
2959
|
+
|
2960
|
+
# Write the c:showVal element.
|
2961
|
+
write_show_val if labels[value]
|
2962
|
+
|
2963
|
+
# Write the c:showCatName element.
|
2964
|
+
write_show_cat_name if labels[category]
|
2965
|
+
|
2966
|
+
# Write the c:showSerName element.
|
2967
|
+
write_show_ser_name if labels[series_name]
|
2968
|
+
|
2969
|
+
@writer.end_tag('c:dLbls')
|
2970
|
+
end
|
2971
|
+
|
2972
|
+
#
|
2973
|
+
# Write the <c:showVal> element.
|
2974
|
+
#
|
2975
|
+
def write_show_val # :nodoc:
|
2976
|
+
val = 1
|
2977
|
+
|
2978
|
+
attributes = ['val', val]
|
2979
|
+
|
2980
|
+
@writer.empty_tag('c:showVal', attributes)
|
2981
|
+
end
|
2982
|
+
|
2983
|
+
#
|
2984
|
+
# Write the <c:showCatName> element.
|
2985
|
+
#
|
2986
|
+
def write_show_cat_name # :nodoc:
|
2987
|
+
val = 1
|
2988
|
+
|
2989
|
+
attributes = ['val', val]
|
2990
|
+
|
2991
|
+
@writer.empty_tag('c:showCatName', attributes)
|
2992
|
+
end
|
2993
|
+
|
2994
|
+
#
|
2995
|
+
# Write the <c:showSerName> element.
|
2996
|
+
#
|
2997
|
+
def write_show_ser_name # :nodoc:
|
2998
|
+
val = 1
|
2999
|
+
|
3000
|
+
attributes = ['val', val]
|
3001
|
+
|
3002
|
+
@writer.empty_tag('c:showSerName', attributes)
|
3003
|
+
end
|
3004
|
+
|
3005
|
+
#
|
3006
|
+
# Write the <c:delete> element.
|
3007
|
+
#
|
3008
|
+
def write_delete(val) # :nodoc:
|
3009
|
+
attributes = ['val', val]
|
3010
|
+
|
3011
|
+
@writer.empty_tag('c:delete', attributes)
|
3012
|
+
end
|
3013
|
+
|
3014
|
+
#
|
3015
|
+
# Write the <c:invertIfNegative> element.
|
3016
|
+
#
|
3017
|
+
def write_c_invert_if_negative(invert = nil) # :nodoc:
|
3018
|
+
val = 1
|
3019
|
+
|
3020
|
+
return unless invert
|
3021
|
+
|
3022
|
+
attributes = ['val', val]
|
3023
|
+
|
3024
|
+
@writer.empty_tag('c:invertIfNegative', attributes)
|
3025
|
+
end
|
3026
|
+
end
|
3027
|
+
end
|