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 $self->{__MARKS} = {};
34 # Removed NAME_MAP until I figure out what the heck it's for
35 for (qw( STACK PARAM_MAP ))
37 next if defined $self->{$_} && ref $self->{$_} eq 'ARRAY';
41 $self->{$_} = 0 for keys %isAbsolute;
46 sub use_unicode { $_[0]->{UNICODE} && 1 }
48 sub _find_param_in_map
51 my ($map, $param, $depth) = @_;
56 for my $map (reverse @{$self->{$map}})
58 next unless exists $map->{$param};
59 $depth--, next if $depth;
62 $val = $map->{$param};
66 die "Parameter '$param' not found\n"
67 if !$found && $self->{DIE_ON_NO_PARAM};
75 $self->_find_param_in_map(
84 # $self->_find_param_in_map(
93 my ($obj, $key, $depth) = @_;
97 my $obj_val = $obj->{$key};
99 $obj_val = $self->param($1)
100 if $obj_val =~ /^\$(\S+)$/o;
102 #GGG Remove this once NAME_MAP is working
103 # $obj_val = $self->named_param($1)
104 # if $obj_val =~ /^\\(\S+)$/o;
106 #GGG Does this adequately test values to make sure they're legal??
107 # A value is defined as:
108 # 1) An optional operator (+, -, *, or /)
109 # 2) A decimal number
111 #GGG Convert this to use //x
112 my ($op, $val) = $obj_val =~ m/^\s*([\+\*\/\-])?\s*([\d.]*\d)\s*$/oi;
114 # Unless it's a relative value, we have what we came for.
115 return $obj_val unless $op;
117 my $prev_val = $isAbsolute{$key}
119 : $self->get($obj, $key, $depth + 1);
121 return $obj_val unless defined $prev_val;
122 return $prev_val unless defined $obj_val;
124 # Prevent divide-by-zero issues.
125 return $val if $op eq '/' and $val == 0;
130 /^\+$/ && do { $new_val = ($prev_val + $val); last; };
131 /^\-$/ && do { $new_val = ($prev_val - $val); last; };
132 /^\*$/ && do { $new_val = ($prev_val * $val); last; };
133 /^\/$/ && do { $new_val = ($prev_val / $val); last; };
135 die "Unknown operator '$op' in arithmetic resolve\n";
138 return $new_val if defined $new_val;
147 push @{$self->{STACK}}, $obj;
149 for my $key (keys %isAbsolute)
151 next unless exists $obj->{$key};
152 $self->{$key} = $self->resolve($obj, $key);
161 my ($obj, $no_delta) = @_;
165 my $deltas = $obj->deltas($self);
166 $self->{$_} += $deltas->{$_} for keys %$deltas;
169 pop @{$self->{STACK}};
177 my ($dummy, $key, $depth) = @_;
181 return unless @{$self->{STACK}};
183 my $obj = $self->{STACK}[-1];
185 return $self->{$key} if $isAbsolute{$key};
188 my $this_depth = $depth;
189 foreach my $e (reverse @{$self->{STACK}})
191 next unless exists $e->{$key};
192 next if $this_depth-- > 0;
194 $val = $self->resolve($e, $key, $depth);
198 $val = $self->{$key} unless defined $val;
199 return $val unless defined $val;
201 return $self->param($1, $depth) if $val =~ /^\$(\S+)$/o;
210 $self->{ACTIVE_FORMAT} = $_[0]
213 $self->{ACTIVE_FORMAT};
219 my ($worksheet) = @_;
221 $self->{ROW} = $self->{COL} = 0;
222 $self->{REFERENCES} = {};
224 my $name = $self->get( $worksheet, 'NAME' );
226 if ( defined $name && length $name )
228 if ( exists $self->{WORKSHEET_NAMES}{$name} )
234 $self->{WORKSHEET_NAMES}{$name} = undef;
242 return $self->active_worksheet(
243 $self->{XLS}->add_worksheet( $name ),
255 @{$self->{__MARKS}}{keys %args} = values %args;
258 return $self->{__MARKS}{$_[0]}
265 $self->{ACTIVE_WORKSHEET} = $_[0]
268 $self->{ACTIVE_WORKSHEET};
274 my ($ref, $row, $col) = @_;
276 $self->{REFERENCES}{$ref} ||= [];
278 push @{$self->{REFERENCES}{$ref}}, [ $row, $col ];
283 sub get_all_references
288 $self->{REFERENCES}{$ref} ||= [];
290 return @{ $self->{REFERENCES}{$ref} };
293 sub get_last_reference
298 $self->{REFERENCES}{$ref} ||= [];
300 return @{ $self->{REFERENCES}{$ref}[-1] };
308 Excel::Template::Context
312 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.
314 Documentation is provided for if you wish to subclass another node.
344 =head2 active_worksheet
350 =head2 get_all_references
352 =head2 get_last_reference
364 Rob Kinyon (rob.kinyon@gmail.com)