File Coverage

lib/Spreadsheet/XLSX/Reader/LibXML/XMLReader/WorksheetToRow.pm
Criterion Covered Total %
statement 38 351 10.8
branch 0 206 0.0
condition 0 117 0.0
subroutine 13 22 59.0
pod n/a
total 51 696 7.3


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