line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Spreadsheet::XLSX::Reader::LibXML::XMLReader::WorksheetToRow; |
2
|
|
|
|
|
|
|
our $AUTHORITY = 'cpan:JANDREW'; |
3
|
3
|
|
|
3
|
|
3471
|
use version; our $VERSION = version->declare('v0.38.20'); |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
52
|
|
4
|
|
|
|
|
|
|
###LogSD warn "You uncovered internal logging statements for Spreadsheet::XLSX::Reader::LibXML::XMLReader::WorksheetToRow-$VERSION"; |
5
|
|
|
|
|
|
|
|
6
|
3
|
|
|
3
|
|
421
|
use 5.010; |
|
3
|
|
|
|
|
11
|
|
7
|
3
|
|
|
3
|
|
15
|
use Moose; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
23
|
|
8
|
3
|
|
|
3
|
|
20394
|
use MooseX::StrictConstructor; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
29
|
|
9
|
3
|
|
|
3
|
|
9710
|
use MooseX::HasDefaults::RO; |
|
3
|
|
|
|
|
9
|
|
|
3
|
|
|
|
|
27
|
|
10
|
3
|
|
|
3
|
|
15624
|
use Clone 'clone'; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
178
|
|
11
|
3
|
|
|
3
|
|
15
|
use Carp qw( confess ); |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
170
|
|
12
|
3
|
|
|
|
|
32
|
use Types::Standard qw( |
13
|
|
|
|
|
|
|
HasMethods InstanceOf ArrayRef Maybe |
14
|
|
|
|
|
|
|
Bool Int is_HashRef is_Int |
15
|
|
|
|
|
|
|
is_ArrayRef |
16
|
3
|
|
|
3
|
|
28
|
); |
|
3
|
|
|
|
|
5
|
|
17
|
3
|
|
|
3
|
|
4950
|
use MooseX::ShortCut::BuildInstance qw ( build_instance should_re_use_classes ); |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
30
|
|
18
|
|
|
|
|
|
|
should_re_use_classes( 1 ); |
19
|
3
|
|
|
3
|
|
1782
|
use lib '../../../../../../lib'; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
25
|
|
20
|
|
|
|
|
|
|
###LogSD use Log::Shiras::Telephone; |
21
|
|
|
|
|
|
|
###LogSD use Log::Shiras::UnhideDebug; |
22
|
|
|
|
|
|
|
extends 'Spreadsheet::XLSX::Reader::LibXML::XMLReader'; |
23
|
3
|
|
|
3
|
|
2542
|
use Spreadsheet::XLSX::Reader::LibXML::Row; |
|
3
|
|
|
|
|
11
|
|
|
3
|
|
|
|
|
123
|
|
24
|
3
|
|
|
3
|
|
26
|
use Data::Dumper; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
12030
|
|
25
|
|
|
|
|
|
|
#########1 Dispatch Tables & Package Variables 5#########6#########7#########8#########9 |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
#########1 Public Attributes 3#########4#########5#########6#########7#########8#########9 |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
has is_hidden =>( |
32
|
|
|
|
|
|
|
isa => Bool, |
33
|
|
|
|
|
|
|
reader => 'is_sheet_hidden', |
34
|
|
|
|
|
|
|
); |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
has workbook_instance =>( |
37
|
|
|
|
|
|
|
isa => HasMethods[qw( |
38
|
|
|
|
|
|
|
counting_from_zero boundary_flag_setting |
39
|
|
|
|
|
|
|
change_boundary_flag _has_shared_strings_file |
40
|
|
|
|
|
|
|
get_shared_string_position _has_styles_file |
41
|
|
|
|
|
|
|
get_format_position set_empty_is_end |
42
|
|
|
|
|
|
|
is_empty_the_end _starts_at_the_edge |
43
|
|
|
|
|
|
|
get_group_return_type set_group_return_type |
44
|
|
|
|
|
|
|
get_epoch_year change_output_encoding |
45
|
|
|
|
|
|
|
get_date_behavior set_date_behavior |
46
|
|
|
|
|
|
|
get_empty_return_type set_error |
47
|
|
|
|
|
|
|
get_values_only set_values_only |
48
|
|
|
|
|
|
|
parse_excel_format_string |
49
|
|
|
|
|
|
|
)], |
50
|
|
|
|
|
|
|
handles => [qw( |
51
|
|
|
|
|
|
|
counting_from_zero boundary_flag_setting |
52
|
|
|
|
|
|
|
change_boundary_flag _has_shared_strings_file |
53
|
|
|
|
|
|
|
get_shared_string_position _has_styles_file |
54
|
|
|
|
|
|
|
get_format_position set_empty_is_end |
55
|
|
|
|
|
|
|
is_empty_the_end _starts_at_the_edge |
56
|
|
|
|
|
|
|
get_group_return_type set_group_return_type |
57
|
|
|
|
|
|
|
get_epoch_year change_output_encoding |
58
|
|
|
|
|
|
|
get_date_behavior set_date_behavior |
59
|
|
|
|
|
|
|
get_empty_return_type set_error |
60
|
|
|
|
|
|
|
get_values_only set_values_only |
61
|
|
|
|
|
|
|
parse_excel_format_string |
62
|
|
|
|
|
|
|
)], |
63
|
|
|
|
|
|
|
required => 1, |
64
|
|
|
|
|
|
|
); |
65
|
|
|
|
|
|
|
###LogSD use Log::Shiras::UnhideDebug; |
66
|
|
|
|
|
|
|
with 'Spreadsheet::XLSX::Reader::LibXML::CellToColumnRow', |
67
|
|
|
|
|
|
|
'Spreadsheet::XLSX::Reader::LibXML::XMLToPerlData', |
68
|
|
|
|
|
|
|
; |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
#########1 Public Methods 3#########4#########5#########6#########7#########8#########9 |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
#########1 Private Attributes 3#########4#########5#########6#########7#########8#########9 |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
has _sheet_min_col =>( |
77
|
|
|
|
|
|
|
isa => Int, |
78
|
|
|
|
|
|
|
writer => '_set_min_col', |
79
|
|
|
|
|
|
|
reader => '_min_col', |
80
|
|
|
|
|
|
|
predicate => 'has_min_col', |
81
|
|
|
|
|
|
|
); |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
has _sheet_min_row =>( |
84
|
|
|
|
|
|
|
isa => Int, |
85
|
|
|
|
|
|
|
writer => '_set_min_row', |
86
|
|
|
|
|
|
|
reader => '_min_row', |
87
|
|
|
|
|
|
|
predicate => 'has_min_row', |
88
|
|
|
|
|
|
|
); |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
has _sheet_max_col =>( |
91
|
|
|
|
|
|
|
isa => Int, |
92
|
|
|
|
|
|
|
writer => '_set_max_col', |
93
|
|
|
|
|
|
|
reader => '_max_col', |
94
|
|
|
|
|
|
|
predicate => 'has_max_col', |
95
|
|
|
|
|
|
|
); |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
has _sheet_max_row =>( |
98
|
|
|
|
|
|
|
isa => Int, |
99
|
|
|
|
|
|
|
writer => '_set_max_row', |
100
|
|
|
|
|
|
|
reader => '_max_row', |
101
|
|
|
|
|
|
|
predicate => 'has_max_row', |
102
|
|
|
|
|
|
|
); |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
has _merge_map =>( |
105
|
|
|
|
|
|
|
isa => ArrayRef, |
106
|
|
|
|
|
|
|
traits => ['Array'], |
107
|
|
|
|
|
|
|
writer => '_set_merge_map', |
108
|
|
|
|
|
|
|
reader => '_get_merge_map', |
109
|
|
|
|
|
|
|
handles =>{ |
110
|
|
|
|
|
|
|
_get_row_merge_map => 'get', |
111
|
|
|
|
|
|
|
}, |
112
|
|
|
|
|
|
|
); |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
has _column_formats =>( |
115
|
|
|
|
|
|
|
isa => ArrayRef, |
116
|
|
|
|
|
|
|
traits => ['Array'], |
117
|
|
|
|
|
|
|
writer => '_set_column_formats', |
118
|
|
|
|
|
|
|
reader => '_get_column_formats', |
119
|
|
|
|
|
|
|
default => sub{ [] }, |
120
|
|
|
|
|
|
|
handles =>{ |
121
|
|
|
|
|
|
|
_get_custom_column_data => 'get', |
122
|
|
|
|
|
|
|
}, |
123
|
|
|
|
|
|
|
); |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
has _new_row_inst =>( |
126
|
|
|
|
|
|
|
isa => InstanceOf[ 'Spreadsheet::XLSX::Reader::LibXML::Row' ], |
127
|
|
|
|
|
|
|
reader => '_get_new_row_inst', |
128
|
|
|
|
|
|
|
writer => '_set_new_row_inst', |
129
|
|
|
|
|
|
|
clearer => '_clear_new_row_inst', |
130
|
|
|
|
|
|
|
predicate => '_has_new_row_inst', |
131
|
|
|
|
|
|
|
handles =>{ |
132
|
|
|
|
|
|
|
_get_new_row_number => 'get_row_number', |
133
|
|
|
|
|
|
|
_is_new_row_hidden => 'is_row_hidden', |
134
|
|
|
|
|
|
|
_get_new_row_formats => 'get_row_format', # pass the desired format key |
135
|
|
|
|
|
|
|
_get_new_column => 'get_the_column', # pass a column number (no next default) returns (cell|undef|EOR) |
136
|
|
|
|
|
|
|
_get_new_next_value => 'get_the_next_value_position', # pass nothing returns next (cell|EOR) |
137
|
|
|
|
|
|
|
_get_new_last_value_col => 'get_last_value_column', |
138
|
|
|
|
|
|
|
_get_new_row_list => 'get_row_all', |
139
|
|
|
|
|
|
|
_get_new_row_end => 'get_row_end' |
140
|
|
|
|
|
|
|
}, |
141
|
|
|
|
|
|
|
); |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
has _row_position_lookup =>( |
144
|
|
|
|
|
|
|
isa => ArrayRef[ Maybe[Int] ], |
145
|
|
|
|
|
|
|
traits =>['Array'], |
146
|
|
|
|
|
|
|
default => sub{ [] }, |
147
|
|
|
|
|
|
|
reader => '_get_all_positions', |
148
|
|
|
|
|
|
|
handles =>{ |
149
|
|
|
|
|
|
|
_set_row_position => 'set', |
150
|
|
|
|
|
|
|
_get_row_position => 'get', |
151
|
|
|
|
|
|
|
_max_row_position_recorded => 'count', |
152
|
|
|
|
|
|
|
_remove_last_row_position => 'pop', |
153
|
|
|
|
|
|
|
}, |
154
|
|
|
|
|
|
|
); |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
has _row_hidden_states =>( |
157
|
|
|
|
|
|
|
isa => ArrayRef[ Bool ], |
158
|
|
|
|
|
|
|
traits =>['Array'], |
159
|
|
|
|
|
|
|
default => sub{ [] }, |
160
|
|
|
|
|
|
|
reader => '_get_all_hidden', |
161
|
|
|
|
|
|
|
handles =>{ |
162
|
|
|
|
|
|
|
_set_row_hidden => 'set', |
163
|
|
|
|
|
|
|
_get_row_hidden => 'get', |
164
|
|
|
|
|
|
|
}, |
165
|
|
|
|
|
|
|
); |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
#########1 Private Methods 3#########4#########5#########6#########7#########8#########9 |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
sub _get_col_row{ |
170
|
0
|
|
|
0
|
|
|
my( $self, $target_col, $target_row ) = @_; |
171
|
|
|
|
|
|
|
###LogSD my $phone = Log::Shiras::Telephone->new( name_space => |
172
|
|
|
|
|
|
|
###LogSD $self->get_all_space . '::WorksheetToRow::_get_col_row', ); |
173
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
174
|
|
|
|
|
|
|
###LogSD "Reached _get_col_row", |
175
|
|
|
|
|
|
|
###LogSD ( $target_row ? "Requesting target row and column: [ $target_row, $target_col ]" : '' ), |
176
|
|
|
|
|
|
|
###LogSD ( $self->_has_new_row_inst ? ("..and stored current row: " . $self->_get_new_row_number) : '') ] ); |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
# Get the raw elements (as available) |
179
|
0
|
|
|
|
|
|
my $cell_ref = $self->_get_specific_position( $target_row, $target_col ); |
180
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
181
|
|
|
|
|
|
|
###LogSD "The cell ref after pulling column -$target_col-", $cell_ref, ] ); |
182
|
0
|
0
|
|
|
|
|
if( $cell_ref ){ |
183
|
0
|
0
|
0
|
|
|
|
if( !$cell_ref or $cell_ref eq 'EOR' ){ |
184
|
|
|
|
|
|
|
###LogSD no warnings 'uninitialized'; |
185
|
|
|
|
|
|
|
###LogSD my $max_positions = $self->_max_row_position_recorded - 1; |
186
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
187
|
|
|
|
|
|
|
###LogSD "Cell ref is EOR or undef - checking that is is also not EOF with the last 10 known row positions: " . |
188
|
|
|
|
|
|
|
###LogSD join( ', ', @{$self->_get_all_positions}[( $max_positions > 10 ? $max_positions - 10 : 0 ) .. $max_positions] ) ] ); |
189
|
|
|
|
|
|
|
###LogSD no warnings 'uninitialized'; |
190
|
|
|
|
|
|
|
# Check if EOR equals EOF |
191
|
0
|
|
|
|
|
|
my $valid_test = 0; |
192
|
0
|
0
|
0
|
|
|
|
if( $self->has_max_row and $self->_max_row == $target_row ){ |
|
|
0
|
|
|
|
|
|
193
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
194
|
|
|
|
|
|
|
###LogSD "This is the last row - and therefore EOF" ] ); |
195
|
0
|
|
|
|
|
|
$cell_ref = 'EOF'; |
196
|
0
|
|
|
|
|
|
$valid_test = 1; |
197
|
|
|
|
|
|
|
}elsif( $self->_max_row_position_recorded - 1 >= $target_row + 1 ){ |
198
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
199
|
|
|
|
|
|
|
###LogSD "At least one more row has been previewed - checking to see if it has values" ] ); |
200
|
0
|
|
|
|
|
|
my $row_positions = $self->_get_all_positions; |
201
|
0
|
|
|
|
|
|
my $test_position = $target_row + 1; |
202
|
0
|
|
|
|
|
|
for my $position ( @$row_positions[ $test_position .. $#$row_positions ] ){ |
203
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
204
|
|
|
|
|
|
|
###LogSD "Checking if the position -$test_position- has a row defined: " . ($position//'undef') ] ); |
205
|
0
|
0
|
|
|
|
|
if( defined $position ){ |
206
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
207
|
|
|
|
|
|
|
###LogSD "Positing -$test_position- is defined - this is not an EOF" ] ); |
208
|
0
|
|
|
|
|
|
$valid_test = 1; |
209
|
0
|
|
|
|
|
|
last; |
210
|
|
|
|
|
|
|
} |
211
|
0
|
|
|
|
|
|
$test_position++; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
} |
214
|
0
|
0
|
|
|
|
|
if( !$valid_test ){ |
215
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
216
|
|
|
|
|
|
|
###LogSD "Unable to know the EOF state from stored data - processing additional rows" ] ); |
217
|
0
|
|
|
|
|
|
my $index_result = $self->_go_to_or_past_row( $target_row + 1 ); |
218
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
219
|
|
|
|
|
|
|
###LogSD "Returned from advancing rows with: $index_result" ] ); |
220
|
0
|
0
|
|
|
|
|
if( $index_result ){ |
221
|
0
|
0
|
|
|
|
|
if( $self->is_empty_the_end ){ |
222
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
223
|
|
|
|
|
|
|
###LogSD "Empty is the end - Just check for EOF" ] ); |
224
|
0
|
0
|
|
|
|
|
if( $index_result eq 'EOF' ){ |
225
|
0
|
|
|
|
|
|
$cell_ref = 'EOF'; |
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
}else{ |
228
|
0
|
0
|
|
|
|
|
if( $self->_max_col >= $target_col ){ |
229
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
230
|
|
|
|
|
|
|
###LogSD "There may be nothing else of value but we are not at the end of the emptys" ] ); |
231
|
0
|
|
|
|
|
|
$cell_ref = undef; |
232
|
|
|
|
|
|
|
}else{ |
233
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
234
|
|
|
|
|
|
|
###LogSD "This really is the end of the row - check for EOF" ] ); |
235
|
0
|
0
|
|
|
|
|
if( $index_result eq 'EOF' ){ |
236
|
0
|
|
|
|
|
|
$cell_ref = 'EOF'; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
} |
243
|
0
|
0
|
0
|
|
|
|
if( $cell_ref and $cell_ref eq 'EOF' ){ |
244
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
245
|
|
|
|
|
|
|
###LogSD "The cell ref is EOF!" ] ); |
246
|
0
|
|
|
|
|
|
$self->_clear_new_row_inst; |
247
|
0
|
|
|
|
|
|
$self->start_the_file_over; |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
} |
250
|
0
|
0
|
|
|
|
|
my $updated_cell = |
|
|
0
|
|
|
|
|
|
251
|
|
|
|
|
|
|
!$cell_ref ? undef : |
252
|
|
|
|
|
|
|
is_HashRef( $cell_ref ) ? $self->_complete_cell( $cell_ref ) : $cell_ref; |
253
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
254
|
|
|
|
|
|
|
###LogSD 'returning ref:', $updated_cell,] ); |
255
|
0
|
|
|
|
|
|
return $updated_cell; |
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
sub _get_next_value_cell{ |
259
|
0
|
|
|
0
|
|
|
my( $self, ) = @_; # to fast forward use _get_col_row |
260
|
|
|
|
|
|
|
###LogSD my $phone = Log::Shiras::Telephone->new( name_space => |
261
|
|
|
|
|
|
|
###LogSD $self->get_all_space . '::WorksheetToRow::_get_next_value_cell', ); |
262
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
263
|
|
|
|
|
|
|
###LogSD "Reached _get_next_value_cell", |
264
|
|
|
|
|
|
|
###LogSD ( $self->_has_new_row_inst ? ("With current stored new row: " . $self->_get_new_row_number) : '') ] ); |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
# Attempt to pull the data from stored values or index the row forward |
267
|
0
|
|
|
|
|
|
my $index_result = 'NoParse'; |
268
|
0
|
|
|
|
|
|
my $cell_ref; |
269
|
0
|
|
|
|
|
|
my $first_pass = 1; |
270
|
0
|
|
|
|
|
|
while( !$cell_ref ){ |
271
|
0
|
0
|
|
|
|
|
if( !$self->_has_new_row_inst ){ |
272
|
0
|
0
|
|
|
|
|
if( $first_pass ){ |
273
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
274
|
|
|
|
|
|
|
###LogSD "Probably the first time through at the beginning of the sheet" ] ); |
275
|
0
|
|
|
|
|
|
$self->start_the_file_over; |
276
|
0
|
|
|
|
|
|
my $first_data_row = 1; |
277
|
0
|
0
|
|
|
|
|
if( $self->_max_row_position_recorded > 1 ){ |
278
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
279
|
|
|
|
|
|
|
###LogSD "The sheet has been processed before - find the first data row" ] ); |
280
|
0
|
|
|
|
|
|
my $found_it = 0; |
281
|
0
|
|
|
|
|
|
while( !$found_it ){ |
282
|
0
|
0
|
|
|
|
|
if( defined $self->_get_row_position( $first_data_row ) ){ |
283
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
284
|
|
|
|
|
|
|
###LogSD "Row number -$first_data_row- has data" ] ); |
285
|
0
|
|
|
|
|
|
$found_it = 1; |
286
|
|
|
|
|
|
|
}else{ |
287
|
0
|
|
|
|
|
|
$first_data_row++; |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
} |
291
|
0
|
|
|
|
|
|
$index_result = $self->_go_to_or_past_row( $first_data_row ); |
292
|
|
|
|
|
|
|
}else{ |
293
|
|
|
|
|
|
|
###LogSD my $max_positions = $self->_max_row_position_recorded - 1; |
294
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
295
|
|
|
|
|
|
|
###LogSD "Likely some bad row bound / EOF / empty last row condition found with last 10 positions: " . join( ', ', @{$self->_get_all_positions}[( $max_positions > 10 ? $max_positions - 10 : 0 ) .. $max_positions] ) ] ); |
296
|
0
|
|
|
|
|
|
$self->start_the_file_over; |
297
|
0
|
|
|
|
|
|
return 'EOF'; |
298
|
|
|
|
|
|
|
} |
299
|
|
|
|
|
|
|
}else{ |
300
|
0
|
|
|
|
|
|
$cell_ref = $self->_get_new_next_value; |
301
|
0
|
|
|
|
|
|
my $current_row = $self->_get_new_row_number; |
302
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
303
|
|
|
|
|
|
|
###LogSD "For row -$current_row- the next cell is:", $cell_ref ] ); |
304
|
0
|
0
|
|
|
|
|
if( $cell_ref eq 'EOR' ){ |
305
|
0
|
|
|
|
|
|
$current_row++; |
306
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
307
|
|
|
|
|
|
|
###LogSD "Reached the end of the row - starting over at row: $current_row" ] ); |
308
|
0
|
0
|
0
|
|
|
|
if( !$self->has_max_row or $current_row <= $self->_max_row ){ |
309
|
0
|
|
|
|
|
|
$index_result = $self->_go_to_or_past_row( $current_row ); |
310
|
0
|
|
|
|
|
|
$cell_ref = undef; |
311
|
|
|
|
|
|
|
}else{ |
312
|
0
|
|
|
|
|
|
$self->_clear_new_row_inst; |
313
|
0
|
|
|
|
|
|
$self->start_the_file_over; |
314
|
0
|
|
|
|
|
|
return 'EOF'; |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
} |
318
|
0
|
|
|
|
|
|
$first_pass = 0; |
319
|
0
|
0
|
0
|
|
|
|
if( !$cell_ref and $index_result eq 'EOF' ){ |
320
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
321
|
|
|
|
|
|
|
###LogSD "Returning: $index_result" ] ); |
322
|
0
|
|
|
|
|
|
return $index_result; |
323
|
|
|
|
|
|
|
} |
324
|
|
|
|
|
|
|
} |
325
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
326
|
|
|
|
|
|
|
###LogSD 'The cell ref after parsing through the rows:', $cell_ref, ] ); |
327
|
|
|
|
|
|
|
|
328
|
0
|
|
|
|
|
|
my $updated_cell = $self->_complete_cell( $cell_ref ); |
329
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
330
|
|
|
|
|
|
|
###LogSD 'returning ref:', $updated_cell,] ); |
331
|
0
|
|
|
|
|
|
return $updated_cell; |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
sub _get_row_all{ |
335
|
0
|
|
|
0
|
|
|
my( $self, $target_row ) = @_; |
336
|
|
|
|
|
|
|
###LogSD my $phone = Log::Shiras::Telephone->new( name_space => |
337
|
|
|
|
|
|
|
###LogSD $self->get_all_space . '::WorksheetToRow::_get_row_all', ); |
338
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
339
|
|
|
|
|
|
|
###LogSD "Reached _get_row_all", |
340
|
|
|
|
|
|
|
###LogSD ( $target_row ? "Requesting target row: $target_row" : '' ), |
341
|
|
|
|
|
|
|
###LogSD ( $self->_has_new_row_inst ? ("..and stored current row: " . $self->_get_new_row_number) : '') ] ); |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
# Get the raw elements (as available) |
344
|
0
|
|
|
|
|
|
my $row_ref = $self->_get_specific_position( $target_row, ); |
345
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
346
|
|
|
|
|
|
|
###LogSD "The row ref is:", $row_ref, ] ); |
347
|
0
|
|
|
|
|
|
my $updated_row = []; |
348
|
0
|
0
|
|
|
|
|
if( is_ArrayRef( $row_ref ) ){ |
349
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
350
|
|
|
|
|
|
|
###LogSD "There are cells to process:", $row_ref ] ); |
351
|
0
|
|
|
|
|
|
for my $cell_ref ( @$row_ref ){ |
352
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
353
|
|
|
|
|
|
|
###LogSD "Processing cell:", $cell_ref ] ); |
354
|
0
|
0
|
|
|
|
|
push @$updated_row, $cell_ref ? $self->_complete_cell( $cell_ref ) : $cell_ref ; |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
}else{ |
357
|
0
|
|
|
|
|
|
$updated_row = $row_ref; |
358
|
|
|
|
|
|
|
} |
359
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
360
|
|
|
|
|
|
|
###LogSD 'returning row ref:', $updated_row,] ); |
361
|
0
|
|
|
|
|
|
return $updated_row; |
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
sub _complete_cell{ |
365
|
0
|
|
|
0
|
|
|
my( $self, $cell_ref ) = @_;#, $new_file, $old_file |
366
|
|
|
|
|
|
|
###LogSD my $phone = Log::Shiras::Telephone->new( name_space => |
367
|
|
|
|
|
|
|
###LogSD $self->get_all_space . '::WorksheetToRow::_complete_cell', ); |
368
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
369
|
|
|
|
|
|
|
###LogSD "adding worksheet data to the cell:", $cell_ref ] ); |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
#Add merge value |
372
|
0
|
|
|
|
|
|
my $merge_row = $self->_get_row_merge_map( $cell_ref->{cell_row} ); |
373
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
374
|
|
|
|
|
|
|
###LogSD "Row merge map:", $merge_row, ] ); |
375
|
0
|
0
|
0
|
|
|
|
if( ref( $merge_row ) and $merge_row->[$cell_ref->{cell_col}] ){ |
376
|
0
|
|
|
|
|
|
$cell_ref->{cell_merge} = $merge_row->[$cell_ref->{cell_col}]; |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
# Check for hiddenness (This logic needs a deep rewrite when adding the skip_hidden attribute to the workbook) |
380
|
0
|
0
|
|
|
|
|
if( $self->is_sheet_hidden ){ |
381
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
382
|
|
|
|
|
|
|
###LogSD 'This cell is from a hidden sheet',] ); |
383
|
0
|
|
|
|
|
|
$cell_ref->{cell_hidden} = 'sheet'; |
384
|
|
|
|
|
|
|
}else{ |
385
|
0
|
|
|
|
|
|
my $column_attributes = $self->_get_custom_column_data( $cell_ref->{cell_col} ); |
386
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
387
|
|
|
|
|
|
|
###LogSD "Column -$cell_ref->{cell_col}- has attributes:", $column_attributes, ] ); |
388
|
0
|
0
|
0
|
|
|
|
if( $column_attributes and $column_attributes->{hidden} ){ |
389
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
390
|
|
|
|
|
|
|
###LogSD 'This cell is from a hidden column',] ); |
391
|
0
|
|
|
|
|
|
$cell_ref->{cell_hidden} = 'column'; |
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
} |
394
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
395
|
|
|
|
|
|
|
###LogSD 'Ref to this point:', $cell_ref,] ); |
396
|
0
|
|
|
|
|
|
return $cell_ref; |
397
|
|
|
|
|
|
|
} |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
sub _get_specific_position{ |
400
|
0
|
|
|
0
|
|
|
my( $self, $target_row, $target_col ) = @_; |
401
|
0
|
0
|
|
|
|
|
my $current_row = $self->_has_new_row_inst ? $self->_get_new_row_number : 0; |
402
|
|
|
|
|
|
|
###LogSD my $phone = Log::Shiras::Telephone->new( name_space => |
403
|
|
|
|
|
|
|
###LogSD $self->get_all_space . '::WorksheetToRow::_get_specific_position', ); |
404
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'info', message => [ |
405
|
|
|
|
|
|
|
###LogSD "Seeking elements of row: $target_row", |
406
|
|
|
|
|
|
|
###LogSD ( defined $target_col ? "..with the intent to extract column: $target_col" : undef) ] ); |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
# Look for the row and then the cell |
409
|
0
|
|
|
|
|
|
my ( $row_found, $advance_result ); |
410
|
0
|
|
|
|
|
|
while( !$row_found ){ |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
# Check for the 'EOF' conditions |
413
|
0
|
0
|
0
|
|
|
|
if( $advance_result and $advance_result eq 'EOF'){ |
|
|
0
|
|
|
|
|
|
414
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
415
|
|
|
|
|
|
|
###LogSD "Returning EOF after arriving at the end of the file" ] ); |
416
|
0
|
|
|
|
|
|
return 'EOF'; |
417
|
|
|
|
|
|
|
}elsif( $self->has_max_row ){ |
418
|
0
|
0
|
0
|
|
|
|
if( $target_row > $self->_max_row ){ |
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
419
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
420
|
|
|
|
|
|
|
###LogSD "Returning EOF because max row less than target row" ] ); |
421
|
0
|
|
|
|
|
|
return 'EOF'; |
422
|
|
|
|
|
|
|
}elsif( defined $target_col and $self->has_max_col and $target_row == $self->_max_row and $target_col > $self->_max_col ){ |
423
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
424
|
|
|
|
|
|
|
###LogSD "Returning EOF because max row equal to target row and max col less than requested column" ] ); |
425
|
0
|
|
|
|
|
|
return 'EOF'; |
426
|
|
|
|
|
|
|
} |
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
# See if the currently stored row is the desired row (or if we know the row is empty) |
430
|
0
|
0
|
|
|
|
|
if( $self->_has_new_row_inst ){ |
431
|
0
|
0
|
|
|
|
|
my $stored_row = $self->_has_new_row_inst ? $self->_get_new_row_number : undef; |
432
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
433
|
|
|
|
|
|
|
###LogSD "Checking if the requested row -$target_row- matches the stored row: " . ($stored_row//'undef'), ] ); |
434
|
0
|
0
|
0
|
|
|
|
if( defined $stored_row and $stored_row == $target_row ){ |
435
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
436
|
|
|
|
|
|
|
###LogSD 'The value might be in the latest row pulled' ] ); |
437
|
0
|
|
|
|
|
|
$row_found = 1;# Currently stored row is the one we want |
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
441
|
|
|
|
|
|
|
###LogSD "The current row found state: " . ($row_found//'undef'), |
442
|
|
|
|
|
|
|
###LogSD "The current max positions recorded: " . $self->_max_row_position_recorded, |
443
|
|
|
|
|
|
|
###LogSD "..against target_row: $target_row" ] ); |
444
|
0
|
0
|
0
|
|
|
|
if( !$row_found and $self->_max_row_position_recorded - 1 >= $target_row ){ |
445
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
446
|
|
|
|
|
|
|
###LogSD "The desired row has already been read - check if it is empty: " ] ); |
447
|
0
|
|
|
|
|
|
my $row_position = $self->_get_row_position( $target_row ); |
448
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
449
|
|
|
|
|
|
|
###LogSD "The desired row is at position: " . ($row_position//'undef') ] ); |
450
|
0
|
0
|
|
|
|
|
if( !defined $row_position ){ |
451
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
452
|
|
|
|
|
|
|
###LogSD "I already know this is an empty row" ] ); |
453
|
0
|
|
|
|
|
|
$row_found = 2;# Empty Row |
454
|
|
|
|
|
|
|
}else{ |
455
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
456
|
|
|
|
|
|
|
###LogSD "Need to index to and then read row -$target_row- at position: $row_position" ] ); |
457
|
|
|
|
|
|
|
} |
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
# Look deeper as needed |
461
|
0
|
0
|
|
|
|
|
if( !$row_found ){ |
462
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
463
|
|
|
|
|
|
|
###LogSD "Need index the currently read row forward to read the target row: $target_row" ] ); |
464
|
0
|
|
|
|
|
|
$advance_result = $self->_go_to_or_past_row( $target_row ); |
465
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
466
|
|
|
|
|
|
|
###LogSD "Result of the index is: $advance_result" ] ); |
467
|
0
|
0
|
0
|
|
|
|
if( $advance_result and $advance_result eq 'EOF' ){ |
468
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
469
|
|
|
|
|
|
|
###LogSD "Setting the return ref to: EOF" ] ); |
470
|
0
|
|
|
|
|
|
$row_found = 3;# EOF condition |
471
|
|
|
|
|
|
|
} |
472
|
|
|
|
|
|
|
} |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
} |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
# Handle unknown $row_found |
477
|
0
|
0
|
0
|
|
|
|
if( $row_found > 3 or $row_found < 1 ){ |
478
|
0
|
|
|
|
|
|
confess "Unknown row_found value: $row_found"; |
479
|
|
|
|
|
|
|
} |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
# Return EOF as known |
482
|
0
|
0
|
|
|
|
|
if( $row_found == 3 ){ |
483
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
484
|
|
|
|
|
|
|
###LogSD "Returning EOF" ] ); |
485
|
0
|
|
|
|
|
|
return 'EOF'; |
486
|
|
|
|
|
|
|
} |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
# If the whole row is needed return that |
489
|
0
|
0
|
|
|
|
|
if( !defined $target_col ){ |
490
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
491
|
|
|
|
|
|
|
###LogSD "Prepping to return the row type: " . ( $row_found == 1 ? 'ArrayRef' : $row_found == 2 ? 'Empty ArrayRef' : 'EOF' ) ] ); |
492
|
0
|
0
|
|
|
|
|
my $row_list = $row_found == 1 ? $self->_get_new_row_list : []; |
493
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
494
|
|
|
|
|
|
|
###LogSD "Returning the row list:", $row_list ] ); |
495
|
0
|
|
|
|
|
|
return $row_list; |
496
|
|
|
|
|
|
|
} |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
# Return the correct cell value |
499
|
0
|
|
|
|
|
|
my $cell_ref; |
500
|
0
|
0
|
|
|
|
|
if( $row_found == 1 ){# Handle current row return |
501
|
0
|
0
|
|
|
|
|
if( $target_col > $self->_get_new_last_value_col ){ |
502
|
0
|
0
|
0
|
|
|
|
$cell_ref = ($self->is_empty_the_end or $self->_get_new_row_end < $target_col) ? 'EOR' : undef; |
503
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
504
|
|
|
|
|
|
|
###LogSD "The requested cell is past the end of the data in this row: " . ($cell_ref//'undef') ] ); |
505
|
|
|
|
|
|
|
}else{ |
506
|
0
|
|
|
|
|
|
$cell_ref = $self->_get_new_column( $target_col ); |
507
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
508
|
|
|
|
|
|
|
###LogSD "Pulling cell data from the stored row:", $cell_ref ] ); |
509
|
|
|
|
|
|
|
} |
510
|
|
|
|
|
|
|
}else{ |
511
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
512
|
|
|
|
|
|
|
###LogSD "Determining how to represent a value from an empty row:", $cell_ref, $self->has_max_col, $self->_max_col, $target_col] ); |
513
|
0
|
0
|
|
|
|
|
$cell_ref = $self->is_empty_the_end ? 'EOR' : ($self->_max_col < $target_col) ? 'EOR' : undef; |
|
|
0
|
|
|
|
|
|
514
|
|
|
|
|
|
|
} |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'info', message => [ |
517
|
|
|
|
|
|
|
###LogSD 'Returning:', $cell_ref ] ); |
518
|
0
|
|
|
|
|
|
return $cell_ref; |
519
|
|
|
|
|
|
|
} |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
sub _go_to_or_past_row{ |
522
|
0
|
|
|
0
|
|
|
my( $self, $target_row ) = @_; |
523
|
0
|
0
|
|
|
|
|
my $current_row = $self->_has_new_row_inst ? $self->_get_new_row_number : 0; |
524
|
|
|
|
|
|
|
###LogSD my $phone = Log::Shiras::Telephone->new( name_space => |
525
|
|
|
|
|
|
|
###LogSD $self->get_all_space . '::WorksheetToRow::_go_to_or_past_row', ); |
526
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'info', message => [ |
527
|
|
|
|
|
|
|
###LogSD "Indexing the row forward to find row: $target_row", "From current row: $current_row" ] ); |
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
# Handle a call where we are already at the required location |
530
|
0
|
0
|
0
|
|
|
|
if( $self->_has_new_row_inst and defined $target_row and $self->_get_new_row_number == $target_row ){ |
|
|
|
0
|
|
|
|
|
531
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'info', message => [ |
532
|
|
|
|
|
|
|
###LogSD 'Asked for a row that has already been built and loaded' ] ); |
533
|
0
|
|
|
|
|
|
return $target_row; |
534
|
|
|
|
|
|
|
} |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
# processes through the unwanted known positions quickly |
537
|
0
|
|
|
|
|
|
my $current_position; |
538
|
|
|
|
|
|
|
my $row_attributes; |
539
|
0
|
|
|
|
|
|
my $attribute_ref; |
540
|
0
|
0
|
|
|
|
|
if( $self->_max_row_position_recorded ){ |
541
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
542
|
|
|
|
|
|
|
###LogSD 'The sheet has recorded some rows' ] ); |
543
|
0
|
|
|
|
|
|
my ( $fast_forward, $test_position ); |
544
|
0
|
|
|
|
|
|
my $test_target = $target_row; |
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
# Look forward for fast forward goal |
547
|
|
|
|
|
|
|
###LogSD no warnings 'uninitialized'; |
548
|
0
|
|
0
|
|
|
|
while( !defined $test_position and $test_target < ($self->_max_row_position_recorded - 1) ){ |
549
|
0
|
|
|
|
|
|
$test_position = $self->_get_row_position( $test_target ); |
550
|
|
|
|
|
|
|
###LogSD my $max_positions = $self->_max_row_position_recorded - 1; |
551
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
552
|
|
|
|
|
|
|
###LogSD "Checking for a defined row position for row: $test_target", |
553
|
|
|
|
|
|
|
###LogSD ".. with position result: " . ($test_position//'undef'), |
554
|
|
|
|
|
|
|
###LogSD ".. with max known column -$max_positions- and the last 10 detailed positions: " . join( ', ', @{$self->_get_all_positions}[( $max_positions > 10 ? $max_positions - 10 : 0 ) .. $max_positions] ) ] ); |
555
|
0
|
|
|
|
|
|
$test_target++; |
556
|
|
|
|
|
|
|
} |
557
|
|
|
|
|
|
|
###LogSD my $max_positions = $self->_max_row_position_recorded - 1; |
558
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
559
|
|
|
|
|
|
|
###LogSD 'After looking at and forward of the target row the test position is: ' . $test_position, |
560
|
|
|
|
|
|
|
###LogSD "..and last 10 known columns: " . join( ', ', @{$self->_get_all_positions}[( $max_positions > 10 ? $max_positions - 10 : 0 ) .. $max_positions] ) ] ) if defined $test_position; |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
# Look backward for fast forward goal |
563
|
0
|
0
|
|
|
|
|
$test_target = $target_row < ($self->_max_row_position_recorded - 1) ? $target_row : -1; |
564
|
0
|
|
0
|
|
|
|
while( !defined $test_position and $test_target < ($self->_max_row_position_recorded - 1) ){ |
565
|
|
|
|
|
|
|
###LogSD my $max_positions = $self->_max_row_position_recorded - 1; |
566
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
567
|
|
|
|
|
|
|
###LogSD "Checking for a defined row position for row: $test_target", |
568
|
|
|
|
|
|
|
###LogSD ".. with position result: " . ($test_position//'undef'), |
569
|
|
|
|
|
|
|
###LogSD ".. against the last 10 positions: " . join( ', ', @{$self->_get_all_positions}[( $max_positions > 10 ? $max_positions - 10 : 0 ) .. $max_positions] ) ] ); |
570
|
0
|
|
|
|
|
|
$test_position = $self->_get_row_position( $test_target ); |
571
|
0
|
|
|
|
|
|
$test_target--; |
572
|
|
|
|
|
|
|
} |
573
|
|
|
|
|
|
|
###LogSD $max_positions = $self->_max_row_position_recorded - 1; |
574
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
575
|
|
|
|
|
|
|
###LogSD 'After looking backward from the the target row the test position is: ' . ($test_position//'undef'), |
576
|
|
|
|
|
|
|
###LogSD ".. against the last 10 positions: " . join( ', ', @{$self->_get_all_positions}[( $max_positions > 10 ? $max_positions - 10 : 0 ) .. $max_positions] ) ] ); |
577
|
|
|
|
|
|
|
###LogSD use warnings 'uninitialized'; |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
# Pull the current position |
580
|
0
|
0
|
|
|
|
|
$current_position = $current_row ? $self->_get_row_position( $current_row ) : 0; |
581
|
0
|
0
|
|
|
|
|
$fast_forward = $current_position ? $test_position - $current_position : $test_position; |
582
|
0
|
|
|
|
|
|
@$attribute_ref{qw( node_depth node_name node_type )} = $self->location_status; |
583
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
584
|
|
|
|
|
|
|
###LogSD "Checking if a speed index can be done between position: " . ($current_position//'undef'), |
585
|
|
|
|
|
|
|
###LogSD "..for last recorded row: " . ($current_row), |
586
|
|
|
|
|
|
|
###LogSD "..to target position: $test_position", |
587
|
|
|
|
|
|
|
###LogSD "..with proposed increment: $fast_forward", |
588
|
|
|
|
|
|
|
###LogSD "..node name: $attribute_ref->{node_name}", "..node type: $attribute_ref->{node_type}", |
589
|
|
|
|
|
|
|
###LogSD "..node depth: $attribute_ref->{node_depth}", ] ); |
590
|
0
|
0
|
0
|
|
|
|
if( $fast_forward < 0 or ($attribute_ref->{node_depth} == 0 and $attribute_ref->{node_name} eq 'EOF') ){ |
|
|
|
0
|
|
|
|
|
591
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
592
|
|
|
|
|
|
|
###LogSD "Looking for a row that is earlier than the current position" ] ); |
593
|
0
|
|
|
|
|
|
$self->start_the_file_over; |
594
|
0
|
|
|
|
|
|
$fast_forward = $test_position - 1; |
595
|
0
|
|
|
|
|
|
$current_row = 0; |
596
|
0
|
|
|
|
|
|
$self->advance_element_position( 'row', ) ; |
597
|
|
|
|
|
|
|
} |
598
|
|
|
|
|
|
|
|
599
|
0
|
0
|
|
|
|
|
if( $fast_forward > 1 ){# Since you quit at the beginning of the next node |
600
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
601
|
|
|
|
|
|
|
###LogSD "Fast forwarding -$fast_forward- times", ] ); |
602
|
0
|
|
|
|
|
|
$self->advance_element_position( 'row', $fast_forward - 1 ) ; |
603
|
0
|
|
|
|
|
|
@$attribute_ref{qw( node_depth node_name node_type )} = $self->location_status; |
604
|
0
|
|
|
|
|
|
$row_attributes = $self->get_attribute_hash_ref; |
605
|
0
|
|
|
|
|
|
$current_row = $row_attributes->{r}; |
606
|
0
|
|
|
|
|
|
$attribute_ref->{attribute_hash} = $row_attributes; |
607
|
0
|
|
|
|
|
|
$current_position = $test_position; |
608
|
|
|
|
|
|
|
} |
609
|
|
|
|
|
|
|
} |
610
|
0
|
|
|
|
|
|
$self->_clear_new_row_inst;# We are not in Kansas anymore |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
# move forward into the unknown (slower, in order to record steps) |
613
|
0
|
|
|
|
|
|
my $count = 0; |
614
|
0
|
|
0
|
|
|
|
while( defined $current_row and $target_row > $current_row ){ |
615
|
0
|
|
|
|
|
|
@$attribute_ref{qw( node_depth node_name node_type )} = $self->location_status; |
616
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'info', message => [ |
617
|
|
|
|
|
|
|
###LogSD "Reading the next row", |
618
|
|
|
|
|
|
|
###LogSD "..from XML file position:", $attribute_ref, "..at current position: " . ($current_position//'undef') ] ); |
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
# find a row node if you don't have one |
621
|
0
|
|
|
|
|
|
my $result = 1; |
622
|
0
|
0
|
|
|
|
|
if( $attribute_ref->{node_name} ne 'row' ){ |
623
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
624
|
|
|
|
|
|
|
###LogSD "Attempting to advanced to a row node from a non row node" ] ); |
625
|
0
|
|
|
|
|
|
$result = $self->advance_element_position( 'row' ); |
626
|
0
|
|
|
|
|
|
@$attribute_ref{qw( node_depth node_name node_type )} = $self->location_status; |
627
|
|
|
|
|
|
|
} |
628
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
629
|
|
|
|
|
|
|
###LogSD "Current location result: $result", $attribute_ref ] ); |
630
|
|
|
|
|
|
|
# Check for EOF node |
631
|
0
|
0
|
|
|
|
|
if( $attribute_ref->{node_name} eq 'EOF' ){ |
632
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
633
|
|
|
|
|
|
|
###LogSD "Returning EOF" ] ); |
634
|
0
|
|
|
|
|
|
$self->_set_max_row_state; |
635
|
0
|
|
|
|
|
|
return 'EOF'; |
636
|
|
|
|
|
|
|
} |
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
# Processe the node advance |
639
|
0
|
0
|
|
|
|
|
if( $result ){ |
640
|
|
|
|
|
|
|
# Get the location from the current row attributes |
641
|
0
|
|
|
|
|
|
$row_attributes = $self->get_attribute_hash_ref; |
642
|
0
|
|
|
|
|
|
$current_row = $row_attributes->{r}; |
643
|
0
|
0
|
|
|
|
|
if( !defined $row_attributes->{r} ){ |
644
|
0
|
|
|
|
|
|
confess "arrived at a row node with no row number: " . Dumper( $row_attributes ); |
645
|
|
|
|
|
|
|
} |
646
|
0
|
0
|
|
|
|
|
$current_position = defined $current_position ? $current_position + 1 : 0; |
647
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
648
|
|
|
|
|
|
|
###LogSD "Currently at row: $current_row", |
649
|
|
|
|
|
|
|
###LogSD "..and current position: $current_position", ] ); |
650
|
0
|
0
|
|
|
|
|
if( $current_row > ($self->_max_row_position_recorded - 1) ){ |
651
|
|
|
|
|
|
|
###LogSD no warnings 'uninitialized'; |
652
|
|
|
|
|
|
|
###LogSD my $max_positions = $self->_max_row_position_recorded - 1; |
653
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
654
|
|
|
|
|
|
|
###LogSD "The current last 10 positions from row -$current_row- of the hidden row ref: " . join( ', ', @{$self->_get_all_hidden}[( $max_positions > 10 ? $max_positions - 10 : 0 ) .. $max_positions] ) ] ); |
655
|
0
|
0
|
|
|
|
|
$self->_set_row_hidden( $current_row => (exists $row_attributes->{hidden} ? 1 : 0) ); |
656
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
657
|
|
|
|
|
|
|
###LogSD "The updated last 10 positions from row -$current_row- of the hidden row ref: " . join( ', ', @{$self->_get_all_hidden}[( $max_positions > 10 ? $max_positions - 10 : 0 ) .. $max_positions] ), |
658
|
|
|
|
|
|
|
###LogSD "..with the current last 10 positions of the updated position row ref: " . join( ', ', @{$self->_get_all_positions}[( $max_positions > 10 ? $max_positions - 10 : 0 ) .. $max_positions] ) ] ); |
659
|
0
|
|
|
|
|
|
$self->_set_row_position( $current_row => $current_position ); |
660
|
|
|
|
|
|
|
###LogSD $max_positions = $self->_max_row_position_recorded - 1; |
661
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
662
|
|
|
|
|
|
|
###LogSD "The position row ref max row is: $max_positions", |
663
|
|
|
|
|
|
|
###LogSD "..with the updated last 10 positions of the updated position row ref: " . join( ', ', @{$self->_get_all_positions}[( $max_positions > 10 ? $max_positions - 10 : 0 ) .. $max_positions] ) ] ); |
664
|
|
|
|
|
|
|
###LogSD use warnings 'uninitialized'; |
665
|
|
|
|
|
|
|
} |
666
|
0
|
|
|
|
|
|
$attribute_ref->{attribute_hash} = $row_attributes; |
667
|
|
|
|
|
|
|
}else{ |
668
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
669
|
|
|
|
|
|
|
###LogSD "Couldn't find another value row -> this is an unexpected end of file" ] ); |
670
|
0
|
|
|
|
|
|
$self->_set_max_row_state; |
671
|
0
|
|
|
|
|
|
return 'EOF'; |
672
|
|
|
|
|
|
|
} |
673
|
0
|
|
|
|
|
|
$count++; |
674
|
|
|
|
|
|
|
} |
675
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
# Collect the details of the final row position |
677
|
0
|
|
|
|
|
|
my $row_ref = $self->parse_element( undef, $attribute_ref ); |
678
|
|
|
|
|
|
|
$row_ref->{list} = |
679
|
|
|
|
|
|
|
exists $row_ref->{list} ? $row_ref->{list} : |
680
|
0
|
0
|
|
|
|
|
exists $row_ref->{c} ? [ $row_ref->{c} ] : []; |
|
|
0
|
|
|
|
|
|
681
|
0
|
0
|
|
|
|
|
delete $row_ref->{c} if exists $row_ref->{c};# Delete the single column c placeholder as needed |
682
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [#ask => 1, |
683
|
|
|
|
|
|
|
###LogSD 'Result of row read:', $row_ref ] ); |
684
|
|
|
|
|
|
|
|
685
|
|
|
|
|
|
|
# Load text values for each cell where appropriate |
686
|
0
|
|
|
|
|
|
my ( $alt_ref, $column_to_cell_translations, $reported_column, $reported_position, $last_value_column ); |
687
|
0
|
|
|
|
|
|
my $x = 0; |
688
|
0
|
|
|
|
|
|
for my $cell ( @{$row_ref->{list}} ){ |
|
0
|
|
|
|
|
|
|
689
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'info', message => [ |
690
|
|
|
|
|
|
|
###LogSD 'Processing cell:', $cell ] ); |
691
|
|
|
|
|
|
|
|
692
|
0
|
|
|
|
|
|
$cell->{cell_type} = 'Text'; |
693
|
0
|
0
|
|
|
|
|
if( exists $cell->{t} ){ |
|
|
0
|
|
|
|
|
|
694
|
0
|
0
|
|
|
|
|
if( $cell->{t} eq 's' ){ |
|
|
0
|
|
|
|
|
|
695
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message =>[ |
696
|
|
|
|
|
|
|
###LogSD "Identified potentially required shared string for cell:", $cell] ); |
697
|
|
|
|
|
|
|
my $position = ( $self->_has_shared_strings_file ) ? |
698
|
0
|
0
|
|
|
|
|
$self->get_shared_string_position( $cell->{v}->{raw_text} ) : $cell->{v}->{raw_text}; |
699
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message =>[ |
700
|
|
|
|
|
|
|
###LogSD "Shared strings resolved to:", $position] ); |
701
|
0
|
0
|
|
|
|
|
if( is_HashRef( $position ) ){ |
702
|
0
|
|
|
|
|
|
@$cell{qw( cell_xml_value rich_text )} = ( $position->{raw_text}, $position->{rich_text} ); |
703
|
0
|
0
|
|
|
|
|
delete $cell->{rich_text} if !$cell->{rich_text}; |
704
|
|
|
|
|
|
|
}else{ |
705
|
0
|
|
|
|
|
|
$cell->{cell_xml_value} = $position; |
706
|
|
|
|
|
|
|
} |
707
|
|
|
|
|
|
|
}elsif( $cell->{t} eq 'str' ){ |
708
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message =>[ |
709
|
|
|
|
|
|
|
###LogSD "Identified a stored string in the worksheet file: " . ($cell->{v}//'')] ); |
710
|
0
|
|
|
|
|
|
$cell->{cell_xml_value} = $cell->{v}->{raw_text}; |
711
|
|
|
|
|
|
|
}else{ |
712
|
0
|
|
|
|
|
|
confess "Unknown 't' attribute set for the cell: $cell->{t}"; |
713
|
|
|
|
|
|
|
} |
714
|
0
|
|
|
|
|
|
delete $cell->{t}; |
715
|
0
|
|
|
|
|
|
delete $cell->{v}; |
716
|
|
|
|
|
|
|
}elsif( exists $cell->{v} ){ |
717
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message =>[ |
718
|
|
|
|
|
|
|
###LogSD "Setting cell_xml_value from: $cell->{v}->{raw_text}", ] ); |
719
|
0
|
|
|
|
|
|
$cell->{cell_xml_value} = $cell->{v}->{raw_text}; |
720
|
0
|
0
|
0
|
|
|
|
$cell->{cell_type} = 'Numeric' if $cell->{cell_xml_value} and $cell->{cell_xml_value} ne ''; |
721
|
0
|
|
|
|
|
|
delete $cell->{v}; |
722
|
|
|
|
|
|
|
} |
723
|
0
|
0
|
0
|
|
|
|
if( $self->get_empty_return_type eq 'empty_string' ){ |
|
|
0
|
0
|
|
|
|
|
724
|
0
|
0
|
0
|
|
|
|
$cell->{cell_xml_value} = '' if !exists $cell->{cell_xml_value} or !defined $cell->{cell_xml_value}; |
725
|
|
|
|
|
|
|
}elsif( !defined $cell->{cell_xml_value} or |
726
|
|
|
|
|
|
|
($cell->{cell_xml_value} and length( $cell->{cell_xml_value} ) == 0) ){ |
727
|
0
|
|
|
|
|
|
delete $cell->{cell_xml_value}; |
728
|
|
|
|
|
|
|
} |
729
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message =>[ |
730
|
|
|
|
|
|
|
###LogSD "Updated cell:", $cell] ); |
731
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
# Clear empty cells if required |
733
|
0
|
0
|
0
|
|
|
|
if( $self->get_values_only and ( !defined $cell->{cell_xml_value} or length( $cell->{cell_xml_value} ) == 0 ) ){ |
|
|
|
0
|
|
|
|
|
734
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'info', message => [ |
735
|
|
|
|
|
|
|
###LogSD 'Values only called - stripping this non-value cell' ] ); |
736
|
|
|
|
|
|
|
}else{ |
737
|
0
|
0
|
|
|
|
|
$cell->{cell_type} = 'Text' if !exists $cell->{cell_type}; |
738
|
0
|
0
|
|
|
|
|
$cell->{cell_hidden} = 'row' if $row_ref->{hidden}; |
739
|
0
|
|
|
|
|
|
@$cell{qw( cell_col cell_row )} = $self->_parse_column_row( $cell->{r} ); |
740
|
0
|
|
|
|
|
|
$last_value_column = $cell->{cell_col}; |
741
|
0
|
0
|
|
|
|
|
$cell->{cell_formula} = $cell->{f}->{raw_text} if $cell->{f}; |
742
|
0
|
|
|
|
|
|
delete $cell->{f}; |
743
|
0
|
|
|
|
|
|
$column_to_cell_translations->[$cell->{cell_col}] = $x++; |
744
|
0
|
0
|
|
|
|
|
$reported_column = $cell->{cell_col} if !defined $reported_column; |
745
|
0
|
|
|
|
|
|
$reported_position = 0; |
746
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'info', message => [ |
747
|
|
|
|
|
|
|
###LogSD 'Saving cell:', $cell ] ); |
748
|
0
|
|
|
|
|
|
push @$alt_ref, $cell; |
749
|
|
|
|
|
|
|
} |
750
|
|
|
|
|
|
|
} |
751
|
|
|
|
|
|
|
|
752
|
|
|
|
|
|
|
#Load the row instance |
753
|
0
|
|
|
|
|
|
my $new_ref; |
754
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message =>[ |
755
|
|
|
|
|
|
|
###LogSD "Row ref:", $row_ref, ] ); |
756
|
0
|
0
|
|
|
|
|
if( defined $row_ref->{r} ){ |
757
|
0
|
|
|
|
|
|
$new_ref->{row_number} = $row_ref->{r}; |
758
|
0
|
|
|
|
|
|
delete $row_ref->{r}; |
759
|
0
|
|
|
|
|
|
delete $row_ref->{list}; |
760
|
0
|
|
|
|
|
|
delete $row_ref->{hidden}; |
761
|
0
|
0
|
|
|
|
|
if( $alt_ref ){ |
762
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message =>[ |
763
|
|
|
|
|
|
|
###LogSD "Alt ref:", $alt_ref, ] ); |
764
|
0
|
|
|
|
|
|
$new_ref->{row_value_cells} = $alt_ref; |
765
|
0
|
0
|
|
|
|
|
$new_ref->{row_span} = $row_ref->{spans} ? [split /:/, $row_ref->{spans}] : [ undef, undef ]; |
766
|
0
|
|
|
|
|
|
$new_ref->{row_last_value_column} = $last_value_column; |
767
|
0
|
|
|
|
|
|
$new_ref->{column_to_cell_translations} = $column_to_cell_translations; |
768
|
0
|
|
0
|
|
|
|
$new_ref->{row_span}->[0] //= $new_ref->{row_value_cells}->[0]->{cell_col}; |
769
|
0
|
0
|
0
|
|
|
|
if( !$self->has_max_col or $self->_max_col < $new_ref->{row_value_cells}->[-1]->{cell_col} ){ |
770
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message =>[ |
771
|
|
|
|
|
|
|
###LogSD "From known cells setting the max column to: $new_ref->{row_value_cells}->[-1]->{cell_col}" ] ); |
772
|
0
|
|
|
|
|
|
$self->_set_max_col( $new_ref->{row_value_cells}->[-1]->{cell_col} ); |
773
|
|
|
|
|
|
|
} |
774
|
0
|
0
|
0
|
|
|
|
if( defined $new_ref->{row_span}->[1] and $self->_max_col < $new_ref->{row_span}->[1] ){ |
775
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message =>[ |
776
|
|
|
|
|
|
|
###LogSD "From the row span setting the max column to: $new_ref->{row_span}->[1]" ] ); |
777
|
0
|
|
|
|
|
|
$self->_set_max_col( $new_ref->{row_span}->[1] ); |
778
|
|
|
|
|
|
|
}else{ |
779
|
0
|
|
0
|
|
|
|
$new_ref->{row_span}->[1] //= $self->_max_col; |
780
|
|
|
|
|
|
|
} |
781
|
|
|
|
|
|
|
}else{ |
782
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message =>[ |
783
|
|
|
|
|
|
|
###LogSD " No row list (with values?) found" ] ); |
784
|
0
|
|
|
|
|
|
$new_ref->{row_span} = [ 0, 0 ]; |
785
|
0
|
|
|
|
|
|
$new_ref->{row_last_value_column} = 0; |
786
|
0
|
|
|
|
|
|
$new_ref->{column_to_cell_translations} = []; |
787
|
|
|
|
|
|
|
} |
788
|
0
|
|
|
|
|
|
delete $row_ref->{spans}; |
789
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message =>[ |
790
|
|
|
|
|
|
|
###LogSD "Row formats:", $row_ref, |
791
|
|
|
|
|
|
|
###LogSD "Row attributes:", $new_ref, ] ); |
792
|
0
|
|
|
|
|
|
my $row_node_ref = build_instance( |
793
|
|
|
|
|
|
|
package => 'RowInstance', |
794
|
|
|
|
|
|
|
superclasses => [ 'Spreadsheet::XLSX::Reader::LibXML::Row' ], |
795
|
|
|
|
|
|
|
row_formats => $row_ref, |
796
|
|
|
|
|
|
|
%$new_ref, |
797
|
|
|
|
|
|
|
###LogSD log_space => $self->get_log_space |
798
|
|
|
|
|
|
|
); |
799
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message =>[ |
800
|
|
|
|
|
|
|
###LogSD "New row instance:", $row_node_ref, ] ); |
801
|
0
|
|
|
|
|
|
$self->_set_new_row_inst( $row_node_ref ); |
802
|
|
|
|
|
|
|
}else{ |
803
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message =>[ |
804
|
|
|
|
|
|
|
###LogSD "line 706 - No row number found - must be EOF", ] ); |
805
|
0
|
|
|
|
|
|
return 'EOF'; |
806
|
|
|
|
|
|
|
} |
807
|
|
|
|
|
|
|
|
808
|
0
|
0
|
|
|
|
|
if( !$alt_ref ){ |
809
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message =>[ |
810
|
|
|
|
|
|
|
###LogSD 'Nothing to see here - move along', ] ); |
811
|
|
|
|
|
|
|
###LogSD no warnings 'uninitialized'; |
812
|
0
|
|
|
|
|
|
my $result = $current_row + 1; |
813
|
0
|
0
|
|
|
|
|
if( is_Int( $current_row ) ){ |
814
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message =>[ |
815
|
|
|
|
|
|
|
###LogSD "Going on to the next row: " . ($current_row +1), ] ); |
816
|
|
|
|
|
|
|
#~ no warnings 'recursion'; |
817
|
0
|
|
|
|
|
|
$result = $self->_go_to_or_past_row( $current_row + 1 );# Recursive call for empty rows |
818
|
|
|
|
|
|
|
#~ use warnings 'recursion'; |
819
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message =>[ |
820
|
|
|
|
|
|
|
###LogSD "Returned from the next row with: " . ($result//'undef'), |
821
|
|
|
|
|
|
|
###LogSD "..target current row is: " . ($current_row +1), ] ); |
822
|
0
|
|
|
|
|
|
$self->_set_row_position( $current_row => undef );# Clean up phantom placeholder |
823
|
0
|
|
|
|
|
|
my $max_positions = $self->_max_row_position_recorded - 1; |
824
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message =>[ |
825
|
|
|
|
|
|
|
###LogSD "The last 10 position ref values are: " . |
826
|
|
|
|
|
|
|
###LogSD join( ', ', @{$self->_get_all_positions}[( $max_positions > 10 ? $max_positions - 10 : 0 ) .. $max_positions] ), ] ); |
827
|
|
|
|
|
|
|
} |
828
|
0
|
|
|
|
|
|
$current_row = $result; |
829
|
|
|
|
|
|
|
###LogSD my $max_positions = $self->_max_row_position_recorded - 1; |
830
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message =>[ |
831
|
|
|
|
|
|
|
###LogSD 'Updated current row -$current_row- pdated last 10 row positions are: ' . |
832
|
|
|
|
|
|
|
###LogSD join( ', ', @{$self->_get_all_positions}[( $max_positions > 10 ? $max_positions - 10 : 0 ) .. $max_positions] ) ] ); |
833
|
|
|
|
|
|
|
###LogSD use warnings 'uninitialized'; |
834
|
|
|
|
|
|
|
} |
835
|
0
|
0
|
0
|
|
|
|
$self->_set_max_row_state if $current_row and $current_row eq 'EOF'; |
836
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message =>[ |
837
|
|
|
|
|
|
|
###LogSD "Returning: ", $current_row ] ); |
838
|
0
|
|
|
|
|
|
return $current_row; |
839
|
|
|
|
|
|
|
} |
840
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
sub _set_max_row_state{ |
842
|
0
|
|
|
0
|
|
|
my( $self, ) = @_; |
843
|
0
|
|
|
|
|
|
my $row_position_ref = $self->_get_all_positions; |
844
|
0
|
|
|
|
|
|
my $max_positions = $#$row_position_ref; |
845
|
|
|
|
|
|
|
###LogSD my $phone = Log::Shiras::Telephone->new( name_space => |
846
|
|
|
|
|
|
|
###LogSD $self->get_all_space . '::WorksheetToRow::_go_to_or_past_row::_set_max_row_state', ); |
847
|
|
|
|
|
|
|
###LogSD no warnings 'uninitialized'; |
848
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
849
|
|
|
|
|
|
|
###LogSD "The current max row is: " . ($self->has_max_row ? $self->_max_row : 'undef'), |
850
|
|
|
|
|
|
|
###LogSD "Setting the max row from the last 10 positions of the row position ref:" . join( ', ', @$row_position_ref[( $max_positions > 10 ? $max_positions - 10 : 0 ) .. $max_positions] ) ] ); |
851
|
|
|
|
|
|
|
###LogSD use warnings 'uninitialized'; |
852
|
0
|
0
|
|
|
|
|
if( $self->is_empty_the_end ){ |
853
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
854
|
|
|
|
|
|
|
###LogSD "Clearing empty rows from the end" ] ); |
855
|
0
|
|
|
|
|
|
my $last_position; |
856
|
0
|
|
|
|
|
|
while( !defined $last_position ){ |
857
|
0
|
|
|
|
|
|
$last_position = $self->_remove_last_row_position; |
858
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
859
|
|
|
|
|
|
|
###LogSD "Removed the last row position value: " . ($last_position//'undef'), |
860
|
|
|
|
|
|
|
###LogSD "..from position: " . $self->_max_row_position_recorded ] ); |
861
|
|
|
|
|
|
|
} |
862
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
863
|
|
|
|
|
|
|
###LogSD "Reload the final poped value: " . $self->_max_row_position_recorded . ' => ' . $last_position ] ); |
864
|
0
|
|
|
|
|
|
$self->_set_row_position( $self->_max_row_position_recorded => $last_position ); |
865
|
|
|
|
|
|
|
} |
866
|
0
|
|
|
|
|
|
my $last_row = $self->_max_row_position_recorded - 1; |
867
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
868
|
|
|
|
|
|
|
###LogSD "Setting the max row to: $last_row" ] ); |
869
|
0
|
|
|
|
|
|
$self->_clear_new_row_inst; |
870
|
0
|
|
|
|
|
|
$self->start_the_file_over; |
871
|
0
|
|
|
|
|
|
$self->_set_max_row( $last_row ); |
872
|
0
|
|
|
|
|
|
return $last_row; |
873
|
|
|
|
|
|
|
} |
874
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
sub _load_unique_bits{ |
876
|
0
|
|
|
0
|
|
|
my( $self, ) = @_;#, $new_file, $old_file |
877
|
|
|
|
|
|
|
###LogSD my $phone = Log::Shiras::Telephone->new( name_space => |
878
|
|
|
|
|
|
|
###LogSD $self->get_all_space . '::WorksheetToRow::_load_unique_bits', ); |
879
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
880
|
|
|
|
|
|
|
###LogSD "Setting the Worksheet unique bits", ] ); |
881
|
|
|
|
|
|
|
|
882
|
|
|
|
|
|
|
# Read the sheet dimensions |
883
|
0
|
|
|
|
|
|
my ( $node_depth, $node_name, $node_type ) = $self->location_status; |
884
|
0
|
0
|
0
|
|
|
|
if( $node_name eq 'dimension' or $self->advance_element_position( 'dimension' ) ){ |
885
|
0
|
|
|
|
|
|
my $dimension = $self->parse_element; |
886
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
887
|
|
|
|
|
|
|
###LogSD "parsed dimension value:", $dimension ] ); |
888
|
0
|
|
|
|
|
|
my ( $start, $end ) = split( /:/, $dimension->{ref} ); |
889
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
890
|
|
|
|
|
|
|
###LogSD "Start position: $start", |
891
|
|
|
|
|
|
|
###LogSD ( $end ? "End position: $end" : '' ), ] ); |
892
|
0
|
0
|
|
|
|
|
my ( $start_column, $start_row ) = ( $self->_starts_at_the_edge ) ? |
893
|
|
|
|
|
|
|
( 1, 1 ) : $self->_parse_column_row( $start ); |
894
|
0
|
0
|
|
|
|
|
my ( $end_column, $end_row ) = $end ? |
895
|
|
|
|
|
|
|
$self->_parse_column_row( $end ) : |
896
|
|
|
|
|
|
|
( undef, undef ) ; |
897
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
898
|
|
|
|
|
|
|
###LogSD 'Start column: ' . ($start_column//'undef'), 'Start row: ' . ($start_row//'undef'), |
899
|
|
|
|
|
|
|
###LogSD 'End column: ' . ($end_column//'undef'), 'End row: ' . ($end_row//'undef') ] ); |
900
|
0
|
|
|
|
|
|
$self->_set_min_col( $start_column ); |
901
|
0
|
|
|
|
|
|
$self->_set_min_row( $start_row ); |
902
|
0
|
0
|
|
|
|
|
$self->_set_max_col( $end_column ) if defined $end_column; |
903
|
0
|
0
|
|
|
|
|
$self->_set_max_row( $end_row ) if defined $end_row; |
904
|
|
|
|
|
|
|
}else{ |
905
|
0
|
|
|
|
|
|
confess "No sheet dimensions provided";# Shouldn't the error instance be loaded already? |
906
|
|
|
|
|
|
|
} |
907
|
|
|
|
|
|
|
|
908
|
|
|
|
|
|
|
#pull column stats |
909
|
0
|
|
|
|
|
|
my $has_column_data = 1; |
910
|
0
|
|
|
|
|
|
( $node_depth, $node_name, $node_type ) = $self->location_status; |
911
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
912
|
|
|
|
|
|
|
###LogSD "Loading the column configuration" ] ); |
913
|
0
|
0
|
0
|
|
|
|
if( $node_name eq 'cols' or $self->advance_element_position( 'cols') ){ |
914
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
915
|
|
|
|
|
|
|
###LogSD "Already arrived at the column data" ] ); |
916
|
|
|
|
|
|
|
}else{ |
917
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
918
|
|
|
|
|
|
|
###LogSD "Restart the sheet to find the column data" ] ); |
919
|
0
|
|
|
|
|
|
$self->start_the_file_over; |
920
|
0
|
|
|
|
|
|
$has_column_data = $self->advance_element_position( 'cols' ); |
921
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
922
|
|
|
|
|
|
|
###LogSD "Column data search result: $has_column_data" ] ); |
923
|
|
|
|
|
|
|
} |
924
|
0
|
0
|
|
|
|
|
if( $has_column_data ){ |
925
|
0
|
|
|
|
|
|
my $column_data = $self->parse_element; |
926
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
927
|
|
|
|
|
|
|
###LogSD "parsed column elements to:", $column_data ] ); |
928
|
0
|
|
|
|
|
|
my $column_store = []; |
929
|
0
|
|
|
|
|
|
for my $definition ( @{$column_data->{list}} ){ |
|
0
|
|
|
|
|
|
|
930
|
0
|
0
|
|
|
|
|
next if !is_HashRef( $definition ); |
931
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
932
|
|
|
|
|
|
|
###LogSD "Processing:", $definition ] ); |
933
|
0
|
|
|
|
|
|
my $row_ref; |
934
|
0
|
0
|
|
|
|
|
map{ $row_ref->{$_} = $definition->{$_} if defined $definition->{$_} } qw( width customWidth bestFit hidden ); |
|
0
|
|
|
|
|
|
|
935
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
936
|
|
|
|
|
|
|
###LogSD "Updated row ref:", $row_ref ] ); |
937
|
0
|
|
|
|
|
|
for my $col ( $definition->{min} .. $definition->{max} ){ |
938
|
0
|
|
|
|
|
|
$column_store->[$col] = $row_ref; |
939
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
940
|
|
|
|
|
|
|
###LogSD "Updated column store is:", $column_store ] ); |
941
|
|
|
|
|
|
|
} |
942
|
|
|
|
|
|
|
} |
943
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
944
|
|
|
|
|
|
|
###LogSD "Final column store is:", $column_store ] ); |
945
|
0
|
|
|
|
|
|
$self->_set_column_formats( $column_store ); |
946
|
|
|
|
|
|
|
} |
947
|
|
|
|
|
|
|
|
948
|
|
|
|
|
|
|
#build a merge map |
949
|
0
|
|
|
|
|
|
my $merge_ref = []; |
950
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
951
|
|
|
|
|
|
|
###LogSD "Loading the mergeCell" ] ); |
952
|
0
|
|
|
|
|
|
( $node_depth, $node_name, $node_type ) = $self->location_status; |
953
|
0
|
|
|
|
|
|
my $found_merges = 0; |
954
|
0
|
0
|
0
|
|
|
|
if( ($node_name and $node_name eq 'mergeCells') or $self->advance_element_position( 'mergeCells') ){ |
|
|
|
0
|
|
|
|
|
955
|
0
|
|
|
|
|
|
$found_merges = 1; |
956
|
|
|
|
|
|
|
}else{ |
957
|
0
|
|
|
|
|
|
$self->start_the_file_over; |
958
|
0
|
|
|
|
|
|
$found_merges = $self->advance_element_position( 'mergeCells'); |
959
|
|
|
|
|
|
|
} |
960
|
0
|
0
|
|
|
|
|
if( $found_merges ){ |
961
|
0
|
|
|
|
|
|
my $merge_range = $self->parse_element; |
962
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
963
|
|
|
|
|
|
|
###LogSD "Processing all merge ranges:", $merge_range ] ); |
964
|
0
|
|
|
|
|
|
my $final_ref; |
965
|
0
|
|
|
|
|
|
for my $merge_ref ( @{$merge_range->{list}} ){ |
|
0
|
|
|
|
|
|
|
966
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
967
|
|
|
|
|
|
|
###LogSD "parsed merge element to:", $merge_ref ] ); |
968
|
0
|
|
|
|
|
|
my ( $start, $end ) = split /:/, $merge_ref->{ref}; |
969
|
0
|
|
|
|
|
|
my ( $start_col, $start_row ) = $self->_parse_column_row( $start ); |
970
|
0
|
|
|
|
|
|
my ( $end_col, $end_row ) = $self->_parse_column_row( $end ); |
971
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
972
|
|
|
|
|
|
|
###LogSD "Start column: $start_col", "Start row: $start_row", |
973
|
|
|
|
|
|
|
###LogSD "End column: $end_col", "End row: $end_row" ] ); |
974
|
0
|
|
|
|
|
|
my $min_col = $start_col; |
975
|
0
|
|
|
|
|
|
while ( $start_row <= $end_row ){ |
976
|
0
|
|
|
|
|
|
$final_ref->[$start_row]->[$start_col] = $merge_ref->{ref}; |
977
|
0
|
|
|
|
|
|
$start_col++; |
978
|
0
|
0
|
|
|
|
|
if( $start_col > $end_col ){ |
979
|
0
|
|
|
|
|
|
$start_col = $min_col; |
980
|
0
|
|
|
|
|
|
$start_row++; |
981
|
|
|
|
|
|
|
} |
982
|
|
|
|
|
|
|
} |
983
|
|
|
|
|
|
|
} |
984
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message => [ |
985
|
|
|
|
|
|
|
###LogSD "Final merge ref:", $final_ref ] ); |
986
|
0
|
|
|
|
|
|
$self->_set_merge_map( $final_ref ); |
987
|
|
|
|
|
|
|
} |
988
|
0
|
|
|
|
|
|
$self->start_the_file_over; |
989
|
0
|
|
|
|
|
|
return 1; |
990
|
|
|
|
|
|
|
} |
991
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
sub _is_column_hidden{ |
993
|
0
|
|
|
0
|
|
|
my( $self, @column_requests ) = @_; |
994
|
|
|
|
|
|
|
###LogSD my $phone = Log::Shiras::Telephone->new( name_space => |
995
|
|
|
|
|
|
|
###LogSD $self->get_all_space . '::WorksheetToRow::is_column_hidden::subsub', ); |
996
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'debug', message => [ |
997
|
|
|
|
|
|
|
###LogSD 'Pulling the hidden state for the columns:', @column_requests ] ); |
998
|
|
|
|
|
|
|
|
999
|
0
|
|
|
|
|
|
my @tru_dat; |
1000
|
0
|
|
|
|
|
|
for my $column ( @column_requests ){ |
1001
|
0
|
|
|
|
|
|
my $column_format = $self->_get_custom_column_data( $column ); |
1002
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'trace', message =>[ |
1003
|
|
|
|
|
|
|
###LogSD "Column formats for column -$column- are:", $column_format ] ); |
1004
|
0
|
0
|
0
|
|
|
|
push @tru_dat, (( $column_format and $column_format->{hidden} ) ? 1 : 0); |
1005
|
|
|
|
|
|
|
} |
1006
|
|
|
|
|
|
|
###LogSD $phone->talk( level => 'info', message =>[ |
1007
|
|
|
|
|
|
|
###LogSD "Final column hidden state is list:", @tru_dat] ); |
1008
|
0
|
|
|
|
|
|
return @tru_dat; |
1009
|
|
|
|
|
|
|
} |
1010
|
|
|
|
|
|
|
|
1011
|
|
|
|
|
|
|
#########1 Phinish 3#########4#########5#########6#########7#########8#########9 |
1012
|
|
|
|
|
|
|
|
1013
|
3
|
|
|
3
|
|
22
|
no Moose; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
41
|
|
1014
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable; |
1015
|
|
|
|
|
|
|
|
1016
|
|
|
|
|
|
|
1; |
1017
|
|
|
|
|
|
|
|
1018
|
|
|
|
|
|
|
#########1 Documentation 3#########4#########5#########6#########7#########8#########9 |
1019
|
|
|
|
|
|
|
__END__ |
1020
|
|
|
|
|
|
|
|
1021
|
|
|
|
|
|
|
=head1 NAME |
1022
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
Spreadsheet::XLSX::Reader::LibXML::XMLReader::WorksheetToRow - Pull rows out of worksheet xml files |
1024
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
=head1 SYNOPSIS |
1026
|
|
|
|
|
|
|
|
1027
|
|
|
|
|
|
|
See t\Spreadsheet\XLSX\Reader\LibXML02-worksheet_to_row.t |
1028
|
|
|
|
|
|
|
|
1029
|
|
|
|
|
|
|
=head1 DESCRIPTION |
1030
|
|
|
|
|
|
|
|
1031
|
|
|
|
|
|
|
This documentation is written to explain ways to use this module when writing your own excel |
1032
|
|
|
|
|
|
|
parser. To use the general package for excel parsing out of the box please review the |
1033
|
|
|
|
|
|
|
documentation for L<Workbooks|Spreadsheet::XLSX::Reader::LibXML>, |
1034
|
|
|
|
|
|
|
L<Worksheets|Spreadsheet::XLSX::Reader::LibXML::Worksheet>, and |
1035
|
|
|
|
|
|
|
L<Cells|Spreadsheet::XLSX::Reader::LibXML::Cell> |
1036
|
|
|
|
|
|
|
|
1037
|
|
|
|
|
|
|
This module provides the basic connection to individual worksheet files (not chartsheets) for |
1038
|
|
|
|
|
|
|
parsing xlsx workbooks and coalating shared strings data to cell data. It does not provide |
1039
|
|
|
|
|
|
|
a way to connect to L<chartsheets|Spreadsheet::XLSX::Reader::LibXML::Chartsheet>. It does |
1040
|
|
|
|
|
|
|
not provide the final view of a given cell. The final view of the cell is collated with |
1041
|
|
|
|
|
|
|
the role (Interface) L<Spreadsheet::XLSX::Reader::LibXML::Worksheet>. This reader extends |
1042
|
|
|
|
|
|
|
the base reader class L<Spreadsheet::XLSX::Reader::LibXML::XMLReader>. The functionality |
1043
|
|
|
|
|
|
|
provided by those modules is not explained here. |
1044
|
|
|
|
|
|
|
|
1045
|
|
|
|
|
|
|
For now this module reads each full row (with values) into a L<Spreadsheet::XLSX::Reader::LibXML::Row> |
1046
|
|
|
|
|
|
|
instance. It stores only the currently read row and the previously read row. Exceptions to |
1047
|
|
|
|
|
|
|
this are the start of read and end of read. For start of read only the current row is available |
1048
|
|
|
|
|
|
|
with the assumption that all prior implied rows are empty. When a position past the end of the sheet |
1049
|
|
|
|
|
|
|
is called both current and prior rows are cleared and an 'EOF' or undef value is returned. See |
1050
|
|
|
|
|
|
|
L<Spreadsheet::XLSX::Reader::LibXML/file_boundary_flags> for more details. This allows for storage |
1051
|
|
|
|
|
|
|
of row general formats by row and where a requested cell falls in a row without values that the empty |
1052
|
|
|
|
|
|
|
state can be determined without rescanning the file. |
1053
|
|
|
|
|
|
|
|
1054
|
|
|
|
|
|
|
I<All positions (row and column places and integers) at this level are stored and returned in count |
1055
|
|
|
|
|
|
|
from one mode!> |
1056
|
|
|
|
|
|
|
|
1057
|
|
|
|
|
|
|
Modification of this module probably means extending a different reader or using other roles |
1058
|
|
|
|
|
|
|
for implementation of the class. Search for |
1059
|
|
|
|
|
|
|
|
1060
|
|
|
|
|
|
|
extends 'Spreadsheet::XLSX::Reader::LibXML::XMLReader'; |
1061
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
To replace the base reader. Search for the method 'worksheet' in L<Spreadsheet::XLSX::Reader::LibXML> |
1063
|
|
|
|
|
|
|
and the variable '$parser_modules' to replace this whole thing. |
1064
|
|
|
|
|
|
|
|
1065
|
|
|
|
|
|
|
=head2 Attributes |
1066
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
Data passed to new when creating an instance. For access to the values in these |
1068
|
|
|
|
|
|
|
attributes see the listed 'attribute methods'. For general information on attributes see |
1069
|
|
|
|
|
|
|
L<Moose::Manual::Attributes>. For ways to manage the instance when opened see the |
1070
|
|
|
|
|
|
|
L<Public Methods|/Public Methods>. |
1071
|
|
|
|
|
|
|
|
1072
|
|
|
|
|
|
|
=head3 is_hidden |
1073
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
=over |
1075
|
|
|
|
|
|
|
|
1076
|
|
|
|
|
|
|
B<Definition:> This is set when the sheet is read from the sheet metadata level indicating |
1077
|
|
|
|
|
|
|
if the sheet is hidden |
1078
|
|
|
|
|
|
|
|
1079
|
|
|
|
|
|
|
B<Default:> none |
1080
|
|
|
|
|
|
|
|
1081
|
|
|
|
|
|
|
B<Range:> (1|0) |
1082
|
|
|
|
|
|
|
|
1083
|
|
|
|
|
|
|
B<attribute methods> Methods provided to adjust this attribute |
1084
|
|
|
|
|
|
|
|
1085
|
|
|
|
|
|
|
=over |
1086
|
|
|
|
|
|
|
|
1087
|
|
|
|
|
|
|
B<is_sheet_hidden> |
1088
|
|
|
|
|
|
|
|
1089
|
|
|
|
|
|
|
=over |
1090
|
|
|
|
|
|
|
|
1091
|
|
|
|
|
|
|
B<Definition:> return the attribute value |
1092
|
|
|
|
|
|
|
|
1093
|
|
|
|
|
|
|
=back |
1094
|
|
|
|
|
|
|
|
1095
|
|
|
|
|
|
|
=back |
1096
|
|
|
|
|
|
|
|
1097
|
|
|
|
|
|
|
=back |
1098
|
|
|
|
|
|
|
|
1099
|
|
|
|
|
|
|
=head3 workbook_instance |
1100
|
|
|
|
|
|
|
|
1101
|
|
|
|
|
|
|
=over |
1102
|
|
|
|
|
|
|
|
1103
|
|
|
|
|
|
|
B<Definition:> This attribute holds a reference back to the workbook instance so that |
1104
|
|
|
|
|
|
|
the worksheet has access to the global settings managed there. As a consequence many |
1105
|
|
|
|
|
|
|
of the workbook methods are be exposed here. This includes some setter methods for |
1106
|
|
|
|
|
|
|
workbook attributes. I<Beware that setting or adjusting the workbook level attributes |
1107
|
|
|
|
|
|
|
with methods here will be universal and affect other worksheets. So don't forget to |
1108
|
|
|
|
|
|
|
return the old value if you want the old behavour after you are done.> If that |
1109
|
|
|
|
|
|
|
doesn't make sense then don't use these methods. (Nothing to see here! Move along.) |
1110
|
|
|
|
|
|
|
|
1111
|
|
|
|
|
|
|
B<Default:> a Spreadsheet::XLSX::Reader::LibXML instance |
1112
|
|
|
|
|
|
|
|
1113
|
|
|
|
|
|
|
B<attribute methods> Methods of the workbook exposed here by the L<delegation |
1114
|
|
|
|
|
|
|
|Moose::Manual::Attributes/Delegation> of the instance to this class through this |
1115
|
|
|
|
|
|
|
attribute |
1116
|
|
|
|
|
|
|
|
1117
|
|
|
|
|
|
|
=over |
1118
|
|
|
|
|
|
|
|
1119
|
|
|
|
|
|
|
B<counting_from_zero> |
1120
|
|
|
|
|
|
|
|
1121
|
|
|
|
|
|
|
=over |
1122
|
|
|
|
|
|
|
|
1123
|
|
|
|
|
|
|
B<Definition:> returns the L<Spreadsheet::XLSX::Reader::LibXML/count_from_zero> |
1124
|
|
|
|
|
|
|
instance state |
1125
|
|
|
|
|
|
|
|
1126
|
|
|
|
|
|
|
=back |
1127
|
|
|
|
|
|
|
|
1128
|
|
|
|
|
|
|
B<boundary_flag_setting> |
1129
|
|
|
|
|
|
|
|
1130
|
|
|
|
|
|
|
=over |
1131
|
|
|
|
|
|
|
|
1132
|
|
|
|
|
|
|
B<Definition:> returns the L<Spreadsheet::XLSX::Reader::LibXML/file_boundary_flags> |
1133
|
|
|
|
|
|
|
instance state |
1134
|
|
|
|
|
|
|
|
1135
|
|
|
|
|
|
|
=back |
1136
|
|
|
|
|
|
|
|
1137
|
|
|
|
|
|
|
B<change_boundary_flag( $Bool )> |
1138
|
|
|
|
|
|
|
|
1139
|
|
|
|
|
|
|
=over |
1140
|
|
|
|
|
|
|
|
1141
|
|
|
|
|
|
|
B<Definition:> sets the L<Spreadsheet::XLSX::Reader::LibXML/file_boundary_flags> |
1142
|
|
|
|
|
|
|
instance state (B<For the whole workbook!>) |
1143
|
|
|
|
|
|
|
|
1144
|
|
|
|
|
|
|
=back |
1145
|
|
|
|
|
|
|
|
1146
|
|
|
|
|
|
|
B<get_shared_string_position( $int )> |
1147
|
|
|
|
|
|
|
|
1148
|
|
|
|
|
|
|
=over |
1149
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
B<Definition:> returns the shared string data stored in the sharedStrings |
1151
|
|
|
|
|
|
|
file at position $int. For more information review |
1152
|
|
|
|
|
|
|
L<Spreadsheet::XLSX::Reader::LibXML::SharedStrings>. I<This is a delegation |
1153
|
|
|
|
|
|
|
of a delegation!> |
1154
|
|
|
|
|
|
|
|
1155
|
|
|
|
|
|
|
=back |
1156
|
|
|
|
|
|
|
|
1157
|
|
|
|
|
|
|
B<get_format_position( $int, [$header] )> |
1158
|
|
|
|
|
|
|
|
1159
|
|
|
|
|
|
|
=over |
1160
|
|
|
|
|
|
|
|
1161
|
|
|
|
|
|
|
B<Definition:> returns the format data stored in the styles |
1162
|
|
|
|
|
|
|
file at position $int. If the optional $header is passed only the data for that |
1163
|
|
|
|
|
|
|
header is returned. Otherwise all styles for that position are returned. |
1164
|
|
|
|
|
|
|
For more information review |
1165
|
|
|
|
|
|
|
L<Spreadsheet::XLSX::Reader::LibXML::Styles>. I<This is a delegation |
1166
|
|
|
|
|
|
|
of a delegation!> |
1167
|
|
|
|
|
|
|
|
1168
|
|
|
|
|
|
|
=back |
1169
|
|
|
|
|
|
|
|
1170
|
|
|
|
|
|
|
B<set_empty_is_end( $Bool )> |
1171
|
|
|
|
|
|
|
|
1172
|
|
|
|
|
|
|
=over |
1173
|
|
|
|
|
|
|
|
1174
|
|
|
|
|
|
|
B<Definition:> sets the L<Spreadsheet::XLSX::Reader::LibXML/empty_is_end> |
1175
|
|
|
|
|
|
|
instance state (B<For the whole workbook!>) |
1176
|
|
|
|
|
|
|
|
1177
|
|
|
|
|
|
|
=back |
1178
|
|
|
|
|
|
|
|
1179
|
|
|
|
|
|
|
B<is_empty_the_end> |
1180
|
|
|
|
|
|
|
|
1181
|
|
|
|
|
|
|
=over |
1182
|
|
|
|
|
|
|
|
1183
|
|
|
|
|
|
|
B<Definition:> returns the L<Spreadsheet::XLSX::Reader::LibXML/empty_is_end> |
1184
|
|
|
|
|
|
|
instance state. |
1185
|
|
|
|
|
|
|
|
1186
|
|
|
|
|
|
|
=back |
1187
|
|
|
|
|
|
|
|
1188
|
|
|
|
|
|
|
B<get_group_return_type> |
1189
|
|
|
|
|
|
|
|
1190
|
|
|
|
|
|
|
=over |
1191
|
|
|
|
|
|
|
|
1192
|
|
|
|
|
|
|
B<Definition:> returns the L<Spreadsheet::XLSX::Reader::LibXML/group_return_type> |
1193
|
|
|
|
|
|
|
instance state. |
1194
|
|
|
|
|
|
|
|
1195
|
|
|
|
|
|
|
=back |
1196
|
|
|
|
|
|
|
|
1197
|
|
|
|
|
|
|
B<set_group_return_type( (instance|unformatted|value) )> |
1198
|
|
|
|
|
|
|
|
1199
|
|
|
|
|
|
|
=over |
1200
|
|
|
|
|
|
|
|
1201
|
|
|
|
|
|
|
B<Definition:> sets the L<Spreadsheet::XLSX::Reader::LibXML/group_return_type> |
1202
|
|
|
|
|
|
|
instance state (B<For the whole workbook!>) |
1203
|
|
|
|
|
|
|
|
1204
|
|
|
|
|
|
|
=back |
1205
|
|
|
|
|
|
|
|
1206
|
|
|
|
|
|
|
B<get_epoch_year> |
1207
|
|
|
|
|
|
|
|
1208
|
|
|
|
|
|
|
=over |
1209
|
|
|
|
|
|
|
|
1210
|
|
|
|
|
|
|
B<Definition:> uses the L<Spreadsheet::XLSX::Reader::LibXML/get_epoch_year> method. |
1211
|
|
|
|
|
|
|
|
1212
|
|
|
|
|
|
|
=back |
1213
|
|
|
|
|
|
|
|
1214
|
|
|
|
|
|
|
B<get_date_behavior> |
1215
|
|
|
|
|
|
|
|
1216
|
|
|
|
|
|
|
=over |
1217
|
|
|
|
|
|
|
|
1218
|
|
|
|
|
|
|
B<Definition:> This is a L<delegated|Moose::Manual::Delegation> method from the |
1219
|
|
|
|
|
|
|
L<styles|Spreadsheet::XLSX::Reader::LibXML::Styles> class (stored as a private |
1220
|
|
|
|
|
|
|
instance in the workbook). It is held (and documented) in the |
1221
|
|
|
|
|
|
|
L<Spreadsheet::XLSX::Reader::LibXML::ParseExcelFormatStrings> role. It will |
1222
|
|
|
|
|
|
|
indicate how far unformatted L<transformation |
1223
|
|
|
|
|
|
|
|Spreadsheet::XLSX::Reader::LibXML::ParseExcelFormatStrings/datetime_dates> |
1224
|
|
|
|
|
|
|
is carried for date coercions when returning formatted values. |
1225
|
|
|
|
|
|
|
|
1226
|
|
|
|
|
|
|
=back |
1227
|
|
|
|
|
|
|
|
1228
|
|
|
|
|
|
|
B<set_date_behavior> |
1229
|
|
|
|
|
|
|
|
1230
|
|
|
|
|
|
|
=over |
1231
|
|
|
|
|
|
|
|
1232
|
|
|
|
|
|
|
B<Definition:> This is a L<delegated|Moose::Manual::Delegation> method from |
1233
|
|
|
|
|
|
|
the L<styles|Spreadsheet::XLSX::Reader::LibXML::Styles> class (stored as a private |
1234
|
|
|
|
|
|
|
instance in the workbook). It is held (and documented) in the |
1235
|
|
|
|
|
|
|
L<Spreadsheet::XLSX::Reader::LibXML::ParseExcelFormatStrings> role. It will set how |
1236
|
|
|
|
|
|
|
far unformatted L<transformation |
1237
|
|
|
|
|
|
|
|Spreadsheet::XLSX::Reader::LibXML::ParseExcelFormatStrings/datetime_dates> |
1238
|
|
|
|
|
|
|
is carried for date coercions when returning formatted values. |
1239
|
|
|
|
|
|
|
|
1240
|
|
|
|
|
|
|
=back |
1241
|
|
|
|
|
|
|
|
1242
|
|
|
|
|
|
|
B<get_values_only> |
1243
|
|
|
|
|
|
|
|
1244
|
|
|
|
|
|
|
=over |
1245
|
|
|
|
|
|
|
|
1246
|
|
|
|
|
|
|
B<Definition:> gets the L<Spreadsheet::XLSX::Reader::LibXML/values_only> |
1247
|
|
|
|
|
|
|
instance state. |
1248
|
|
|
|
|
|
|
|
1249
|
|
|
|
|
|
|
=back |
1250
|
|
|
|
|
|
|
|
1251
|
|
|
|
|
|
|
B<set_values_only> |
1252
|
|
|
|
|
|
|
|
1253
|
|
|
|
|
|
|
=over |
1254
|
|
|
|
|
|
|
|
1255
|
|
|
|
|
|
|
B<Definition:> sets the L<Spreadsheet::XLSX::Reader::LibXML/values_only> |
1256
|
|
|
|
|
|
|
instance state (B<For the whole workbook!>) |
1257
|
|
|
|
|
|
|
|
1258
|
|
|
|
|
|
|
=back |
1259
|
|
|
|
|
|
|
|
1260
|
|
|
|
|
|
|
=back |
1261
|
|
|
|
|
|
|
|
1262
|
|
|
|
|
|
|
=back |
1263
|
|
|
|
|
|
|
|
1264
|
|
|
|
|
|
|
=head3 _sheet_min_col |
1265
|
|
|
|
|
|
|
|
1266
|
|
|
|
|
|
|
=over |
1267
|
|
|
|
|
|
|
|
1268
|
|
|
|
|
|
|
B<Definition:> This is the minimum column in the sheet with data or formatting. For this |
1269
|
|
|
|
|
|
|
module it is pulled from the xml file at worksheet/dimension:ref = "upperleft:lowerright" |
1270
|
|
|
|
|
|
|
|
1271
|
|
|
|
|
|
|
B<Range:> an integer |
1272
|
|
|
|
|
|
|
|
1273
|
|
|
|
|
|
|
B<attribute methods> Methods provided to adjust this attribute |
1274
|
|
|
|
|
|
|
|
1275
|
|
|
|
|
|
|
=over |
1276
|
|
|
|
|
|
|
|
1277
|
|
|
|
|
|
|
B<_set_min_col> |
1278
|
|
|
|
|
|
|
|
1279
|
|
|
|
|
|
|
=over |
1280
|
|
|
|
|
|
|
|
1281
|
|
|
|
|
|
|
B<Definition:> sets the attribute value |
1282
|
|
|
|
|
|
|
|
1283
|
|
|
|
|
|
|
=back |
1284
|
|
|
|
|
|
|
|
1285
|
|
|
|
|
|
|
B<_min_col> |
1286
|
|
|
|
|
|
|
|
1287
|
|
|
|
|
|
|
=over |
1288
|
|
|
|
|
|
|
|
1289
|
|
|
|
|
|
|
B<Definition:> returns the attribute value |
1290
|
|
|
|
|
|
|
|
1291
|
|
|
|
|
|
|
=back |
1292
|
|
|
|
|
|
|
|
1293
|
|
|
|
|
|
|
B<has_min_col> |
1294
|
|
|
|
|
|
|
|
1295
|
|
|
|
|
|
|
=over |
1296
|
|
|
|
|
|
|
|
1297
|
|
|
|
|
|
|
B<Definition:> attribute predicate |
1298
|
|
|
|
|
|
|
|
1299
|
|
|
|
|
|
|
=back |
1300
|
|
|
|
|
|
|
|
1301
|
|
|
|
|
|
|
=back |
1302
|
|
|
|
|
|
|
|
1303
|
|
|
|
|
|
|
=back |
1304
|
|
|
|
|
|
|
|
1305
|
|
|
|
|
|
|
=head3 _sheet_min_row |
1306
|
|
|
|
|
|
|
|
1307
|
|
|
|
|
|
|
=over |
1308
|
|
|
|
|
|
|
|
1309
|
|
|
|
|
|
|
B<Definition:> This is the minimum row in the sheet with data or formatting. For this |
1310
|
|
|
|
|
|
|
module it is pulled from the xml file at worksheet/dimension:ref = "upperleft:lowerright" |
1311
|
|
|
|
|
|
|
|
1312
|
|
|
|
|
|
|
B<Range:> an integer |
1313
|
|
|
|
|
|
|
|
1314
|
|
|
|
|
|
|
B<attribute methods> Methods provided to adjust this attribute |
1315
|
|
|
|
|
|
|
|
1316
|
|
|
|
|
|
|
=over |
1317
|
|
|
|
|
|
|
|
1318
|
|
|
|
|
|
|
B<_set_min_row> |
1319
|
|
|
|
|
|
|
|
1320
|
|
|
|
|
|
|
=over |
1321
|
|
|
|
|
|
|
|
1322
|
|
|
|
|
|
|
B<Definition:> sets the attribute value |
1323
|
|
|
|
|
|
|
|
1324
|
|
|
|
|
|
|
=back |
1325
|
|
|
|
|
|
|
|
1326
|
|
|
|
|
|
|
B<_min_row> |
1327
|
|
|
|
|
|
|
|
1328
|
|
|
|
|
|
|
=over |
1329
|
|
|
|
|
|
|
|
1330
|
|
|
|
|
|
|
B<Definition:> returns the attribute value |
1331
|
|
|
|
|
|
|
|
1332
|
|
|
|
|
|
|
=back |
1333
|
|
|
|
|
|
|
|
1334
|
|
|
|
|
|
|
B<has_min_row> |
1335
|
|
|
|
|
|
|
|
1336
|
|
|
|
|
|
|
=over |
1337
|
|
|
|
|
|
|
|
1338
|
|
|
|
|
|
|
B<Definition:> attribute predicate |
1339
|
|
|
|
|
|
|
|
1340
|
|
|
|
|
|
|
=back |
1341
|
|
|
|
|
|
|
|
1342
|
|
|
|
|
|
|
=back |
1343
|
|
|
|
|
|
|
|
1344
|
|
|
|
|
|
|
=back |
1345
|
|
|
|
|
|
|
|
1346
|
|
|
|
|
|
|
=head3 _sheet_max_col |
1347
|
|
|
|
|
|
|
|
1348
|
|
|
|
|
|
|
=over |
1349
|
|
|
|
|
|
|
|
1350
|
|
|
|
|
|
|
B<Definition:> This is the maximum column in the sheet with data or formatting. For this |
1351
|
|
|
|
|
|
|
module it is pulled from the xml file at worksheet/dimension:ref = "upperleft:lowerright" |
1352
|
|
|
|
|
|
|
|
1353
|
|
|
|
|
|
|
B<Range:> an integer |
1354
|
|
|
|
|
|
|
|
1355
|
|
|
|
|
|
|
B<attribute methods> Methods provided to adjust this attribute |
1356
|
|
|
|
|
|
|
|
1357
|
|
|
|
|
|
|
=over |
1358
|
|
|
|
|
|
|
|
1359
|
|
|
|
|
|
|
B<_set_max_col> |
1360
|
|
|
|
|
|
|
|
1361
|
|
|
|
|
|
|
=over |
1362
|
|
|
|
|
|
|
|
1363
|
|
|
|
|
|
|
B<Definition:> sets the attribute value |
1364
|
|
|
|
|
|
|
|
1365
|
|
|
|
|
|
|
=back |
1366
|
|
|
|
|
|
|
|
1367
|
|
|
|
|
|
|
B<_max_col> |
1368
|
|
|
|
|
|
|
|
1369
|
|
|
|
|
|
|
=over |
1370
|
|
|
|
|
|
|
|
1371
|
|
|
|
|
|
|
B<Definition:> returns the attribute value |
1372
|
|
|
|
|
|
|
|
1373
|
|
|
|
|
|
|
=back |
1374
|
|
|
|
|
|
|
|
1375
|
|
|
|
|
|
|
B<has_max_col> |
1376
|
|
|
|
|
|
|
|
1377
|
|
|
|
|
|
|
=over |
1378
|
|
|
|
|
|
|
|
1379
|
|
|
|
|
|
|
B<Definition:> attribute predicate |
1380
|
|
|
|
|
|
|
|
1381
|
|
|
|
|
|
|
=back |
1382
|
|
|
|
|
|
|
|
1383
|
|
|
|
|
|
|
=back |
1384
|
|
|
|
|
|
|
|
1385
|
|
|
|
|
|
|
=back |
1386
|
|
|
|
|
|
|
|
1387
|
|
|
|
|
|
|
=head3 _sheet_max_row |
1388
|
|
|
|
|
|
|
|
1389
|
|
|
|
|
|
|
=over |
1390
|
|
|
|
|
|
|
|
1391
|
|
|
|
|
|
|
B<Definition:> This is the maximum row in the sheet with data or formatting. For this |
1392
|
|
|
|
|
|
|
module it is pulled from the xml file at worksheet/dimension:ref = "upperleft:lowerright" |
1393
|
|
|
|
|
|
|
|
1394
|
|
|
|
|
|
|
B<Range:> an integer |
1395
|
|
|
|
|
|
|
|
1396
|
|
|
|
|
|
|
B<attribute methods> Methods provided to adjust this attribute |
1397
|
|
|
|
|
|
|
|
1398
|
|
|
|
|
|
|
=over |
1399
|
|
|
|
|
|
|
|
1400
|
|
|
|
|
|
|
B<_set_max_row> |
1401
|
|
|
|
|
|
|
|
1402
|
|
|
|
|
|
|
=over |
1403
|
|
|
|
|
|
|
|
1404
|
|
|
|
|
|
|
B<Definition:> sets the attribute value |
1405
|
|
|
|
|
|
|
|
1406
|
|
|
|
|
|
|
=back |
1407
|
|
|
|
|
|
|
|
1408
|
|
|
|
|
|
|
B<_max_row> |
1409
|
|
|
|
|
|
|
|
1410
|
|
|
|
|
|
|
=over |
1411
|
|
|
|
|
|
|
|
1412
|
|
|
|
|
|
|
B<Definition:> returns the attribute value |
1413
|
|
|
|
|
|
|
|
1414
|
|
|
|
|
|
|
=back |
1415
|
|
|
|
|
|
|
|
1416
|
|
|
|
|
|
|
B<has_max_row> |
1417
|
|
|
|
|
|
|
|
1418
|
|
|
|
|
|
|
=over |
1419
|
|
|
|
|
|
|
|
1420
|
|
|
|
|
|
|
B<Definition:> attribute predicate |
1421
|
|
|
|
|
|
|
|
1422
|
|
|
|
|
|
|
=back |
1423
|
|
|
|
|
|
|
|
1424
|
|
|
|
|
|
|
=back |
1425
|
|
|
|
|
|
|
|
1426
|
|
|
|
|
|
|
=back |
1427
|
|
|
|
|
|
|
|
1428
|
|
|
|
|
|
|
=head3 _merge_map |
1429
|
|
|
|
|
|
|
|
1430
|
|
|
|
|
|
|
=over |
1431
|
|
|
|
|
|
|
|
1432
|
|
|
|
|
|
|
B<Definition:> This is an array ref of array refs where the first level represents rows |
1433
|
|
|
|
|
|
|
and the second level of array represents cells. If a cell is merged then the merge span |
1434
|
|
|
|
|
|
|
is stored in the row sub array position. This means the same span is stored in multiple |
1435
|
|
|
|
|
|
|
positions. The data is stored in the Excel convention of count from 1 so the first position |
1436
|
|
|
|
|
|
|
in both levels of the array are essentially placeholders. The data is extracted from the |
1437
|
|
|
|
|
|
|
merge section of the worksheet at worksheet/mergeCells. That array is read and converted |
1438
|
|
|
|
|
|
|
into this format for reading by this module when it first opens the worksheet. |
1439
|
|
|
|
|
|
|
|
1440
|
|
|
|
|
|
|
B<Range:> an array ref |
1441
|
|
|
|
|
|
|
|
1442
|
|
|
|
|
|
|
B<attribute methods> Methods provided to adjust this attribute |
1443
|
|
|
|
|
|
|
|
1444
|
|
|
|
|
|
|
=over |
1445
|
|
|
|
|
|
|
|
1446
|
|
|
|
|
|
|
B<_set_merge_map> |
1447
|
|
|
|
|
|
|
|
1448
|
|
|
|
|
|
|
=over |
1449
|
|
|
|
|
|
|
|
1450
|
|
|
|
|
|
|
B<Definition:> sets the attribute value |
1451
|
|
|
|
|
|
|
|
1452
|
|
|
|
|
|
|
=back |
1453
|
|
|
|
|
|
|
|
1454
|
|
|
|
|
|
|
=back |
1455
|
|
|
|
|
|
|
|
1456
|
|
|
|
|
|
|
B<_get_merge_map> |
1457
|
|
|
|
|
|
|
|
1458
|
|
|
|
|
|
|
=over |
1459
|
|
|
|
|
|
|
|
1460
|
|
|
|
|
|
|
B<Definition:> returns the attribute array of arrays |
1461
|
|
|
|
|
|
|
|
1462
|
|
|
|
|
|
|
=back |
1463
|
|
|
|
|
|
|
|
1464
|
|
|
|
|
|
|
=back |
1465
|
|
|
|
|
|
|
|
1466
|
|
|
|
|
|
|
B<delegated methods> This attribute uses the native trait 'Array' |
1467
|
|
|
|
|
|
|
|
1468
|
|
|
|
|
|
|
=over |
1469
|
|
|
|
|
|
|
|
1470
|
|
|
|
|
|
|
B<_get_row_merge_map( $int )> delgated from 'Array' 'get' |
1471
|
|
|
|
|
|
|
|
1472
|
|
|
|
|
|
|
=over |
1473
|
|
|
|
|
|
|
|
1474
|
|
|
|
|
|
|
B<Definition:> returns the sub array ref representing any merges for that |
1475
|
|
|
|
|
|
|
row. If no merges are available for that row it returns undef. |
1476
|
|
|
|
|
|
|
|
1477
|
|
|
|
|
|
|
=back |
1478
|
|
|
|
|
|
|
|
1479
|
|
|
|
|
|
|
=back |
1480
|
|
|
|
|
|
|
|
1481
|
|
|
|
|
|
|
=head3 _column_formats |
1482
|
|
|
|
|
|
|
|
1483
|
|
|
|
|
|
|
=over |
1484
|
|
|
|
|
|
|
|
1485
|
|
|
|
|
|
|
B<Definition:> In order to (eventually) show all column formats that also affect individual |
1486
|
|
|
|
|
|
|
cells the column based formats are read from the metada when the worksheet is opened. They |
1487
|
|
|
|
|
|
|
are stored here for use although for now they are mostly used to determine the hidden state of |
1488
|
|
|
|
|
|
|
the column. The formats are stored in the array by count from 1 column position. |
1489
|
|
|
|
|
|
|
|
1490
|
|
|
|
|
|
|
B<Range:> an array ref |
1491
|
|
|
|
|
|
|
|
1492
|
|
|
|
|
|
|
B<attribute methods> Methods provided to adjust this attribute |
1493
|
|
|
|
|
|
|
|
1494
|
|
|
|
|
|
|
=over |
1495
|
|
|
|
|
|
|
|
1496
|
|
|
|
|
|
|
B<_set_set_column_formats> |
1497
|
|
|
|
|
|
|
|
1498
|
|
|
|
|
|
|
=over |
1499
|
|
|
|
|
|
|
|
1500
|
|
|
|
|
|
|
B<Definition:> sets the attribute value |
1501
|
|
|
|
|
|
|
|
1502
|
|
|
|
|
|
|
=back |
1503
|
|
|
|
|
|
|
|
1504
|
|
|
|
|
|
|
=back |
1505
|
|
|
|
|
|
|
|
1506
|
|
|
|
|
|
|
B<_get_get_column_formats> |
1507
|
|
|
|
|
|
|
|
1508
|
|
|
|
|
|
|
=over |
1509
|
|
|
|
|
|
|
|
1510
|
|
|
|
|
|
|
B<Definition:> returns the attribute array |
1511
|
|
|
|
|
|
|
|
1512
|
|
|
|
|
|
|
=back |
1513
|
|
|
|
|
|
|
|
1514
|
|
|
|
|
|
|
=back |
1515
|
|
|
|
|
|
|
|
1516
|
|
|
|
|
|
|
B<delegated methods> This attribute uses the native trait 'Array' |
1517
|
|
|
|
|
|
|
|
1518
|
|
|
|
|
|
|
=over |
1519
|
|
|
|
|
|
|
|
1520
|
|
|
|
|
|
|
B<_get_custom_column_data( $int )> delgated from 'Array' 'get' |
1521
|
|
|
|
|
|
|
|
1522
|
|
|
|
|
|
|
=over |
1523
|
|
|
|
|
|
|
|
1524
|
|
|
|
|
|
|
B<Definition:> returns the sub hash ref representing any formatting |
1525
|
|
|
|
|
|
|
for that column. If no custom formatting is available it returns undef. |
1526
|
|
|
|
|
|
|
|
1527
|
|
|
|
|
|
|
=back |
1528
|
|
|
|
|
|
|
|
1529
|
|
|
|
|
|
|
=back |
1530
|
|
|
|
|
|
|
|
1531
|
|
|
|
|
|
|
=head3 _new_row_inst |
1532
|
|
|
|
|
|
|
|
1533
|
|
|
|
|
|
|
=over |
1534
|
|
|
|
|
|
|
|
1535
|
|
|
|
|
|
|
B<Definition:> This is the current read row instance or undef for the end of the sheet |
1536
|
|
|
|
|
|
|
read. |
1537
|
|
|
|
|
|
|
|
1538
|
|
|
|
|
|
|
B<Range:> isa => InstanceOf[ L<Spreadsheet::XLSX::Reader::LibXML::Row> ] |
1539
|
|
|
|
|
|
|
|
1540
|
|
|
|
|
|
|
B<attribute methods> Methods provided to adjust this attribute |
1541
|
|
|
|
|
|
|
|
1542
|
|
|
|
|
|
|
=over |
1543
|
|
|
|
|
|
|
|
1544
|
|
|
|
|
|
|
B<_set_new_row_inst> |
1545
|
|
|
|
|
|
|
|
1546
|
|
|
|
|
|
|
=over |
1547
|
|
|
|
|
|
|
|
1548
|
|
|
|
|
|
|
B<Definition:> sets the attribute value |
1549
|
|
|
|
|
|
|
|
1550
|
|
|
|
|
|
|
=back |
1551
|
|
|
|
|
|
|
|
1552
|
|
|
|
|
|
|
B<_get_new_row_inst> |
1553
|
|
|
|
|
|
|
|
1554
|
|
|
|
|
|
|
=over |
1555
|
|
|
|
|
|
|
|
1556
|
|
|
|
|
|
|
B<Definition:> returns the attribute |
1557
|
|
|
|
|
|
|
|
1558
|
|
|
|
|
|
|
=back |
1559
|
|
|
|
|
|
|
|
1560
|
|
|
|
|
|
|
B<_clear_new_row_inst> |
1561
|
|
|
|
|
|
|
|
1562
|
|
|
|
|
|
|
=over |
1563
|
|
|
|
|
|
|
|
1564
|
|
|
|
|
|
|
B<Definition:> clears the attribute |
1565
|
|
|
|
|
|
|
|
1566
|
|
|
|
|
|
|
=back |
1567
|
|
|
|
|
|
|
|
1568
|
|
|
|
|
|
|
B<_has_new_row_inst> |
1569
|
|
|
|
|
|
|
|
1570
|
|
|
|
|
|
|
=over |
1571
|
|
|
|
|
|
|
|
1572
|
|
|
|
|
|
|
B<Definition:> predicate for the attribute |
1573
|
|
|
|
|
|
|
|
1574
|
|
|
|
|
|
|
=back |
1575
|
|
|
|
|
|
|
|
1576
|
|
|
|
|
|
|
B<delegated methods> from L<Spreadsheet::XLSX::Reader::LibXML::Row> |
1577
|
|
|
|
|
|
|
|
1578
|
|
|
|
|
|
|
=over |
1579
|
|
|
|
|
|
|
|
1580
|
|
|
|
|
|
|
B<_get_new_row_number> = L<Spreadsheet::XLSX::Reader::LibXML::Row/get_row_number> |
1581
|
|
|
|
|
|
|
|
1582
|
|
|
|
|
|
|
B<_is_new_row_hidden> = L<Spreadsheet::XLSX::Reader::LibXML::Row/is_row_hidden> |
1583
|
|
|
|
|
|
|
|
1584
|
|
|
|
|
|
|
B<_get_new_row_formats> = L<Spreadsheet::XLSX::Reader::LibXML::Row/get_row_format> |
1585
|
|
|
|
|
|
|
|
1586
|
|
|
|
|
|
|
=over |
1587
|
|
|
|
|
|
|
|
1588
|
|
|
|
|
|
|
pass the desired format key |
1589
|
|
|
|
|
|
|
|
1590
|
|
|
|
|
|
|
=back |
1591
|
|
|
|
|
|
|
|
1592
|
|
|
|
|
|
|
B<_get_new_column> = L<Spreadsheet::XLSX::Reader::LibXML::Row/get_the_column( $column )> |
1593
|
|
|
|
|
|
|
|
1594
|
|
|
|
|
|
|
=over |
1595
|
|
|
|
|
|
|
|
1596
|
|
|
|
|
|
|
pass a column number (no next default) returns (cell|undef|EOR) |
1597
|
|
|
|
|
|
|
|
1598
|
|
|
|
|
|
|
=back |
1599
|
|
|
|
|
|
|
|
1600
|
|
|
|
|
|
|
B<_get_new_next_value> = L<Spreadsheet::XLSX::Reader::LibXML::Row/get_the_next_value_position> |
1601
|
|
|
|
|
|
|
|
1602
|
|
|
|
|
|
|
=over |
1603
|
|
|
|
|
|
|
|
1604
|
|
|
|
|
|
|
pass nothing returns next (cell|EOR) |
1605
|
|
|
|
|
|
|
|
1606
|
|
|
|
|
|
|
=back |
1607
|
|
|
|
|
|
|
|
1608
|
|
|
|
|
|
|
B<_get_new_last_value_col> = L<Spreadsheet::XLSX::Reader::LibXML::Row/get_last_value_column> |
1609
|
|
|
|
|
|
|
|
1610
|
|
|
|
|
|
|
B<_get_new_row_list> = L<Spreadsheet::XLSX::Reader::LibXML::Row/get_row_all> |
1611
|
|
|
|
|
|
|
|
1612
|
|
|
|
|
|
|
B<_get_new_row_end> = L<Spreadsheet::XLSX::Reader::LibXML::Row/get_row_endl> |
1613
|
|
|
|
|
|
|
|
1614
|
|
|
|
|
|
|
=back |
1615
|
|
|
|
|
|
|
|
1616
|
|
|
|
|
|
|
=back |
1617
|
|
|
|
|
|
|
|
1618
|
|
|
|
|
|
|
=back |
1619
|
|
|
|
|
|
|
|
1620
|
|
|
|
|
|
|
=head3 _row_hidden_states |
1621
|
|
|
|
|
|
|
|
1622
|
|
|
|
|
|
|
=over |
1623
|
|
|
|
|
|
|
|
1624
|
|
|
|
|
|
|
B<Definition:> As the worksheet is parsed it will store the hidden state for |
1625
|
|
|
|
|
|
|
the row in this attribute when each row is read. This is the only worksheet |
1626
|
|
|
|
|
|
|
level caching done. B<It will not test whether the requested row hidden state |
1627
|
|
|
|
|
|
|
has been read when accessing this data.> If a method call a row past the |
1628
|
|
|
|
|
|
|
current max parsed row it will return 0 (unhidden). |
1629
|
|
|
|
|
|
|
|
1630
|
|
|
|
|
|
|
B<Range:> an array ref of Boolean values |
1631
|
|
|
|
|
|
|
|
1632
|
|
|
|
|
|
|
B<delegated methods> This attribute uses the native trait 'Array' |
1633
|
|
|
|
|
|
|
|
1634
|
|
|
|
|
|
|
=over |
1635
|
|
|
|
|
|
|
|
1636
|
|
|
|
|
|
|
B<_set_row_hidden( $int )> delgated from 'Array' 'set' |
1637
|
|
|
|
|
|
|
|
1638
|
|
|
|
|
|
|
=over |
1639
|
|
|
|
|
|
|
|
1640
|
|
|
|
|
|
|
B<Definition:> sets the hidden state for that $int (row) counting from 1. |
1641
|
|
|
|
|
|
|
|
1642
|
|
|
|
|
|
|
=back |
1643
|
|
|
|
|
|
|
|
1644
|
|
|
|
|
|
|
B<_get_row_hidden( $int )> delgated from 'Array' 'get' |
1645
|
|
|
|
|
|
|
|
1646
|
|
|
|
|
|
|
=over |
1647
|
|
|
|
|
|
|
|
1648
|
|
|
|
|
|
|
B<Definition:> returns the known hidden state of the row. |
1649
|
|
|
|
|
|
|
|
1650
|
|
|
|
|
|
|
=back |
1651
|
|
|
|
|
|
|
|
1652
|
|
|
|
|
|
|
=back |
1653
|
|
|
|
|
|
|
|
1654
|
|
|
|
|
|
|
=back |
1655
|
|
|
|
|
|
|
|
1656
|
|
|
|
|
|
|
=head2 Methods |
1657
|
|
|
|
|
|
|
|
1658
|
|
|
|
|
|
|
These are the methods provided by this class for use within the package but are not intended |
1659
|
|
|
|
|
|
|
to be used by the end user. Other private methods not listed here are used in the module but |
1660
|
|
|
|
|
|
|
not used by the package. If the private method is listed here then replacement of this module |
1661
|
|
|
|
|
|
|
either requires replacing them or rewriting all the associated connecting roles and classes. |
1662
|
|
|
|
|
|
|
|
1663
|
|
|
|
|
|
|
=head3 _load_unique_bits |
1664
|
|
|
|
|
|
|
|
1665
|
|
|
|
|
|
|
=over |
1666
|
|
|
|
|
|
|
|
1667
|
|
|
|
|
|
|
B<Definition:> This is called by L<Spreadsheet::XLSX::Reader::LibXML::XMLReader> when the file is |
1668
|
|
|
|
|
|
|
loaded for the first time so that file specific metadata can be collected. |
1669
|
|
|
|
|
|
|
|
1670
|
|
|
|
|
|
|
B<Accepts:> nothing |
1671
|
|
|
|
|
|
|
|
1672
|
|
|
|
|
|
|
B<Returns:> nothing |
1673
|
|
|
|
|
|
|
|
1674
|
|
|
|
|
|
|
=back |
1675
|
|
|
|
|
|
|
|
1676
|
|
|
|
|
|
|
=head3 _get_next_value_cell |
1677
|
|
|
|
|
|
|
|
1678
|
|
|
|
|
|
|
=over |
1679
|
|
|
|
|
|
|
|
1680
|
|
|
|
|
|
|
B<Definition:> This returns the worksheet file hash ref representation of the xml stored for the |
1681
|
|
|
|
|
|
|
'next' value cell. A cell is determined to have value based on the attribute |
1682
|
|
|
|
|
|
|
L<Spreadsheet::XLSX::Reader::LibXML/values_only>. Next is affected by the attribute |
1683
|
|
|
|
|
|
|
L<Spreadsheet::XLSX::Reader::LibXML/empty_is_end>. This method never returns an 'EOR' flag. |
1684
|
|
|
|
|
|
|
It just wraps automatically. This does return values from the shared strings file integrated but |
1685
|
|
|
|
|
|
|
not values from the Styles file integrated. |
1686
|
|
|
|
|
|
|
|
1687
|
|
|
|
|
|
|
B<Accepts:> nothing |
1688
|
|
|
|
|
|
|
|
1689
|
|
|
|
|
|
|
B<Returns:> a hashref of key value pairs |
1690
|
|
|
|
|
|
|
|
1691
|
|
|
|
|
|
|
=back |
1692
|
|
|
|
|
|
|
|
1693
|
|
|
|
|
|
|
=head3 _get_col_row( $col, $row ) |
1694
|
|
|
|
|
|
|
|
1695
|
|
|
|
|
|
|
=over |
1696
|
|
|
|
|
|
|
|
1697
|
|
|
|
|
|
|
B<Definition:> This is the way to return the information about a specific position in the worksheet. |
1698
|
|
|
|
|
|
|
Since this is a private method it requires its inputs to be in the 'count from one' index. |
1699
|
|
|
|
|
|
|
|
1700
|
|
|
|
|
|
|
B<Accepts:> ( $column, $row ) - both required in that order |
1701
|
|
|
|
|
|
|
|
1702
|
|
|
|
|
|
|
B<Returns:> whatever is in that worksheet position as a hashref |
1703
|
|
|
|
|
|
|
|
1704
|
|
|
|
|
|
|
=back |
1705
|
|
|
|
|
|
|
|
1706
|
|
|
|
|
|
|
=head3 _get_row_all( $row ) |
1707
|
|
|
|
|
|
|
|
1708
|
|
|
|
|
|
|
=over |
1709
|
|
|
|
|
|
|
|
1710
|
|
|
|
|
|
|
B<Definition:> This is returns an array ref of each of the values in the row placed in their 'count |
1711
|
|
|
|
|
|
|
from one' position. If the row is empty but it is not the end of the sheet then this will return an |
1712
|
|
|
|
|
|
|
empty array ref. |
1713
|
|
|
|
|
|
|
|
1714
|
|
|
|
|
|
|
B<Accepts:> ( $row ) - required |
1715
|
|
|
|
|
|
|
|
1716
|
|
|
|
|
|
|
B<Returns:> an array ref |
1717
|
|
|
|
|
|
|
|
1718
|
|
|
|
|
|
|
=back |
1719
|
|
|
|
|
|
|
|
1720
|
|
|
|
|
|
|
=head3 _is_column_hidden( @query_list ) |
1721
|
|
|
|
|
|
|
|
1722
|
|
|
|
|
|
|
=over |
1723
|
|
|
|
|
|
|
|
1724
|
|
|
|
|
|
|
B<Definition:> This is returns a list of hidden states for each column integer in the @query_list |
1725
|
|
|
|
|
|
|
it will generally return n array ref of each of the values in the row placed in their 'count |
1726
|
|
|
|
|
|
|
from one' position. If the row is empty but it is not the end of the sheet then this will return an |
1727
|
|
|
|
|
|
|
empty array ref. |
1728
|
|
|
|
|
|
|
|
1729
|
|
|
|
|
|
|
B<Accepts:> ( @query_list ) - integers in count from 1 representing requested columns |
1730
|
|
|
|
|
|
|
|
1731
|
|
|
|
|
|
|
B<Returns (when wantarray):> a list of hidden states as follows; 1 => hidden, 0 => known to be unhidden, |
1732
|
|
|
|
|
|
|
undef => unknown state (usually this represents columns before min_col or after max_col or at least past |
1733
|
|
|
|
|
|
|
the last stored value in the column) |
1734
|
|
|
|
|
|
|
|
1735
|
|
|
|
|
|
|
=back |
1736
|
|
|
|
|
|
|
|
1737
|
|
|
|
|
|
|
=head1 SUPPORT |
1738
|
|
|
|
|
|
|
|
1739
|
|
|
|
|
|
|
=over |
1740
|
|
|
|
|
|
|
|
1741
|
|
|
|
|
|
|
L<github Spreadsheet::XLSX::Reader::LibXML/issues |
1742
|
|
|
|
|
|
|
|https://github.com/jandrew/Spreadsheet-XLSX-Reader-LibXML/issues> |
1743
|
|
|
|
|
|
|
|
1744
|
|
|
|
|
|
|
=back |
1745
|
|
|
|
|
|
|
|
1746
|
|
|
|
|
|
|
=head1 TODO |
1747
|
|
|
|
|
|
|
|
1748
|
|
|
|
|
|
|
=over |
1749
|
|
|
|
|
|
|
|
1750
|
|
|
|
|
|
|
B<1.> Nothing L<yet|/SUPPORT> |
1751
|
|
|
|
|
|
|
|
1752
|
|
|
|
|
|
|
=back |
1753
|
|
|
|
|
|
|
|
1754
|
|
|
|
|
|
|
=head1 AUTHOR |
1755
|
|
|
|
|
|
|
|
1756
|
|
|
|
|
|
|
=over |
1757
|
|
|
|
|
|
|
|
1758
|
|
|
|
|
|
|
=item Jed Lund |
1759
|
|
|
|
|
|
|
|
1760
|
|
|
|
|
|
|
=item jandrew@cpan.org |
1761
|
|
|
|
|
|
|
|
1762
|
|
|
|
|
|
|
=back |
1763
|
|
|
|
|
|
|
|
1764
|
|
|
|
|
|
|
=head1 COPYRIGHT |
1765
|
|
|
|
|
|
|
|
1766
|
|
|
|
|
|
|
This program is free software; you can redistribute |
1767
|
|
|
|
|
|
|
it and/or modify it under the same terms as Perl itself. |
1768
|
|
|
|
|
|
|
|
1769
|
|
|
|
|
|
|
The full text of the license can be found in the |
1770
|
|
|
|
|
|
|
LICENSE file included with this module. |
1771
|
|
|
|
|
|
|
|
1772
|
|
|
|
|
|
|
This software is copyrighted (c) 2014, 2015 by Jed Lund |
1773
|
|
|
|
|
|
|
|
1774
|
|
|
|
|
|
|
=head1 DEPENDENCIES |
1775
|
|
|
|
|
|
|
|
1776
|
|
|
|
|
|
|
=over |
1777
|
|
|
|
|
|
|
|
1778
|
|
|
|
|
|
|
L<version> |
1779
|
|
|
|
|
|
|
|
1780
|
|
|
|
|
|
|
L<perl 5.010|perl/5.10.0> |
1781
|
|
|
|
|
|
|
|
1782
|
|
|
|
|
|
|
L<Moose> |
1783
|
|
|
|
|
|
|
|
1784
|
|
|
|
|
|
|
L<MooseX::StrictConstructor> |
1785
|
|
|
|
|
|
|
|
1786
|
|
|
|
|
|
|
L<MooseX::HasDefaults::RO> |
1787
|
|
|
|
|
|
|
|
1788
|
|
|
|
|
|
|
L<Clone> - clone |
1789
|
|
|
|
|
|
|
|
1790
|
|
|
|
|
|
|
L<Carp> - confess |
1791
|
|
|
|
|
|
|
|
1792
|
|
|
|
|
|
|
L<Type::Tiny> - 1.000 |
1793
|
|
|
|
|
|
|
|
1794
|
|
|
|
|
|
|
L<MooseX::ShortCut::BuildInstance> - build_instance should_re_use_classes |
1795
|
|
|
|
|
|
|
|
1796
|
|
|
|
|
|
|
L<Spreadsheet::XLSX::Reader::LibXML> |
1797
|
|
|
|
|
|
|
|
1798
|
|
|
|
|
|
|
L<Spreadsheet::XLSX::Reader::LibXML::XMLReader> |
1799
|
|
|
|
|
|
|
|
1800
|
|
|
|
|
|
|
L<Spreadsheet::XLSX::Reader::LibXML::Row> |
1801
|
|
|
|
|
|
|
|
1802
|
|
|
|
|
|
|
L<Spreadsheet::XLSX::Reader::LibXML::CellToColumnRow> |
1803
|
|
|
|
|
|
|
|
1804
|
|
|
|
|
|
|
L<Spreadsheet::XLSX::Reader::LibXML::XMLToPerlData> |
1805
|
|
|
|
|
|
|
|
1806
|
|
|
|
|
|
|
=back |
1807
|
|
|
|
|
|
|
|
1808
|
|
|
|
|
|
|
=head1 SEE ALSO |
1809
|
|
|
|
|
|
|
|
1810
|
|
|
|
|
|
|
=over |
1811
|
|
|
|
|
|
|
|
1812
|
|
|
|
|
|
|
L<Log::Shiras|https://github.com/jandrew/Log-Shiras> |
1813
|
|
|
|
|
|
|
|
1814
|
|
|
|
|
|
|
=over |
1815
|
|
|
|
|
|
|
|
1816
|
|
|
|
|
|
|
All lines in this package that use Log::Shiras are commented out |
1817
|
|
|
|
|
|
|
|
1818
|
|
|
|
|
|
|
=back |
1819
|
|
|
|
|
|
|
|
1820
|
|
|
|
|
|
|
=back |
1821
|
|
|
|
|
|
|
|
1822
|
|
|
|
|
|
|
=cut |
1823
|
|
|
|
|
|
|
|
1824
|
|
|
|
|
|
|
#########1 Documentation End 3#########4#########5#########6#########7#########8#########9 |