Tagging for v0.15 v0.15
Rob Kinyon [Thu, 4 Nov 2004 21:15:38 +0000 (21:15 +0000)]
31 files changed:
trunk/Changes
trunk/MANIFEST
trunk/Makefile.PL
trunk/lib/Excel/Template.pm
trunk/lib/Excel/Template/Base.pm
trunk/lib/Excel/Template/Container.pm
trunk/lib/Excel/Template/Container/Bold.pm
trunk/lib/Excel/Template/Container/Conditional.pm
trunk/lib/Excel/Template/Container/Format.pm
trunk/lib/Excel/Template/Container/Hidden.pm
trunk/lib/Excel/Template/Container/Italic.pm
trunk/lib/Excel/Template/Container/Locked.pm
trunk/lib/Excel/Template/Container/Loop.pm
trunk/lib/Excel/Template/Container/Outline.pm
trunk/lib/Excel/Template/Container/Row.pm
trunk/lib/Excel/Template/Container/Scope.pm
trunk/lib/Excel/Template/Container/Shadow.pm
trunk/lib/Excel/Template/Container/Strikeout.pm
trunk/lib/Excel/Template/Container/Workbook.pm
trunk/lib/Excel/Template/Container/Worksheet.pm
trunk/lib/Excel/Template/Context.pm
trunk/lib/Excel/Template/Element.pm
trunk/lib/Excel/Template/Element/Backref.pm [new file with mode: 0755]
trunk/lib/Excel/Template/Element/Cell.pm_ [new file with mode: 0755]
trunk/lib/Excel/Template/Element/Formula.pm
trunk/lib/Excel/Template/Element/Range.pm [new file with mode: 0755]
trunk/lib/Excel/Template/Element/Var.pm
trunk/lib/Excel/Template/Factory.pm
trunk/lib/Excel/Template/Format.pm
trunk/lib/Excel/Template/Iterator.pm
trunk/lib/Excel/Template/TextObject.pm_ [new file with mode: 0755]

index f1e84ad..05e7456 100644 (file)
@@ -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
index 0ff82b1..88d5c49 100644 (file)
@@ -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)
index 89504ef..a7aefc3 100644 (file)
@@ -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 = <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;
+}
index 665405b..1d7626e 100644 (file)
@@ -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
 
index 9788c11..9215ac5 100644 (file)
@@ -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]) }
 #{
index 97d6972..51ed783 100644 (file)
@@ -140,7 +140,7 @@ Excel::Template::Container
 
 =head1 AUTHOR
 
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
 
 =head1 SEE ALSO
 
index f4b345f..6e53931 100644 (file)
@@ -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
 
index cd7ec75..89cf668 100644 (file)
@@ -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
 
index 3574362..c272e15 100644 (file)
@@ -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
 
index 97f8f08..9b18489 100644 (file)
@@ -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
 
index f4f4e00..e74439b 100644 (file)
@@ -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
 
index 55cab43..4ad52d9 100644 (file)
@@ -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
 
index 574ca5f..16e0cbc 100644 (file)
@@ -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
 
index a13447b..d2551e6 100644 (file)
@@ -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
 
index cc5c3d1..fc0323f 100644 (file)
@@ -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
 
index 97c4124..700e720 100644 (file)
@@ -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
 
index 8597218..bd7502e 100644 (file)
@@ -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
 
index bc6b96b..3630831 100644 (file)
@@ -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
 
index 2defd37..cbc9f3b 100644 (file)
@@ -53,7 +53,7 @@ None
 
 =head1 AUTHOR
 
-Rob Kinyon (rkinyon@columbus.rr.com)
+Rob Kinyon (rob.kinyon@gmail.com)
 
 =head1 SEE ALSO
 
index c707779..6a1edaf 100644 (file)
@@ -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
 
index 79c5415..7a66225 100644 (file)
@@ -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
 
index 4ca8284..16d4d9c 100644 (file)
@@ -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 (executable)
index 0000000..fe82f1b
--- /dev/null
@@ -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...
+
+  <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
diff --git a/trunk/lib/Excel/Template/Element/Cell.pm_ b/trunk/lib/Excel/Template/Element/Cell.pm_
new file mode 100755 (executable)
index 0000000..e09a4c2
--- /dev/null
@@ -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
+
+  <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
index 094326e..3de93b0 100644 (file)
@@ -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 (executable)
index 0000000..c880654
--- /dev/null
@@ -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...
+
+  <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
index b4eac2f..74bfede 100644 (file)
@@ -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
 
index 6b806c9..7a0a6a4 100644 (file)
@@ -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
 
index dcd2a1f..77c0056 100644 (file)
@@ -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()
index bdd74e2..ccdc8b1 100644 (file)
@@ -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 (executable)
index 0000000..8fa6b47
--- /dev/null
@@ -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 <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