1 package Excel::Template::Context;
7 @ISA = qw(Excel::Template::Base);
9 use Excel::Template::Base;
12 use Excel::Template::Format;
14 # This is a helper object. It is not instantiated by the user, nor does it
15 # represent an XML node. Rather, every container will use this object to
16 # maintain the context for its children.
18 my %isAbsolute = map { $_ => ~~1 } qw(
26 my $self = $class->SUPER::new(@_);
28 $self->{ACTIVE_WORKSHEET} = undef;
29 $self->{FORMAT_OBJECT} = Excel::Template::Format->new;
30 $self->{ACTIVE_FORMAT} = $self->{FORMAT_OBJECT}->blank_format($self);
31 $self->{WORKSHEET_NAMES} = undef;
33 $self->{__MARKS} = {};
35 # Removed NAME_MAP until I figure out what the heck it's for
36 for (qw( STACK PARAM_MAP ))
38 next if defined $self->{$_} && ref $self->{$_} eq 'ARRAY';
42 $self->{$_} = 0 for keys %isAbsolute;
47 sub use_unicode { $_[0]->{UNICODE} && 1 }
49 sub _find_param_in_map
52 my ($map, $param, $depth) = @_;
57 for my $map (reverse @{$self->{$map}})
59 next unless exists $map->{$param};
60 $depth--, next if $depth;
63 $val = $map->{$param};
67 die "Parameter '$param' not found\n"
68 if !$found && $self->{DIE_ON_NO_PARAM};
76 $self->_find_param_in_map(
85 # $self->_find_param_in_map(
94 my ($obj, $key, $depth) = @_;
98 my $obj_val = $obj->{$key};
100 $obj_val = $self->param($1)
101 if $obj_val =~ /^\$(\S+)$/o;
103 #GGG Remove this once NAME_MAP is working
104 # $obj_val = $self->named_param($1)
105 # if $obj_val =~ /^\\(\S+)$/o;
107 #GGG Does this adequately test values to make sure they're legal??
108 # A value is defined as:
109 # 1) An optional operator (+, -, *, or /)
110 # 2) A decimal number
112 #GGG Convert this to use //x
113 my ($op, $val) = $obj_val =~ m/^\s*([\+\*\/\-])?\s*([\d.]*\d)\s*$/oi;
115 # Unless it's a relative value, we have what we came for.
116 return $obj_val unless $op;
118 my $prev_val = $isAbsolute{$key}
120 : $self->get($obj, $key, $depth + 1);
122 return $obj_val unless defined $prev_val;
123 return $prev_val unless defined $obj_val;
125 # Prevent divide-by-zero issues.
126 return $prev_val if $op eq '/' and $val == 0;
131 /^\+$/ && do { $new_val = ($prev_val + $val); last; };
132 /^\-$/ && do { $new_val = ($prev_val - $val); last; };
133 /^\*$/ && do { $new_val = ($prev_val * $val); last; };
134 /^\/$/ && do { $new_val = ($prev_val / $val); last; };
136 die "Unknown operator '$op' in arithmetic resolve\n";
139 return $new_val if defined $new_val;
148 push @{$self->{STACK}}, $obj;
150 for my $key (keys %isAbsolute)
152 next unless exists $obj->{$key};
153 $self->{$key} = $self->resolve($obj, $key);
162 my ($obj, $no_delta) = @_;
166 my $deltas = $obj->deltas($self);
167 $self->{$_} += $deltas->{$_} for keys %$deltas;
170 pop @{$self->{STACK}};
178 my ($dummy, $key, $depth) = @_;
182 return unless @{$self->{STACK}};
184 my $obj = $self->{STACK}[-1];
186 return $self->{$key} if $isAbsolute{$key};
189 my $this_depth = $depth;
190 foreach my $e (reverse @{$self->{STACK}})
192 next unless exists $e->{$key};
193 next if $this_depth-- > 0;
195 $val = $self->resolve($e, $key, $depth);
199 $val = $self->{$key} unless defined $val;
200 return $val unless defined $val;
202 return $self->param($1, $depth) if $val =~ /^\$(\S+)$/o;
211 $self->{ACTIVE_FORMAT} = $_[0]
214 $self->{ACTIVE_FORMAT};
220 my ($worksheet) = @_;
222 $self->{ROW} = $self->{COL} = 0;
223 $self->{REFERENCES} = {};
225 my $name = $self->get( $worksheet, 'NAME' );
227 if ( defined $name && length $name )
229 if ( exists $self->{WORKSHEET_NAMES}{$name} )
235 $self->{WORKSHEET_NAMES}{$name} = undef;
243 return $self->active_worksheet(
244 $self->{XLS}->add_worksheet( $name ),
256 @{$self->{__MARKS}}{keys %args} = values %args;
259 return $self->{__MARKS}{$_[0]}
266 $self->{ACTIVE_WORKSHEET} = $_[0]
269 $self->{ACTIVE_WORKSHEET};
275 my ($ref, $row, $col) = @_;
277 $self->{REFERENCES}{$ref} ||= [];
279 push @{$self->{REFERENCES}{$ref}}, [ $row, $col ];
284 sub get_all_references
289 $self->{REFERENCES}{$ref} ||= [];
291 return @{ $self->{REFERENCES}{$ref} };
294 sub get_last_reference
299 $self->{REFERENCES}{$ref} ||= [];
301 return @{ $self->{REFERENCES}{$ref}[-1] };
304 sub format_object { $_[0]{FORMAT_OBJECT} }
311 Excel::Template::Context
315 This is a helper node that provides the global context for the nodes do their processing within. It provides attribute scoping, parameter resolution, and other very nice things.
317 Documentation is provided for if you wish to subclass another node.
347 =head2 active_worksheet
355 =head2 get_all_references
357 =head2 get_last_reference
369 Rob Kinyon (rob.kinyon@gmail.com)