=pod

=encoding utf-8

=head1 NAME

Spreadsheet::XLSX::Reader::LibXML::Worksheet - Read xlsx worksheets with LibXML

=head1 SYNOPSIS

See the SYNOPSIS in the L<Workbook class|Spreadsheet::XLSX::Reader::LibXML/SYNOPSIS>

=head1 DESCRIPTION

The worksheet class provided by this package is an amalgam of a class, a few roles, 
and a few traits aggregated at run time based on attribute settings from the workbook 
level class.  This documentation shows the ways to use the resulting instance.  First, 
it is best to generate a worksheet instance from the workbook class using one of the 
various L<worksheet|Spreadsheet::XLSX::Reader::LibXML/worksheet( $name )> methods.  
Once you have done that there are several ways to step through the data inside of each 
worksheet and access information from the identified location in the sheet of the .xlsx 
file.


=head2 Extending the worksheet class

In general since this is a L<Moose> package I tried to architect it as extensibly as 
possible.  One advantage of that is the ability to delay the building of the final 
worksheet class until  runtime to allow for the needed roles and traits to be aggregated 
into different base classes so that different file types can be read and different parsing 
methods can be implemented based on runtime decisions.  On the other hand since the 
worksheet class is built at runtime and the eventual class guts are based on logic from 
runtime inputs it is difficult to extend this class at runtime.  With that said, the 
architecture should allow you to L<fork|https://help.github.com/articles/fork-a-repo/> 
the L<package on github|https://github.com/jandrew/Spreadsheet-XLSX-Reader-LibXML> and 
build a module for just the behaviour that you wish to change rather that doing a full 
rewrite.  The file t/Spreadsheet/XLSX/Reader/LibXML/10-get_cell.t represents a good 
'under the hood' example of the way all the elements are integrated into the larger 
worksheet class as a whole.    If you are feeling extra generous and the update you 
create can co-exist with this package please send a pull request on github. 

=head2 The way to set what type of information is returned

There is a an attribute set in the workbook instance called L<group_return_type
|Spreadsheet::XLSX::Reader::LibXML/group_return_type>.  Setting this attribute will return 
either a full L<Spreadsheet::XLSX::Reader::LibXML::Cell> instance, just the unformatted 
value, or the formatted value.  For more details on the data available in the Cell instance 
read the documentation for the L<Cell|Spreadsheet::XLSX::Reader::LibXML::Cell> instance.

=head2 Methods to access data from the sheet

These are the various functions that are available (independent of sheet parser type) to 
select which cell(s) to read.  When allowed the requested row and column numbers are 
interpreted using the attribute L<Spreadsheet::XLSX::Reader::LibXML/count_from_zero>.  
all the methods are object methods performed on the worksheet.

B<Example:>

	my $cell_data = $worksheet->get_cell( $row, $column );

=head3 get_cell( $row, $column )

=over

B<Definition:> Indicate both the requested row and requested column and the information for 
that position will be returned.  Both $row and $column are required

B<Accepts:> the list ( $row, $column ) both required

B<Returns:> see the attribute L<Spreadsheet::XLSX::Reader::LibXML/group_return_type> for 
details on what is returned

=back

=head3 get_next_value

=over

B<Definition:> Reading left to right and top to bottom this will return the next cell with 
a value.  This actually includes cells with no value but some unique formatting such as 
cells that have been merged with other cells.

B<Accepts:> nothing

B<Returns:> see the attribute L<Spreadsheet::XLSX::Reader::LibXML/group_return_type> for 
details on what is returned

=back

=head3 fetchrow_arrayref( $row )

=over

B<Definition:> In an homage to L<DBI> I included this function to return an array ref of 
the cells or values in the requested $row.  If no row is requested this returns the 'next' 
row.  In the array ref any empty and non unique cell will show as 'undef'.

B<Accepts:> undef = next|$row = a row integer indicating the desired row

B<Returns:> an array ref of all possible column positions in that row with data filled in 
per the attribute L<Spreadsheet::XLSX::Reader::LibXML/group_return_type>.

=back

=head3 fetchrow_array( $row )

=over

B<Definition:> This function is just like L<fetchrow_arrayref|/fetchrow_arrayref( $row )> 
except it returns an array instead of an array ref

B<Accepts:> undef = next|$row = a row integer indicating the desired row

B<Returns:> an array ref of all possible column positions in that row with data filled in 
per the attribute L<Spreadsheet::XLSX::Reader::LibXML/group_return_type>.

=back

=head3 set_headers( @header_row_list )

=over

B<Definition:> This function is used to set headers used in the function 
L<fetchrow_hashref|/fetchrow_hashref( $row )>.  It accepts a list of row numbers that 
will be collated into a set of headers used to build the hashref for each row.
The header rows are coallated in sequence with the first number in the list taking 
precedence.  The list is also used to set the lowest row of the headers in the table.  
All rows at that level and higher will be considered out of the table and will return 
'undef' while setting the error instance.  If some of the columns do not have values 
then the instance will auto generate unique headers for each empty header column to 
fill out the header ref.  Please pay attention to the fact that this method is also 
affected by the attribute L<Spreadsheet::XLSX::Reader::LibXML/group_return_type> with 
one exception.  If that attribute is set to 'instance' the headers will be composed of 
the converted 'value's of each cell rather than either the instance pointer string or 
the 'unformatted' value.

B<Accepts:> a list of row numbers

B<Returns:> an array ref of the built headers for review

=back

=head3 fetchrow_hashref( $row )

=over

B<Definition:> This function is used to return a hashref representing the data in the 
specified row.  If no $row value is passed it will return the 'next' row of data.  A call 
to this function without L<setting|/set_headers( @header_row_list )> the headers first 
will return 'undef' and set the error instance.

B<Accepts:> a target $row number for return values or undef meaning 'next'

B<Returns:> a hash ref of the values for that row.  This function ignores the attribute 
L<group_return_type|Spreadsheet::XLSX::Reader::LibXML/group_return_type> when it is 
set to 'instance' and returns 'value's instead.  See also the attributes 
L<min_header_col|/min_header_col> and L<max_header_col|/max_header_col> to pare the 
start and end columns of the returned hash ref.

=back

=head3 min_row

=over

B<Definition:> This is the minimum row determined when the sheet is opened.  This 
value is affected by the workbook attributes 
L<from_the_edge|Spreadsheet::XLSX::Reader::LibXML/from_the_edge>, and 
L<count_from_zero|Spreadsheet::XLSX::Reader::LibXML/count_from_zero>

B<Accepts:> nothing

B<Returns:> an integer

=back

=head3 has_min_row

=over

B<Definition:> The L<predicate|Moose::Manual::Attributes/Predicate and clearer methods> 
of min_row

=back

=head3 max_row

=over

B<Definition:> This is the maximum row with data listed in the sheet.  This value 
is affected by the workbook attribute 
L<count_from_zero|Spreadsheet::XLSX::Reader::LibXML/count_from_zero>

B<Accepts:> nothing

B<Returns:> an integer

=back

=head3 has_max_row

=over

B<Definition:> The L<predicate|Moose::Manual::Attributes/Predicate and clearer methods> 
of max_row

=back

=head3 min_col

=over

B<Definition:> This is the minimum column with data listed in the sheet.  This value 
is affected by the workbook attributes 
L<from_the_edge|Spreadsheet::XLSX::Reader::LibXML/from_the_edge>, and 
L<count_from_zero|Spreadsheet::XLSX::Reader::LibXML/count_from_zero>

B<Accepts:> nothing

B<Returns:> an integer

=back

=head3 has_min_col

=over

B<Definition:> The L<predicate|Moose::Manual::Attributes/Predicate and clearer methods> 
of min_col

=back

=head3 max_col

=over

B<Definition:> This is the maximum row with data listed in the sheet.  This value 
is affected by the workbook attribute 
L<count_from_zero|Spreadsheet::XLSX::Reader::LibXML/count_from_zero>

B<Accepts:> nothing

B<Returns:> an integer

=back

=head3 has_max_col

=over

B<Definition:> The L<predicate|Moose::Manual::Attributes/Predicate and clearer methods> 
of max_col

=back

=head3 row_range

=over

B<Definition:> This returns a list containing the minimum row number followed 
by the maximum row number.  This list is affected by the workbook attributes 
L<from_the_edge|Spreadsheet::XLSX::Reader::LibXML/from_the_edge>, and 
L<count_from_zero|Spreadsheet::XLSX::Reader::LibXML/count_from_zero>

B<Accepts:> nothing

B<Returns:> ( $minimum_row, $maximum_row )

=back

=head3 col_range

=over

B<Definition:> This returns a list containing the minimum column number followed 
by the maximum column number.  This list is affected by the workbook attributes 
L<from_the_edge|Spreadsheet::XLSX::Reader::LibXML/from_the_edge>, and 
L<count_from_zero|Spreadsheet::XLSX::Reader::LibXML/count_from_zero>

B<Accepts:> nothing

B<Returns:> ( $minimum_column, $maximum_column )

=back

=head2 Attributes

These are attributes that affect the behaviour of the returned data in the worksheet 
instance.  In general you would not set these on instance generation, I<Because the primary 
class will generate this instance for you>.  Rather you would use the attribue methods 
listed with each attribute to change the attribute after the worksheet instance has been 
generated.  Additionally at the end of this list that a reference to the workbook is stored 
in one of the attributes as well so many workbook settings can be adjusted from the worksheet 
instance..

=head3 min_header_col

=over

B<Definition:> This attribute affects the hashref that is returned in the method 
L<fetchrow_hashref|/fetchrow_hashref( $row )>.  If the table you are reading does not 
start in the first column of the sheet then you need to indicate where to start.  
Otherwize the fetchrow_hashref method will return auto generated headers and attach 
them to the cell data outside your table but inside the sheet data boundaries.  This 
attribute tells fetchrow_hashref what column to use to start the hash ref build.

B<Default:> undef (which is equivalent to the minimum column of the sheet)

B<Range:> The minimum column of the sheet to or less than the
L<max_header_col|/max_header_col>

B<attribute methods> Methods provided to adjust this attribute

=over

B<get_min_header_col>

=over

B<Definition:> returns the value stored in the attribute

=back

B<set_min_header_col>

=over

B<Definition:> Sets a new value for the attribute

=back

B<has_min_header_col>

=over

B<Definition:> Indicates if the attribute has a stored value

=back

=back

=back

=head3 max_header_col

=over

B<Definition:> This attribute affects the hashref that is returned in the method 
L<fetchrow_hashref|/fetchrow_hashref( $row )>.  If the table you are reading ends 
before the max column of the sheet then you need indicate where to stop reading.  
Otherwize the fetchrow_hashref method will return auto generated headers and attach 
them to the cell values outside your table.  This attribute tells fetchrow_hashref 
what column to use to end the hash ref build.

B<Default:> undef (equal to the maximum column of the sheet)

B<Range:> The maximum column of the sheet to or less than the 
L<min_header_col|/min_header_col>

B<attribute methods> Methods provided to adjust this attribute

=over

B<get_max_header_col>

=over

B<Definition:> returns the value stored in the attribute

=back

B<set_max_header_col>

=over

B<Definition:> Sets a new value for the attribute

=back

B<has_max_header_col>

=over

B<Definition:> Indicates if the attribute has a stored value

=back

=back

=back

=head3 custom_formats

=over

B<Definition:> This package will generate value conversions that generally match the 
numerical conversions set in the Excel spreadsheet.  However, it may be that you want 
to convert the unformatted values for certain cells, rows, or columns in some user 
defined way.  Build an object instance that has the two following methods; 
'assert_coerce' and 'display_name'.  Then place it here in this attribute as a value 
to a hash key that is keyed on the target Cell ID, or the row number, or the Column 
letter callout and this package will assign that conversion when calling 'value' on 
the cell rather than the conversion stored in the Excel spreadsheet.

B<Default:> {} = no custom conversions

B<Range:> keys representing cell ID's, row numbers, or column letter callouts 
followed by values that are instance references for specific conversions.

B<Example:>

Building a converter on the fly (or use L<Type::Tiny|Type::Tiny::Manual::Libraries> 
or L<MooseX::Types>)

	use DateTimeX::Format::Excel;
	use DateTime::Format::Flexible;
	use Type::Coercion;
	use Type::Tiny;
	my @args_list  = ( system_type => 'apple_excel' );
	my $num_converter  = DateTimeX::Format::Excel->new( @args_list );
	
	# build conversion subroutines (number and strings to DateTime objects)
	my $string_via = sub{ 
	      my $str = $_[0];
	      return DateTime::Format::Flexible->parse_datetime( $str );
	};
	my $num_via	= sub{
	      my $num = $_[0];
	      return $num_converter->parse_datetime( $num );
	};
	
	# Combine conversion subroutines into a coercion object! 
	#  (Note numbers are attempted first)
	my $date_time_from_value = Type::Coercion->new( 
		type_coercion_map => [ Num, $num_via, Str, $string_via, ],
	);
	
	# Install the coercion in a type that ensures it passes through a DateTime check
	$date_time_type = Type::Tiny->new(
	   name       => 'Custom_date_type',
	   constraint => sub{ ref($_) eq 'DateTime' },
	   coercion   => $date_time_from_value,
	);
	
	# Chained coercions! to handle first the $date_time_from_value coercion 
	#    and then build a specific date string output
	$string_type = Type::Tiny->new(
	   name       => 'YYYYMMDD',
	   constraint => sub{
	      !$_ or (
	         $_ =~ /^\d{4}\-(\d{2})-(\d{2})$/ and
	         $1 > 0 and $1 < 13 and $2 > 0 and $2 < 32 
	      )
	   },
	   coercion => Type::Coercion->new(
	   type_coercion_map =>[
	      $date_time_type->coercibles, sub{ 
	         my $tmp = $date_time_type->coerce( $_ );
	         $tmp->format_cldr( 'yyyy-MM-dd' )
	      },
	   ],
	), );

Setting custom conversions to use for the worksheet

	my $worksheet = $workbook->worksheet( 'TargetWorksheetName' );
	$worksheet->set_custom_formats( {
	    E10 => $date_time_type,
	    10  => $string_type,
	    D14 => $string_type,
	} );

B<attribute methods> Methods provided to adjust this attribute

=over

B<set_custom_formats>

=over

B<Definition:> Sets a new (complete) hashref for the attribute

=back

B<has_custom_format( $key )>

=over

B<Definition:> checks if the specific custom format $key is set

=back

B<set_custom_format( $key =E<gt> $coercion, ... )>

=over

B<Definition:> sets the specific custom format $key(s) with $coercion(s)

=back

B<get_custom_format( $key )>

=over

B<Definition:> returns the specific custom format for that $key (see has_custom_format )

=back

=back

=back

=head3 sheet_rel_id

=over

B<Definition:> This is the relId of the sheet listed in the XML of the .xlsx file.  
You probably don't care and you should never set this value.

B<attribute methods> Methods provided to adjust this attribute

=over

B<rel_id>

=over

B<Definition:> returns the value stored in the attribute

=back

=back

=back

=head3 sheet_id

=over

B<Definition:> This is the Id of the sheet listed in the XML of the .xlsx file.  
I beleive this to be the number used in vbscript to reference the sheet.  You 
should never set this value.

B<attribute methods> Methods provided to adjust this attribute

=over

B<sheet_id>

=over

B<Definition:> returns the value stored in the attribute

=back

=back

=back

=head3 sheet_position

=over

B<Definition:> This is the visual sheet position in the .xlsx file.  
You should never set this value.

B<attribute methods> Methods provided to adjust this attribute

=over

B<position>

=over

B<Definition:> returns the value stored in the attribute

=back

=back

=back

=head3 sheet_name

=over

B<Definition:> This is the visual sheet name in the .xlsx file.  
You should never set this value.

B<attribute methods> Methods provided to adjust this attribute

=over

B<get_name>

=over

B<Definition:> returns the value stored in the attribute

=back

=back

=back

=head3 workbook_instance

=over

B<Definition:> This attribute holds a reference back to the workbook instance so that 
the worksheet has access to the global settings managed there.  As a consequence many 
of the workbook methods are be exposed here.  This includes some setter methods for 
workbook attributes. I<Beware that setting or adjusting the workbook level attributes 
with methods here will be universal and affect other worksheets.  So don't forget to 
return the old value if you want the old behavour after you are done.>  If that 
doesn't make sense then don't use these methods.  (Nothing to see here! Move along.)

B<Default:> a Spreadsheet::XLSX::Reader::LibXML instance

B<attribute methods> Methods of the workbook exposed here by the L<delegation
|Moose::Manual::Attributes/Delegation> of the instance to this class through this 
attribute

=over

B<counting_from_zero>

=over

B<Definition:> returns the L<Spreadsheet::XLSX::Reader::LibXML/count_from_zero> 
instance state

=back

B<boundary_flag_setting>

=over

B<Definition:> returns the L<Spreadsheet::XLSX::Reader::LibXML/file_boundary_flags> 
instance state

=back

B<change_boundary_flag( $Bool )>

=over

B<Definition:> sets the L<Spreadsheet::XLSX::Reader::LibXML/file_boundary_flags> 
instance state (B<For the whole workbook!>)

=back

B<get_shared_string_position( $int )>

=over

B<Definition:> returns the shared string data stored in the sharedStrings 
file at position $int.  For more information review 
L<Spreadsheet::XLSX::Reader::LibXML::SharedStrings>.  I<This is a delegation 
of a delegation!>

=back

B<get_format_position( $int, [$header] )>

=over

B<Definition:> returns the format data stored in the styles 
file at position $int.  If the optional $header is passed only the data for that 
header is returned.  Otherwise all styles for that position are returned.  
For more information review 
L<Spreadsheet::XLSX::Reader::LibXML::Styles>.  I<This is a delegation 
of a delegation!>

=back

B<set_empty_is_end( $Bool )>

=over

B<Definition:> sets the L<Spreadsheet::XLSX::Reader::LibXML/empty_is_end> 
instance state (B<For the whole workbook!>)

=back

B<is_empty_the_end>

=over

B<Definition:> returns the L<Spreadsheet::XLSX::Reader::LibXML/empty_is_end> 
instance state.

=back

B<get_group_return_type>

=over

B<Definition:> returns the L<Spreadsheet::XLSX::Reader::LibXML/group_return_type> 
instance state.

=back

B<set_group_return_type( (instance|unformatted|value) )>

=over

B<Definition:> sets the L<Spreadsheet::XLSX::Reader::LibXML/group_return_type> 
instance state (B<For the whole workbook!>)

=back

B<get_epoch_year>

=over

B<Definition:> uses the L<Spreadsheet::XLSX::Reader::LibXML/get_epoch_year> method.

=back

B<get_date_behavior>

=over

B<Definition:> This is a L<delegated|Moose::Manual::Delegation> method from the 
L<styles|Spreadsheet::XLSX::Reader::LibXML::Styles> class (stored as a private 
instance in the workbook).  It is held (and documented) in the 
L<Spreadsheet::XLSX::Reader::LibXML::ParseExcelFormatStrings> role.  It will 
indicate how far unformatted L<transformation
|Spreadsheet::XLSX::Reader::LibXML::ParseExcelFormatStrings/datetime_dates> 
is carried for date coercions when returning formatted values. 

=back

B<set_date_behavior>

=over

B<Definition:> This is a L<delegated|Moose::Manual::Delegation> method from 
the L<styles|Spreadsheet::XLSX::Reader::LibXML::Styles> class (stored as a private 
instance in the workbook).  It is held (and documented) in the 
L<Spreadsheet::XLSX::Reader::LibXML::ParseExcelFormatStrings> role.  It will set how 
far unformatted L<transformation
|Spreadsheet::XLSX::Reader::LibXML::ParseExcelFormatStrings/datetime_dates> 
is carried for date coercions when returning formatted values. 

=back

B<get_values_only>

=over

B<Definition:> gets the L<Spreadsheet::XLSX::Reader::LibXML/values_only> 
instance state.

=back

B<set_values_only>

=over

B<Definition:> sets the L<Spreadsheet::XLSX::Reader::LibXML/values_only> 
instance state (B<For the whole workbook!>)

=back

=back

=back

=head1 SUPPORT

=over

L<github Spreadsheet::XLSX::Reader::LibXML/issues|https://github.com/jandrew/Spreadsheet-XLSX-Reader-LibXML/issues>

=back

=head1 TODO

=over

B<1.> Add a way to set manual headers for fetchrow_hashref

B<2.> Add a pivot table reader (sometimes returns different values than just the sheet shows)

B<3.> Add more exposure to worksheet formatting values

B<4.> Add a DOM version of the parser

=back

=head1 AUTHOR

=over

=item Jed Lund

=item jandrew@cpan.org

=back

=head1 COPYRIGHT

This program is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.

The full text of the license can be found in the
LICENSE file included with this module.

This software is copyrighted (c) 2014, 2015 by Jed Lund

=head1 DEPENDENCIES

=over

L<Spreadsheet::XLSX::Reader::LibXML>

=back

=head1 SEE ALSO

=over

L<Spreadsheet::ParseExcel> - Excel 2003 and earlier

L<Spreadsheet::XLSX> - 2007+

L<Spreadsheet::ParseXLSX> - 2007+

L<Log::Shiras|https://github.com/jandrew/Log-Shiras>

=over

All lines in this package that use Log::Shiras are commented out

=back

=back

=cut

#########1#########2 main pod documentation end  5#########6#########7#########8#########9