Skip to content

Commit

Permalink
wip: initial working embed_image()
Browse files Browse the repository at this point in the history
  • Loading branch information
jmcnamara committed Feb 15, 2024
1 parent 238943a commit 85a1b84
Show file tree
Hide file tree
Showing 10 changed files with 270 additions and 50 deletions.
77 changes: 43 additions & 34 deletions lib/Excel/Writer/XLSX/Package/Metadata.pm
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ sub new {
my $fh = shift;
my $self = Excel::Writer::XLSX::Package::XMLwriter->new( $fh );

$self->{_cell_metadata} = 0;
$self->{_value_metadata} = 0;
$self->{_has_dynamic_functions} = 0;
$self->{_has_embedded_images} = 0;
$self->{_num_embedded_images} = 0;

bless $self, $class;

Expand All @@ -63,6 +64,10 @@ sub _assemble_xml_file {

my $self = shift;

if ( $self->{_num_embedded_images} > 0 ) {
$self->{_has_embedded_images} = 1;
}

$self->xml_declaration;

# Write the metadata element.
Expand All @@ -72,12 +77,12 @@ sub _assemble_xml_file {
$self->_write_metadata_types();

# Write the futureMetadata element.
$self->_write_cell_future_metadata() if $self->{_cell_metadata};
$self->_write_value_future_metadata() if $self->{_value_metadata};
$self->_write_cell_future_metadata() if $self->{_has_dynamic_functions};
$self->_write_value_future_metadata() if $self->{_has_embedded_images};

# Write the valueMetadata element.
$self->_write_cell_metadata() if $self->{_cell_metadata};
$self->_write_value_metadata() if $self->{_value_metadata};
$self->_write_cell_metadata() if $self->{_has_dynamic_functions};
$self->_write_value_metadata() if $self->{_has_embedded_images};

$self->xml_end_tag( 'metadata' );

Expand Down Expand Up @@ -109,15 +114,15 @@ sub _write_metadata {
);


if ( $self->{_value_metadata} ) {
if ( $self->{_has_embedded_images} ) {
push @attributes,
(
'xmlns:xlrd' =>
'http://schemas.microsoft.com/office/spreadsheetml/2017/richdata'
);
}

if ( $self->{_cell_metadata} ) {
if ( $self->{_has_dynamic_functions} ) {
push @attributes,
(
'xmlns:xda' =>
Expand All @@ -137,18 +142,16 @@ sub _write_metadata {
#
sub _write_metadata_types {

my $self = shift;
my $count = $self->{_cell_metadata} + $self->{_value_metadata};
my $self = shift;
my $count = $self->{_has_dynamic_functions} + $self->{_has_embedded_images};

my @attributes = ( 'count' => $count );

$self->xml_start_tag( 'metadataTypes', @attributes );

# Write the Cell Metadata element.
$self->_write_cell_metadata_type() if $self->{_cell_metadata};

# Write the Vell Metadata element.
$self->_write_value_metadata_type() if $self->{_value_metadata};
# Write the metadataType element.
$self->_write_cell_metadata_type() if $self->{_has_dynamic_functions};
$self->_write_value_metadata_type() if $self->{_has_embedded_images};

$self->xml_end_tag( 'metadataTypes' );
}
Expand Down Expand Up @@ -251,23 +254,27 @@ sub _write_cell_future_metadata {
#
sub _write_value_future_metadata {

my $self = shift;
my $self = shift;
my $num_images = $self->{_num_embedded_images};

my @attributes = (
'name' => 'XLRICHVALUE',
'count' => 1,
'count' => $num_images,
);

$self->xml_start_tag( 'futureMetadata', @attributes );
$self->xml_start_tag( 'bk' );
$self->xml_start_tag( 'extLst' );

# Write the ext element.
$self->_write_value_ext();
for my $i ( 0 .. $num_images - 1 ) {
$self->xml_start_tag( 'bk' );
$self->xml_start_tag( 'extLst' );

$self->xml_end_tag( 'ext' );
$self->xml_end_tag( 'extLst' );
$self->xml_end_tag( 'bk' );
# Write the ext element.
$self->_write_value_ext( $i );

$self->xml_end_tag( 'ext' );
$self->xml_end_tag( 'extLst' );
$self->xml_end_tag( 'bk' );
}

$self->xml_end_tag( 'futureMetadata' );
}
Expand Down Expand Up @@ -302,14 +309,14 @@ sub _write_cell_ext {
sub _write_value_ext {

my $self = shift;
my $uri = shift;
my $num = shift;

my @attributes = ( 'uri' => '{3e2802c4-a4d2-4d8b-9148-e3be6c30e623}' );

$self->xml_start_tag( 'ext', @attributes );

# Write the <xlrd:rvb> element.
$self->_write_xlrd_rvb();
$self->_write_xlrd_rvb( $num );
}

##############################################################################
Expand Down Expand Up @@ -364,18 +371,21 @@ sub _write_cell_metadata {
sub _write_value_metadata {

my $self = shift;
my $count = $self->{_value_metadata};
my $count = $self->{_num_embedded_images};

my @attributes = ( 'count' => $count, );

$self->xml_start_tag( 'valueMetadata', @attributes );
$self->xml_start_tag( 'bk' );

# Write the rc element.
$self->_write_rc(0);
for my $i ( 0 .. $count - 1 ) {
$self->xml_start_tag( 'bk' );

# Write the rc element.
$self->_write_rc( $i );

$self->xml_end_tag( 'bk' );
}

$self->xml_end_tag( 'bk' );
$self->xml_end_tag( 'valueMetadata' );
}

Expand All @@ -393,7 +403,7 @@ sub _write_rc {

my @attributes = (
't' => 1,
'v' => 0,
'v' => $value,
);

$self->xml_empty_tag( 'rc', @attributes );
Expand All @@ -409,15 +419,14 @@ sub _write_rc {
sub _write_xlrd_rvb {

my $self = shift;
my $value = 0;
my $value = shift;

my @attributes = ( 'i' => $value, );

$self->xml_empty_tag( 'xlrd:rvb', @attributes );
}



1;


Expand Down
14 changes: 7 additions & 7 deletions lib/Excel/Writer/XLSX/Package/Packager.pm
Original file line number Diff line number Diff line change
Expand Up @@ -479,8 +479,8 @@ sub _write_metadata_file {

return if !$self->{_workbook}->{_has_metadata};

$metadata->{_cell_metadata} = $self->{_workbook}->{_cell_metadata};
$metadata->{_value_metadata} = $self->{_workbook}->{_value_metadata};
$metadata->{_has_dynamic_functions} = $self->{_workbook}->{_has_dynamic_functions};
$metadata->{_num_embedded_images} = @{ $self->{_workbook}->{_embedded_images} };

_mkdir( $dir . '/xl' );

Expand All @@ -500,7 +500,7 @@ sub _write_rich_value_files {
my $self = shift;
my $dir = $self->{_package_dir};

return if !$self->{_workbook}->{_value_metadata};
return if !$self->{_workbook}->{_has_embedded_images};

_mkdir( $dir . '/xl' );
_mkdir( $dir . '/xl/richData' );
Expand All @@ -524,7 +524,7 @@ sub _write_rich_value_file {
my $dir = $self->{_package_dir};
my $rich_value = Excel::Writer::XLSX::Package::RichValue->new();

$rich_value->{_value_count} = $self->{_workbook}->{_value_metadata};
$rich_value->{_value_count} = @{ $self->{_workbook}->{_embedded_images} };

$rich_value->_set_xml_writer( $dir . '/xl/richData/rdrichvalue.xml' );
$rich_value->_assemble_xml_file();
Expand Down Expand Up @@ -576,7 +576,7 @@ sub _write_rich_value_rel {
my $dir = $self->{_package_dir};
my $rich_value = Excel::Writer::XLSX::Package::RichValueRel->new();

$rich_value->{_value_count} = $self->{_workbook}->{_value_metadata};
$rich_value->{_value_count} = @{ $self->{_workbook}->{_embedded_images} };

$rich_value->_set_xml_writer( $dir . '/xl/richData/richValueRel.xml' );
$rich_value->_assemble_xml_file();
Expand Down Expand Up @@ -672,7 +672,7 @@ sub _write_content_types_file {
}

# Add the RichValue file if present.
if ( $self->{_workbook}->{_value_metadata} ) {
if ( $self->{_workbook}->{_has_embedded_images} ) {
$content->_add_richvalue();
}

Expand Down Expand Up @@ -862,7 +862,7 @@ sub _write_workbook_rels_file {
}

# Add the RichValue file if present.
if ( $self->{_workbook}->{_value_metadata} ) {
if ( $self->{_workbook}->{_has_embedded_images} ) {
$rels->_add_worksheet_rich_value_relationships();
}

Expand Down
10 changes: 5 additions & 5 deletions lib/Excel/Writer/XLSX/Workbook.pm
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ sub new {
$self->{_has_comments} = 0;
$self->{_read_only} = 0;
$self->{_has_metadata} = 0;
$self->{_cell_metadata} = 0;
$self->{_value_metadata} = 0;
$self->{_has_dynamic_functions} = 0;
$self->{_has_embedded_images} = 0;

$self->{_default_format_properties} = {};

Expand Down Expand Up @@ -2076,10 +2076,10 @@ sub _prepare_metadata {
my $self = shift;

for my $sheet ( @{ $self->{_worksheets} } ) {
if ($sheet->{_cell_metadata} || $sheet->{_value_metadata}) {
if ($sheet->{_has_dynamic_functions} || $sheet->{_has_embedded_images}) {
$self->{_has_metadata} = 1;
$self->{_cell_metadata} += $sheet->{_cell_metadata};
$self->{_value_metadata} += $sheet->{_value_metadata};
$self->{_has_dynamic_functions} ||= $sheet->{_has_dynamic_functions};
$self->{_has_embedded_images} ||= $sheet->{_has_embedded_images};
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions lib/Excel/Writer/XLSX/Worksheet.pm
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,8 @@ sub new {
$self->{_vml_drawing_rels_id} = 0;
$self->{_horizontal_dpi} = 0;
$self->{_vertical_dpi} = 0;
$self->{_cell_metadata} = 0;
$self->{_value_metadata} = 0;
$self->{_has_dynamic_functions} = 0;
$self->{_has_embedded_images} = 0;
$self->{_use_future_functions} = 0;

$self->{_rstring} = '';
Expand Down Expand Up @@ -3218,7 +3218,7 @@ sub write_dynamic_array_formula {
my $error = $self->_write_array_formula( 'd', @_ );

if ( $error == 0 ) {
$self->{_cell_metadata} = 1;
$self->{_has_dynamic_functions} = 1;
}

return $error;
Expand Down Expand Up @@ -6587,7 +6587,7 @@ sub embed_image {

# Write the cell placeholder.
$self->{_table}->{$row}->{$col} = [ 'e', "#VALUE!", $xf, $image_index];
$self->{_value_metadata} = 1;
$self->{_has_embedded_images} = 1;
}


Expand Down
70 changes: 70 additions & 0 deletions t/regression/embed_image02.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
###############################################################################
#
# 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_image02.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 $worksheet = $workbook->add_worksheet();

$worksheet->embed_image( 0, 0, $dir . 'images/red.png' );
$worksheet->embed_image( 8, 4, $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__
Loading

0 comments on commit 85a1b84

Please sign in to comment.