| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Excel::Table; |
|
2
|
|
|
|
|
|
|
# |
|
3
|
|
|
|
|
|
|
# Excel::Table.pm - spreadsheet table processing class. |
|
4
|
|
|
|
|
|
|
# |
|
5
|
|
|
|
|
|
|
=head1 NAME |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
Excel::Table |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 AUTHOR |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
Copyright (C) 2012 Tom McMeekin Etmcmeeki@cpan.orgE |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
use Excel::Table; |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
my $xs = Excel::Table->new('dir' => '/cygdrive/c/Users/self/Desktop'); |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
for ($xs->list_workbooks) { |
|
20
|
|
|
|
|
|
|
print "workbook [$_]\n"; |
|
21
|
|
|
|
|
|
|
} |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
$xs->open('mybook.xls'); |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
my $wb1 = $xs->open_re('foo*bar*'); |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
for my $worksheet ($wb1->worksheets) { |
|
28
|
|
|
|
|
|
|
print "worksheet: " . $worksheet->get_name() . "\n"; |
|
29
|
|
|
|
|
|
|
} |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
$xs->null("this is a null value"); |
|
32
|
|
|
|
|
|
|
$xs->force_null(1); |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
$xs->rowid(0); |
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
$xs->trim(0); |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
my @data = $xs->extract('Sheet1'); |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
for (@data) { |
|
41
|
|
|
|
|
|
|
printf "rowid [%s] title [%s] max_width [%d] value [%s]\n", |
|
42
|
|
|
|
|
|
|
$_->[0], |
|
43
|
|
|
|
|
|
|
$xs->titles->[0], |
|
44
|
|
|
|
|
|
|
$xs->widths->[0], |
|
45
|
|
|
|
|
|
|
$data{$_}->[0]; |
|
46
|
|
|
|
|
|
|
} |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
@data = $xs->extract_hash('Sheet1'); |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
@data = $xs->select("column1,column2,column3", 'Sheet1'); |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
@data = $xs->select_hash("column1,column2,column3", 'Sheet1'); |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
printf "columns %d rows %d title_row %d\n", |
|
55
|
|
|
|
|
|
|
$xs->columns, $xs->rows, $xs->title_row; |
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
printf "regexp [%s] pathname [%s] sheet_name [%s]\n", |
|
58
|
|
|
|
|
|
|
$xs->regexp, $xs->pathname, $xs->sheet_name; |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
printf "colid2title(0) = [%s]\n", $xs->colid2title(0); |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
printf "title2colid('Foo') = %d\n", $xs->title2colid('Foo'); |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
Excel::Table.pm - spreadsheet table processing. Retrieves worksheets as |
|
67
|
|
|
|
|
|
|
if they are structured tables array-format. |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=over 4 |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=item 1a. OBJ->dir(EXPR) |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
Override the directory location in which to look for workbooks. |
|
74
|
|
|
|
|
|
|
Defaults to "." (i.e. the current working directory). |
|
75
|
|
|
|
|
|
|
This location is critical to the B, B, |
|
76
|
|
|
|
|
|
|
and B methods. |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
=item 1b. OBJ->list_workbooks |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
Returns an array of workbook files in the directory defined by the |
|
81
|
|
|
|
|
|
|
B property. |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=item 2a. OBJ->open(EXPR) |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
Parses the filename specified by EXPR. The B property |
|
86
|
|
|
|
|
|
|
will designate the search path. |
|
87
|
|
|
|
|
|
|
Once opened, via this method (or B) the |
|
88
|
|
|
|
|
|
|
workbook is available for use by the B method. |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
=item 2b. OBJ->open_re(EXPR) |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
This will search for a file which has a filename matching the regexp EXPR. |
|
93
|
|
|
|
|
|
|
A warning will be issued if multiple matches are found, only the first will |
|
94
|
|
|
|
|
|
|
be opened. |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=item 3. OBJ->regexp |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
Returns the regexp used to search for the workbook on the filesystem. |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
=item 4. OBJ->pathname |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
Returns the pathname of the opened workbook. |
|
103
|
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=item 5a. OBJ->extract(EXPR,[TITLE_ROW]) |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
This will extract all data from the worksheet named EXPR. Data is extracted |
|
107
|
|
|
|
|
|
|
into an array and returned. Format of data is per below: |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
[ value1, value2, value3, ... ], |
|
110
|
|
|
|
|
|
|
[ value1, value2, value3, ... ], |
|
111
|
|
|
|
|
|
|
[ value1, value2, value3, ... ], |
|
112
|
|
|
|
|
|
|
... |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
The object OBJ will be populated with various properties to assist you to |
|
115
|
|
|
|
|
|
|
access the data in the array, including column titles and widths. |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
A worksheet object is temporarily created in order to populate the array. |
|
118
|
|
|
|
|
|
|
Once a worksheet is extracted, the associated worksheet object is destroyed. |
|
119
|
|
|
|
|
|
|
This routine can be called again on any worksheet in the workbook. |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
If the TITLE_ROW argument is specified, then the B property will |
|
122
|
|
|
|
|
|
|
also be updated prior to extraction. |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=item 5b. OBJ->extract_hash(EXPR,[TITLE_ROW]) |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
Per the B method, but returns an array of hashes, with the hash |
|
127
|
|
|
|
|
|
|
keys corresponding to the titles. |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=item 5c. OBJ->select(CLAUSE,EXPR,[TITLE_ROW]) |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
Similar to the B method, this will extract all rows from the worksheet EXPR, constraining the columns to those specified by the B argument, |
|
132
|
|
|
|
|
|
|
which is a comma-separated string, e.g. "column1,column2,column3". |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
As with the B method, the B and B properties will |
|
135
|
|
|
|
|
|
|
be revised. |
|
136
|
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=item 5d. OBJ->select_hash(CLAUSE,EXPR,[TITLE_ROW]) |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
Per the B |
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=item 6. OBJ->columns or OBJ->rows |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
Returns the number of columns or rows available in the sheet extracted via the |
|
144
|
|
|
|
|
|
|
B method. |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=item 7a. OBJ->force_null |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
Flag which determines if whitespace fields should be |
|
149
|
|
|
|
|
|
|
replaced by specific text (see OBJ->null). |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=item 7b. OBJ->null |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
String to replace whitespace fields with. Defaults to "(null)". |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=item 8. OBJ->rowid |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
Flag which determines whether a pseudo-column "rowid" is included in each |
|
158
|
|
|
|
|
|
|
tuple. The value will take the form "999999999" Defaults to FALSE. |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=item 9. OBJ->sheet_name |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
Returns the sheet_name against which data was extracted via B. |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
=item 10. OBJ->trim |
|
165
|
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
Flag which determines if trailing whitespace fields should be trimmed. |
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=item 11a. OBJ->title_row |
|
169
|
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
Returns the title row of the worksheet (defaults to zero), following extract. |
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=item 11b. OBJ->titles |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
Returns an array of title fields, the title row number having been defined |
|
175
|
|
|
|
|
|
|
as OBJ->title_row. |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=item 11c. OBJ->colid2title(colid) |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
Converts the column number (colid) to a string column title (i.e. |
|
180
|
|
|
|
|
|
|
the offset within the title_row array). |
|
181
|
|
|
|
|
|
|
If no match, then returns undef. |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=item 11d. OBJ->title2colid(REGEXP) |
|
184
|
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
Returns the column number of the title identified by REGEXP. |
|
186
|
|
|
|
|
|
|
If no match, then returns undef. |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=item 12. OBJ->widths |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
Returns an array of maximum lengths of any (non-title) data in each column. |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=back |
|
193
|
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=cut |
|
195
|
|
|
|
|
|
|
|
|
196
|
9
|
|
|
9
|
|
698301
|
use strict; |
|
|
9
|
|
|
|
|
17
|
|
|
|
9
|
|
|
|
|
385
|
|
|
197
|
9
|
|
|
9
|
|
44
|
use warnings; |
|
|
9
|
|
|
|
|
17
|
|
|
|
9
|
|
|
|
|
275
|
|
|
198
|
|
|
|
|
|
|
|
|
199
|
9
|
|
|
9
|
|
901
|
use Data::Dumper; |
|
|
9
|
|
|
|
|
11672
|
|
|
|
9
|
|
|
|
|
653
|
|
|
200
|
9
|
|
|
9
|
|
8372
|
use Spreadsheet::ParseExcel 0.57; |
|
|
9
|
|
|
|
|
540692
|
|
|
|
9
|
|
|
|
|
313
|
|
|
201
|
9
|
|
|
9
|
|
4992
|
use Spreadsheet::XLSX; |
|
|
9
|
|
|
|
|
565063
|
|
|
|
9
|
|
|
|
|
325
|
|
|
202
|
9
|
|
|
9
|
|
92
|
use File::Basename; |
|
|
9
|
|
|
|
|
13
|
|
|
|
9
|
|
|
|
|
669
|
|
|
203
|
|
|
|
|
|
|
|
|
204
|
9
|
|
|
9
|
|
51
|
use Carp qw(cluck confess); # only use stack backtrace within class |
|
|
9
|
|
|
|
|
12
|
|
|
|
9
|
|
|
|
|
510
|
|
|
205
|
9
|
|
|
9
|
|
47
|
use Log::Log4perl qw/ get_logger /; |
|
|
9
|
|
|
|
|
11
|
|
|
|
9
|
|
|
|
|
91
|
|
|
206
|
|
|
|
|
|
|
|
|
207
|
9
|
|
|
9
|
|
542
|
use vars qw/ @EXPORT $VERSION /; |
|
|
9
|
|
|
|
|
16
|
|
|
|
9
|
|
|
|
|
578
|
|
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
$VERSION = "1.021"; # update this on new release |
|
210
|
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
#@ISA = qw(Exporter); |
|
212
|
|
|
|
|
|
|
#@EXPORT = qw(); |
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
# package constants |
|
215
|
9
|
|
|
9
|
|
122
|
use constant S_RID => "rowid"; |
|
|
9
|
|
|
|
|
13
|
|
|
|
9
|
|
|
|
|
564
|
|
|
216
|
9
|
|
|
9
|
|
41
|
use constant S_NULL => "(null)"; |
|
|
9
|
|
|
|
|
10
|
|
|
|
9
|
|
|
|
|
421
|
|
|
217
|
9
|
|
|
|
|
518
|
use constant EXT_EXCEL => qw/ |
|
218
|
|
|
|
|
|
|
\.xls \.xla \.xlb \.xlc \.xld \.xlk \.xll \.xlm \.xlt |
|
219
|
|
|
|
|
|
|
\.xlv \.xlw \.xls \.xlt |
|
220
|
9
|
|
|
9
|
|
39
|
/; # known extensions for EXCEL file |
|
|
9
|
|
|
|
|
11
|
|
|
221
|
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
# need the Spreadsheet::XLSX module for the following: |
|
223
|
9
|
|
|
|
|
23338
|
use constant EXT_EXCEL_2007 => qw/ |
|
224
|
|
|
|
|
|
|
\.xlsx \.xlsm \.xlsb \.xltm \.xlam |
|
225
|
9
|
|
|
9
|
|
43
|
/; # known extensions for EXCEL 2007 file |
|
|
9
|
|
|
|
|
11
|
|
|
226
|
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
# package globals |
|
229
|
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
our $AUTOLOAD; |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
# package locals |
|
234
|
|
|
|
|
|
|
my $n_Objects = 0; # counter of objects created. |
|
235
|
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
my %attribute = ( |
|
237
|
|
|
|
|
|
|
_n_objects => \$n_Objects, |
|
238
|
|
|
|
|
|
|
_xl_vers => undef, |
|
239
|
|
|
|
|
|
|
columns => undef, |
|
240
|
|
|
|
|
|
|
dir => ".", |
|
241
|
|
|
|
|
|
|
_log => get_logger("Excel::Table"), |
|
242
|
|
|
|
|
|
|
null => S_NULL, |
|
243
|
|
|
|
|
|
|
pathname => undef, |
|
244
|
|
|
|
|
|
|
regexp => undef, |
|
245
|
|
|
|
|
|
|
force_null => 0, |
|
246
|
|
|
|
|
|
|
rows => undef, |
|
247
|
|
|
|
|
|
|
rowid => 0, |
|
248
|
|
|
|
|
|
|
sheet_name => undef, |
|
249
|
|
|
|
|
|
|
title_row => 0, # if title row is zero, first data row is 1 |
|
250
|
|
|
|
|
|
|
titles => undef, |
|
251
|
|
|
|
|
|
|
trim => 0, |
|
252
|
|
|
|
|
|
|
widths => undef, |
|
253
|
|
|
|
|
|
|
workbook => undef, |
|
254
|
|
|
|
|
|
|
); |
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
#INIT { }; |
|
258
|
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
sub AUTOLOAD { |
|
261
|
18985
|
|
|
18985
|
|
577870
|
my $self = shift; |
|
262
|
18985
|
50
|
|
|
|
29607
|
my $type = ref($self) or croak("self is not an object"); |
|
263
|
|
|
|
|
|
|
|
|
264
|
18985
|
|
|
|
|
16937
|
my $name = $AUTOLOAD; |
|
265
|
18985
|
|
|
|
|
42574
|
$name =~ s/.*://; # strip fully−qualified portion |
|
266
|
|
|
|
|
|
|
|
|
267
|
18985
|
50
|
|
|
|
35565
|
unless (exists $self->{_permitted}->{$name} ) { |
|
268
|
0
|
|
|
|
|
0
|
confess "no attribute [$name] in class [$type]"; |
|
269
|
|
|
|
|
|
|
} |
|
270
|
|
|
|
|
|
|
|
|
271
|
18985
|
100
|
|
|
|
23411
|
if (@_) { |
|
272
|
328
|
|
|
|
|
848
|
return $self->{$name} = shift; |
|
273
|
|
|
|
|
|
|
} else { |
|
274
|
18657
|
|
|
|
|
52818
|
return $self->{$name}; |
|
275
|
|
|
|
|
|
|
} |
|
276
|
|
|
|
|
|
|
} |
|
277
|
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
sub new { |
|
280
|
24
|
|
|
24
|
0
|
33013
|
my ($class) = shift; |
|
281
|
|
|
|
|
|
|
#my $self = $class->SUPER::new(@_); |
|
282
|
24
|
|
|
|
|
346
|
my $self = { _permitted => \%attribute, %attribute }; |
|
283
|
|
|
|
|
|
|
|
|
284
|
24
|
|
|
|
|
81
|
++ ${ $self->{_n_objects} }; |
|
|
24
|
|
|
|
|
62
|
|
|
285
|
|
|
|
|
|
|
|
|
286
|
24
|
|
|
|
|
57
|
bless ($self, $class); |
|
287
|
|
|
|
|
|
|
|
|
288
|
24
|
|
|
|
|
63
|
my %args = @_; # start processing any parameters passed |
|
289
|
24
|
|
|
|
|
36
|
my ($method,$value); # start processing any parameters passed |
|
290
|
24
|
|
|
|
|
137
|
while (($method, $value) = each %args) { |
|
291
|
|
|
|
|
|
|
|
|
292
|
31
|
50
|
|
|
|
75
|
confess "SYNTAX new(method => value, ...) value not specified" |
|
293
|
|
|
|
|
|
|
unless (defined $value); |
|
294
|
|
|
|
|
|
|
|
|
295
|
31
|
|
|
|
|
145
|
$self->_log->debug("method [self->$method($value)]"); |
|
296
|
|
|
|
|
|
|
|
|
297
|
31
|
|
|
|
|
269
|
$self->$method($value); |
|
298
|
|
|
|
|
|
|
} |
|
299
|
|
|
|
|
|
|
|
|
300
|
24
|
|
|
|
|
74
|
return $self; |
|
301
|
|
|
|
|
|
|
} |
|
302
|
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
sub _determine_xl_vers { |
|
305
|
290
|
|
|
290
|
|
402
|
my ($self,$pn)=@_; |
|
306
|
290
|
50
|
|
|
|
512
|
$self->_log->logcroak("SYNTAX: _determine_xl_vers(path)") |
|
307
|
|
|
|
|
|
|
unless defined ($pn); |
|
308
|
|
|
|
|
|
|
# return version string or undef for given pathname |
|
309
|
290
|
|
|
|
|
264
|
my $extension; |
|
310
|
|
|
|
|
|
|
my @extensions; |
|
311
|
290
|
|
|
|
|
253
|
my $retval = undef; |
|
312
|
|
|
|
|
|
|
|
|
313
|
290
|
|
|
|
|
881
|
$self->_log->debug("pn [$pn]"); |
|
314
|
|
|
|
|
|
|
|
|
315
|
290
|
|
|
|
|
2328
|
@extensions = EXT_EXCEL; |
|
316
|
290
|
|
|
|
|
26154
|
(undef,undef,$extension) = fileparse($pn,@extensions); |
|
317
|
|
|
|
|
|
|
#$self->_log->debug(sprintf " extension [%s] \@extensions [%s]", $extension, Dumper(\@extensions)); |
|
318
|
|
|
|
|
|
|
|
|
319
|
290
|
100
|
|
|
|
774
|
$retval = 'xl2003' if ($extension ne ""); |
|
320
|
|
|
|
|
|
|
|
|
321
|
290
|
|
|
|
|
810
|
@extensions = EXT_EXCEL_2007; |
|
322
|
290
|
|
|
|
|
12506
|
(undef,undef,$extension) = fileparse($pn,@extensions); |
|
323
|
|
|
|
|
|
|
|
|
324
|
290
|
100
|
|
|
|
755
|
$retval = 'xl2007' if ($extension ne ""); |
|
325
|
|
|
|
|
|
|
|
|
326
|
290
|
100
|
|
|
|
484
|
if (defined $retval) { |
|
327
|
56
|
|
|
|
|
240
|
$self->_log->debug("pn [$pn] returning [$retval]"); |
|
328
|
|
|
|
|
|
|
} |
|
329
|
|
|
|
|
|
|
|
|
330
|
290
|
|
|
|
|
1676
|
return $retval; |
|
331
|
|
|
|
|
|
|
} |
|
332
|
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
sub list_workbooks { |
|
335
|
13
|
|
|
13
|
1
|
1065
|
my $self = shift; |
|
336
|
|
|
|
|
|
|
|
|
337
|
13
|
|
|
|
|
57
|
my $dn = $self->dir; |
|
338
|
13
|
|
|
|
|
17
|
my ($dh,$fn); |
|
339
|
0
|
|
|
|
|
0
|
my @workbooks; |
|
340
|
|
|
|
|
|
|
|
|
341
|
13
|
|
|
|
|
45
|
$self->_log->debug("dn [$dn]"); |
|
342
|
|
|
|
|
|
|
|
|
343
|
13
|
50
|
|
|
|
699
|
opendir($dh, $dn) || $self->_log->logcroak("opendir($dn)"); |
|
344
|
|
|
|
|
|
|
|
|
345
|
13
|
|
|
|
|
209
|
while ($fn = readdir($dh)) { |
|
346
|
260
|
|
|
|
|
2042
|
my $pn = File::Spec->catfile($dn, $fn); |
|
347
|
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
# need to remember just the filename here, not the path because |
|
349
|
|
|
|
|
|
|
# open will use the self->dir property to make the path |
|
350
|
260
|
100
|
|
|
|
596
|
push @workbooks, $fn |
|
351
|
|
|
|
|
|
|
if (defined($self->_determine_xl_vers($pn))); |
|
352
|
|
|
|
|
|
|
} |
|
353
|
|
|
|
|
|
|
|
|
354
|
13
|
|
|
|
|
132
|
closedir $dh; |
|
355
|
|
|
|
|
|
|
|
|
356
|
13
|
|
|
|
|
73
|
$self->_log->debug(sprintf '@workbooks [%s]', Dumper(\@workbooks)); |
|
357
|
|
|
|
|
|
|
|
|
358
|
13
|
|
|
|
|
1267
|
return @workbooks; |
|
359
|
|
|
|
|
|
|
} |
|
360
|
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
sub open { |
|
363
|
30
|
|
|
30
|
1
|
9525
|
my ($self,$fn)=@_; |
|
364
|
30
|
50
|
|
|
|
108
|
$self->_log->logcroak("SYNTAX: open(file)") unless defined ($fn); |
|
365
|
30
|
|
|
|
|
196
|
my $pn = File::Spec->catfile($self->dir, $fn); |
|
366
|
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
# to look for the file in the cwd, is not good behaviour, |
|
368
|
|
|
|
|
|
|
# so dir must be explicit, thus the default to "." |
|
369
|
|
|
|
|
|
|
|
|
370
|
30
|
50
|
|
|
|
604
|
if (-f $pn) { |
|
371
|
30
|
|
|
|
|
158
|
$self->pathname($pn); |
|
372
|
|
|
|
|
|
|
} else { |
|
373
|
0
|
|
|
|
|
0
|
$self->_log->logcroak("no such path [$pn]"); |
|
374
|
|
|
|
|
|
|
} |
|
375
|
|
|
|
|
|
|
|
|
376
|
30
|
|
|
|
|
141
|
$self->_log->debug("parsing [$pn]"); |
|
377
|
|
|
|
|
|
|
|
|
378
|
30
|
|
|
|
|
318
|
$self->{'_xl_vers'} = $self->_determine_xl_vers($pn); |
|
379
|
|
|
|
|
|
|
|
|
380
|
30
|
|
|
|
|
47
|
my $parser; |
|
381
|
|
|
|
|
|
|
|
|
382
|
30
|
100
|
|
|
|
157
|
if ($self->_xl_vers eq 'xl2007') { |
|
383
|
13
|
|
|
|
|
185
|
$parser = Spreadsheet::XLSX->new($pn); |
|
384
|
|
|
|
|
|
|
|
|
385
|
13
|
50
|
|
|
|
409905
|
$self->_log->logcroak("Spreadsheet::XLSX->new($pn) failed") |
|
386
|
|
|
|
|
|
|
unless defined $parser; |
|
387
|
|
|
|
|
|
|
|
|
388
|
13
|
|
|
|
|
127
|
$self->workbook($parser); |
|
389
|
|
|
|
|
|
|
} else { |
|
390
|
17
|
|
|
|
|
150
|
$parser = Spreadsheet::ParseExcel->new(); |
|
391
|
17
|
|
|
|
|
28926
|
$self->workbook($parser->Parse($pn)); |
|
392
|
|
|
|
|
|
|
|
|
393
|
17
|
50
|
|
|
|
835
|
$self->_log->logcroak("Parse() failed, error: " . $self->workbook->error()) |
|
394
|
|
|
|
|
|
|
unless defined $self->workbook; |
|
395
|
|
|
|
|
|
|
} |
|
396
|
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
|
|
398
|
30
|
|
|
|
|
146
|
return $self->workbook; |
|
399
|
|
|
|
|
|
|
} |
|
400
|
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
sub open_re { |
|
403
|
7
|
|
|
7
|
1
|
3583
|
my $self = shift; |
|
404
|
7
|
50
|
|
|
|
20
|
if (@_) { $self->regexp(shift); } else { $self->_log->logcroak("SYNTAX: open_re(regexp)"); } |
|
|
7
|
|
|
|
|
39
|
|
|
|
0
|
|
|
|
|
0
|
|
|
405
|
7
|
|
|
|
|
45
|
my $re = $self->regexp; |
|
406
|
7
|
|
|
|
|
12
|
my $matches = 0; |
|
407
|
7
|
|
|
|
|
8
|
my $wb = undef; |
|
408
|
|
|
|
|
|
|
|
|
409
|
7
|
|
|
|
|
24
|
$self->_log->debug(sprintf "regexp [%s]", $self->regexp); |
|
410
|
7
|
|
|
|
|
60
|
for ( $self->list_workbooks ) { |
|
411
|
14
|
|
|
|
|
53
|
$self->_log->debug(" file [$_]"); |
|
412
|
14
|
100
|
|
|
|
160
|
if ($_ =~ /$re/) { |
|
413
|
10
|
|
|
|
|
34
|
$self->_log->debug(" FOUND [$_]"); |
|
414
|
10
|
100
|
|
|
|
77
|
$wb = $_ unless ($matches++); # remember first occurence |
|
415
|
|
|
|
|
|
|
} |
|
416
|
|
|
|
|
|
|
} |
|
417
|
|
|
|
|
|
|
|
|
418
|
7
|
100
|
|
|
|
22
|
unless (defined $wb) { |
|
419
|
1
|
|
|
|
|
3
|
$self->_log->logcarp("could not find file matching [$re]"); |
|
420
|
1
|
|
|
|
|
529
|
return undef; |
|
421
|
|
|
|
|
|
|
} |
|
422
|
|
|
|
|
|
|
|
|
423
|
6
|
100
|
|
|
|
28
|
$self->_log->logwarn("non-unique match on [$re]") |
|
424
|
|
|
|
|
|
|
if ($matches > 1); |
|
425
|
|
|
|
|
|
|
|
|
426
|
6
|
|
|
|
|
1554
|
return $self->open($wb); |
|
427
|
|
|
|
|
|
|
} |
|
428
|
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
sub _prepend_rowid { |
|
431
|
110
|
|
|
110
|
|
122
|
my ($self, $ra_columns, $id)=@_; |
|
432
|
|
|
|
|
|
|
|
|
433
|
110
|
100
|
|
|
|
260
|
my $rowid = ($id == $self->title_row) ? S_RID : sprintf "%09d", $id; |
|
434
|
|
|
|
|
|
|
|
|
435
|
110
|
|
|
|
|
156
|
push @$ra_columns, $rowid; |
|
436
|
|
|
|
|
|
|
|
|
437
|
110
|
|
|
|
|
120
|
return $rowid; |
|
438
|
|
|
|
|
|
|
} |
|
439
|
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
sub extract { |
|
442
|
36
|
|
|
36
|
1
|
5114
|
my $self = shift; |
|
443
|
36
|
50
|
|
|
|
125
|
if (@_) { $self->sheet_name(shift); } |
|
|
36
|
|
|
|
|
210
|
|
|
444
|
36
|
50
|
|
|
|
118
|
if (@_) { $self->title_row(shift); } |
|
|
0
|
|
|
|
|
0
|
|
|
445
|
|
|
|
|
|
|
|
|
446
|
36
|
50
|
33
|
|
|
138
|
$self->_log->logcroak("SYNTAX: extract(sheet_name,title_row)") |
|
447
|
|
|
|
|
|
|
unless (defined $self->sheet_name && defined $self->title_row); |
|
448
|
|
|
|
|
|
|
|
|
449
|
36
|
|
|
|
|
154
|
$self->_log->debug(sprintf "opening [%s]", $self->sheet_name); |
|
450
|
|
|
|
|
|
|
|
|
451
|
36
|
|
|
|
|
400
|
my $ws = $self->workbook->worksheet($self->sheet_name); |
|
452
|
|
|
|
|
|
|
|
|
453
|
36
|
|
|
|
|
573
|
my ($minr, $maxr) = $ws->row_range(); |
|
454
|
36
|
|
|
|
|
372
|
my ($minc, $maxc) = $ws->col_range(); |
|
455
|
|
|
|
|
|
|
|
|
456
|
36
|
|
|
|
|
380
|
$self->rows($maxr); |
|
457
|
36
|
|
|
|
|
204
|
$self->columns($maxc + 1); |
|
458
|
|
|
|
|
|
|
|
|
459
|
36
|
100
|
|
|
|
116
|
$self->title_row($minr) # fix minimum row |
|
460
|
|
|
|
|
|
|
if ($self->title_row < $minr); |
|
461
|
|
|
|
|
|
|
|
|
462
|
36
|
|
|
|
|
133
|
$self->_log->debug(sprintf "sheet_name [%s] minr [%d] maxr [%d] minc [%d] maxc [%d]", |
|
463
|
|
|
|
|
|
|
$self->sheet_name, $minr, $maxr, $minc, $maxc); |
|
464
|
|
|
|
|
|
|
|
|
465
|
36
|
|
|
|
|
209
|
my ($subr,$subc,$value); |
|
466
|
0
|
|
|
|
|
0
|
my @data; |
|
467
|
0
|
|
|
|
|
0
|
my (@columns,@widths); |
|
468
|
|
|
|
|
|
|
|
|
469
|
36
|
|
|
|
|
119
|
for ($subr = $self->title_row; $subr <= $maxr; $subr++) { |
|
470
|
|
|
|
|
|
|
|
|
471
|
368
|
100
|
|
|
|
968
|
$self->_prepend_rowid(\@columns, $subr) |
|
472
|
|
|
|
|
|
|
if ($self->rowid); |
|
473
|
|
|
|
|
|
|
|
|
474
|
368
|
|
|
|
|
769
|
for ($subc = $minc; $subc <= $maxc; $subc++) { |
|
475
|
|
|
|
|
|
|
|
|
476
|
3584
|
|
|
|
|
7355
|
my $cell = $ws->get_cell($subr, $subc); |
|
477
|
|
|
|
|
|
|
|
|
478
|
3584
|
100
|
|
|
|
27844
|
if (defined $cell) { |
|
479
|
3552
|
100
|
|
|
|
8820
|
$value = ($self->trim) ? $self->_trim_whitespace($cell->value) : $cell->value; |
|
480
|
|
|
|
|
|
|
} else { |
|
481
|
32
|
|
|
|
|
42
|
$value = undef; |
|
482
|
|
|
|
|
|
|
} |
|
483
|
|
|
|
|
|
|
|
|
484
|
3584
|
100
|
|
|
|
13211
|
$value = $self->_resolve_null($value, $self->null) |
|
485
|
|
|
|
|
|
|
if ($self->force_null); |
|
486
|
|
|
|
|
|
|
|
|
487
|
3584
|
|
|
|
|
7803
|
push @columns, $value; |
|
488
|
|
|
|
|
|
|
} |
|
489
|
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
# adjust widths, including rowid column |
|
491
|
368
|
|
|
|
|
343
|
$subc = 0; |
|
492
|
368
|
|
|
|
|
474
|
for $value (@columns) { |
|
493
|
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
# calculate width, ignoring title_row |
|
495
|
|
|
|
|
|
|
|
|
496
|
3694
|
100
|
|
|
|
8891
|
if ($subr == $self->title_row) { |
|
497
|
346
|
|
|
|
|
371
|
$widths[$subc] = 0; |
|
498
|
|
|
|
|
|
|
} else { |
|
499
|
3348
|
100
|
100
|
|
|
11149
|
$widths[$subc] = length($value) |
|
500
|
|
|
|
|
|
|
if (defined($value) && |
|
501
|
|
|
|
|
|
|
length($value) > $widths[$subc]); |
|
502
|
|
|
|
|
|
|
} |
|
503
|
|
|
|
|
|
|
|
|
504
|
3694
|
|
|
|
|
3946
|
$subc++; |
|
505
|
|
|
|
|
|
|
} |
|
506
|
|
|
|
|
|
|
|
|
507
|
368
|
|
|
|
|
966
|
$self->_log->debug(sprintf '@columns [%s]', Dumper(\@columns)); |
|
508
|
368
|
|
|
|
|
26592
|
$self->_log->debug(sprintf '@widths [%s]', Dumper(\@widths)); |
|
509
|
|
|
|
|
|
|
|
|
510
|
368
|
100
|
|
|
|
22789
|
if ($subr == $self->title_row) { |
|
511
|
36
|
|
|
|
|
195
|
$self->titles([ @columns ]); |
|
512
|
|
|
|
|
|
|
} else { |
|
513
|
332
|
|
|
|
|
936
|
push @data, [ @columns ]; |
|
514
|
|
|
|
|
|
|
} |
|
515
|
368
|
|
|
|
|
1079
|
@columns = (); |
|
516
|
|
|
|
|
|
|
} |
|
517
|
36
|
|
|
|
|
216
|
$self->widths([ @widths ]); |
|
518
|
|
|
|
|
|
|
|
|
519
|
36
|
|
|
|
|
85
|
@widths = $ws = (); |
|
520
|
|
|
|
|
|
|
|
|
521
|
36
|
|
|
|
|
292
|
return @data; |
|
522
|
|
|
|
|
|
|
} |
|
523
|
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
sub colid2title { |
|
526
|
4
|
|
|
4
|
1
|
9
|
my ($self,$colid)=@_; |
|
527
|
|
|
|
|
|
|
|
|
528
|
4
|
50
|
|
|
|
16
|
$self->_log->logcroak("SYNTAX: colid2title2(colid)") |
|
529
|
|
|
|
|
|
|
unless (defined $colid); |
|
530
|
|
|
|
|
|
|
|
|
531
|
4
|
|
|
|
|
23
|
$self->_log->debug("colid [$colid]"); |
|
532
|
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
return undef |
|
534
|
4
|
50
|
|
|
|
38
|
if ($colid < 0); |
|
535
|
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
return undef |
|
537
|
4
|
100
|
|
|
|
5
|
unless ($colid < scalar @{ $self->titles }); |
|
|
4
|
|
|
|
|
18
|
|
|
538
|
|
|
|
|
|
|
|
|
539
|
2
|
|
|
|
|
10
|
return $self->titles->[$colid]; |
|
540
|
|
|
|
|
|
|
} |
|
541
|
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
sub title2colid { |
|
544
|
44
|
|
|
44
|
1
|
69
|
my ($self,$title)=@_; |
|
545
|
|
|
|
|
|
|
|
|
546
|
44
|
50
|
|
|
|
93
|
$self->_log->logcroak("SYNTAX: title2colid(title)") |
|
547
|
|
|
|
|
|
|
unless (defined $title); |
|
548
|
|
|
|
|
|
|
|
|
549
|
44
|
|
|
|
|
124
|
$self->_log->debug("title [$title] "); |
|
550
|
|
|
|
|
|
|
|
|
551
|
44
|
|
|
|
|
189
|
my $tmax = scalar @{ $self->titles }; |
|
|
44
|
|
|
|
|
118
|
|
|
552
|
|
|
|
|
|
|
|
|
553
|
44
|
|
|
|
|
139
|
for (my $tsub = 0; $tsub < $tmax; $tsub++) { |
|
554
|
294
|
100
|
|
|
|
831
|
if ($self->titles->[$tsub] =~ /$title/) { |
|
555
|
30
|
|
|
|
|
95
|
$self->_log->debug("match at colid $tsub"); |
|
556
|
30
|
|
|
|
|
186
|
return $tsub; |
|
557
|
|
|
|
|
|
|
} |
|
558
|
|
|
|
|
|
|
} |
|
559
|
14
|
|
|
|
|
54
|
$self->_log->debug("NO MATCH"); |
|
560
|
|
|
|
|
|
|
|
|
561
|
14
|
|
|
|
|
90
|
return undef; |
|
562
|
|
|
|
|
|
|
} |
|
563
|
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
sub _trim_whitespace { |
|
566
|
1526
|
|
|
1526
|
|
5288
|
my ($self,$s_value)=@_; |
|
567
|
|
|
|
|
|
|
|
|
568
|
1526
|
50
|
|
|
|
2207
|
if (defined $s_value) { |
|
569
|
1526
|
|
|
|
|
3360
|
$self->_log->debug("s_value [$s_value]"); |
|
570
|
|
|
|
|
|
|
|
|
571
|
1526
|
|
|
|
|
7909
|
$s_value =~ s/^[[:cntrl:][:space:]]+//; # trim leading |
|
572
|
1526
|
|
|
|
|
2194
|
$s_value =~ s/[[:cntrl:][:space:]]+$//; # trim trailing |
|
573
|
|
|
|
|
|
|
|
|
574
|
1526
|
|
|
|
|
3538
|
$self->_log->debug("after s_value [$s_value]"); |
|
575
|
|
|
|
|
|
|
} |
|
576
|
|
|
|
|
|
|
|
|
577
|
1526
|
|
|
|
|
7464
|
return $s_value; |
|
578
|
|
|
|
|
|
|
} |
|
579
|
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
sub _resolve_null { |
|
582
|
440
|
|
|
440
|
|
434
|
my ($self, $s_value, $s_null)=@_; |
|
583
|
|
|
|
|
|
|
|
|
584
|
440
|
100
|
|
|
|
787
|
$self->_log->debug(sprintf "s_value [%s] s_null [%s]", |
|
|
|
50
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
(defined $s_value) ? $s_value : "not defined", |
|
586
|
|
|
|
|
|
|
(defined $s_null) ? $s_null : "not defined", |
|
587
|
|
|
|
|
|
|
); |
|
588
|
|
|
|
|
|
|
|
|
589
|
440
|
100
|
|
|
|
1871
|
if (defined $s_value) { |
|
590
|
436
|
100
|
|
|
|
656
|
$s_value = $s_null |
|
591
|
|
|
|
|
|
|
if ($s_value eq ""); |
|
592
|
|
|
|
|
|
|
} else { |
|
593
|
4
|
|
|
|
|
5
|
$s_value = $s_null; |
|
594
|
|
|
|
|
|
|
} |
|
595
|
|
|
|
|
|
|
|
|
596
|
440
|
|
|
|
|
470
|
return $s_value; |
|
597
|
|
|
|
|
|
|
} |
|
598
|
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
sub _array_to_hash { |
|
601
|
4
|
|
|
4
|
|
6
|
my $self = shift; |
|
602
|
4
|
|
|
|
|
6
|
my @data; |
|
603
|
|
|
|
|
|
|
|
|
604
|
4
|
|
|
|
|
12
|
for my $row (@_) { |
|
605
|
40
|
|
|
|
|
136
|
$self->_log->debug(sprintf '$row [%s]', Dumper($row)); |
|
606
|
|
|
|
|
|
|
|
|
607
|
40
|
|
|
|
|
2353
|
my %data; |
|
608
|
40
|
|
|
|
|
68
|
my $unique = 0; |
|
609
|
40
|
|
|
|
|
59
|
my $m_value = scalar(@$row); |
|
610
|
|
|
|
|
|
|
|
|
611
|
40
|
|
|
|
|
99
|
for (my $ss_value = 0; $ss_value < $m_value; $ss_value++) { |
|
612
|
|
|
|
|
|
|
|
|
613
|
260
|
|
|
|
|
632
|
my $column = $self->titles->[$ss_value]; |
|
614
|
260
|
|
|
|
|
289
|
my $value = $row->[$ss_value]; |
|
615
|
|
|
|
|
|
|
|
|
616
|
260
|
100
|
|
|
|
367
|
my $key = (exists $data{$column}) ? $column . $unique++ : $column; |
|
617
|
260
|
|
|
|
|
565
|
$data{$key} = $value; |
|
618
|
|
|
|
|
|
|
} |
|
619
|
|
|
|
|
|
|
|
|
620
|
40
|
|
|
|
|
109
|
$self->_log->debug(sprintf 'data [%s]', Dumper(\%data)); |
|
621
|
|
|
|
|
|
|
|
|
622
|
40
|
|
|
|
|
2687
|
push @data, { %data }; |
|
623
|
|
|
|
|
|
|
|
|
624
|
40
|
|
|
|
|
127
|
%data = (); |
|
625
|
|
|
|
|
|
|
} |
|
626
|
|
|
|
|
|
|
|
|
627
|
4
|
|
|
|
|
26
|
return @data; |
|
628
|
|
|
|
|
|
|
} |
|
629
|
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
sub extract_hash { |
|
632
|
2
|
|
|
2
|
1
|
5
|
my $self = shift; |
|
633
|
|
|
|
|
|
|
|
|
634
|
2
|
50
|
|
|
|
8
|
$self->_log->logcroak("SYNTAX: extract_hash(sheet_name,[title_row])") |
|
635
|
|
|
|
|
|
|
unless (@_ > 0); |
|
636
|
|
|
|
|
|
|
|
|
637
|
2
|
|
|
|
|
7
|
return $self->_array_to_hash($self->extract(@_)); |
|
638
|
|
|
|
|
|
|
} |
|
639
|
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
sub select_hash { |
|
642
|
2
|
|
|
2
|
1
|
9344
|
my $self = shift; |
|
643
|
2
|
|
|
|
|
5
|
my $clause = shift; |
|
644
|
|
|
|
|
|
|
|
|
645
|
2
|
50
|
|
|
|
11
|
$self->_log->logcroak("SYNTAX: select_hash(clause,[sheet_name,title_row])") |
|
646
|
|
|
|
|
|
|
unless (@_ > 0); |
|
647
|
|
|
|
|
|
|
|
|
648
|
2
|
|
|
|
|
10
|
return $self->_array_to_hash($self->select($clause, @_)); |
|
649
|
|
|
|
|
|
|
} |
|
650
|
|
|
|
|
|
|
|
|
651
|
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
sub select { |
|
653
|
14
|
|
|
14
|
1
|
9667
|
my $self = shift; |
|
654
|
14
|
|
|
|
|
28
|
my $clause = shift; |
|
655
|
|
|
|
|
|
|
|
|
656
|
14
|
50
|
|
|
|
50
|
$self->_log->logcroak("SYNTAX: select(clause,[sheet_name,title_row])") |
|
657
|
|
|
|
|
|
|
unless (defined $clause); |
|
658
|
|
|
|
|
|
|
|
|
659
|
14
|
|
|
|
|
61
|
my @pre = $self->extract(@_); |
|
660
|
14
|
|
|
|
|
29
|
my (@post, @id); |
|
661
|
0
|
|
|
|
|
0
|
my (@columns, @widths); |
|
662
|
|
|
|
|
|
|
|
|
663
|
14
|
100
|
|
|
|
46
|
$clause = join(',', S_RID, $clause) |
|
664
|
|
|
|
|
|
|
if ($self->rowid); |
|
665
|
|
|
|
|
|
|
|
|
666
|
14
|
|
|
|
|
71
|
for my $column (split(/,/, $clause)) { |
|
667
|
40
|
|
|
|
|
3079
|
$self->_log->debug("column [$column]"); |
|
668
|
|
|
|
|
|
|
|
|
669
|
40
|
|
|
|
|
241
|
my $id = $self->title2colid($column); |
|
670
|
|
|
|
|
|
|
|
|
671
|
40
|
100
|
|
|
|
72
|
if (defined $id) { |
|
672
|
28
|
|
|
|
|
43
|
push @id, $id; |
|
673
|
28
|
|
|
|
|
33
|
push @columns, $column; |
|
674
|
28
|
|
|
|
|
69
|
push @widths, $self->widths->[$id]; |
|
675
|
|
|
|
|
|
|
} else { |
|
676
|
12
|
|
|
|
|
33
|
$self->_log->logwarn("invalid column [$column]"); |
|
677
|
|
|
|
|
|
|
} |
|
678
|
|
|
|
|
|
|
} |
|
679
|
|
|
|
|
|
|
|
|
680
|
14
|
|
|
|
|
905
|
$self->_log->debug(sprintf '@id [%s]', Dumper(\@id)); |
|
681
|
|
|
|
|
|
|
|
|
682
|
14
|
100
|
|
|
|
857
|
my $f_no_columns = ($self->rowid) ? 1 : 0; |
|
683
|
|
|
|
|
|
|
|
|
684
|
14
|
100
|
|
|
|
47
|
unless (scalar(@columns) == $f_no_columns) { # no columns, thus no rows |
|
685
|
10
|
|
|
|
|
24
|
for my $row (@pre) { |
|
686
|
100
|
|
|
|
|
422
|
$self->_log->debug(sprintf 'row [%s]', Dumper($row)); |
|
687
|
|
|
|
|
|
|
|
|
688
|
100
|
|
|
|
|
6455
|
my @wanted = (); |
|
689
|
|
|
|
|
|
|
|
|
690
|
100
|
|
|
|
|
158
|
for my $id (@id) { |
|
691
|
260
|
|
|
|
|
365
|
push @wanted, $row->[$id]; |
|
692
|
|
|
|
|
|
|
} |
|
693
|
|
|
|
|
|
|
|
|
694
|
100
|
|
|
|
|
379
|
$self->_log->debug(sprintf '@wanted [%s]', Dumper(\@wanted)); |
|
695
|
|
|
|
|
|
|
|
|
696
|
100
|
50
|
|
|
|
5001
|
push @post, [ @wanted ] |
|
697
|
|
|
|
|
|
|
if (scalar(@wanted)); # account for null case |
|
698
|
|
|
|
|
|
|
} |
|
699
|
|
|
|
|
|
|
} |
|
700
|
|
|
|
|
|
|
|
|
701
|
14
|
|
|
|
|
59
|
$self->_log->debug(sprintf '@columns [%s]', Dumper(\@columns)); |
|
702
|
14
|
|
|
|
|
664
|
$self->_log->debug(sprintf '@widths [%s]', Dumper(\@widths)); |
|
703
|
|
|
|
|
|
|
|
|
704
|
14
|
|
|
|
|
703
|
$self->titles([ @columns ]); |
|
705
|
14
|
|
|
|
|
65
|
$self->widths([ @widths ]); |
|
706
|
|
|
|
|
|
|
|
|
707
|
14
|
|
|
|
|
217
|
return @post; |
|
708
|
|
|
|
|
|
|
} |
|
709
|
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
DESTROY { |
|
712
|
24
|
|
|
24
|
|
68830
|
my $self = shift; |
|
713
|
24
|
|
|
|
|
31
|
-- ${ $self->{_n_objects} }; |
|
|
24
|
|
|
|
|
3078
|
|
|
714
|
|
|
|
|
|
|
}; |
|
715
|
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
#END { } |
|
717
|
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
1; |
|
719
|
|
|
|
|
|
|
|
|
720
|
|
|
|
|
|
|
__END__ |