File Coverage

blib/lib/Spreadsheet/Compare/Reporter/XLSX.pm
Criterion Covered Total %
statement 122 122 100.0
branch 23 30 76.6
condition 9 18 50.0
subroutine 13 13 100.0
pod 7 7 100.0
total 174 190 91.5


line stmt bran cond sub pod time code
1             package Spreadsheet::Compare::Reporter::XLSX;
2              
3 2     2   2133 use Mojo::Base 'Spreadsheet::Compare::Reporter', -signatures;
  2         10  
  2         32  
4 2     2   466 use Spreadsheet::Compare::Common;
  2         5  
  2         11  
5              
6 2     2   2837 use Excel::Writer::XLSX;
  2         337936  
  2         3717  
7              
8             my %format_defaults = (
9             fmt_head => 'bold 1 align left',
10             fmt_headerr => 'bold 1 align left bg_color yellow',
11             fmt_default => 'color black',
12             fmt_left_odd => 'color blue',
13             fmt_right_odd => 'color red',
14             fmt_diff_odd => 'color green',
15             fmt_left_even => 'color blue bg_color silver',
16             fmt_right_even => 'color red bg_color silver',
17             fmt_diff_even => 'color green bg_color silver',
18             fmt_left_high => 'color blue bg_color yellow',
19             fmt_right_high => 'color red bg_color yellow',
20             fmt_diff_high => 'color black bg_color yellow',
21             fmt_left_low => 'color blue bg_color lime',
22             fmt_right_low => 'color red bg_color lime',
23             fmt_diff_low => 'color black bg_color lime',
24             );
25              
26             has $_, $format_defaults{$_} for keys %format_defaults;
27              
28             has report_filename => sub {
29             ( my $title = $_[0]->test_title ) =~ s/[^\w-]/_/g;
30             return "$title.xlsx";
31             };
32              
33              
34 28     28 1 57 sub add_stream ( $self, $name ) {
  28         47  
  28         64  
  28         41  
35              
36 28 100       108 $self->_open_wkb() unless $self->{wbk};
37              
38 28         132 $self->{ws}{$name} = $self->{wbk}->add_worksheet($name);
39 28         9752 $self->{ws}{$name}->add_write_handler( qr[\d], \&_write_with_infinity );
40 28         376 $self->{row}{$name} = 0;
41              
42 28         103 return $self;
43             }
44              
45              
46 28     28 1 48 sub write_header ( $self, $name ) {
  28         38  
  28         69  
  28         53  
47              
48 28         144 $self->{ws}{$name}->write_row( $self->{row}{$name}++, 0, $self->header, $self->fmt_head );
49 28         2106 $self->{ws}{$name}->freeze_panes( 1, 0 );
50              
51 28         594 return $self;
52             }
53              
54              
55 7     7 1 18 sub mark_header ( $self, $name, $mask ) {
  7         17  
  7         16  
  7         14  
  7         13  
56              
57 7         52 my $smask = $self->strip_ignore($mask);
58 7         52 my $off = $self->head_offset;
59 7         65 my $rhead = $self->record_header;
60 7         69 for my $col ( 0 .. $#$rhead ) {
61 440 100       11343 $self->{ws}{$name}->write( 0, $col + $off, $rhead->[$col], $self->fmt_headerr )
62             if $smask->[$col];
63             }
64              
65 7         51 return $self;
66             }
67              
68              
69 36     36 1 105 sub write_row ( $self, $name, $robj ) {
  36         60  
  36         85  
  36         53  
  36         57  
70 36         193 my($fnorm) = $self->_get_fmt( $name, $robj->side );
71 36         297 $self->{ws}{$name}->write_row( $self->{row}{$name}++, 0, $self->output_record($robj), $fnorm );
72 36         5238 return $self;
73             }
74              
75              
76 5366     5366   41984 sub _get_fmt ( $self, $name, $side ) {
  5366         9267  
  5366         10472  
  5366         9111  
  5366         7325  
77              
78 5366 100 33     36883 $self->{$name}{odd} ^= 1
      66        
79             if $name eq 'Additional' and $side eq 'right'
80             or $side eq 'left';
81              
82 5366 100       17883 my $oe = $self->{$name}{odd} ? 'odd' : 'even';
83              
84 5366   33     32178 my $fnorm = $self->{format}{$side}{$oe} || $self->fmt_default;
85 5366   33     18128 my $fhigh = $self->{format}{$side}{high} || $self->fmt_default;
86 5366   33     17515 my $flow = $self->{format}{$side}{low} || $self->fmt_default;
87              
88 5366         17547 return ( $fnorm, $fhigh, $flow );
89             }
90              
91              
92 5330     5330 1 10104 sub write_fmt_row ( $self, $name, $robj ) {
  5330         11754  
  5330         9445  
  5330         10854  
  5330         8387  
93              
94 5330         25080 my $data = $self->output_record($robj);
95 5330         20445 my $mask = $self->strip_ignore( $robj->limit_mask );
96 5330         34922 my $off = $self->head_offset;
97 5330         37931 my $row = $self->{row}{$name}++;
98              
99 5330         18597 my( $fnorm, $fhigh, $flow ) = $self->_get_fmt( $name, $robj->side );
100              
101 5330         20528 for my $col ( 0 .. $#$data ) {
102 352180         22579334 my $idx = $col - $off;
103 352180 50       657992 my $flag = $idx < 0 ? 0 : $mask->[$idx];
104 352180 100       998408 $self->{ws}{$name}->write(
    100          
105             $row, $col, $data->[$col], $flag
106             ? ( $flag == 1 ? $fhigh : $flow )
107             : $fnorm,
108             );
109             }
110              
111 5330         454470 return $self;
112             }
113              
114              
115 7     7   15 sub _open_wkb ($self) {
  7         19  
  7         12  
116              
117 7         34 my $rfn = $self->report_fullname->stringify;
118 7         381 INFO "opening report file $rfn";
119              
120 7 50       116 $self->{wbk} = Excel::Writer::XLSX->new($rfn)
121             or LOGDIE "could not create >>$rfn<<, $!";
122              
123 7         5021 for my $fname ( keys %format_defaults ) {
124 105         341 my( undef, $side, $fmt ) = split( /_/, $fname );
125 105         468 my $fobj = $self->{wbk}->add_format( split( /\s+/, $self->$fname ) );
126 105 100       10630 if ($fmt) {
127 84         284 $self->{format}{$side}{$fmt} = $fobj;
128             }
129             else {
130 21         65 $self->{$fname} = $fobj;
131             }
132             }
133              
134 7         31 return $self;
135             }
136              
137              
138 7     7 1 20 sub save_and_close ($self) {
  7         17  
  7         16  
139              
140 7 50       34 if ( $self->header->@* ) {
141 7         112 for my $name ( keys $self->{ws}->%* ) {
142 28         3331 $self->{ws}{$name}->autofilter( 0, 0, $self->{row}{$name} - 1, $self->header->$#* );
143             }
144             }
145              
146 7 50       972 if ( $self->{wbk} ) {
147 7         68 $self->{wbk}->close();
148 7         25165985 delete $self->{wbk};
149             }
150              
151 7         35867 return $self;
152             }
153              
154              
155 2     2 1 7 sub write_summary ( $self, $summary, $filename ) {
  2         7  
  2         5  
  2         7  
  2         4  
156              
157 2 50       23 $filename .= '.xlsx' unless $filename =~ /\.xlsx$/i;
158              
159 2         17 my $sfn = $self->report_fullname($filename)->stringify;
160              
161 2         193 INFO "opening summary file $sfn";
162 2 50       44 my $wbk = Excel::Writer::XLSX->new($sfn)
163             or ERROR "could not create >>$sfn<<, $!";
164              
165 2         1652 my $fhead = $wbk->add_format(qw/bold 1 align left/);
166 2         321 my $head = $self->stat_head;
167              
168 2         21 for my $suite ( sort keys %$summary ) {
169 3         26 my $ws = $wbk->add_worksheet($suite);
170 3         1370 my $row = 0;
171 3         27 $ws->write_row( $row++, 0, $head, $fhead );
172 3         2851 $ws->freeze_panes( 1, 0 );
173 3         67 for my $test ( @{ $summary->{$suite} } ) {
  3         14  
174 14         45 my $result = $test->{result};
175 14         52 $result->{title} = $test->{title};
176 14         119 my $data = [ @$result{@$head} ];
177 14         53 $ws->write_row( $row, 0, $data );
178 14 50       8852 $ws->write_url( $row, $#$head, "external:$test->{report}", undef, $test->{title} ) if $test->{report};
179 14         2668 $row++;
180             }
181             }
182              
183 2         27 $wbk->close();
184              
185 2         101210 return $self;
186             }
187              
188             my $qr_num = qr/^
189             (?:[+-]?)
190             (?=[0-9]|\.[0-9])
191             [0-9]*
192             (\.[0-9]*)?
193             ([Ee]([+-]?[0-9]+))?
194             $/x;
195              
196             sub _write_with_infinity {
197 258655     258655   4670676 my $ws = shift;
198 258655 100 100     1905818 return $ws->write_string(@_) if $_[2] =~ /$qr_num/ and $_[2]+0 =~ /Inf/;
199 70144         147311 return;
200             }
201              
202              
203             1;
204              
205              
206             =head1 NAME
207              
208             Spreadsheet::Compare::Reporter::XLSX - XLSX Report Adapter for Spreadsheet::Compare
209              
210             =head1 DESCRIPTION
211              
212             Handles writing Spreadsheet::Compare reports in XLSX format.
213              
214             =head1 ATTRIBUTES
215              
216             The format attributes have to be valid format strings used by L<Excel::Writer::XLSX>.
217             (see L<Excel::Writer::XLSX/CELL FORMATTING>)
218              
219             The defaults for the attributes are:
220              
221             fmt_head => 'bold 1 align left',
222             fmt_headerr => 'bold 1 align left bg_color yellow',
223             fmt_default => 'color black',
224             fmt_left_odd => 'color blue',
225             fmt_right_odd => 'color red',
226             fmt_diff_odd => 'color green',
227             fmt_left_even => 'color blue bg_color silver',
228             fmt_right_even => 'color red bg_color silver',
229             fmt_diff_even => 'color green bg_color silver',
230             fmt_left_high => 'color blue bg_color yellow',
231             fmt_right_high => 'color red bg_color yellow',
232             fmt_diff_high => 'color black bg_color yellow',
233             fmt_left_low => 'color blue bg_color lime',
234             fmt_right_low => 'color red bg_color lime',
235             fmt_diff_low => 'color black bg_color lime',
236              
237             =head1 METHODS
238              
239             see L<Spreadsheet::Compare::Reporter>
240              
241             =cut