File Coverage

blib/lib/Catmandu/Importer/XLS.pm
Criterion Covered Total %
statement 15 50 30.0
branch 0 18 0.0
condition 0 6 0.0
subroutine 5 9 55.5
pod 0 1 0.0
total 20 84 23.8


line stmt bran cond sub pod time code
1             package Catmandu::Importer::XLS;
2            
3             our $VERSION = '0.08';
4            
5 3     3   28836 use namespace::clean;
  3         18607  
  3         20  
6 3     3   1159 use Catmandu::Sane;
  3         162752  
  3         25  
7 3     3   4740 use Spreadsheet::ParseExcel;
  3         162190  
  3         122  
8 3     3   34 use Spreadsheet::ParseExcel::Utility qw(int2col);
  3         8  
  3         196  
9 3     3   17 use Moo;
  3         6  
  3         31  
10            
11             with 'Catmandu::Importer';
12            
13             has xls => (is => 'ro', builder => '_build_xls');
14             has header => (is => 'ro', default => sub { 1 });
15             has columns => (is => 'ro' , default => sub { 0 });
16             has fields => (
17             is => 'rw',
18             coerce => sub {
19             my $fields = $_[0];
20             if (ref $fields eq 'ARRAY') { return $fields }
21             if (ref $fields eq 'HASH') { return [sort keys %$fields] }
22             return [split ',', $fields];
23             },
24             );
25             has worksheet => (is => 'ro' , default => sub { 0 });
26             has _n => (is => 'rw', default => sub { 0 });
27             has _row_min => (is => 'rw');
28             has _row_max => (is => 'rw');
29             has _col_min => (is => 'rw');
30             has _col_max => (is => 'rw');
31            
32             sub BUILD {
33 0     0 0   my $self = shift;
34            
35 0 0         if ( $self->header ) {
36 0 0         if ( $self->fields ) {
    0          
37 0           $self->{_n}++;
38             }
39             elsif ( $self->columns ) {
40 0           $self->fields([$self->_get_cols]);
41 0           $self->{_n}++;
42             }
43             else {
44 0           $self->fields([$self->_get_row]);
45 0           $self->{_n}++;
46             }
47             }
48             else {
49 0 0 0       if ( !$self->fields || $self->columns ) {
50 0           $self->fields([$self->_get_cols]);
51             }
52             }
53             }
54            
55             sub _build_xls {
56 0     0     my ($self) = @_;
57 0           my $parser = Spreadsheet::ParseExcel->new();
58 0 0         my $xls = $parser->parse( $self->file ) or Catmandu::Error->throw("could not parse file \"$self->{file}\": " . $parser->error());
59            
60 0 0         $xls = $xls->worksheet($self->worksheet) or Catmandu::Error->throw("worksheet $self->{worksheet} does not exist.");
61 0           ($self->{_row_min}, $self->{_row_max}) = $xls->row_range();
62 0           ($self->{_col_min}, $self->{_col_max}) = $xls->col_range();
63 0           return $xls;
64             }
65            
66             sub generator {
67             my ($self) = @_;
68             sub {
69             while ($self->_n <= $self->_row_max) {
70             my @data = $self->_get_row();
71             $self->{_n}++;
72             my @fields = @{$self->fields()};
73             my %hash = map {
74             my $key = shift @fields;
75             defined $_ ? ($key => $_) : ()
76             } @data;
77             return \%hash;
78             }
79             return;
80             }
81             }
82            
83             sub _get_row {
84 0     0     my ($self) = @_;
85 0           my @row;
86 0           for my $col ( $self->_col_min .. $self->_col_max ) {
87 0           my $cell = $self->xls->get_cell( $self->_n, $col );
88 0 0         if ($cell) {
89 0           push(@row,$cell->value());
90             }
91             else{
92 0           push(@row, undef);
93             }
94             }
95 0           return @row;
96             }
97            
98             sub _get_cols {
99 0     0     my ($self) = @_;
100            
101 0           my @row;
102 0           for my $col ( $self->_col_min .. $self->_col_max ) {
103            
104 0 0 0       if (!$self->header || $self->columns) {
105 0           push(@row,int2col($col));
106             }
107             else {
108 0           my $cell = $self->xls->get_cell( $self->_n, $col );
109 0 0         if ($cell) {
110 0           push(@row,$cell->value());
111             }
112             else{
113 0           push(@row, undef);
114             }
115             }
116             }
117 0           return @row;
118             }
119            
120             =head1 NAME
121            
122             Catmandu::Importer::XLS - Package that imports XLS files
123            
124             =head1 SYNOPSIS
125            
126             # On the command line
127             $ catmandu convert XLS < ./t/test.xls
128             $ catmandu convert XLS --header 0 < ./t/test.xls
129             $ catmandu convert XLS --fields 1,2,3 < ./t/test.xls
130             $ catmandu convert XLS --columns 1 < ./t/test.xls
131             $ catmandu convert XLS --worksheet 1 < ./t/test.xls
132            
133             # Or in Perl
134             use Catmandu::Importer::XLS;
135            
136             my $importer = Catmandu::Importer::XLS->new(file => "./t/test.xls");
137            
138             my $n = $importer->each(sub {
139             my $hashref = $_[0];
140             # ...
141             });
142            
143             =head1 DESCRIPTION
144            
145             L importer for XLS files.
146            
147             =head1 METHODS
148            
149             This module inherits all methods of L and by this
150             L.
151            
152             =head1 CONFIGURATION
153            
154             In addition to the configuration provided by L (C,
155             C, etc.) the importer can be configured with the following parameters:
156            
157             =over
158            
159             =item header
160            
161             By default object fields are read from the XLS header line. If no header
162             line is avaiable object fields are named as column coordinates (A,B,C,...). Default: 1.
163            
164             =item fields
165            
166             Provide custom object field names as array, hash reference or comma-
167             separated list.
168            
169             =item columns
170            
171             When the 'columns' option is provided, then the object fields are named as
172             column coordinates (A,B,C,...). Default: 0.
173            
174             =item worksheet
175            
176             If the Excel workbook contains more than one worksheet, you can select a specific worksheet by its index number (0,1,2,...). Default: 0.
177            
178             =back
179            
180             =head1 SEE ALSO
181            
182             L, L, L, L.
183            
184             =cut
185            
186             1;