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 for (qw( STACK PARAM_MAP NAME_MAP ))
34 next if defined $self->{$_} && UNIVERSAL::isa($self->{$_}, 'ARRAY');
38 $self->{$_} = 0 for keys %isAbsolute;
43 sub use_unicode { $_[0]->{UNICODE} && 1 }
45 sub _find_param_in_map
48 my ($map, $param, $depth) = @_;
53 for my $map (reverse @{$self->{$map}})
55 next unless exists $map->{$param};
56 $depth--, next if $depth;
59 $val = $map->{$param};
63 die "Parameter '$param' not found\n"
64 if !$found && $self->{DIE_ON_NO_PARAM};
72 $self->_find_param_in_map(
81 $self->_find_param_in_map(
90 my ($obj, $key, $depth) = @_;
94 my $obj_val = $obj->{$key};
96 $obj_val = $self->param($1)
97 if $obj_val =~ /^\$(\S+)$/o;
99 #GGG Remove this once NAME_MAP is working
100 # $obj_val = $self->named_param($1)
101 # if $obj_val =~ /^\\(\S+)$/o;
103 #GGG Does this adequately test values to make sure they're legal??
104 # A value is defined as:
105 # 1) An optional operator (+, -, *, or /)
106 # 2) A decimal number
108 #GGG Convert this to use //x
109 my ($op, $val) = $obj_val =~ m!^\s*([\+\*\/\-])?\s*([\d.]*\d)\s*$!oi;
111 # Unless it's a relative value, we have what we came for.
112 return $obj_val unless $op;
114 my $prev_val = $isAbsolute{$key}
116 : $self->get($obj, $key, $depth + 1);
118 return $obj_val unless defined $prev_val;
119 return $prev_val unless defined $obj_val;
121 # Prevent divide-by-zero issues.
122 return $val if $op eq '/' and $val == 0;
127 /^\+$/ && do { $new_val = ($prev_val + $val); last; };
128 /^\-$/ && do { $new_val = ($prev_val - $val); last; };
129 /^\*$/ && do { $new_val = ($prev_val * $val); last; };
130 /^\/$/ && do { $new_val = ($prev_val / $val); last; };
132 die "Unknown operator '$op' in arithmetic resolve\n";
135 return $new_val if defined $new_val;
144 push @{$self->{STACK}}, $obj;
146 for my $key (keys %isAbsolute)
148 next unless exists $obj->{$key};
149 $self->{$key} = $self->resolve($obj, $key);
158 my ($obj, $no_delta) = @_;
162 my $deltas = $obj->deltas($self);
163 $self->{$_} += $deltas->{$_} for keys %$deltas;
166 pop @{$self->{STACK}};
174 my ($dummy, $key, $depth) = @_;
178 return unless @{$self->{STACK}};
180 my $obj = $self->{STACK}[-1];
182 return $self->{$key} if $isAbsolute{$key};
185 my $this_depth = $depth;
186 foreach my $e (reverse @{$self->{STACK}})
188 next unless exists $e->{$key};
189 next if $this_depth-- > 0;
191 $val = $self->resolve($e, $key, $depth);
195 $val = $self->{$key} unless defined $val;
196 return $val unless defined $val;
198 return $self->param($1, $depth) if $val =~ /^\$(\S+)$/o;
207 $self->{ACTIVE_FORMAT} = $_[0]
210 $self->{ACTIVE_FORMAT};
216 my ($worksheet) = @_;
218 $self->{ROW} = $self->{COL} = 0;
219 $self->{REFERENCES} = {};
221 my $name = $self->get( $worksheet, 'NAME' );
223 if ( defined $name && length $name )
225 if ( exists $self->{WORKSHEET_NAMES}{$name} )
231 $self->{WORKSHEET_NAMES}{$name} = undef;
239 $self->active_worksheet(
240 $self->{XLS}->add_worksheet( $name ),
248 $self->{ACTIVE_WORKSHEET} = $_[0]
251 $self->{ACTIVE_WORKSHEET};
257 my ($ref, $row, $col) = @_;
259 $self->{REFERENCES}{$ref} ||= [];
261 push @{$self->{REFERENCES}{$ref}}, [ $row, $col ];
266 sub get_all_references
271 $self->{REFERENCES}{$ref} ||= [];
273 return @{ $self->{REFERENCES}{$ref} };
276 sub get_last_reference
281 $self->{REFERENCES}{$ref} ||= [];
283 return @{ $self->{REFERENCES}{$ref}[-1] };
291 Excel::Template::Context
295 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.
297 Documentation is provided for if you wish to subclass another node.
327 =head2 active_worksheet
333 =head2 get_all_references
335 =head2 get_last_reference
347 Rob Kinyon (rob.kinyon@gmail.com)