From: Rob Kinyon Date: Thu, 4 Nov 2004 21:15:38 +0000 (+0000) Subject: Tagging for v0.15 X-Git-Tag: v0.15 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=2b7b7e9040dfed53e6497a77a078d5d16d3d93af;p=p5sagit%2FExcel-Template.git Tagging for v0.15 --- diff --git a/trunk/Changes b/trunk/Changes index f1e84ad..05e7456 100644 --- a/trunk/Changes +++ b/trunk/Changes @@ -1,4 +1,23 @@ -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 diff --git a/trunk/MANIFEST b/trunk/MANIFEST index 0ff82b1..88d5c49 100644 --- a/trunk/MANIFEST +++ b/trunk/MANIFEST @@ -11,7 +11,7 @@ lib/Excel/Template/Element.pm 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 @@ -26,8 +26,11 @@ lib/Excel/Template/Container/Strikeout.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) diff --git a/trunk/Makefile.PL b/trunk/Makefile.PL index 89504ef..a7aefc3 100644 --- a/trunk/Makefile.PL +++ b/trunk/Makefile.PL @@ -1,16 +1,84 @@ 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 = ; + 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 = ; + 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; +} diff --git a/trunk/lib/Excel/Template.pm b/trunk/lib/Excel/Template.pm index 665405b..1d7626e 100644 --- a/trunk/lib/Excel/Template.pm +++ b/trunk/lib/Excel/Template.pm @@ -6,7 +6,7 @@ BEGIN { use Excel::Template::Base; use vars qw ($VERSION @ISA); - $VERSION = '0.12'; + $VERSION = '0.15'; @ISA = qw( Excel::Template::Base ); } @@ -123,11 +123,11 @@ sub parse_xml 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; @@ -341,7 +341,21 @@ but I expect to be adding on to it very soon. =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 diff --git a/trunk/lib/Excel/Template/Base.pm b/trunk/lib/Excel/Template/Base.pm index 9788c11..9215ac5 100644 --- a/trunk/lib/Excel/Template/Base.pm +++ b/trunk/lib/Excel/Template/Base.pm @@ -25,6 +25,7 @@ sub new } sub isa { Excel::Template::Factory::isa(@_) } +sub is_embedded { Excel::Template::Factory::is_embedded(@_) } sub calculate { ($_[1])->get(@_[0,2]) } #{ diff --git a/trunk/lib/Excel/Template/Container.pm b/trunk/lib/Excel/Template/Container.pm index 97d6972..51ed783 100644 --- a/trunk/lib/Excel/Template/Container.pm +++ b/trunk/lib/Excel/Template/Container.pm @@ -140,7 +140,7 @@ Excel::Template::Container =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Container/Bold.pm b/trunk/lib/Excel/Template/Container/Bold.pm index f4b345f..6e53931 100644 --- a/trunk/lib/Excel/Template/Container/Bold.pm +++ b/trunk/lib/Excel/Template/Container/Bold.pm @@ -66,7 +66,7 @@ elements) in a bold format. All other formatting will remain the same and the =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Container/Conditional.pm b/trunk/lib/Excel/Template/Container/Conditional.pm index cd7ec75..89cf668 100644 --- a/trunk/lib/Excel/Template/Container/Conditional.pm +++ b/trunk/lib/Excel/Template/Container/Conditional.pm @@ -180,7 +180,7 @@ In the above example, the children will be executed if the value of __ODD__ =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Container/Format.pm b/trunk/lib/Excel/Template/Container/Format.pm index 3574362..c272e15 100644 --- a/trunk/lib/Excel/Template/Container/Format.pm +++ b/trunk/lib/Excel/Template/Container/Format.pm @@ -27,6 +27,8 @@ sub render my $child_success = $self->iterate_over_children($context); $context->active_format($old_format); + + return $child_success; } 1; @@ -52,19 +54,55 @@ Excel::Template::Container =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 @@ -74,13 +112,87 @@ OUTLINE tag) =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 @@ -107,7 +219,7 @@ elements) in a bold format. All other formatting will remain the same and the =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Container/Hidden.pm b/trunk/lib/Excel/Template/Container/Hidden.pm index 97f8f08..9b18489 100644 --- a/trunk/lib/Excel/Template/Container/Hidden.pm +++ b/trunk/lib/Excel/Template/Container/Hidden.pm @@ -66,7 +66,7 @@ elements) in a hidden format. All other formatting will remain the same and the =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Container/Italic.pm b/trunk/lib/Excel/Template/Container/Italic.pm index f4f4e00..e74439b 100644 --- a/trunk/lib/Excel/Template/Container/Italic.pm +++ b/trunk/lib/Excel/Template/Container/Italic.pm @@ -66,7 +66,7 @@ elements) in a italic format. All other formatting will remain the same and the =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Container/Locked.pm b/trunk/lib/Excel/Template/Container/Locked.pm index 55cab43..4ad52d9 100644 --- a/trunk/lib/Excel/Template/Container/Locked.pm +++ b/trunk/lib/Excel/Template/Container/Locked.pm @@ -66,7 +66,7 @@ elements) in a locked format. All other formatting will remain the same and the =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Container/Loop.pm b/trunk/lib/Excel/Template/Container/Loop.pm index 574ca5f..16e0cbc 100644 --- a/trunk/lib/Excel/Template/Container/Loop.pm +++ b/trunk/lib/Excel/Template/Container/Loop.pm @@ -172,7 +172,7 @@ also hide outside variables with inner values, if you desire, just like Perl. =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Container/Outline.pm b/trunk/lib/Excel/Template/Container/Outline.pm index a13447b..d2551e6 100644 --- a/trunk/lib/Excel/Template/Container/Outline.pm +++ b/trunk/lib/Excel/Template/Container/Outline.pm @@ -66,7 +66,7 @@ elements) in a outline format. All other formatting will remain the same and the =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Container/Row.pm b/trunk/lib/Excel/Template/Container/Row.pm index cc5c3d1..fc0323f 100644 --- a/trunk/lib/Excel/Template/Container/Row.pm +++ b/trunk/lib/Excel/Template/Container/Row.pm @@ -72,7 +72,7 @@ Generally, you will have CELL and/or FORMULA tags within a ROW. =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Container/Scope.pm b/trunk/lib/Excel/Template/Container/Scope.pm index 97c4124..700e720 100644 --- a/trunk/lib/Excel/Template/Container/Scope.pm +++ b/trunk/lib/Excel/Template/Container/Scope.pm @@ -59,7 +59,7 @@ all has the same set of parameter values, but don't have a common parent. =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Container/Shadow.pm b/trunk/lib/Excel/Template/Container/Shadow.pm index 8597218..bd7502e 100644 --- a/trunk/lib/Excel/Template/Container/Shadow.pm +++ b/trunk/lib/Excel/Template/Container/Shadow.pm @@ -66,7 +66,7 @@ elements) in a shadow format. All other formatting will remain the same and the =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Container/Strikeout.pm b/trunk/lib/Excel/Template/Container/Strikeout.pm index bc6b96b..3630831 100644 --- a/trunk/lib/Excel/Template/Container/Strikeout.pm +++ b/trunk/lib/Excel/Template/Container/Strikeout.pm @@ -66,7 +66,7 @@ elements) in a bold format. All other formatting will remain the same and the =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Container/Workbook.pm b/trunk/lib/Excel/Template/Container/Workbook.pm index 2defd37..cbc9f3b 100644 --- a/trunk/lib/Excel/Template/Container/Workbook.pm +++ b/trunk/lib/Excel/Template/Container/Workbook.pm @@ -53,7 +53,7 @@ None =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Container/Worksheet.pm b/trunk/lib/Excel/Template/Container/Worksheet.pm index c707779..6a1edaf 100644 --- a/trunk/lib/Excel/Template/Container/Worksheet.pm +++ b/trunk/lib/Excel/Template/Container/Worksheet.pm @@ -14,7 +14,7 @@ sub render my $self = shift; my ($context) = @_; - $context->new_worksheet($self->{NAME}); + $context->new_worksheet( $self ); return $self->SUPER::render($context); } @@ -71,7 +71,7 @@ In the above example, the children will be executed in the context of the =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Context.pm b/trunk/lib/Excel/Template/Context.pm index 79c5415..7a66225 100644 --- a/trunk/lib/Excel/Template/Context.pm +++ b/trunk/lib/Excel/Template/Context.pm @@ -15,7 +15,7 @@ use Excel::Template::Format; # 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 ); @@ -27,6 +27,7 @@ sub new $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 ); @@ -43,15 +44,13 @@ sub _find_param_in_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; } @@ -145,7 +144,7 @@ sub enter_scope $self->{$key} = $self->resolve($obj, $key); } - return 1; + return !!1; } sub exit_scope @@ -161,7 +160,7 @@ sub exit_scope pop @{$self->{STACK}}; - return 1; + return !!1; } sub get @@ -209,14 +208,31 @@ sub active_format 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 ), ); } @@ -230,6 +246,38 @@ sub active_worksheet $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__ @@ -255,7 +303,7 @@ Excel::Template::Context =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Element.pm b/trunk/lib/Excel/Template/Element.pm index 4ca8284..16d4d9c 100644 --- a/trunk/lib/Excel/Template/Element.pm +++ b/trunk/lib/Excel/Template/Element.pm @@ -34,7 +34,7 @@ Excel::Template::Element =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Element/Backref.pm b/trunk/lib/Excel/Template/Element/Backref.pm new file mode 100755 index 0000000..fe82f1b --- /dev/null +++ b/trunk/lib/Excel/Template/Element/Backref.pm @@ -0,0 +1,89 @@ +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... + + + + + + =+ + + +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 diff --git a/trunk/lib/Excel/Template/Element/Cell.pm_ b/trunk/lib/Excel/Template/Element/Cell.pm_ new file mode 100755 index 0000000..e09a4c2 --- /dev/null +++ b/trunk/lib/Excel/Template/Element/Cell.pm_ @@ -0,0 +1,155 @@ +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 + + + Some other text here + + + Some text here + +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 diff --git a/trunk/lib/Excel/Template/Element/Formula.pm b/trunk/lib/Excel/Template/Element/Formula.pm index 094326e..3de93b0 100644 --- a/trunk/lib/Excel/Template/Element/Formula.pm +++ b/trunk/lib/Excel/Template/Element/Formula.pm @@ -100,7 +100,7 @@ parameters are the entire parameter's value. =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Element/Range.pm b/trunk/lib/Excel/Template/Element/Range.pm new file mode 100755 index 0000000..c880654 --- /dev/null +++ b/trunk/lib/Excel/Template/Element/Range.pm @@ -0,0 +1,107 @@ +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... + + + + + + =SUM() + + +The formula in row 2 would be =SUM(B1:C1). + +=head1 AUTHOR + +Rob Kinyon (rkinyon@columbus.rr.com) + +=head1 SEE ALSO + +CELL, REF + +=cut diff --git a/trunk/lib/Excel/Template/Element/Var.pm b/trunk/lib/Excel/Template/Element/Var.pm index b4eac2f..74bfede 100644 --- a/trunk/lib/Excel/Template/Element/Var.pm +++ b/trunk/lib/Excel/Template/Element/Var.pm @@ -66,7 +66,7 @@ Where the actual name to be substituted is, itself, a parameter. =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/Factory.pm b/trunk/lib/Excel/Template/Factory.pm index 6b806c9..7a0a6a4 100644 --- a/trunk/lib/Excel/Template/Factory.pm +++ b/trunk/lib/Excel/Template/Factory.pm @@ -16,13 +16,16 @@ BEGIN { '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', @@ -32,7 +35,7 @@ BEGIN { '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', @@ -52,6 +55,8 @@ BEGIN { ITALIC OUTLINE LOOP + BACKREF + RANGE ROW SHADOW STRIKEOUT @@ -135,6 +140,14 @@ sub isa : UNIVERSAL::isa(@_) } +sub is_embedded +{ + return unless @_ >= 1; + + isa( $_[0], $_ ) && return !!1 for qw( VAR BACKREF RANGE ); + return; +} + 1; __END__ @@ -144,23 +157,19 @@ Excel::Template::Factory =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 diff --git a/trunk/lib/Excel/Template/Format.pm b/trunk/lib/Excel/Template/Format.pm index dcd2a1f..77c0056 100644 --- a/trunk/lib/Excel/Template/Format.pm +++ b/trunk/lib/Excel/Template/Format.pm @@ -10,132 +10,134 @@ use strict; # 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() diff --git a/trunk/lib/Excel/Template/Iterator.pm b/trunk/lib/Excel/Template/Iterator.pm index bdd74e2..ccdc8b1 100644 --- a/trunk/lib/Excel/Template/Iterator.pm +++ b/trunk/lib/Excel/Template/Iterator.pm @@ -204,7 +204,7 @@ Excel::Template::Iterator =head1 AUTHOR -Rob Kinyon (rkinyon@columbus.rr.com) +Rob Kinyon (rob.kinyon@gmail.com) =head1 SEE ALSO diff --git a/trunk/lib/Excel/Template/TextObject.pm_ b/trunk/lib/Excel/Template/TextObject.pm_ new file mode 100755 index 0000000..8fa6b47 --- /dev/null +++ b/trunk/lib/Excel/Template/TextObject.pm_ @@ -0,0 +1,79 @@ +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 , 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