summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2015-06-17 17:12:49 +0200
committerCaolán McNamara <caolanm@redhat.com>2015-06-30 11:31:34 +0000
commit2d4f172c963e5503c74ae79318d09392454ae144 (patch)
treedbc33f660f10bab313ce01608c411b446b1a5708
parent326ca9e0710d17274eb0a6cdc0d95d4f933784f0 (diff)
Resolves: tdf#83365 push proper references in INDIRECT
... that take relative/absolute addressing and sheet 3D flag into account to be fed to reference extension via range operator. (cherry picked from commit fb6dd2a73074b9695bd8ddf7ba40f1819b03024e) properly inherit relative and 3D flags when extending, tdf#83365 related Commit 194e9f9bae28bdf22a9ed4779c1656ee693f3302 oversimplified things. (cherry picked from commit e503addfbbe45efe1a3c06392c66fb79c3c72d07) Change-Id: Iabe13ae384577e2d71ca87af6482ddccbf7ad0ac ea6a84c4a7be49af036690afbb1512ae2c1045a2 Reviewed-on: https://gerrit.libreoffice.org/16352 Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r--sc/inc/refdata.hxx5
-rw-r--r--sc/source/core/inc/interpre.hxx2
-rw-r--r--sc/source/core/tool/interpr1.cxx5
-rw-r--r--sc/source/core/tool/interpr4.cxx20
-rw-r--r--sc/source/core/tool/refdata.cxx73
5 files changed, 101 insertions, 4 deletions
diff --git a/sc/inc/refdata.hxx b/sc/inc/refdata.hxx
index ac27db8a3d9a..e0d9b807a78b 100644
--- a/sc/inc/refdata.hxx
+++ b/sc/inc/refdata.hxx
@@ -57,6 +57,8 @@ public:
void InitAddress( SCCOL nCol, SCROW nRow, SCTAB nTab );
/// InitAddressRel: InitFlags and set address, everything relative to rPos
void InitAddressRel( const ScAddress& rAdr, const ScAddress& rPos );
+ /// InitFlags and set address, relative to rPos if rRef says so.
+ void InitFromRefAddress( const ScRefAddress& rRef, const ScAddress& rPos );
sal_uInt8 FlagValue() const { return mnFlagValue;}
void SetColRel( bool bVal ) { Flags.bColRel = bVal; }
@@ -135,6 +137,9 @@ struct ScComplexRefData
Ref2.InitAddress( nCol2, nRow2, nTab2 );
}
+ /// InitFlags and set range, relative to rPos if rRef1 and rRef2 say so.
+ void InitFromRefAddresses( const ScRefAddress& rRef1, const ScRefAddress& rRef2, const ScAddress& rPos );
+
bool Valid() const;
/** In external references nTab is -1 for the start tab and -1 for the end
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index ed6c171e3362..7ca010a2deb4 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -331,6 +331,8 @@ void PushExternalSingleRef(sal_uInt16 nFileId, const OUString& rTabName,
void PushExternalDoubleRef(sal_uInt16 nFileId, const OUString& rTabName,
SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
SCCOL nCol2, SCROW nRow2, SCTAB nTab2);
+void PushSingleRef( const ScRefAddress& rRef );
+void PushDoubleRef( const ScRefAddress& rRef1, const ScRefAddress& rRef2 );
void PushMatrix( const sc::RangeMatrix& rMat );
void PushMatrix(const ScMatrixRef& pMat);
void PushError( sal_uInt16 nError );
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index f2f1d43f9c50..fe314bfef995 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -7064,8 +7064,7 @@ void ScInterpreter::ScIndirect()
aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab());
}
else
- PushDoubleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(),
- aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab() );
+ PushDoubleRef( aRefAd, aRefAd2);
}
else if (ConvertSingleRef(pDok, sRefStr, nTab, aRefAd, aDetails, &aExtInfo))
{
@@ -7075,7 +7074,7 @@ void ScInterpreter::ScIndirect()
aExtInfo.mnFileId, aExtInfo.maTabName, aRefAd.Col(), aRefAd.Row(), aRefAd.Tab());
}
else
- PushSingleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab() );
+ PushSingleRef( aRefAd);
}
else
{
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 8b5fb734e390..504e87873fcf 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -1965,6 +1965,26 @@ void ScInterpreter::PushExternalDoubleRef(
}
}
+void ScInterpreter::PushSingleRef( const ScRefAddress& rRef )
+{
+ if (!IfErrorPushError())
+ {
+ ScSingleRefData aRef;
+ aRef.InitFromRefAddress( rRef, aPos);
+ PushTempTokenWithoutError( new ScSingleRefToken( aRef ) );
+ }
+}
+
+void ScInterpreter::PushDoubleRef( const ScRefAddress& rRef1, const ScRefAddress& rRef2 )
+{
+ if (!IfErrorPushError())
+ {
+ ScComplexRefData aRef;
+ aRef.InitFromRefAddresses( rRef1, rRef2, aPos);
+ PushTempTokenWithoutError( new ScDoubleRefToken( aRef ) );
+ }
+}
+
void ScInterpreter::PushMatrix( const sc::RangeMatrix& rMat )
{
if (!rMat.isRangeValid())
diff --git a/sc/source/core/tool/refdata.cxx b/sc/source/core/tool/refdata.cxx
index d508247ad641..97d419c03105 100644
--- a/sc/source/core/tool/refdata.cxx
+++ b/sc/source/core/tool/refdata.cxx
@@ -41,6 +41,16 @@ void ScSingleRefData::InitAddressRel( const ScAddress& rAdr, const ScAddress& rP
SetAddress(rAdr, rPos);
}
+void ScSingleRefData::InitFromRefAddress( const ScRefAddress& rRef, const ScAddress& rPos )
+{
+ InitFlags();
+ SetColRel( rRef.IsRelCol());
+ SetRowRel( rRef.IsRelRow());
+ SetTabRel( rRef.IsRelTab());
+ SetFlag3D( rRef.Tab() != rPos.Tab());
+ SetAddress( rRef.GetAddress(), rPos);
+}
+
void ScSingleRefData::SetAbsCol( SCCOL nVal )
{
Flags.bColRel = false;
@@ -257,10 +267,38 @@ void ScSingleRefData::Dump( int nIndent ) const
}
#endif
+void ScComplexRefData::InitFromRefAddresses( const ScRefAddress& rRef1, const ScRefAddress& rRef2, const ScAddress& rPos )
+{
+ InitFlags();
+ Ref1.SetColRel( rRef1.IsRelCol());
+ Ref1.SetRowRel( rRef1.IsRelRow());
+ Ref1.SetTabRel( rRef1.IsRelTab());
+ Ref1.SetFlag3D( rRef1.Tab() != rPos.Tab() || rRef1.Tab() != rRef2.Tab());
+ Ref2.SetColRel( rRef2.IsRelCol());
+ Ref2.SetRowRel( rRef2.IsRelRow());
+ Ref2.SetTabRel( rRef2.IsRelTab());
+ Ref2.SetFlag3D( rRef1.Tab() != rRef2.Tab());
+ SetRange( ScRange( rRef1.GetAddress(), rRef2.GetAddress()), rPos);
+}
+
ScComplexRefData& ScComplexRefData::Extend( const ScSingleRefData & rRef, const ScAddress & rPos )
{
+ bool bInherit3D = (Ref1.IsFlag3D() && !Ref2.IsFlag3D() && !rRef.IsFlag3D());
ScRange aAbsRange = toAbs(rPos);
- ScAddress aAbs = rRef.toAbs(rPos);
+
+ ScSingleRefData aRef = rRef;
+ // If no sheet was given in the extending part, let it point to the same
+ // sheet as this reference's end point, inheriting the absolute/relative
+ // mode.
+ // [$]Sheet1.A5:A6:A7 on Sheet2 do still reference only Sheet1.
+ if (!rRef.IsFlag3D())
+ {
+ if (Ref2.IsTabRel())
+ aRef.SetRelTab( Ref2.Tab());
+ else
+ aRef.SetAbsTab( Ref2.Tab());
+ }
+ ScAddress aAbs = aRef.toAbs(rPos);
if (aAbs.Col() < aAbsRange.aStart.Col())
aAbsRange.aStart.SetCol(aAbs.Col());
@@ -280,6 +318,39 @@ ScComplexRefData& ScComplexRefData::Extend( const ScSingleRefData & rRef, const
if (aAbsRange.aEnd.Tab() < aAbs.Tab())
aAbsRange.aEnd.SetTab(aAbs.Tab());
+ // In Ref2 inherit absolute/relative addressing from the extending part.
+ // A$5:A5 => A$5:A$5:A5 => A$5:A5, and not A$5:A$5
+ // A$6:$A5 => A$6:A$6:$A5 => A5:$A$6
+ if (aAbsRange.aEnd.Col() == aAbs.Col())
+ Ref2.SetColRel( rRef.IsColRel());
+ if (aAbsRange.aEnd.Row() == aAbs.Row())
+ Ref2.SetRowRel( rRef.IsRowRel());
+
+ // In Ref1 inherit relative sheet from extending part if given.
+ if (aAbsRange.aStart.Tab() == aAbs.Tab() && rRef.IsFlag3D())
+ Ref1.SetTabRel( rRef.IsTabRel());
+
+ // In Ref2 inherit relative sheet from either Ref1 or extending part.
+ // Use the original 3D flags to determine which.
+ // $Sheet1.$A$5:$A$6 => $Sheet1.$A$5:$A$5:$A$6 => $Sheet1.$A$5:$A$6, and
+ // not $Sheet1.$A$5:Sheet1.$A$6 (with invisible second 3D, but relative).
+ if (aAbsRange.aEnd.Tab() == aAbs.Tab())
+ Ref2.SetTabRel( bInherit3D ? Ref1.IsTabRel() : rRef.IsTabRel());
+
+ // Force 3D flag in Ref1 if different sheet or more than one sheet
+ // referenced.
+ if (aAbsRange.aStart.Tab() != rPos.Tab() || aAbsRange.aStart.Tab() != aAbsRange.aEnd.Tab())
+ Ref1.SetFlag3D(true);
+
+ // Force 3D flag in Ref2 if more than one sheet referenced.
+ if (aAbsRange.aStart.Tab() != aAbsRange.aEnd.Tab())
+ Ref2.SetFlag3D(true);
+
+ // Inherit 3D flag in Ref1 from extending part in case range wasn't
+ // extended as in A5:A5:Sheet1.A5 if on Sheet1.
+ if (rRef.IsFlag3D())
+ Ref1.SetFlag3D( true);
+
SetRange(aAbsRange, rPos);
return *this;