File Coverage

blib/lib/Spreadsheet/BasicRead.pm
Criterion Covered Total %
statement 100 144 69.4
branch 30 68 44.1
condition 10 41 24.3
subroutine 17 25 68.0
pod 17 17 100.0
total 174 295 58.9


line stmt bran cond sub pod time code
1             #
2             # Spreadsheet::BasicRead.pm
3             #
4             # Synopsis: see POD at end of file
5             #
6             #-- The package
7             #--------------------------------------------------
8             package Spreadsheet::BasicRead;
9            
10             $VERSION = '1.12';
11             #--------------------------------------------------
12             #
13            
14             #-- Required Modules
15             #-------------------
16 1     1   3761 use strict;
  1         2  
  1         45  
17 1     1   5 use warnings;
  1         2  
  1         22  
18 1     1   626 use Spreadsheet::ParseExcel;
  1         45067  
  1         26  
19 1     1   360 use Spreadsheet::XLSX;
  1         63058  
  1         709  
20            
21            
22             #-- Linage
23             #---------
24             our @ISA = qw( Spreadsheet::ParseExcel );
25            
26            
27             sub new
28             {
29 1     1 1 139 my $proto = shift;
30 1   33     6 my $class = ref($proto) || $proto;
31            
32 1         2 my $self = {};
33 1         3 bless($self, $class);
34            
35 1         7 $self->{skipBlankRows} = 0;
36 1         8 $self->{oldCell} = 0;
37            
38             # Do we have any arguments to process
39             #------------------------------------
40            
41             # Is there just one argument? If so treat as filename, otherwise assume named arguments
42 1 50       5 if (@_ == 1)
43             {
44 1         3 $self->{fileName} = $_[0];
45 1         5 $self->openSpreadsheet($self->{fileName});
46            
47 1         6 return $self;
48             }
49            
50            
51            
52             # If we get to here then we assume named arguments to process
53 0         0 my %args = @_;
54            
55             # Is there a log object
56 0 0 0     0 if (defined($args{log}) && $args{log} ne '')
57             {
58 0         0 $self->{log} = $args{log};
59             }
60            
61             # Do we skip blank rows
62 0 0       0 if (defined($args{skipBlankRows}))
63             {
64 0 0       0 $self->{skipBlankRows} = $args{skipBlankRows} ? 1 : 0;
65             }
66            
67             # Is there a file to open
68 0 0 0     0 if (defined($args{fileName}) && $args{fileName} ne '')
69             {
70 0         0 $self->{fileName} = $args{fileName};
71 0         0 $self->openSpreadsheet($args{fileName});
72             }
73            
74             # Skip headings (if defined) else skip the first row
75 0 0       0 if (defined $args{skipHeadings})
76             {
77 0         0 $self->{skipHeadings} = $args{skipHeadings};
78             }
79            
80             # Do we return undef on empty cells (old mode) or ''
81 0 0       0 $self->{oldCell} = $args{oldCell} if $args{oldCell};
82            
83 0         0 return $self;
84             }
85            
86            
87             sub openSpreadsheet
88             {
89 1     1 1 3 my ($self, $ssFileName) = @_;
90            
91             #-- Open the Excel spreadsheet and process
92 1         3 my $ssExcel;
93             my $ssBook;
94 1 50       5 if ($ssFileName =~ /\.xls[xm]$/i)
95             {
96 0         0 my $converter = Spreadsheet::XLSX::XLSXConvert->new();
97 0         0 $ssExcel = Spreadsheet::XLSX->new($ssFileName, $converter);
98 0         0 $ssBook = $ssExcel;
99             }
100             else
101             {
102 1         5 $ssExcel = new Spreadsheet::ParseExcel;
103 1         284 $ssBook = $ssExcel->Parse($ssFileName);
104             }
105            
106 1 50       22008 unless ($ssBook)
107             {
108 0         0 $self->logexp("Could not open Excel spreadsheet file '$ssFileName': $!");
109             }
110            
111             # Store the objects
112 1         3 $self->{ssExcel} = $ssExcel;
113 1         3 $self->{ssBook} = $ssBook;
114            
115             # Get the first sheet
116 1         5 $self->getFirstSheet();
117            
118 1         2 return ($ssExcel, $ssBook)
119             }
120            
121            
122            
123            
124             sub numSheets
125             {
126 7     7 1 95 my $self = shift;
127            
128 7 50       34 return defined($self->{ssBook}) ? $self->{ssBook}->{SheetCount} : undef;
129             }
130            
131            
132            
133             sub currentSheetNum
134             {
135 3     3 1 6 my $self = shift;
136            
137 3 100       8 return defined($self->{currentSheetNum}) ? $self->{currentSheetNum} : 0;
138             }
139            
140            
141            
142             sub currentSheetName
143             {
144 4     4 1 113 my $self = shift;
145            
146 4 50       41 return defined($self->{ssSheet}) ? $self->{ssSheet}->{Name} : undef;
147             }
148            
149            
150            
151             sub setCurrentSheetNum
152             {
153 3     3 1 4 my $self = shift;
154 3   50     8 my $shtNo = shift || 0;
155            
156             # Check if this is a valid value
157 3 50 33     13 return undef unless ($shtNo >= 0 && $shtNo <= $self->numSheets());
158            
159             # Set the new sheet number and return the sheet.
160 3         7 $self->{currentSheetNum} = $shtNo;
161 3         7 $self->{ssSheet} = $self->{ssBook}->{Worksheet}[$shtNo];
162 3 100       8 $self->{ssSheetRow} = $self->{ssSheet}->{MinRow} if (defined($self->{ssSheet}));
163 3 100       8 $self->{ssSheetCol} = $self->{ssSheet}->{MinCol} if (defined($self->{ssSheet}));
164 3         5 $self->{ssSheetRow} = -7; # Flag to getNextRow that this is the first row
165 3         5 return $self->{ssSheet};
166             }
167            
168            
169             sub skipHeadings
170             {
171 0   0 0 1 0 $_[0]->{skipHeadings} = $_[1] || 0;
172             }
173            
174            
175             sub getNextSheet
176             {
177 3     3 1 11 my $self = shift;
178            
179 3         6 my $currentSheet = $self->currentSheetNum();
180            
181             # No sheet, so get the first sheet
182 3 50       8 return $self->getFirstSheet() unless (defined($self->{ssSheet}));
183            
184             # Get the next sheet
185 3 50 33     11 if (defined($self->{ssSheet}) && $currentSheet < $self->numSheets())
186             {
187 3         10 $self->setCurrentSheetNum(++$currentSheet);
188 3         6 $self->{ssSheet} = $self->{ssBook}->{Worksheet}[$currentSheet];
189             # $self->{ssSheetRow} = $self->{ssSheet}->{MinRow} if (defined($self->{ssSheet}));
190 3         5 $self->{ssSheetRow} = -7; # So we then find the correct start, setting to min will skip the min row! - Thanks Tim Rossiter
191 3 100       7 $self->{ssSheetCol} = $self->{ssSheet}->{MinCol} if (defined($self->{ssSheet}));
192 3         8 return $self->{ssSheet};
193             }
194            
195 0         0 return undef;
196             }
197            
198            
199            
200             sub getFirstSheet
201             {
202 2     2 1 76 my $self = shift;
203            
204 2         6 $self->{setCurrentSheetNum} = 0;
205 2 50       7 $self->{ssSheet} = $self->{ssBook}->{Worksheet}[0] if (defined($self->{ssBook}));
206 2         6 $self->{ssSheetRow} = -7; # Flag to getNextRow that this is the first row
207 2 50       7 $self->{ssSheetCol} = $self->{ssSheet}->{MinCol} if (defined($self->{ssSheet}));
208 2         4 return $self->{ssSheet};
209             }
210            
211            
212             sub cellValue
213             {
214 21     21 1 40 my ($self, $r, $c) = @_;
215 21 0 33     80 return ($self->{oldCell}? undef : '') unless (defined($self->{ssSheet}) && defined($self->{ssSheet}->{Cells}[$r][$c]));
    50          
216            
217            
218             #return $self->{ssSheet}->{Cells}[$r][$c]->Value;
219             # V1.8 2006/03/05 Changes to cater for OpenOffice returning 'GENERAL'
220 21         51 my $cell_value = $self->{ssSheet}->{Cells}[$r][$c]->Value;
221 21 50       106 if ( $cell_value eq 'GENERAL' ) {
222 0         0 $cell_value = $self->{ssSheet}->{Cells}[$r][$c]->{Val};
223             }
224 21         38 return $cell_value;
225             }
226            
227            
228            
229             sub setHeadingRow
230             {
231 0     0 1 0 my $self = shift;
232 0         0 my $headingRow = shift;
233            
234             $self->{headingRow} = ($headingRow >= $self->{ssSheet}->{MinRow} &&
235             $headingRow <= $self->{ssSheet}->{MaxRow}) ?
236 0 0 0     0 $headingRow : $self->{ssSheet}->{MinRow};
237             }
238            
239            
240             sub getFirstRow
241             {
242 4     4 1 8 my $self = shift;
243            
244 4 50       11 return undef unless defined($self->{ssSheet});
245            
246 4   33     15 my $row = $self->{headingRow} || $self->{ssSheet}->{MinRow};
247 4         8 $self->{ssSheetRow} = $row;
248            
249            
250             # Loop through each column and put into array
251 4         8 my $x = 0;
252 4         9 my @data = ();
253 4         9 my $blank = 0;
254 4         13 for (my $col = $self->{ssSheet}->{MinCol}; $col <= $self->{ssSheet}->{MaxCol}; $x++, $col++)
255             {
256 1     1   9 no warnings qw(uninitialized);
  1         2  
  1         183  
257            
258             # Note that this is the formatted value of the cell (ie what you see, no the real value)
259 12         26 $data[$x] = $self->cellValue($row, $col);
260            
261             # remove leading and trailing whitespace
262 12         27 $data[$x] =~ s/^\s+//;
263 12         29 $data[$x] =~ s/\s+$//;
264 12 50       45 $blank++ unless $data[$x] =~ /^$/;
265             }
266            
267            
268 4 50 33     41 return ($self->{skipHeadings} || ($self->{skipBlankRows} && $blank == 0)) ? $self->getNextRow() : \@data;
269             }
270            
271            
272            
273             sub getNextRow
274             {
275 10     10 1 176 my $self = shift;
276            
277             # Must have a sheet defined
278 10 50       28 return undef unless defined($self->{ssSheet});
279            
280             # Find the next row and make sure it's valid
281 10         16 my $row = ++$self->{ssSheetRow};
282             # Check to make sure there is something on this sheet
283 10 100 66     53 return undef if (! defined($self->{ssSheet}->{MaxRow}) || $row > $self->{ssSheet}->{MaxRow});
284            
285             # If row is zero or negative then this is the first row
286 7 100       22 return $self->getFirstRow() if ($row <= 0);
287            
288            
289             # Loop through each column and put into array
290 3         5 my $x = 0;
291 3         6 my @data = ();
292 3         6 my $blank = 0;
293 3         10 for (my $col = $self->{ssSheet}->{MinCol}; $col <= $self->{ssSheet}->{MaxCol}; $x++, $col++)
294             {
295 1     1   6 no warnings qw(uninitialized);
  1         2  
  1         359  
296            
297             # Note that this is the formatted value of the cell (ie what you see, no the real value)
298 9         18 $data[$x] = $self->cellValue($row, $col);
299            
300             # remove leading and trailing whitespace
301 9         18 $data[$x] =~ s/^\s+//;
302 9         25 $data[$x] =~ s/\s+$//;
303 9 50       30 $blank++ unless $data[$x] =~ /^$/;
304             }
305            
306 3 50 33     13 return ($self->{skipBlankRows} && $blank == 0) ? $self->getNextRow() : \@data;
307             }
308            
309            
310             sub setRow
311             {
312 0   0 0 1   $_[0]->{ssSheetRow} = ($_[1] || 0) - 1;
313             }
314            
315            
316             sub getRowNumber
317             {
318 0   0 0 1   return $_[0]->{ssSheetRow} || -1;
319             }
320            
321            
322             sub logexp
323             {
324 0     0 1   my $self = shift;
325            
326 0           my $msg = join('', @_);
327 0 0         if (defined $self->{log})
328             {
329 0           $self->{log}->exp($msg);
330             }
331            
332 0           die $msg;
333             }
334            
335            
336            
337             sub logmsg
338             {
339 0     0 1   my $self = shift;
340 0           my $level = shift;
341            
342 0           my $msg = join('', @_);
343 0 0         if (defined $self->{log})
344             {
345 0           $self->{log}->msg($level, $msg);
346             }
347             else
348             {
349 0           print STDERR $msg;
350             }
351             }
352            
353             {
354             package Spreadsheet::XLSX::XLSXConvert;
355             sub new {
356 0     0     my $module = shift;
357            
358 0           return bless( { }, $module );
359             }
360             sub convert {
361 0     0     my $self = shift;
362 0           my ($raw) = @_;
363 0           utf8::decode($raw);
364             #also decode html escapes,
365 0           $raw =~ s/\&/&/g;
366 0           $raw =~ s/\</\
367 0           $raw =~ s/\>/\>/g;
368 0           return $raw;
369             }
370             }
371            
372             #####################################################################
373             # DO NOT REMOVE THE FOLLOWING LINE, IT IS NEEDED TO LOAD THIS LIBRARY
374             1;
375            
376             __END__