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);
31 UNIVERSAL::isa($self->{$_}, 'ARRAY') || ($self->{$_} = [])
32 for qw( STACK PARAM_MAP NAME_MAP );
34 $self->{$_} = 0 for keys %isAbsolute;
39 sub _find_param_in_map
42 my ($map, $param, $depth) = @_;
49 for my $map (reverse @{$self->{$map}})
51 next unless exists $map->{$param};
52 $depth--, next if $depth;
55 $val = $map->{$param};
59 die "Parameter '$param' not found\n"
60 if !$found && $self->{DIE_ON_NO_PARAM};
68 $self->_find_param_in_map(
77 $self->_find_param_in_map(
86 my ($obj, $key, $depth) = @_;
90 my $obj_val = $obj->{$key};
92 $obj_val = $self->param($1)
93 if $obj_val =~ /^\$(\S+)$/o;
95 #GGG Remove this once NAME_MAP is working
96 # $obj_val = $self->named_param($1)
97 # if $obj_val =~ /^\\(\S+)$/o;
99 #GGG Does this adequately test values to make sure they're legal??
100 # A value is defined as:
101 # 1) An optional operator (+, -, *, or /)
102 # 2) A decimal number
104 #GGG Convert this to use //x
105 my ($op, $val) = $obj_val =~ m!^\s*([\+\*\/\-])?\s*([\d.]*\d)\s*$!oi;
107 # Unless it's a relative value, we have what we came for.
108 return $obj_val unless $op;
110 my $prev_val = $isAbsolute{$key}
112 : $self->get($obj, $key, $depth + 1);
114 return $obj_val unless defined $prev_val;
115 return $prev_val unless defined $obj_val;
117 # Prevent divide-by-zero issues.
118 return $val if $op eq '/' and $val == 0;
123 /^\+$/ && do { $new_val = ($prev_val + $val); last; };
124 /^\-$/ && do { $new_val = ($prev_val - $val); last; };
125 /^\*$/ && do { $new_val = ($prev_val * $val); last; };
126 /^\/$/ && do { $new_val = ($prev_val / $val); last; };
128 die "Unknown operator '$op' in arithmetic resolve\n";
131 return $new_val if defined $new_val;
140 push @{$self->{STACK}}, $obj;
142 for my $key (keys %isAbsolute)
144 next unless exists $obj->{$key};
145 $self->{$key} = $self->resolve($obj, $key);
154 my ($obj, $no_delta) = @_;
158 my $deltas = $obj->deltas($self);
159 $self->{$_} += $deltas->{$_} for keys %$deltas;
162 pop @{$self->{STACK}};
170 my ($dummy, $key, $depth) = @_;
174 return unless @{$self->{STACK}};
176 my $obj = $self->{STACK}[-1];
178 return $self->{$key} if $isAbsolute{$key};
181 my $this_depth = $depth;
182 foreach my $e (reverse @{$self->{STACK}})
184 next unless exists $e->{$key};
185 next if $this_depth-- > 0;
187 $val = $self->resolve($e, $key, $depth);
191 $val = $self->{$key} unless defined $val;
192 return $val unless defined $val;
194 return $self->param($1, $depth) if $val =~ /^\$(\S+)$/o;
203 $self->{ACTIVE_FORMAT} = $_[0]
206 $self->{ACTIVE_FORMAT};
214 $self->{ROW} = $self->{COL} = 0;
216 $self->active_worksheet(
217 $self->{XLS}->add_worksheet(
227 $self->{ACTIVE_WORKSHEET} = $_[0]
230 $self->{ACTIVE_WORKSHEET};
238 Excel::Template::Context
258 Rob Kinyon (rob.kinyon@gmail.com)