Implement a relative reference robust to source and reference moving
The new function is X(SRC,REF), which briefly for a cell in the neighborhood of REF returns the corresponding cell in the neighborhood in SRC. For further details, see the updated documention. In developing and documenting this function, I refined some of the existing error messages (e.g. showing the coordinates when there is an attempt to obtain a cell with a negative coordinate) and improved the error propagation to increase the chance that the innermost error will percolate to the top level.
This commit is contained in:
parent
ab1a2fbb5a
commit
341b12ba04
12 changed files with 650 additions and 238 deletions
421
doc/teapot.lyx
421
doc/teapot.lyx
|
@ -4625,7 +4625,7 @@ save-tbl
|
|||
file
|
||||
\series default
|
||||
\emph default
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Description
|
||||
|
@ -4642,7 +4642,7 @@ save-csv
|
|||
file
|
||||
\series default
|
||||
\emph default
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Description
|
||||
|
@ -4659,7 +4659,7 @@ save-latex
|
|||
file
|
||||
\series default
|
||||
\emph default
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Description
|
||||
|
@ -4676,7 +4676,7 @@ save-context
|
|||
file
|
||||
\series default
|
||||
\emph default
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Description
|
||||
|
@ -4855,6 +4855,11 @@ Location Cell labels and the
|
|||
&()
|
||||
\family default
|
||||
function have this type, but there are no location constant literals.
|
||||
However,
|
||||
\family typewriter
|
||||
&(3,2,1),
|
||||
\family default
|
||||
for example, acts very much like a location constant literal.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Description
|
||||
|
@ -5041,7 +5046,7 @@ y
|
|||
x
|
||||
\family typewriter
|
||||
\emph default
|
||||
=
|
||||
~=
|
||||
\family default
|
||||
\emph on
|
||||
y
|
||||
|
@ -5489,7 +5494,8 @@ y
|
|||
z
|
||||
\emph default
|
||||
is omitted, the coordinate of the cell is used.
|
||||
The second form is in fact a no-op, but it is allowed for convenience
|
||||
The second form is in fact a no-op, but it is allowed for convenience and
|
||||
consistency of expressions.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Description
|
||||
|
@ -5515,8 +5521,21 @@ relative.
|
|||
\begin_inset Quotes erd
|
||||
\end_inset
|
||||
|
||||
Thus R(-1) returns the value of the cell immediately to the left of this
|
||||
one.
|
||||
Thus
|
||||
\family sans
|
||||
\series bold
|
||||
R
|
||||
\series default
|
||||
(-1)
|
||||
\family default
|
||||
returns the value of the cell immediately to the left of this one, and
|
||||
\family sans
|
||||
\series bold
|
||||
R
|
||||
\series default
|
||||
(,,1)
|
||||
\family default
|
||||
returns the same cell as this one but on the following layer.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Description
|
||||
|
@ -5541,8 +5560,181 @@ displaced (by).
|
|||
\begin_inset Quotes erd
|
||||
\end_inset
|
||||
|
||||
Thus, D(-1) returns the location of the cell immediately to the left of
|
||||
this one.
|
||||
Thus,
|
||||
\family sans
|
||||
\series bold
|
||||
D
|
||||
\series default
|
||||
(-1)
|
||||
\family default
|
||||
returns the location of the cell immediately to the left of this one, and
|
||||
\family sans
|
||||
\series bold
|
||||
D
|
||||
\series default
|
||||
(,2,1)
|
||||
\family default
|
||||
returns the location of the cell two below this one on the following layer.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Description
|
||||
X(
|
||||
\series medium
|
||||
label
|
||||
\emph on
|
||||
|
||||
\begin_inset space ~
|
||||
\end_inset
|
||||
|
||||
to,
|
||||
\begin_inset space ~
|
||||
\end_inset
|
||||
|
||||
|
||||
\emph default
|
||||
label
|
||||
\emph on
|
||||
|
||||
\begin_inset space ~
|
||||
\end_inset
|
||||
|
||||
from,
|
||||
\begin_inset space ~
|
||||
\end_inset
|
||||
|
||||
|
||||
\emph default
|
||||
[bool
|
||||
\emph on
|
||||
|
||||
\begin_inset space ~
|
||||
\end_inset
|
||||
|
||||
fix_x
|
||||
\emph default
|
||||
]
|
||||
\emph on
|
||||
,
|
||||
\begin_inset space ~
|
||||
\end_inset
|
||||
|
||||
|
||||
\emph default
|
||||
[bool
|
||||
\emph on
|
||||
|
||||
\begin_inset space ~
|
||||
\end_inset
|
||||
|
||||
fix_y
|
||||
\emph default
|
||||
]
|
||||
\emph on
|
||||
,
|
||||
\begin_inset space ~
|
||||
\end_inset
|
||||
|
||||
|
||||
\emph default
|
||||
[bool
|
||||
\emph on
|
||||
|
||||
\begin_inset space ~
|
||||
\end_inset
|
||||
|
||||
fix_z
|
||||
\emph default
|
||||
]
|
||||
\series default
|
||||
)
|
||||
\begin_inset Quotes eld
|
||||
\end_inset
|
||||
|
||||
Excel reference
|
||||
\begin_inset Quotes erd
|
||||
\end_inset
|
||||
|
||||
: returns the value of the cell at a computed target location.
|
||||
This target location is the one reached from the current cell via the same
|
||||
offset as the cell with label
|
||||
\emph on
|
||||
to
|
||||
\emph default
|
||||
has from label
|
||||
\emph on
|
||||
from.
|
||||
|
||||
\emph default
|
||||
The idea is that if you label the source of data you want to reference,
|
||||
say with
|
||||
\family sans
|
||||
SRC
|
||||
\family default
|
||||
, and the location of some place you want to start referring to it with
|
||||
|
||||
\family sans
|
||||
REF
|
||||
\family default
|
||||
, then you can use
|
||||
\family sans
|
||||
\series bold
|
||||
X
|
||||
\series default
|
||||
(SRC,REF)
|
||||
\family default
|
||||
to refer to the source data, and fill this formula to neighboring cells
|
||||
to refer to the neighbors of the source, and it will all continue to work
|
||||
if either the source or the reference is moved around in the sheet.
|
||||
|
||||
\begin_inset Newline newline
|
||||
\end_inset
|
||||
|
||||
If the
|
||||
\emph on
|
||||
fix_DIM
|
||||
\emph default
|
||||
argument is present and positive, then the corresponding coordinate of
|
||||
the target cell is set to match that of
|
||||
\emph on
|
||||
to
|
||||
\emph default
|
||||
.
|
||||
This corresponds to fixing the row or column (or layer) of the reference,
|
||||
as with a
|
||||
\begin_inset Quotes eld
|
||||
\end_inset
|
||||
|
||||
$
|
||||
\begin_inset Quotes erd
|
||||
\end_inset
|
||||
|
||||
character in Excel.
|
||||
Thus
|
||||
\family sans
|
||||
\series bold
|
||||
X
|
||||
\series default
|
||||
(SRC,REF,1,1,1)
|
||||
\family default
|
||||
is identical to
|
||||
\family sans
|
||||
@(SRC)
|
||||
\family default
|
||||
, but you should certainly prefer the latter for clarity of expression.
|
||||
\begin_inset Newline newline
|
||||
\end_inset
|
||||
|
||||
There is a corresponding location function
|
||||
\family sans
|
||||
X&()
|
||||
\family default
|
||||
as well, which takes exactly the same arguments with the same meanings,
|
||||
but it is rarely needed.
|
||||
It is provided for completeness.
|
||||
\begin_inset Newline newline
|
||||
\end_inset
|
||||
|
||||
See the FAQ below for further discussion of cell references.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Description
|
||||
|
@ -5904,7 +6096,7 @@ clock
|
|||
|
||||
condition
|
||||
\emph default
|
||||
,[location[,location])
|
||||
,[location[,location])
|
||||
\series default
|
||||
conditionally clocks the specified cell if the condition is not 0.
|
||||
If two locations are given, all cells in that range will be clocked.
|
||||
|
@ -7264,8 +7456,22 @@ z
|
|||
position of the given location, of the currently updated cell if none is
|
||||
given.
|
||||
These functions are usually used in combination with the @ function for
|
||||
relative relations to other cells.
|
||||
relative relations to other cell, but see also the convenience functions
|
||||
|
||||
\family sans
|
||||
\series bold
|
||||
R
|
||||
\series default
|
||||
()
|
||||
\family default
|
||||
and
|
||||
\family sans
|
||||
\series bold
|
||||
D
|
||||
\series default
|
||||
()
|
||||
\family default
|
||||
for relative references.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsection
|
||||
|
@ -7763,11 +7969,13 @@ X
|
|||
\end_layout
|
||||
|
||||
\begin_layout Quote
|
||||
eval(&((@(X)>=0)+x(BAD),y(BAD),z(BAD)))
|
||||
eval(BAD + &((@(X)>=0),0,0))
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
The cell labelled
|
||||
Note this is making use of the fact that you can add locations in the natural
|
||||
way.
|
||||
The cell labelled
|
||||
\family typewriter
|
||||
BAD
|
||||
\family default
|
||||
|
@ -7786,5 +7994,190 @@ BAD
|
|||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsection
|
||||
But my references don't do the right thing when I move or copy them!
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
If you are used to other spreadsheets, you have probably noticed that references
|
||||
like
|
||||
\family sans
|
||||
@(0,1,0)
|
||||
\family default
|
||||
(for the start of the second row) or
|
||||
\family sans
|
||||
@(MYDATA)
|
||||
\family default
|
||||
(for a location) are
|
||||
\begin_inset Quotes eld
|
||||
\end_inset
|
||||
|
||||
absolute
|
||||
\begin_inset Quotes erd
|
||||
\end_inset
|
||||
|
||||
– they always refer to the same location no matter where in the spreadsheet
|
||||
they occur.
|
||||
And of course sometimes it is convenient, for example when making a column
|
||||
of consecutive numbers, to refer to nearby cells in a relative manner,
|
||||
either with say
|
||||
\family sans
|
||||
@(x(),y()-1,z())+1
|
||||
\family default
|
||||
or
|
||||
\family sans
|
||||
@(&()+&(0,-1,0))+1
|
||||
\family default
|
||||
or just
|
||||
\family sans
|
||||
R(,-1)+1
|
||||
\family default
|
||||
to add one to the value of the cell just above.
|
||||
Then you can fill that expression down and get your column of consecutive
|
||||
numbers.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
But these sorts of relative expressions only keep working if the cells move
|
||||
together with the cells they refer to.
|
||||
If for example you have a row of cells that are all referring to the row
|
||||
above with a relative reference (like
|
||||
\family sans
|
||||
R(,-1)
|
||||
\family default
|
||||
) and you insert another row in between them, your references will be all
|
||||
messed up.
|
||||
There is value to
|
||||
\begin_inset Quotes eld
|
||||
\end_inset
|
||||
|
||||
Excel-style
|
||||
\begin_inset Quotes erd
|
||||
\end_inset
|
||||
|
||||
references that can be used to fill and which also can move around while
|
||||
still just
|
||||
\begin_inset Quotes eld
|
||||
\end_inset
|
||||
|
||||
referring to what you want.
|
||||
\begin_inset Quotes erd
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
To provide for this need, teapot has a function
|
||||
\family sans
|
||||
X(SRC, REF)
|
||||
\family default
|
||||
to retrieve the value of the cell labeled
|
||||
\family sans
|
||||
SRC
|
||||
\family default
|
||||
|
||||
\bar under
|
||||
from
|
||||
\bar default
|
||||
the cell labeled
|
||||
\family sans
|
||||
REF
|
||||
\family default
|
||||
.
|
||||
If the so-labeled cells move around (either the source or the reference)
|
||||
it will still work.
|
||||
This is not particularly useful in and of itself; what makes it useful
|
||||
is that from a cell other than
|
||||
\family sans
|
||||
REF
|
||||
\family default
|
||||
, it gives you the value of the cell that stands in the same relation to
|
||||
|
||||
\family sans
|
||||
SRC
|
||||
\family default
|
||||
as that cell stands to
|
||||
\family sans
|
||||
REF
|
||||
\family default
|
||||
.
|
||||
So in the cell to the right of
|
||||
\family sans
|
||||
REF
|
||||
\family default
|
||||
, it will give you the value of the cell to the right of
|
||||
\family sans
|
||||
SRC
|
||||
\family default
|
||||
; in the cell below, it gives you the cell below
|
||||
\family sans
|
||||
SRC
|
||||
\family default
|
||||
, etc.
|
||||
Now you can fill a block of cells around
|
||||
\family sans
|
||||
REF
|
||||
\family default
|
||||
with formulas contaning
|
||||
\family sans
|
||||
X(SRC,REF)
|
||||
\family default
|
||||
and they will refer to the analogous block of cells around
|
||||
\family sans
|
||||
SRC
|
||||
\family default
|
||||
.
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Sometimes you want to make this kind of reference but fix one of the coordinates
|
||||
but not the others;
|
||||
\family sans
|
||||
X()
|
||||
\family default
|
||||
has optional flags for this, as well, so that
|
||||
\family sans
|
||||
X(SRC,REF,,,1)
|
||||
\family default
|
||||
will always be on the same layer as
|
||||
\family sans
|
||||
SRC
|
||||
\family default
|
||||
regardless of what layer it is called from or what layer
|
||||
\family sans
|
||||
REF
|
||||
\family default
|
||||
is on.
|
||||
Thus
|
||||
\family sans
|
||||
X(SRC,REF,1,1,1)
|
||||
\family default
|
||||
is just
|
||||
\family sans
|
||||
@(SRC)
|
||||
\family default
|
||||
, but the intent of the latter is much clearer.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
You might ask as a follow-up question: Isnt
|
||||
\family sans
|
||||
X(SRC, REF)
|
||||
\family default
|
||||
much more cumbersome than just referring to cells by coordinate and then
|
||||
letting Excel just do the right thing as you copy and move either that
|
||||
formula or the referred-to data? The response to this is that in a typical
|
||||
spreadsheet, there are only a small number of fundamental references, and
|
||||
all other references derive from them in this way.
|
||||
So you generally only need a few labels, and by taking just a little extra
|
||||
time to apply those labels and refer to them in initial formulas, you are
|
||||
making the semantics of your references much clearer and in essence documenting
|
||||
them within your spreadsheet.
|
||||
This extra effort will therefore be repaid in an easier-to-use, easier-to-under
|
||||
stand, and easier-to-maintain and update spreadsheet.
|
||||
\end_layout
|
||||
|
||||
\end_body
|
||||
\end_document
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue