File Coverage

blib/lib/Excel/Writer/XLSX/Chart.pm
Criterion Covered Total %
statement 2001 2081 96.1
branch 644 726 88.7
condition 129 169 76.3
subroutine 222 223 99.5
pod 18 20 90.0
total 3014 3219 93.6


line stmt bran cond sub pod time code
1              
2             ###############################################################################
3             #
4             # Chart - A class for writing Excel Charts.
5             #
6             #
7             # Used in conjunction with Excel::Writer::XLSX.
8             #
9             # Copyright 2000-2021, John McNamara, jmcnamara@cpan.org
10             #
11             # Documentation after __END__
12             #
13              
14             # perltidy with the following options: -mbl=2 -pt=0 -nola
15              
16             use 5.008002;
17 1124     1124   17283 use strict;
  1124         4331  
18 1124     1124   5591 use warnings;
  1124         3121  
  1124         19094  
19 1124     1124   6165 use Carp;
  1124         2784  
  1124         23691  
20 1124     1124   5301 use Excel::Writer::XLSX::Format;
  1124         2952  
  1124         48402  
21 1124     1124   6022 use Excel::Writer::XLSX::Package::XMLwriter;
  1124         2605  
  1124         27562  
22 1124     1124   7083 use Excel::Writer::XLSX::Utility qw(xl_cell_to_rowcol
  1124         2851  
  1124         34293  
23 1124         17270156 xl_rowcol_to_cell
24             xl_col_to_name
25             xl_range_formula
26             quote_sheetname );
27 1124     1124   6173  
  1124         2987  
28             our @ISA = qw(Excel::Writer::XLSX::Package::XMLwriter);
29             our $VERSION = '1.09';
30              
31              
32             ###############################################################################
33             #
34             # factory()
35             #
36             # Factory method for returning chart objects based on their class type.
37             #
38              
39             my $current_class = shift;
40             my $chart_subclass = shift;
41 437     437 0 992  
42 437         848 $chart_subclass = ucfirst lc $chart_subclass;
43              
44 437         1804 my $module = "Excel::Writer::XLSX::Chart::" . $chart_subclass;
45              
46 437         1533 eval "require $module";
47              
48 437         28223 # TODO. Need to re-raise this error from Workbook::add_chart().
49             die "Chart type '$chart_subclass' not supported in add_chart()\n" if $@;
50              
51 437 50       2214 my $fh = undef;
52             return $module->new( $fh, @_ );
53 437         1114 }
54 437         2935  
55              
56             ###############################################################################
57             #
58             # new()
59             #
60             # Default constructor for sub-classes.
61             #
62              
63             my $class = shift;
64             my $fh = shift;
65             my $self = Excel::Writer::XLSX::Package::XMLwriter->new( $fh );
66 523     523 0 63223  
67 523         930 $self->{_subtype} = shift;
68 523         2116 $self->{_sheet_type} = 0x0200;
69             $self->{_orientation} = 0x0;
70 523         1951 $self->{_series} = [];
71 523         1277 $self->{_embedded} = 0;
72 523         1078 $self->{_id} = -1;
73 523         1177 $self->{_series_index} = 0;
74 523         1159 $self->{_style_id} = 2;
75 523         1151 $self->{_axis_ids} = [];
76 523         1390 $self->{_axis2_ids} = [];
77 523         1079 $self->{_cat_has_num_fmt} = 0;
78 523         2239 $self->{_requires_category} = 0;
79 523         1901 $self->{_legend} = {};
80 523         1082 $self->{_cat_axis_position} = 'b';
81 523         1685 $self->{_val_axis_position} = 'l';
82 523         1517 $self->{_formula_ids} = {};
83 523         1164 $self->{_formula_data} = [];
84 523         25455 $self->{_horiz_cat_axis} = 0;
85 523         17901 $self->{_horiz_val_axis} = 1;
86 523         2511 $self->{_protection} = 0;
87 523         1326 $self->{_chartarea} = {};
88 523         978 $self->{_plotarea} = {};
89 523         1030 $self->{_x_axis} = {};
90 523         1032 $self->{_y_axis} = {};
91 523         1005 $self->{_y2_axis} = {};
92 523         954 $self->{_x2_axis} = {};
93 523         921 $self->{_chart_name} = '';
94 523         955 $self->{_show_blanks} = 'gap';
95 523         937 $self->{_show_hidden_data} = 0;
96 523         1092 $self->{_show_crosses} = 1;
97 523         1007 $self->{_width} = 480;
98 523         923 $self->{_height} = 288;
99 523         900 $self->{_x_scale} = 1;
100 523         1595 $self->{_y_scale} = 1;
101 523         1081 $self->{_x_offset} = 0;
102 523         1002 $self->{_y_offset} = 0;
103 523         963 $self->{_table} = undef;
104 523         979 $self->{_smooth_allowed} = 0;
105 523         943 $self->{_cross_between} = 'between';
106 523         1256 $self->{_date_category} = 0;
107 523         900 $self->{_already_inserted} = 0;
108 523         942 $self->{_combined} = undef;
109 523         873 $self->{_is_secondary} = 0;
110 523         927  
111 523         876 $self->{_label_positions} = {};
112 523         860 $self->{_label_position_default} = '';
113              
114 523         901 bless $self, $class;
115 523         888 $self->_set_default_properties();
116             return $self;
117 523         1016 }
118 523         2098  
119 523         1389  
120             ###############################################################################
121             #
122             # _assemble_xml_file()
123             #
124             # Assemble and write the XML file.
125             #
126              
127             my $self = shift;
128              
129             $self->xml_declaration();
130              
131 426     426   956 # Write the c:chartSpace element.
132             $self->_write_chart_space();
133 426         2529  
134             # Write the c:lang element.
135             $self->_write_lang();
136 426         2843  
137             # Write the c:style element.
138             $self->_write_style();
139 426         2564  
140             # Write the c:protection element.
141             $self->_write_protection();
142 426         2200  
143             # Write the c:chart element.
144             $self->_write_chart();
145 426         2357  
146             # Write the c:spPr element for the chartarea formatting.
147             $self->_write_sp_pr( $self->{_chartarea} );
148 426         2183  
149             # Write the c:printSettings element.
150             $self->_write_print_settings() if $self->{_embedded};
151 426         2611  
152             # Close the worksheet tag.
153             $self->xml_end_tag( 'c:chartSpace' );
154 426 100       3942  
155             # Close the XML writer filehandle.
156             $self->xml_get_fh()->close();
157 426         1437 }
158              
159              
160 426         2289 ###############################################################################
161             #
162             # Public methods.
163             #
164             ###############################################################################
165              
166              
167             ###############################################################################
168             #
169             # add_series()
170             #
171             # Add a series and it's properties to a chart.
172             #
173              
174             my $self = shift;
175             my %arg = @_;
176              
177             # Check that the required input has been specified.
178             if ( !exists $arg{values} ) {
179 1037     1037 1 7081 croak "Must specify 'values' in add_series()";
180 1037         3152 }
181              
182             if ( $self->{_requires_category} && !exists $arg{categories} ) {
183 1037 50       2630 croak "Must specify 'categories' in add_series() for this chart type";
184 0         0 }
185              
186             if ( @{ $self->{_series} } == 255 ) {
187 1037 50 66     3087 carp "The maximum number of series that can be added to an "
188 0         0 . "Excel Chart is 255";
189             return
190             }
191 1037 50       1569  
  1037         2799  
192 0         0 # Convert aref params into a formula string.
193             my $values = $self->_aref_to_formula( $arg{values} );
194             my $categories = $self->_aref_to_formula( $arg{categories} );
195 0         0  
196             # Switch name and name_formula parameters if required.
197             my ( $name, $name_formula ) =
198 1037         3668 $self->_process_names( $arg{name}, $arg{name_formula} );
199 1037         2888  
200             # Get an id for the data equivalent to the range formula.
201             my $cat_id = $self->_get_data_id( $categories, $arg{categories_data} );
202             my $val_id = $self->_get_data_id( $values, $arg{values_data} );
203 1037         4574 my $name_id = $self->_get_data_id( $name_formula, $arg{name_data} );
204              
205             # Set the line properties for the series.
206 1037         4511 my $line = $self->_get_line_properties( $arg{line} );
207 1037         2771  
208 1037         2913 # Allow 'border' as a synonym for 'line' in bar/column style charts.
209             if ( $arg{border} ) {
210             $line = $self->_get_line_properties( $arg{border} );
211 1037         3799 }
212              
213             # Set the fill properties for the series.
214 1037 100       2748 my $fill = $self->_get_fill_properties( $arg{fill} );
215 7         19  
216             # Set the pattern properties for the series.
217             my $pattern = $self->_get_pattern_properties( $arg{pattern} );
218              
219 1037         3565 # Set the gradient fill properties for the series.
220             my $gradient = $self->_get_gradient_properties( $arg{gradient} );
221              
222 1037         3990 # Pattern fill overrides solid fill.
223             if ( $pattern ) {
224             $fill = undef;
225 1037         3844 }
226              
227             # Gradient fill overrides solid and pattern fills.
228 1037 100       2431 if ( $gradient ) {
229 56         78 $pattern = undef;
230             $fill = undef;
231             }
232              
233 1037 100       2219 # Set the marker properties for the series.
234 11         21 my $marker = $self->_get_marker_properties( $arg{marker} );
235 11         23  
236             # Set the trendline properties for the series.
237             my $trendline = $self->_get_trendline_properties( $arg{trendline} );
238              
239 1037         3710 # Set the line smooth property for the series.
240             my $smooth = $arg{smooth};
241              
242 1037         3961 # Set the error bars properties for the series.
243             my $y_error_bars = $self->_get_error_bars_properties( $arg{y_error_bars} );
244             my $x_error_bars = $self->_get_error_bars_properties( $arg{x_error_bars} );
245 1037         1968  
246             # Set the point properties for the series.
247             my $points = $self->_get_points_properties($arg{points});
248 1037         3551  
249 1037         2724 # Set the labels properties for the series.
250             my $labels = $self->_get_labels_properties( $arg{data_labels} );
251              
252 1037         4084 # Set the "invert if negative" fill property.
253             my $invert_if_neg = $arg{invert_if_negative};
254              
255 1037         3733 # Set the secondary axis properties.
256             my $x2_axis = $arg{x2_axis};
257             my $y2_axis = $arg{y2_axis};
258 1037         1947  
259             # Store secondary status for combined charts.
260             if ($x2_axis || $y2_axis) {
261 1037         1489 $self->{_is_secondary} = 1;
262 1037         1589 }
263              
264             # Set the gap for Bar/Column charts.
265 1037 100 100     3541 if ( defined $arg{gap} ) {
266 13         28 if ($y2_axis) {
267             $self->{_series_gap_2} = $arg{gap};
268             }
269             else {
270 1037 100       2353 $self->{_series_gap_1} = $arg{gap};
271 7 100       16 }
272 2         2 }
273              
274             # Set the overlap for Bar/Column charts.
275 5         9 if ( defined $arg{overlap} ) {
276             if ($y2_axis) {
277             $self->{_series_overlap_2} = $arg{overlap};
278             }
279             else {
280 1037 100       2206 $self->{_series_overlap_1} = $arg{overlap};
281 7 100       15 }
282 2         2 }
283              
284             # Add the user supplied data to the internal structures.
285 5         12 %arg = (
286             _values => $values,
287             _categories => $categories,
288             _name => $name,
289             _name_formula => $name_formula,
290             _name_id => $name_id,
291 1037         11146 _val_data_id => $val_id,
292             _cat_data_id => $cat_id,
293             _line => $line,
294             _fill => $fill,
295             _pattern => $pattern,
296             _gradient => $gradient,
297             _marker => $marker,
298             _trendline => $trendline,
299             _smooth => $smooth,
300             _labels => $labels,
301             _invert_if_neg => $invert_if_neg,
302             _x2_axis => $x2_axis,
303             _y2_axis => $y2_axis,
304             _points => $points,
305             _error_bars =>
306             { _x_error_bars => $x_error_bars, _y_error_bars => $y_error_bars },
307             );
308              
309              
310             push @{ $self->{_series} }, \%arg;
311             }
312              
313              
314             ###############################################################################
315 1037         1860 #
  1037         3888  
316             # set_x_axis()
317             #
318             # Set the properties of the X-axis.
319             #
320              
321             my $self = shift;
322              
323             my $axis = $self->_convert_axis_args( $self->{_x_axis}, @_ );
324              
325             $self->{_x_axis} = $axis;
326             }
327 682     682 1 1598  
328              
329 682         2529 ###############################################################################
330             #
331 682         2022 # set_y_axis()
332             #
333             # Set the properties of the Y-axis.
334             #
335              
336             my $self = shift;
337              
338             my $axis = $self->_convert_axis_args( $self->{_y_axis}, @_ );
339              
340             $self->{_y_axis} = $axis;
341             }
342              
343 928     928 1 1891  
344             ###############################################################################
345 928         2581 #
346             # set_x2_axis()
347 928         3095 #
348             # Set the properties of the secondary X-axis.
349             #
350              
351             my $self = shift;
352              
353             my $axis = $self->_convert_axis_args( $self->{_x2_axis}, @_ );
354              
355             $self->{_x2_axis} = $axis;
356             }
357              
358              
359 537     537 1 1067 ###############################################################################
360             #
361 537         1826 # set_y2_axis()
362             #
363 537         1430 # Set the properties of the secondary Y-axis.
364             #
365              
366             my $self = shift;
367              
368             my $axis = $self->_convert_axis_args( $self->{_y2_axis}, @_ );
369              
370             $self->{_y2_axis} = $axis;
371             }
372              
373              
374             ###############################################################################
375 524     524 1 1002 #
376             # set_title()
377 524         1670 #
378             # Set the properties of the chart title.
379 524         1460 #
380              
381             my $self = shift;
382             my %arg = @_;
383              
384             my ( $name, $name_formula ) =
385             $self->_process_names( $arg{name}, $arg{name_formula} );
386              
387             my $data_id = $self->_get_data_id( $name_formula, $arg{data} );
388              
389             $self->{_title_name} = $name;
390             $self->{_title_formula} = $name_formula;
391 21     21 1 168 $self->{_title_data_id} = $data_id;
392 21         87  
393             # Set the font properties if present.
394             $self->{_title_font} = $self->_convert_font_args( $arg{name_font} );
395 21         85  
396             # Set the title layout.
397 21         87 $self->{_title_layout} = $self->_get_layout_properties( $arg{layout}, 1 );
398              
399 21         62 # Set the title overlay option.
400 21         48 $self->{_title_overlay} = $arg{overlay};
401 21         43  
402             # Set the no automatic title option.
403             $self->{_title_none} = $arg{none};
404 21         102 }
405              
406              
407 21         94 ###############################################################################
408             #
409             # set_legend()
410 21         74 #
411             # Set the properties of the chart legend.
412             #
413 21         69  
414             my $self = shift;
415              
416             # Convert the user defined properties to internal properties.
417             $self->{_legend} = $self->_get_legend_properties( @_ );
418             }
419              
420              
421             ###############################################################################
422             #
423             # set_plotarea()
424             #
425 31     31 1 405 # Set the properties of the chart plotarea.
426             #
427              
428 31         143 my $self = shift;
429              
430             # Convert the user defined properties to internal properties.
431             $self->{_plotarea} = $self->_get_area_properties( @_ );
432             }
433              
434              
435             ###############################################################################
436             #
437             # set_chartarea()
438             #
439             # Set the properties of the chart chartarea.
440 10     10 1 149 #
441              
442             my $self = shift;
443 10         37  
444             # Convert the user defined properties to internal properties.
445             $self->{_chartarea} = $self->_get_area_properties( @_ );
446             }
447              
448              
449             ###############################################################################
450             #
451             # set_style()
452             #
453             # Set on of the 48 built-in Excel chart styles. The default style is 2.
454             #
455 10     10 1 113  
456             my $self = shift;
457             my $style_id = defined $_[0] ? $_[0] : 2;
458 10         58  
459             if ( $style_id < 0 || $style_id > 48 ) {
460             $style_id = 2;
461             }
462              
463             $self->{_style_id} = $style_id;
464             }
465              
466              
467             ###############################################################################
468             #
469             # show_blanks_as()
470 6     6 1 103 #
471 6 50       26 # Set the option for displaying blank data in a chart. The default is 'gap'.
472             #
473 6 100 100     40  
474 2         4 my $self = shift;
475             my $option = shift;
476              
477 6         18 return unless $option;
478              
479             my %valid = (
480             gap => 1,
481             zero => 1,
482             span => 1,
483              
484             );
485              
486             if ( !exists $valid{$option} ) {
487             warn "Unknown show_blanks_as() option '$option'\n";
488             return;
489 6     6 1 35 }
490 6         20  
491             $self->{_show_blanks} = $option;
492 6 50       15 }
493              
494 6         23  
495             ###############################################################################
496             #
497             # show_hidden_data()
498             #
499             # Display data in hidden rows or columns.
500             #
501 6 50       25  
502 0         0 my $self = shift;
503 0         0  
504             $self->{_show_hidden_data} = 1;
505             }
506 6         21  
507              
508             ###############################################################################
509             #
510             # set_size()
511             #
512             # Set dimensions or scale for the chart.
513             #
514              
515             my $self = shift;
516             my %args = @_;
517              
518 1     1 1 6 $self->{_width} = $args{width} if $args{width};
519             $self->{_height} = $args{height} if $args{height};
520 1         3 $self->{_x_scale} = $args{x_scale} if $args{x_scale};
521             $self->{_y_scale} = $args{y_scale} if $args{y_scale};
522             $self->{_x_offset} = $args{x_offset} if $args{x_offset};
523             $self->{_y_offset} = $args{y_offset} if $args{y_offset};
524              
525             }
526              
527             # Backward compatibility with poorly chosen method name.
528             *size = *set_size;
529              
530              
531             ###############################################################################
532 3     3 1 24 #
533 3         10 # set_table()
534             #
535 3 100       12 # Set properties for an axis data table.
536 3 100       16 #
537 3 100       10  
538 3 100       10 my $self = shift;
539 3 100       10 my %args = @_;
540 3 100       13  
541             my %table = (
542             _horizontal => 1,
543             _vertical => 1,
544             _outline => 1,
545             _show_keys => 0,
546             );
547              
548             $table{_horizontal} = $args{horizontal} if defined $args{horizontal};
549             $table{_vertical} = $args{vertical} if defined $args{vertical};
550             $table{_outline} = $args{outline} if defined $args{outline};
551             $table{_show_keys} = $args{show_keys} if defined $args{show_keys};
552             $table{_font} = $self->_convert_font_args( $args{font} );
553              
554             $self->{_table} = \%table;
555             }
556 3     3 1 29  
557 3         15  
558             ###############################################################################
559 3         14 #
560             # set_up_down_bars()
561             #
562             # Set properties for the chart up-down bars.
563             #
564              
565             my $self = shift;
566 3 100       12 my %args = @_;
567 3 100       12  
568 3 100       9 # Map border to line.
569 3 100       10 if ( defined $args{up}->{border} ) {
570 3         18 $args{up}->{line} = $args{up}->{border};
571             }
572 3         11 if ( defined $args{down}->{border} ) {
573             $args{down}->{line} = $args{down}->{border};
574             }
575              
576             # Set the up and down bar properties.
577             my $up_line = $self->_get_line_properties( $args{up}->{line} );
578             my $down_line = $self->_get_line_properties( $args{down}->{line} );
579             my $up_fill = $self->_get_fill_properties( $args{up}->{fill} );
580             my $down_fill = $self->_get_fill_properties( $args{down}->{fill} );
581              
582             $self->{_up_down_bars} = {
583             _up => {
584 3     3 1 30 _line => $up_line,
585 3         7 _fill => $up_fill,
586             },
587             _down => {
588 3 50       17 _line => $down_line,
589 0         0 _fill => $down_fill,
590             },
591 3 100       8 };
592 1         2 }
593              
594              
595             ###############################################################################
596 3         14 #
597 3         12 # set_drop_lines()
598 3         19 #
599 3         9 # Set properties for the chart drop lines.
600             #
601              
602 3         17 my $self = shift;
603             my %args = @_;
604              
605             # Set the drop line properties.
606             my $line = $self->_get_line_properties( $args{line} );
607              
608             $self->{_drop_lines} = { _line => $line };
609             }
610              
611              
612             ###############################################################################
613             #
614             # set_high_low_lines()
615             #
616             # Set properties for the chart high-low lines.
617             #
618              
619             my $self = shift;
620             my %args = @_;
621              
622 4     4 1 44 # Set the drop line properties.
623 4         13 my $line = $self->_get_line_properties( $args{line} );
624              
625             $self->{_hi_low_lines} = { _line => $line };
626 4         29 }
627              
628 4         29  
629             ###############################################################################
630             #
631             # combine()
632             #
633             # Add another chart to create a combined chart.
634             #
635              
636             my $self = shift;
637             my $chart = shift;
638              
639             $self->{_combined} = $chart;
640 2     2 1 23 }
641 2         7  
642              
643             ###############################################################################
644 2         13 #
645             # Internal methods. The following section of methods are used for the internal
646 2         10 # structuring of the Chart object and file format.
647             #
648             ###############################################################################
649              
650              
651             ###############################################################################
652             #
653             # _convert_axis_args()
654             #
655             # Convert user defined axis values into private hash values.
656             #
657              
658 9     9 1 53 my $self = shift;
659 9         15 my $axis = shift;
660             my %arg = ( %{ $axis->{_defaults} }, @_ );
661 9         20  
662             my ( $name, $name_formula ) =
663             $self->_process_names( $arg{name}, $arg{name_formula} );
664              
665             my $data_id = $self->_get_data_id( $name_formula, $arg{data} );
666              
667             $axis = {
668             _defaults => $axis->{_defaults},
669             _name => $name,
670             _formula => $name_formula,
671             _data_id => $data_id,
672             _reverse => $arg{reverse},
673             _min => $arg{min},
674             _max => $arg{max},
675             _minor_unit => $arg{minor_unit},
676             _major_unit => $arg{major_unit},
677             _minor_unit_type => $arg{minor_unit_type},
678             _major_unit_type => $arg{major_unit_type},
679             _log_base => $arg{log_base},
680             _crossing => $arg{crossing},
681 2671     2671   3461 _position_axis => $arg{position_axis},
682 2671         3258 _position => $arg{position},
683 2671         3145 _label_position => $arg{label_position},
  2671         9728  
684             _label_align => $arg{label_align},
685             _num_format => $arg{num_format},
686 2671         8634 _num_format_linked => $arg{num_format_linked},
687             _interval_unit => $arg{interval_unit},
688 2671         7975 _interval_tick => $arg{interval_tick},
689             _visible => defined $arg{visible} ? $arg{visible} : 1,
690             _text_axis => 0,
691             };
692              
693             # Map major_gridlines properties.
694             if ( $arg{major_gridlines} && $arg{major_gridlines}->{visible} ) {
695             $axis->{_major_gridlines} =
696             $self->_get_gridline_properties( $arg{major_gridlines} );
697             }
698              
699             # Map minor_gridlines properties.
700             if ( $arg{minor_gridlines} && $arg{minor_gridlines}->{visible} ) {
701             $axis->{_minor_gridlines} =
702             $self->_get_gridline_properties( $arg{minor_gridlines} );
703             }
704              
705             # Convert the display units.
706             $axis->{_display_units} = $self->_get_display_units( $arg{display_units} );
707             if ( defined $arg{display_units_visible} ) {
708             $axis->{_display_units_visible} = $arg{display_units_visible};
709             }
710             else {
711             $axis->{_display_units_visible} = 1;
712 2671 100       26636 }
713              
714             # Only use the first letter of bottom, top, left or right.
715             if ( defined $axis->{_position} ) {
716             $axis->{_position} = substr lc $axis->{_position}, 0, 1;
717 2671 100 100     10070 }
718              
719 936         2909 # Set the position for a category axis on or between the tick marks.
720             if ( defined $axis->{_position_axis} ) {
721             if ( $axis->{_position_axis} eq 'on_tick' ) {
722             $axis->{_position_axis} = 'midCat';
723 2671 50 66     4936 }
724             elsif ( $axis->{_position_axis} eq 'between' ) {
725 9         24  
726             # Doesn't need to be modified.
727             }
728             else {
729 2671         6387 # Otherwise use the default value.
730 2671 100       5480 $axis->{_position_axis} = undef;
731 11         29 }
732             }
733              
734 2660         3736 # Set the category axis as a date axis.
735             if ( $arg{date_axis} ) {
736             $self->{_date_category} = 1;
737             }
738 2671 100       5000  
739 527         2019 # Set the category axis as a text axis.
740             if ( $arg{text_axis} ) {
741             $self->{_date_category} = 0;
742             $axis->{_text_axis} = 1;
743 2671 100       4649 }
744 3 100       12  
    50          
745 2         4  
746             # Set the font properties if present.
747             $axis->{_num_font} = $self->_convert_font_args( $arg{num_font} );
748             $axis->{_name_font} = $self->_convert_font_args( $arg{name_font} );
749              
750             # Set the axis name layout.
751             $axis->{_layout} = $self->_get_layout_properties( $arg{name_layout}, 1 );
752              
753 0         0 # Set the line properties for the axis.
754             $axis->{_line} = $self->_get_line_properties( $arg{line} );
755              
756             # Set the fill properties for the axis.
757             $axis->{_fill} = $self->_get_fill_properties( $arg{fill} );
758 2671 100       4515  
759 4         14 # Set the tick marker types.
760             $axis->{_minor_tick_mark} = $self->_get_tick_type($arg{minor_tick_mark});
761             $axis->{_major_tick_mark} = $self->_get_tick_type($arg{major_tick_mark});
762              
763 2671 100       4274  
764 1         1 return $axis;
765 1         2 }
766              
767              
768             ###############################################################################
769             #
770 2671         5857 # _convert_fonts_args()
771 2671         5748 #
772             # Convert user defined font values into private hash values.
773             #
774 2671         6661  
775             my $self = shift;
776             my $args = shift;
777 2671         6712  
778             return unless $args;
779              
780 2671         6594 my $font = {
781             _name => $args->{name},
782             _color => $args->{color},
783 2671         6760 _size => $args->{size},
784 2671         5924 _bold => $args->{bold},
785             _italic => $args->{italic},
786             _underline => $args->{underline},
787 2671         5962 _pitch_family => $args->{pitch_family},
788             _charset => $args->{charset},
789             _baseline => $args->{baseline} || 0,
790             _rotation => $args->{rotation},
791             };
792              
793             # Convert font size units.
794             $font->{_size} *= 100 if $font->{_size};
795              
796             # Convert rotation into 60,000ths of a degree.
797             if ( $font->{_rotation} ) {
798             $font->{_rotation} = 60_000 * int( $font->{_rotation} );
799 5411     5411   6286 }
800 5411         7111  
801             return $font;
802 5411 100       9668 }
803              
804              
805             ###############################################################################
806             #
807             # _aref_to_formula()
808             #
809             # Convert and aref of row col values to a range formula.
810             #
811              
812             my $self = shift;
813             my $data = shift;
814              
815 65   100     636 # If it isn't an array ref it is probably a formula already.
816             return $data if !ref $data;
817              
818 65 100       191 my $formula = xl_range_formula( @$data );
819              
820             return $formula;
821 65 100       182 }
822 21         54  
823              
824             ###############################################################################
825 65         127 #
826             # _process_names()
827             #
828             # Switch name and name_formula parameters if required.
829             #
830              
831             my $self = shift;
832             my $name = shift;
833             my $name_formula = shift;
834              
835             if ( defined $name ) {
836              
837 2074     2074   2727 if ( ref $name eq 'ARRAY' ) {
838 2074         2894 my $cell = xl_rowcol_to_cell( $name->[1], $name->[2], 1, 1 );
839             $name_formula = quote_sheetname( $name->[0] ) . '!' . $cell;
840             $name = '';
841 2074 100       4602 }
842             elsif ( $name =~ m/^=[^!]+!\$/ ) {
843 33         123  
844             # Name looks like a formula, use it to set name_formula.
845 33         60 $name_formula = $name;
846             $name = '';
847             }
848             }
849              
850             return ( $name, $name_formula );
851             }
852              
853              
854             ###############################################################################
855             #
856             # _get_data_type()
857 3732     3732   4997 #
858 3732         5729 # Find the overall type of the data associated with a series.
859 3732         5040 #
860             # TODO. Need to handle date type.
861 3732 100       6833 #
862              
863 85 100       418 my $self = shift;
    100          
864 1         4 my $data = shift;
865 1         4  
866 1         2 # Check for no data in the series.
867             return 'none' if !defined $data;
868             return 'none' if @$data == 0;
869              
870             if (ref $data->[0] eq 'ARRAY') {
871 20         35 return 'multi_str'
872 20         38 }
873              
874             # If the token isn't a number assume it is a string.
875             for my $token ( @$data ) {
876 3732         9683 next if !defined $token;
877             return 'str'
878             if $token !~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/;
879             }
880              
881             # The series data was all numeric.
882             return 'num';
883             }
884              
885              
886             ###############################################################################
887             #
888             # _get_data_id()
889             #
890 255     255   463 # Assign an id to a each unique series formula or title/axis formula. Repeated
891 255         412 # formulas such as for categories get the same id. If the series or title
892             # has user specified data associated with it then that is also stored. This
893             # data is used to populate cached Excel data when creating a chart.
894 255 50       650 # If there is no user defined data then it will be populated by the parent
895 255 50       745 # workbook in Workbook::_add_chart_data()
896             #
897 255 100       750  
898 3         6 my $self = shift;
899             my $formula = shift;
900             my $data = shift;
901             my $id;
902 252         569  
903 1220 100       1881 # Ignore series without a range formula.
904 1219 100       4482 return unless $formula;
905              
906             # Strip the leading '=' from the formula.
907             $formula =~ s/^=//;
908              
909 243         591 # Store the data id in a hash keyed by the formula and store the data
910             # in a separate array with the same id.
911             if ( !exists $self->{_formula_ids}->{$formula} ) {
912              
913             # Haven't seen this formula before.
914             $id = @{ $self->{_formula_data} };
915              
916             push @{ $self->{_formula_data} }, $data;
917             $self->{_formula_ids}->{$formula} = $id;
918             }
919             else {
920              
921             # Formula already seen. Return existing id.
922             $id = $self->{_formula_ids}->{$formula};
923              
924             # Store user defined data if it isn't already there.
925             if ( !defined $self->{_formula_data}->[$id] ) {
926 5813     5813   7232 $self->{_formula_data}->[$id] = $data;
927 5813         6582 }
928 5813         7383 }
929 5813         6003  
930             return $id;
931             }
932 5813 100       10310  
933              
934             ###############################################################################
935 1330         4859 #
936             # _get_color()
937             #
938             # Convert the user specified colour index or string to a rgb colour.
939 1330 100       4271 #
940              
941             my $self = shift;
942 1211         1650 my $color = shift;
  1211         2179  
943              
944 1211         1647 # Convert a HTML style #RRGGBB color.
  1211         2326  
945 1211         2512 if ( defined $color and $color =~ /^#[0-9a-fA-F]{6}$/ ) {
946             $color =~ s/^#//;
947             return uc $color;
948             }
949              
950 119         261 my $index = &Excel::Writer::XLSX::Format::_get_color( $color );
951              
952             # Set undefined colors to black.
953 119 100       470 if ( !$index ) {
954 114         266 $index = 0x08;
955             warn "Unknown color '$color' used in chart formatting. "
956             . "Converting to black.\n";
957             }
958 1330         2274  
959             return $self->_get_palette_color( $index );
960             }
961              
962              
963             ###############################################################################
964             #
965             # _get_palette_color()
966             #
967             # Convert from an Excel internal colour index to a XML style #RRGGBB index
968             # based on the default or user defined values in the Workbook palette.
969             # Note: This version doesn't add an alpha channel.
970 269     269   399 #
971 269         379  
972             my $self = shift;
973             my $index = shift;
974 269 100 66     1328 my $palette = $self->{_palette};
975 187         455  
976 187         412 # Adjust the colour index.
977             $index -= 8;
978              
979 82         342 # Palette is passed in from the Workbook class.
980             my @rgb = @{ $palette->[$index] };
981              
982 82 50       239 return sprintf "%02X%02X%02X", @rgb[0, 1, 2];
983 0         0 }
984 0         0  
985              
986             ###############################################################################
987             #
988 82         431 # _get_swe_line_pattern()
989             #
990             # Get the Spreadsheet::WriteExcel line pattern for backward compatibility.
991             #
992              
993             my $self = shift;
994             my $value = lc shift;
995             my $default = 'solid';
996             my $pattern;
997              
998             my %patterns = (
999             0 => 'solid',
1000             1 => 'dash',
1001             2 => 'dot',
1002 82     82   150 3 => 'dash_dot',
1003 82         128 4 => 'long_dash_dot_dot',
1004 82         186 5 => 'none',
1005             6 => 'solid',
1006             7 => 'solid',
1007 82         156 8 => 'solid',
1008             'solid' => 'solid',
1009             'dash' => 'dash',
1010 82         166 'dot' => 'dot',
  82         277  
1011             'dash-dot' => 'dash_dot',
1012 82         550 'dash-dot-dot' => 'long_dash_dot_dot',
1013             'none' => 'none',
1014             'dark-gray' => 'solid',
1015             'medium-gray' => 'solid',
1016             'light-gray' => 'solid',
1017             );
1018              
1019             if ( exists $patterns{$value} ) {
1020             $pattern = $patterns{$value};
1021             }
1022             else {
1023             $pattern = $default;
1024 2     2   3 }
1025 2         3  
1026 2         2 return $pattern;
1027 2         2 }
1028              
1029 2         22  
1030             ###############################################################################
1031             #
1032             # _get_swe_line_weight()
1033             #
1034             # Get the Spreadsheet::WriteExcel line weight for backward compatibility.
1035             #
1036              
1037             my $self = shift;
1038             my $value = lc shift;
1039             my $default = 1;
1040             my $weight;
1041              
1042             my %weights = (
1043             1 => 0.25,
1044             2 => 1,
1045             3 => 2,
1046             4 => 3,
1047             'hairline' => 0.25,
1048             'narrow' => 1,
1049             'medium' => 2,
1050 2 50       4 'wide' => 3,
1051 2         3 );
1052              
1053             if ( exists $weights{$value} ) {
1054 0         0 $weight = $weights{$value};
1055             }
1056             else {
1057 2         6 $weight = $default;
1058             }
1059              
1060             return $weight;
1061             }
1062              
1063              
1064             ###############################################################################
1065             #
1066             # _get_line_properties()
1067             #
1068             # Convert user defined line properties to the structure required internally.
1069 1     1   2 #
1070 1         2  
1071 1         1 my $self = shift;
1072 1         1 my $line = shift;
1073              
1074 1         6 return { _defined => 0 } unless $line;
1075              
1076             # Copy the user supplied properties.
1077             $line = { %$line };
1078              
1079             my %dash_types = (
1080             solid => 'solid',
1081             round_dot => 'sysDot',
1082             square_dot => 'sysDash',
1083             dash => 'dash',
1084             dash_dot => 'dashDot',
1085 1 50       2 long_dash => 'lgDash',
1086 1         2 long_dash_dot => 'lgDashDot',
1087             long_dash_dot_dot => 'lgDashDotDot',
1088             dot => 'dot',
1089 0         0 system_dash_dot => 'sysDashDot',
1090             system_dash_dot_dot => 'sysDashDotDot',
1091             );
1092 1         2  
1093             # Check the dash type.
1094             my $dash_type = $line->{dash_type};
1095              
1096             if ( defined $dash_type ) {
1097             if ( exists $dash_types{$dash_type} ) {
1098             $line->{dash_type} = $dash_types{$dash_type};
1099             }
1100             else {
1101             warn "Unknown dash type '$dash_type'\n";
1102             return;
1103             }
1104 4927     4927   6314 }
1105 4927         6533  
1106             $line->{_defined} = 1;
1107 4927 100       12334  
1108             return $line;
1109             }
1110 63         260  
1111              
1112 63         642 ###############################################################################
1113             #
1114             # _get_fill_properties()
1115             #
1116             # Convert user defined fill properties to the structure required internally.
1117             #
1118              
1119             my $self = shift;
1120             my $fill = shift;
1121              
1122             return { _defined => 0 } unless $fill;
1123              
1124             $fill->{_defined} = 1;
1125              
1126             return $fill;
1127 63         147 }
1128              
1129 63 100       188  
1130 28 50       160 ###############################################################################
1131 28         76 #
1132             # _get_pattern_properties()
1133             #
1134 0         0 # Convert user defined pattern properties to the structure required internally.
1135 0         0 #
1136              
1137             my $self = shift;
1138             my $args = shift;
1139 63         125 my $pattern = {};
1140              
1141 63         233 return unless $args;
1142              
1143             # Check the pattern type is present.
1144             if ( !$args->{pattern} ) {
1145             carp "Pattern must include 'pattern'";
1146             return;
1147             }
1148              
1149             # Check the foreground color is present.
1150             if ( !$args->{fg_color} ) {
1151             carp "Pattern must include 'fg_color'";
1152             return;
1153 3926     3926   4909 }
1154 3926         5389  
1155             my %types = (
1156 3926 100       9672 'percent_5' => 'pct5',
1157             'percent_10' => 'pct10',
1158 51         90 'percent_20' => 'pct20',
1159             'percent_25' => 'pct25',
1160 51         100 'percent_30' => 'pct30',
1161             'percent_40' => 'pct40',
1162              
1163             'percent_50' => 'pct50',
1164             'percent_60' => 'pct60',
1165             'percent_70' => 'pct70',
1166             'percent_75' => 'pct75',
1167             'percent_80' => 'pct80',
1168             'percent_90' => 'pct90',
1169              
1170             'light_downward_diagonal' => 'ltDnDiag',
1171             'light_upward_diagonal' => 'ltUpDiag',
1172 1249     1249   2242 'dark_downward_diagonal' => 'dkDnDiag',
1173 1249         2071 'dark_upward_diagonal' => 'dkUpDiag',
1174 1249         1928 'wide_downward_diagonal' => 'wdDnDiag',
1175             'wide_upward_diagonal' => 'wdUpDiag',
1176 1249 100       3270  
1177             'light_vertical' => 'ltVert',
1178             'light_horizontal' => 'ltHorz',
1179 59 50       111 'narrow_vertical' => 'narVert',
1180 0         0 'narrow_horizontal' => 'narHorz',
1181 0         0 'dark_vertical' => 'dkVert',
1182             'dark_horizontal' => 'dkHorz',
1183              
1184             'dashed_downward_diagonal' => 'dashDnDiag',
1185 59 50       117 'dashed_upward_diagonal' => 'dashUpDiag',
1186 0         0 'dashed_horizontal' => 'dashHorz',
1187 0         0 'dashed_vertical' => 'dashVert',
1188             'small_confetti' => 'smConfetti',
1189             'large_confetti' => 'lgConfetti',
1190 59         1118  
1191             'zigzag' => 'zigZag',
1192             'wave' => 'wave',
1193             'diagonal_brick' => 'diagBrick',
1194             'horizontal_brick' => 'horzBrick',
1195             'weave' => 'weave',
1196             'plaid' => 'plaid',
1197              
1198             'divot' => 'divot',
1199             'dotted_grid' => 'dotGrid',
1200             'dotted_diamond' => 'dotDmnd',
1201             'shingle' => 'shingle',
1202             'trellis' => 'trellis',
1203             'sphere' => 'sphere',
1204              
1205             'small_grid' => 'smGrid',
1206             'large_grid' => 'lgGrid',
1207             'small_check' => 'smCheck',
1208             'large_check' => 'lgCheck',
1209             'outlined_diamond' => 'openDmnd',
1210             'solid_diamond' => 'solidDmnd',
1211             );
1212              
1213             # Check for valid types.
1214             my $pattern_type = $args->{pattern};
1215              
1216             if ( exists $types{$pattern_type} ) {
1217             $pattern->{pattern} = $types{$pattern_type};
1218             }
1219             else {
1220             carp "Unknown pattern type '$pattern_type'";
1221             return;
1222             }
1223              
1224             # Specify a default background color.
1225             if ( !$args->{bg_color} ) {
1226             $pattern->{bg_color} = '#FFFFFF';
1227             }
1228             else {
1229             $pattern->{bg_color} = $args->{bg_color};
1230             }
1231              
1232             $pattern->{fg_color} = $args->{fg_color};
1233              
1234             return $pattern;
1235             }
1236              
1237              
1238             ###############################################################################
1239             #
1240             # _get_gradient_properties()
1241             #
1242             # Convert user defined gradient to the structure required internally.
1243             #
1244              
1245             my $self = shift;
1246             my $args = shift;
1247             my $gradient = {};
1248              
1249 59         92 my %types = (
1250             linear => 'linear',
1251 59 50       103 radial => 'circle',
1252 59         122 rectangular => 'rect',
1253             path => 'shape'
1254             );
1255 0         0  
1256 0         0 return unless $args;
1257              
1258             # Check the colors array exists and is valid.
1259             if ( !$args->{colors} || ref $args->{colors} ne 'ARRAY' ) {
1260 59 100       107 carp "Gradient must include colors array";
1261 50         69 return;
1262             }
1263              
1264 9         18 # Check the colors array has the required number of entries.
1265             if ( @{ $args->{colors} } < 2 ) {
1266             carp "Gradient colors array must at least 2 values";
1267 59         85 return;
1268             }
1269 59         291  
1270             $gradient->{_colors} = $args->{colors};
1271              
1272             if ( $args->{positions} ) {
1273              
1274             # Check the positions array has the right number of entries.
1275             if ( @{ $args->{positions} } != @{ $args->{colors} } ) {
1276             carp "Gradient positions not equal to number of colors";
1277             return;
1278             }
1279              
1280             # Check the positions are in the correct range.
1281 1249     1249   1888 for my $pos ( @{ $args->{positions} } ) {
1282 1249         1975 if ( $pos < 0 || $pos > 100 ) {
1283 1249         1831 carp "Gradient position '", $pos,
1284             "' must be in range 0 <= pos <= 100";
1285 1249         4852 return;
1286             }
1287             }
1288              
1289             $gradient->{_positions} = $args->{positions};
1290             }
1291             else {
1292 1249 100       3841 # Use the default gradient positions.
1293             if ( @{ $args->{colors} } == 2 ) {
1294             $gradient->{_positions} = [ 0, 100 ];
1295 14 50 33     102 }
1296 0         0 elsif ( @{ $args->{colors} } == 3 ) {
1297 0         0 $gradient->{_positions} = [ 0, 50, 100 ];
1298             }
1299             elsif ( @{ $args->{colors} } == 4 ) {
1300             $gradient->{_positions} = [ 0, 33, 66, 100 ];
1301 14 50       42 }
  14         80  
1302 0         0 else {
1303 0         0 carp "Must specify gradient positions";
1304             return;
1305             }
1306 14         65 }
1307              
1308 14 100       77 # Set the gradient angle.
1309             if ( defined $args->{angle} ) {
1310             my $angle = $args->{angle};
1311 2 50       6  
  2         6  
  2         9  
1312 0         0 if ( $angle < 0 || $angle > 359.9 ) {
1313 0         0 carp "Gradient angle '", $angle,
1314             "' must be in range 0 <= pos < 360";
1315             return;
1316             }
1317 2         3 $gradient->{_angle} = $angle;
  2         6  
1318 5 50 33     21 }
1319 0         0 else {
1320             $gradient->{_angle} = 90;
1321 0         0 }
1322              
1323             # Set the gradient type.
1324             if ( defined $args->{type} ) {
1325 2         7 my $type = $args->{type};
1326              
1327             if ( !exists $types{$type} ) {
1328             carp "Unknown gradient type '", $type, "'";
1329 12 100       29 return;
  12 100       69  
    50          
1330 1         3 }
1331             $gradient->{_type} = $types{$type};
1332 11         37 }
1333 10         45 else {
1334             $gradient->{_type} = 'linear';
1335 1         4 }
1336 1         3  
1337             return $gradient;
1338             }
1339 0         0  
1340 0         0  
1341             ###############################################################################
1342             #
1343             # _get_marker_properties()
1344             #
1345 14 100       44 # Convert user defined marker properties to the structure required internally.
1346 2         5 #
1347              
1348 2 50 33     15 my $self = shift;
1349 0         0 my $marker = shift;
1350              
1351 0         0 return if !$marker && ref $marker ne 'HASH';
1352              
1353 2         6 # Copy the user supplied properties.
1354             $marker = { %$marker };
1355              
1356 12         28 my %types = (
1357             automatic => 'automatic',
1358             none => 'none',
1359             square => 'square',
1360 14 100       41 diamond => 'diamond',
1361 3         6 triangle => 'triangle',
1362             x => 'x',
1363 3 50       9 star => 'star',
1364 0         0 dot => 'dot',
1365 0         0 short_dash => 'dot',
1366             dash => 'dash',
1367 3         8 long_dash => 'dash',
1368             circle => 'circle',
1369             plus => 'plus',
1370 11         33 picture => 'picture',
1371             );
1372              
1373 14         45 # Check for valid types.
1374             my $marker_type = $marker->{type};
1375              
1376             if ( defined $marker_type ) {
1377             if ( $marker_type eq 'automatic' ) {
1378             $marker->{automatic} = 1;
1379             }
1380              
1381             if ( exists $types{$marker_type} ) {
1382             $marker->{type} = $types{$marker_type};
1383             }
1384             else {
1385 1037     1037   1751 warn "Unknown marker type '$marker_type'\n";
1386 1037         1736 return;
1387             }
1388 1037 100 66     4499 }
1389              
1390             # Set the line properties for the marker..
1391 11         35 my $line = $self->_get_line_properties( $marker->{line} );
1392              
1393 11         139 # Allow 'border' as a synonym for 'line'.
1394             if ( $marker->{border} ) {
1395             $line = $self->_get_line_properties( $marker->{border} );
1396             }
1397              
1398             # Set the fill properties for the marker.
1399             my $fill = $self->_get_fill_properties( $marker->{fill} );
1400              
1401             # Set the pattern properties for the series.
1402             my $pattern = $self->_get_pattern_properties( $marker->{pattern} );
1403              
1404             # Set the gradient fill properties for the series.
1405             my $gradient = $self->_get_gradient_properties( $marker->{gradient} );
1406              
1407             # Pattern fill overrides solid fill.
1408             if ( $pattern ) {
1409             $fill = undef;
1410             }
1411 11         27  
1412             # Gradient fill overrides solid and pattern fills.
1413 11 50       34 if ( $gradient ) {
1414 11 100       34 $pattern = undef;
1415 6         19 $fill = undef;
1416             }
1417              
1418 11 50       28 $marker->{_line} = $line;
1419 11         27 $marker->{_fill} = $fill;
1420             $marker->{_pattern} = $pattern;
1421             $marker->{_gradient} = $gradient;
1422 0         0  
1423 0         0 return $marker;
1424             }
1425              
1426              
1427             ###############################################################################
1428 11         32 #
1429             # _get_trendline_properties()
1430             #
1431 11 50       42 # Convert user defined trendline properties to the structure required
1432 0         0 # internally.
1433             #
1434              
1435             my $self = shift;
1436 11         37 my $trendline = shift;
1437              
1438             return if !$trendline && ref $trendline ne 'HASH';
1439 11         42  
1440             # Copy the user supplied properties.
1441             $trendline = { %$trendline };
1442 11         33  
1443             my %types = (
1444             exponential => 'exp',
1445 11 50       44 linear => 'linear',
1446 0         0 log => 'log',
1447             moving_average => 'movingAvg',
1448             polynomial => 'poly',
1449             power => 'power',
1450 11 50       25 );
1451 0         0  
1452 0         0 # Check the trendline type.
1453             my $trend_type = $trendline->{type};
1454              
1455 11         22 if ( exists $types{$trend_type} ) {
1456 11         21 $trendline->{type} = $types{$trend_type};
1457 11         19 }
1458 11         18 else {
1459             warn "Unknown trendline type '$trend_type'\n";
1460 11         36 return;
1461             }
1462              
1463             # Set the line properties for the trendline..
1464             my $line = $self->_get_line_properties( $trendline->{line} );
1465              
1466             # Allow 'border' as a synonym for 'line'.
1467             if ( $trendline->{border} ) {
1468             $line = $self->_get_line_properties( $trendline->{border} );
1469             }
1470              
1471             # Set the fill properties for the trendline.
1472             my $fill = $self->_get_fill_properties( $trendline->{fill} );
1473 1037     1037   1693  
1474 1037         1718 # Set the pattern properties for the series.
1475             my $pattern = $self->_get_pattern_properties( $trendline->{pattern} );
1476 1037 100 66     3953  
1477             # Set the gradient fill properties for the series.
1478             my $gradient = $self->_get_gradient_properties( $trendline->{gradient} );
1479 13         62  
1480             # Pattern fill overrides solid fill.
1481 13         103 if ( $pattern ) {
1482             $fill = undef;
1483             }
1484              
1485             # Gradient fill overrides solid and pattern fills.
1486             if ( $gradient ) {
1487             $pattern = undef;
1488             $fill = undef;
1489             }
1490              
1491 13         34 $trendline->{_line} = $line;
1492             $trendline->{_fill} = $fill;
1493 13 50       39 $trendline->{_pattern} = $pattern;
1494 13         39 $trendline->{_gradient} = $gradient;
1495              
1496             return $trendline;
1497 0         0 }
1498 0         0  
1499              
1500             ###############################################################################
1501             #
1502 13         46 # _get_error_bars_properties()
1503             #
1504             # Convert user defined error bars properties to structure required internally.
1505 13 50       42 #
1506 0         0  
1507             my $self = shift;
1508             my $args = shift;
1509              
1510 13         39 return if !$args && ref $args ne 'HASH';
1511              
1512             # Copy the user supplied properties.
1513 13         44 $args = { %$args };
1514              
1515              
1516 13         41 # Default values.
1517             my $error_bars = {
1518             _type => 'fixedVal',
1519 13 50       36 _value => 1,
1520 0         0 _endcap => 1,
1521             _direction => 'both',
1522             _plus_values => [1],
1523             _minus_values => [1],
1524 13 50       40 _plus_data => [],
1525 0         0 _minus_data => [],
1526 0         0 };
1527              
1528             my %types = (
1529 13         29 fixed => 'fixedVal',
1530 13         33 percentage => 'percentage',
1531 13         27 standard_deviation => 'stdDev',
1532 13         26 standard_error => 'stdErr',
1533             custom => 'cust',
1534 13         36 );
1535              
1536             # Check the error bars type.
1537             my $error_type = $args->{type};
1538              
1539             if ( exists $types{$error_type} ) {
1540             $error_bars->{_type} = $types{$error_type};
1541             }
1542             else {
1543             warn "Unknown error bars type '$error_type'\n";
1544             return;
1545             }
1546 2074     2074   2903  
1547 2074         2978 # Set the value for error types that require it.
1548             if ( defined $args->{value} ) {
1549 2074 100 66     6420 $error_bars->{_value} = $args->{value};
1550             }
1551              
1552 14         50 # Set the end-cap style.
1553             if ( defined $args->{end_style} ) {
1554             $error_bars->{_endcap} = $args->{end_style};
1555             }
1556 14         122  
1557             # Set the error bar direction.
1558             if ( defined $args->{direction} ) {
1559             if ( $args->{direction} eq 'minus' ) {
1560             $error_bars->{_direction} = 'minus';
1561             }
1562             elsif ( $args->{direction} eq 'plus' ) {
1563             $error_bars->{_direction} = 'plus';
1564             }
1565             else {
1566             # Default to 'both'.
1567 14         82 }
1568             }
1569              
1570             # Set any custom values.
1571             if ( defined $args->{plus_values} ) {
1572             $error_bars->{_plus_values} = $args->{plus_values};
1573             }
1574             if ( defined $args->{minus_values} ) {
1575             $error_bars->{_minus_values} = $args->{minus_values};
1576 14         29 }
1577             if ( defined $args->{plus_data} ) {
1578 14 50       45 $error_bars->{_plus_data} = $args->{plus_data};
1579 14         31 }
1580             if ( defined $args->{minus_data} ) {
1581             $error_bars->{_minus_data} = $args->{minus_data};
1582 0         0 }
1583 0         0  
1584             # Set the line properties for the error bars.
1585             $error_bars->{_line} = $self->_get_line_properties( $args->{line} );
1586              
1587 14 100       37 return $error_bars;
1588 3         5 }
1589              
1590              
1591             ###############################################################################
1592 14 100       38 #
1593 1         3 # _get_gridline_properties()
1594             #
1595             # Convert user defined gridline properties to the structure required internally.
1596             #
1597 14 100       33  
1598 2 100       7 my $self = shift;
    50          
1599 1         3 my $args = shift;
1600             my $gridline;
1601              
1602 1         2 # Set the visible property for the gridline.
1603             $gridline->{_visible} = $args->{visible};
1604              
1605             # Set the line properties for the gridline..
1606             $gridline->{_line} = $self->_get_line_properties( $args->{line} );
1607              
1608             return $gridline;
1609             }
1610 14 100       36  
1611 3         7  
1612             ###############################################################################
1613 14 100       31 #
1614 3         13 # _get_labels_properties()
1615             #
1616 14 100       39 # Convert user defined labels properties to the structure required internally.
1617 1         2 #
1618              
1619 14 100       38 my $self = shift;
1620 1         1 my $labels = shift;
1621              
1622             return if !$labels && ref $labels ne 'HASH';
1623              
1624 14         46 # Copy the user supplied properties.
1625             $labels = { %$labels };
1626 14         48  
1627             # Map user defined label positions to Excel positions.
1628             if ( my $position = $labels->{position} ) {
1629              
1630             if ( exists $self->{_label_positions}->{$position} ) {
1631             if ($position eq $self->{_label_position_default}) {
1632             $labels->{position} = undef;
1633             }
1634             else {
1635             $labels->{position} = $self->{_label_positions}->{$position};
1636             }
1637             }
1638 945     945   1591 else {
1639 945         1356 carp "Unsupported label position '$position' for this chart type";
1640 945         1301 return undef
1641             }
1642             }
1643 945         2087  
1644             # Map the user defined label separator to the Excel separator.
1645             if ( my $separator = $labels->{separator} ) {
1646 945         2585  
1647             my %separators = (
1648 945         2200 ',' => ', ',
1649             ';' => '; ',
1650             '.' => '. ',
1651             "\n" => "\n",
1652             ' ' => ' '
1653             );
1654              
1655             if ( exists $separators{$separator} ) {
1656             $labels->{separator} = $separators{$separator};
1657             }
1658             else {
1659             carp "Unsupported label separator";
1660 1055     1055   2125 return undef
1661 1055         1614 }
1662             }
1663 1055 100 66     4195  
1664             # Set the line properties for the data labels.
1665             my $line = $self->_get_line_properties( $labels->{line} );
1666 92         351  
1667             # Allow 'border' as a synonym for 'line'.
1668             if ( $labels->{border} ) {
1669 92 100       346 $line = $self->_get_line_properties( $labels->{border} );
1670             }
1671 52 50       162  
1672 52 100       149 # Set the fill properties for the labels.
1673 13         36 my $fill = $self->_get_fill_properties( $labels->{fill} );
1674              
1675             # Set the pattern properties for the labels.
1676 39         101 my $pattern = $self->_get_pattern_properties( $labels->{pattern} );
1677              
1678             # Set the gradient fill properties for the labels.
1679             my $gradient = $self->_get_gradient_properties( $labels->{gradient} );
1680 0         0  
1681             # Pattern fill overrides solid fill.
1682 0         0 if ( $pattern ) {
1683             $fill = undef;
1684             }
1685              
1686 92 100       273 # Gradient fill overrides solid and pattern fills.
1687             if ( $gradient ) {
1688 6         48 $pattern = undef;
1689             $fill = undef;
1690             }
1691              
1692             $labels->{_line} = $line;
1693             $labels->{_fill} = $fill;
1694             $labels->{_pattern} = $pattern;
1695             $labels->{_gradient} = $gradient;
1696 6 50       18  
1697 6         16  
1698             if ($labels->{font}) {
1699             $labels->{font} = $self->_convert_font_args( $labels->{font} );
1700 0         0 }
1701              
1702 0         0 if ( $labels->{custom} ) {
1703              
1704             # Duplicate, and modify, the custom label properties.
1705             my @custom = ();
1706 92         281  
1707             for my $label ( @{ $labels->{custom} } ) {
1708             if (! defined $label) {
1709 92 100       288 push @custom, undef;
1710 5         17 next;
1711             }
1712              
1713             my %property = %{$label};
1714 92         264  
1715             # Convert formula.
1716             if ( $property{value} && $property{value} =~ m/^=[^!]+!\$/) {
1717 92         315 $property{formula} = $property{value};
1718             }
1719              
1720 92         300 if ( $property{formula} ) {
1721             $property{formula} =~ s/^=//;
1722              
1723 92 100       264 my $data_id = $self->_get_data_id( $property{formula},
1724 1         3 $property{data} );
1725             $property{data_id} = $data_id;
1726             }
1727              
1728 92 100       254 if ($property{font}) {
1729 1         2 $property{font} = $self->_convert_font_args( $property{font} );
1730 1         2 }
1731              
1732             # Set the line properties for the data labels.
1733 92         239 my $line = $self->_get_line_properties( $property{line} );
1734 92         230  
1735 92         184 # Allow 'border' as a synonym for 'line'.
1736 92         244 if ( $property{border} ) {
1737             $line = $self->_get_line_properties( $property{border} );
1738             }
1739 92 100       259  
1740 6         38 # Set the fill properties for the labels.
1741             my $fill = $self->_get_fill_properties( $property{fill} );
1742              
1743 92 100       265 # Set the pattern properties for the labels.
1744             my $pattern = $self->_get_pattern_properties( $property{pattern} );
1745              
1746 22         50 # Set the gradient fill properties for the labels.
1747             my $gradient = $self->_get_gradient_properties( $property{gradient} );
1748 22         33  
  22         59  
1749 30 100       79 # Pattern fill overrides solid fill.
1750 3         4 if ( $pattern ) {
1751 3         5 $fill = undef;
1752             }
1753              
1754 27         44 # Gradient fill overrides solid and pattern fills.
  27         107  
1755             if ( $gradient ) {
1756             $pattern = undef;
1757 27 100 100     166 $fill = undef;
1758 8         31 }
1759              
1760             $property{_line} = $line;
1761 27 100       76 $property{_fill} = $fill;
1762 10         33 $property{_pattern} = $pattern;
1763             $property{_gradient} = $gradient;
1764              
1765 10         37 push @custom, \%property;
1766 10         23 }
1767              
1768             $labels->{custom} = \@custom;
1769 27 100       76 }
1770 8         51  
1771             return $labels;
1772             }
1773              
1774 27         114  
1775             ###############################################################################
1776             #
1777 27 100       157 # _get_area_properties()
1778 9         28 #
1779             # Convert user defined area properties to the structure required internally.
1780             #
1781              
1782 27         89 my $self = shift;
1783             my %arg = @_;
1784             my $area = {};
1785 27         78  
1786              
1787             # Map deprecated Spreadsheet::WriteExcel fill colour.
1788 27         72 if ( $arg{color} ) {
1789             $arg{fill}->{color} = $arg{color};
1790             }
1791 27 50       88  
1792 0         0 # Map deprecated Spreadsheet::WriteExcel line_weight.
1793             if ( $arg{line_weight} ) {
1794             my $width = $self->_get_swe_line_weight( $arg{line_weight} );
1795             $arg{border}->{width} = $width;
1796 27 50       60 }
1797 0         0  
1798 0         0 # Map deprecated Spreadsheet::WriteExcel line_pattern.
1799             if ( $arg{line_pattern} ) {
1800             my $pattern = $self->_get_swe_line_pattern( $arg{line_pattern} );
1801 27         63  
1802 27         43 if ( $pattern eq 'none' ) {
1803 27         87 $arg{border}->{none} = 1;
1804 27         50 }
1805             else {
1806 27         75 $arg{border}->{dash_type} = $pattern;
1807             }
1808             }
1809 22         62  
1810             # Map deprecated Spreadsheet::WriteExcel line colour.
1811             if ( $arg{line_color} ) {
1812 92         232 $arg{border}->{color} = $arg{line_color};
1813             }
1814              
1815              
1816             # Handle Excel::Writer::XLSX style properties.
1817              
1818             # Set the line properties for the chartarea.
1819             my $line = $self->_get_line_properties( $arg{line} );
1820              
1821             # Allow 'border' as a synonym for 'line'.
1822             if ( $arg{border} ) {
1823             $line = $self->_get_line_properties( $arg{border} );
1824 20     20   44 }
1825 20         57  
1826 20         32 # Set the fill properties for the chartarea.
1827             my $fill = $self->_get_fill_properties( $arg{fill} );
1828              
1829             # Set the pattern properties for the series.
1830 20 100       75 my $pattern = $self->_get_pattern_properties( $arg{pattern} );
1831 2         5  
1832             # Set the gradient fill properties for the series.
1833             my $gradient = $self->_get_gradient_properties( $arg{gradient} );
1834              
1835 20 100       66 # Pattern fill overrides solid fill.
1836 1         4 if ( $pattern ) {
1837 1         2 $fill = undef;
1838             }
1839              
1840             # Gradient fill overrides solid and pattern fills.
1841 20 100       57 if ( $gradient ) {
1842 2         7 $pattern = undef;
1843             $fill = undef;
1844 2 100       4 }
1845 1         2  
1846             # Set the plotarea layout.
1847             my $layout = $self->_get_layout_properties( $arg{layout} );
1848 1         2  
1849             $area->{_line} = $line;
1850             $area->{_fill} = $fill;
1851             $area->{_pattern} = $pattern;
1852             $area->{_gradient} = $gradient;
1853 20 100       93 $area->{_layout} = $layout;
1854 1         2  
1855             return $area;
1856             }
1857              
1858              
1859             ###############################################################################
1860             #
1861 20         68 # _get_legend_properties()
1862             #
1863             # Convert user defined legend properties to the structure required internally.
1864 20 100       61 #
1865 13         31  
1866             my $self = shift;
1867             my %arg = @_;
1868             my $legend = {};
1869 20         61  
1870             $legend->{_position} = $arg{position} || 'right';
1871             $legend->{_delete_series} = $arg{delete_series};
1872 20         55 $legend->{_font} = $self->_convert_font_args( $arg{font} );
1873              
1874             # Set the legend layout.
1875 20         65 $legend->{_layout} = $self->_get_layout_properties( $arg{layout} );
1876              
1877             # Turn off the legend.
1878 20 100       74 if ( $arg{none} ) {
1879 2         11 $legend->{_position} = 'none';
1880             }
1881              
1882             # Set the line properties for the legend.
1883 20 100       91 my $line = $self->_get_line_properties( $arg{line} );
1884 2         4  
1885 2         4 # Allow 'border' as a synonym for 'line'.
1886             if ( $arg{border} ) {
1887             $line = $self->_get_line_properties( $arg{border} );
1888             }
1889 20         96  
1890             # Set the fill properties for the legend.
1891 20         79 my $fill = $self->_get_fill_properties( $arg{fill} );
1892 20         35  
1893 20         35 # Set the pattern properties for the legend.
1894 20         33 my $pattern = $self->_get_pattern_properties( $arg{pattern} );
1895 20         33  
1896             # Set the gradient fill properties for the legend.
1897 20         65 my $gradient = $self->_get_gradient_properties( $arg{gradient} );
1898              
1899             # Pattern fill overrides solid fill.
1900             if ( $pattern ) {
1901             $fill = undef;
1902             }
1903              
1904             # Gradient fill overrides solid and pattern fills.
1905             if ( $gradient ) {
1906             $pattern = undef;
1907             $fill = undef;
1908             }
1909 31     31   56  
1910 31         81 # Set the legend layout.
1911 31         54 my $layout = $self->_get_layout_properties( $arg{layout} );
1912              
1913 31   100     156 $legend->{_line} = $line;
1914 31         96 $legend->{_fill} = $fill;
1915 31         133 $legend->{_pattern} = $pattern;
1916             $legend->{_gradient} = $gradient;
1917             $legend->{_layout} = $layout;
1918 31         125  
1919             return $legend;
1920             }
1921 31 100       105  
1922 2         5  
1923             ###############################################################################
1924             #
1925             # _get_layout_properties()
1926 31         101 #
1927             # Convert user defined layout properties to the format required internally.
1928             #
1929 31 100       91  
1930 1         2 my $self = shift;
1931             my $args = shift;
1932             my $is_text = shift;
1933             my $layout = {};
1934 31         87 my @properties;
1935             my %allowable;
1936              
1937 31         153 return if !$args;
1938              
1939             if ( $is_text ) {
1940 31         90 @properties = ( 'x', 'y' );
1941             }
1942             else {
1943 31 50       91 @properties = ( 'x', 'y', 'width', 'height' );
1944 0         0 }
1945              
1946             # Check for valid properties.
1947             @allowable{@properties} = undef;
1948 31 50       114  
1949 0         0 for my $key ( keys %$args ) {
1950 0         0  
1951             if ( !exists $allowable{$key} ) {
1952             warn "Property '$key' not allowed in layout options\n";
1953             return;
1954 31         102 }
1955             }
1956 31         63  
1957 31         60 # Set the layout properties.
1958 31         57 for my $property ( @properties ) {
1959 31         76  
1960 31         49 if ( !exists $args->{$property} ) {
1961             warn "Property '$property' must be specified in layout options\n";
1962 31         100 return;
1963             }
1964              
1965             my $value = $args->{$property};
1966              
1967             if ( $value !~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/ ) {
1968             warn "Property '$property' value '$value' must be numeric"
1969             . " in layout options\n";
1970             return;
1971             }
1972              
1973             if ( $value < 0 || $value > 1 ) {
1974 2774     2774   3547 warn "Property '$property' value '$value' must be in range "
1975 2774         3854 . "0 < x <= 1 in layout options\n";
1976 2774         3313 return;
1977 2774         3852 }
1978 2774         3877  
1979             # Convert to the format used by Excel for easier testing
1980             $layout->{$property} = sprintf "%.17g", $value;
1981 2774 100       6788 }
1982              
1983 11 100       30 return $layout;
1984 6         22 }
1985              
1986              
1987 5         13 ###############################################################################
1988             #
1989             # _get_points_properties()
1990             #
1991 11         35 # Convert user defined points properties to structure required internally.
1992             #
1993 11         39  
1994             my $self = shift;
1995 32 50       66 my $user_points = shift;
1996 0         0 my @points;
1997 0         0  
1998             return unless $user_points;
1999              
2000             for my $user_point ( @$user_points ) {
2001              
2002 11         27 my $point;
2003              
2004 32 50       73 if ( defined $user_point ) {
2005 0         0  
2006 0         0 # Set the line properties for the point.
2007             my $line = $self->_get_line_properties( $user_point->{line} );
2008              
2009 32         49 # Allow 'border' as a synonym for 'line'.
2010             if ( $user_point->{border} ) {
2011 32 50       218 $line = $self->_get_line_properties( $user_point->{border} );
2012 0         0 }
2013              
2014 0         0 # Set the fill properties for the chartarea.
2015             my $fill = $self->_get_fill_properties( $user_point->{fill} );
2016              
2017 32 50 33     130  
2018 0         0 # Set the pattern properties for the series.
2019             my $pattern =
2020 0         0 $self->_get_pattern_properties( $user_point->{pattern} );
2021              
2022             # Set the gradient fill properties for the series.
2023             my $gradient =
2024 32         133 $self->_get_gradient_properties( $user_point->{gradient} );
2025              
2026             # Pattern fill overrides solid fill.
2027 11         42 if ( $pattern ) {
2028             $fill = undef;
2029             }
2030              
2031             # Gradient fill overrides solid and pattern fills.
2032             if ( $gradient ) {
2033             $pattern = undef;
2034             $fill = undef;
2035             }
2036             # Gradient fill overrides solid fill.
2037             if ( $gradient ) {
2038             $fill = undef;
2039 1037     1037   1573 }
2040 1037         1641  
2041 1037         1583 $point->{_line} = $line;
2042             $point->{_fill} = $fill;
2043 1037 100       2392 $point->{_pattern} = $pattern;
2044             $point->{_gradient} = $gradient;
2045 9         29 }
2046              
2047 22         31 push @points, $point;
2048             }
2049 22 100       41  
2050             return \@points;
2051             }
2052 18         49  
2053             ##############################################################################
2054             #
2055 18 100       52 # _has_fill_formatting()
2056 1         3 #
2057             # Check if a chart element has line, fill or gradient formatting.
2058             #
2059              
2060 18         36 my $element = shift;
2061              
2062             if ( !$element->{_line}->{_defined}
2063             and !$element->{_fill}->{_defined}
2064             and !$element->{_pattern}
2065 18         58 and !$element->{_gradient} )
2066             {
2067             return 0;
2068             }
2069 18         129 else {
2070             return 1;
2071             }
2072 18 50       51 }
2073 0         0  
2074              
2075             ###############################################################################
2076             #
2077 18 50       33 # _get_display_units()
2078 0         0 #
2079 0         0 # Convert user defined display units to internal units.
2080             #
2081              
2082 18 50       38 my $self = shift;
2083 0         0 my $display_units = shift;
2084              
2085             return if !$display_units;
2086 18         34  
2087 18         33 my %types = (
2088 18         30 'hundreds' => 'hundreds',
2089 18         29 'thousands' => 'thousands',
2090             'ten_thousands' => 'tenThousands',
2091             'hundred_thousands' => 'hundredThousands',
2092 22         40 'millions' => 'millions',
2093             'ten_millions' => 'tenMillions',
2094             'hundred_millions' => 'hundredMillions',
2095 9         44 'billions' => 'billions',
2096             'trillions' => 'trillions',
2097             );
2098              
2099             if ( exists $types{$display_units} ) {
2100             $display_units = $types{$display_units};
2101             }
2102             else {
2103             warn "Unknown display_units type '$display_units'\n";
2104             return;
2105             }
2106 3541     3541   4320  
2107             return $display_units;
2108 3541 100 100     22427 }
2109              
2110              
2111              
2112             ###############################################################################
2113 3293         7995 #
2114             # _get_tick_type()
2115             #
2116 248         628 # Convert user tick types to internal units.
2117             #
2118              
2119             my $self = shift;
2120             my $tick_type = shift;
2121              
2122             return if !$tick_type;
2123              
2124             my %types = (
2125             'outside' => 'out',
2126             'inside' => 'in',
2127             'none' => 'none',
2128             'cross' => 'cross',
2129 2671     2671   3529 );
2130 2671         3768  
2131             if ( exists $types{$tick_type} ) {
2132 2671 100       5452 $tick_type = $types{$tick_type};
2133             }
2134 12         88 else {
2135             warn "Unknown tick_type type '$tick_type'\n";
2136             return;
2137             }
2138              
2139             return $tick_type;
2140             }
2141              
2142              
2143             ###############################################################################
2144             #
2145             # _get_primary_axes_series()
2146 12 50       39 #
2147 12         29 # Returns series which use the primary axes.
2148             #
2149              
2150 0         0 my $self = shift;
2151 0         0 my @primary_axes_series;
2152              
2153             for my $series ( @{ $self->{_series} } ) {
2154 12         37 push @primary_axes_series, $series unless $series->{_y2_axis};
2155             }
2156              
2157             return @primary_axes_series;
2158             }
2159              
2160              
2161             ###############################################################################
2162             #
2163             # _get_secondary_axes_series()
2164             #
2165             # Returns series which use the secondary axes.
2166             #
2167 5342     5342   6232  
2168 5342         6791 my $self = shift;
2169             my @secondary_axes_series;
2170 5342 100       13715  
2171             for my $series ( @{ $self->{_series} } ) {
2172 5         21 push @secondary_axes_series, $series if $series->{_y2_axis};
2173             }
2174              
2175             return @secondary_axes_series;
2176             }
2177              
2178              
2179 5 50       15 ###############################################################################
2180 5         9 #
2181             # _add_axis_ids()
2182             #
2183 0         0 # Add unique ids for primary or secondary axes
2184 0         0 #
2185              
2186             my $self = shift;
2187 5         23 my %args = @_;
2188             my $chart_id = 5001 + $self->{_id};
2189             my $axis_count = 1 + @{ $self->{_axis2_ids} } + @{ $self->{_axis_ids} };
2190              
2191             my $id1 = sprintf '%04d%04d', $chart_id, $axis_count;
2192             my $id2 = sprintf '%04d%04d', $chart_id, $axis_count + 1;
2193              
2194             push @{ $self->{_axis_ids} }, $id1, $id2 if $args{primary_axes};
2195             push @{ $self->{_axis2_ids} }, $id1, $id2 if !$args{primary_axes};
2196             }
2197              
2198              
2199 377     377   811 ##############################################################################
2200 377         659 #
2201             # _get_font_style_attributes.
2202 377         751 #
  377         1276  
2203 971 100       2977 # Get the font style attributes from a font hashref.
2204             #
2205              
2206 377         1312 my $self = shift;
2207             my $font = shift;
2208              
2209             return () unless $font;
2210              
2211             my @attributes;
2212             push @attributes, ( 'sz' => $font->{_size} ) if $font->{_size};
2213             push @attributes, ( 'b' => $font->{_bold} ) if defined $font->{_bold};
2214             push @attributes, ( 'i' => $font->{_italic} ) if defined $font->{_italic};
2215             push @attributes, ( 'u' => 'sng' ) if defined $font->{_underline};
2216              
2217             # Turn off baseline when testing fonts that don't have it.
2218 377     377   903 if ($font->{_baseline} != -1) {
2219 377         762 push @attributes, ( 'baseline' => $font->{_baseline} );
2220             }
2221 377         732  
  377         1265  
2222 971 100       2650 return @attributes;
2223             }
2224              
2225 377         1180  
2226             ##############################################################################
2227             #
2228             # _get_font_latin_attributes.
2229             #
2230             # Get the font latin attributes from a font hashref.
2231             #
2232              
2233             my $self = shift;
2234             my $font = shift;
2235              
2236             return () unless $font;
2237 385     385   877  
2238 385         1088 my @attributes;
2239 385         1055 push @attributes, ( 'typeface' => $font->{_name} ) if $font->{_name};
2240 385         757  
  385         1021  
  385         979  
2241             push @attributes, ( 'pitchFamily' => $font->{_pitch_family} )
2242 385         2299 if defined $font->{_pitch_family};
2243 385         1339  
2244             push @attributes, ( 'charset' => $font->{_charset} )
2245 385 100       1502 if defined $font->{_charset};
  373         1440  
2246 385 100       1806  
  12         48  
2247             return @attributes;
2248             }
2249              
2250              
2251             ###############################################################################
2252             #
2253             # Config data.
2254             #
2255             ###############################################################################
2256              
2257             ###############################################################################
2258 233     233   367 #
2259 233         317 # _set_default_properties()
2260             #
2261 233 100       686 # Setup the default properties for a chart.
2262             #
2263 85         119  
2264 85 100       231 my $self = shift;
2265 85 100       232  
2266 85 100       218 # Set the default axis properties.
2267 85 100       239 $self->{_x_axis}->{_defaults} = {
2268             num_format => 'General',
2269             major_gridlines => { visible => 0 }
2270 85 100       207 };
2271 32         67  
2272             $self->{_y_axis}->{_defaults} = {
2273             num_format => 'General',
2274 85         214 major_gridlines => { visible => 1 }
2275             };
2276              
2277             $self->{_x2_axis}->{_defaults} = {
2278             num_format => 'General',
2279             label_position => 'none',
2280             crossing => 'max',
2281             visible => 0
2282             };
2283              
2284             $self->{_y2_axis}->{_defaults} = {
2285             num_format => 'General',
2286 233     233   385 major_gridlines => { visible => 0 },
2287 233         323 position => 'right',
2288             visible => 1
2289 233 100       592 };
2290              
2291 85         111 $self->set_x_axis();
2292 85 100       229 $self->set_y_axis();
2293              
2294             $self->set_x2_axis();
2295 85 100       222 $self->set_y2_axis();
2296             }
2297              
2298 85 100       213  
2299             ###############################################################################
2300 85         196 #
2301             # _set_embedded_config_data()
2302             #
2303             # Setup the default configuration data for an embedded chart.
2304             #
2305              
2306             my $self = shift;
2307              
2308             $self->{_embedded} = 1;
2309             }
2310              
2311              
2312             ###############################################################################
2313             #
2314             # XML writing methods.
2315             #
2316             ###############################################################################
2317              
2318 523     523   975  
2319             ##############################################################################
2320             #
2321             # _write_chart_space()
2322 523         4408 #
2323             # Write the <c:chartSpace> element.
2324             #
2325              
2326             my $self = shift;
2327 523         2144 my $schema = 'http://schemas.openxmlformats.org/';
2328             my $xmlns_c = $schema . 'drawingml/2006/chart';
2329             my $xmlns_a = $schema . 'drawingml/2006/main';
2330             my $xmlns_r = $schema . 'officeDocument/2006/relationships';
2331              
2332 523         2173 my @attributes = (
2333             'xmlns:c' => $xmlns_c,
2334             'xmlns:a' => $xmlns_a,
2335             'xmlns:r' => $xmlns_r,
2336             );
2337              
2338             $self->xml_start_tag( 'c:chartSpace', @attributes );
2339 523         2141 }
2340              
2341              
2342             ##############################################################################
2343             #
2344             # _write_lang()
2345 523         1907 #
2346 523         1767 # Write the <c:lang> element.
2347             #
2348 523         1720  
2349 523         1633 my $self = shift;
2350             my $val = 'en-US';
2351              
2352             my @attributes = ( 'val' => $val );
2353              
2354             $self->xml_empty_tag( 'c:lang', @attributes );
2355             }
2356              
2357              
2358             ##############################################################################
2359             #
2360             # _write_style()
2361 417     417   840 #
2362             # Write the <c:style> element.
2363 417         1088 #
2364              
2365             my $self = shift;
2366             my $style_id = $self->{_style_id};
2367              
2368             # Don't write an element for the default style, 2.
2369             return if $style_id == 2;
2370              
2371             my @attributes = ( 'val' => $style_id );
2372              
2373             $self->xml_empty_tag( 'c:style', @attributes );
2374             }
2375              
2376              
2377             ##############################################################################
2378             #
2379             # _write_chart()
2380             #
2381             # Write the <c:chart> element.
2382 427     427   854 #
2383 427         870  
2384 427         1286 my $self = shift;
2385 427         999  
2386 427         921 $self->xml_start_tag( 'c:chart' );
2387              
2388 427         1415 # Write the chart title elements.
2389              
2390             if ( $self->{_title_none} ) {
2391              
2392             # Turn off the title.
2393             $self->_write_auto_title_deleted();
2394 427         2335 }
2395             else {
2396             my $title;
2397             if ( $title = $self->{_title_formula} ) {
2398             $self->_write_title_formula(
2399              
2400             $title,
2401             $self->{_title_data_id},
2402             undef,
2403             $self->{_title_font},
2404             $self->{_title_layout},
2405             $self->{_title_overlay}
2406 427     427   929 );
2407 427         753 }
2408             elsif ( $title = $self->{_title_name} ) {
2409 427         1067 $self->_write_title_rich(
2410              
2411 427         2145 $title,
2412             undef,
2413             $self->{_title_font},
2414             $self->{_title_layout},
2415             $self->{_title_overlay}
2416             );
2417             }
2418             }
2419              
2420             # Write the c:plotArea element.
2421             $self->_write_plot_area();
2422              
2423 430     430   865 # Write the c:legend element.
2424 430         974 $self->_write_legend();
2425              
2426             # Write the c:plotVisOnly element.
2427 430 100       1698 $self->_write_plot_vis_only();
2428              
2429 3         8 # Write the c:dispBlanksAs element.
2430             $self->_write_disp_blanks_as();
2431 3         13  
2432             $self->xml_end_tag( 'c:chart' );
2433             }
2434              
2435              
2436             ##############################################################################
2437             #
2438             # _write_disp_blanks_as()
2439             #
2440             # Write the <c:dispBlanksAs> element.
2441             #
2442              
2443 426     426   864 my $self = shift;
2444             my $val = $self->{_show_blanks};
2445 426         1627  
2446             # Ignore the default value.
2447             return if $val eq 'gap';
2448              
2449 426 100       1611 my @attributes = ( 'val' => $val );
2450              
2451             $self->xml_empty_tag( 'c:dispBlanksAs', @attributes );
2452 1         4 }
2453              
2454              
2455 425         849 ##############################################################################
2456 425 100       2413 #
    100          
2457             # _write_plot_area()
2458             #
2459             # Write the <c:plotArea> element.
2460             #
2461              
2462             my $self = shift;
2463             my $second_chart = $self->{_combined};
2464              
2465 5         39 $self->xml_start_tag( 'c:plotArea' );
2466              
2467             # Write the c:layout element.
2468             $self->_write_layout( $self->{_plotarea}->{_layout}, 'plot' );
2469              
2470             # Write the subclass chart type elements for primary and secondary axes.
2471             $self->_write_chart_type( primary_axes => 1 );
2472             $self->_write_chart_type( primary_axes => 0 );
2473              
2474              
2475 15         112 # Configure a combined chart if present.
2476             if ( $second_chart ) {
2477              
2478             # Secondary axis has unique id otherwise use same as primary.
2479             if ( $second_chart->{_is_secondary} ) {
2480 426         2554 $second_chart->{_id} = 1000 + $self->{_id};
2481             }
2482             else {
2483 426         2579 $second_chart->{_id} = $self->{_id};
2484             }
2485              
2486 426         2915 # Shart the same filehandle for writing.
2487             $second_chart->{_fh} = $self->{_fh};
2488              
2489 426         2625 # Share series index with primary chart.
2490             $second_chart->{_series_index} = $self->{_series_index};
2491 426         1493  
2492             # Write the subclass chart type elements for combined chart.
2493             $second_chart->_write_chart_type( primary_axes => 1 );
2494             $second_chart->_write_chart_type( primary_axes => 0 );
2495             }
2496              
2497             # Write the category and value elements for the primary axes.
2498             my @args = (
2499             x_axis => $self->{_x_axis},
2500             y_axis => $self->{_y_axis},
2501             axis_ids => $self->{_axis_ids}
2502             );
2503 426     426   934  
2504 426         1024 if ( $self->{_date_category} ) {
2505             $self->_write_date_axis( @args );
2506             }
2507 426 100       1559 else {
2508             $self->_write_cat_axis( @args );
2509 4         13 }
2510              
2511 4         10 $self->_write_val_axis( @args );
2512              
2513             # Write the category and value elements for the secondary axes.
2514             @args = (
2515             x_axis => $self->{_x2_axis},
2516             y_axis => $self->{_y2_axis},
2517             axis_ids => $self->{_axis2_ids}
2518             );
2519              
2520             $self->_write_val_axis( @args );
2521              
2522             # Write the secondary axis for the secondary chart.
2523 338     338   675 if ( $second_chart && $second_chart->{_is_secondary} ) {
2524 338         794  
2525             @args = (
2526 338         1299 x_axis => $second_chart->{_x2_axis},
2527             y_axis => $second_chart->{_y2_axis},
2528             axis_ids => $second_chart->{_axis2_ids}
2529 338         2237 );
2530              
2531             $second_chart->_write_val_axis( @args );
2532 338         1688 }
2533 338         1346  
2534              
2535             if ( $self->{_date_category} ) {
2536             $self->_write_date_axis( @args );
2537 338 100       1045 }
2538             else {
2539             $self->_write_cat_axis( @args );
2540 8 100       48 }
2541 4         12  
2542             # Write the c:dTable element.
2543             $self->_write_d_table();
2544 4         12  
2545             # Write the c:spPr element for the plotarea formatting.
2546             $self->_write_sp_pr( $self->{_plotarea} );
2547              
2548 8         16 $self->xml_end_tag( 'c:plotArea' );
2549             }
2550              
2551 8         15  
2552             ##############################################################################
2553             #
2554 8         36 # _write_layout()
2555 8         22 #
2556             # Write the <c:layout> element.
2557             #
2558              
2559             my $self = shift;
2560             my $layout = shift;
2561             my $type = shift;
2562              
2563 338         1649 if ( !$layout ) {
2564             # Automatic layout.
2565 338 100       1400 $self->xml_empty_tag( 'c:layout' );
2566 16         103 }
2567             else {
2568             # User defined manual layout.
2569 322         1995 $self->xml_start_tag( 'c:layout' );
2570             $self->_write_manual_layout( $layout, $type );
2571             $self->xml_end_tag( 'c:layout' );
2572 338         2372 }
2573             }
2574              
2575             ##############################################################################
2576             #
2577             # _write_manual_layout()
2578             #
2579 338         1401 # Write the <c:manualLayout> element.
2580             #
2581 338         1323  
2582             my $self = shift;
2583             my $layout = shift;
2584 338 100 100     1146 my $type = shift;
2585              
2586             $self->xml_start_tag( 'c:manualLayout' );
2587              
2588             # Plotarea has a layoutTarget element.
2589             if ( $type eq 'plot' ) {
2590 4         18 $self->xml_empty_tag( 'c:layoutTarget', ( 'val' => 'inner' ) );
2591             }
2592 4         22  
2593             # Set the x, y positions.
2594             $self->xml_empty_tag( 'c:xMode', ( 'val' => 'edge' ) );
2595             $self->xml_empty_tag( 'c:yMode', ( 'val' => 'edge' ) );
2596 338 100       1134 $self->xml_empty_tag( 'c:x', ( 'val' => $layout->{x} ) );
2597 16         60 $self->xml_empty_tag( 'c:y', ( 'val' => $layout->{y} ) );
2598              
2599             # For plotarea and legend set the width and height.
2600 322         1426 if ( $type ne 'text' ) {
2601             $self->xml_empty_tag( 'c:w', ( 'val' => $layout->{width} ) );
2602             $self->xml_empty_tag( 'c:h', ( 'val' => $layout->{height} ) );
2603             }
2604 338         2290  
2605             $self->xml_end_tag( 'c:manualLayout' );
2606             }
2607 338         1742  
2608             ##############################################################################
2609 338         1597 #
2610             # _write_chart_type()
2611             #
2612             # Write the chart type element. This method should be overridden by the
2613             # subclasses.
2614             #
2615              
2616             my $self = shift;
2617             }
2618              
2619              
2620             ##############################################################################
2621 955     955   1689 #
2622 955         1901 # _write_grouping()
2623 955         1461 #
2624             # Write the <c:grouping> element.
2625 955 100       2381 #
2626              
2627 946         2430 my $self = shift;
2628             my $val = shift;
2629              
2630             my @attributes = ( 'val' => $val );
2631 9         37  
2632 9         129 $self->xml_empty_tag( 'c:grouping', @attributes );
2633 9         32 }
2634              
2635              
2636             ##############################################################################
2637             #
2638             # _write_series()
2639             #
2640             # Write the series elements.
2641             #
2642              
2643             my $self = shift;
2644             my $series = shift;
2645 9     9   20  
2646 9         22 $self->_write_ser( $series );
2647 9         19 }
2648              
2649 9         30  
2650             ##############################################################################
2651             #
2652 9 100       38 # _write_ser()
2653 1         3 #
2654             # Write the <c:ser> element.
2655             #
2656              
2657 9         38 my $self = shift;
2658 9         29 my $series = shift;
2659 9         34 my $index = $self->{_series_index}++;
2660 9         31  
2661             $self->xml_start_tag( 'c:ser' );
2662              
2663 9 100       27 # Write the c:idx element.
2664 3         12 $self->_write_idx( $index );
2665 3         10  
2666             # Write the c:order element.
2667             $self->_write_order( $index );
2668 9         40  
2669             # Write the series name.
2670             $self->_write_series_name( $series );
2671              
2672             # Write the c:spPr element.
2673             $self->_write_sp_pr( $series );
2674              
2675             # Write the c:marker element.
2676             $self->_write_marker( $series->{_marker} );
2677              
2678             # Write the c:invertIfNegative element.
2679             $self->_write_c_invert_if_negative( $series->{_invert_if_neg} );
2680 0     0   0  
2681             # Write the c:dPt element.
2682             $self->_write_d_pt( $series->{_points} );
2683              
2684             # Write the c:dLbls element.
2685             $self->_write_d_lbls( $series->{_labels} );
2686              
2687             # Write the c:trendline element.
2688             $self->_write_trendline( $series->{_trendline} );
2689              
2690             # Write the c:errBars element.
2691             $self->_write_error_bars( $series->{_error_bars} );
2692 333     333   710  
2693 333         652 # Write the c:cat element.
2694             $self->_write_cat( $series );
2695 333         1007  
2696             # Write the c:val element.
2697 333         1070 $self->_write_val( $series );
2698              
2699             # Write the c:smooth element.
2700             if ( $self->{_smooth_allowed} ) {
2701             $self->_write_c_smooth( $series->{_smooth} );
2702             }
2703              
2704             $self->xml_end_tag( 'c:ser' );
2705             }
2706              
2707              
2708             ##############################################################################
2709 249     249   438 #
2710 249         394 # _write_idx()
2711             #
2712 249         769 # Write the <c:idx> element.
2713             #
2714              
2715             my $self = shift;
2716             my $val = shift;
2717              
2718             my @attributes = ( 'val' => $val );
2719              
2720             $self->xml_empty_tag( 'c:idx', @attributes );
2721             }
2722              
2723              
2724 970     970   1643 ##############################################################################
2725 970         1383 #
2726 970         1844 # _write_order()
2727             #
2728 970         2563 # Write the <c:order> element.
2729             #
2730              
2731 970         3306 my $self = shift;
2732             my $val = shift;
2733              
2734 970         3145 my @attributes = ( 'val' => $val );
2735              
2736             $self->xml_empty_tag( 'c:order', @attributes );
2737 970         3457 }
2738              
2739              
2740 970         3419 ##############################################################################
2741             #
2742             # _write_series_name()
2743 970         3659 #
2744             # Write the series name.
2745             #
2746 970         3514  
2747             my $self = shift;
2748             my $series = shift;
2749 970         3250  
2750             my $name;
2751             if ( $name = $series->{_name_formula} ) {
2752 970         3438 $self->_write_tx_formula( $name, $series->{_name_id} );
2753             }
2754             elsif ( $name = $series->{_name} ) {
2755 970         3399 $self->_write_tx_value( $name );
2756             }
2757              
2758 970         3207 }
2759              
2760              
2761 970         3228 ##############################################################################
2762             #
2763             # _write_cat()
2764 970         3322 #
2765             # Write the <c:cat> element.
2766             #
2767 970 100       2543  
2768 214         926 my $self = shift;
2769             my $series = shift;
2770             my $formula = $series->{_categories};
2771 970         2242 my $data_id = $series->{_cat_data_id};
2772             my $data;
2773              
2774             if ( defined $data_id ) {
2775             $data = $self->{_formula_data}->[$data_id];
2776             }
2777              
2778             # Ignore <c:cat> elements for charts without category values.
2779             return unless $formula;
2780              
2781             $self->xml_start_tag( 'c:cat' );
2782              
2783 1087     1087   1706 # Check the type of cached data.
2784 1087         1520 my $type = $self->_get_data_type( $data );
2785              
2786 1087         2184 if ( $type eq 'str' ) {
2787              
2788 1087         2701 $self->{_cat_has_num_fmt} = 0;
2789              
2790             # Write the c:numRef element.
2791             $self->_write_str_ref( $formula, $data, $type );
2792             }
2793             elsif ( $type eq 'multi_str') {
2794              
2795             $self->{_cat_has_num_fmt} = 0;
2796              
2797             # Write the c:multiLvLStrRef element.
2798             $self->_write_multi_lvl_str_ref( $formula, $data );
2799             }
2800 1033     1033   1629 else {
2801 1033         1498  
2802             $self->{_cat_has_num_fmt} = 1;
2803 1033         2046  
2804             # Write the c:numRef element.
2805 1033         2461 $self->_write_num_ref( $formula, $data, $type );
2806             }
2807              
2808              
2809             $self->xml_end_tag( 'c:cat' );
2810             }
2811              
2812              
2813             ##############################################################################
2814             #
2815             # _write_val()
2816             #
2817 1032     1032   1566 # Write the <c:val> element.
2818 1032         1479 #
2819              
2820 1032         1436 my $self = shift;
2821 1032 100       4076 my $series = shift;
    100          
2822 11         45 my $formula = $series->{_values};
2823             my $data_id = $series->{_val_data_id};
2824             my $data = $self->{_formula_data}->[$data_id];
2825 2         20  
2826             $self->xml_start_tag( 'c:val' );
2827              
2828             # Unlike Cat axes data should only be numeric.
2829              
2830             # Write the c:numRef element.
2831             $self->_write_num_ref( $formula, $data, 'num' );
2832              
2833             $self->xml_end_tag( 'c:val' );
2834             }
2835              
2836              
2837             ##############################################################################
2838             #
2839 970     970   1411 # _write_num_ref()
2840 970         1369 #
2841 970         1598 # Write the <c:numRef> element.
2842 970         1426 #
2843 970         1245  
2844             my $self = shift;
2845 970 100       2182 my $formula = shift;
2846 193         446 my $data = shift;
2847             my $type = shift;
2848              
2849             $self->xml_start_tag( 'c:numRef' );
2850 970 100       2094  
2851             # Write the c:f element.
2852 193         659 $self->_write_series_formula( $formula );
2853              
2854             if ( $type eq 'num' ) {
2855 193         737  
2856             # Write the c:numCache element.
2857 193 100       857 $self->_write_num_cache( $data );
    100          
2858             }
2859 7         14 elsif ( $type eq 'str' ) {
2860              
2861             # Write the c:strCache element.
2862 7         23 $self->_write_str_cache( $data );
2863             }
2864              
2865             $self->xml_end_tag( 'c:numRef' );
2866 3         5 }
2867              
2868              
2869 3         7 ##############################################################################
2870             #
2871             # _write_str_ref()
2872             #
2873 183         398 # Write the <c:strRef> element.
2874             #
2875              
2876 183         767 my $self = shift;
2877             my $formula = shift;
2878             my $data = shift;
2879             my $type = shift;
2880 193         515  
2881             $self->xml_start_tag( 'c:strRef' );
2882              
2883             # Write the c:f element.
2884             $self->_write_series_formula( $formula );
2885              
2886             if ( $type eq 'num' ) {
2887              
2888             # Write the c:numCache element.
2889             $self->_write_num_cache( $data );
2890             }
2891             elsif ( $type eq 'str' ) {
2892 970     970   1470  
2893 970         1326 # Write the c:strCache element.
2894 970         1763 $self->_write_str_cache( $data );
2895 970         1456 }
2896 970         1857  
2897             $self->xml_end_tag( 'c:strRef' );
2898 970         2710 }
2899              
2900              
2901             ##############################################################################
2902             #
2903 970         3151 # _write_multi_lvl_str_ref()
2904             #
2905 970         2034 # Write the <c:multiLvLStrRef> element.
2906             #
2907              
2908             my $self = shift;
2909             my $formula = shift;
2910             my $data = shift;
2911             my $count = @$data;
2912              
2913             return if !$count;
2914              
2915             $self->xml_start_tag( 'c:multiLvlStrRef' );
2916              
2917 1277     1277   1909 # Write the c:f element.
2918 1277         1783 $self->_write_series_formula( $formula );
2919 1277         1747  
2920 1277         1666 $self->xml_start_tag( 'c:multiLvlStrCache' );
2921              
2922 1277         3134 # Write the c:ptCount element.
2923             $count = @{ $data->[-1] };
2924             $self->_write_pt_count( $count );
2925 1277         4344  
2926             # Write the data arrays in reverse order.
2927 1277 50       3224 for my $aref ( reverse @$data ) {
    0          
2928             $self->xml_start_tag( 'c:lvl' );
2929              
2930 1277         4043 for my $i ( 0 .. @$aref - 1 ) {
2931             # Write the c:pt element.
2932             $self->_write_pt( $i, $aref->[$i] );
2933             }
2934              
2935 0         0 $self->xml_end_tag( 'c:lvl' );
2936             }
2937              
2938 1277         2902 $self->xml_end_tag( 'c:multiLvlStrCache' );
2939              
2940             $self->xml_end_tag( 'c:multiLvlStrRef' );
2941             }
2942              
2943              
2944             ##############################################################################
2945             #
2946             # _write_series_formula()
2947             #
2948             # Write the <c:f> element.
2949             #
2950 44     44   88  
2951 44         119 my $self = shift;
2952 44         73 my $formula = shift;
2953 44         68  
2954             # Strip the leading '=' from the formula.
2955 44         131 $formula =~ s/^=//;
2956              
2957             $self->xml_data_element( 'c:f', $formula );
2958 44         176 }
2959              
2960 44 50       187  
    50          
2961             ##############################################################################
2962             #
2963 0         0 # _write_axis_ids()
2964             #
2965             # Write the <c:axId> elements for the primary or secondary axes.
2966             #
2967              
2968 44         200 my $self = shift;
2969             my %args = @_;
2970              
2971 44         108 # Generate the axis ids.
2972             $self->_add_axis_ids( %args );
2973              
2974             if ( $args{primary_axes} ) {
2975              
2976             # Write the axis ids for the primary axes.
2977             $self->_write_axis_id( $self->{_axis_ids}->[0] );
2978             $self->_write_axis_id( $self->{_axis_ids}->[1] );
2979             }
2980             else {
2981             # Write the axis ids for the secondary axes.
2982             $self->_write_axis_id( $self->{_axis2_ids}->[0] );
2983 3     3   3 $self->_write_axis_id( $self->{_axis2_ids}->[1] );
2984 3         4 }
2985 3         3 }
2986 3         3  
2987              
2988 3 50       4 ##############################################################################
2989             #
2990 3         7 # _write_axis_id()
2991             #
2992             # Write the <c:axId> element.
2993 3         6 #
2994              
2995 3         6 my $self = shift;
2996             my $val = shift;
2997              
2998 3         4 my @attributes = ( 'val' => $val );
  3         5  
2999 3         6  
3000             $self->xml_empty_tag( 'c:axId', @attributes );
3001             }
3002 3         6  
3003 6         12  
3004             ##############################################################################
3005 6         12 #
3006             # _write_cat_axis()
3007 30         35 #
3008             # Write the <c:catAx> element. Usually the X axis.
3009             #
3010 6         16  
3011             my $self = shift;
3012             my %args = @_;
3013 3         6 my $x_axis = $args{x_axis};
3014             my $y_axis = $args{y_axis};
3015 3         7 my $axis_ids = $args{axis_ids};
3016              
3017             # if there are no axis_ids then we don't need to write this element
3018             return unless $axis_ids;
3019             return unless scalar @$axis_ids;
3020              
3021             my $position = $self->{_cat_axis_position};
3022             my $is_y_axis = $self->{_horiz_cat_axis};
3023              
3024             # Overwrite the default axis position with a user supplied value.
3025             $position = $x_axis->{_position} || $position;
3026              
3027 1325     1325   1939 $self->xml_start_tag( 'c:catAx' );
3028 1325         1975  
3029             $self->_write_axis_id( $axis_ids->[0] );
3030              
3031 1325         5064 # Write the c:scaling element.
3032             $self->_write_scaling( $x_axis->{_reverse} );
3033 1325         4639  
3034             $self->_write_delete( 1 ) unless $x_axis->{_visible};
3035              
3036             # Write the c:axPos element.
3037             $self->_write_axis_pos( $position, $y_axis->{_reverse} );
3038              
3039             # Write the c:majorGridlines element.
3040             $self->_write_major_gridlines( $x_axis->{_major_gridlines} );
3041              
3042             # Write the c:minorGridlines element.
3043             $self->_write_minor_gridlines( $x_axis->{_minor_gridlines} );
3044              
3045 385     385   866 # Write the axis title elements.
3046 385         1399 my $title;
3047             if ( $title = $x_axis->{_formula} ) {
3048              
3049 385         2672 $self->_write_title_formula( $title, $x_axis->{_data_id}, $is_y_axis,
3050             $x_axis->{_name_font}, $x_axis->{_layout} );
3051 385 100       1630 }
3052             elsif ( $title = $x_axis->{_name} ) {
3053             $self->_write_title_rich( $title, $is_y_axis, $x_axis->{_name_font},
3054 373         2609 $x_axis->{_layout} );
3055 373         1193 }
3056              
3057             # Write the c:numFmt element.
3058             $self->_write_cat_number_format( $x_axis );
3059 12         61  
3060 12         41 # Write the c:majorTickMark element.
3061             $self->_write_major_tick_mark( $x_axis->{_major_tick_mark} );
3062              
3063             # Write the c:minorTickMark element.
3064             $self->_write_minor_tick_mark( $x_axis->{_minor_tick_mark} );
3065              
3066             # Write the c:tickLblPos element.
3067             $self->_write_tick_label_pos( $x_axis->{_label_position} );
3068              
3069             # Write the c:spPr element for the axis line.
3070             $self->_write_sp_pr( $x_axis );
3071              
3072             # Write the axis font elements.
3073 1533     1533   2308 $self->_write_axis_font( $x_axis->{_num_font} );
3074 1533         2080  
3075             # Write the c:crossAx element.
3076 1533         2885 $self->_write_cross_axis( $axis_ids->[1] );
3077              
3078 1533         3587 if ( $self->{_show_crosses} || $x_axis->{_visible} ) {
3079              
3080             # Note, the category crossing comes from the value axis.
3081             if ( !defined $y_axis->{_crossing}
3082             || $y_axis->{_crossing} eq 'max'
3083             || $y_axis->{_crossing} eq 'min' )
3084             {
3085             # Write the c:crosses element.
3086             $self->_write_crosses( $y_axis->{_crossing} );
3087             }
3088             else {
3089              
3090 644     644   1178 # Write the c:crossesAt element.
3091 644         1883 $self->_write_c_crosses_at( $y_axis->{_crossing} );
3092 644         1174 }
3093 644         1020 }
3094 644         1050  
3095             # Write the c:auto element.
3096             if (!$x_axis->{_text_axis}) {
3097 644 50       1701 $self->_write_auto( 1 );
3098 644 100       1966 }
3099              
3100 332         770 # Write the c:labelAlign element.
3101 332         711 $self->_write_label_align( $x_axis->{_label_align} );
3102              
3103             # Write the c:labelOffset element.
3104 332   66     1890 $self->_write_label_offset( 100 );
3105              
3106 332         1516 # Write the c:tickLblSkip element.
3107             $self->_write_tick_lbl_skip( $x_axis->{_interval_unit} );
3108 332         1228  
3109             # Write the c:tickMarkSkip element.
3110             $self->_write_tick_mark_skip( $x_axis->{_interval_tick} );
3111 332         2353  
3112             $self->xml_end_tag( 'c:catAx' );
3113 332 100       1381 }
3114              
3115              
3116 332         2289 ##############################################################################
3117             #
3118             # _write_val_axis()
3119 332         2426 #
3120             # Write the <c:valAx> element. Usually the Y axis.
3121             #
3122 332         2266 # TODO. Maybe should have a _write_cat_val_axis() method as well for scatter.
3123             #
3124              
3125 332         634 my $self = shift;
3126 332 100       2152 my %args = @_;
    100          
3127             my $x_axis = $args{x_axis};
3128             my $y_axis = $args{y_axis};
3129 3         19 my $axis_ids = $args{axis_ids};
3130             my $position = $args{position} || $self->{_val_axis_position};
3131             my $is_y_axis = $self->{_horiz_val_axis};
3132              
3133 19         108 return unless $axis_ids && scalar @$axis_ids;
3134              
3135             # Overwrite the default axis position with a user supplied value.
3136             $position = $y_axis->{_position} || $position;
3137 332         2144  
3138             $self->xml_start_tag( 'c:valAx' );
3139              
3140 332         1986 $self->_write_axis_id( $axis_ids->[1] );
3141              
3142             # Write the c:scaling element.
3143 332         1736 $self->_write_scaling(
3144             $y_axis->{_reverse}, $y_axis->{_min},
3145             $y_axis->{_max}, $y_axis->{_log_base}
3146 332         1904 );
3147              
3148             $self->_write_delete( 1 ) unless $y_axis->{_visible};
3149 332         1308  
3150             # Write the c:axPos element.
3151             $self->_write_axis_pos( $position, $x_axis->{_reverse} );
3152 332         2125  
3153             # Write the c:majorGridlines element.
3154             $self->_write_major_gridlines( $y_axis->{_major_gridlines} );
3155 332         1865  
3156             # Write the c:minorGridlines element.
3157 332 100 100     1851 $self->_write_minor_gridlines( $y_axis->{_minor_gridlines} );
3158              
3159             # Write the axis title elements.
3160 328 100 100     2298 my $title;
      100        
3161             if ( $title = $y_axis->{_formula} ) {
3162             $self->_write_title_formula( $title, $y_axis->{_data_id}, $is_y_axis,
3163             $y_axis->{_name_font}, $y_axis->{_layout} );
3164             }
3165 327         2086 elsif ( $title = $y_axis->{_name} ) {
3166             $self->_write_title_rich( $title, $is_y_axis, $y_axis->{_name_font},
3167             $y_axis->{_layout} );
3168             }
3169              
3170 1         7 # Write the c:numberFormat element.
3171             $self->_write_number_format( $y_axis );
3172              
3173             # Write the c:majorTickMark element.
3174             $self->_write_major_tick_mark( $y_axis->{_major_tick_mark} );
3175 332 100       1314  
3176 331         1917 # Write the c:minorTickMark element.
3177             $self->_write_minor_tick_mark( $y_axis->{_minor_tick_mark} );
3178              
3179             # Write the c:tickLblPos element.
3180 332         2272 $self->_write_tick_label_pos( $y_axis->{_label_position} );
3181              
3182             # Write the c:spPr element for the axis line.
3183 332         3114 $self->_write_sp_pr( $y_axis );
3184              
3185             # Write the axis font elements.
3186 332         2254 $self->_write_axis_font( $y_axis->{_num_font} );
3187              
3188             # Write the c:crossAx element.
3189 332         1949 $self->_write_cross_axis( $axis_ids->[0] );
3190              
3191 332         1222 # Note, the category crossing comes from the value axis.
3192             if ( !defined $x_axis->{_crossing}
3193             || $x_axis->{_crossing} eq 'max'
3194             || $x_axis->{_crossing} eq 'min' )
3195             {
3196             # Write the c:crosses element.
3197             $self->_write_crosses( $x_axis->{_crossing} );
3198             }
3199             else {
3200              
3201             # Write the c:crossesAt element.
3202             $self->_write_c_crosses_at( $x_axis->{_crossing} );
3203             }
3204              
3205 742     742   1254 # Write the c:crossBetween element.
3206 742         2273 $self->_write_cross_between( $x_axis->{_position_axis} );
3207 742         1407  
3208 742         1253 # Write the c:majorUnit element.
3209 742         1187 $self->_write_c_major_unit( $y_axis->{_major_unit} );
3210 742   66     3492  
3211 742         1265 # Write the c:minorUnit element.
3212             $self->_write_c_minor_unit( $y_axis->{_minor_unit} );
3213 742 100 50     3701  
3214             # Write the c:dispUnits element.
3215             $self->_write_disp_units( $y_axis->{_display_units},
3216 381   66     2026 $y_axis->{_display_units_visible} );
3217              
3218 381         1874 $self->xml_end_tag( 'c:valAx' );
3219             }
3220 381         1593  
3221              
3222             ##############################################################################
3223             #
3224             # _write_cat_val_axis()
3225             #
3226 381         1935 # Write the <c:valAx> element. This is for the second valAx in scatter plots.
3227             # Usually the X axis.
3228 381 50       1330 #
3229              
3230             my $self = shift;
3231 381         1696 my %args = @_;
3232             my $x_axis = $args{x_axis};
3233             my $y_axis = $args{y_axis};
3234 381         1407 my $axis_ids = $args{axis_ids};
3235             my $position = $args{position} || $self->{_val_axis_position};
3236             my $is_y_axis = $self->{_horiz_val_axis};
3237 381         1770  
3238             return unless $axis_ids && scalar @$axis_ids;
3239              
3240 381         685 # Overwrite the default axis position with a user supplied value.
3241 381 100       2313 $position = $x_axis->{_position} || $position;
    100          
3242              
3243 5         24 $self->xml_start_tag( 'c:valAx' );
3244              
3245             $self->_write_axis_id( $axis_ids->[0] );
3246              
3247 20         143 # Write the c:scaling element.
3248             $self->_write_scaling(
3249             $x_axis->{_reverse}, $x_axis->{_min},
3250             $x_axis->{_max}, $x_axis->{_log_base}
3251 381         2583 );
3252              
3253             $self->_write_delete( 1 ) unless $x_axis->{_visible};
3254 381         1607  
3255             # Write the c:axPos element.
3256             $self->_write_axis_pos( $position, $y_axis->{_reverse} );
3257 381         1267  
3258             # Write the c:majorGridlines element.
3259             $self->_write_major_gridlines( $x_axis->{_major_gridlines} );
3260 381         1363  
3261             # Write the c:minorGridlines element.
3262             $self->_write_minor_gridlines( $x_axis->{_minor_gridlines} );
3263 381         1343  
3264             # Write the axis title elements.
3265             my $title;
3266 381         1597 if ( $title = $x_axis->{_formula} ) {
3267             $self->_write_title_formula( $title, $x_axis->{_data_id}, $is_y_axis,
3268             $x_axis->{_name_font}, $x_axis->{_layout} );
3269 381         1324 }
3270             elsif ( $title = $x_axis->{_name} ) {
3271             $self->_write_title_rich( $title, $is_y_axis, $x_axis->{_name_font},
3272 381 100 100     2486 $x_axis->{_layout} );
      100        
3273             }
3274              
3275             # Write the c:numberFormat element.
3276             $self->_write_number_format( $x_axis );
3277 379         1577  
3278             # Write the c:majorTickMark element.
3279             $self->_write_major_tick_mark( $x_axis->{_major_tick_mark} );
3280              
3281             # Write the c:minorTickMark element.
3282 2         5 $self->_write_minor_tick_mark( $x_axis->{_minor_tick_mark} );
3283              
3284             # Write the c:tickLblPos element.
3285             $self->_write_tick_label_pos( $x_axis->{_label_position} );
3286 381         2934  
3287             # Write the c:spPr element for the axis line.
3288             $self->_write_sp_pr( $x_axis );
3289 381         2089  
3290             # Write the axis font elements.
3291             $self->_write_axis_font( $x_axis->{_num_font} );
3292 381         2197  
3293             # Write the c:crossAx element.
3294             $self->_write_cross_axis( $axis_ids->[1] );
3295              
3296 381         2518 # Note, the category crossing comes from the value axis.
3297             if ( !defined $y_axis->{_crossing}
3298 381         1362 || $y_axis->{_crossing} eq 'max'
3299             || $y_axis->{_crossing} eq 'min' )
3300             {
3301             # Write the c:crosses element.
3302             $self->_write_crosses( $y_axis->{_crossing} );
3303             }
3304             else {
3305              
3306             # Write the c:crossesAt element.
3307             $self->_write_c_crosses_at( $y_axis->{_crossing} );
3308             }
3309              
3310             # Write the c:crossBetween element.
3311 62     62   133 $self->_write_cross_between( $y_axis->{_position_axis} );
3312 62         258  
3313 62         124 # Write the c:majorUnit element.
3314 62         99 $self->_write_c_major_unit( $x_axis->{_major_unit} );
3315 62         120  
3316 62   33     173 # Write the c:minorUnit element.
3317 62         98 $self->_write_c_minor_unit( $x_axis->{_minor_unit} );
3318              
3319 62 100 50     367 # Write the c:dispUnits element.
3320             $self->_write_disp_units( $x_axis->{_display_units},
3321             $x_axis->{_display_units_visible} );
3322 32   66     168  
3323             $self->xml_end_tag( 'c:valAx' );
3324 32         122 }
3325              
3326 32         115  
3327             ##############################################################################
3328             #
3329             # _write_date_axis()
3330             #
3331             # Write the <c:dateAx> element. Usually the X axis.
3332 32         262 #
3333              
3334 32 100       112 my $self = shift;
3335             my %args = @_;
3336             my $x_axis = $args{x_axis};
3337 32         194 my $y_axis = $args{y_axis};
3338             my $axis_ids = $args{axis_ids};
3339              
3340 32         335 return unless $axis_ids && scalar @$axis_ids;
3341              
3342             my $position = $self->{_cat_axis_position};
3343 32         218  
3344             # Overwrite the default axis position with a user supplied value.
3345             $position = $x_axis->{_position} || $position;
3346 32         66  
3347 32 100       241 $self->xml_start_tag( 'c:dateAx' );
    100          
3348              
3349 1         6 $self->_write_axis_id( $axis_ids->[0] );
3350              
3351             # Write the c:scaling element.
3352             $self->_write_scaling(
3353 1         6 $x_axis->{_reverse}, $x_axis->{_min},
3354             $x_axis->{_max}, $x_axis->{_log_base}
3355             );
3356              
3357 32         181 $self->_write_delete( 1 ) unless $x_axis->{_visible};
3358              
3359             # Write the c:axPos element.
3360 32         205 $self->_write_axis_pos( $position, $y_axis->{_reverse} );
3361              
3362             # Write the c:majorGridlines element.
3363 32         195 $self->_write_major_gridlines( $x_axis->{_major_gridlines} );
3364              
3365             # Write the c:minorGridlines element.
3366 32         176 $self->_write_minor_gridlines( $x_axis->{_minor_gridlines} );
3367              
3368             # Write the axis title elements.
3369 32         110 my $title;
3370             if ( $title = $x_axis->{_formula} ) {
3371             $self->_write_title_formula( $title, $x_axis->{_data_id}, undef,
3372 32         231 $x_axis->{_name_font}, $x_axis->{_layout} );
3373             }
3374             elsif ( $title = $x_axis->{_name} ) {
3375 32         179 $self->_write_title_rich( $title, undef, $x_axis->{_name_font},
3376             $x_axis->{_layout} );
3377             }
3378 32 100 100     207  
      66        
3379             # Write the c:numFmt element.
3380             $self->_write_number_format( $x_axis );
3381              
3382             # Write the c:majorTickMark element.
3383 31         258 $self->_write_major_tick_mark( $x_axis->{_major_tick_mark} );
3384              
3385             # Write the c:minorTickMark element.
3386             $self->_write_minor_tick_mark( $x_axis->{_minor_tick_mark} );
3387              
3388 1         11 # Write the c:tickLblPos element.
3389             $self->_write_tick_label_pos( $x_axis->{_label_position} );
3390              
3391             # Write the c:spPr element for the axis line.
3392 32         206 $self->_write_sp_pr( $x_axis );
3393              
3394             # Write the axis font elements.
3395 32         194 $self->_write_axis_font( $x_axis->{_num_font} );
3396              
3397             # Write the c:crossAx element.
3398 32         185 $self->_write_cross_axis( $axis_ids->[1] );
3399              
3400             if ( $self->{_show_crosses} || $x_axis->{_visible} ) {
3401              
3402 32         244 # Note, the category crossing comes from the value axis.
3403             if ( !defined $y_axis->{_crossing}
3404 32         118 || $y_axis->{_crossing} eq 'max'
3405             || $y_axis->{_crossing} eq 'min' )
3406             {
3407             # Write the c:crosses element.
3408             $self->_write_crosses( $y_axis->{_crossing} );
3409             }
3410             else {
3411              
3412             # Write the c:crossesAt element.
3413             $self->_write_c_crosses_at( $y_axis->{_crossing} );
3414             }
3415             }
3416 32     32   53  
3417 32         82 # Write the c:auto element.
3418 32         64 $self->_write_auto( 1 );
3419 32         54  
3420 32         47 # Write the c:labelOffset element.
3421             $self->_write_label_offset( 100 );
3422 32 100 50     246  
3423             # Write the c:tickLblSkip element.
3424 17         43 $self->_write_tick_lbl_skip( $x_axis->{_interval_unit} );
3425              
3426             # Write the c:tickMarkSkip element.
3427 17   33     96 $self->_write_tick_mark_skip( $x_axis->{_interval_tick} );
3428              
3429 17         78 # Write the c:majorUnit element.
3430             $self->_write_c_major_unit( $x_axis->{_major_unit} );
3431 17         53  
3432             # Write the c:majorTimeUnit element.
3433             if ( defined $x_axis->{_major_unit} ) {
3434             $self->_write_c_major_time_unit( $x_axis->{_major_unit_type} );
3435             }
3436              
3437 17         116 # Write the c:minorUnit element.
3438             $self->_write_c_minor_unit( $x_axis->{_minor_unit} );
3439 17 100       63  
3440             # Write the c:minorTimeUnit element.
3441             if ( defined $x_axis->{_minor_unit} ) {
3442 17         111 $self->_write_c_minor_time_unit( $x_axis->{_minor_unit_type} );
3443             }
3444              
3445 17         113 $self->xml_end_tag( 'c:dateAx' );
3446             }
3447              
3448 17         117  
3449             ##############################################################################
3450             #
3451 17         32 # _write_scaling()
3452 17 50       86 #
    100          
3453             # Write the <c:scaling> element.
3454 0         0 #
3455              
3456             my $self = shift;
3457             my $reverse = shift;
3458 1         4 my $min = shift;
3459             my $max = shift;
3460             my $log_base = shift;
3461              
3462 17         91 $self->xml_start_tag( 'c:scaling' );
3463              
3464             # Write the c:logBase element.
3465 17         93 $self->_write_c_log_base( $log_base );
3466              
3467             # Write the c:orientation element.
3468 17         102 $self->_write_orientation( $reverse );
3469              
3470             # Write the c:max element.
3471 17         129 $self->_write_c_max( $max );
3472              
3473             # Write the c:min element.
3474 17         53 $self->_write_c_min( $min );
3475              
3476             $self->xml_end_tag( 'c:scaling' );
3477 17         109 }
3478              
3479              
3480 17         89 ##############################################################################
3481             #
3482 17 100 100     179 # _write_c_log_base()
3483             #
3484             # Write the <c:logBase> element.
3485 16 50 33     100 #
      33        
3486              
3487             my $self = shift;
3488             my $val = shift;
3489              
3490 16         130 return unless $val;
3491              
3492             my @attributes = ( 'val' => $val );
3493              
3494             $self->xml_empty_tag( 'c:logBase', @attributes );
3495 0         0 }
3496              
3497              
3498             ##############################################################################
3499             #
3500 17         118 # _write_orientation()
3501             #
3502             # Write the <c:orientation> element.
3503 17         90 #
3504              
3505             my $self = shift;
3506 17         101 my $reverse = shift;
3507             my $val = 'minMax';
3508              
3509 17         118 $val = 'maxMin' if $reverse;
3510              
3511             my @attributes = ( 'val' => $val );
3512 17         110  
3513             $self->xml_empty_tag( 'c:orientation', @attributes );
3514             }
3515 17 100       45  
3516 3         14  
3517             ##############################################################################
3518             #
3519             # _write_c_max()
3520 17         135 #
3521             # Write the <c:max> element.
3522             #
3523 17 100       49  
3524 3         18 my $self = shift;
3525             my $max = shift;
3526              
3527 17         47 return unless defined $max;
3528              
3529             my @attributes = ( 'val' => $max );
3530              
3531             $self->xml_empty_tag( 'c:max', @attributes );
3532             }
3533              
3534              
3535             ##############################################################################
3536             #
3537             # _write_c_min()
3538             #
3539 762     762   1363 # Write the <c:min> element.
3540 762         1230 #
3541 762         1163  
3542 762         1144 my $self = shift;
3543 762         1148 my $min = shift;
3544              
3545 762         2279 return unless defined $min;
3546              
3547             my @attributes = ( 'val' => $min );
3548 762         3070  
3549             $self->xml_empty_tag( 'c:min', @attributes );
3550             }
3551 762         2804  
3552              
3553             ##############################################################################
3554 762         2916 #
3555             # _write_axis_pos()
3556             #
3557 762         2736 # Write the <c:axPos> element.
3558             #
3559 762         1891  
3560             my $self = shift;
3561             my $val = shift;
3562             my $reverse = shift;
3563              
3564             if ( $reverse ) {
3565             $val = 'r' if $val eq 'l';
3566             $val = 't' if $val eq 'b';
3567             }
3568              
3569             my @attributes = ( 'val' => $val );
3570              
3571 762     762   1312 $self->xml_empty_tag( 'c:axPos', @attributes );
3572 762         1142 }
3573              
3574 762 100       1913  
3575             ##############################################################################
3576 1         2 #
3577             # _write_number_format()
3578 1         2 #
3579             # Write the <c:numberFormat> element. Note: It is assumed that if a user
3580             # defined number format is supplied (i.e., non-default) then the sourceLinked
3581             # attribute is 0. The user can override this if required.
3582             #
3583              
3584             my $self = shift;
3585             my $axis = shift;
3586             my $format_code = $axis->{_num_format};
3587             my $source_linked = 1;
3588              
3589             # Check if a user defined number format has been set.
3590 763     763   1167 if ( $format_code ne $axis->{_defaults}->{num_format} ) {
3591 763         1074 $source_linked = 0;
3592 763         1227 }
3593              
3594 763 100       1793 # User override of sourceLinked.
3595             if ( $axis->{_num_format_linked} ) {
3596 763         1778 $source_linked = 1;
3597             }
3598 763         1968  
3599             my @attributes = (
3600             'formatCode' => $format_code,
3601             'sourceLinked' => $source_linked,
3602             );
3603              
3604             $self->xml_empty_tag( 'c:numFmt', @attributes );
3605             }
3606              
3607              
3608             ##############################################################################
3609             #
3610 762     762   1227 # _write_cat_number_format()
3611 762         1155 #
3612             # Write the <c:numFmt> element. Special case handler for category axes which
3613 762 100       2064 # don't always have a number format.
3614             #
3615 7         15  
3616             my $self = shift;
3617 7         21 my $axis = shift;
3618             my $format_code = $axis->{_num_format};
3619             my $source_linked = 1;
3620             my $default_format = 1;
3621              
3622             # Check if a user defined number format has been set.
3623             if ( $format_code ne $axis->{_defaults}->{num_format} ) {
3624             $source_linked = 0;
3625             $default_format = 0;
3626             }
3627              
3628             # User override of linkedSource.
3629 762     762   1220 if ( $axis->{_num_format_linked} ) {
3630 762         1122 $source_linked = 1;
3631             }
3632 762 100       1882  
3633             # Skip if cat doesn't have a num format (unless it is non-default).
3634 7         25 if ( !$self->{_cat_has_num_fmt} && $default_format ) {
3635             return;
3636 7         15 }
3637              
3638             my @attributes = (
3639             'formatCode' => $format_code,
3640             'sourceLinked' => $source_linked,
3641             );
3642              
3643             $self->xml_empty_tag( 'c:numFmt', @attributes );
3644             }
3645              
3646              
3647             ##############################################################################
3648 763     763   1345 #
3649 763         1202 # _write_number_format()
3650 763         1106 #
3651             # Write the <c:numberFormat> element for data labels.
3652 763 100       1790 #
3653 5 100       15  
3654 5 100       11 my $self = shift;
3655             my $format_code = shift;
3656             my $source_linked = 0;
3657 763         1816  
3658             my @attributes = (
3659 763         2105 'formatCode' => $format_code,
3660             'sourceLinked' => $source_linked,
3661             );
3662              
3663             $self->xml_empty_tag( 'c:numFmt', @attributes );
3664             }
3665              
3666              
3667             ##############################################################################
3668             #
3669             # _write_major_tick_mark()
3670             #
3671             # Write the <c:majorTickMark> element.
3672             #
3673 432     432   939  
3674 432         808 my $self = shift;
3675 432         931 my $val = shift;
3676 432         794  
3677             return unless $val;
3678              
3679 432 100       1741 my @attributes = ( 'val' => $val );
3680 8         23  
3681             $self->xml_empty_tag( 'c:majorTickMark', @attributes );
3682             }
3683              
3684 432 100       1387  
3685 4         8 ##############################################################################
3686             #
3687             # _write_minor_tick_mark()
3688 432         1459 #
3689             # Write the <c:minorTickMark> element.
3690             #
3691              
3692             my $self = shift;
3693 432         1836 my $val = shift;
3694              
3695             return unless $val;
3696              
3697             my @attributes = ( 'val' => $val );
3698              
3699             $self->xml_empty_tag( 'c:minorTickMark', @attributes );
3700             }
3701              
3702              
3703             ##############################################################################
3704             #
3705             # _write_tick_label_pos()
3706 334     334   793 #
3707 334         655 # Write the <c:tickLblPos> element.
3708 334         839 #
3709 334         653  
3710 334         631 my $self = shift;
3711             my $val = shift || 'nextTo';
3712              
3713 334 100       1446 if ( $val eq 'next_to' ) {
3714 6         10 $val = 'nextTo';
3715 6         11 }
3716              
3717             my @attributes = ( 'val' => $val );
3718              
3719 334 100       1622 $self->xml_empty_tag( 'c:tickLblPos', @attributes );
3720 2         4 }
3721              
3722              
3723             ##############################################################################
3724 334 100 100     2012 #
3725 261         612 # _write_cross_axis()
3726             #
3727             # Write the <c:crossAx> element.
3728 73         243 #
3729              
3730             my $self = shift;
3731             my $val = shift;
3732              
3733 73         280 my @attributes = ( 'val' => $val );
3734              
3735             $self->xml_empty_tag( 'c:crossAx', @attributes );
3736             }
3737              
3738              
3739             ##############################################################################
3740             #
3741             # _write_crosses()
3742             #
3743             # Write the <c:crosses> element.
3744             #
3745 4     4   12  
3746 4         7 my $self = shift;
3747 4         6 my $val = shift || 'autoZero';
3748              
3749 4         11 my @attributes = ( 'val' => $val );
3750              
3751             $self->xml_empty_tag( 'c:crosses', @attributes );
3752             }
3753              
3754 4         11  
3755             ##############################################################################
3756             #
3757             # _write_c_crosses_at()
3758             #
3759             # Write the <c:crossesAt> element.
3760             #
3761              
3762             my $self = shift;
3763             my $val = shift;
3764              
3765             my @attributes = ( 'val' => $val );
3766 762     762   1327  
3767 762         1131 $self->xml_empty_tag( 'c:crossesAt', @attributes );
3768             }
3769 762 100       1835  
3770              
3771 7         26 ##############################################################################
3772             #
3773 7         32 # _write_auto()
3774             #
3775             # Write the <c:auto> element.
3776             #
3777              
3778             my $self = shift;
3779             my $val = shift;
3780              
3781             my @attributes = ( 'val' => $val );
3782              
3783             $self->xml_empty_tag( 'c:auto', @attributes );
3784             }
3785 762     762   1262  
3786 762         1186  
3787             ##############################################################################
3788 762 100       1836 #
3789             # _write_label_align()
3790 2         3 #
3791             # Write the <c:labelAlign> element.
3792 2         5 #
3793              
3794             my $self = shift;
3795             my $val = shift || 'ctr';
3796              
3797             if ( $val eq 'right' ) {
3798             $val = 'r';
3799             }
3800              
3801             if ( $val eq 'left' ) {
3802             $val = 'l';
3803             }
3804 763     763   1308  
3805 763   100     2915 my @attributes = ( 'val' => $val );
3806              
3807 763 100       2062 $self->xml_empty_tag( 'c:lblAlgn', @attributes );
3808 2         4 }
3809              
3810              
3811 763         1703 ##############################################################################
3812             #
3813 763         2200 # _write_label_offset()
3814             #
3815             # Write the <c:labelOffset> element.
3816             #
3817              
3818             my $self = shift;
3819             my $val = shift;
3820              
3821             my @attributes = ( 'val' => $val );
3822              
3823             $self->xml_empty_tag( 'c:lblOffset', @attributes );
3824             }
3825 763     763   1238  
3826 763         1178  
3827             ##############################################################################
3828 763         1680 #
3829             # _write_tick_lbl_skip()
3830 763         2071 #
3831             # Write the <c:tickLblSkip> element.
3832             #
3833              
3834             my $self = shift;
3835             my $val = shift;
3836              
3837             return unless $val;
3838              
3839             my @attributes = ( 'val' => $val );
3840              
3841             $self->xml_empty_tag( 'c:tickLblSkip', @attributes );
3842 754     754   1640 }
3843 754   100     2742  
3844              
3845 754         1851 ##############################################################################
3846             #
3847 754         2144 # _write_tick_mark_skip()
3848             #
3849             # Write the <c:tickMarkSkip> element.
3850             #
3851              
3852             my $self = shift;
3853             my $val = shift;
3854              
3855             return unless $val;
3856              
3857             my @attributes = ( 'val' => $val );
3858              
3859 4     4   8 $self->xml_empty_tag( 'c:tickMarkSkip', @attributes );
3860 4         5 }
3861              
3862 4         9  
3863             ##############################################################################
3864 4         9 #
3865             # _write_major_gridlines()
3866             #
3867             # Write the <c:majorGridlines> element.
3868             #
3869              
3870             my $self = shift;
3871             my $gridlines = shift;
3872              
3873             return unless $gridlines;
3874             return unless $gridlines->{_visible};
3875              
3876 349     349   783 if ( $gridlines->{_line}->{_defined} ) {
3877 349         667 $self->xml_start_tag( 'c:majorGridlines' );
3878              
3879 349         929 # Write the c:spPr element.
3880             $self->_write_sp_pr( $gridlines );
3881 349         1253  
3882             $self->xml_end_tag( 'c:majorGridlines' );
3883             }
3884             else {
3885             $self->xml_empty_tag( 'c:majorGridlines' );
3886             }
3887             }
3888              
3889              
3890             ##############################################################################
3891             #
3892             # _write_minor_gridlines()
3893 333     333   717 #
3894 333   100     1790 # Write the <c:minorGridlines> element.
3895             #
3896 333 100       1274  
3897 1         1 my $self = shift;
3898             my $gridlines = shift;
3899              
3900 333 100       1256 return unless $gridlines;
3901 1         3 return unless $gridlines->{_visible};
3902              
3903             if ( $gridlines->{_line}->{_defined} ) {
3904 333         1014 $self->xml_start_tag( 'c:minorGridlines' );
3905              
3906 333         1459 # Write the c:spPr element.
3907             $self->_write_sp_pr( $gridlines );
3908              
3909             $self->xml_end_tag( 'c:minorGridlines' );
3910             }
3911             else {
3912             $self->xml_empty_tag( 'c:minorGridlines' );
3913             }
3914             }
3915              
3916              
3917             ##############################################################################
3918 350     350   819 #
3919 350         679 # _write_cross_between()
3920             #
3921 350         1052 # Write the <c:crossBetween> element.
3922             #
3923 350         1316  
3924             my $self = shift;
3925              
3926             my $val = shift || $self->{_cross_between};
3927              
3928             my @attributes = ( 'val' => $val );
3929              
3930             $self->xml_empty_tag( 'c:crossBetween', @attributes );
3931             }
3932              
3933              
3934             ##############################################################################
3935 349     349   748 #
3936 349         637 # _write_c_major_unit()
3937             #
3938 349 100       1145 # Write the <c:majorUnit> element.
3939             #
3940 2         10  
3941             my $self = shift;
3942 2         7 my $val = shift;
3943              
3944             return unless $val;
3945              
3946             my @attributes = ( 'val' => $val );
3947              
3948             $self->xml_empty_tag( 'c:majorUnit', @attributes );
3949             }
3950              
3951              
3952             ##############################################################################
3953             #
3954 349     349   684 # _write_c_minor_unit()
3955 349         599 #
3956             # Write the <c:minorUnit> element.
3957 349 100       1066 #
3958              
3959 1         6 my $self = shift;
3960             my $val = shift;
3961 1         10  
3962             return unless $val;
3963              
3964             my @attributes = ( 'val' => $val );
3965              
3966             $self->xml_empty_tag( 'c:minorUnit', @attributes );
3967             }
3968              
3969              
3970             ##############################################################################
3971             #
3972             # _write_c_major_time_unit()
3973 763     763   1416 #
3974 763         1352 # Write the <c:majorTimeUnit> element.
3975             #
3976 763 100       2019  
3977 379 50       1443 my $self = shift;
3978             my $val = shift || 'days';
3979 379 100       1495  
3980 2         4 my @attributes = ( 'val' => $val );
3981              
3982             $self->xml_empty_tag( 'c:majorTimeUnit', @attributes );
3983 2         5 }
3984              
3985 2         4  
3986             ##############################################################################
3987             #
3988 377         1463 # _write_c_minor_time_unit()
3989             #
3990             # Write the <c:minorTimeUnit> element.
3991             #
3992              
3993             my $self = shift;
3994             my $val = shift || 'days';
3995              
3996             my @attributes = ( 'val' => $val );
3997              
3998             $self->xml_empty_tag( 'c:minorTimeUnit', @attributes );
3999             }
4000              
4001 762     762   1321  
4002 762         1561 ##############################################################################
4003             #
4004 762 100       1911 # _write_legend()
4005 9 50       25 #
4006             # Write the <c:legend> element.
4007 9 100       26 #
4008 2         6  
4009             my $self = shift;
4010             my $legend = $self->{_legend};
4011 2         5 my $position = $legend->{_position} || 'right';
4012             my $font = $legend->{_font};
4013 2         4 my @delete_series = ();
4014             my $overlay = 0;
4015              
4016 7         16 if ( defined $legend->{_delete_series}
4017             && ref $legend->{_delete_series} eq 'ARRAY' )
4018             {
4019             @delete_series = @{ $legend->{_delete_series} };
4020             }
4021              
4022             if ( $position =~ s/^overlay_// ) {
4023             $overlay = 1;
4024             }
4025              
4026             my %allowed = (
4027             right => 'r',
4028             left => 'l',
4029 413     413   933 top => 't',
4030             bottom => 'b',
4031 413   66     2449 top_right => 'tr',
4032             );
4033 413         1231  
4034             return if $position eq 'none';
4035 413         1637 return unless exists $allowed{$position};
4036              
4037             $position = $allowed{$position};
4038              
4039             $self->xml_start_tag( 'c:legend' );
4040              
4041             # Write the c:legendPos element.
4042             $self->_write_legend_pos( $position );
4043              
4044             # Remove series labels from the legend.
4045             for my $index ( @delete_series ) {
4046              
4047 430     430   939 # Write the c:legendEntry element.
4048 430         814 $self->_write_legend_entry( $index );
4049             }
4050 430 100       1345  
4051             # Write the c:layout element.
4052 6         15 $self->_write_layout( $legend->{_layout}, 'legend' );
4053              
4054 6         17 # Write the c:overlay element.
4055             $self->_write_overlay() if $overlay;
4056              
4057             # Write the c:spPr element.
4058             $self->_write_sp_pr( $legend );
4059              
4060             # Write the c:txPr element.
4061             if ( $font ) {
4062             $self->_write_tx_pr( $font );
4063             }
4064              
4065             $self->xml_end_tag( 'c:legend' );
4066 430     430   878 }
4067 430         791  
4068              
4069 430 100       1371 ##############################################################################
4070             #
4071 6         18 # _write_legend_pos()
4072             #
4073 6         17 # Write the <c:legendPos> element.
4074             #
4075              
4076             my $self = shift;
4077             my $val = shift;
4078              
4079             my @attributes = ( 'val' => $val );
4080              
4081             $self->xml_empty_tag( 'c:legendPos', @attributes );
4082             }
4083              
4084              
4085 3     3   5 ##############################################################################
4086 3   100     9 #
4087             # _write_legend_entry()
4088 3         8 #
4089             # Write the <c:legendEntry> element.
4090 3         8 #
4091              
4092             my $self = shift;
4093             my $index = shift;
4094              
4095             $self->xml_start_tag( 'c:legendEntry' );
4096              
4097             # Write the c:idx element.
4098             $self->_write_idx( $index );
4099              
4100             # Write the c:delete element.
4101             $self->_write_delete( 1 );
4102 3     3   5  
4103 3   100     19 $self->xml_end_tag( 'c:legendEntry' );
4104             }
4105 3         7  
4106              
4107 3         10 ##############################################################################
4108             #
4109             # _write_overlay()
4110             #
4111             # Write the <c:overlay> element.
4112             #
4113              
4114             my $self = shift;
4115             my $val = 1;
4116              
4117             my @attributes = ( 'val' => $val );
4118              
4119 381     381   776 $self->xml_empty_tag( 'c:overlay', @attributes );
4120 381         879 }
4121 381   100     2230  
4122 381         822  
4123 381         1184 ##############################################################################
4124 381         757 #
4125             # _write_plot_vis_only()
4126 381 100 66     1740 #
4127             # Write the <c:plotVisOnly> element.
4128             #
4129 4         9  
  4         10  
4130             my $self = shift;
4131             my $val = 1;
4132 381 100       1614  
4133 5         8 # Ignore this element if we are plotting hidden data.
4134             return if $self->{_show_hidden_data};
4135              
4136 381         2507 my @attributes = ( 'val' => $val );
4137              
4138             $self->xml_empty_tag( 'c:plotVisOnly', @attributes );
4139             }
4140              
4141              
4142             ##############################################################################
4143             #
4144 381 100       1434 # _write_print_settings()
4145 378 100       1431 #
4146             # Write the <c:printSettings> element.
4147 377         880 #
4148              
4149 377         1951 my $self = shift;
4150              
4151             $self->xml_start_tag( 'c:printSettings' );
4152 377         2528  
4153             # Write the c:headerFooter element.
4154             $self->_write_header_footer();
4155 377         1090  
4156             # Write the c:pageMargins element.
4157             $self->_write_page_margins();
4158 8         23  
4159             # Write the c:pageSetup element.
4160             $self->_write_page_setup();
4161              
4162 377         1703 $self->xml_end_tag( 'c:printSettings' );
4163             }
4164              
4165 377 100       1282  
4166             ##############################################################################
4167             #
4168 377         1734 # _write_header_footer()
4169             #
4170             # Write the <c:headerFooter> element.
4171 377 100       1132 #
4172 2         11  
4173             my $self = shift;
4174              
4175 377         1816 $self->xml_empty_tag( 'c:headerFooter' );
4176             }
4177              
4178              
4179             ##############################################################################
4180             #
4181             # _write_page_margins()
4182             #
4183             # Write the <c:pageMargins> element.
4184             #
4185              
4186             my $self = shift;
4187 434     434   990 my $b = 0.75;
4188 434         858 my $l = 0.7;
4189             my $r = 0.7;
4190 434         1193 my $t = 0.75;
4191             my $header = 0.3;
4192 434         1620 my $footer = 0.3;
4193              
4194             my @attributes = (
4195             'b' => $b,
4196             'l' => $l,
4197             'r' => $r,
4198             't' => $t,
4199             'header' => $header,
4200             'footer' => $footer,
4201             );
4202              
4203             $self->xml_empty_tag( 'c:pageMargins', @attributes );
4204 9     9   14 }
4205 9         14  
4206              
4207 9         25 ##############################################################################
4208             #
4209             # _write_page_setup()
4210 9         42 #
4211             # Write the <c:pageSetup> element.
4212             #
4213 9         35  
4214             my $self = shift;
4215 9         24  
4216             $self->xml_empty_tag( 'c:pageSetup' );
4217             }
4218              
4219              
4220             ##############################################################################
4221             #
4222             # _write_auto_title_deleted()
4223             #
4224             # Write the <c:autoTitleDeleted> element.
4225             #
4226              
4227 8     8   14 my $self = shift;
4228 8         11  
4229             my @attributes = ( 'val' => 1 );
4230 8         25  
4231             $self->xml_empty_tag( 'c:autoTitleDeleted', @attributes );
4232 8         25 }
4233              
4234              
4235             ##############################################################################
4236             #
4237             # _write_title_rich()
4238             #
4239             # Write the <c:title> element for a rich string.
4240             #
4241              
4242             my $self = shift;
4243             my $title = shift;
4244 427     427   894 my $is_y_axis = shift;
4245 427         835 my $font = shift;
4246             my $layout = shift;
4247             my $overlay = shift;
4248 427 100       1613  
4249             $self->xml_start_tag( 'c:title' );
4250 426         1272  
4251             # Write the c:tx element.
4252 426         1956 $self->_write_tx_rich( $title, $is_y_axis, $font );
4253              
4254             # Write the c:layout element.
4255             $self->_write_layout( $layout, 'text' );
4256              
4257             # Write the c:overlay element.
4258             $self->_write_overlay() if $overlay;
4259              
4260             $self->xml_end_tag( 'c:title' );
4261             }
4262              
4263              
4264 406     406   855 ##############################################################################
4265             #
4266 406         2006 # _write_title_formula()
4267             #
4268             # Write the <c:title> element for a rich string.
4269 406         2758 #
4270              
4271             my $self = shift;
4272 406         2285 my $title = shift;
4273             my $data_id = shift;
4274             my $is_y_axis = shift;
4275 406         2336 my $font = shift;
4276             my $layout = shift;
4277 406         1252 my $overlay = shift;
4278              
4279             $self->xml_start_tag( 'c:title' );
4280              
4281             # Write the c:tx element.
4282             $self->_write_tx_formula( $title, $data_id );
4283              
4284             # Write the c:layout element.
4285             $self->_write_layout( $layout, 'text' );
4286              
4287             # Write the c:overlay element.
4288             $self->_write_overlay() if $overlay;
4289 406     406   930  
4290             # Write the c:txPr element.
4291 406         1263 $self->_write_tx_pr( $font, $is_y_axis );
4292              
4293             $self->xml_end_tag( 'c:title' );
4294             }
4295              
4296              
4297             ##############################################################################
4298             #
4299             # _write_tx_rich()
4300             #
4301             # Write the <c:tx> element.
4302             #
4303 407     407   837  
4304 407         765 my $self = shift;
4305 407         738 my $title = shift;
4306 407         804 my $is_y_axis = shift;
4307 407         781 my $font = shift;
4308 407         731  
4309 407         656 $self->xml_start_tag( 'c:tx' );
4310              
4311 407         1831 # Write the c:rich element.
4312             $self->_write_rich( $title, $font, $is_y_axis );
4313              
4314             $self->xml_end_tag( 'c:tx' );
4315             }
4316              
4317              
4318             ##############################################################################
4319             #
4320 407         1443 # _write_tx_value()
4321             #
4322             # Write the <c:tx> element with a simple value such as for series names.
4323             #
4324              
4325             my $self = shift;
4326             my $title = shift;
4327              
4328             $self->xml_start_tag( 'c:tx' );
4329              
4330             # Write the c:v element.
4331             $self->_write_v( $title );
4332 407     407   835  
4333             $self->xml_end_tag( 'c:tx' );
4334 407         1341 }
4335              
4336              
4337             ##############################################################################
4338             #
4339             # _write_tx_formula()
4340             #
4341             # Write the <c:tx> element.
4342             #
4343              
4344             my $self = shift;
4345             my $title = shift;
4346 1     1   2 my $data_id = shift;
4347             my $data;
4348 1         2  
4349             if ( defined $data_id ) {
4350 1         2 $data = $self->{_formula_data}->[$data_id];
4351             }
4352              
4353             $self->xml_start_tag( 'c:tx' );
4354              
4355             # Write the c:strRef element.
4356             $self->_write_str_ref( $title, $data, 'str' );
4357              
4358             $self->xml_end_tag( 'c:tx' );
4359             }
4360              
4361              
4362 56     56   102 ##############################################################################
4363 56         116 #
4364 56         99 # _write_rich()
4365 56         151 #
4366 56         79 # Write the <c:rich> element.
4367 56         96 #
4368              
4369 56         165 my $self = shift;
4370             my $title = shift;
4371             my $font = shift;
4372 56         250 my $is_y_axis = shift;
4373             my $ignore_rich_pr = shift;
4374              
4375 56         198 my $rotation = undef;
4376              
4377             if ( $font && exists $font->{_rotation} ) {
4378 56 100       162 $rotation = $font->{_rotation};
4379             }
4380 56         136  
4381             $self->xml_start_tag( 'c:rich' );
4382              
4383             # Write the a:bodyPr element.
4384             $self->_write_a_body_pr( $rotation, $is_y_axis );
4385              
4386             # Write the a:lstStyle element.
4387             $self->_write_a_lst_style();
4388              
4389             # Write the a:p element.
4390             $self->_write_a_p_rich( $title, $font, $ignore_rich_pr );
4391              
4392 14     14   27 $self->xml_end_tag( 'c:rich' );
4393 14         23 }
4394 14         21  
4395 14         31  
4396 14         24 ##############################################################################
4397 14         21 #
4398 14         18 # _write_a_body_pr()
4399             #
4400 14         50 # Write the <a:bodyPr> element.
4401              
4402             my $self = shift;
4403 14         62 my $rot = shift;
4404             my $is_y_axis = shift;
4405              
4406 14         69 my @attributes = ();
4407              
4408             if ( !defined $rot && $is_y_axis ) {
4409 14 100       49 $rot = -5400000;
4410             }
4411              
4412 14         61 if (defined $rot) {
4413             if ($rot == 16_200_000) {
4414 14         35 # 270 deg/stacked angle.
4415             push @attributes, ( 'rot' => 0 );
4416             push @attributes, ( 'vert' => 'wordArtVert' );
4417              
4418             }
4419             elsif ($rot == 16_260_000) {
4420             # 271 deg/East Asian vertical.
4421             push @attributes, ( 'rot' => 0 );
4422             push @attributes, ( 'vert' => 'eaVert' );
4423              
4424             }
4425             else {
4426 56     56   91 push @attributes, ( 'rot' => $rot );
4427 56         105 push @attributes, ( 'vert' => 'horz' );
4428 56         85 }
4429 56         83 }
4430              
4431 56         153 $self->xml_empty_tag( 'a:bodyPr', @attributes );
4432             }
4433              
4434 56         240  
4435             ##############################################################################
4436 56         124 #
4437             # _write_a_lst_style()
4438             #
4439             # Write the <a:lstStyle> element.
4440             #
4441              
4442             my $self = shift;
4443              
4444             $self->xml_empty_tag( 'a:lstStyle' );
4445             }
4446              
4447              
4448 2     2   3 ##############################################################################
4449 2         3 #
4450             # _write_a_p_rich()
4451 2         5 #
4452             # Write the <a:p> element for rich string titles.
4453             #
4454 2         7  
4455             my $self = shift;
4456 2         6 my $title = shift;
4457             my $font = shift;
4458             my $ignore_rich_pr = shift;
4459              
4460             $self->xml_start_tag( 'a:p' );
4461              
4462             # Write the a:pPr element.
4463             if ( !$ignore_rich_pr ) {
4464             $self->_write_a_p_pr_rich( $font );
4465             }
4466              
4467             # Write the a:r element.
4468 25     25   43 $self->_write_a_r( $title, $font );
4469 25         47  
4470 25         41 $self->xml_end_tag( 'a:p' );
4471 25         32 }
4472              
4473 25 50       63  
4474 25         58 ##############################################################################
4475             #
4476             # _write_a_p_formula()
4477 25         65 #
4478             # Write the <a:p> element for formula titles.
4479             #
4480 25         124  
4481             my $self = shift;
4482 25         58 my $font = shift;
4483              
4484             $self->xml_start_tag( 'a:p' );
4485              
4486             # Write the a:pPr element.
4487             $self->_write_a_p_pr_formula( $font );
4488              
4489             # Write the a:endParaRPr element.
4490             $self->_write_a_end_para_rpr();
4491              
4492             $self->xml_end_tag( 'a:p' );
4493             }
4494 65     65   136  
4495 65         114  
4496 65         101 ##############################################################################
4497 65         100 #
4498 65         108 # _write_a_p_pr_rich()
4499             #
4500 65         115 # Write the <a:pPr> element for rich string titles.
4501             #
4502 65 50 66     245  
4503 21         42 my $self = shift;
4504             my $font = shift;
4505              
4506 65         187 $self->xml_start_tag( 'a:pPr' );
4507              
4508             # Write the a:defRPr element.
4509 65         302 $self->_write_a_def_rpr( $font );
4510              
4511             $self->xml_end_tag( 'a:pPr' );
4512 65         310 }
4513              
4514              
4515 65         276 ##############################################################################
4516             #
4517 65         165 # _write_a_p_pr_formula()
4518             #
4519             # Write the <a:pPr> element for formula titles.
4520             #
4521              
4522             my $self = shift;
4523             my $font = shift;
4524              
4525             $self->xml_start_tag( 'a:pPr' );
4526              
4527             # Write the a:defRPr element.
4528 175     175   318 $self->_write_a_def_rpr( $font );
4529 175         329  
4530 175         303 $self->xml_end_tag( 'a:pPr' );
4531             }
4532 175         333  
4533              
4534 175 100 100     870 ##############################################################################
4535 18         42 #
4536             # _write_a_def_rpr()
4537             #
4538 175 100       469 # Write the <a:defRPr> element.
4539 43 100       216 #
    100          
4540              
4541 4         6 my $self = shift;
4542 4         6 my $font = shift;
4543             my $has_color = 0;
4544              
4545             my @style_attributes = $self->_get_font_style_attributes( $font );
4546             my @latin_attributes = $self->_get_font_latin_attributes( $font );
4547 4         13  
4548 4         13 $has_color = 1 if $font && $font->{_color};
4549              
4550             if ( @latin_attributes || $has_color ) {
4551             $self->xml_start_tag( 'a:defRPr', @style_attributes );
4552 35         91  
4553 35         110  
4554             if ( $has_color ) {
4555             $self->_write_a_solid_fill( { color => $font->{_color} } );
4556             }
4557 175         571  
4558             if ( @latin_attributes ) {
4559             $self->_write_a_latin( @latin_attributes );
4560             }
4561              
4562             $self->xml_end_tag( 'a:defRPr' );
4563             }
4564             else {
4565             $self->xml_empty_tag( 'a:defRPr', @style_attributes );
4566             }
4567             }
4568              
4569 175     175   349  
4570             ##############################################################################
4571 175         451 #
4572             # _write_a_end_para_rpr()
4573             #
4574             # Write the <a:endParaRPr> element.
4575             #
4576              
4577             my $self = shift;
4578             my $lang = 'en-US';
4579              
4580             my @attributes = ( 'lang' => $lang );
4581              
4582             $self->xml_empty_tag( 'a:endParaRPr', @attributes );
4583 65     65   114 }
4584 65         100  
4585 65         91  
4586 65         106 ##############################################################################
4587             #
4588 65         201 # _write_a_r()
4589             #
4590             # Write the <a:r> element.
4591 65 100       170 #
4592 58         232  
4593             my $self = shift;
4594             my $title = shift;
4595             my $font = shift;
4596 65         336  
4597             $self->xml_start_tag( 'a:r' );
4598 65         153  
4599             # Write the a:rPr element.
4600             $self->_write_a_r_pr( $font );
4601              
4602             # Write the a:t element.
4603             $self->_write_a_t( $title );
4604              
4605             $self->xml_end_tag( 'a:r' );
4606             }
4607              
4608              
4609             ##############################################################################
4610 26     26   51 #
4611 26         44 # _write_a_r_pr()
4612             #
4613 26         84 # Write the <a:rPr> element.
4614             #
4615              
4616 26         146 my $self = shift;
4617             my $font = shift;
4618             my $has_color = 0;
4619 26         138 my $lang = 'en-US';
4620              
4621 26         76 my @style_attributes = $self->_get_font_style_attributes( $font );
4622             my @latin_attributes = $self->_get_font_latin_attributes( $font );
4623              
4624             $has_color = 1 if $font && $font->{_color};
4625              
4626             # Add the lang type to the attributes.
4627             @style_attributes = ( 'lang' => $lang, @style_attributes );
4628              
4629              
4630             if ( @latin_attributes || $has_color ) {
4631             $self->xml_start_tag( 'a:rPr', @style_attributes );
4632              
4633 86     86   150  
4634 86         143 if ( $has_color ) {
4635             $self->_write_a_solid_fill( { color => $font->{_color} } );
4636 86         230 }
4637              
4638             if ( @latin_attributes ) {
4639 86         415 $self->_write_a_latin( @latin_attributes );
4640             }
4641 86         275  
4642             $self->xml_end_tag( 'a:rPr' );
4643             }
4644             else {
4645             $self->xml_empty_tag( 'a:rPr', @style_attributes );
4646             }
4647              
4648              
4649             }
4650              
4651              
4652             ##############################################################################
4653 26     26   52 #
4654 26         41 # _write_a_t()
4655             #
4656 26         73 # Write the <a:t> element.
4657             #
4658              
4659 26         126 my $self = shift;
4660             my $title = shift;
4661 26         73  
4662             $self->xml_data_element( 'a:t', $title );
4663             }
4664              
4665              
4666             ##############################################################################
4667             #
4668             # _write_tx_pr()
4669             #
4670             # Write the <c:txPr> element.
4671             #
4672              
4673 168     168   299 my $self = shift;
4674 168         262 my $font = shift;
4675 168         260 my $is_y_axis = shift;
4676             my $rotation = undef;
4677 168         704  
4678 168         815 if ( $font && exists $font->{_rotation} ) {
4679             $rotation = $font->{_rotation};
4680 168 100 100     642 }
4681              
4682 168 100 100     781 $self->xml_start_tag( 'c:txPr' );
4683 17         75  
4684             # Write the a:bodyPr element.
4685             $self->_write_a_body_pr( $rotation, $is_y_axis );
4686 17 100       38  
4687 12         65 # Write the a:lstStyle element.
4688             $self->_write_a_lst_style();
4689              
4690 17 100       63 # Write the a:p element.
4691 9         53 $self->_write_a_p_formula( $font );
4692              
4693             $self->xml_end_tag( 'c:txPr' );
4694 17         60 }
4695              
4696              
4697 151         478 ##############################################################################
4698             #
4699             # _write_marker()
4700             #
4701             # Write the <c:marker> element.
4702             #
4703              
4704             my $self = shift;
4705             my $marker = shift || $self->{_default_marker};
4706              
4707             return unless $marker;
4708             return if $marker->{automatic};
4709              
4710 110     110   199 $self->xml_start_tag( 'c:marker' );
4711 110         194  
4712             # Write the c:symbol element.
4713 110         247 $self->_write_symbol( $marker->{type} );
4714              
4715 110         311 # Write the c:size element.
4716             my $size = $marker->{size};
4717             $self->_write_marker_size( $size ) if $size;
4718              
4719             # Write the c:spPr element.
4720             $self->_write_sp_pr( $marker );
4721              
4722             $self->xml_end_tag( 'c:marker' );
4723             }
4724              
4725              
4726             ##############################################################################
4727 65     65   106 #
4728 65         106 # _write_marker_size()
4729 65         102 #
4730             # Write the <c:size> element.
4731 65         171 #
4732              
4733             my $self = shift;
4734 65         260 my $val = shift;
4735              
4736             my @attributes = ( 'val' => $val );
4737 65         277  
4738             $self->xml_empty_tag( 'c:size', @attributes );
4739 65         192 }
4740              
4741              
4742             ##############################################################################
4743             #
4744             # _write_symbol()
4745             #
4746             # Write the <c:symbol> element.
4747             #
4748              
4749             my $self = shift;
4750             my $val = shift;
4751 65     65   106  
4752 65         88 my @attributes = ( 'val' => $val );
4753 65         119  
4754 65         106 $self->xml_empty_tag( 'c:symbol', @attributes );
4755             }
4756 65         172  
4757 65         165  
4758             ##############################################################################
4759 65 100 100     251 #
4760             # _write_sp_pr()
4761             #
4762 65         157 # Write the <c:spPr> element.
4763             #
4764              
4765 65 100 100     322 my $self = shift;
4766 4         11 my $series = shift;
4767              
4768             return if !_has_fill_formatting($series);
4769 4 50       7  
4770 4         15 $self->xml_start_tag( 'c:spPr' );
4771              
4772             # Write the fill elements for solid charts such as pie/doughnut and bar.
4773 4 100       10 if ( $series->{_fill}->{_defined} ) {
4774 3         5  
4775             if ( $series->{_fill}->{none} ) {
4776              
4777 4         10 # Write the a:noFill element.
4778             $self->_write_a_no_fill();
4779             }
4780 61         165 else {
4781             # Write the a:solidFill element.
4782             $self->_write_a_solid_fill( $series->{_fill} );
4783             }
4784             }
4785              
4786             if ( $series->{_pattern} ) {
4787              
4788             # Write the a:pattFill element.
4789             $self->_write_a_patt_fill( $series->{_pattern} );
4790             }
4791              
4792             if ( $series->{_gradient} ) {
4793              
4794             # Write the a:gradFill element.
4795 65     65   122 $self->_write_a_grad_fill( $series->{_gradient} );
4796 65         104 }
4797              
4798 65         269  
4799             # Write the a:ln element.
4800             if ( $series->{_line}->{_defined} ) {
4801             $self->_write_a_ln( $series->{_line} );
4802             }
4803              
4804             $self->xml_end_tag( 'c:spPr' );
4805             }
4806              
4807              
4808             ##############################################################################
4809             #
4810 26     26   89 # _write_a_ln()
4811 26         48 #
4812 26         40 # Write the <a:ln> element.
4813 26         39 #
4814              
4815 26 50 66     118 my $self = shift;
4816 15         25 my $line = shift;
4817             my @attributes = ();
4818              
4819 26         80 # Add the line width as an attribute.
4820             if ( my $width = $line->{width} ) {
4821              
4822 26         121 # Round width to nearest 0.25, like Excel.
4823             $width = int( ( $width + 0.125 ) * 4 ) / 4;
4824              
4825 26         141 # Convert to internal units.
4826             $width = int( 0.5 + ( 12700 * $width ) );
4827              
4828 26         120 @attributes = ( 'w' => $width );
4829             }
4830 26         80  
4831             $self->xml_start_tag( 'a:ln', @attributes );
4832              
4833             # Write the line fill.
4834             if ( $line->{none} ) {
4835              
4836             # Write the a:noFill element.
4837             $self->_write_a_no_fill();
4838             }
4839             elsif ( $line->{color} ) {
4840              
4841             # Write the a:solidFill element.
4842 1033     1033   1692 $self->_write_a_solid_fill( $line );
4843 1033   100     3611 }
4844              
4845 1033 100       2350 # Write the line/dash type.
4846 274 100       660 if ( my $type = $line->{dash_type} ) {
4847              
4848 268         759 # Write the a:prstDash element.
4849             $self->_write_a_prst_dash( $type );
4850             }
4851 268         1052  
4852             $self->xml_end_tag( 'a:ln' );
4853             }
4854 268         479  
4855 268 100       643  
4856             ##############################################################################
4857             #
4858 268         691 # _write_a_no_fill()
4859             #
4860 268         947 # Write the <a:noFill> element.
4861             #
4862              
4863             my $self = shift;
4864              
4865             $self->xml_empty_tag( 'a:noFill' );
4866             }
4867              
4868              
4869             ##############################################################################
4870             #
4871             # _write_a_solid_fill()
4872 17     17   52 #
4873 17         34 # Write the <a:solidFill> element.
4874             #
4875 17         42  
4876             my $self = shift;
4877 17         52 my $fill = shift;
4878              
4879             $self->xml_start_tag( 'a:solidFill' );
4880              
4881             if ( $fill->{color} ) {
4882              
4883             my $color = $self->_get_color( $fill->{color} );
4884              
4885             # Write the a:srgbClr element.
4886             $self->_write_a_srgb_clr( $color, $fill->{transparency} );
4887             }
4888              
4889 269     269   401 $self->xml_end_tag( 'a:solidFill' );
4890 269         403 }
4891              
4892 269         581  
4893             ##############################################################################
4894 269         687 #
4895             # _write_a_srgb_clr()
4896             #
4897             # Write the <a:srgbClr> element.
4898             #
4899              
4900             my $self = shift;
4901             my $color = shift;
4902             my $transparency = shift;
4903              
4904             my @attributes = ( 'val' => $color );
4905              
4906 3508     3508   4774 if ( $transparency ) {
4907 3508         4210 $self->xml_start_tag( 'a:srgbClr', @attributes );
4908              
4909 3508 100       6395 # Write the a:alpha element.
4910             $self->_write_a_alpha( $transparency );
4911 235         797  
4912             $self->xml_end_tag( 'a:srgbClr' );
4913             }
4914 235 100       717 else {
4915             $self->xml_empty_tag( 'a:srgbClr', @attributes );
4916 51 100       177 }
4917             }
4918              
4919 6         24  
4920             ##############################################################################
4921             #
4922             # _write_a_alpha()
4923 45         224 #
4924             # Write the <a:alpha> element.
4925             #
4926              
4927 235 100       643 my $self = shift;
4928             my $val = shift;
4929              
4930 59         150 $val = ( 100 - int( $val ) ) * 1000;
4931              
4932             my @attributes = ( 'val' => $val );
4933 235 100       666  
4934             $self->xml_empty_tag( 'a:alpha', @attributes );
4935             }
4936 14         94  
4937              
4938             ##############################################################################
4939             #
4940             # _write_a_prst_dash()
4941 235 100       734 #
4942 141         658 # Write the <a:prstDash> element.
4943             #
4944              
4945 235         565 my $self = shift;
4946             my $val = shift;
4947              
4948             my @attributes = ( 'val' => $val );
4949              
4950             $self->xml_empty_tag( 'a:prstDash', @attributes );
4951             }
4952              
4953              
4954             ##############################################################################
4955             #
4956             # _write_trendline()
4957 141     141   277 #
4958 141         251 # Write the <c:trendline> element.
4959 141         272 #
4960              
4961             my $self = shift;
4962 141 100       426 my $trendline = shift;
4963              
4964             return unless $trendline;
4965 92         343  
4966             $self->xml_start_tag( 'c:trendline' );
4967              
4968 92         187 # Write the c:name element.
4969             $self->_write_name( $trendline->{name} );
4970 92         204  
4971             # Write the c:spPr element.
4972             $self->_write_sp_pr( $trendline );
4973 141         527  
4974             # Write the c:trendlineType element.
4975             $self->_write_trendline_type( $trendline->{type} );
4976 141 100       487  
    100          
4977             # Write the c:order element for polynomial trendlines.
4978             if ( $trendline->{type} eq 'poly' ) {
4979 86         283 $self->_write_trendline_order( $trendline->{order} );
4980             }
4981              
4982             # Write the c:period element for moving average trendlines.
4983             if ( $trendline->{type} eq 'movingAvg' ) {
4984 49         252 $self->_write_period( $trendline->{period} );
4985             }
4986              
4987             # Write the c:forward element.
4988 141 100       497 $self->_write_forward( $trendline->{forward} );
4989              
4990             # Write the c:backward element.
4991 28         141 $self->_write_backward( $trendline->{backward} );
4992              
4993             if ( defined $trendline->{intercept} ) {
4994 141         423 # Write the c:intercept element.
4995             $self->_write_intercept( $trendline->{intercept} );
4996             }
4997              
4998             if ($trendline->{display_r_squared}) {
4999             # Write the c:dispRSqr element.
5000             $self->_write_disp_rsqr();
5001             }
5002              
5003             if ($trendline->{display_equation}) {
5004             # Write the c:dispEq element.
5005             $self->_write_disp_eq();
5006 92     92   148  
5007             # Write the c:trendlineLbl element.
5008 92         215 $self->_write_trendline_lbl();
5009             }
5010              
5011             $self->xml_end_tag( 'c:trendline' );
5012             }
5013              
5014              
5015             ##############################################################################
5016             #
5017             # _write_trendline_type()
5018             #
5019             # Write the <c:trendlineType> element.
5020 110     110   189 #
5021 110         182  
5022             my $self = shift;
5023 110         312 my $val = shift;
5024              
5025 110 50       333 my @attributes = ( 'val' => $val );
5026              
5027 110         479 $self->xml_empty_tag( 'c:trendlineType', @attributes );
5028             }
5029              
5030 110         527  
5031             ##############################################################################
5032             #
5033 110         420 # _write_name()
5034             #
5035             # Write the <c:name> element.
5036             #
5037              
5038             my $self = shift;
5039             my $data = shift;
5040              
5041             return unless defined $data;
5042              
5043             $self->xml_data_element( 'c:name', $data );
5044             }
5045 269     269   399  
5046 269         387  
5047 269         414 ##############################################################################
5048             #
5049 269         502 # _write_trendline_order()
5050             #
5051 269 100       563 # Write the <c:order> element.
5052 6         38 #
5053              
5054             my $self = shift;
5055 6         50 my $val = defined $_[0] ? $_[0] : 2;
5056              
5057 6         27 my @attributes = ( 'val' => $val );
5058              
5059             $self->xml_empty_tag( 'c:order', @attributes );
5060 263         703 }
5061              
5062              
5063             ##############################################################################
5064             #
5065             # _write_period()
5066             #
5067             # Write the <c:period> element.
5068             #
5069              
5070             my $self = shift;
5071             my $val = defined $_[0] ? $_[0] : 2;
5072              
5073 6     6   12 my @attributes = ( 'val' => $val );
5074 6         11  
5075             $self->xml_empty_tag( 'c:period', @attributes );
5076 6         15 }
5077              
5078 6         16  
5079             ##############################################################################
5080 6         22 #
5081             # _write_forward()
5082             #
5083             # Write the <c:forward> element.
5084             #
5085              
5086             my $self = shift;
5087             my $val = shift;
5088              
5089             return unless $val;
5090              
5091             my @attributes = ( 'val' => $val );
5092 28     28   67  
5093 28         48 $self->xml_empty_tag( 'c:forward', @attributes );
5094             }
5095 28         66  
5096              
5097 28         99 ##############################################################################
5098             #
5099             # _write_backward()
5100             #
5101             # Write the <c:backward> element.
5102             #
5103              
5104             my $self = shift;
5105             my $val = shift;
5106              
5107             return unless $val;
5108              
5109 1032     1032   1544 my @attributes = ( 'val' => $val );
5110 1032         1470  
5111             $self->xml_empty_tag( 'c:backward', @attributes );
5112 1032 100       2264 }
5113              
5114 13         49  
5115             ##############################################################################
5116             #
5117 13         84 # _write_intercept()
5118             #
5119             # Write the <c:intercept> element.
5120 13         60 #
5121              
5122             my $self = shift;
5123 13         79 my $val = shift;
5124              
5125             my @attributes = ( 'val' => $val );
5126 13 100       57  
5127 4         29 $self->xml_empty_tag( 'c:intercept', @attributes );
5128             }
5129              
5130              
5131 13 100       48 ##############################################################################
5132 1         6 #
5133             # _write_disp_eq()
5134             #
5135             # Write the <c:dispEq> element.
5136 13         119 #
5137              
5138             my $self = shift;
5139 13         102  
5140             my @attributes = ( 'val' => 1 );
5141 13 100       41  
5142             $self->xml_empty_tag( 'c:dispEq', @attributes );
5143 2         10 }
5144              
5145              
5146 13 100       42 ##############################################################################
5147             #
5148 4         22 # _write_disp_rsqr()
5149             #
5150             # Write the <c:dispRSqr> element.
5151 13 100       47 #
5152              
5153 6         38 my $self = shift;
5154              
5155             my @attributes = ( 'val' => 1 );
5156 6         38  
5157             $self->xml_empty_tag( 'c:dispRSqr', @attributes );
5158             }
5159 13         57  
5160             ##############################################################################
5161             #
5162             # _write_trendline_lbl()
5163             #
5164             # Write the <c:trendlineLbl> element.
5165             #
5166              
5167             my $self = shift;
5168              
5169             $self->xml_start_tag( 'c:trendlineLbl' );
5170              
5171 13     13   26 # Write the c:layout element.
5172 13         23 $self->_write_layout();
5173              
5174 13         47 # Write the c:numFmt element.
5175             $self->_write_trendline_num_fmt();
5176 13         53  
5177             $self->xml_end_tag( 'c:trendlineLbl' );
5178             }
5179              
5180             ##############################################################################
5181             #
5182             # _write_trendline_num_fmt()
5183             #
5184             # Write the <c:numFmt> element.
5185             #
5186              
5187             my $self = shift;
5188 13     13   27 my $format_code = 'General';
5189 13         30 my $source_linked = 0;
5190              
5191 13 100       39 my @attributes = (
5192             'formatCode' => $format_code,
5193 4         20 'sourceLinked' => $source_linked,
5194             );
5195              
5196             $self->xml_empty_tag( 'c:numFmt', @attributes );
5197             }
5198              
5199             ##############################################################################
5200             #
5201             # _write_hi_low_lines()
5202             #
5203             # Write the <c:hiLowLines> element.
5204             #
5205 4     4   15  
5206 4 50       33 my $self = shift;
5207              
5208 4         12 my $hi_low_lines = $self->{_hi_low_lines};
5209              
5210 4         15 return unless $hi_low_lines;
5211              
5212             if ( $hi_low_lines->{_line}->{_defined} ) {
5213              
5214             $self->xml_start_tag( 'c:hiLowLines' );
5215              
5216             # Write the c:spPr element.
5217             $self->_write_sp_pr( $hi_low_lines );
5218              
5219             $self->xml_end_tag( 'c:hiLowLines' );
5220             }
5221             else {
5222 1     1   2 $self->xml_empty_tag( 'c:hiLowLines' );
5223 1 50       8 }
5224             }
5225 1         3  
5226              
5227 1         3 #############################################################################
5228             #
5229             # _write_drop_lines()
5230             #
5231             # Write the <c:dropLines> element.
5232             #
5233              
5234             my $self = shift;
5235              
5236             my $drop_lines = $self->{_drop_lines};
5237              
5238             return unless $drop_lines;
5239 13     13   35  
5240 13         26 if ( $drop_lines->{_line}->{_defined} ) {
5241              
5242 13 100       46 $self->xml_start_tag( 'c:dropLines' );
5243              
5244 4         14 # Write the c:spPr element.
5245             $self->_write_sp_pr( $drop_lines );
5246 4         13  
5247             $self->xml_end_tag( 'c:dropLines' );
5248             }
5249             else {
5250             $self->xml_empty_tag( 'c:dropLines' );
5251             }
5252             }
5253              
5254              
5255             ##############################################################################
5256             #
5257             # _write_overlap()
5258 13     13   28 #
5259 13         24 # Write the <c:overlap> element.
5260             #
5261 13 100       34  
5262             my $self = shift;
5263 4         11 my $val = shift;
5264              
5265 4         12 return if !defined $val;
5266              
5267             my @attributes = ( 'val' => $val );
5268              
5269             $self->xml_empty_tag( 'c:overlap', @attributes );
5270             }
5271              
5272              
5273             ##############################################################################
5274             #
5275             # _write_num_cache()
5276             #
5277 2     2   6 # Write the <c:numCache> element.
5278 2         3 #
5279              
5280 2         7 my $self = shift;
5281             my $data = shift;
5282 2         6 my $count = 0;
5283              
5284             if (defined $data) {
5285             $count = @$data;
5286             }
5287              
5288             $self->xml_start_tag( 'c:numCache' );
5289              
5290             # Write the c:formatCode element.
5291             $self->_write_format_code( 'General' );
5292              
5293             # Write the c:ptCount element.
5294 6     6   11 $self->_write_pt_count( $count );
5295              
5296 6         14 for my $i ( 0 .. $count - 1 ) {
5297             my $token = $data->[$i];
5298 6         18  
5299             # Write non-numeric data as 0.
5300             if ( defined $token
5301             && $token !~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/ )
5302             {
5303             $token = 0;
5304             }
5305              
5306             # Write the c:pt element.
5307             $self->_write_pt( $i, $token );
5308             }
5309              
5310 4     4   9 $self->xml_end_tag( 'c:numCache' );
5311             }
5312 4         11  
5313              
5314 4         18 ##############################################################################
5315             #
5316             # _write_str_cache()
5317             #
5318             # Write the <c:strCache> element.
5319             #
5320              
5321             my $self = shift;
5322             my $data = shift;
5323             my $count = @$data;
5324              
5325 6     6   14 $self->xml_start_tag( 'c:strCache' );
5326              
5327 6         21 # Write the c:ptCount element.
5328             $self->_write_pt_count( $count );
5329              
5330 6         22 for my $i ( 0 .. $count - 1 ) {
5331              
5332             # Write the c:pt element.
5333 6         42 $self->_write_pt( $i, $data->[$i] );
5334             }
5335 6         20  
5336             $self->xml_end_tag( 'c:strCache' );
5337             }
5338              
5339              
5340             ##############################################################################
5341             #
5342             # _write_format_code()
5343             #
5344             # Write the <c:formatCode> element.
5345             #
5346 6     6   10  
5347 6         11 my $self = shift;
5348 6         23 my $data = shift;
5349              
5350 6         21 $self->xml_data_element( 'c:formatCode', $data );
5351             }
5352              
5353              
5354             ##############################################################################
5355 6         18 #
5356             # _write_pt_count()
5357             #
5358             # Write the <c:ptCount> element.
5359             #
5360              
5361             my $self = shift;
5362             my $val = shift;
5363              
5364             my @attributes = ( 'val' => $val );
5365              
5366 105     105   271 $self->xml_empty_tag( 'c:ptCount', @attributes );
5367             }
5368 105         323  
5369              
5370 105 100       365 ##############################################################################
5371             #
5372 14 100       66 # _write_pt()
5373             #
5374 1         4 # Write the <c:pt> element.
5375             #
5376              
5377 1         4 my $self = shift;
5378             my $idx = shift;
5379 1         3 my $value = shift;
5380              
5381             return if !defined $value;
5382 13         51  
5383             my @attributes = ( 'idx' => $idx );
5384              
5385             $self->xml_start_tag( 'c:pt', @attributes );
5386              
5387             # Write the c:v element.
5388             $self->_write_v( $value );
5389              
5390             $self->xml_end_tag( 'c:pt' );
5391             }
5392              
5393              
5394             ##############################################################################
5395 117     117   304 #
5396             # _write_v()
5397 117         308 #
5398             # Write the <c:v> element.
5399 117 100       504 #
5400              
5401 4 100       30 my $self = shift;
5402             my $data = shift;
5403 1         5  
5404             $self->xml_data_element( 'c:v', $data );
5405             }
5406 1         5  
5407              
5408 1         4 ##############################################################################
5409             #
5410             # _write_protection()
5411 3         10 #
5412             # Write the <c:protection> element.
5413             #
5414              
5415             my $self = shift;
5416              
5417             return unless $self->{_protection};
5418              
5419             $self->xml_empty_tag( 'c:protection' );
5420             }
5421              
5422              
5423             ##############################################################################
5424 228     228   522 #
5425 228         527 # _write_d_pt()
5426             #
5427 228 100       954 # Write the <c:dPt> elements.
5428             #
5429 12         31  
5430             my $self = shift;
5431 12         35 my $points = shift;
5432             my $index = -1;
5433              
5434             return unless $points;
5435              
5436             for my $point ( @$points ) {
5437              
5438             $index++;
5439             next unless $point;
5440              
5441             $self->_write_d_pt_point( $index, $point );
5442             }
5443 1278     1278   1913 }
5444 1278         1794  
5445 1278         1788  
5446             ##############################################################################
5447 1278 50       2839 #
5448 1278         2099 # _write_d_pt_point()
5449             #
5450             # Write an individual <c:dPt> element.
5451 1278         3221 #
5452              
5453             my $self = shift;
5454 1278         4095 my $index = shift;
5455             my $point = shift;
5456              
5457 1278         3870 $self->xml_start_tag( 'c:dPt' );
5458              
5459 1278         3438 # Write the c:idx element.
5460 6188         8812 $self->_write_idx( $index );
5461              
5462             # Write the c:spPr element.
5463 6188 100 100     30938 $self->_write_sp_pr( $point );
5464              
5465             $self->xml_end_tag( 'c:dPt' );
5466 3         6  
5467             }
5468              
5469              
5470 6188         12085 ##############################################################################
5471             #
5472             # _write_d_lbls()
5473 1278         2865 #
5474             # Write the <c:dLbls> element.
5475             #
5476              
5477             my $self = shift;
5478             my $labels = shift;
5479              
5480             return unless $labels;
5481              
5482             $self->xml_start_tag( 'c:dLbls' );
5483              
5484             # Write the custom c:dLbl elements.
5485 44     44   87 if ( $labels->{custom} ) {
5486 44         74 $self->_write_custom_labels( $labels, $labels->{custom} );
5487 44         76 }
5488              
5489 44         128 # Write the c:numFmt element.
5490             if ( $labels->{num_format} ) {
5491             $self->_write_data_label_number_format( $labels->{num_format} );
5492 44         166 }
5493              
5494 44         178 # Write the c:spPr element.
5495             $self->_write_sp_pr( $labels );
5496              
5497 74         228 # Write the data label font elements.
5498             if ($labels->{font} ) {
5499             $self->_write_axis_font( $labels->{font} );
5500 44         121 }
5501              
5502             # Write the c:dLblPos element.
5503             $self->_write_d_lbl_pos( $labels->{position} ) if $labels->{position};
5504              
5505             # Write the c:showLegendKey element.
5506             $self->_write_show_legend_key() if $labels->{legend_key};
5507              
5508             # Write the c:showVal element.
5509             $self->_write_show_val() if $labels->{value};
5510              
5511             # Write the c:showCatName element.
5512 1283     1283   1852 $self->_write_show_cat_name() if $labels->{category};
5513 1283         1762  
5514             # Write the c:showSerName element.
5515 1283         2835 $self->_write_show_ser_name() if $labels->{series_name};
5516              
5517             # Write the c:showPercent element.
5518             $self->_write_show_percent() if $labels->{percentage};
5519              
5520             # Write the c:separator element.
5521             $self->_write_separator($labels->{separator}) if $labels->{separator};
5522              
5523             # Write the c:showLeaderLines element.
5524             $self->_write_show_leader_lines() if $labels->{leader_lines};
5525              
5526             $self->xml_end_tag( 'c:dLbls' );
5527 1330     1330   1868 }
5528 1330         1881  
5529              
5530 1330         2678 ##############################################################################
5531             #
5532 1330         2972 # _write_custom_labels()
5533             #
5534             # Write the <c:dLbl> element.
5535             #
5536              
5537             my $self = shift;
5538             my $parent = shift;
5539             my $labels = shift;
5540             my $index = 0;
5541              
5542             for my $label ( @$labels ) {
5543             $index++;
5544 6301     6301   7401 next if !defined $label;
5545 6301         6704  
5546 6301         7072 $self->xml_start_tag( 'c:dLbl' );
5547              
5548 6301 100       9883 # Write the c:idx element.
5549             $self->_write_idx( $index - 1 );
5550 6283         9432  
5551             if ( defined $label->{delete} && $label->{delete} ) {
5552 6283         13181 $self->_write_delete( 1 );
5553             }
5554             elsif ( defined $label->{formula} ) {
5555 6283         13280 $self->_write_custom_label_formula( $label );
5556              
5557 6283         11780 if ( $parent->{position} ) {
5558             $self->_write_d_lbl_pos( $parent->{position} );
5559             }
5560              
5561             $self->_write_show_val() if $parent->{value};
5562             $self->_write_show_cat_name() if $parent->{category};
5563             $self->_write_show_ser_name() if $parent->{series_name};
5564             }
5565             elsif ( defined $label->{value} ) {
5566             $self->_write_custom_label_str( $label );
5567              
5568             if ( $parent->{position} ) {
5569 6286     6286   7348 $self->_write_d_lbl_pos( $parent->{position} );
5570 6286         7012 }
5571              
5572 6286         10314 $self->_write_show_val() if $parent->{value};
5573             $self->_write_show_cat_name() if $parent->{category};
5574             $self->_write_show_ser_name() if $parent->{series_name};
5575             }
5576             else {
5577             $self->_write_custom_label_format_only( $label );
5578             }
5579              
5580             $self->xml_end_tag( 'c:dLbl' );
5581             }
5582             }
5583              
5584 426     426   878  
5585             ##############################################################################
5586 426 100       1622 #
5587             # _write_custom_label_str()
5588 1         3 #
5589             # Write parts of the <c:dLbl> element for strings.
5590             #
5591              
5592             my $self = shift;
5593             my $label = shift;
5594             my $value = $label->{value};
5595             my $font = $label->{font};
5596             my $is_y_axis = 0;
5597             my $has_formatting = _has_fill_formatting($label);
5598              
5599             # Write the c:layout element.
5600 1032     1032   1561 $self->_write_layout();
5601 1032         2725  
5602 1032         1448 $self->xml_start_tag( 'c:tx' );
5603              
5604 1032 100       2252 # Write the c:rich element.
5605             $self->_write_rich( $value, $font, $is_y_axis, !$has_formatting );
5606 9         24  
5607             $self->xml_end_tag( 'c:tx' );
5608 22         31  
5609 22 100       45 # Write the c:spPr element.
5610             $self->_write_sp_pr( $label );
5611 18         68 }
5612              
5613             ##############################################################################
5614             #
5615             # _write_custom_label_formula()
5616             #
5617             # Write parts of the <c:dLbl> element for formulas.
5618             #
5619              
5620             my $self = shift;
5621             my $label = shift;
5622             my $formula = $label->{formula};
5623             my $data_id = $label->{data_id};
5624 14     14   21 my $font = $label->{font};
5625 14         17 my $has_formatting = _has_fill_formatting($label);
5626 14         18 my $data;
5627              
5628 14         34 if ( defined $data_id ) {
5629             $data = $self->{_formula_data}->[$data_id];
5630             }
5631 14         37  
5632             # Write the c:layout element.
5633             $self->_write_layout();
5634 14         33  
5635             $self->xml_start_tag( 'c:tx' );
5636 14         367  
5637             # Write the c:strRef element.
5638             $self->_write_str_ref( $formula, $data, 'str' );
5639              
5640             $self->xml_end_tag( 'c:tx' );
5641              
5642             # Write the data label formating, if any.
5643             $self->_write_custom_label_format_only($label);
5644             }
5645              
5646             ##############################################################################
5647             #
5648             # _write_custom_label_format_only()
5649 1050     1050   1621 #
5650 1050         1522 # Write parts of the <c:dLbl> element for labels where only the formatting has
5651             # changed.
5652 1050 100       2571 #
5653              
5654 92         337 my $self = shift;
5655             my $label = shift;
5656             my $font = $label->{font};
5657 92 100       289 my $has_formatting = _has_fill_formatting($label);
5658 22         134  
5659             if ( $has_formatting ) {
5660              
5661             # Write the c:spPr element.
5662 92 100       249 $self->_write_sp_pr( $label );
5663 4         20 $self->_write_tx_pr( $font );
5664             }
5665             elsif ( $font ) {
5666             $self->xml_empty_tag( 'c:spPr' );
5667 92         310 $self->_write_tx_pr( $font );
5668             }
5669             }
5670 92 100       275  
5671 6         39  
5672             ##############################################################################
5673             #
5674             # _write_show_legend_key()
5675 92 100       410 #
5676             # Write the <c:showLegendKey> element.
5677             #
5678 92 100       269  
5679             my $self = shift;
5680             my $val = 1;
5681 92 100       555  
5682             my @attributes = ( 'val' => $val );
5683              
5684 92 100       315 $self->xml_empty_tag( 'c:showLegendKey', @attributes );
5685             }
5686              
5687 92 100       300 ##############################################################################
5688             #
5689             # _write_show_val()
5690 92 100       289 #
5691             # Write the <c:showVal> element.
5692             #
5693 92 100       310  
5694             my $self = shift;
5695             my $val = 1;
5696 92 100       292  
5697             my @attributes = ( 'val' => $val );
5698 92         325  
5699             $self->xml_empty_tag( 'c:showVal', @attributes );
5700             }
5701              
5702              
5703             ##############################################################################
5704             #
5705             # _write_show_cat_name()
5706             #
5707             # Write the <c:showCatName> element.
5708             #
5709              
5710 22     22   41 my $self = shift;
5711 22         42 my $val = 1;
5712 22         34  
5713 22         44 my @attributes = ( 'val' => $val );
5714              
5715 22         61 $self->xml_empty_tag( 'c:showCatName', @attributes );
5716 30         47 }
5717 30 100       79  
5718              
5719 27         82 ##############################################################################
5720             #
5721             # _write_show_ser_name()
5722 27         84 #
5723             # Write the <c:showSerName> element.
5724 27 100 66     182 #
    100          
    100          
5725 4         13  
5726             my $self = shift;
5727             my $val = 1;
5728 10         65  
5729             my @attributes = ( 'val' => $val );
5730 10 100       29  
5731 1         7 $self->xml_empty_tag( 'c:showSerName', @attributes );
5732             }
5733              
5734 10 50       88  
5735 10 50       39 ##############################################################################
5736 10 50       29 #
5737             # _write_show_percent()
5738             #
5739 9         62 # Write the <c:showPercent> element.
5740             #
5741 9 100       30  
5742 1         17 my $self = shift;
5743             my $val = 1;
5744              
5745 9 50       71 my @attributes = ( 'val' => $val );
5746 9 100       29  
5747 9 100       32 $self->xml_empty_tag( 'c:showPercent', @attributes );
5748             }
5749              
5750 4         29 ##############################################################################
5751             #
5752             # _write_separator()
5753 27         124 #
5754             # Write the <c:separator> element.
5755             #
5756              
5757             my $self = shift;
5758             my $data = shift;
5759              
5760             $self->xml_data_element( 'c:separator', $data );
5761             }
5762              
5763             ##############################################################################
5764             #
5765             # _write_show_leader_lines()
5766 9     9   14 #
5767 9         13 # Write the <c:showLeaderLines> element.
5768 9         19 #
5769 9         20  
5770 9         14 my $self = shift;
5771 9         22 my $val = 1;
5772              
5773             my @attributes = ( 'val' => $val );
5774 9         29  
5775             $self->xml_empty_tag( 'c:showLeaderLines', @attributes );
5776 9         26 }
5777              
5778              
5779 9         46 ##############################################################################
5780             #
5781 9         22 # _write_d_lbl_pos()
5782             #
5783             # Write the <c:dLblPos> element.
5784 9         21 #
5785              
5786             my $self = shift;
5787             my $val = shift;
5788              
5789             my @attributes = ( 'val' => $val );
5790              
5791             $self->xml_empty_tag( 'c:dLblPos', @attributes );
5792             }
5793              
5794              
5795 10     10   24 ##############################################################################
5796 10         21 #
5797 10         19 # _write_delete()
5798 10         16 #
5799 10         18 # Write the <c:delete> element.
5800 10         30 #
5801 10         14  
5802             my $self = shift;
5803 10 50       31 my $val = shift;
5804 10         29  
5805             my @attributes = ( 'val' => $val );
5806              
5807             $self->xml_empty_tag( 'c:delete', @attributes );
5808 10         30 }
5809              
5810 10         32  
5811             ##############################################################################
5812             #
5813 10         67 # _write_c_invert_if_negative()
5814             #
5815 10         27 # Write the <c:invertIfNegative> element.
5816             #
5817              
5818 10         49 my $self = shift;
5819             my $invert = shift;
5820             my $val = 1;
5821              
5822             return unless $invert;
5823              
5824             my @attributes = ( 'val' => $val );
5825              
5826             $self->xml_empty_tag( 'c:invertIfNegative', @attributes );
5827             }
5828              
5829              
5830 14     14   31 ##############################################################################
5831 14         22 #
5832 14         26 # _write_axis_font()
5833 14         35 #
5834             # Write the axis font elements.
5835 14 100       46 #
    100          
5836              
5837             my $self = shift;
5838 7         42 my $font = shift;
5839 7         39  
5840             return unless $font;
5841              
5842 2         7 $self->xml_start_tag( 'c:txPr' );
5843 2         9 $self->_write_a_body_pr($font->{_rotation});
5844             $self->_write_a_lst_style();
5845             $self->xml_start_tag( 'a:p' );
5846              
5847             $self->_write_a_p_pr_rich( $font );
5848              
5849             $self->_write_a_end_para_rpr();
5850             $self->xml_end_tag( 'a:p' );
5851             $self->xml_end_tag( 'c:txPr' );
5852             }
5853              
5854              
5855             ##############################################################################
5856 3     3   6 #
5857 3         4 # _write_a_latin()
5858             #
5859 3         7 # Write the <a:latin> element.
5860             #
5861 3         11  
5862             my $self = shift;
5863             my @attributes = @_;
5864              
5865             $self->xml_empty_tag( 'a:latin', @attributes );
5866             }
5867              
5868              
5869             ##############################################################################
5870             #
5871             # _write_d_table()
5872 108     108   180 #
5873 108         167 # Write the <c:dTable> element.
5874             #
5875 108         248  
5876             my $self = shift;
5877 108         301 my $table = $self->{_table};
5878              
5879             return if !$table;
5880              
5881             $self->xml_start_tag( 'c:dTable' );
5882              
5883             if ( $table->{_horizontal} ) {
5884              
5885             # Write the c:showHorzBorder element.
5886             $self->_write_show_horz_border();
5887             }
5888              
5889 14     14   21 if ( $table->{_vertical} ) {
5890 14         34  
5891             # Write the c:showVertBorder element.
5892 14         34 $self->_write_show_vert_border();
5893             }
5894 14         49  
5895             if ( $table->{_outline} ) {
5896              
5897             # Write the c:showOutline element.
5898             $self->_write_show_outline();
5899             }
5900              
5901             if ( $table->{_show_keys} ) {
5902              
5903             # Write the c:showKeys element.
5904             $self->_write_show_keys();
5905             }
5906 8     8   15  
5907 8         18 if ( $table->{_font} ) {
5908             # Write the table font.
5909 8         20 $self->_write_tx_pr( $table->{_font} );
5910             }
5911 8         25  
5912             $self->xml_end_tag( 'c:dTable' );
5913             }
5914              
5915              
5916             ##############################################################################
5917             #
5918             # _write_show_horz_border()
5919             #
5920             # Write the <c:showHorzBorder> element.
5921             #
5922              
5923 3     3   7 my $self = shift;
5924 3         6  
5925             my @attributes = ( 'val' => 1 );
5926 3         8  
5927             $self->xml_empty_tag( 'c:showHorzBorder', @attributes );
5928 3         9 }
5929              
5930             ##############################################################################
5931             #
5932             # _write_show_vert_border()
5933             #
5934             # Write the <c:showVertBorder> element.
5935             #
5936              
5937             my $self = shift;
5938              
5939 6     6   11 my @attributes = ( 'val' => 1 );
5940 6         16  
5941             $self->xml_empty_tag( 'c:showVertBorder', @attributes );
5942 6         21 }
5943              
5944              
5945             ##############################################################################
5946             #
5947             # _write_show_outline()
5948             #
5949             # Write the <c:showOutline> element.
5950             #
5951              
5952             my $self = shift;
5953 14     14   33  
5954 14         21 my @attributes = ( 'val' => 1 );
5955              
5956 14         34 $self->xml_empty_tag( 'c:showOutline', @attributes );
5957             }
5958 14         41  
5959              
5960             ##############################################################################
5961             #
5962             # _write_show_keys()
5963             #
5964             # Write the <c:showKeys> element.
5965             #
5966              
5967             my $self = shift;
5968              
5969             my @attributes = ( 'val' => 1 );
5970 41     41   89  
5971 41         73 $self->xml_empty_tag( 'c:showKeys', @attributes );
5972             }
5973 41         138  
5974              
5975 41         128 ##############################################################################
5976             #
5977             # _write_error_bars()
5978             #
5979             # Write the X and Y error bars.
5980             #
5981              
5982             my $self = shift;
5983             my $error_bars = shift;
5984              
5985             return unless $error_bars;
5986              
5987 25     25   66 if ( $error_bars->{_x_error_bars} ) {
5988 25         41 $self->_write_err_bars( 'x', $error_bars->{_x_error_bars} );
5989             }
5990 25         61  
5991             if ( $error_bars->{_y_error_bars} ) {
5992 25         77 $self->_write_err_bars( 'y', $error_bars->{_y_error_bars} );
5993             }
5994              
5995             }
5996              
5997              
5998             ##############################################################################
5999             #
6000             # _write_err_bars()
6001             #
6002             # Write the <c:errBars> element.
6003             #
6004 970     970   1435  
6005 970         1370 my $self = shift;
6006 970         1325 my $direction = shift;
6007             my $error_bars = shift;
6008 970 100       2111  
6009             return unless $error_bars;
6010 2         7  
6011             $self->xml_start_tag( 'c:errBars' );
6012 2         7  
6013             # Write the c:errDir element.
6014             $self->_write_err_dir( $direction );
6015              
6016             # Write the c:errBarType element.
6017             $self->_write_err_bar_type( $error_bars->{_direction} );
6018              
6019             # Write the c:errValType element.
6020             $self->_write_err_val_type( $error_bars->{_type} );
6021              
6022             if ( !$error_bars->{_endcap} ) {
6023              
6024 768     768   1255 # Write the c:noEndCap element.
6025 768         1150 $self->_write_no_end_cap();
6026             }
6027 768 100       1725  
6028             if ( $error_bars->{_type} eq 'stdErr' ) {
6029 28         83  
6030 28         118 # Don't need to write a c:errValType tag.
6031 28         170 }
6032 28         92 elsif ( $error_bars->{_type} eq 'cust' ) {
6033              
6034 28         127 # Write the custom error tags.
6035             $self->_write_custom_error( $error_bars );
6036 28         148 }
6037 28         113 else {
6038 28         71 # Write the c:val element.
6039             $self->_write_error_val( $error_bars->{_value} );
6040             }
6041              
6042             # Write the c:spPr element.
6043             $self->_write_sp_pr( $error_bars );
6044              
6045             $self->xml_end_tag( 'c:errBars' );
6046             }
6047              
6048              
6049             ##############################################################################
6050 13     13   35 #
6051 13         37 # _write_err_dir()
6052             #
6053 13         35 # Write the <c:errDir> element.
6054             #
6055              
6056             my $self = shift;
6057             my $val = shift;
6058              
6059             my @attributes = ( 'val' => $val );
6060              
6061             $self->xml_empty_tag( 'c:errDir', @attributes );
6062             }
6063              
6064              
6065 338     338   746 ##############################################################################
6066 338         824 #
6067             # _write_err_bar_type()
6068 338 100       1155 #
6069             # Write the <c:errBarType> element.
6070 3         11 #
6071              
6072 3 100       8 my $self = shift;
6073             my $val = shift;
6074              
6075 1         5 my @attributes = ( 'val' => $val );
6076              
6077             $self->xml_empty_tag( 'c:errBarType', @attributes );
6078 3 100       22 }
6079              
6080              
6081 1         4 ##############################################################################
6082             #
6083             # _write_err_val_type()
6084 3 100       11 #
6085             # Write the <c:errValType> element.
6086             #
6087 1         3  
6088             my $self = shift;
6089             my $val = shift;
6090 3 100       11  
6091             my @attributes = ( 'val' => $val );
6092              
6093 2         10 $self->xml_empty_tag( 'c:errValType', @attributes );
6094             }
6095              
6096 3 100       9  
6097             ##############################################################################
6098 1         6 #
6099             # _write_no_end_cap()
6100             #
6101 3         9 # Write the <c:noEndCap> element.
6102             #
6103              
6104             my $self = shift;
6105              
6106             my @attributes = ( 'val' => 1 );
6107              
6108             $self->xml_empty_tag( 'c:noEndCap', @attributes );
6109             }
6110              
6111              
6112             ##############################################################################
6113 1     1   2 #
6114             # _write_error_val()
6115 1         2 #
6116             # Write the <c:val> element for error bars.
6117 1         9 #
6118              
6119             my $self = shift;
6120             my $val = shift;
6121              
6122             my @attributes = ( 'val' => $val );
6123              
6124             $self->xml_empty_tag( 'c:val', @attributes );
6125             }
6126              
6127              
6128 1     1   2 ##############################################################################
6129             #
6130 1         2 # _write_custom_error()
6131             #
6132 1         3 # Write the custom error bars tags.
6133             #
6134              
6135             my $self = shift;
6136             my $error_bars = shift;
6137              
6138             if ( $error_bars->{_plus_values} ) {
6139              
6140             # Write the c:plus element.
6141             $self->xml_start_tag( 'c:plus' );
6142              
6143             if ( ref $error_bars->{_plus_values} eq 'ARRAY' ) {
6144 1     1   2 $self->_write_num_lit( $error_bars->{_plus_values} );
6145             }
6146 1         2 else {
6147             $self->_write_num_ref( $error_bars->{_plus_values},
6148 1         3 $error_bars->{_plus_data}, 'num' );
6149             }
6150              
6151             $self->xml_end_tag( 'c:plus' );
6152             }
6153              
6154             if ( $error_bars->{_minus_values} ) {
6155              
6156             # Write the c:minus element.
6157             $self->xml_start_tag( 'c:minus' );
6158              
6159             if ( ref $error_bars->{_minus_values} eq 'ARRAY' ) {
6160 2     2   4 $self->_write_num_lit( $error_bars->{_minus_values} );
6161             }
6162 2         6 else {
6163             $self->_write_num_ref( $error_bars->{_minus_values},
6164 2         7 $error_bars->{_minus_data}, 'num' );
6165             }
6166              
6167             $self->xml_end_tag( 'c:minus' );
6168             }
6169             }
6170              
6171              
6172              
6173             ##############################################################################
6174             #
6175             # _write_num_lit()
6176 1032     1032   1500 #
6177 1032         1415 # Write the <c:numLit> element for literal number list elements.
6178             #
6179 1032 50       2371  
6180             my $self = shift;
6181 1032 100       2556 my $data = shift;
6182 2         13 my $count = @$data;
6183              
6184              
6185 1032 100       2440 # Write the c:numLit element.
6186 12         49 $self->xml_start_tag( 'c:numLit' );
6187              
6188             # Write the c:formatCode element.
6189             $self->_write_format_code( 'General' );
6190              
6191             # Write the c:ptCount element.
6192             $self->_write_pt_count( $count );
6193              
6194             for my $i ( 0 .. $count - 1 ) {
6195             my $token = $data->[$i];
6196              
6197             # Write non-numeric data as 0.
6198             if ( defined $token
6199             && $token !~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/ )
6200 14     14   23 {
6201 14         27 $token = 0;
6202 14         25 }
6203              
6204 14 50       36 # Write the c:pt element.
6205             $self->_write_pt( $i, $token );
6206 14         45 }
6207              
6208             $self->xml_end_tag( 'c:numLit' );
6209 14         57  
6210              
6211             }
6212 14         57  
6213              
6214             ##############################################################################
6215 14         56 #
6216             # _write_up_down_bars()
6217 14 100       43 #
6218             # Write the <c:upDownBars> element.
6219             #
6220 1         4  
6221             my $self = shift;
6222             my $up_down_bars = $self->{_up_down_bars};
6223 14 100       55  
    100          
6224             return unless $up_down_bars;
6225              
6226             $self->xml_start_tag( 'c:upDownBars' );
6227              
6228             # Write the c:gapWidth element.
6229             $self->_write_gap_width( 150 );
6230 3         18  
6231             # Write the c:upBars element.
6232             $self->_write_up_bars( $up_down_bars->{_up} );
6233              
6234 3         11 # Write the c:downBars element.
6235             $self->_write_down_bars( $up_down_bars->{_down} );
6236              
6237             $self->xml_end_tag( 'c:upDownBars' );
6238 14         58 }
6239              
6240 14         41  
6241             ##############################################################################
6242             #
6243             # _write_gap_width()
6244             #
6245             # Write the <c:gapWidth> element.
6246             #
6247              
6248             my $self = shift;
6249             my $val = shift;
6250              
6251             return if !defined $val;
6252 12     12   19  
6253 12         18 my @attributes = ( 'val' => $val );
6254              
6255 12         27 $self->xml_empty_tag( 'c:gapWidth', @attributes );
6256             }
6257 12         31  
6258             ##############################################################################
6259             #
6260             # _write_up_bars()
6261             #
6262             # Write the <c:upBars> element.
6263             #
6264              
6265             my $self = shift;
6266             my $format = shift;
6267              
6268             if ( $format->{_line}->{_defined} || $format->{_fill}->{_defined} ) {
6269 14     14   23  
6270 14         22 $self->xml_start_tag( 'c:upBars' );
6271              
6272 14         25 # Write the c:spPr element.
6273             $self->_write_sp_pr( $format );
6274 14         36  
6275             $self->xml_end_tag( 'c:upBars' );
6276             }
6277             else {
6278             $self->xml_empty_tag( 'c:upBars' );
6279             }
6280             }
6281              
6282              
6283             ##############################################################################
6284             #
6285             # _write_down_bars()
6286 14     14   29 #
6287 14         21 # Write the <c:downBars> element.
6288             #
6289 14         36  
6290             my $self = shift;
6291 14         45 my $format = shift;
6292              
6293             if ( $format->{_line}->{_defined} || $format->{_fill}->{_defined} ) {
6294              
6295             $self->xml_start_tag( 'c:downBars' );
6296              
6297             # Write the c:spPr element.
6298             $self->_write_sp_pr( $format );
6299              
6300             $self->xml_end_tag( 'c:downBars' );
6301             }
6302             else {
6303 1     1   2 $self->xml_empty_tag( 'c:downBars' );
6304             }
6305 1         3 }
6306              
6307 1         3  
6308             ##############################################################################
6309             #
6310             # _write_c_smooth()
6311             #
6312             # Write the <c:smooth> element.
6313             #
6314              
6315             my $self = shift;
6316             my $smooth = shift;
6317              
6318             return unless $smooth;
6319 3     3   5  
6320 3         14 my @attributes = ( 'val' => 1 );
6321              
6322 3         9 $self->xml_empty_tag( 'c:smooth', @attributes );
6323             }
6324 3         7  
6325             ##############################################################################
6326             #
6327             # _write_disp_units()
6328             #
6329             # Write the <c:dispUnits> element.
6330             #
6331              
6332             my $self = shift;
6333             my $units = shift;
6334             my $display = shift;
6335              
6336 3     3   11 return if not $units;
6337 3         7  
6338             my @attributes = ( 'val' => $units );
6339 3 50       15  
6340             $self->xml_start_tag( 'c:dispUnits' );
6341              
6342 3         14 $self->xml_empty_tag( 'c:builtInUnit', @attributes );
6343              
6344 3 100       11 if ( $display ) {
6345 2         9 $self->xml_start_tag( 'c:dispUnitsLbl' );
6346             $self->xml_empty_tag( 'c:layout' );
6347             $self->xml_end_tag( 'c:dispUnitsLbl' );
6348             }
6349 1         5  
6350             $self->xml_end_tag( 'c:dispUnits' );
6351             }
6352 3         7  
6353              
6354             ##############################################################################
6355 3 50       9 #
6356             # _write_a_grad_fill()
6357             #
6358 3         8 # Write the <a:gradFill> element.
6359             #
6360 3 100       22  
6361 2         7 my $self = shift;
6362             my $gradient = shift;
6363              
6364              
6365 1         3 my @attributes = (
6366             'flip' => 'none',
6367             'rotWithShape' => 1,
6368 3         9 );
6369              
6370              
6371             if ( $gradient->{_type} eq 'linear' ) {
6372             @attributes = ();
6373             }
6374              
6375             $self->xml_start_tag( 'a:gradFill', @attributes );
6376              
6377             # Write the a:gsLst element.
6378             $self->_write_a_gs_lst( $gradient );
6379              
6380             if ( $gradient->{_type} eq 'linear' ) {
6381             # Write the a:lin element.
6382 4     4   7 $self->_write_a_lin( $gradient->{_angle} );
6383 4         5 }
6384 4         5 else {
6385             # Write the a:path element.
6386             $self->_write_a_path( $gradient->{_type} );
6387              
6388 4         20 # Write the a:tileRect element.
6389             $self->_write_a_tile_rect( $gradient->{_type} );
6390             }
6391 4         26  
6392             $self->xml_end_tag( 'a:gradFill' );
6393             }
6394 4         13  
6395              
6396 4         11 ##############################################################################
6397 8         13 #
6398             # _write_a_gs_lst()
6399             #
6400 8 50 33     49 # Write the <a:gsLst> element.
6401             #
6402              
6403 0         0 my $self = shift;
6404             my $gradient = shift;
6405             my $positions = $gradient->{_positions};
6406             my $colors = $gradient->{_colors};
6407 8         26  
6408             $self->xml_start_tag( 'a:gsLst' );
6409              
6410 4         7 for my $i ( 0 .. @$colors -1 ) {
6411              
6412             my $pos = int($positions->[$i] * 1000);
6413              
6414             my @attributes = ( 'pos' => $pos );
6415             $self->xml_start_tag( 'a:gs', @attributes );
6416              
6417             my $color = $self->_get_color( $colors->[$i] );
6418              
6419             # Write the a:srgbClr element.
6420             # TODO: Wait for a feature request to support transparency.
6421             $self->_write_a_srgb_clr( $color );
6422              
6423             $self->xml_end_tag( 'a:gs' );
6424 106     106   227 }
6425 106         247  
6426             $self->xml_end_tag( 'a:gsLst' );
6427 106 100       420 }
6428              
6429 3         13  
6430             ##############################################################################
6431             #
6432 3         14 # _write_a_lin()
6433             #
6434             # Write the <a:lin> element.
6435 3         17 #
6436              
6437             my $self = shift;
6438 3         27 my $angle = shift;
6439             my $scaled = 0;
6440 3         8  
6441             $angle = int( 60000 * $angle );
6442              
6443             my @attributes = (
6444             'ang' => $angle,
6445             'scaled' => $scaled,
6446             );
6447              
6448             $self->xml_empty_tag( 'a:lin', @attributes );
6449             }
6450              
6451             ##############################################################################
6452 231     231   596 #
6453 231         617 # _write_a_path()
6454             #
6455 231 100       913 # Write the <a:path> element.
6456             #
6457 10         27  
6458             my $self = shift;
6459 10         34 my $type = shift;
6460              
6461              
6462             my @attributes = ( 'path' => $type );
6463              
6464             $self->xml_start_tag( 'a:path', @attributes );
6465              
6466             # Write the a:fillToRect element.
6467             $self->_write_a_fill_to_rect( $type );
6468              
6469             $self->xml_end_tag( 'a:path' );
6470 3     3   6 }
6471 3         5  
6472              
6473 3 100 66     18 ##############################################################################
6474             #
6475 1         10 # _write_a_fill_to_rect()
6476             #
6477             # Write the <a:fillToRect> element.
6478 1         4 #
6479              
6480 1         2 my $self = shift;
6481             my $type = shift;
6482             my @attributes = ();
6483 2         6  
6484             if ( $type eq 'shape' ) {
6485             @attributes = (
6486             'l' => 50000,
6487             't' => 50000,
6488             'r' => 50000,
6489             'b' => 50000,
6490             );
6491              
6492             }
6493             else {
6494             @attributes = (
6495             'l' => 100000,
6496 3     3   5 't' => 100000,
6497 3         5 );
6498             }
6499 3 100 66     17  
6500              
6501 1         3 $self->xml_empty_tag( 'a:fillToRect', @attributes );
6502             }
6503              
6504 1         3  
6505             ##############################################################################
6506 1         2 #
6507             # _write_a_tile_rect()
6508             #
6509 2         6 # Write the <a:tileRect> element.
6510             #
6511              
6512             my $self = shift;
6513             my $type = shift;
6514             my @attributes = ();
6515              
6516             if ( $type eq 'shape' ) {
6517             @attributes = ();
6518             }
6519             else {
6520             @attributes = (
6521             'r' => -100000,
6522 276     276   468 'b' => -100000,
6523 276         458 );
6524             }
6525 276 100       737  
6526             $self->xml_empty_tag( 'a:tileRect', @attributes );
6527 10         26 }
6528              
6529 10         36  
6530             ##############################################################################
6531             #
6532             # _write_a_patt_fill()
6533             #
6534             # Write the <a:pattFill> element.
6535             #
6536              
6537             my $self = shift;
6538             my $pattern = shift;
6539              
6540 413     413   831 my @attributes = ( 'prst' => $pattern->{pattern} );
6541 413         772  
6542 413         724 $self->xml_start_tag( 'a:pattFill', @attributes );
6543              
6544 413 100       1245 # Write the a:fgClr element.
6545             $self->_write_a_fg_clr( $pattern->{fg_color} );
6546 12         28  
6547             # Write the a:bgClr element.
6548 12         48 $self->_write_a_bg_clr( $pattern->{bg_color} );
6549              
6550 12         38 $self->xml_end_tag( 'a:pattFill' );
6551             }
6552 12 100       34  
6553 1         3  
6554 1         2 ##############################################################################
6555 1         2 #
6556             # _write_a_fg_clr()
6557             #
6558 12         35 # Write the <a:fgClr> element.
6559             #
6560              
6561             my $self = shift;
6562             my $color = shift;
6563              
6564             $color = $self->_get_color( $color );
6565              
6566             $self->xml_start_tag( 'a:fgClr' );
6567              
6568             # Write the a:srgbClr element.
6569             $self->_write_a_srgb_clr( $color );
6570 14     14   38  
6571 14         19 $self->xml_end_tag( 'a:fgClr' );
6572             }
6573              
6574 14         58  
6575              
6576             ##############################################################################
6577             #
6578             # _write_a_bg_clr()
6579             #
6580 14 100       57 # Write the <a:bgClr> element.
6581 11         29 #
6582              
6583             my $self = shift;
6584 14         56 my $color = shift;
6585              
6586             $color = $self->_get_color( $color );
6587 14         74  
6588             $self->xml_start_tag( 'a:bgClr' );
6589 14 100       84  
6590             # Write the a:srgbClr element.
6591 11         64 $self->_write_a_srgb_clr( $color );
6592              
6593             $self->xml_end_tag( 'a:bgClr' );
6594             }
6595 3         20  
6596              
6597             1;
6598 3         14  
6599              
6600              
6601 14         73 =head1 NAME
6602              
6603             Chart - A class for writing Excel Charts.
6604              
6605             =head1 SYNOPSIS
6606              
6607             To create a simple Excel file with a chart using Excel::Writer::XLSX:
6608              
6609             #!/usr/bin/perl
6610              
6611             use strict;
6612             use warnings;
6613 14     14   27 use Excel::Writer::XLSX;
6614 14         34  
6615 14         46 my $workbook = Excel::Writer::XLSX->new( 'chart.xlsx' );
6616 14         26 my $worksheet = $workbook->add_worksheet();
6617              
6618 14         61 # Add the worksheet data the chart refers to.
6619             my $data = [
6620 14         65 [ 'Category', 2, 3, 4, 5, 6, 7 ],
6621             [ 'Value', 1, 4, 5, 2, 1, 5 ],
6622 41         99  
6623             ];
6624 41         84  
6625 41         97 $worksheet->write( 'A1', $data );
6626              
6627 41         136 # Add a worksheet chart.
6628             my $chart = $workbook->add_chart( type => 'column' );
6629              
6630             # Configure the chart.
6631 41         139 $chart->add_series(
6632             categories => '=Sheet1!$A$2:$A$7',
6633 41         184 values => '=Sheet1!$B$2:$B$7',
6634             );
6635              
6636 14         64 $workbook->close();
6637              
6638             __END__
6639              
6640              
6641             =head1 DESCRIPTION
6642              
6643             The C<Chart> module is an abstract base class for modules that implement charts in L<Excel::Writer::XLSX>. The information below is applicable to all of the available subclasses.
6644              
6645             The C<Chart> module isn't used directly. A chart object is created via the Workbook C<add_chart()> method where the chart type is specified:
6646              
6647             my $chart = $workbook->add_chart( type => 'column' );
6648 11     11   22  
6649 11         21 Currently the supported chart types are:
6650 11         21  
6651             =over
6652 11         26  
6653             =item * C<area>
6654 11         37  
6655             Creates an Area (filled line) style chart. See L<Excel::Writer::XLSX::Chart::Area>.
6656              
6657             =item * C<bar>
6658              
6659 11         36 Creates a Bar style (transposed histogram) chart. See L<Excel::Writer::XLSX::Chart::Bar>.
6660              
6661             =item * C<column>
6662              
6663             Creates a column style (histogram) chart. See L<Excel::Writer::XLSX::Chart::Column>.
6664              
6665             =item * C<line>
6666              
6667             Creates a Line style chart. See L<Excel::Writer::XLSX::Chart::Line>.
6668              
6669             =item * C<pie>
6670 3     3   6  
6671 3         6 Creates a Pie style chart. See L<Excel::Writer::XLSX::Chart::Pie>.
6672              
6673             =item * C<doughnut>
6674 3         8  
6675             Creates a Doughnut style chart. See L<Excel::Writer::XLSX::Chart::Doughnut>.
6676 3         9  
6677             =item * C<scatter>
6678              
6679 3         13 Creates a Scatter style chart. See L<Excel::Writer::XLSX::Chart::Scatter>.
6680              
6681 3         9 =item * C<stock>
6682              
6683             Creates a Stock style chart. See L<Excel::Writer::XLSX::Chart::Stock>.
6684              
6685             =item * C<radar>
6686              
6687             Creates a Radar style chart. See L<Excel::Writer::XLSX::Chart::Radar>.
6688              
6689             =back
6690              
6691             Chart subtypes are also supported in some cases:
6692              
6693 3     3   5 $workbook->add_chart( type => 'bar', subtype => 'stacked' );
6694 3         5  
6695 3         5 The currently available subtypes are:
6696              
6697 3 100       8 area
6698 1         3 stacked
6699             percent_stacked
6700              
6701             bar
6702             stacked
6703             percent_stacked
6704              
6705             column
6706             stacked
6707 2         4 percent_stacked
6708              
6709             scatter
6710             straight_with_markers
6711             straight
6712             smooth_with_markers
6713             smooth
6714 3         10  
6715             line
6716             stacked
6717             percent_stacked
6718              
6719             radar
6720             with_markers
6721             filled
6722              
6723              
6724             =head1 CHART METHODS
6725              
6726 3     3   5 Methods that are common to all chart types are documented below. See the documentation for each of the above chart modules for chart specific information.
6727 3         20  
6728 3         14 =head2 add_series()
6729              
6730 3 100       23 In an Excel chart a "series" is a collection of information such as values, X axis labels and the formatting that define which data is plotted.
6731 1         2  
6732             With an Excel::Writer::XLSX chart object the C<add_series()> method is used to set the properties for a series:
6733              
6734 2         8 $chart->add_series(
6735             categories => '=Sheet1!$A$2:$A$10', # Optional.
6736             values => '=Sheet1!$B$2:$B$10', # Required.
6737             line => { color => 'blue' },
6738             );
6739              
6740 3         10 The properties that can be set are:
6741              
6742             =over
6743              
6744             =item * C<values>
6745              
6746             This is the most important property of a series and must be set for every chart object. It links the chart with the worksheet data that it displays. A formula or array ref can be used for the data range, see below.
6747              
6748             =item * C<categories>
6749              
6750             This sets the chart category labels. The category is more or less the same as the X axis. In most chart types the C<categories> property is optional and the chart will just assume a sequential series from C<1 .. n>.
6751              
6752 59     59   77 =item * C<name>
6753 59         69  
6754             Set the name for the series. The name is displayed in the chart legend and in the formula bar. The name property is optional and if it isn't supplied it will default to C<Series 1 .. n>.
6755 59         141  
6756             =item * C<line>
6757 59         132  
6758             Set the properties of the series line type such as colour and width. See the L</CHART FORMATTING> section below.
6759              
6760 59         160 =item * C<border>
6761              
6762             Set the border properties of the series such as colour and style. See the L</CHART FORMATTING> section below.
6763 59         153  
6764             =item * C<fill>
6765 59         111  
6766             Set the fill properties of the series such as colour. See the L</CHART FORMATTING> section below.
6767              
6768             =item * C<pattern>
6769              
6770             Set the pattern properties of the series. See the L</CHART FORMATTING> section below.
6771              
6772             =item * C<gradient>
6773              
6774             Set the gradient properties of the series. See the L</CHART FORMATTING> section below.
6775              
6776             =item * C<marker>
6777 59     59   76  
6778 59         83 Set the properties of the series marker such as style and colour. See the L</SERIES OPTIONS> section below.
6779              
6780 59         149 =item * C<trendline>
6781              
6782 59         149 Set the properties of the series trendline such as linear, polynomial and moving average types. See the L</SERIES OPTIONS> section below.
6783              
6784             =item * C<smooth>
6785 59         176  
6786             The C<smooth> option is used to set the smooth property of a line series. See the L</SERIES OPTIONS> section below.
6787 59         146  
6788             =item * C<y_error_bars>
6789              
6790             Set vertical error bounds for a chart series. See the L</SERIES OPTIONS> section below.
6791              
6792             =item * C<x_error_bars>
6793              
6794             Set horizontal error bounds for a chart series. See the L</SERIES OPTIONS> section below.
6795              
6796             =item * C<data_labels>
6797              
6798             Set data labels for the series. See the L</SERIES OPTIONS> section below.
6799              
6800 59     59   74 =item * C<points>
6801 59         74  
6802             Set properties for individual points in a series. See the L</SERIES OPTIONS> section below.
6803 59         123  
6804             =item * C<invert_if_negative>
6805 59         142  
6806             Invert the fill colour for negative values. Usually only applicable to column and bar charts.
6807              
6808 59         139 =item * C<overlap>
6809              
6810 59         114 Set the overlap between series in a Bar/Column chart. The range is +/- 100. Default is 0.
6811              
6812             overlap => 20,
6813              
6814             Note, it is only necessary to apply this property to one series of the chart.
6815              
6816             =item * C<gap>
6817              
6818             Set the gap between series in a Bar/Column chart. The range is 0 to 500. Default is 150.
6819              
6820             gap => 200,
6821              
6822             Note, it is only necessary to apply this property to one series of the chart.
6823              
6824             =back
6825              
6826             The C<categories> and C<values> can take either a range formula such as C<=Sheet1!$A$2:$A$7> or, more usefully when generating the range programmatically, an array ref with zero indexed row/column values:
6827              
6828             [ $sheetname, $row_start, $row_end, $col_start, $col_end ]
6829              
6830             The following are equivalent:
6831              
6832             $chart->add_series( categories => '=Sheet1!$A$2:$A$7' ); # Same as ...
6833             $chart->add_series( categories => [ 'Sheet1', 1, 6, 0, 0 ] ); # Zero-indexed.
6834              
6835             You can add more than one series to a chart. In fact, some chart types such as C<stock> require it. The series numbering and order in the Excel chart will be the same as the order in which they are added in Excel::Writer::XLSX.
6836              
6837             # Add the first series.
6838             $chart->add_series(
6839             categories => '=Sheet1!$A$2:$A$7',
6840             values => '=Sheet1!$B$2:$B$7',
6841             name => 'Test data series 1',
6842             );
6843              
6844             # Add another series. Same categories. Different range values.
6845             $chart->add_series(
6846             categories => '=Sheet1!$A$2:$A$7',
6847             values => '=Sheet1!$C$2:$C$7',
6848             name => 'Test data series 2',
6849             );
6850              
6851             It is also possible to specify non-contiguous ranges:
6852              
6853             $chart->add_series(
6854             categories => '=(Sheet1!$A$1:$A$9,Sheet1!$A$14:$A$25)',
6855             values => '=(Sheet1!$B$1:$B$9,Sheet1!$B$14:$B$25)',
6856             );
6857              
6858              
6859             =head2 set_x_axis()
6860              
6861             The C<set_x_axis()> method is used to set properties of the X axis.
6862              
6863             $chart->set_x_axis( name => 'Quarterly results' );
6864              
6865             The properties that can be set are:
6866              
6867             name
6868             name_font
6869             name_layout
6870             num_font
6871             num_format
6872             line
6873             fill
6874             pattern
6875             gradient
6876             min
6877             max
6878             minor_unit
6879             major_unit
6880             interval_unit
6881             interval_tick
6882             crossing
6883             reverse
6884             position_axis
6885             log_base
6886             label_position
6887             major_gridlines
6888             minor_gridlines
6889             visible
6890             date_axis
6891             text_axis
6892             minor_unit_type
6893             major_unit_type
6894             minor_tick_mark
6895             major_tick_mark
6896             display_units
6897             display_units_visible
6898              
6899             These are explained below. Some properties are only applicable to value or category axes, as indicated. See L<Value and Category Axes> for an explanation of Excel's distinction between the axis types.
6900              
6901             =over
6902              
6903             =item * C<name>
6904              
6905              
6906             Set the name (title or caption) for the axis. The name is displayed below the X axis. The C<name> property is optional. The default is to have no axis name. (Applicable to category and value axes).
6907              
6908             $chart->set_x_axis( name => 'Quarterly results' );
6909              
6910             The name can also be a formula such as C<=Sheet1!$A$1>.
6911              
6912             =item * C<name_font>
6913              
6914             Set the font properties for the axis title. (Applicable to category and value axes).
6915              
6916             $chart->set_x_axis( name_font => { name => 'Arial', size => 10 } );
6917              
6918             =item * C<name_layout>
6919              
6920             Set the C<(x, y)> position of the axis caption in chart relative units. (Applicable to category and value axes).
6921              
6922             $chart->set_x_axis(
6923             name => 'X axis',
6924             name_layout => {
6925             x => 0.34,
6926             y => 0.85,
6927             }
6928             );
6929              
6930             See the L</CHART LAYOUT> section below.
6931              
6932             =item * C<num_font>
6933              
6934             Set the font properties for the axis numbers. (Applicable to category and value axes).
6935              
6936             $chart->set_x_axis( num_font => { bold => 1, italic => 1 } );
6937              
6938             See the L</CHART FONTS> section below.
6939              
6940             =item * C<num_format>
6941              
6942             Set the number format for the axis. (Applicable to category and value axes).
6943              
6944             $chart->set_x_axis( num_format => '#,##0.00' );
6945             $chart->set_y_axis( num_format => '0.00%' );
6946              
6947             The number format is similar to the Worksheet Cell Format C<num_format> apart from the fact that a format index cannot be used. The explicit format string must be used as shown above. See L<Excel::Writer::XLSX/set_num_format()> for more information.
6948              
6949             =item * C<line>
6950              
6951             Set the properties of the axis line type such as colour and width. See the L</CHART FORMATTING> section below.
6952              
6953             $chart->set_x_axis( line => { none => 1 });
6954              
6955              
6956             =item * C<fill>
6957              
6958             Set the fill properties of the axis such as colour. See the L</CHART FORMATTING> section below. Note, in Excel the axis fill is applied to the area of the numbers of the axis and not to the area of the axis bounding box. That background is set from the chartarea fill.
6959              
6960             =item * C<pattern>
6961              
6962             Set the pattern properties of the axis such as colour. See the L</CHART FORMATTING> section below.
6963              
6964             =item * C<gradient>
6965              
6966             Set the gradient properties of the axis such as colour. See the L</CHART FORMATTING> section below.
6967              
6968             =item * C<min>
6969              
6970             Set the minimum value for the axis range. (Applicable to value axes only.)
6971              
6972             $chart->set_x_axis( min => 20 );
6973              
6974             =item * C<max>
6975              
6976             Set the maximum value for the axis range. (Applicable to value axes only.)
6977              
6978             $chart->set_x_axis( max => 80 );
6979              
6980             =item * C<minor_unit>
6981              
6982             Set the increment of the minor units in the axis range. (Applicable to value axes only.)
6983              
6984             $chart->set_x_axis( minor_unit => 0.4 );
6985              
6986             =item * C<major_unit>
6987              
6988             Set the increment of the major units in the axis range. (Applicable to value axes only.)
6989              
6990             $chart->set_x_axis( major_unit => 2 );
6991              
6992             =item * C<interval_unit>
6993              
6994             Set the interval unit for a category axis. (Applicable to category axes only.)
6995              
6996             $chart->set_x_axis( interval_unit => 2 );
6997              
6998             =item * C<interval_tick>
6999              
7000             Set the tick interval for a category axis. (Applicable to category axes only.)
7001              
7002             $chart->set_x_axis( interval_tick => 4 );
7003              
7004             =item * C<crossing>
7005              
7006             Set the position where the y axis will cross the x axis. (Applicable to category and value axes.)
7007              
7008             The C<crossing> value can either be a numeric value or the strings C<'max'> or C<'min'> to set the crossing at the maximum/minimum axis value.
7009              
7010             $chart->set_x_axis( crossing => 3 );
7011             # or
7012             $chart->set_x_axis( crossing => 'max' );
7013              
7014             B<For category axes the numeric value must be an integer> to represent the category number that the axis crosses at. For value axes it can have any value associated with the axis.
7015              
7016             If crossing is omitted (the default) the crossing will be set automatically by Excel based on the chart data.
7017              
7018             =item * C<position_axis>
7019              
7020             Position the axis on or between the axis tick marks. (Applicable to category axes only.)
7021              
7022             There are two allowable values C<on_tick> and C<between>:
7023              
7024             $chart->set_x_axis( position_axis => 'on_tick' );
7025             $chart->set_x_axis( position_axis => 'between' );
7026              
7027             =item * C<reverse>
7028              
7029             Reverse the order of the axis categories or values. (Applicable to category and value axes.)
7030              
7031             $chart->set_x_axis( reverse => 1 );
7032              
7033             =item * C<log_base>
7034              
7035             Set the log base of the axis range. (Applicable to value axes only.)
7036              
7037             $chart->set_x_axis( log_base => 10 );
7038              
7039             =item * C<label_position>
7040              
7041             Set the "Axis labels" position for the axis. The following positions are available:
7042              
7043             next_to (the default)
7044             high
7045             low
7046             none
7047              
7048             =item * C<major_gridlines>
7049              
7050             Configure the major gridlines for the axis. The available properties are:
7051              
7052             visible
7053             line
7054              
7055             For example:
7056              
7057             $chart->set_x_axis(
7058             major_gridlines => {
7059             visible => 1,
7060             line => { color => 'red', width => 1.25, dash_type => 'dash' }
7061             }
7062             );
7063              
7064             The C<visible> property is usually on for the X-axis but it depends on the type of chart.
7065              
7066             The C<line> property sets the gridline properties such as colour and width. See the L</CHART FORMATTING> section below.
7067              
7068             =item * C<minor_gridlines>
7069              
7070             This takes the same options as C<major_gridlines> above.
7071              
7072             The minor gridline C<visible> property is off by default for all chart types.
7073              
7074             =item * C<visible>
7075              
7076             Configure the visibility of the axis.
7077              
7078             $chart->set_x_axis( visible => 0 );
7079              
7080              
7081             =item * C<date_axis>
7082              
7083             This option is used to treat a category axis with date or time data as a Date Axis. (Applicable to category axes only.)
7084              
7085             $chart->set_x_axis( date_axis => 1 );
7086              
7087             This option also allows you to set C<max> and C<min> values for a category axis which isn't allowed by Excel for non-date category axes.
7088              
7089             See L<Date Category Axes> for more details.
7090              
7091             =item * C<text_axis>
7092              
7093             This option is used to treat a category axis explicitly as a Text Axis. (Applicable to category axes only.)
7094              
7095             $chart->set_x_axis( text_axis => 1 );
7096              
7097              
7098             =item * C<minor_unit_type>
7099              
7100             For C<date_axis> axes, see above, this option is used to set the type of the minor units. (Applicable to date category axes only.)
7101              
7102             $chart->set_x_axis(
7103             date_axis => 1,
7104             minor_unit => 4,
7105             minor_unit_type => 'months',
7106             );
7107              
7108             The allowable values for this option are C<days>, C<months> and C<years>.
7109              
7110             =item * C<major_unit_type>
7111              
7112             Same as C<minor_unit_type>, see above, but for major axes unit types.
7113              
7114             More than one property can be set in a call to C<set_x_axis()>:
7115              
7116             $chart->set_x_axis(
7117             name => 'Quarterly results',
7118             min => 10,
7119             max => 80,
7120             );
7121              
7122             =item * C<major_tick_mark>
7123              
7124             Set the axis major tick mark type to one of the following values:
7125              
7126             none
7127             inside
7128             outside
7129             cross (inside and outside)
7130              
7131             For example:
7132              
7133             $chart->set_x_axis( major_tick_mark => 'none',
7134             minor_tick_mark => 'inside' );
7135              
7136             =item * C<minor_tick_mark>
7137              
7138             Set the axis minor tick mark type. Same as C<major_tick_mark>, see above.
7139              
7140             =item * C<display_units>
7141              
7142             Set the display units for the axis. This can be useful if the axis numbers are very large but you don't want to represent them in scientific notation. (Applicable to value axes only.) The available display units are:
7143              
7144             hundreds
7145             thousands
7146             ten_thousands
7147             hundred_thousands
7148             millions
7149             ten_millions
7150             hundred_millions
7151             billions
7152             trillions
7153              
7154             Example:
7155              
7156             $chart->set_x_axis( display_units => 'thousands' )
7157             $chart->set_y_axis( display_units => 'millions' )
7158              
7159              
7160             * C<display_units_visible>
7161              
7162             Control the visibility of the display units turned on by the previous option. This option is on by default. (Applicable to value axes only.)::
7163              
7164             $chart->set_x_axis( display_units => 'thousands',
7165             display_units_visible => 0 )
7166              
7167             =back
7168              
7169             =head2 set_y_axis()
7170              
7171             The C<set_y_axis()> method is used to set properties of the Y axis. The properties that can be set are the same as for C<set_x_axis>, see above.
7172              
7173              
7174             =head2 set_x2_axis()
7175              
7176             The C<set_x2_axis()> method is used to set properties of the secondary X axis.
7177             The properties that can be set are the same as for C<set_x_axis>, see above.
7178             The default properties for this axis are:
7179              
7180             label_position => 'none',
7181             crossing => 'max',
7182             visible => 0,
7183              
7184              
7185             =head2 set_y2_axis()
7186              
7187             The C<set_y2_axis()> method is used to set properties of the secondary Y axis.
7188             The properties that can be set are the same as for C<set_x_axis>, see above.
7189             The default properties for this axis are:
7190              
7191             major_gridlines => { visible => 0 }
7192              
7193              
7194             =head2 combine()
7195              
7196             The chart C<combine()> method is used to combine two charts of different
7197             types, for example a column and line chart:
7198              
7199             my $column_chart = $workbook->add_chart( type => 'column', embedded => 1 );
7200              
7201             # Configure the data series for the primary chart.
7202             $column_chart->add_series(...);
7203              
7204             # Create a new column chart. This will use this as the secondary chart.
7205             my $line_chart = $workbook->add_chart( type => 'line', embedded => 1 );
7206              
7207             # Configure the data series for the secondary chart.
7208             $line_chart->add_series(...);
7209              
7210             # Combine the charts.
7211             $column_chart->combine( $line_chart );
7212              
7213             See L<Combined Charts> for more details.
7214              
7215              
7216             =head2 set_size()
7217              
7218             The C<set_size()> method is used to set the dimensions of the chart. The size properties that can be set are:
7219              
7220             width
7221             height
7222             x_scale
7223             y_scale
7224             x_offset
7225             y_offset
7226              
7227             The C<width> and C<height> are in pixels. The default chart width is 480 pixels and the default height is 288 pixels. The size of the chart can be modified by setting the C<width> and C<height> or by setting the C<x_scale> and C<y_scale>:
7228              
7229             $chart->set_size( width => 720, height => 576 );
7230              
7231             # Same as:
7232              
7233             $chart->set_size( x_scale => 1.5, y_scale => 2 );
7234              
7235             The C<x_offset> and C<y_offset> position the top left corner of the chart in the cell that it is inserted into.
7236              
7237              
7238             Note: the C<x_scale>, C<y_scale>, C<x_offset> and C<y_offset> parameters can also be set via the C<insert_chart()> method:
7239              
7240             $worksheet->insert_chart( 'E2', $chart, { x_offset =>2, y_offset => 4,
7241             x_scale => 1.5, y_scale => 2 } );
7242              
7243              
7244             =head2 set_title()
7245              
7246             The C<set_title()> method is used to set properties of the chart title.
7247              
7248             $chart->set_title( name => 'Year End Results' );
7249              
7250             The properties that can be set are:
7251              
7252             =over
7253              
7254             =item * C<name>
7255              
7256             Set the name (title) for the chart. The name is displayed above the chart. The name can also be a formula such as C<=Sheet1!$A$1>. The name property is optional. The default is to have no chart title.
7257              
7258             =item * C<name_font>
7259              
7260             Set the font properties for the chart title. See the L</CHART FONTS> section below.
7261              
7262             =item * C<overlay>
7263              
7264             Allow the title to be overlaid on the chart. Generally used with the layout property below.
7265              
7266             =item * C<layout>
7267              
7268             Set the C<(x, y)> position of the title in chart relative units:
7269              
7270             $chart->set_title(
7271             name => 'Title',
7272             overlay => 1,
7273             layout => {
7274             x => 0.42,
7275             y => 0.14,
7276             }
7277             );
7278              
7279             See the L</CHART LAYOUT> section below.
7280              
7281             =item * C<none>
7282              
7283             By default Excel adds an automatic chart title to charts with a single series and a user defined series name. The C<none> option turns this default title off. It also turns off all other C<set_title()> options.
7284              
7285             $chart->set_title( none => 1 );
7286              
7287             =back
7288              
7289              
7290             =head2 set_legend()
7291              
7292             The C<set_legend()> method is used to set properties of the chart legend.
7293              
7294              
7295             The properties that can be set are:
7296              
7297             =over
7298              
7299             =item * C<none>
7300              
7301             The C<none> option turns off the chart legend. In Excel chart legends are on by default:
7302              
7303             $chart->set_legend( none => 1 );
7304              
7305             Note, for backward compatibility, it is also possible to turn off the legend via the C<position> property:
7306              
7307             $chart->set_legend( position => 'none' );
7308              
7309             =item * C<position>
7310              
7311             Set the position of the chart legend.
7312              
7313             $chart->set_legend( position => 'bottom' );
7314              
7315             The default legend position is C<right>. The available positions are:
7316              
7317             top
7318             bottom
7319             left
7320             right
7321             top_right
7322             overlay_left
7323             overlay_right
7324             overlay_top_right
7325             none
7326              
7327             =item * C<border>
7328              
7329             Set the border properties of the legend such as colour and style. See the L</CHART FORMATTING> section below.
7330              
7331             =item * C<fill>
7332              
7333             Set the fill properties of the legend such as colour. See the L</CHART FORMATTING> section below.
7334              
7335             =item * C<pattern>
7336              
7337             Set the pattern fill properties of the legend. See the L</CHART FORMATTING> section below.
7338              
7339             =item * C<gradient>
7340              
7341             Set the gradient fill properties of the legend. See the L</CHART FORMATTING> section below.
7342              
7343              
7344             =item * C<font>
7345              
7346             Set the font properties of the chart legend:
7347              
7348             $chart->set_legend( font => { bold => 1, italic => 1 } );
7349              
7350             See the L</CHART FONTS> section below.
7351              
7352             =item * C<delete_series>
7353              
7354             This allows you to remove 1 or more series from the legend (the series will still display on the chart). This property takes an array ref as an argument and the series are zero indexed:
7355              
7356             # Delete/hide series index 0 and 2 from the legend.
7357             $chart->set_legend( delete_series => [0, 2] );
7358              
7359             =item * C<layout>
7360              
7361             Set the C<(x, y)> position of the legend in chart relative units:
7362              
7363             $chart->set_legend(
7364             layout => {
7365             x => 0.80,
7366             y => 0.37,
7367             width => 0.12,
7368             height => 0.25,
7369             }
7370             );
7371              
7372             See the L</CHART LAYOUT> section below.
7373              
7374             =back
7375              
7376              
7377             =head2 set_chartarea()
7378              
7379             The C<set_chartarea()> method is used to set the properties of the chart area.
7380              
7381             $chart->set_chartarea(
7382             border => { none => 1 },
7383             fill => { color => 'red' }
7384             );
7385              
7386             The properties that can be set are:
7387              
7388             =over
7389              
7390             =item * C<border>
7391              
7392             Set the border properties of the chartarea such as colour and style. See the L</CHART FORMATTING> section below.
7393              
7394             =item * C<fill>
7395              
7396             Set the fill properties of the chartarea such as colour. See the L</CHART FORMATTING> section below.
7397              
7398             =item * C<pattern>
7399              
7400             Set the pattern fill properties of the chartarea. See the L</CHART FORMATTING> section below.
7401              
7402             =item * C<gradient>
7403              
7404             Set the gradient fill properties of the chartarea. See the L</CHART FORMATTING> section below.
7405              
7406              
7407             =back
7408              
7409             =head2 set_plotarea()
7410              
7411             The C<set_plotarea()> method is used to set properties of the plot area of a chart.
7412              
7413             $chart->set_plotarea(
7414             border => { color => 'yellow', width => 1, dash_type => 'dash' },
7415             fill => { color => '#92D050' }
7416             );
7417              
7418             The properties that can be set are:
7419              
7420             =over
7421              
7422             =item * C<border>
7423              
7424             Set the border properties of the plotarea such as colour and style. See the L</CHART FORMATTING> section below.
7425              
7426             =item * C<fill>
7427              
7428             Set the fill properties of the plotarea such as colour. See the L</CHART FORMATTING> section below.
7429              
7430              
7431             =item * C<pattern>
7432              
7433             Set the pattern fill properties of the plotarea. See the L</CHART FORMATTING> section below.
7434              
7435             =item * C<gradient>
7436              
7437             Set the gradient fill properties of the plotarea. See the L</CHART FORMATTING> section below.
7438              
7439             =item * C<layout>
7440              
7441             Set the C<(x, y)> position of the plotarea in chart relative units:
7442              
7443             $chart->set_plotarea(
7444             layout => {
7445             x => 0.35,
7446             y => 0.26,
7447             width => 0.62,
7448             height => 0.50,
7449             }
7450             );
7451              
7452             See the L</CHART LAYOUT> section below.
7453              
7454             =back
7455              
7456              
7457             =head2 set_style()
7458              
7459             The C<set_style()> method is used to set the style of the chart to one of the 42 built-in styles available on the 'Design' tab in Excel:
7460              
7461             $chart->set_style( 4 );
7462              
7463             The default style is 2.
7464              
7465              
7466             =head2 set_table()
7467              
7468             The C<set_table()> method adds a data table below the horizontal axis with the data used to plot the chart.
7469              
7470             $chart->set_table();
7471              
7472             The available options, with default values are:
7473              
7474             vertical => 1 # Display vertical lines in the table.
7475             horizontal => 1 # Display horizontal lines in the table.
7476             outline => 1 # Display an outline in the table.
7477             show_keys => 0 # Show the legend keys with the table data.
7478             font => {} # Standard chart font properties.
7479              
7480             The data table can only be shown with Bar, Column, Line, Area and stock charts. For font properties see the L</CHART FONTS> section below.
7481              
7482              
7483             =head2 set_up_down_bars
7484              
7485             The C<set_up_down_bars()> method adds Up-Down bars to Line charts to indicate the difference between the first and last data series.
7486              
7487             $chart->set_up_down_bars();
7488              
7489             It is possible to format the up and down bars to add C<fill>, C<pattern>, C<gradient> and C<border> properties if required. See the L</CHART FORMATTING> section below.
7490              
7491             $chart->set_up_down_bars(
7492             up => { fill => { color => 'green' } },
7493             down => { fill => { color => 'red' } },
7494             );
7495              
7496             Up-down bars can only be applied to Line charts and to Stock charts (by default).
7497              
7498              
7499             =head2 set_drop_lines
7500              
7501             The C<set_drop_lines()> method adds Drop Lines to charts to show the Category value of points in the data.
7502              
7503             $chart->set_drop_lines();
7504              
7505             It is possible to format the Drop Line C<line> properties if required. See the L</CHART FORMATTING> section below.
7506              
7507             $chart->set_drop_lines( line => { color => 'red', dash_type => 'square_dot' } );
7508              
7509             Drop Lines are only available in Line, Area and Stock charts.
7510              
7511              
7512             =head2 set_high_low_lines
7513              
7514             The C<set_high_low_lines()> method adds High-Low lines to charts to show the maximum and minimum values of points in a Category.
7515              
7516             $chart->set_high_low_lines();
7517              
7518             It is possible to format the High-Low Line C<line> properties if required. See the L</CHART FORMATTING> section below.
7519              
7520             $chart->set_high_low_lines( line => { color => 'red' } );
7521              
7522             High-Low Lines are only available in Line and Stock charts.
7523              
7524              
7525             =head2 show_blanks_as()
7526              
7527             The C<show_blanks_as()> method controls how blank data is displayed in a chart.
7528              
7529             $chart->show_blanks_as( 'span' );
7530              
7531             The available options are:
7532              
7533             gap # Blank data is shown as a gap. The default.
7534             zero # Blank data is displayed as zero.
7535             span # Blank data is connected with a line.
7536              
7537              
7538             =head2 show_hidden_data()
7539              
7540             Display data in hidden rows or columns on the chart.
7541              
7542             $chart->show_hidden_data();
7543              
7544              
7545             =head1 SERIES OPTIONS
7546              
7547             This section details the following properties of C<add_series()> in more detail:
7548              
7549             marker
7550             trendline
7551             y_error_bars
7552             x_error_bars
7553             data_labels
7554             points
7555             smooth
7556              
7557             =head2 Marker
7558              
7559             The marker format specifies the properties of the markers used to distinguish series on a chart. In general only Line and Scatter chart types and trendlines use markers.
7560              
7561             The following properties can be set for C<marker> formats in a chart.
7562              
7563             type
7564             size
7565             border
7566             fill
7567             pattern
7568             gradient
7569              
7570             The C<type> property sets the type of marker that is used with a series.
7571              
7572             $chart->add_series(
7573             values => '=Sheet1!$B$1:$B$5',
7574             marker => { type => 'diamond' },
7575             );
7576              
7577             The following C<type> properties can be set for C<marker> formats in a chart. These are shown in the same order as in the Excel format dialog.
7578              
7579             automatic
7580             none
7581             square
7582             diamond
7583             triangle
7584             x
7585             star
7586             short_dash
7587             long_dash
7588             circle
7589             plus
7590              
7591             The C<automatic> type is a special case which turns on a marker using the default marker style for the particular series number.
7592              
7593             $chart->add_series(
7594             values => '=Sheet1!$B$1:$B$5',
7595             marker => { type => 'automatic' },
7596             );
7597              
7598             If C<automatic> is on then other marker properties such as size, border or fill cannot be set.
7599              
7600             The C<size> property sets the size of the marker and is generally used in conjunction with C<type>.
7601              
7602             $chart->add_series(
7603             values => '=Sheet1!$B$1:$B$5',
7604             marker => { type => 'diamond', size => 7 },
7605             );
7606              
7607             Nested C<border> and C<fill> properties can also be set for a marker. See the L</CHART FORMATTING> section below.
7608              
7609             $chart->add_series(
7610             values => '=Sheet1!$B$1:$B$5',
7611             marker => {
7612             type => 'square',
7613             size => 5,
7614             border => { color => 'red' },
7615             fill => { color => 'yellow' },
7616             },
7617             );
7618              
7619              
7620             =head2 Trendline
7621              
7622             A trendline can be added to a chart series to indicate trends in the data such as a moving average or a polynomial fit.
7623              
7624             The following properties can be set for trendlines in a chart series.
7625              
7626             type
7627             order (for polynomial trends)
7628             period (for moving average)
7629             forward (for all except moving average)
7630             backward (for all except moving average)
7631             name
7632             line
7633             intercept (for exponential, linear and polynomial only)
7634             display_equation (for all except moving average)
7635             display_r_squared (for all except moving average)
7636              
7637              
7638             The C<type> property sets the type of trendline in the series.
7639              
7640             $chart->add_series(
7641             values => '=Sheet1!$B$1:$B$5',
7642             trendline => { type => 'linear' },
7643             );
7644              
7645             The available C<trendline> types are:
7646              
7647             exponential
7648             linear
7649             log
7650             moving_average
7651             polynomial
7652             power
7653              
7654             A C<polynomial> trendline can also specify the C<order> of the polynomial. The default value is 2.
7655              
7656             $chart->add_series(
7657             values => '=Sheet1!$B$1:$B$5',
7658             trendline => {
7659             type => 'polynomial',
7660             order => 3,
7661             },
7662             );
7663              
7664             A C<moving_average> trendline can also specify the C<period> of the moving average. The default value is 2.
7665              
7666             $chart->add_series(
7667             values => '=Sheet1!$B$1:$B$5',
7668             trendline => {
7669             type => 'moving_average',
7670             period => 3,
7671             },
7672             );
7673              
7674             The C<forward> and C<backward> properties set the forecast period of the trendline.
7675              
7676             $chart->add_series(
7677             values => '=Sheet1!$B$1:$B$5',
7678             trendline => {
7679             type => 'linear',
7680             forward => 0.5,
7681             backward => 0.5,
7682             },
7683             );
7684              
7685             The C<name> property sets an optional name for the trendline that will appear in the chart legend. If it isn't specified the Excel default name will be displayed. This is usually a combination of the trendline type and the series name.
7686              
7687             $chart->add_series(
7688             values => '=Sheet1!$B$1:$B$5',
7689             trendline => {
7690             type => 'linear',
7691             name => 'Interpolated trend',
7692             },
7693             );
7694              
7695             The C<intercept> property sets the point where the trendline crosses the Y (value) axis:
7696              
7697             $chart->add_series(
7698             values => '=Sheet1!$B$1:$B$5',
7699             trendline => {
7700             type => 'linear',
7701             intercept => 0.8,
7702             },
7703             );
7704              
7705              
7706             The C<display_equation> property displays the trendline equation on the chart.
7707              
7708             $chart->add_series(
7709             values => '=Sheet1!$B$1:$B$5',
7710             trendline => {
7711             type => 'linear',
7712             display_equation => 1,
7713             },
7714             );
7715              
7716             The C<display_r_squared> property displays the R squared value of the trendline on the chart.
7717              
7718             $chart->add_series(
7719             values => '=Sheet1!$B$1:$B$5',
7720             trendline => {
7721             type => 'linear',
7722             display_r_squared => 1
7723             },
7724             );
7725              
7726              
7727             Several of these properties can be set in one go:
7728              
7729             $chart->add_series(
7730             values => '=Sheet1!$B$1:$B$5',
7731             trendline => {
7732             type => 'polynomial',
7733             name => 'My trend name',
7734             order => 2,
7735             forward => 0.5,
7736             backward => 0.5,
7737             intercept => 1.5,
7738             display_equation => 1,
7739             display_r_squared => 1,
7740             line => {
7741             color => 'red',
7742             width => 1,
7743             dash_type => 'long_dash',
7744             }
7745             },
7746             );
7747              
7748             Trendlines cannot be added to series in a stacked chart or pie chart, radar chart, doughnut or (when implemented) to 3D, or surface charts.
7749              
7750             =head2 Error Bars
7751              
7752             Error bars can be added to a chart series to indicate error bounds in the data. The error bars can be vertical C<y_error_bars> (the most common type) or horizontal C<x_error_bars> (for Bar and Scatter charts only).
7753              
7754             The following properties can be set for error bars in a chart series.
7755              
7756             type
7757             value (for all types except standard error and custom)
7758             plus_values (for custom only)
7759             minus_values (for custom only)
7760             direction
7761             end_style
7762             line
7763              
7764             The C<type> property sets the type of error bars in the series.
7765              
7766             $chart->add_series(
7767             values => '=Sheet1!$B$1:$B$5',
7768             y_error_bars => { type => 'standard_error' },
7769             );
7770              
7771             The available error bars types are available:
7772              
7773             fixed
7774             percentage
7775             standard_deviation
7776             standard_error
7777             custom
7778              
7779             All error bar types, except for C<standard_error> and C<custom> must also have a value associated with it for the error bounds:
7780              
7781             $chart->add_series(
7782             values => '=Sheet1!$B$1:$B$5',
7783             y_error_bars => {
7784             type => 'percentage',
7785             value => 5,
7786             },
7787             );
7788              
7789             The C<custom> error bar type must specify C<plus_values> and C<minus_values> which should either by a C<Sheet1!$A$1:$A$5> type range formula or an arrayref of
7790             values:
7791              
7792             $chart->add_series(
7793             categories => '=Sheet1!$A$1:$A$5',
7794             values => '=Sheet1!$B$1:$B$5',
7795             y_error_bars => {
7796             type => 'custom',
7797             plus_values => '=Sheet1!$C$1:$C$5',
7798             minus_values => '=Sheet1!$D$1:$D$5',
7799             },
7800             );
7801              
7802             # or
7803              
7804              
7805             $chart->add_series(
7806             categories => '=Sheet1!$A$1:$A$5',
7807             values => '=Sheet1!$B$1:$B$5',
7808             y_error_bars => {
7809             type => 'custom',
7810             plus_values => [1, 1, 1, 1, 1],
7811             minus_values => [2, 2, 2, 2, 2],
7812             },
7813             );
7814              
7815             Note, as in Excel the items in the C<minus_values> do not need to be negative.
7816              
7817             The C<direction> property sets the direction of the error bars. It should be one of the following:
7818              
7819             plus # Positive direction only.
7820             minus # Negative direction only.
7821             both # Plus and minus directions, The default.
7822              
7823             The C<end_style> property sets the style of the error bar end cap. The options are 1 (the default) or 0 (for no end cap):
7824              
7825             $chart->add_series(
7826             values => '=Sheet1!$B$1:$B$5',
7827             y_error_bars => {
7828             type => 'fixed',
7829             value => 2,
7830             end_style => 0,
7831             direction => 'minus'
7832             },
7833             );
7834              
7835              
7836              
7837             =head2 Data Labels
7838              
7839             Data labels can be added to a chart series to indicate the values of the plotted data points.
7840              
7841             The following properties can be set for C<data_labels> formats in a chart.
7842              
7843             value
7844             category
7845             series_name
7846             position
7847             percentage
7848             leader_lines
7849             separator
7850             legend_key
7851             num_format
7852             font
7853             border
7854             fill
7855             pattern
7856             gradient
7857             custom
7858              
7859             The C<value> property turns on the I<Value> data label for a series.
7860              
7861             $chart->add_series(
7862             values => '=Sheet1!$B$1:$B$5',
7863             data_labels => { value => 1 },
7864             );
7865              
7866             The C<category> property turns on the I<Category Name> data label for a series.
7867              
7868             $chart->add_series(
7869             values => '=Sheet1!$B$1:$B$5',
7870             data_labels => { category => 1 },
7871             );
7872              
7873              
7874             The C<series_name> property turns on the I<Series Name> data label for a series.
7875              
7876             $chart->add_series(
7877             values => '=Sheet1!$B$1:$B$5',
7878             data_labels => { series_name => 1 },
7879             );
7880              
7881             The C<position> property is used to position the data label for a series.
7882              
7883             $chart->add_series(
7884             values => '=Sheet1!$B$1:$B$5',
7885             data_labels => { value => 1, position => 'center' },
7886             );
7887              
7888             In Excel the data label positions vary for different chart types. The allowable positions are:
7889              
7890             | Position | Line | Bar | Pie | Area |
7891             | | Scatter | Column | Doughnut | Radar |
7892             | | Stock | | | |
7893             |---------------|-----------|-----------|-----------|-----------|
7894             | center | Yes | Yes | Yes | Yes* |
7895             | right | Yes* | | | |
7896             | left | Yes | | | |
7897             | above | Yes | | | |
7898             | below | Yes | | | |
7899             | inside_base | | Yes | | |
7900             | inside_end | | Yes | Yes | |
7901             | outside_end | | Yes* | Yes | |
7902             | best_fit | | | Yes* | |
7903              
7904             Note: The * indicates the default position for each chart type in Excel, if a position isn't specified.
7905              
7906             The C<percentage> property is used to turn on the display of data labels as a I<Percentage> for a series. It is mainly used for pie and doughnut charts.
7907              
7908             $chart->add_series(
7909             values => '=Sheet1!$B$1:$B$5',
7910             data_labels => { percentage => 1 },
7911             );
7912              
7913             The C<leader_lines> property is used to turn on I<Leader Lines> for the data label for a series. It is mainly used for pie charts.
7914              
7915             $chart->add_series(
7916             values => '=Sheet1!$B$1:$B$5',
7917             data_labels => { value => 1, leader_lines => 1 },
7918             );
7919              
7920             Note: Even when leader lines are turned on they aren't automatically visible in Excel or Excel::Writer::XLSX. Due to an Excel limitation (or design) leader lines only appear if the data label is moved manually or if the data labels are very close and need to be adjusted automatically.
7921              
7922             The C<separator> property is used to change the separator between multiple data label items:
7923              
7924             $chart->add_series(
7925             values => '=Sheet1!$B$1:$B$5',
7926             data_labels => { percentage => 1 },
7927             data_labels => { value => 1, category => 1, separator => "\n" },
7928             );
7929              
7930             The separator value must be one of the following strings:
7931              
7932             ','
7933             ';'
7934             '.'
7935             "\n"
7936             ' '
7937              
7938             The C<legend_key> property is used to turn on I<Legend Key> for the data label for a series:
7939              
7940             $chart->add_series(
7941             values => '=Sheet1!$B$1:$B$5',
7942             data_labels => { value => 1, legend_key => 1 },
7943             );
7944              
7945              
7946             The C<num_format> property is used to set the number format for the data labels.
7947              
7948             $chart->add_series(
7949             values => '=Sheet1!$A$1:$A$5',
7950             data_labels => { value => 1, num_format => '#,##0.00' },
7951             );
7952              
7953             The number format is similar to the Worksheet Cell Format C<num_format> apart from the fact that a format index cannot be used. The explicit format string must be used as shown above. See L<Excel::Writer::XLSX/set_num_format()> for more information.
7954              
7955             The C<font> property is used to set the font properties of the data labels in a series:
7956              
7957             $chart->add_series(
7958             values => '=Sheet1!$A$1:$A$5',
7959             data_labels => {
7960             value => 1,
7961             font => { name => 'Consolas' }
7962             },
7963             );
7964              
7965             The C<font> property is also used to rotate the data labels in a series:
7966              
7967             $chart->add_series(
7968             values => '=Sheet1!$A$1:$A$5',
7969             data_labels => {
7970             value => 1,
7971             font => { rotation => 45 }
7972             },
7973             );
7974              
7975             See the L</CHART FONTS> section below.
7976              
7977             The C<border> property sets the border properties of the data labels such as colour and style. See the L</CHART FORMATTING> section below.
7978              
7979             The C<fill> property sets the fill properties of the data labels such as colour. See the L</CHART FORMATTING> section below.
7980              
7981             Example of setting data label formatting:
7982              
7983             $chart->add_series(
7984             categories => '=Sheet1!$A$2:$A$7',
7985             values => '=Sheet1!$B$2:$B$7',
7986             data_labels => { value => 1,
7987             border => {color => 'red'},
7988             fill => {color => 'yellow'} },
7989             );
7990              
7991             The C<pattern> property sets the pattern properties of the data labels. See the L</CHART FORMATTING> section below.
7992              
7993             The C<gradient> property sets the gradient properties of the data labels. See the L</CHART FORMATTING> section below.
7994              
7995             The C<custom> property is used to set the properties of individual data labels, see below.
7996              
7997              
7998             =head2 Custom Data Labels
7999              
8000             The C<custom> property data label property is used to set the properties of individual data labels in a series. The most common use for this is to set custom text or number labels:
8001              
8002             my $custom_labels = [
8003             { value => 'Jan' },
8004             { value => 'Feb' },
8005             { value => 'Mar' },
8006             { value => 'Apr' },
8007             { value => 'May' },
8008             { value => 'Jun' },
8009             ];
8010              
8011             $chart->add_series(
8012             categories => '=Sheet1!$A$2:$A$7',
8013             values => '=Sheet1!$B$2:$B$7',
8014             data_labels => { value => 1, custom => $custom_labels },
8015             );
8016              
8017             As shown in the previous examples th C<custom> property should be a list of dicts. Any property dict that is set to C<undef> or not included in the list will be assigned the default data label value:
8018              
8019             my $custom_labels = [
8020             undef,
8021             { value => 'Feb' },
8022             { value => 'Mar' },
8023             { value => 'Apr' },
8024             ];
8025              
8026             The property elements of the C<custom> lists should be dicts with the following allowable keys/sub-properties:
8027              
8028             value
8029             font
8030             border
8031             fill
8032             pattern
8033             gradient
8034             delete
8035              
8036             The C<value> property should be a string, number or formula string that refers to a cell from which the value will be taken:
8037              
8038             $custom_labels = [
8039             { value => '=Sheet1!$C$2' },
8040             { value => '=Sheet1!$C$3' },
8041             { value => '=Sheet1!$C$4' },
8042             { value => '=Sheet1!$C$5' },
8043             { value => '=Sheet1!$C$6' },
8044             { value => '=Sheet1!$C$7' },
8045             ];
8046              
8047             The C<font> property is used to set the font of the custom data label of a series (See the L</CHART FONTS> section below):
8048              
8049             $custom_labels = [
8050             { value => '=Sheet1!$C$1', font => { color => 'red' } },
8051             { value => '=Sheet1!$C$2', font => { color => 'red' } },
8052             { value => '=Sheet1!$C$2', font => { color => 'red' } },
8053             { value => '=Sheet1!$C$4', font => { color => 'red' } },
8054             { value => '=Sheet1!$C$5', font => { color => 'red' } },
8055             { value => '=Sheet1!$C$6', font => { color => 'red' } },
8056             ];
8057              
8058             The C<border> property sets the border properties of the data labels such as colour and style. See the L</CHART FORMATTING> section below.
8059              
8060             The C<fill> property sets the fill properties of the data labels such as colour. See the L</CHART FORMATTING> section below.
8061              
8062             Example of setting custom data label formatting:
8063              
8064             $custom_labels = [
8065             { value => 'Jan', border => {color => 'blue'} },
8066             { value => 'Feb' },
8067             { value => 'Mar' },
8068             { value => 'Apr' },
8069             { value => 'May' },
8070             { value => 'Jun', fill => {color => 'green'} },
8071             ];
8072              
8073             The C<pattern> property sets the pattern properties of the data labels. See the L</CHART FORMATTING> section below.
8074              
8075             The C<gradient> property sets the gradient properties of the data labels. See the L</CHART FORMATTING> section below.
8076              
8077             The C<delete> property can be used to delete labels in a series. This can be
8078             useful if you want to highlight one or more cells in the series, for example
8079             the maximum and the minimum:
8080              
8081             $custom_labels = [
8082             undef,
8083             { delete => 1 },
8084             { delete => 1 },
8085             { delete => 1 },
8086             { delete => 1 },
8087             undef,
8088             ];
8089              
8090              
8091             =head2 Points
8092              
8093             In general formatting is applied to an entire series in a chart. However, it is occasionally required to format individual points in a series. In particular this is required for Pie and Doughnut charts where each segment is represented by a point.
8094              
8095             In these cases it is possible to use the C<points> property of C<add_series()>:
8096              
8097             $chart->add_series(
8098             values => '=Sheet1!$A$1:$A$3',
8099             points => [
8100             { fill => { color => '#FF0000' } },
8101             { fill => { color => '#CC0000' } },
8102             { fill => { color => '#990000' } },
8103             ],
8104             );
8105              
8106             The C<points> property takes an array ref of format options (see the L</CHART FORMATTING> section below). To assign default properties to points in a series pass C<undef> values in the array ref:
8107              
8108             # Format point 3 of 3 only.
8109             $chart->add_series(
8110             values => '=Sheet1!$A$1:$A$3',
8111             points => [
8112             undef,
8113             undef,
8114             { fill => { color => '#990000' } },
8115             ],
8116             );
8117              
8118             # Format the first point only.
8119             $chart->add_series(
8120             values => '=Sheet1!$A$1:$A$3',
8121             points => [ { fill => { color => '#FF0000' } } ],
8122             );
8123              
8124             =head2 Smooth
8125              
8126             The C<smooth> option is used to set the smooth property of a line series. It is only applicable to the C<Line> and C<Scatter> chart types.
8127              
8128             $chart->add_series( values => '=Sheet1!$C$1:$C$5',
8129             smooth => 1 );
8130              
8131              
8132             =head1 CHART FORMATTING
8133              
8134             The following chart formatting properties can be set for any chart object that they apply to (and that are supported by Excel::Writer::XLSX) such as chart lines, column fill areas, plot area borders, markers, gridlines and other chart elements documented above.
8135              
8136             line
8137             border
8138             fill
8139             pattern
8140             gradient
8141              
8142             Chart formatting properties are generally set using hash refs.
8143              
8144             $chart->add_series(
8145             values => '=Sheet1!$B$1:$B$5',
8146             line => { color => 'blue' },
8147             );
8148              
8149             In some cases the format properties can be nested. For example a C<marker> may contain C<border> and C<fill> sub-properties.
8150              
8151             $chart->add_series(
8152             values => '=Sheet1!$B$1:$B$5',
8153             line => { color => 'blue' },
8154             marker => {
8155             type => 'square',
8156             size => 5,
8157             border => { color => 'red' },
8158             fill => { color => 'yellow' },
8159             },
8160             );
8161              
8162             =head2 Line
8163              
8164             The line format is used to specify properties of line objects that appear in a chart such as a plotted line on a chart or a border.
8165              
8166             The following properties can be set for C<line> formats in a chart.
8167              
8168             none
8169             color
8170             width
8171             dash_type
8172             transparency
8173              
8174              
8175             The C<none> property is uses to turn the C<line> off (it is always on by default except in Scatter charts). This is useful if you wish to plot a series with markers but without a line.
8176              
8177             $chart->add_series(
8178             values => '=Sheet1!$B$1:$B$5',
8179             line => { none => 1 },
8180             );
8181              
8182              
8183             The C<color> property sets the color of the C<line>.
8184              
8185             $chart->add_series(
8186             values => '=Sheet1!$B$1:$B$5',
8187             line => { color => 'red' },
8188             );
8189              
8190             The available colours are shown in the main L<Excel::Writer::XLSX> documentation. It is also possible to set the colour of a line with a HTML style RGB colour:
8191              
8192             $chart->add_series(
8193             line => { color => '#FF0000' },
8194             );
8195              
8196              
8197             The C<width> property sets the width of the C<line>. It should be specified in increments of 0.25 of a point as in Excel.
8198              
8199             $chart->add_series(
8200             values => '=Sheet1!$B$1:$B$5',
8201             line => { width => 3.25 },
8202             );
8203              
8204             The C<dash_type> property sets the dash style of the line.
8205              
8206             $chart->add_series(
8207             values => '=Sheet1!$B$1:$B$5',
8208             line => { dash_type => 'dash_dot' },
8209             );
8210              
8211             The following C<dash_type> values are available. They are shown in the order that they appear in the Excel dialog.
8212              
8213             solid
8214             round_dot
8215             square_dot
8216             dash
8217             dash_dot
8218             long_dash
8219             long_dash_dot
8220             long_dash_dot_dot
8221              
8222             The default line style is C<solid>.
8223              
8224             The C<transparency> property sets the transparency of the C<line> color in the integer range 1 - 100. The color must be set for transparency to work, it doesn't work with an automatic/default color:
8225              
8226             $chart->add_series(
8227             values => '=Sheet1!$B$1:$B$5',
8228             line => { color => 'yellow', transparency => 50 },
8229             );
8230              
8231             More than one C<line> property can be specified at a time:
8232              
8233             $chart->add_series(
8234             values => '=Sheet1!$B$1:$B$5',
8235             line => {
8236             color => 'red',
8237             width => 1.25,
8238             dash_type => 'square_dot',
8239             },
8240             );
8241              
8242             =head2 Border
8243              
8244             The C<border> property is a synonym for C<line>.
8245              
8246             It can be used as a descriptive substitute for C<line> in chart types such as Bar and Column that have a border and fill style rather than a line style. In general chart objects with a C<border> property will also have a fill property.
8247              
8248              
8249             =head2 Solid Fill
8250              
8251             The fill format is used to specify filled areas of chart objects such as the interior of a column or the background of the chart itself.
8252              
8253             The following properties can be set for C<fill> formats in a chart.
8254              
8255             none
8256             color
8257             transparency
8258              
8259             The C<none> property is used to turn the C<fill> property off (it is generally on by default).
8260              
8261              
8262             $chart->add_series(
8263             values => '=Sheet1!$B$1:$B$5',
8264             fill => { none => 1 },
8265             );
8266              
8267             The C<color> property sets the colour of the C<fill> area.
8268              
8269             $chart->add_series(
8270             values => '=Sheet1!$B$1:$B$5',
8271             fill => { color => 'red' },
8272             );
8273              
8274             The available colours are shown in the main L<Excel::Writer::XLSX> documentation. It is also possible to set the colour of a fill with a HTML style RGB colour:
8275              
8276             $chart->add_series(
8277             fill => { color => '#FF0000' },
8278             );
8279              
8280             The C<transparency> property sets the transparency of the solid fill color in the integer range 1 - 100. The color must be set for transparency to work, it doesn't work with an automatic/default color:
8281              
8282             $chart->set_chartarea( fill => { color => 'yellow', transparency => 75 } );
8283              
8284             The C<fill> format is generally used in conjunction with a C<border> format which has the same properties as a C<line> format.
8285              
8286             $chart->add_series(
8287             values => '=Sheet1!$B$1:$B$5',
8288             border => { color => 'red' },
8289             fill => { color => 'yellow' },
8290             );
8291              
8292              
8293              
8294             =head2 Pattern Fill
8295              
8296             The pattern fill format is used to specify pattern filled areas of chart objects such as the interior of a column or the background of the chart itself.
8297              
8298             The following properties can be set for C<pattern> fill formats in a chart:
8299              
8300             pattern: the pattern to be applied (required)
8301             fg_color: the foreground color of the pattern (required)
8302             bg_color: the background color (optional, defaults to white)
8303              
8304              
8305             For example:
8306              
8307             $chart->set_plotarea(
8308             pattern => {
8309             pattern => 'percent_5',
8310             fg_color => 'red',
8311             bg_color => 'yellow',
8312             }
8313             );
8314              
8315             The following patterns can be applied:
8316              
8317             percent_5
8318             percent_10
8319             percent_20
8320             percent_25
8321             percent_30
8322             percent_40
8323             percent_50
8324             percent_60
8325             percent_70
8326             percent_75
8327             percent_80
8328             percent_90
8329             light_downward_diagonal
8330             light_upward_diagonal
8331             dark_downward_diagonal
8332             dark_upward_diagonal
8333             wide_downward_diagonal
8334             wide_upward_diagonal
8335             light_vertical
8336             light_horizontal
8337             narrow_vertical
8338             narrow_horizontal
8339             dark_vertical
8340             dark_horizontal
8341             dashed_downward_diagonal
8342             dashed_upward_diagonal
8343             dashed_horizontal
8344             dashed_vertical
8345             small_confetti
8346             large_confetti
8347             zigzag
8348             wave
8349             diagonal_brick
8350             horizontal_brick
8351             weave
8352             plaid
8353             divot
8354             dotted_grid
8355             dotted_diamond
8356             shingle
8357             trellis
8358             sphere
8359             small_grid
8360             large_grid
8361             small_check
8362             large_check
8363             outlined_diamond
8364             solid_diamond
8365              
8366              
8367             The foreground color, C<fg_color>, is a required parameter and can be a Html style C<#RRGGBB> string or a limited number of named colors. The available colours are shown in the main L<Excel::Writer::XLSX> documentation.
8368              
8369             The background color, C<bg_color>, is optional and defaults to black.
8370              
8371             If a pattern fill is used on a chart object it overrides the solid fill properties of the object.
8372              
8373              
8374             =head2 Gradient Fill
8375              
8376             The gradient fill format is used to specify gradient filled areas of chart objects such as the interior of a column or the background of the chart itself.
8377              
8378              
8379             The following properties can be set for C<gradient> fill formats in a chart:
8380              
8381             colors: a list of colors
8382             positions: an optional list of positions for the colors
8383             type: the optional type of gradient fill
8384             angle: the optional angle of the linear fill
8385              
8386             The C<colors> property sets a list of colors that define the C<gradient>:
8387              
8388             $chart->set_plotarea(
8389             gradient => { colors => [ '#DDEBCF', '#9CB86E', '#156B13' ] }
8390             );
8391              
8392             Excel allows between 2 and 10 colors in a gradient but it is unlikely that you will require more than 2 or 3.
8393              
8394             As with solid or pattern fill it is also possible to set the colors of a gradient with a Html style C<#RRGGBB> string or a limited number of named colors. The available colours are shown in the main L<Excel::Writer::XLSX> documentation:
8395              
8396             $chart->add_series(
8397             values => '=Sheet1!$A$1:$A$5',
8398             gradient => { colors => [ 'red', 'green' ] }
8399             );
8400              
8401             The C<positions> defines an optional list of positions, between 0 and 100, of
8402             where the colors in the gradient are located. Default values are provided for
8403             C<colors> lists of between 2 and 4 but they can be specified if required:
8404              
8405             $chart->add_series(
8406             values => '=Sheet1!$A$1:$A$5',
8407             gradient => {
8408             colors => [ '#DDEBCF', '#156B13' ],
8409             positions => [ 10, 90 ],
8410             }
8411             );
8412              
8413             The C<type> property can have one of the following values:
8414              
8415             linear (the default)
8416             radial
8417             rectangular
8418             path
8419              
8420             For example:
8421              
8422             $chart->add_series(
8423             values => '=Sheet1!$A$1:$A$5',
8424             gradient => {
8425             colors => [ '#DDEBCF', '#9CB86E', '#156B13' ],
8426             type => 'radial'
8427             }
8428             );
8429              
8430             If C<type> isn't specified it defaults to C<linear>.
8431              
8432             For a C<linear> fill the angle of the gradient can also be specified:
8433              
8434             $chart->add_series(
8435             values => '=Sheet1!$A$1:$A$5',
8436             gradient => { colors => [ '#DDEBCF', '#9CB86E', '#156B13' ],
8437             angle => 30 }
8438             );
8439              
8440             The default angle is 90 degrees.
8441              
8442             If gradient fill is used on a chart object it overrides the solid fill and pattern fill properties of the object.
8443              
8444              
8445              
8446              
8447             =head1 CHART FONTS
8448              
8449             The following font properties can be set for any chart object that they apply to (and that are supported by Excel::Writer::XLSX) such as chart titles, axis labels, axis numbering and data labels. They correspond to the equivalent Worksheet cell Format object properties. See L<Excel::Writer::XLSX/FORMAT_METHODS> for more information.
8450              
8451             name
8452             size
8453             bold
8454             italic
8455             underline
8456             rotation
8457             color
8458              
8459             The following explains the available font properties:
8460              
8461             =over
8462              
8463             =item * C<name>
8464              
8465             Set the font name:
8466              
8467             $chart->set_x_axis( num_font => { name => 'Arial' } );
8468              
8469             =item * C<size>
8470              
8471             Set the font size:
8472              
8473             $chart->set_x_axis( num_font => { name => 'Arial', size => 10 } );
8474              
8475             =item * C<bold>
8476              
8477             Set the font bold property, should be 0 or 1:
8478              
8479             $chart->set_x_axis( num_font => { bold => 1 } );
8480              
8481             =item * C<italic>
8482              
8483             Set the font italic property, should be 0 or 1:
8484              
8485             $chart->set_x_axis( num_font => { italic => 1 } );
8486              
8487             =item * C<underline>
8488              
8489             Set the font underline property, should be 0 or 1:
8490              
8491             $chart->set_x_axis( num_font => { underline => 1 } );
8492              
8493             =item * C<rotation>
8494              
8495             Set the font rotation in the integer range -90 to 90, and 270-271:
8496              
8497             $chart->set_x_axis( num_font => { rotation => 45 } );
8498              
8499             This is useful for displaying large axis data such as dates in a more compact format.
8500              
8501             There are 2 special case angles outside the range -90 to 90:
8502              
8503             =over
8504              
8505             =item * 270: Stacked text, where the text runs from top to bottom.
8506              
8507             =item * 271: A special variant of stacked text for East Asian fonts.
8508              
8509             =back
8510              
8511             =item * C<color>
8512              
8513             Set the font color property. Can be a color index, a color name or HTML style RGB colour:
8514              
8515             $chart->set_x_axis( num_font => { color => 'red' } );
8516             $chart->set_y_axis( num_font => { color => '#92D050' } );
8517              
8518             =back
8519              
8520             Here is an example of Font formatting in a Chart program:
8521              
8522             # Format the chart title.
8523             $chart->set_title(
8524             name => 'Sales Results Chart',
8525             name_font => {
8526             name => 'Calibri',
8527             color => 'yellow',
8528             },
8529             );
8530              
8531             # Format the X-axis.
8532             $chart->set_x_axis(
8533             name => 'Month',
8534             name_font => {
8535             name => 'Arial',
8536             color => '#92D050'
8537             },
8538             num_font => {
8539             name => 'Courier New',
8540             color => '#00B0F0',
8541             },
8542             );
8543              
8544             # Format the Y-axis.
8545             $chart->set_y_axis(
8546             name => 'Sales (1000 units)',
8547             name_font => {
8548             name => 'Century',
8549             underline => 1,
8550             color => 'red'
8551             },
8552             num_font => {
8553             bold => 1,
8554             italic => 1,
8555             color => '#7030A0',
8556             },
8557             );
8558              
8559              
8560              
8561             =head1 CHART LAYOUT
8562              
8563             The position of the chart in the worksheet is controlled by the C<set_size()> method shown above.
8564              
8565             It is also possible to change the layout of the following chart sub-objects:
8566              
8567             plotarea
8568             legend
8569             title
8570             x_axis caption
8571             y_axis caption
8572              
8573             Here are some examples:
8574              
8575             $chart->set_plotarea(
8576             layout => {
8577             x => 0.35,
8578             y => 0.26,
8579             width => 0.62,
8580             height => 0.50,
8581             }
8582             );
8583              
8584             $chart->set_legend(
8585             layout => {
8586             x => 0.80,
8587             y => 0.37,
8588             width => 0.12,
8589             height => 0.25,
8590             }
8591             );
8592              
8593             $chart->set_title(
8594             name => 'Title',
8595             layout => {
8596             x => 0.42,
8597             y => 0.14,
8598             }
8599             );
8600              
8601             $chart->set_x_axis(
8602             name => 'X axis',
8603             name_layout => {
8604             x => 0.34,
8605             y => 0.85,
8606             }
8607             );
8608              
8609             Note that it is only possible to change the width and height for the C<plotarea> and C<legend> objects. For the other text based objects the width and height are changed by the font dimensions.
8610              
8611             The layout units must be a float in the range C<0 < x <= 1> and are expressed as a percentage of the chart dimensions as shown below:
8612              
8613             =begin html
8614              
8615             <p><center><img src="http://jmcnamara.github.io/excel-writer-xlsx/images/examples/layout.png" width="826" height="423" alt="Chart object layout." /></center></p>
8616              
8617             =end html
8618              
8619             From this the layout units are calculated as follows:
8620              
8621             layout:
8622             width = w / W
8623             height = h / H
8624             x = a / W
8625             y = b / H
8626              
8627             These units are slightly cumbersome but are required by Excel so that the chart object positions remain relative to each other if the chart is resized by the user.
8628              
8629             Note that for C<plotarea> the origin is the top left corner in the plotarea itself and does not take into account the axes.
8630              
8631              
8632             =head1 WORKSHEET METHODS
8633              
8634             In Excel a chartsheet (i.e, a chart that isn't embedded) shares properties with data worksheets such as tab selection, headers, footers, margins, and print properties.
8635              
8636             In Excel::Writer::XLSX you can set chartsheet properties using the same methods that are used for Worksheet objects.
8637              
8638             The following Worksheet methods are also available through a non-embedded Chart object:
8639              
8640             get_name()
8641             activate()
8642             select()
8643             hide()
8644             set_first_sheet()
8645             protect()
8646             set_zoom()
8647             set_tab_color()
8648              
8649             set_landscape()
8650             set_portrait()
8651             set_paper()
8652             set_margins()
8653             set_header()
8654             set_footer()
8655              
8656             See L<Excel::Writer::XLSX> for a detailed explanation of these methods.
8657              
8658             =head1 EXAMPLE
8659              
8660             Here is a complete example that demonstrates some of the available features when creating a chart.
8661              
8662             #!/usr/bin/perl
8663              
8664             use strict;
8665             use warnings;
8666             use Excel::Writer::XLSX;
8667              
8668             my $workbook = Excel::Writer::XLSX->new( 'chart.xlsx' );
8669             my $worksheet = $workbook->add_worksheet();
8670             my $bold = $workbook->add_format( bold => 1 );
8671              
8672             # Add the worksheet data that the charts will refer to.
8673             my $headings = [ 'Number', 'Batch 1', 'Batch 2' ];
8674             my $data = [
8675             [ 2, 3, 4, 5, 6, 7 ],
8676             [ 10, 40, 50, 20, 10, 50 ],
8677             [ 30, 60, 70, 50, 40, 30 ],
8678              
8679             ];
8680              
8681             $worksheet->write( 'A1', $headings, $bold );
8682             $worksheet->write( 'A2', $data );
8683              
8684             # Create a new chart object. In this case an embedded chart.
8685             my $chart = $workbook->add_chart( type => 'column', embedded => 1 );
8686              
8687             # Configure the first series.
8688             $chart->add_series(
8689             name => '=Sheet1!$B$1',
8690             categories => '=Sheet1!$A$2:$A$7',
8691             values => '=Sheet1!$B$2:$B$7',
8692             );
8693              
8694             # Configure second series. Note alternative use of array ref to define
8695             # ranges: [ $sheetname, $row_start, $row_end, $col_start, $col_end ].
8696             $chart->add_series(
8697             name => '=Sheet1!$C$1',
8698             categories => [ 'Sheet1', 1, 6, 0, 0 ],
8699             values => [ 'Sheet1', 1, 6, 2, 2 ],
8700             );
8701              
8702             # Add a chart title and some axis labels.
8703             $chart->set_title ( name => 'Results of sample analysis' );
8704             $chart->set_x_axis( name => 'Test number' );
8705             $chart->set_y_axis( name => 'Sample length (mm)' );
8706              
8707             # Set an Excel chart style. Blue colors with white outline and shadow.
8708             $chart->set_style( 11 );
8709              
8710             # Insert the chart into the worksheet (with an offset).
8711             $worksheet->insert_chart( 'D2', $chart, { x_offset => 25, y_offset => 10 } );
8712              
8713             $workbook->close();
8714              
8715             __END__
8716              
8717             =begin html
8718              
8719             <p>This will produce a chart that looks like this:</p>
8720              
8721             <p><center><img src="http://jmcnamara.github.io/excel-writer-xlsx/images/examples/area1.jpg" width="527" height="320" alt="Chart example." /></center></p>
8722              
8723             =end html
8724              
8725              
8726             =head1 Value and Category Axes
8727              
8728             Excel differentiates between a chart axis that is used for series B<categories> and an axis that is used for series B<values>.
8729              
8730             In the example above the X axis is the category axis and each of the values is evenly spaced. The Y axis (in this case) is the value axis and points are displayed according to their value.
8731              
8732             Since Excel treats the axes differently it also handles their formatting differently and exposes different properties for each.
8733              
8734             As such some of C<Excel::Writer::XLSX> axis properties can be set for a value axis, some can be set for a category axis and some properties can be set for both.
8735              
8736             For example the C<min> and C<max> properties can only be set for value axes and C<reverse> can be set for both. The type of axis that a property applies to is shown in the C<set_x_axis()> section of the documentation above.
8737              
8738             Some charts such as C<Scatter> and C<Stock> have two value axes.
8739              
8740             Date Axes are a special type of category axis which are explained below.
8741              
8742             =head1 Date Category Axes
8743              
8744             Date Category Axes are category axes that display time or date information. In Excel::Writer::XLSX Date Category Axes are set using the C<date_axis> option:
8745              
8746             $chart->set_x_axis( date_axis => 1 );
8747              
8748             In general you should also specify a number format for a date axis although Excel will usually default to the same format as the data being plotted:
8749              
8750             $chart->set_x_axis(
8751             date_axis => 1,
8752             num_format => 'dd/mm/yyyy',
8753             );
8754              
8755             Excel doesn't normally allow minimum and maximum values to be set for category axes. However, date axes are an exception. The C<min> and C<max> values should be set as Excel times or dates:
8756              
8757             $chart->set_x_axis(
8758             date_axis => 1,
8759             min => $worksheet->convert_date_time('2013-01-02T'),
8760             max => $worksheet->convert_date_time('2013-01-09T'),
8761             num_format => 'dd/mm/yyyy',
8762             );
8763              
8764             For date axes it is also possible to set the type of the major and minor units:
8765              
8766             $chart->set_x_axis(
8767             date_axis => 1,
8768             minor_unit => 4,
8769             minor_unit_type => 'months',
8770             major_unit => 1,
8771             major_unit_type => 'years',
8772             num_format => 'dd/mm/yyyy',
8773             );
8774              
8775              
8776             =head1 Secondary Axes
8777              
8778             It is possible to add a secondary axis of the same type to a chart by setting the C<y2_axis> or C<x2_axis> property of the series:
8779              
8780             #!/usr/bin/perl
8781              
8782             use strict;
8783             use warnings;
8784             use Excel::Writer::XLSX;
8785              
8786             my $workbook = Excel::Writer::XLSX->new( 'chart_secondary_axis.xlsx' );
8787             my $worksheet = $workbook->add_worksheet();
8788              
8789             # Add the worksheet data that the charts will refer to.
8790             my $data = [
8791             [ 2, 3, 4, 5, 6, 7 ],
8792             [ 10, 40, 50, 20, 10, 50 ],
8793              
8794             ];
8795              
8796             $worksheet->write( 'A1', $data );
8797              
8798             # Create a new chart object. In this case an embedded chart.
8799             my $chart = $workbook->add_chart( type => 'line', embedded => 1 );
8800              
8801             # Configure a series with a secondary axis
8802             $chart->add_series(
8803             values => '=Sheet1!$A$1:$A$6',
8804             y2_axis => 1,
8805             );
8806              
8807             $chart->add_series(
8808             values => '=Sheet1!$B$1:$B$6',
8809             );
8810              
8811              
8812             # Insert the chart into the worksheet.
8813             $worksheet->insert_chart( 'D2', $chart );
8814              
8815             $workbook->close();
8816              
8817             __END__
8818              
8819             It is also possible to have a secondary, combined, chart either with a shared or secondary axis, see below.
8820              
8821             =head1 Combined Charts
8822              
8823             It is also possible to combine two different chart types, for example a column and line chart to create a Pareto chart using the Chart C<combine()> method:
8824              
8825              
8826             =begin html
8827              
8828             <p><center><img src="https://raw.githubusercontent.com/jmcnamara/XlsxWriter/master/dev/docs/source/_images/chart_pareto.png" alt="Chart image." /></center></p>
8829              
8830             =end html
8831              
8832              
8833             Here is a simpler example:
8834              
8835             use strict;
8836             use warnings;
8837             use Excel::Writer::XLSX;
8838              
8839             my $workbook = Excel::Writer::XLSX->new( 'chart_combined.xlsx' );
8840             my $worksheet = $workbook->add_worksheet();
8841             my $bold = $workbook->add_format( bold => 1 );
8842              
8843             # Add the worksheet data that the charts will refer to.
8844             my $headings = [ 'Number', 'Batch 1', 'Batch 2' ];
8845             my $data = [
8846             [ 2, 3, 4, 5, 6, 7 ],
8847             [ 10, 40, 50, 20, 10, 50 ],
8848             [ 30, 60, 70, 50, 40, 30 ],
8849              
8850             ];
8851              
8852             $worksheet->write( 'A1', $headings, $bold );
8853             $worksheet->write( 'A2', $data );
8854              
8855             #
8856             # In the first example we will create a combined column and line chart.
8857             # They will share the same X and Y axes.
8858             #
8859              
8860             # Create a new column chart. This will use this as the primary chart.
8861             my $column_chart = $workbook->add_chart( type => 'column', embedded => 1 );
8862              
8863             # Configure the data series for the primary chart.
8864             $column_chart->add_series(
8865             name => '=Sheet1!$B$1',
8866             categories => '=Sheet1!$A$2:$A$7',
8867             values => '=Sheet1!$B$2:$B$7',
8868             );
8869              
8870             # Create a new column chart. This will use this as the secondary chart.
8871             my $line_chart = $workbook->add_chart( type => 'line', embedded => 1 );
8872              
8873             # Configure the data series for the secondary chart.
8874             $line_chart->add_series(
8875             name => '=Sheet1!$C$1',
8876             categories => '=Sheet1!$A$2:$A$7',
8877             values => '=Sheet1!$C$2:$C$7',
8878             );
8879              
8880             # Combine the charts.
8881             $column_chart->combine( $line_chart );
8882              
8883             # Add a chart title and some axis labels. Note, this is done via the
8884             # primary chart.
8885             $column_chart->set_title( name => 'Combined chart - same Y axis' );
8886             $column_chart->set_x_axis( name => 'Test number' );
8887             $column_chart->set_y_axis( name => 'Sample length (mm)' );
8888              
8889              
8890             # Insert the chart into the worksheet
8891             $worksheet->insert_chart( 'E2', $column_chart );
8892              
8893             $workbook->close();
8894              
8895             =begin html
8896              
8897             <p><center><img src="https://raw.githubusercontent.com/jmcnamara/XlsxWriter/master/dev/docs/source/_images/chart_combined1.png" alt="Chart image." /></center></p>
8898              
8899             =end html
8900              
8901              
8902              
8903             The secondary chart can also be placed on a secondary axis using the methods shown in the previous section.
8904              
8905             In this case it is just necessary to add a C<y2_axis> parameter to the series and, if required, add a title using C<set_y2_axis()> B<of the secondary chart>. The following are the additions to the previous example to place the secondary chart on the secondary axis:
8906              
8907             ...
8908              
8909             $line_chart->add_series(
8910             name => '=Sheet1!$C$1',
8911             categories => '=Sheet1!$A$2:$A$7',
8912             values => '=Sheet1!$C$2:$C$7',
8913             y2_axis => 1,
8914             );
8915              
8916             ...
8917              
8918             # Note: the y2 properites are on the secondary chart.
8919             $line_chart2->set_y2_axis( name => 'Target length (mm)' );
8920              
8921              
8922             =begin html
8923              
8924             <p><center><img src="https://raw.githubusercontent.com/jmcnamara/XlsxWriter/master/dev/docs/source/_images/chart_combined2.png" alt="Chart image." /></center></p>
8925              
8926             =end html
8927              
8928              
8929             The examples above use the concept of a I<primary> and I<secondary> chart. The primary chart is the chart that defines the primary X and Y axis. It is also used for setting all chart properties apart from the secondary data series. For example the chart title and axes properties should be set via the primary chart (except for the the secondary C<y2> axis properties which should be applied to the secondary chart).
8930              
8931             See also C<chart_combined.pl> and C<chart_pareto.pl> examples in the distro for more detailed
8932             examples.
8933              
8934             There are some limitations on combined charts:
8935              
8936             =over
8937              
8938             =item * Pie charts cannot currently be combined.
8939              
8940             =item * Scatter charts cannot currently be used as a primary chart but they can be used as a secondary chart.
8941              
8942             =item * Bar charts can only combined secondary charts on a secondary axis. This is an Excel limitation.
8943              
8944             =back
8945              
8946              
8947             =head1 AUTHOR
8948              
8949             John McNamara jmcnamara@cpan.org
8950              
8951             =head1 COPYRIGHT
8952              
8953             Copyright MM-MMXXI, John McNamara.
8954              
8955             All Rights Reserved. This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.