Skip to content

Commit

Permalink
worksheet: fix multi-sheet embed_image()
Browse files Browse the repository at this point in the history
  • Loading branch information
jmcnamara committed Feb 24, 2024
1 parent 7dda1e3 commit 71824ef
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 12 deletions.
33 changes: 33 additions & 0 deletions examples/embedded_images.pl
Original file line number Diff line number Diff line change
@@ -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, [email protected]
#
# 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();
38 changes: 28 additions & 10 deletions lib/Excel/Writer/XLSX.pm
Original file line number Diff line number Diff line change
Expand Up @@ -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' );
Expand All @@ -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<insert_image()> 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<options> hash/hashref parameter can be used to set various options for the image. The defaults are:
See C<insert_image()> for the equivalent method to "Place over Cells".
The optional C<options> hash/hashref parameter can be used to set various
options for the image. The defaults are:
%options = (
cell_format => format,
Expand All @@ -1810,14 +1814,16 @@ The optional C<options> hash/hashref parameter can be used to set various option
decorative => 0,
);
The C<cell_format> parameters can be an standard Format to set the formatting of the cell behind the image.
The C<cell_format> parameters can be an standard Format to set the formatting
of the cell behind the image.
The C<url> 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<write_url()> method and the same rules/limits apply.
The supported url formats are the same as those supported by the
C<write_url()> method and the same rules/limits apply.
The C<tip> option can be use to used to add a mouseover tip to the hyperlink:
Expand All @@ -1828,18 +1834,30 @@ The C<tip> option can be use to used to add a mouseover tip to the hyperlink:
}
);
The C<description> 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<description> 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<decorative> 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<description> field isn't written. It is used as follows:
The optional C<decorative> 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<description>
field isn't written. It is used as follows:
$worksheet->insert_image( 'E9', 'logo.png', {decorative => 1} );
Note: you must call C<set_row()> or C<set_column()> before C<insert_image()> 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<set_row()> if it contains a font size that will change the row height.
Note: you must call C<set_row()> or C<set_column()> before C<insert_image()>
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<set_row()> 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.
Expand Down
5 changes: 3 additions & 2 deletions lib/Excel/Writer/XLSX/Worksheet.pm
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
85 changes: 85 additions & 0 deletions t/regression/embed_image13.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
###############################################################################
#
# Tests the output of Excel::Writer::XLSX against Excel generated files.
#
# Copyright 2000-2023, John McNamara, [email protected]
#
# 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__
Binary file added t/regression/xlsx_files/embed_image13.xlsx
Binary file not shown.

0 comments on commit 71824ef

Please sign in to comment.