diff options
-rw-r--r-- | Changes | 7 | ||||
-rw-r--r-- | lib/Spreadsheet/ParseXLSX.pm | 67 | ||||
-rw-r--r-- | t/bug-38.t | 11 | ||||
-rw-r--r-- | t/data/bug-38.xlsx | bin | 0 -> 12338 bytes | |||
-rw-r--r-- | t/data/hidden-row-and-column.xlsx | bin | 0 -> 7467 bytes | |||
-rw-r--r-- | t/data/hidden-sheet.xlsx | bin | 0 -> 7397 bytes | |||
-rw-r--r-- | t/data/target-abspath.xlsx | bin | 0 -> 6927 bytes | |||
-rw-r--r-- | t/hidden-row-and-column.t | 17 | ||||
-rw-r--r-- | t/hidden-sheet.t | 15 | ||||
-rw-r--r-- | t/target-abspath.t | 11 |
10 files changed, 107 insertions, 21 deletions
@@ -1,6 +1,13 @@ Revision history for Spreadsheet-ParseXLSX {{$NEXT}} + +0.18 2015-09-19 + - Fix 5.8 support (rjbs, #39) + - Fix parsing of files which have empty worksheets (for instance, + worksheets that are only charts) (Stuart Watt, #43) + +0.17 2015-03-25 - Fix using_1904_date (f20, #31) - Add support for get_header, get_footer, get_margin_*, get_print_scale, get_paper, is_portrait, and get_start_page, and also fill in the diff --git a/lib/Spreadsheet/ParseXLSX.pm b/lib/Spreadsheet/ParseXLSX.pm index dca3c7c..4c446c9 100644 --- a/lib/Spreadsheet/ParseXLSX.pm +++ b/lib/Spreadsheet/ParseXLSX.pm @@ -1,7 +1,7 @@ package Spreadsheet::ParseXLSX; use strict; use warnings; -use 5.010; +use 5.008; # ABSTRACT: parse XLSX files use Archive::Zip; @@ -178,13 +178,18 @@ sub _parse_workbook { my @sheets = map { my $idx = $_->att('r:id'); - my $sheet = Spreadsheet::ParseExcel::Worksheet->new( - Name => $_->att('name'), - _Book => $workbook, - _SheetNo => $idx, - ); - $self->_parse_sheet($sheet, $files->{sheets}{$idx}); - $sheet + if ($files->{sheets}{$idx}) { + my $sheet = Spreadsheet::ParseExcel::Worksheet->new( + Name => $_->att('name'), + _Book => $workbook, + _SheetNo => $idx, + ); + $sheet->{SheetHidden} = 1 if defined $_->att('state') and $_->att('state') eq 'hidden'; + $self->_parse_sheet($sheet, $files->{sheets}{$idx}); + ($sheet) + } else { + () + } } $files->{workbook}->find_nodes('//sheets/sheet'); $workbook->{Worksheet} = \@sheets; @@ -211,7 +216,9 @@ sub _parse_sheet { my @column_formats; my @column_widths; + my @columns_hidden; my @row_heights; + my @rows_hidden; my $default_row_height = 15; my $default_column_width = 10; @@ -252,7 +259,8 @@ sub _parse_sheet { my ($twig, $margin) = @_; map { my $key = "\u${_}Margin"; - $sheet->{$key} = $margin->att($_) // 0 + $sheet->{$key} = defined $margin->att($_) + ? $margin->att($_) : 0 } qw(left right top bottom header footer); $twig->purge; @@ -260,9 +268,13 @@ sub _parse_sheet { 'pageSetup' => sub { my ($twig, $setup) = @_; - $sheet->{Scale} = $setup->att('scale') // 100; - $sheet->{Landscape} = ($setup->att('orientation') // '') ne 'landscape'; - $sheet->{PaperSize} = $setup->att('paperSize') // 1; + $sheet->{Scale} = defined $setup->att('scale') + ? $setup->att('scale') + : 100; + $sheet->{Landscape} = ($setup->att('orientation') || '') ne 'landscape'; + $sheet->{PaperSize} = defined $setup->att('paperSize') + ? $setup->att('paperSize') + : 1; $sheet->{PageStart} = $setup->att('firstPageNumber'); $sheet->{UsePage} = $self->_xml_boolean($setup->att('useFirstPageNumber')); $sheet->{HorizontalDPI} = $setup->att('horizontalDpi'); @@ -297,8 +309,10 @@ sub _parse_sheet { 'sheetFormatPr' => sub { my ( $twig, $format ) = @_; - $default_row_height //= $format->att('defaultRowHeight'); - $default_column_width //= $format->att('baseColWidth'); + $default_row_height = $format->att('defaultRowHeight') + unless defined $default_row_height; + $default_column_width = $format->att('baseColWidth') + unless defined $default_column_width; $twig->purge; }, @@ -309,6 +323,7 @@ sub _parse_sheet { for my $colnum ($col->att('min')..$col->att('max')) { $column_widths[$colnum - 1] = $col->att('width'); $column_formats[$colnum - 1] = $col->att('style'); + $columns_hidden[$colnum - 1] = $col->att('hidden'); } $twig->purge; @@ -318,6 +333,7 @@ sub _parse_sheet { my ( $twig, $row ) = @_; $row_heights[ $row->att('r') - 1 ] = $row->att('ht'); + $rows_hidden[ $row->att('r') - 1 ] = $row->att('hidden'); $twig->purge; }, @@ -452,10 +468,12 @@ sub _parse_sheet { $sheet->{RowHeight} = [ map { defined $_ ? 0+$_ : 0+$default_row_height } @row_heights ]; + $sheet->{RowHidden} = \@rows_hidden; $sheet->{ColWidth} = [ map { defined $_ ? 0+$_ : 0+$default_column_width } @column_widths ]; $sheet->{ColFmtNo} = \@column_formats; + $sheet->{ColHidden} = \@columns_hidden; } @@ -771,6 +789,7 @@ sub _extract_files { my $wb_name = ($rels->find_nodes( qq<//Relationship[\@Type="$type_base/officeDocument"]> ))[0]->att('Target'); + $wb_name =~ s{^/}{}; my $wb_xml = $self->_parse_xml($zip, $wb_name); my $path_base = $self->_base_path_for($wb_name); @@ -779,25 +798,33 @@ sub _extract_files { $self->_rels_for($wb_name) ); + my $get_path = sub { + my ($p) = @_; + + return $p =~ s{^/}{} + ? $p + : $path_base . $p; + }; + my ($strings_xml) = map { - $zip->memberNamed($path_base . $_->att('Target'))->contents + $zip->memberNamed($get_path->($_->att('Target')))->contents } $wb_rels->find_nodes(qq<//Relationship[\@Type="$type_base/sharedStrings"]>); my $styles_xml = $self->_parse_xml( $zip, - $path_base . ($wb_rels->find_nodes( + $get_path->(($wb_rels->find_nodes( qq<//Relationship[\@Type="$type_base/styles"]> - ))[0]->att('Target') + ))[0]->att('Target')) ); my %worksheet_xml = map { - if ( my $sheetfile = $zip->memberNamed($path_base . $_->att('Target'))->contents ) { + if ( my $sheetfile = $zip->memberNamed($get_path->($_->att('Target')))->contents ) { ( $_->att('Id') => $sheetfile ); } } $wb_rels->find_nodes(qq<//Relationship[\@Type="$type_base/worksheet"]>); my %themes_xml = map { - $_->att('Id') => $self->_parse_xml($zip, $path_base . $_->att('Target')) + $_->att('Id') => $self->_parse_xml($zip, $get_path->($_->att('Target'))) } $wb_rels->find_nodes(qq<//Relationship[\@Type="$type_base/theme"]>); return { @@ -1394,8 +1421,6 @@ although this may have other consequences such as memory leaks. =item Intra-cell formatting is discarded -=item Diagonal border styles are ignored - =back In addition, there are still a few areas which are not yet implemented (the diff --git a/t/bug-38.t b/t/bug-38.t new file mode 100644 index 0000000..fa61176 --- /dev/null +++ b/t/bug-38.t @@ -0,0 +1,11 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use Test::More; + +use Spreadsheet::ParseXLSX; + +my $wb = Spreadsheet::ParseXLSX->new->parse('t/data/bug-38.xlsx'); +pass('it parses successfully'); + +done_testing; diff --git a/t/data/bug-38.xlsx b/t/data/bug-38.xlsx Binary files differnew file mode 100644 index 0000000..be360b4 --- /dev/null +++ b/t/data/bug-38.xlsx diff --git a/t/data/hidden-row-and-column.xlsx b/t/data/hidden-row-and-column.xlsx Binary files differnew file mode 100644 index 0000000..4d4bac4 --- /dev/null +++ b/t/data/hidden-row-and-column.xlsx diff --git a/t/data/hidden-sheet.xlsx b/t/data/hidden-sheet.xlsx Binary files differnew file mode 100644 index 0000000..d29cafb --- /dev/null +++ b/t/data/hidden-sheet.xlsx diff --git a/t/data/target-abspath.xlsx b/t/data/target-abspath.xlsx Binary files differnew file mode 100644 index 0000000..2ca7970 --- /dev/null +++ b/t/data/target-abspath.xlsx diff --git a/t/hidden-row-and-column.t b/t/hidden-row-and-column.t new file mode 100644 index 0000000..cd18c70 --- /dev/null +++ b/t/hidden-row-and-column.t @@ -0,0 +1,17 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use Test::More; + +use Spreadsheet::ParseXLSX; + +my $wb = Spreadsheet::ParseXLSX->new->parse('t/data/hidden-row-and-column.xlsx'); +my $ws = $wb->worksheet(0); + +ok(!$ws->is_row_hidden(0), 'Regular row is not hidden'); +ok( $ws->is_row_hidden(1), 'Hidden row is hidden'); + +ok(!$ws->is_col_hidden(0), 'Regular column is not hidden'); +ok( $ws->is_col_hidden(1), 'Hidden column is hidden'); + +done_testing; diff --git a/t/hidden-sheet.t b/t/hidden-sheet.t new file mode 100644 index 0000000..09d4402 --- /dev/null +++ b/t/hidden-sheet.t @@ -0,0 +1,15 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use Test::More; + +use Spreadsheet::ParseXLSX; + +my $wb = Spreadsheet::ParseXLSX->new->parse('t/data/hidden-sheet.xlsx'); +my $ws1 = $wb->worksheet(0); +ok(!$ws1->is_sheet_hidden(), 'Regular worksheet is not hidden'); + +my $ws2 = $wb->worksheet(1); +ok($ws2->is_sheet_hidden(), 'Hidden worksheet is hidden'); + +done_testing; diff --git a/t/target-abspath.t b/t/target-abspath.t new file mode 100644 index 0000000..9e9786c --- /dev/null +++ b/t/target-abspath.t @@ -0,0 +1,11 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use Test::More; + +use Spreadsheet::ParseXLSX; + +my $wb = Spreadsheet::ParseXLSX->new->parse('t/data/target-abspath.xlsx'); +is($wb->worksheet(0)->get_cell(1, 0)->value, '10213.576'); + +done_testing; |