File Coverage

blib/lib/Excel/Writer/XLSX/Format.pm
Criterion Covered Total %
statement 203 217 93.5
branch 132 154 85.7
condition 13 18 72.2
subroutine 30 32 93.7
pod 0 22 0.0
total 378 443 85.3


line stmt bran cond sub pod time code
1              
2             ###############################################################################
3             #
4             # Format - A class for defining Excel formatting.
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             use 5.008002;
15 1126     1126   15438 use Exporter;
  1126         13779  
16 1126     1126   6588 use strict;
  1126         1904  
  1126         34759  
17 1126     1126   5450 use warnings;
  1126         1908  
  1126         22125  
18 1126     1126   4848 use Carp;
  1126         2032  
  1126         25111  
19 1126     1126   5009  
  1126         2007  
  1126         2237900  
20              
21             our @ISA = qw(Exporter);
22             our $VERSION = '1.09';
23             our $AUTOLOAD;
24              
25              
26             ###############################################################################
27             #
28             # new()
29             #
30             # Constructor
31             #
32              
33             my $class = shift;
34              
35 2148     2148 0 40423 my $self = {
36             _xf_format_indices => shift,
37 2148         49881 _dxf_format_indices => shift,
38             _xf_index => undef,
39             _dxf_index => undef,
40              
41             _num_format => 'General',
42             _num_format_index => 0,
43             _font_index => 0,
44             _has_font => 0,
45             _has_dxf_font => 0,
46             _font => 'Calibri',
47             _size => 11,
48             _bold => 0,
49             _italic => 0,
50             _color => 0x0,
51             _underline => 0,
52             _font_strikeout => 0,
53             _font_outline => 0,
54             _font_shadow => 0,
55             _font_script => 0,
56             _font_family => 2,
57             _font_charset => 0,
58             _font_scheme => 'minor',
59             _font_condense => 0,
60             _font_extend => 0,
61             _theme => 0,
62             _hyperlink => 0,
63             _xf_id => 0,
64              
65             _hidden => 0,
66             _locked => 1,
67              
68             _text_h_align => 0,
69             _text_wrap => 0,
70             _text_v_align => 0,
71             _text_justlast => 0,
72             _rotation => 0,
73              
74             _fg_color => 0x00,
75             _bg_color => 0x00,
76             _pattern => 0,
77             _has_fill => 0,
78             _has_dxf_fill => 0,
79             _fill_index => 0,
80             _fill_count => 0,
81              
82             _border_index => 0,
83             _has_border => 0,
84             _has_dxf_border => 0,
85             _border_count => 0,
86              
87             _bottom => 0,
88             _bottom_color => 0x0,
89             _diag_border => 0,
90             _diag_color => 0x0,
91             _diag_type => 0,
92             _left => 0,
93             _left_color => 0x0,
94             _right => 0,
95             _right_color => 0x0,
96             _top => 0,
97             _top_color => 0x0,
98              
99             _indent => 0,
100             _shrink => 0,
101             _merge_range => 0,
102             _reading_order => 0,
103             _just_distrib => 0,
104             _color_indexed => 0,
105             _font_only => 0,
106              
107             };
108              
109             bless $self, $class;
110              
111 2148         4266 # Set properties passed to Workbook::add_format()
112             $self->set_format_properties(@_) if @_;
113              
114 2148 100       9027 return $self;
115             }
116 2148         5845  
117              
118             ###############################################################################
119             #
120             # copy($format)
121             #
122             # Copy the attributes of another Excel::Writer::XLSX::Format object.
123             #
124             my $self = shift;
125             my $other = $_[0];
126              
127 2     2 0 7  
128 2         4 return unless defined $other;
129             return unless ( ref( $self ) eq ref( $other ) );
130              
131 2 50       5 # Store properties that we don't want over-ridden.
132 2 50       6 my $xf_index = $self->{_xf_index};
133             my $dxf_index = $self->{_dxf_index};
134             my $xf_format_indices = $self->{_xf_format_indices};
135 2         4 my $dxf_format_indices = $self->{_dxf_format_indices};
136 2         2 my $palette = $self->{_palette};
137 2         4  
138 2         3 # Copy properties.
139 2         4 %$self = %$other;
140              
141             # Restore original properties.
142 2         38 $self->{_xf_index} = $xf_index;
143             $self->{_dxf_index} = $dxf_index;
144             $self->{_xf_format_indices} = $xf_format_indices;
145 2         7 $self->{_dxf_format_indices} = $dxf_format_indices;
146 2         4 $self->{_palette} = $palette;
147 2         4 }
148 2         3  
149 2         17  
150             ###############################################################################
151             #
152             # get_align_properties()
153             #
154             # Return properties for an Style xf <alignment> sub-element.
155             #
156              
157             my $self = shift;
158              
159             my @align; # Attributes to return
160              
161 1207     1207 0 2378 # Check if any alignment options in the format have been changed.
162             my $changed =
163 1207         2062 ( $self->{_text_h_align} != 0
164             || $self->{_text_v_align} != 0
165             || $self->{_indent} != 0
166             || $self->{_rotation} != 0
167             || $self->{_text_wrap} != 0
168             || $self->{_shrink} != 0
169             || $self->{_reading_order} != 0 ) ? 1 : 0;
170              
171             return unless $changed;
172              
173 1207 100 100     22398  
174              
175 1207 100       5930 # Indent is only allowed for horizontal left, right and distributed. If it
176             # is defined for any other alignment or no alignment has been set then
177             # default to left alignment.
178             if ( $self->{_indent}
179             && $self->{_text_h_align} != 1
180             && $self->{_text_h_align} != 3
181             && $self->{_text_h_align} != 7 )
182 45 100 100     140 {
      100        
      100        
183             $self->{_text_h_align} = 1;
184             }
185              
186             # Check for properties that are mutually exclusive.
187 1         3 $self->{_shrink} = 0 if $self->{_text_wrap};
188             $self->{_shrink} = 0 if $self->{_text_h_align} == 4; # Fill
189             $self->{_shrink} = 0 if $self->{_text_h_align} == 5; # Justify
190             $self->{_shrink} = 0 if $self->{_text_h_align} == 7; # Distributed
191 45 100       133 $self->{_just_distrib} = 0 if $self->{_text_h_align} != 7; # Distributed
192 45 100       125 $self->{_just_distrib} = 0 if $self->{_indent};
193 45 100       128  
194 45 100       110 my $continuous = 'centerContinuous';
195 45 100       109  
196 45 100       94 push @align, 'horizontal', 'left' if $self->{_text_h_align} == 1;
197             push @align, 'horizontal', 'center' if $self->{_text_h_align} == 2;
198 45         63 push @align, 'horizontal', 'right' if $self->{_text_h_align} == 3;
199             push @align, 'horizontal', 'fill' if $self->{_text_h_align} == 4;
200 45 100       144 push @align, 'horizontal', 'justify' if $self->{_text_h_align} == 5;
201 45 100       113 push @align, 'horizontal', $continuous if $self->{_text_h_align} == 6;
202 45 100       103 push @align, 'horizontal', 'distributed' if $self->{_text_h_align} == 7;
203 45 100       103  
204 45 100       121 push @align, 'justifyLastLine', 1 if $self->{_just_distrib};
205 45 100       92  
206 45 100       97 # Property 'vertical' => 'bottom' is a default. It sets applyAlignment
207             # without an alignment sub-element.
208 45 100       118 push @align, 'vertical', 'top' if $self->{_text_v_align} == 1;
209             push @align, 'vertical', 'center' if $self->{_text_v_align} == 2;
210             push @align, 'vertical', 'justify' if $self->{_text_v_align} == 4;
211             push @align, 'vertical', 'distributed' if $self->{_text_v_align} == 5;
212 45 100       116  
213 45 100       118 push @align, 'indent', $self->{_indent} if $self->{_indent};
214 45 100       102 push @align, 'textRotation', $self->{_rotation} if $self->{_rotation};
215 45 100       83  
216             push @align, 'wrapText', 1 if $self->{_text_wrap};
217 45 100       92 push @align, 'shrinkToFit', 1 if $self->{_shrink};
218 45 100       104  
219             push @align, 'readingOrder', 1 if $self->{_reading_order} == 1;
220 45 100       84 push @align, 'readingOrder', 2 if $self->{_reading_order} == 2;
221 45 100       85  
222             return $changed, @align;
223 45 100       95 }
224 45 100       98  
225              
226 45         168 ###############################################################################
227             #
228             # get_protection_properties()
229             #
230             # Return properties for an Excel XML <Protection> element.
231             #
232              
233             my $self = shift;
234              
235             my @attribs;
236              
237             push @attribs, 'locked', 0 if !$self->{_locked};
238 1207     1207 0 2416 push @attribs, 'hidden', 1 if $self->{_hidden};
239              
240 1207         2038 return @attribs;
241             }
242 1207 100       3943  
243 1207 100       4222  
244             ###############################################################################
245 1207         3253 #
246             # get_format_key()
247             #
248             # Returns a unique hash key for the Format object.
249             #
250              
251             my $self = shift;
252              
253             my $key = join ':',
254             (
255             $self->get_font_key(), $self->get_border_key,
256             $self->get_fill_key(), $self->get_alignment_key(),
257 262     262 0 426 $self->{_num_format}, $self->{_locked},
258             $self->{_hidden}
259             );
260              
261             return $key;
262             }
263              
264             ###############################################################################
265 262         711 #
266             # get_font_key()
267 262         669 #
268             # Returns a unique hash key for a font. Used by Workbook.
269             #
270              
271             my $self = shift;
272              
273             my $key = join ':', (
274             $self->{_bold},
275             $self->{_color},
276             $self->{_font_charset},
277             $self->{_font_family},
278 1435     1435 0 2481 $self->{_font_outline},
279             $self->{_font_script},
280             $self->{_font_shadow},
281             $self->{_font_strikeout},
282             $self->{_font},
283             $self->{_italic},
284             $self->{_size},
285             $self->{_underline},
286             $self->{_theme},
287              
288             );
289              
290             return $key;
291             }
292              
293              
294             ###############################################################################
295 1435         9821 #
296             # get_border_key()
297 1435         3734 #
298             # Returns a unique hash key for a border style. Used by Workbook.
299             #
300              
301             my $self = shift;
302              
303             my $key = join ':', (
304             $self->{_bottom},
305             $self->{_bottom_color},
306             $self->{_diag_border},
307             $self->{_diag_color},
308             $self->{_diag_type},
309 1468     1468 0 2480 $self->{_left},
310             $self->{_left_color},
311             $self->{_right},
312             $self->{_right_color},
313             $self->{_top},
314             $self->{_top_color},
315              
316             );
317              
318             return $key;
319             }
320              
321              
322             ###############################################################################
323             #
324 1468         8022 # get_fill_key()
325             #
326 1468         3767 # Returns a unique hash key for a fill style. Used by Workbook.
327             #
328              
329             my $self = shift;
330              
331             my $key = join ':', (
332             $self->{_pattern},
333             $self->{_bg_color},
334             $self->{_fg_color},
335              
336             );
337              
338 1435     1435 0 2900 return $key;
339             }
340              
341              
342             ###############################################################################
343             #
344             # get_alignment_key()
345 1435         4459 #
346             # Returns a unique hash key for alignment formats.
347 1435         3912 #
348              
349             my $self = shift;
350              
351             my $key = join ':', (
352             $self->{_text_h_align},
353             $self->{_text_v_align},
354             $self->{_indent},
355             $self->{_rotation},
356             $self->{_text_wrap},
357             $self->{_shrink},
358             $self->{_reading_order},
359 262     262 0 611  
360             );
361              
362             return $key;
363             }
364              
365              
366             ###############################################################################
367             #
368             # get_xf_index()
369             #
370 262         1429 # Returns the index used by Worksheet->_XF()
371             #
372 262         963 my $self = shift;
373              
374             if ( defined $self->{_xf_index} ) {
375             return $self->{_xf_index};
376             }
377             else {
378             my $key = $self->get_format_key();
379             my $indices_href = ${ $self->{_xf_format_indices} };
380              
381             if ( exists $indices_href->{$key} ) {
382             return $indices_href->{$key};
383 529     529 0 1063 }
384             else {
385 529 100       1208 my $index = 1 + scalar keys %$indices_href;
386 286         896 $indices_href->{$key} = $index;
387             $self->{_xf_index} = $index;
388             return $index;
389 243         769 }
390 243         389 }
  243         458  
391             }
392 243 100       749  
393 8         58  
394             ###############################################################################
395             #
396 235         587 # get_dxf_index()
397 235         547 #
398 235         363 # Returns the index used by Worksheet->_XF()
399 235         677 #
400             my $self = shift;
401              
402             if ( defined $self->{_dxf_index} ) {
403             return $self->{_dxf_index};
404             }
405             else {
406             my $key = $self->get_format_key();
407             my $indices_href = ${ $self->{_dxf_format_indices} };
408              
409             if ( exists $indices_href->{$key} ) {
410             return $indices_href->{$key};
411             }
412 37     37 0 84 else {
413             my $index = scalar keys %$indices_href;
414 37 100       113 $indices_href->{$key} = $index;
415 18         42 $self->{_dxf_index} = $index;
416             return $index;
417             }
418 19         67 }
419 19         29 }
  19         47  
420              
421 19 50       53  
422 0         0 ###############################################################################
423             #
424             # _get_color()
425 19         60 #
426 19         51 # Used in conjunction with the set_xxx_color methods to convert a color
427 19         32 # string into a number. Color range is 0..63 but we will restrict it
428 19         70 # to 8..63 to comply with Gnumeric. Colors 0..7 are repeated in 8..15.
429             #
430              
431             my %colors = (
432             aqua => 0x0F,
433             cyan => 0x0F,
434             black => 0x08,
435             blue => 0x0C,
436             brown => 0x10,
437             magenta => 0x0E,
438             fuchsia => 0x0E,
439             gray => 0x17,
440             grey => 0x17,
441             green => 0x11,
442             lime => 0x0B,
443             navy => 0x12,
444 4306     4306   21635 orange => 0x35,
445             pink => 0x21,
446             purple => 0x14,
447             red => 0x0A,
448             silver => 0x16,
449             white => 0x09,
450             yellow => 0x0D,
451             );
452              
453             # Return the default color if undef,
454             return 0x00 unless defined $_[0];
455              
456             # Return RGB style colors for processing later.
457             if ( $_[0] =~ m/^#[0-9A-F]{6}$/i ) {
458             return $_[0];
459             }
460              
461             # or the color string converted to an integer,
462             return $colors{ lc( $_[0] ) } if exists $colors{ lc( $_[0] ) };
463              
464             # or the default color if string is unrecognised,
465             return 0x00 if ( $_[0] =~ m/\D/ );
466              
467 4306 50       6904 # or an index < 8 mapped into the correct range,
468             return $_[0] + 8 if $_[0] < 8;
469              
470 4306 100       7116 # or the default color if arg is outside range,
471 22         94 return 0x00 if $_[0] > 63;
472              
473             # or an integer in the valid range
474             return $_[0];
475 4284 100       7893 }
476              
477              
478 4165 50       8732 ###############################################################################
479             #
480             # set_type()
481 4165 50       5747 #
482             # Set the XF object type as 0 = cell XF or 0xFFF5 = style XF.
483             #
484 4165 100       13748  
485             my $self = shift;
486             my $type = $_[0];
487 4         19  
488             if (defined $_[0] and $_[0] eq 0) {
489             $self->{_type} = 0x0000;
490             }
491             else {
492             $self->{_type} = 0xFFF5;
493             }
494             }
495              
496              
497             ###############################################################################
498             #
499 0     0 0 0 # set_align()
500 0         0 #
501             # Set cell alignment.
502 0 0 0     0 #
503 0         0  
504             my $self = shift;
505             my $location = $_[0];
506 0         0  
507             return if not defined $location; # No default
508             return if $location =~ m/\d/; # Ignore numbers
509              
510             $location = lc( $location );
511              
512             $self->set_text_h_align( 1 ) if $location eq 'left';
513             $self->set_text_h_align( 2 ) if $location eq 'centre';
514             $self->set_text_h_align( 2 ) if $location eq 'center';
515             $self->set_text_h_align( 3 ) if $location eq 'right';
516             $self->set_text_h_align( 4 ) if $location eq 'fill';
517             $self->set_text_h_align( 5 ) if $location eq 'justify';
518             $self->set_text_h_align( 6 ) if $location eq 'center_across';
519 34     34 0 51 $self->set_text_h_align( 6 ) if $location eq 'centre_across';
520 34         58 $self->set_text_h_align( 6 ) if $location eq 'merge'; # Legacy.
521             $self->set_text_h_align( 7 ) if $location eq 'distributed';
522 34 50       82 $self->set_text_h_align( 7 ) if $location eq 'equal_space'; # S::PE.
523 34 50       112 $self->set_text_h_align( 7 ) if $location eq 'justify_distributed';
524              
525 34         66 $self->{_just_distrib} = 1 if $location eq 'justify_distributed';
526              
527 34 100       96 $self->set_text_v_align( 1 ) if $location eq 'top';
528 34 50       78 $self->set_text_v_align( 2 ) if $location eq 'vcentre';
529 34 100       156 $self->set_text_v_align( 2 ) if $location eq 'vcenter';
530 34 100       83 $self->set_text_v_align( 3 ) if $location eq 'bottom';
531 34 100       72 $self->set_text_v_align( 4 ) if $location eq 'vjustify';
532 34 100       66 $self->set_text_v_align( 5 ) if $location eq 'vdistributed';
533 34 100       78 $self->set_text_v_align( 5 ) if $location eq 'vequal_space'; # S::PE.
534 34 50       73 }
535 34 50       97  
536 34 100       81  
537 34 50       74 ###############################################################################
538 34 100       61 #
539             # set_valign()
540 34 100       133 #
541             # Set vertical cell alignment. This is required by the set_properties() method
542 34 100       126 # to differentiate between the vertical and horizontal properties.
543 34 50       65 #
544 34 100       83  
545 34 100       75 my $self = shift;
546 34 100       70 $self->set_align( @_ );
547 34 100       70 }
548 34 50       165  
549              
550             ###############################################################################
551             #
552             # set_center_across()
553             #
554             # Implements the Excel5 style "merge".
555             #
556              
557             my $self = shift;
558              
559             $self->set_text_h_align( 6 );
560             }
561 3     3 0 4  
562 3         10  
563             ###############################################################################
564             #
565             # set_merge()
566             #
567             # This was the way to implement a merge in Excel5. However it should have been
568             # called "center_across" and not "merge".
569             # This is now deprecated. Use set_center_across() or better merge_range().
570             #
571             #
572              
573             my $self = shift;
574 1     1 0 5  
575             $self->set_text_h_align( 6 );
576 1         8 }
577              
578              
579             ###############################################################################
580             #
581             # set_bold()
582             #
583             #
584              
585             my $self = shift;
586             my $bold = defined $_[0] ? $_[0] : 1;
587              
588             $self->{_bold} = $bold ? 1 : 0;
589             }
590              
591 1     1 0 1  
592             ###############################################################################
593 1         6 #
594             # set_border($style)
595             #
596             # Set cells borders to the same style
597             #
598              
599             my $self = shift;
600             my $style = $_[0];
601              
602             $self->set_bottom( $style );
603             $self->set_top( $style );
604 80     80 0 165 $self->set_left( $style );
605 80 100       281 $self->set_right( $style );
606             }
607 80 50       482  
608              
609             ###############################################################################
610             #
611             # set_border_color($color)
612             #
613             # Set cells border to the same color
614             #
615              
616             my $self = shift;
617             my $color = $_[0];
618              
619 1     1 0 2 $self->set_bottom_color( $color );
620 1         2 $self->set_top_color( $color );
621             $self->set_left_color( $color );
622 1         7 $self->set_right_color( $color );
623 1         5 }
624 1         7  
625 1         5  
626             ###############################################################################
627             #
628             # set_rotation($angle)
629             #
630             # Set the rotation angle of the text. An alignment property.
631             #
632              
633             my $self = shift;
634             my $rotation = $_[0];
635              
636             # Argument should be a number
637 0     0 0 0 return if $rotation !~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/;
638 0         0  
639             # The arg type can be a double but the Excel dialog only allows integers.
640 0         0 $rotation = int $rotation;
641 0         0  
642 0         0 if ( $rotation == 270 ) {
643 0         0 $rotation = 255;
644             }
645             elsif ( $rotation >= -90 and $rotation <= 90 ) {
646             $rotation = -$rotation + 90 if $rotation < 0;
647             }
648             else {
649             carp "Rotation $rotation outside range: -90 <= angle <= 90";
650             $rotation = 0;
651             }
652              
653             $self->{_rotation} = $rotation;
654             }
655 7     7 0 11  
656 7         10  
657             ###############################################################################
658             #
659 7 50       42 # set_hyperlink()
660             #
661             # Set the properties for the hyperlink style. This isn't a public method. To
662 7         15 # be fixed when styles are supported.
663             #
664 7 100 33     47  
    50          
665 1         2 my $self = shift;
666             my $hyperlink = shift;
667              
668 6 100       17 $self->{_xf_id} = 1;
669              
670             $self->set_underline( 1 );
671 0         0 $self->set_theme( 10 );
672 0         0 $self->{_hyperlink} = $hyperlink;
673             }
674              
675 7         26  
676             ###############################################################################
677             #
678             # set_format_properties()
679             #
680             # Convert hashes of properties to method calls.
681             #
682              
683             my $self = shift;
684              
685             my %properties = @_; # Merge multiple hashes into one
686              
687             while ( my ( $key, $value ) = each( %properties ) ) {
688 896     896 0 2070  
689 896         1855 # Strip leading "-" from Tk style properties e.g. -color => 'red'.
690             $key =~ s/^-//;
691 896         2032  
692             # Create a sub to set the property.
693 896         6981 my $sub = \&{"set_$key"};
694 896         7721 $sub->( $self, $value );
695 896         3981 }
696             }
697              
698             # Renamed rarely used set_properties() to set_format_properties() to avoid
699             # confusion with Workbook method of the same name. The following acts as an
700             # alias for any code that uses the old name.
701             *set_properties = *set_format_properties;
702              
703              
704             ###############################################################################
705             #
706             # AUTOLOAD. Deus ex machina.
707 2111     2111 0 3363 #
708             # Dynamically create set methods that aren't already defined.
709 2111         5789 #
710              
711 2111         7962 my $self = shift;
712              
713             # Ignore calls to DESTROY
714 2322         4737 return if $AUTOLOAD =~ /::DESTROY$/;
715              
716             # Check for a valid method names, i.e. "set_xxx_yyy".
717 2322         3190 $AUTOLOAD =~ /.*::set(\w+)/ or die "Unknown method: $AUTOLOAD\n";
  2322         9465  
718 2322         8651  
719             # Match the attribute, i.e. "_xxx_yyy".
720             my $attribute = $1;
721              
722             # Check that the attribute exists
723             exists $self->{$attribute} or die "Unknown method: $AUTOLOAD\n";
724              
725             # The attribute value
726             my $value;
727              
728              
729             # There are two types of set methods: set_property() and
730             # set_property_color(). When a method is AUTOLOADED we store a new anonymous
731             # sub in the appropriate slot in the symbol table. The speeds up subsequent
732             # calls to the same method.
733             #
734             no strict 'refs'; # To allow symbol table hackery
735              
736 5000     5000   51252 if ( $AUTOLOAD =~ /.*::set\w+color$/ ) {
737              
738             # For "set_property_color" methods
739 5000 100       207588 $value = _get_color( $_[0] );
740              
741             *{$AUTOLOAD} = sub {
742 2853 50       14011 my $self = shift;
743              
744             $self->{$attribute} = _get_color( $_[0] );
745 2853         6801 };
746             }
747             else {
748 2853 50       9430  
749             $value = $_[0];
750             $value = 1 if not defined $value; # The default value is always 1
751 2853         3879  
752             *{$AUTOLOAD} = sub {
753             my $self = shift;
754             my $value = shift;
755              
756             $value = 1 if not defined $value;
757             $self->{$attribute} = $value;
758             };
759 1126     1126   9385 }
  1126         2371  
  1126         208300  
760              
761 2853 100       6867  
762             $self->{$attribute} = $value;
763             }
764 41         135  
765              
766 41         147 1;
767 17     17   28  
768              
769 17         41  
770 41         160  
771             =head1 NAME
772              
773             Format - A class for defining Excel formatting.
774 2812         4182  
775 2812 100       5684 =head1 SYNOPSIS
776              
777 2812         9674 See the documentation for L<Excel::Writer::XLSX>
778 271     271   410  
779 271         381 =head1 DESCRIPTION
780              
781 271 50       566 This module is used in conjunction with L<Excel::Writer::XLSX>.
782 271         761  
783 2812         9071 =head1 AUTHOR
784              
785             John McNamara jmcnamara@cpan.org
786              
787 2853         13834 =head1 COPYRIGHT
788              
789             (c) MM-MMXXI, John McNamara.
790              
791             All Rights Reserved. This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.