Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
core
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
LibreOffice
core
Commits
8a5b9413
Kaydet (Commit)
8a5b9413
authored
Ock 29, 2013
tarafından
Kohei Yoshida
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
bnc#484599: Prevent pivot table from getting sheared when cells are shifted.
Change-Id: Ic6766105bb221aa4ebc700cbf99b4f6f5b3abf8b
üst
0941a1b0
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
313 additions
and
2 deletions
+313
-2
document.hxx
sc/inc/document.hxx
+2
-0
dpobject.hxx
sc/inc/dpobject.hxx
+4
-0
globstr.hrc
sc/inc/globstr.hrc
+3
-1
documen3.cxx
sc/source/core/data/documen3.cxx
+10
-0
dpobject.cxx
sc/source/core/data/dpobject.cxx
+98
-0
docfunc.cxx
sc/source/ui/docshell/docfunc.cxx
+191
-1
globstr.src
sc/source/ui/src/globstr.src
+5
-0
No files found.
sc/inc/document.hxx
Dosyayı görüntüle @
8a5b9413
...
...
@@ -483,7 +483,9 @@ public:
SC_DLLPUBLIC
const
ScRangeData
*
GetRangeAtBlock
(
const
ScRange
&
rBlock
,
rtl
::
OUString
*
pName
=
NULL
)
const
;
bool
HasPivotTable
()
const
;
SC_DLLPUBLIC
ScDPCollection
*
GetDPCollection
();
SC_DLLPUBLIC
const
ScDPCollection
*
GetDPCollection
()
const
;
ScDPObject
*
GetDPAtCursor
(
SCCOL
nCol
,
SCROW
nRow
,
SCTAB
nTab
)
const
;
ScDPObject
*
GetDPAtBlock
(
const
ScRange
&
rBlock
)
const
;
...
...
sc/inc/dpobject.hxx
Dosyayı görüntüle @
8a5b9413
...
...
@@ -395,6 +395,10 @@ public:
NameCaches
&
GetNameCaches
();
DBCaches
&
GetDBCaches
();
bool
IntersectsTableByColumns
(
SCCOL
nCol1
,
SCCOL
nCol2
,
SCROW
nRow
,
SCTAB
nTab
)
const
;
bool
IntersectsTableByRows
(
SCCOL
nCol
,
SCROW
nRow1
,
SCROW
nRow2
,
SCTAB
nTab
)
const
;
bool
HasTable
(
const
ScRange
&
rRange
)
const
;
private
:
/** Only to be called from ScDPCache::RemoveReference(). */
void
RemoveCache
(
const
ScDPCache
*
pCache
);
...
...
sc/inc/globstr.hrc
Dosyayı görüntüle @
8a5b9413
...
...
@@ -634,6 +634,8 @@
#define STR_QUERY_FORMULA_RECALC_ONLOAD_XLS 507
#define STR_ALWAYS_PERFORM_SELECTED 508
#define STR_COUNT 509
#define STR_NO_INSERT_DELETE_OVER_PIVOT_TABLE 509
#define STR_COUNT 510
#endif
sc/source/core/data/documen3.cxx
Dosyayı görüntüle @
8a5b9413
...
...
@@ -302,6 +302,11 @@ ScDBData* ScDocument::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nC
return
NULL
;
}
bool
ScDocument
::
HasPivotTable
()
const
{
return
pDPCollection
&&
pDPCollection
->
GetCount
();
}
ScDPCollection
*
ScDocument
::
GetDPCollection
()
{
if
(
!
pDPCollection
)
...
...
@@ -309,6 +314,11 @@ ScDPCollection* ScDocument::GetDPCollection()
return
pDPCollection
;
}
const
ScDPCollection
*
ScDocument
::
GetDPCollection
()
const
{
return
pDPCollection
;
}
ScDPObject
*
ScDocument
::
GetDPAtCursor
(
SCCOL
nCol
,
SCROW
nRow
,
SCTAB
nTab
)
const
{
if
(
!
pDPCollection
)
...
...
sc/source/core/data/dpobject.cxx
Dosyayı görüntüle @
8a5b9413
...
...
@@ -561,6 +561,86 @@ public:
}
};
class
FindIntersectingTable
:
std
::
unary_function
<
ScDPObject
,
bool
>
{
ScRange
maRange
;
public
:
FindIntersectingTable
(
const
ScRange
&
rRange
)
:
maRange
(
rRange
)
{}
bool
operator
()
(
const
ScDPObject
&
rObj
)
const
{
return
maRange
.
Intersects
(
rObj
.
GetOutRange
());
}
};
class
FindIntersetingTableByColumns
:
std
::
unary_function
<
ScDPObject
,
bool
>
{
SCCOL
mnCol1
;
SCCOL
mnCol2
;
SCROW
mnRow
;
SCTAB
mnTab
;
public
:
FindIntersetingTableByColumns
(
SCCOL
nCol1
,
SCCOL
nCol2
,
SCROW
nRow
,
SCTAB
nTab
)
:
mnCol1
(
nCol1
),
mnCol2
(
nCol2
),
mnRow
(
nRow
),
mnTab
(
nTab
)
{}
bool
operator
()
(
const
ScDPObject
&
rObj
)
const
{
const
ScRange
&
rRange
=
rObj
.
GetOutRange
();
if
(
mnTab
!=
rRange
.
aStart
.
Tab
())
// Not on this sheet.
return
false
;
if
(
rRange
.
aEnd
.
Row
()
<
mnRow
)
// This table is above the row. It's safe.
return
false
;
if
(
mnCol1
<=
rRange
.
aStart
.
Col
()
&&
rRange
.
aEnd
.
Col
()
<=
mnCol2
)
// This table is fully enclosed in this column range.
return
false
;
if
(
rRange
.
aEnd
.
Col
()
<
mnCol1
||
mnCol2
<
rRange
.
aStart
.
Col
())
// This table is entirely outside this column range.
return
false
;
// This table must be intersected by this column range.
return
true
;
}
};
class
FindIntersectingTableByRows
:
std
::
unary_function
<
ScDPObject
,
bool
>
{
SCCOL
mnCol
;
SCROW
mnRow1
;
SCROW
mnRow2
;
SCTAB
mnTab
;
public
:
FindIntersectingTableByRows
(
SCCOL
nCol
,
SCROW
nRow1
,
SCROW
nRow2
,
SCTAB
nTab
)
:
mnCol
(
nCol
),
mnRow1
(
nRow1
),
mnRow2
(
nRow2
),
mnTab
(
nTab
)
{}
bool
operator
()
(
const
ScDPObject
&
rObj
)
const
{
const
ScRange
&
rRange
=
rObj
.
GetOutRange
();
if
(
mnTab
!=
rRange
.
aStart
.
Tab
())
// Not on this sheet.
return
false
;
if
(
rRange
.
aEnd
.
Col
()
<
mnCol
)
// This table is to the left of the column. It's safe.
return
false
;
if
(
mnRow1
<=
rRange
.
aStart
.
Row
()
&&
rRange
.
aEnd
.
Row
()
<=
mnRow2
)
// This table is fully enclosed in this row range.
return
false
;
if
(
rRange
.
aEnd
.
Row
()
<
mnRow1
||
mnRow2
<
rRange
.
aStart
.
Row
())
// This table is entirely outside this row range.
return
false
;
// This table must be intersected by this row range.
return
true
;
}
};
}
ScDPTableData
*
ScDPObject
::
GetTableData
()
...
...
@@ -3398,6 +3478,24 @@ ScDPCollection::DBCaches& ScDPCollection::GetDBCaches()
return
maDBCaches
;
}
bool
ScDPCollection
::
IntersectsTableByColumns
(
SCCOL
nCol1
,
SCCOL
nCol2
,
SCROW
nRow
,
SCTAB
nTab
)
const
{
return
std
::
find_if
(
maTables
.
begin
(),
maTables
.
end
(),
FindIntersetingTableByColumns
(
nCol1
,
nCol2
,
nRow
,
nTab
))
!=
maTables
.
end
();
}
bool
ScDPCollection
::
IntersectsTableByRows
(
SCCOL
nCol
,
SCROW
nRow1
,
SCROW
nRow2
,
SCTAB
nTab
)
const
{
return
std
::
find_if
(
maTables
.
begin
(),
maTables
.
end
(),
FindIntersectingTableByRows
(
nCol
,
nRow1
,
nRow2
,
nTab
))
!=
maTables
.
end
();
}
bool
ScDPCollection
::
HasTable
(
const
ScRange
&
rRange
)
const
{
return
std
::
find_if
(
maTables
.
begin
(),
maTables
.
end
(),
FindIntersectingTable
(
rRange
))
!=
maTables
.
end
();
}
void
ScDPCollection
::
RemoveCache
(
const
ScDPCache
*
pCache
)
{
if
(
maSheetCaches
.
remove
(
pCache
))
...
...
sc/source/ui/docshell/docfunc.cxx
Dosyayı görüntüle @
8a5b9413
...
...
@@ -79,6 +79,7 @@
#include "externalrefmgr.hxx"
#include "undorangename.hxx"
#include "progress.hxx"
#include "dpobject.hxx"
#include <memory>
#include <basic/basmgr.hxx>
...
...
@@ -1346,7 +1347,182 @@ sal_Bool ScDocFunc::ApplyStyle( const ScMarkData& rMark, const String& rStyleNam
return
sal_True
;
}
//------------------------------------------------------------------------
namespace
{
/**
* Check if this insertion attempt would end up cutting one or more pivot
* tables in half, which is not desirable.
*
* @return true if this insertion can be done safely without shearing any
* existing pivot tables, false otherwise.
*/
bool
canInsertCellsByPivot
(
const
ScRange
&
rRange
,
const
ScMarkData
&
rMarkData
,
InsCellCmd
eCmd
,
const
ScDocument
*
pDoc
)
{
if
(
!
pDoc
->
HasPivotTable
())
// This document has no pivot tables.
return
true
;
const
ScDPCollection
*
pDPs
=
pDoc
->
GetDPCollection
();
ScMarkData
::
const_iterator
itBeg
=
rMarkData
.
begin
(),
itEnd
=
rMarkData
.
end
();
ScRange
aRange
(
rRange
);
// local copy
switch
(
eCmd
)
{
case
INS_INSROWS
:
{
aRange
.
aStart
.
SetCol
(
0
);
aRange
.
aEnd
.
SetCol
(
MAXCOL
);
// Continue below.
}
case
INS_CELLSDOWN
:
{
for
(
ScMarkData
::
const_iterator
it
=
itBeg
;
it
!=
itEnd
;
++
it
)
{
if
(
pDPs
->
IntersectsTableByColumns
(
aRange
.
aStart
.
Col
(),
aRange
.
aEnd
.
Col
(),
aRange
.
aStart
.
Row
(),
*
it
))
// This column range cuts through at least one pivot table. Not good.
return
false
;
}
// Start row must be either at the top or above any pivot tables.
if
(
aRange
.
aStart
.
Row
()
<
0
)
// I don't know how to handle this case.
return
false
;
if
(
aRange
.
aStart
.
Row
()
==
0
)
// First row is always allowed.
return
true
;
ScRange
aTest
(
aRange
);
aTest
.
aStart
.
IncRow
(
-
1
);
// Test one row up.
aTest
.
aEnd
.
SetRow
(
aTest
.
aStart
.
Row
());
for
(
ScMarkData
::
const_iterator
it
=
itBeg
;
it
!=
itEnd
;
++
it
)
{
aTest
.
aStart
.
SetTab
(
*
it
);
aTest
.
aEnd
.
SetTab
(
*
it
);
if
(
pDPs
->
HasTable
(
aTest
))
return
false
;
}
}
break
;
case
INS_INSCOLS
:
{
aRange
.
aStart
.
SetRow
(
0
);
aRange
.
aEnd
.
SetRow
(
MAXROW
);
// Continue below.
}
case
INS_CELLSRIGHT
:
{
for
(
ScMarkData
::
const_iterator
it
=
itBeg
;
it
!=
itEnd
;
++
it
)
{
if
(
pDPs
->
IntersectsTableByRows
(
aRange
.
aStart
.
Col
(),
aRange
.
aStart
.
Row
(),
aRange
.
aEnd
.
Row
(),
*
it
))
// This column range cuts through at least one pivot table. Not good.
return
false
;
}
// Start row must be either at the top or above any pivot tables.
if
(
aRange
.
aStart
.
Col
()
<
0
)
// I don't know how to handle this case.
return
false
;
if
(
aRange
.
aStart
.
Col
()
==
0
)
// First row is always allowed.
return
true
;
ScRange
aTest
(
aRange
);
aTest
.
aStart
.
IncCol
(
-
1
);
// Test one column to the left.
aTest
.
aEnd
.
SetCol
(
aTest
.
aStart
.
Col
());
for
(
ScMarkData
::
const_iterator
it
=
itBeg
;
it
!=
itEnd
;
++
it
)
{
aTest
.
aStart
.
SetTab
(
*
it
);
aTest
.
aEnd
.
SetTab
(
*
it
);
if
(
pDPs
->
HasTable
(
aTest
))
return
false
;
}
}
break
;
default
:
;
}
return
true
;
}
/**
* Check if this deletion attempt would end up cutting one or more pivot
* tables in half, which is not desirable.
*
* @return true if this deletion can be done safely without shearing any
* existing pivot tables, false otherwise.
*/
bool
canDeleteCellsByPivot
(
const
ScRange
&
rRange
,
const
ScMarkData
&
rMarkData
,
DelCellCmd
eCmd
,
const
ScDocument
*
pDoc
)
{
if
(
!
pDoc
->
HasPivotTable
())
// This document has no pivot tables.
return
true
;
const
ScDPCollection
*
pDPs
=
pDoc
->
GetDPCollection
();
ScMarkData
::
const_iterator
itBeg
=
rMarkData
.
begin
(),
itEnd
=
rMarkData
.
end
();
ScRange
aRange
(
rRange
);
// local copy
switch
(
eCmd
)
{
case
DEL_DELROWS
:
{
aRange
.
aStart
.
SetCol
(
0
);
aRange
.
aEnd
.
SetCol
(
MAXCOL
);
// Continue below.
}
case
DEL_CELLSUP
:
{
for
(
ScMarkData
::
const_iterator
it
=
itBeg
;
it
!=
itEnd
;
++
it
)
{
if
(
pDPs
->
IntersectsTableByColumns
(
aRange
.
aStart
.
Col
(),
aRange
.
aEnd
.
Col
(),
aRange
.
aStart
.
Row
(),
*
it
))
// This column range cuts through at least one pivot table. Not good.
return
false
;
}
ScRange
aTest
(
aRange
);
for
(
ScMarkData
::
const_iterator
it
=
itBeg
;
it
!=
itEnd
;
++
it
)
{
aTest
.
aStart
.
SetTab
(
*
it
);
aTest
.
aEnd
.
SetTab
(
*
it
);
if
(
pDPs
->
HasTable
(
aTest
))
return
false
;
}
}
break
;
case
DEL_DELCOLS
:
{
aRange
.
aStart
.
SetRow
(
0
);
aRange
.
aEnd
.
SetRow
(
MAXROW
);
// Continue below.
}
case
DEL_CELLSLEFT
:
{
for
(
ScMarkData
::
const_iterator
it
=
itBeg
;
it
!=
itEnd
;
++
it
)
{
if
(
pDPs
->
IntersectsTableByRows
(
aRange
.
aStart
.
Col
(),
aRange
.
aStart
.
Row
(),
aRange
.
aEnd
.
Row
(),
*
it
))
// This column range cuts through at least one pivot table. Not good.
return
false
;
}
ScRange
aTest
(
aRange
);
for
(
ScMarkData
::
const_iterator
it
=
itBeg
;
it
!=
itEnd
;
++
it
)
{
aTest
.
aStart
.
SetTab
(
*
it
);
aTest
.
aEnd
.
SetTab
(
*
it
);
if
(
pDPs
->
HasTable
(
aTest
))
return
false
;
}
}
break
;
default
:
;
}
return
true
;
}
}
bool
ScDocFunc
::
InsertCells
(
const
ScRange
&
rRange
,
const
ScMarkData
*
pTabMark
,
InsCellCmd
eCmd
,
bool
bRecord
,
bool
bApi
,
bool
bPartOfPaste
)
...
...
@@ -1463,6 +1639,14 @@ bool ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark,
return
false
;
}
// Check if this insertion is allowed with respect to pivot table.
if
(
!
canInsertCellsByPivot
(
rRange
,
aMark
,
eCmd
,
pDoc
))
{
if
(
!
bApi
)
rDocShell
.
ErrorMessage
(
STR_NO_INSERT_DELETE_OVER_PIVOT_TABLE
);
return
false
;
}
WaitObject
aWait
(
rDocShell
.
GetActiveDialogParent
()
);
// wichtig wegen TrackFormulas bei UpdateReference
ScDocument
*
pRefUndoDoc
=
NULL
;
...
...
@@ -1880,6 +2064,12 @@ bool ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark,
return
false
;
}
if
(
!
canDeleteCellsByPivot
(
rRange
,
aMark
,
eCmd
,
pDoc
))
{
if
(
!
bApi
)
rDocShell
.
ErrorMessage
(
STR_NO_INSERT_DELETE_OVER_PIVOT_TABLE
);
return
false
;
}
// Test zusammengefasste
SCCOL
nMergeTestEndCol
=
(
eCmd
==
DEL_CELLSLEFT
)
?
MAXCOL
:
nUndoEndCol
;
...
...
sc/source/ui/src/globstr.src
Dosyayı görüntüle @
8a5b9413
...
...
@@ -2017,5 +2017,10 @@ Resource RID_GLOBSTR
{
Text [ en-US ] = "Always perform this without prompt in the future.";
};
String STR_NO_INSERT_DELETE_OVER_PIVOT_TABLE
{
Text [ en-US ] = "You cannot insert or delete cells when the affected range intersects with pivot table.";
};
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment