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   2223 use Mojo::Base 'Spreadsheet::Compare::Reporter', -signatures;
  2         13  
  2         41  
4 2     2   388 use Spreadsheet::Compare::Common;
  2         5  
  2         9  
5              
6 2     2   3022 use Excel::Writer::XLSX;
  2         366598  
  2         4103  
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 48 sub add_stream ( $self, $name ) {
  28         49  
  28         56  
  28         45  
35              
36 28 100       140 $self->_open_wkb() unless $self->{wbk};
37              
38 28         149 $self->{ws}{$name} = $self->{wbk}->add_worksheet($name);
39 28         9904 $self->{ws}{$name}->add_write_handler( qr[\d], \&_write_with_infinity );
40 28         381 $self->{row}{$name} = 0;
41              
42 28         107 return $self;
43             }
44              
45              
46 28     28 1 65 sub write_header ( $self, $name ) {
  28         45  
  28         55  
  28         43  
47              
48 28         159 $self->{ws}{$name}->write_row( $self->{row}{$name}++, 0, $self->header, $self->fmt_head );
49 28         2186 $self->{ws}{$name}->freeze_panes( 1, 0 );
50              
51 28         696 return $self;
52             }
53              
54              
55 7     7 1 24 sub mark_header ( $self, $name, $mask ) {
  7         19  
  7         23  
  7         23  
  7         18  
56              
57 7         58 my $smask = $self->strip_ignore($mask);
58 7         54 my $off = $self->head_offset;
59 7         77 my $rhead = $self->record_header;
60 7         58 for my $col ( 0 .. $#$rhead ) {
61 440 100       11710 $self->{ws}{$name}->write( 0, $col + $off, $rhead->[$col], $self->fmt_headerr )
62             if $smask->[$col];
63             }
64              
65 7         56 return $self;
66             }
67              
68              
69 36     36 1 84 sub write_row ( $self, $name, $robj ) {
  36         73  
  36         93  
  36         78  
  36         107  
70 36         263 my($fnorm) = $self->_get_fmt( $name, $robj->side );
71 36         453 $self->{ws}{$name}->write_row( $self->{row}{$name}++, 0, $self->output_record($robj), $fnorm );
72 36         5986 return $self;
73             }
74              
75              
76 5366     5366   39624 sub _get_fmt ( $self, $name, $side ) {
  5366         8302  
  5366         8882  
  5366         9023  
  5366         7897  
77              
78 5366 100 33     35128 $self->{$name}{odd} ^= 1
      66        
79             if $name eq 'Additional' and $side eq 'right'
80             or $side eq 'left';
81              
82 5366 100       16096 my $oe = $self->{$name}{odd} ? 'odd' : 'even';
83              
84 5366   33     28336 my $fnorm = $self->{format}{$side}{$oe} || $self->fmt_default;
85 5366   33     18643 my $fhigh = $self->{format}{$side}{high} || $self->fmt_default;
86 5366   33     15425 my $flow = $self->{format}{$side}{low} || $self->fmt_default;
87              
88 5366         17025 return ( $fnorm, $fhigh, $flow );
89             }
90              
91              
92 5330     5330 1 11198 sub write_fmt_row ( $self, $name, $robj ) {
  5330         9920  
  5330         9958  
  5330         7893  
  5330         7962  
93              
94 5330         23136 my $data = $self->output_record($robj);
95 5330         19813 my $mask = $self->strip_ignore( $robj->limit_mask );
96 5330         37006 my $off = $self->head_offset;
97 5330         33642 my $row = $self->{row}{$name}++;
98              
99 5330         18592 my( $fnorm, $fhigh, $flow ) = $self->_get_fmt( $name, $robj->side );
100              
101 5330         19611 for my $col ( 0 .. $#$data ) {
102 352180         23532924 my $idx = $col - $off;
103 352180 50       704689 my $flag = $idx < 0 ? 0 : $mask->[$idx];
104 352180 100       1054798 $self->{ws}{$name}->write(
    100          
105             $row, $col, $data->[$col], $flag
106             ? ( $flag == 1 ? $fhigh : $flow )
107             : $fnorm,
108             );
109             }
110              
111 5330         443287 return $self;
112             }
113              
114              
115 7     7   20 sub _open_wkb ($self) {
  7         15  
  7         20  
116              
117 7         40 my $rfn = $self->report_fullname->stringify;
118 7         390 INFO "opening report file $rfn";
119              
120 7 50       125 $self->{wbk} = Excel::Writer::XLSX->new($rfn)
121             or LOGDIE "could not create >>$rfn<<, $!";
122              
123 7         5282 for my $fname ( keys %format_defaults ) {
124 105         366 my( undef, $side, $fmt ) = split( /_/, $fname );
125 105         490 my $fobj = $self->{wbk}->add_format( split( /\s+/, $self->$fname ) );
126 105 100       11313 if ($fmt) {
127 84         307 $self->{format}{$side}{$fmt} = $fobj;
128             }
129             else {
130 21         63 $self->{$fname} = $fobj;
131             }
132             }
133              
134 7         32 return $self;
135             }
136              
137              
138 7     7 1 20 sub save_and_close ($self) {
  7         17  
  7         17  
139              
140 7 50       41 if ( $self->header->@* ) {
141 7         101 for my $name ( keys $self->{ws}->%* ) {
142 28         3636 $self->{ws}{$name}->autofilter( 0, 0, $self->{row}{$name} - 1, $self->header->$#* );
143             }
144             }
145              
146 7 50       1097 if ( $self->{wbk} ) {
147 7         74 $self->{wbk}->close();
148 7         27394248 delete $self->{wbk};
149             }
150              
151 7         39267 return $self;
152             }
153              
154              
155 2     2 1 7 sub write_summary ( $self, $summary, $filename ) {
  2         5  
  2         6  
  2         11  
  2         5  
156              
157 2 50       26 $filename .= '.xlsx' unless $filename =~ /\.xlsx$/i;
158              
159 2         17 my $sfn = $self->report_fullname($filename)->stringify;
160              
161 2         183 INFO "opening summary file $sfn";
162 2 50       35 my $wbk = Excel::Writer::XLSX->new($sfn)
163             or ERROR "could not create >>$sfn<<, $!";
164              
165 2         1638 my $fhead = $wbk->add_format(qw/bold 1 align left/);
166 2         350 my $head = $self->stat_head;
167              
168 2         18 for my $suite ( sort keys %$summary ) {
169 3         18 my $ws = $wbk->add_worksheet($suite);
170 3         1352 my $row = 0;
171 3         22 $ws->write_row( $row++, 0, $head, $fhead );
172 3         3155 $ws->freeze_panes( 1, 0 );
173 3         65 for my $test ( @{ $summary->{$suite} } ) {
  3         13  
174 14         48 my $result = $test->{result};
175 14         52 $result->{title} = $test->{title};
176 14         134 my $data = [ @$result{@$head} ];
177 14         56 $ws->write_row( $row, 0, $data );
178 14 50       9097 $ws->write_url( $row, $#$head, "external:$test->{report}", undef, $test->{title} ) if $test->{report};
179 14         2805 $row++;
180             }
181             }
182              
183 2         27 $wbk->close();
184              
185 2         106779 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   4860583 my $ws = shift;
198 258655 100 100     2038520 return $ws->write_string(@_) if $_[2] =~ /$qr_num/ and $_[2]+0 =~ /Inf/;
199 70144         161575 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