File Coverage

blib/lib/DBIx/DataModel/Schema/ResultAs/Xlsx.pm
Criterion Covered Total %
statement 55 55 100.0
branch 3 6 50.0
condition n/a
subroutine 14 14 100.0
pod 1 7 14.2
total 73 82 89.0


line stmt bran cond sub pod time code
1             #----------------------------------------------------------------------
2             package DBIx::DataModel::Schema::ResultAs::Xlsx;
3             #----------------------------------------------------------------------
4 1     1   698 use warnings;
  1         3  
  1         46  
5 1     1   7 use strict;
  1         3  
  1         43  
6 1     1   7 use Carp::Clan qw[^(DBIx::DataModel::|SQL::Abstract)];
  1         3  
  1         14  
7 1     1   107 use Excel::Writer::XLSX;
  1         2  
  1         39  
8 1     1   6 use Params::Validate qw/validate_with SCALAR/;
  1         3  
  1         64  
9              
10 1     1   6 use parent 'DBIx::DataModel::Schema::ResultAs';
  1         3  
  1         9  
11              
12 1     1   68 use namespace::clean;
  1         2  
  1         10  
13              
14             sub param_spec { # class method
15             return {
16 1     1 0 29 -worksheet => {type => SCALAR, default => 'Data'},
17             -tech_details => {type => SCALAR, default => 'Technical_details'},
18             };
19             }
20              
21             sub new {
22 1     1 0 4 my $class = shift;
23              
24             # the first positional arg is the output file .. string or a filehandle
25 1 50       4 my $file = shift
26             or croak 'select(..., -result_as => [xlsx => $file]): file is missing';
27              
28             # other args as a hash of named options
29 1         4 my %self = validate_with(
30             params => \@_,
31             spec => $class->param_spec,
32             allow_extra => 0);
33              
34             # assemble and bless
35 1         7 $self{file} = $file;
36 1         5 return bless \%self, $class;
37             }
38              
39              
40             sub get_result {
41 1     1 1 3 my ($self, $statement) = @_;
42              
43             # create the Excel workbook
44 1         3 my $workbook = $self->create_workbook;
45              
46             # gather data from the statement
47 1         7 $statement->execute;
48 1         5 $statement->make_fast;
49 1         3 my @headers = $statement->headers;
50 1         25 my @rows;
51 1         5 while (my $row = $statement->next) {
52 3         6 push @rows, [@{$row}{@headers}];
  3         12  
53             }
54              
55             # create the data worksheet
56 1         4 my $worksheet = $self->create_data_worksheet($workbook);
57 1         4 $self->populate_worksheet($worksheet, \@headers, \@rows);
58              
59             # optionally insert another sheet with technical details
60 1 50       1372 $self->add_technical_details($workbook, $statement) if $self->{-tech_details};
61              
62             # finalize
63 1         16 $statement->finish;
64 1         38 $workbook->close;
65              
66             # return filename or filehandle
67 1         45484 return $self->{file};
68             }
69              
70              
71             sub create_workbook {
72 1     1 0 3 my ($self) = @_;
73              
74             my $workbook = Excel::Writer::XLSX->new($self->{file})
75 1 50       10 or die "open Excel file $self->{file}: $!";
76              
77 1         515 return $workbook;
78             }
79              
80              
81             sub create_data_worksheet {
82 1     1 0 2 my ($self, $workbook) = @_;
83 1         12 my $worksheet = $workbook->add_worksheet($self->{-worksheet});
84              
85 1         441 return $worksheet;
86             }
87              
88              
89             sub populate_worksheet {
90 1     1 0 3 my ($self, $worksheet, $headers, $rows) = @_;
91              
92             # insert data as an Excel table
93             $worksheet->add_table(0, 0, scalar(@$rows), scalar(@$headers)-1, {
94             data => $rows,
95 1         3 columns => [ map { {header => $_}} @$headers ],
  3         18  
96             autofilter => 1,
97             });
98             }
99              
100              
101             sub add_technical_details {
102 1     1 0 4 my ($self, $workbook, $statement, $n_rows) = @_;
103              
104 1         4 my $tech_worksheet = $workbook->add_worksheet($self->{-tech_details});
105             $tech_worksheet->write_col(0, 0, [
106             scalar(localtime), # time of the extraction
107             $statement->schema->dbh->{Name}, # database name
108 1         338 $statement->row_num . " rows", # number of rows
109             $statement->sql, # SQL and bind values
110             ]);
111              
112 1         325 return $tech_worksheet;
113             }
114              
115              
116             1;
117              
118              
119             __END__