-Revision history for Perl module Excel::Template
+Revision history for Perl distribution Excel::Template
+
+0.15 Thu Nov 04 16:15:00 2004
+ - Fixed bugs that were:
+ - preventing a worksheet from using a variable name in a loop
+ - allowing two worksheets to have the same name
+ - preventing a worksheet from being called '0' or '0.0'
+ - Added back-references. This allows for one cell to refer to another
+ cell in an Excel-aware way, especially in formulas.
+ - Added the following nodes:
+ - BACKREF
+ - RANGE
+
+0.14 Thu Nov 04 13:30:00 2004
+ - Added new format support for (nearly) all formats supported by
+ Spreadsheet::WriteExcel
+ - Fixed email address everywhere
+
+0.13 Thu Oct 29 07:30:00 2004
+ - Fixed email address and added GoogleGroup
0.12 Thu Apr 08 07:30:00 2004
- Fixed bug regarding empty arrays as loop variables
lib/Excel/Template/Factory.pm
lib/Excel/Template/Format.pm
lib/Excel/Template/Iterator.pm
-lib/Excel/Template/TextObject.pm
+lib/Excel/Template/TextObject.pm_
lib/Excel/Template/Container/Bold.pm
lib/Excel/Template/Container/Conditional.pm
lib/Excel/Template/Container/Format.pm
lib/Excel/Template/Container/Shadow.pm
lib/Excel/Template/Container/Workbook.pm
lib/Excel/Template/Container/Worksheet.pm
-lib/Excel/Template/Element/Cell.pm
+lib/Excel/Template/Element/Backref.pm
+lib/Excel/Template/Element/Cell.pm_
lib/Excel/Template/Element/Formula.pm
+lib/Excel/Template/Element/Range.pm
lib/Excel/Template/Element/Var.pm
t/001_load.t
Makefile.PL
+META.yml Module meta-data (added by MakeMaker)
use ExtUtils::MakeMaker;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
+
+use File::Spec;
+
+my $prereqs = {
+ 'Test::Simple' => 0.44,
+ 'XML::Parser' => 0.01,
+ 'IO::File' => 0.01,
+ 'IO::Scalar' => 0.01,
+ 'File::Basename' => 0.01,
+ 'Spreadsheet::WriteExcel' => 0.42,
+};
+
+# The assumption is the 5.8.0 and greater doesn't need Unicode::String.
+if ($] < 5.008)
+{
+ print "Do you want Unicode support? ";
+ my $answer = <STDIN>;
+ my $need_unicode = $answer =~ /^[Yy]/;
+
+ my $use_unicode = 0;
+ if ($need_unicode)
+ {
+ $prereqs{'Unicode::String'} = '0.01';
+ $use_unicode = 1;
+ }
+}
+
+use_unicode($use_unicode);
+
WriteMakefile(
NAME => 'Excel::Template',
VERSION_FROM => 'lib/Excel/Template.pm', # finds $VERSION
- AUTHOR => 'Rob Kinyon (rkinyon@columbus.rr.com',
+ AUTHOR => 'Rob Kinyon (rob.kinyon@gmail.com)',
ABSTRACT => 'Excel::Template',
- PREREQ_PM => {
- 'Test::Simple' => 0.44,
- 'Spreadsheet::WriteExcel' => 0.42,
- 'XML::Parser' => 0.01,
- 'IO::Scalar' => 0.01,
- 'IO::File' => 0.01,
- },
+ PREREQ_PM => $prereqs,
);
+
+sub use_unicode
+{
+ my $using_unicode = shift;
+
+ my @filenames = map {
+ File::Spec->catfile(
+ qw( lib Excel Template ),
+ @{$_},
+ )
+ } ( [ qw( Element Cell.pm_ ) ], [ qw( TextObject.pm_ ) ] );
+
+ foreach my $filename (@filenames)
+ {
+ open(IN_FILE, $filename)
+ or die "Cannot open '$filename' for reading: $!\n";
+ my @lines = <IN_FILE>;
+ close(IN_FILE);
+
+ if ($using_unicode)
+ {
+ for (@lines)
+ {
+ s/^UNI_YES / /;
+ s/^UNI_NO /#/;
+ }
+ }
+ else
+ {
+ for (@lines)
+ {
+ s/^UNI_YES /#/;
+ s/^UNI_NO / /;
+ }
+ }
+
+ $filename =~ s/_$//;
+ open(OUT_FILE, ">$filename")
+ or die "Cannot open '$filename' for writing: $!\n";
+ print OUT_FILE @lines;
+ close(OUT_FILE);
+ }
+
+ return 1;
+}
use Excel::Template::Base;
use vars qw ($VERSION @ISA);
- $VERSION = '0.12';
+ $VERSION = '0.15';
@ISA = qw( Excel::Template::Base );
}
my $node = Excel::Template::Factory->create_node($name, @_);
die "'$name' (@_) didn't make a node!\n" unless defined $node;
- if ($name eq 'WORKBOOK')
+ if ( $node->isa( 'WORKBOOK' ) )
{
push @{$self->{WORKBOOKS}}, $node;
}
- elsif ($name eq 'VAR')
+ elsif ( $node->is_embedded )
{
return unless @stack;
=head1 AUTHOR
Rob Kinyon
- rkinyon@columbus.rr.com
+ rob.kinyon@gmail.com
+
+=head1 CONTRIBUTORS
+
+There is a mailing list at http://groups-beta.google.com/group/ExcelTemplate
+
+Robert Graff -
+
+=over 4
+
+=item * Finishing formats
+
+=item * Fixing several bugs in worksheet naming
+
+=back 4
=head1 COPYRIGHT
}
sub isa { Excel::Template::Factory::isa(@_) }
+sub is_embedded { Excel::Template::Factory::is_embedded(@_) }
sub calculate { ($_[1])->get(@_[0,2]) }
#{
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
my $child_success = $self->iterate_over_children($context);
$context->active_format($old_format);
+
+ return $child_success;
}
1;
=over 4
+Boolean attributes should be set to 1, 0, true, or false.
+
+Color values can be the color name or the color index. See http://search.cpan.org/~jmcnamara/Spreadsheet-WriteExcel-2.11/lib/Spreadsheet/WriteExcel.pm#COLOURS_IN_EXCEL
+
+
+=item * align
+
+Set to either left, center, right, fill, or justify. Default is left. See also valign.
+
+=item * bg_color
+
+Set to a color value. Default is none.
+
=item * bold
This will set bold to on or off, depending on the boolean value.
-=item * hidden
+=item * border
-This will set whether the cell is hidden to on or off, depending on the boolean
-value. (q.v. BOLD tag)
+Set the border for all for edges of a cell. Also see bottom, top, left, and right.
+Valid values are 0 - 7.
-=item * italic
+http://search.cpan.org/~jmcnamara/Spreadsheet-WriteExcel-2.11/lib/Spreadsheet/WriteExcel.pm#set_border()
-This will set italic to on or off, depending on the boolean value. (q.v. ITALIC
-tag)
+=item * border_color
+
+Sets the color value for the border. See also border, top_color, bottom_color, left_color
+and right_color.
+
+=item * bottom
+
+See border.
+
+=item * bottom_color
+
+See border_color
+
+=item * color
+
+This will set the color of the text, depending on color value. Default is black.
+
+=item * fg_color
+
+Set to a color value. This color will be used in foreground of some patterns. See color
+to change the color of text. Also see bg_color and pattern.
+
+=item * font
+
+This will sent the font face. Default is Arial.
=item * font_outline
=item * font_shadow
This will set font_shadow to on or off, depending on the boolean value. (q.v.
-SHADOW tag)
+SHADOW tag). This only applies to Excel for Macintosh.
=item * font_strikeout
This will set font_strikeout to on or off, depending on the boolean value. (q.v.
STRIKEOUT tag)
+=item * hidden
+
+This will set whether the cell is hidden to on or off, depending on the boolean
+value.
+
+=item * indent
+
+Set the indentation level for a cell. Positive integers are allowed.
+
+=item * italic
+
+This will set italic to on or off, depending on the boolean value. (q.v. ITALIC
+tag)
+
+=item * left
+
+See border.
+
+=item * left_color
+
+See border_color.
+
+=item * num_format
+
+Set to the index of one of Excel's built-in number formats. See http://search.cpan.org/~jmcnamara/Spreadsheet-WriteExcel-2.11/lib/Spreadsheet/WriteExcel.pm#set_num_format()
+
+=item * pattern
+
+Set to an integer, 0 - 18. Sets the background fill pattern of a ell. Default is 1, solid.
+
+=item * right
+
+See border.
+
+=item * right_color
+
+See border color.
+
+=item * rotation
+
+Set the rotation of the text in a cell. The rotation can be any angle in the range -90 to 90 degrees.
+The angle 270 is also supported. This indicates text where the letters run from top to bottom.
+
+=item * shrink
+
+A boolean value. If true, text will shrink to fit a cell.
+
+=item * size
+
+This will set the size of the font. Default is 10. Unless a row height is
+specifically set, the row will grow taller as necessary.
+
+=item * text_justlast
+
+A boolean value to justify the last line. Only applies to Far Eastern versions of Excel.
+
+=item * text_wrap
+
+A boolean value. When set to true, text will wrap in a cell instead of crossing over
+into empty cells. If the row height is not set, the row will grow taller to accomodate
+the wrapping text.
+
+=item * top
+
+See border.
+
+=item * top_color
+
+See border_color
+
+=item * valign
+
+Set to top, vcenter, bottom, or vjustify. Default is vcenter. See also align.
+
=back 4
=head1 CHILDREN
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
my $self = shift;
my ($context) = @_;
- $context->new_worksheet($self->{NAME});
+ $context->new_worksheet( $self );
return $self->SUPER::render($context);
}
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
# represent an XML object. Rather, every container will use this object to
# maintain the context for its children.
-my %isAbsolute = map { $_ => 1 } qw(
+my %isAbsolute = map { $_ => !!1 } qw(
ROW
COL
);
$self->{ACTIVE_WORKSHEET} = undef;
$self->{ACTIVE_FORMAT} = Excel::Template::Format->blank_format($self);
+ $self->{WORKSHEET_NAMES} = undef;
UNIVERSAL::isa($self->{$_}, 'ARRAY') || ($self->{$_} = [])
for qw( STACK PARAM_MAP NAME_MAP );
$param = uc $param;
$depth ||= 0;
- my $val = undef;
- my $found = 0;
-
+ my ($val, $found);
for my $map (reverse @{$self->{$map}})
{
next unless exists $map->{$param};
$depth--, next if $depth;
- $found = 1;
+ $found = !!1;
$val = $map->{$param};
last;
}
$self->{$key} = $self->resolve($obj, $key);
}
- return 1;
+ return !!1;
}
sub exit_scope
pop @{$self->{STACK}};
- return 1;
+ return !!1;
}
sub get
sub new_worksheet
{
my $self = shift;
- my ($name) = @_;
+ my ($worksheet) = @_;
$self->{ROW} = $self->{COL} = 0;
+ $self->{REFERENCES} = {};
+
+ my $name = $self->get( $worksheet, 'NAME' );
+
+ if ( defined $name && length $name )
+ {
+ if ( exists $self->{WORKSHEET_NAMES}{$name} )
+ {
+ $name = '';
+ }
+ else
+ {
+ $self->{WORKSHEET_NAMES}{$name} = undef;
+ }
+ }
+ else
+ {
+ $name = '';
+ }
$self->active_worksheet(
- $self->{XLS}->add_worksheet(
- $name || '',
- ),
+ $self->{XLS}->add_worksheet( $name ),
);
}
$self->{ACTIVE_WORKSHEET};
}
+sub add_reference
+{
+ my $self = shift;
+ my ($ref, $row, $col) = @_;
+
+ $self->{REFERENCES}{$ref} ||= [];
+
+ push @{$self->{REFERENCES}{$ref}}, [ $row, $col ];
+
+ return !!1;
+}
+
+sub get_all_references
+{
+ my $self = shift;
+ my $ref = uc shift;
+
+ $self->{REFERENCES}{$ref} ||= [];
+
+ return @{ $self->{REFERENCES}{$ref} };
+}
+
+sub get_last_reference
+{
+ my $self = shift;
+ my $ref = uc shift;
+
+ $self->{REFERENCES}{$ref} ||= [];
+
+ return @{ $self->{REFERENCES}{$ref}[-1] };
+}
+
1;
__END__
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
--- /dev/null
+package Excel::Template::Element::Backref;
+
+use strict;
+use Spreadsheet::WriteExcel::Utility;
+
+BEGIN {
+ use vars qw(@ISA);
+ @ISA = qw(Excel::Template::Element);
+
+ use Excel::Template::Element;
+}
+
+sub resolve
+{
+ my $self = shift;
+ my ($context) = @_;
+
+ my $ref_name = $context->resolve($self, 'REF');
+
+ my ($row, $col) = $context->get_last_reference( $ref_name );
+ return '' unless defined $row && defined $col;
+
+ return xl_rowcol_to_cell( $row, $col );
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Excel::Template::Element::Ref
+
+=head1 PURPOSE
+
+Returns the cell location (i.e. B2) of the last cell to name this reference. To
+return the location of the entire range of cells to name this reference see RANGE.
+
+=head1 NODE NAME
+
+REF
+
+=head1 INHERITANCE
+
+Excel::Template::Element
+
+=head1 ATTRIBUTES
+
+=over 4
+
+=item * REF
+
+This is the name of the reference to look up.
+
+=back 4
+
+=head1 CHILDREN
+
+None
+
+=head1 EFFECTS
+
+None
+
+=head1 DEPENDENCIES
+
+This will only be used within CELL tags.
+
+=head1 USAGE
+
+In the example...
+
+ <row>
+ <cell ref="this_cell"/><cell ref="that_cell"><cell ref="that_cell">
+ </row>
+ <row>
+ <formula>=<ref ref="this_cell">+<ref ref="that_cell"></formula>
+ </row>
+
+The formula in row 2 would be =A1+C1. C1 is the last to reference "that_cell".
+
+=head1 AUTHOR
+
+Rob Kinyon (rkinyon@columbus.rr.com)
+
+=head1 SEE ALSO
+
+CELL, RANGE
+
+=cut
--- /dev/null
+package Excel::Template::Element::Cell;
+
+use strict;
+
+BEGIN {
+ use vars qw(@ISA);
+ @ISA = qw(Excel::Template::Element);
+
+ use Excel::Template::Element;
+}
+
+sub new
+{
+ my $class = shift;
+ my $self = $class->SUPER::new(@_);
+
+ $self->{TXTOBJ} = Excel::Template::Factory->create('TEXTOBJECT');
+
+ return $self;
+}
+
+sub get_text
+{
+ my $self = shift;
+ my ($context) = @_;
+
+ my $txt = $context->get($self, 'TEXT');
+ if (defined $txt)
+ {
+ my $txt_obj = Excel::Template::Factory->create('TEXTOBJECT');
+ push @{$txt_obj->{STACK}}, $txt;
+ $txt = $txt_obj->resolve($context);
+ }
+ elsif ($self->{TXTOBJ})
+ {
+ $txt = $self->{TXTOBJ}->resolve($context)
+ }
+ else
+ {
+UNI_YES $txt = Unicode::String::utf8('');
+UNI_NO $txt = '';
+ }
+
+ return $txt;
+}
+
+sub render
+{
+ my $self = shift;
+ my ($context) = @_;
+
+ my ($row, $col) = map { $context->get($self, $_) } qw(ROW COL);
+
+ my $ref = uc $context->get( $self, 'REF' );
+ if (defined $ref && length $ref)
+ {
+ $context->add_reference( $ref, $row, $col );
+ }
+
+ $context->active_worksheet->write(
+ $row, $col,
+ $self->get_text($context),
+ $context->active_format,
+ );
+
+ return 1;
+}
+
+sub deltas
+{
+ return {
+ COL => +1,
+ };
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Excel::Template::Element::Cell - Excel::Template::Element::Cell
+
+=head1 PURPOSE
+
+To actually write stuff to the worksheet
+
+=head1 NODE NAME
+
+CELL
+
+=head1 INHERITANCE
+
+Excel::Template::Element
+
+=head1 ATTRIBUTES
+
+=over 4
+
+=item * TEXT
+
+This is the text to write to the cell. This can either be text or a parameter
+with a dollar-sign in front of the parameter name.
+
+=item * COL
+
+Optionally, you can specify which column you want this cell to be in. It can be
+either a number (zero-based) or an offset. See Excel::Template for more info on
+offset-based numbering.
+
+=back 4
+
+There will be more parameters added, as features are added.
+
+=head1 CHILDREN
+
+Excel::Template::Element::Formula
+
+=head1 EFFECTS
+
+This will consume one column on the current row.
+
+=head1 DEPENDENCIES
+
+None
+
+=head1 USAGE
+
+ <cell text="Some Text Here"/>
+ <cell>Some other text here</cell>
+
+ <cell text="$Param2"/>
+ <cell>Some <var name="Param"> text here</cell>
+
+In the above example, four cells are written out. The first two have text hard-
+coded. The second two have variables. The third and fourth items have another
+thing that should be noted. If you have text where you want a variable in the
+middle, you have to use the latter form. Variables within parameters are the
+entire parameter's value.
+
+Please see Spreadsheet::WriteExcel for what constitutes a legal formula.
+
+=head1 BACK-REFERENCES
+
+Currently, you can only use a hard-coded formula. The next release will add the
+capability to have a formula reference other nodes in the template dynamically.
+
+=head1 AUTHOR
+
+Rob Kinyon (rob.kinyon@gmail.com)
+
+=head1 SEE ALSO
+
+ROW, VAR, FORMULA
+
+=cut
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
--- /dev/null
+package Excel::Template::Element::Range;
+
+use strict;
+use Spreadsheet::WriteExcel::Utility;
+
+BEGIN {
+ use vars qw(@ISA);
+ @ISA = qw(Excel::Template::Element);
+
+ use Excel::Template::Element;
+}
+
+sub min { $_[0] < $_[1] ? $_[0] : $_[1] }
+sub max { $_[0] > $_[1] ? $_[0] : $_[1] }
+
+sub resolve
+{
+ my $self = shift;
+ my ($context) = @_;
+
+ my $ref_name = $context->resolve($self, 'REF');
+
+ my @refs = $context->get_all_references( $ref_name );
+ return '' unless @refs;
+
+ my ($top, $left, $bottom, $right) =
+ ( $refs[0][0], $refs[0][1] ) x 2;
+
+ shift @refs;
+ foreach my $ref ( @refs )
+ {
+ $top = min( $top, $ref->[0]);
+ $bottom = max( $bottom, $ref->[0]);
+ $left = min( $left, $ref->[1]);
+ $right = max( $right, $ref->[1]);
+ }
+
+ return join( ':',
+ xl_rowcol_to_cell($top, $left),
+ xl_rowcol_to_cell($bottom, $right)
+ );
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Excel::Template::Element::Range
+
+=head1 PURPOSE
+
+Returns a range of cell locations (i.e. B2:C2) that contains all calls using this
+reference. To return the location of the last cell, use REF.
+
+=head1 NODE NAME
+
+REF
+
+=head1 INHERITANCE
+
+Excel::Template::Element
+
+=head1 ATTRIBUTES
+
+=over 4
+
+=item * REF
+
+This is the name of the reference to look up.
+
+=back 4
+
+=head1 CHILDREN
+
+None
+
+=head1 EFFECTS
+
+None
+
+=head1 DEPENDENCIES
+
+This will only be used within CELL tags.
+
+=head1 USAGE
+
+In the example...
+
+ <row>
+ <cell ref="this_cell"/><cell ref="that_cell"><cell ref="that_cell">
+ </row>
+ <row>
+ <formula>=SUM(<range ref="that_cell">)</formula>
+ </row>
+
+The formula in row 2 would be =SUM(B1:C1).
+
+=head1 AUTHOR
+
+Rob Kinyon (rkinyon@columbus.rr.com)
+
+=head1 SEE ALSO
+
+CELL, REF
+
+=cut
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
'WORKBOOK' => 'Excel::Template::Container::Workbook',
'WORKSHEET' => 'Excel::Template::Container::Worksheet',
+ 'BACKREF' => 'Excel::Template::Element::Backref',
'CELL' => 'Excel::Template::Element::Cell',
'FORMULA' => 'Excel::Template::Element::Formula',
+ 'RANGE' => 'Excel::Template::Element::Range',
'VAR' => 'Excel::Template::Element::Var',
'FORMAT' => 'Excel::Template::Container::Format',
# These are all the Format short-cut objects
+# They are also instantiable
'BOLD' => 'Excel::Template::Container::Bold',
'HIDDEN' => 'Excel::Template::Container::Hidden',
'ITALIC' => 'Excel::Template::Container::Italic',
'STRIKEOUT' => 'Excel::Template::Container::Strikeout',
# These are the helper objects
-
+# They are also in here to make E::T::Factory::isa() work.
'CONTEXT' => 'Excel::Template::Context',
'ITERATOR' => 'Excel::Template::Iterator',
'TEXTOBJECT' => 'Excel::Template::TextObject',
ITALIC
OUTLINE
LOOP
+ BACKREF
+ RANGE
ROW
SHADOW
STRIKEOUT
: UNIVERSAL::isa(@_)
}
+sub is_embedded
+{
+ return unless @_ >= 1;
+
+ isa( $_[0], $_ ) && return !!1 for qw( VAR BACKREF RANGE );
+ return;
+}
+
1;
__END__
=head1 PURPOSE
-=head1 NODE NAME
+To provide a common way to instantiate Excel::Template nodes
-=head1 INHERITANCE
-
-=head1 ATTRIBUTES
-
-=head1 CHILDREN
+=head1 USAGE
-=head1 AFFECTS
+=head2 register()
-=head1 DEPENDENCIES
+Use this to register your own nodes.
-=head1 USAGE
+Example forthcoming.
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
# formats and making new formats based on old ones.
{
- # %_Parameters is a hash with the key being the format name and the value
- # being the index/length of the format in the bit-vector.
- my %_Formats = (
- bold => [ 0, 1 ],
- italic => [ 1, 1 ],
- locked => [ 2, 1 ],
- hidden => [ 3, 1 ],
- font_outline => [ 4, 1 ],
- font_shadow => [ 5, 1 ],
- font_strikeout => [ 6, 1 ],
+ my %_Formats;
+
+ sub _assign { $_Formats{$_[0]} = $_[1]; $_Formats{$_[1]} = $_[0] }
+# my $key = shift;
+# my $format = shift;
+# $_Formats{$key} = $format;
+# $_Formats{$format} = $key;
+# }
+
+ sub _retrieve_key { $_Formats{ $_[0] } }
+# my $format = shift;
+# return $_Formats{$format};
+# }
+
+ *_retrieve_format = \&_retrieve_key;
+# sub _retrieve_format {
+# my $key = shift;
+# return $_Formats{$key};
+# }
+}
+
+{
+ my @_boolean_formats = qw(
+ bold italic locked hidden font_outline font_shadow font_strikeout
+ text_wrap text_justlast shrink
);
-
- sub _params_to_vec
+
+ my @_integer_formats = qw(
+ size num_format underline rotation indent pattern border
+ bottom top left right
+ );
+
+ my @_string_formats = qw(
+ font color align valign bg_color fg_color border_color
+ bottom_color top_color left_color right_color
+ );
+
+ sub _params_to_key
{
my %params = @_;
$params{lc $_} = delete $params{$_} for keys %params;
-
- my $vec = '';
- vec( $vec, $_Formats{$_}[0], $_Formats{$_}[1] ) = ($params{$_} && 1)
- for grep { exists $_Formats{$_} }
- map { lc } keys %params;
-
- $vec;
+
+ my @parts = (
+ (map { !! $params{$_} } @_boolean_formats),
+ (map { $params{$_} ? $params{$_} + 0 : '' } @_integer_formats),
+ (map { $params{$_} || '' } @_string_formats),
+ );
+
+ return join( "\n", @parts );
}
-
- sub _vec_to_params
+
+ sub _key_to_params
{
- my ($vec) = @_;
-
+ my ($key) = @_;
+
+ my @key_parts = split /\n/, $key;
+
+ my @boolean_parts = splice @key_parts, 0, scalar( @_boolean_formats );
+ my @integer_parts = splice @key_parts, 0, scalar( @_integer_formats );
+ my @string_parts = splice @key_parts, 0, scalar( @_string_formats );
+
my %params;
- while (my ($k, $v) = each %_Formats)
- {
- next unless vec( $vec, $v->[0], $v->[1] );
- $params{$k} = 1;
- }
-
- %params;
- }
-}
+ $params{ $_boolean_formats[$_] } = !!1
+ for grep { $boolean_parts[$_] } 0 .. $#_boolean_formats;
-{
- my %_Formats;
+ $params{ $_integer_formats[$_] } = $integer_parts[$_]
+ for grep { length $integer_parts[$_] } 0 .. $#_integer_formats;
+
+ $params{ $_string_formats[$_] } = $string_parts[$_]
+ for grep { $string_parts[$_] } 0 .. $#_string_formats;
- sub _assign {
- $_Formats{$_[0]} = $_[1] unless exists $_Formats{$_[0]};
- $_Formats{$_[1]} = $_[0] unless exists $_Formats{$_[1]};
+ return %params;
}
- sub _retrieve_vec { ref($_[0]) ? ($_Formats{$_[0]}) : ($_[0]); }
- sub _retrieve_format { ref($_[0]) ? ($_[0]) : ($_Formats{$_[0]}); }
-}
+ sub copy
+ {
+ shift;
+ my ($context, $old_fmt, %properties) = @_;
-sub blank_format
-{
- shift;
- my ($context) = @_;
+ defined(my $key = _retrieve_key($old_fmt))
+ || die "Internal Error: Cannot find key for format '$old_fmt'!\n";
+
+ my %params = _key_to_params($key);
+ PROPERTY:
+ while ( my ($prop, $value) = each %properties )
+ {
+ $prop = lc $prop;
+ foreach (@_boolean_formats)
+ {
+ if ($prop eq $_) {
+ $params{$_} = ($value && $value !~ /false/i);
+ next PROPERTY;
+ }
+ }
+ foreach (@_integer_formats, @_string_formats)
+ {
+ if ($prop eq $_) {
+ $params{$_} = $value;
+ next PROPERTY;
+ }
+ }
+ }
- my $blank_vec = _params_to_vec();
+ my $new_key = _params_to_key(%params);
- my $format = _retrieve_format($blank_vec);
- return $format if $format;
+ my $format = _retrieve_format($new_key);
+ return $format if $format;
- $format = $context->{XLS}->add_format;
- _assign($blank_vec, $format);
- $format;
+ $format = $context->{XLS}->add_format(%params);
+ _assign($new_key, $format);
+ return $format;
+ }
}
-sub copy
+sub blank_format
{
shift;
- my ($context, $old_format, %properties) = @_;
-
- defined(my $vec = _retrieve_vec($old_format))
- || die "Internal Error: Cannot find vector for format '$old_format'!\n";
-
- my $new_vec = _params_to_vec(%properties);
+ my ($context) = @_;
- $new_vec |= $vec;
+ my $blank_key = _params_to_key();
- my $format = _retrieve_format($new_vec);
+ my $format = _retrieve_format($blank_key);
return $format if $format;
- $format = $context->{XLS}->add_format(_vec_to_params($new_vec));
- _assign($new_vec, $format);
- $format;
+ $format = $context->{XLS}->add_format;
+ _assign($blank_key, $format);
+ return $format;
}
1;
__END__
-
-Category Description Property Method Name Implemented
--------- ----------- -------- ----------- -----------
-Font Font type font set_font()
- Font size size set_size()
- Font color color set_color()
- Bold bold set_bold() YES
- Italic italic set_italic() YES
- Underline underline set_underline()
- Strikeout font_strikeout set_font_strikeout() YES
- Super/Subscript font_script set_font_script()
- Outline font_outline set_font_outline() YES
- Shadow font_shadow set_font_shadow() YES
-
-Number Numeric format num_format set_num_format()
-
-Protection Lock cells locked set_locked() YES
- Hide formulas hidden set_hidden() YES
-
-Alignment Horizontal align align set_align()
- Vertical align valign set_align()
- Rotation rotation set_rotation()
- Text wrap text_wrap set_text_wrap()
- Justify last text_justlast set_text_justlast()
- Merge merge set_merge()
-
-Pattern Cell pattern pattern set_pattern()
- Background color bg_color set_bg_color()
- Foreground color fg_color set_fg_color()
-
-Border Cell border border set_border()
- Bottom border bottom set_bottom()
- Top border top set_top()
- Left border left set_left()
- Right border right set_right()
- Border color border_color set_border_color()
- Bottom color bottom_color set_bottom_color()
- Top color top_color set_top_color()
- Left color left_color set_left_color()
- Right color right_color set_right_color()
=head1 AUTHOR
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
=head1 SEE ALSO
--- /dev/null
+package Excel::Template::TextObject;
+
+use strict;
+
+BEGIN {
+ use vars qw(@ISA);
+ @ISA = qw(Excel::Template::Base);
+
+ use Excel::Template::Base;
+
+UNI_YES use Unicode::String;
+}
+
+# This is a helper object. It is not instantiated by the user,
+# nor does it represent an XML object. Rather, certain elements,
+# such as <textbox>, can use this object to do text with variable
+# substitutions.
+
+sub new
+{
+ my $class = shift;
+ my $self = $class->SUPER::new(@_);
+
+ $self->{STACK} = [] unless UNIVERSAL::isa($self->{STACK}, 'ARRAY');
+
+ return $self;
+}
+
+sub resolve
+{
+ my $self = shift;
+ my ($context) = @_;
+
+UNI_YES my $t = Unicode::String::utf8('');
+UNI_NO my $t = '';
+
+ for my $tok (@{$self->{STACK}})
+ {
+ my $val = $tok;
+ $val = $val->resolve($context)
+ if Excel::Template::Factory::is_embedded( $val );
+
+UNI_YES $t .= Unicode::String::utf8("$val");
+UNI_NO $t .= $val;
+ }
+
+ return $t;
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Excel::Template::TextObject
+
+=head1 PURPOSE
+
+=head1 NODE NAME
+
+=head1 INHERITANCE
+
+=head1 ATTRIBUTES
+
+=head1 CHILDREN
+
+=head1 AFFECTS
+
+=head1 DEPENDENCIES
+
+=head1 USAGE
+
+=head1 AUTHOR
+
+Rob Kinyon (rob.kinyon@gmail.com)
+
+=head1 SEE ALSO
+
+=cut