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 object. 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->{ACTIVE_FORMAT} = Excel::Template::Format->blank_format($self);
30 $self->{WORKSHEET_NAMES} = undef;
32 # Removed NAME_MAP until I figure out what the heck it's for
33 for (qw( STACK PARAM_MAP ))
35 next if defined $self->{$_} && ref $self->{$_} eq 'ARRAY';
39 $self->{$_} = 0 for keys %isAbsolute;
44 sub use_unicode { $_[0]->{UNICODE} && 1 }
46 sub _find_param_in_map
49 my ($map, $param, $depth) = @_;
54 for my $map (reverse @{$self->{$map}})
56 next unless exists $map->{$param};
57 $depth--, next if $depth;
60 $val = $map->{$param};
64 die "Parameter '$param' not found\n"
65 if !$found && $self->{DIE_ON_NO_PARAM};
73 $self->_find_param_in_map(
82 # $self->_find_param_in_map(
91 my ($obj, $key, $depth) = @_;
95 my $obj_val = $obj->{$key};
97 $obj_val = $self->param($1)
98 if $obj_val =~ /^\$(\S+)$/o;
100 #GGG Remove this once NAME_MAP is working
101 # $obj_val = $self->named_param($1)
102 # if $obj_val =~ /^\\(\S+)$/o;
104 #GGG Does this adequately test values to make sure they're legal??
105 # A value is defined as:
106 # 1) An optional operator (+, -, *, or /)
107 # 2) A decimal number
109 #GGG Convert this to use //x
110 my ($op, $val) = $obj_val =~ m!^\s*([\+\*\/\-])?\s*([\d.]*\d)\s*$!oi;
112 # Unless it's a relative value, we have what we came for.
113 return $obj_val unless $op;
115 my $prev_val = $isAbsolute{$key}
117 : $self->get($obj, $key, $depth + 1);
119 return $obj_val unless defined $prev_val;
120 return $prev_val unless defined $obj_val;
122 # Prevent divide-by-zero issues.
123 return $val if $op eq '/' and $val == 0;
128 /^\+$/ && do { $new_val = ($prev_val + $val); last; };
129 /^\-$/ && do { $new_val = ($prev_val - $val); last; };
130 /^\*$/ && do { $new_val = ($prev_val * $val); last; };
131 /^\/$/ && do { $new_val = ($prev_val / $val); last; };
133 die "Unknown operator '$op' in arithmetic resolve\n";
136 return $new_val if defined $new_val;
145 push @{$self->{STACK}}, $obj;
147 for my $key (keys %isAbsolute)
149 next unless exists $obj->{$key};
150 $self->{$key} = $self->resolve($obj, $key);
159 my ($obj, $no_delta) = @_;
163 my $deltas = $obj->deltas($self);
164 $self->{$_} += $deltas->{$_} for keys %$deltas;
167 pop @{$self->{STACK}};
175 my ($dummy, $key, $depth) = @_;
179 return unless @{$self->{STACK}};
181 my $obj = $self->{STACK}[-1];
183 return $self->{$key} if $isAbsolute{$key};
186 my $this_depth = $depth;
187 foreach my $e (reverse @{$self->{STACK}})
189 next unless exists $e->{$key};
190 next if $this_depth-- > 0;
192 $val = $self->resolve($e, $key, $depth);
196 $val = $self->{$key} unless defined $val;
197 return $val unless defined $val;
199 return $self->param($1, $depth) if $val =~ /^\$(\S+)$/o;
208 $self->{ACTIVE_FORMAT} = $_[0]
211 $self->{ACTIVE_FORMAT};
217 my ($worksheet) = @_;
219 $self->{ROW} = $self->{COL} = 0;
220 $self->{REFERENCES} = {};
222 my $name = $self->get( $worksheet, 'NAME' );
224 if ( defined $name && length $name )
226 if ( exists $self->{WORKSHEET_NAMES}{$name} )
232 $self->{WORKSHEET_NAMES}{$name} = undef;
240 $self->active_worksheet(
241 $self->{XLS}->add_worksheet( $name ),
249 $self->{ACTIVE_WORKSHEET} = $_[0]
252 $self->{ACTIVE_WORKSHEET};
258 my ($ref, $row, $col) = @_;
260 $self->{REFERENCES}{$ref} ||= [];
262 push @{$self->{REFERENCES}{$ref}}, [ $row, $col ];
267 sub get_all_references
272 $self->{REFERENCES}{$ref} ||= [];
274 return @{ $self->{REFERENCES}{$ref} };
277 sub get_last_reference
282 $self->{REFERENCES}{$ref} ||= [];
284 return @{ $self->{REFERENCES}{$ref}[-1] };
292 Excel::Template::Context
296 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.
298 Documentation is provided for if you wish to subclass another node.
328 =head2 active_worksheet
334 =head2 get_all_references
336 =head2 get_last_reference
348 Rob Kinyon (rob.kinyon@gmail.com)