diff --git a/examples/embedded_images.pl b/examples/embedded_images.pl new file mode 100644 index 00000000..de40792f --- /dev/null +++ b/examples/embedded_images.pl @@ -0,0 +1,33 @@ +####################################################################### +# +# An example of embedding images into a worksheet cells using the the +# Excel::Writer::XLSX module. This is equivalent to Excel's "Place in cell" +# image insert. +# +# Copyright 2000-2023, John McNamara, jmcnamara@cpan.org +# +# SPDX-License-Identifier: Artistic-1.0-Perl OR GPL-1.0-or-later +# + +use strict; +use Excel::Writer::XLSX; + +# Create a new workbook called simple.xls and add a worksheet +my $workbook = Excel::Writer::XLSX->new( 'embedded_images.xlsx' ); +my $worksheet = $workbook->add_worksheet(); + + +# Widen the first column to make the caption clearer. +$worksheet->set_column( 0, 0, 30 ); +$worksheet->write( 0, 0, "Embed images that scale to cell size" ); + +# Embed an images in cells of different widths/heights. +$worksheet->set_column( 1, 1, 14 ); + +$worksheet->set_row( 1, 60 ); +$worksheet->embed_image( 1, 1, "republic.png" ); + +$worksheet->set_row( 3, 120 ); +$worksheet->embed_image( 3, 1, "republic.png" ); + +$workbook->close(); diff --git a/lib/Excel/Writer/XLSX.pm b/lib/Excel/Writer/XLSX.pm index 18af38a8..f677cdd5 100644 --- a/lib/Excel/Writer/XLSX.pm +++ b/lib/Excel/Writer/XLSX.pm @@ -1785,7 +1785,8 @@ BMP images must be 24 bit, true colour, bitmaps. In general it is best to avoid =head2 embed_image( $row, $col, $filename, { %options } ) -This method can be used to embed an image into a worksheet. The image can be in PNG, JPEG, GIF or BMP format. +This method can be used to embed an image into a worksheet. The image can be +in PNG, JPEG, GIF or BMP format. $worksheet1->embed_image( 'A1', 'perl.bmp' ); $worksheet2->embed_image( 'A1', '../images/perl.bmp' ); @@ -1797,10 +1798,13 @@ of the image is preserved but the size of the image is adjusted to fit the largest possible width or height depending on the cell dimensions. This is the equivalent of Excel's menu option to insert an image using the -option to "Place in Cell". See C for the equivalent method to -"Place over Cells". +option to "Place in Cell" which is only available in Excel 365 versions from +2023 onwards. For older versions of Excel a ``#VALUE!`` error is displayed. -The optional C hash/hashref parameter can be used to set various options for the image. The defaults are: +See C for the equivalent method to "Place over Cells". + +The optional C hash/hashref parameter can be used to set various +options for the image. The defaults are: %options = ( cell_format => format, @@ -1810,14 +1814,16 @@ The optional C hash/hashref parameter can be used to set various option decorative => 0, ); -The C parameters can be an standard Format to set the formatting of the cell behind the image. +The C parameters can be an standard Format to set the formatting +of the cell behind the image. The C option can be use to used to add a hyperlink to an image: $worksheet->insert_image( 'A1', 'logo.png', { url => 'https://github.com/jmcnamara' } ); -The supported url formats are the same as those supported by the C method and the same rules/limits apply. +The supported url formats are the same as those supported by the +C method and the same rules/limits apply. The C option can be use to used to add a mouseover tip to the hyperlink: @@ -1828,18 +1834,30 @@ The C option can be use to used to add a mouseover tip to the hyperlink: } ); -The C parameter can be used to specify a description or "alt text" string for the image. In general this would be used to provide a text description of the image to help accessibility. It is an optional parameter and defaults to the filename of the image. It can be used as follows: +The C parameter can be used to specify a description or "alt +text" string for the image. In general this would be used to provide a text +description of the image to help accessibility. It is an optional parameter +and defaults to the filename of the image. It can be used as follows: $worksheet->insert_image( 'E9', 'logo.png', {description => "This is some alternative text"} ); -The optional C parameter is also used to help accessibility. It is used to mark the image as decorative, and thus uninformative, for automated screen readers. As in Excel, if this parameter is in use the C field isn't written. It is used as follows: +The optional C parameter is also used to help accessibility. It is +used to mark the image as decorative, and thus uninformative, for automated +screen readers. As in Excel, if this parameter is in use the C +field isn't written. It is used as follows: $worksheet->insert_image( 'E9', 'logo.png', {decorative => 1} ); -Note: you must call C or C before C if you wish to change the default dimensions of any of the rows or columns that the image occupies. The height of a row can also change if you use a font that is larger than the default. This in turn will affect the scaling of your image. To avoid this you should explicitly set the height of the row using C if it contains a font size that will change the row height. +Note: you must call C or C before C +if you wish to change the default dimensions of any of the rows or columns +that the image occupies. The height of a row can also change if you use a font +that is larger than the default. This in turn will affect the scaling of your +image. To avoid this you should explicitly set the height of the row using +C if it contains a font size that will change the row height. -BMP images must be 24 bit, true colour, bitmaps. In general it is best to avoid BMP images since they aren't compressed. +BMP images must be 24 bit, true colour, bitmaps. In general it is best to +avoid BMP images since they aren't compressed. diff --git a/lib/Excel/Writer/XLSX/Worksheet.pm b/lib/Excel/Writer/XLSX/Worksheet.pm index dd5bd839..1b835add 100644 --- a/lib/Excel/Writer/XLSX/Worksheet.pm +++ b/lib/Excel/Writer/XLSX/Worksheet.pm @@ -6588,13 +6588,14 @@ sub embed_image { get_image_properties( $image ); # Check for duplicate images. - my $image_index = ${ $self->{_embedded_images_indexes} }->{$md5}; + my $image_index = ${ $self->{_embedded_image_indexes} }->{$md5}; + if ( !$image_index ) { push @{ ${ $self->{_embedded_images} } }, [ $image, $type, $description, $decorative ]; $image_index = scalar @{ ${ $self->{_embedded_images} } }; - ${ $self->{_embedded_images_indexes} }->{$md5} = $image_index; + ${ $self->{_embedded_image_indexes} }->{$md5} = $image_index; } # Write the cell placeholder. diff --git a/t/regression/embed_image13.t b/t/regression/embed_image13.t new file mode 100644 index 00000000..b25a99db --- /dev/null +++ b/t/regression/embed_image13.t @@ -0,0 +1,85 @@ +############################################################################### +# +# Tests the output of Excel::Writer::XLSX against Excel generated files. +# +# Copyright 2000-2023, John McNamara, jmcnamara@cpan.org +# +# SPDX-License-Identifier: Artistic-1.0-Perl OR GPL-1.0-or-later +# + +use lib 't/lib'; +use TestFunctions qw(_compare_xlsx_files _is_deep_diff); +use strict; +use warnings; + +use Test::More tests => 1; + +############################################################################### +# +# Tests setup. +# +my $filename = 'embed_image13.xlsx'; +my $dir = 't/regression/'; +my $got_filename = $dir . "ewx_$filename"; +my $exp_filename = $dir . 'xlsx_files/' . $filename; + +my $ignore_members = []; +my $ignore_elements = {}; + + +############################################################################### +# +# Test the creation of a simple Excel::Writer::XLSX file with image(s). +# +use Excel::Writer::XLSX; + +my $workbook = Excel::Writer::XLSX->new( $got_filename ); + +my $worksheet1 = $workbook->add_worksheet(); + +$worksheet1->embed_image( 0, 0, $dir . 'images/red.png' ); +$worksheet1->embed_image( 2, 0, $dir . 'images/blue.png' ); +$worksheet1->embed_image( 4, 0, $dir . 'images/yellow.png' ); + +my $worksheet2 = $workbook->add_worksheet(); + +$worksheet2->embed_image( 0, 0, $dir . 'images/yellow.png' ); +$worksheet2->embed_image( 2, 0, $dir . 'images/red.png' ); +$worksheet2->embed_image( 4, 0, $dir . 'images/blue.png' ); + +my $worksheet3 = $workbook->add_worksheet(); + +$worksheet3->embed_image( 0, 0, $dir . 'images/blue.png' ); +$worksheet3->embed_image( 2, 0, $dir . 'images/yellow.png' ); +$worksheet3->embed_image( 4, 0, $dir . 'images/red.png' ); + + +$workbook->close(); + + +############################################################################### +# +# Compare the generated and existing Excel files. +# + +my ( $got, $expected, $caption ) = _compare_xlsx_files( + + $got_filename, + $exp_filename, + $ignore_members, + $ignore_elements, +); + +_is_deep_diff( $got, $expected, $caption ); + + +############################################################################### +# +# Cleanup. +# +unlink $got_filename; + +__END__ + + + diff --git a/t/regression/xlsx_files/embed_image13.xlsx b/t/regression/xlsx_files/embed_image13.xlsx new file mode 100644 index 00000000..038f9747 Binary files /dev/null and b/t/regression/xlsx_files/embed_image13.xlsx differ