sc: Add sheet view sync for CreatePivotTableOperation
For pivot tables we operate with ScDPObject as input, which has the input and output ranges. We need to convert the ranges to the default view tab, so the pivot table is created on the default view. Sync will take pivot tables into account when copying the content to sheet views, so we don't need to do anything special here. Change-Id: Ie28fda2d04576fd689d11010401709c6c02431c8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/201695 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/202115 Tested-by: Tomaž Vajngerl <quikee@gmail.com> Reviewed-by: Tomaž Vajngerl <quikee@gmail.com> (cherry picked from commit a36ac18990c89f740b8329b8325e4abe3d3e2087) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/205551 Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org> Tested-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
committed by
Xisco Fauli
parent
86c3b212a8
commit
7f2a75d8d7
@@ -44,6 +44,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sc_sheetview_test, \
|
||||
$(eval $(call gb_CppunitTest_use_externals,sc_sheetview_test,\
|
||||
boost_headers \
|
||||
libxml2 \
|
||||
mdds_headers \
|
||||
))
|
||||
|
||||
$(eval $(call gb_CppunitTest_set_include,sc_sheetview_test,\
|
||||
|
||||
+1
-1
@@ -437,7 +437,7 @@ public:
|
||||
SC_DLLPUBLIC ScDPObject& operator[](size_t nIndex);
|
||||
SC_DLLPUBLIC const ScDPObject& operator[](size_t nIndex) const;
|
||||
|
||||
ScDPObject* GetByName(std::u16string_view rName) const;
|
||||
SC_DLLPUBLIC ScDPObject* GetByName(std::u16string_view rName) const;
|
||||
|
||||
void DeleteOnTab( SCTAB nTab );
|
||||
void UpdateReference( UpdateRefMode eUpdateRefMode,
|
||||
|
||||
@@ -37,9 +37,15 @@
|
||||
#include <Sparkline.hxx>
|
||||
#include <SparklineAttributes.hxx>
|
||||
#include <SparklineGroup.hxx>
|
||||
#include <dpobject.hxx>
|
||||
#include <dpshttab.hxx>
|
||||
#include <dpsave.hxx>
|
||||
#include <generalfunction.hxx>
|
||||
#include <svx/svdorect.hxx>
|
||||
#include <svx/svdpage.hxx>
|
||||
|
||||
#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
|
||||
|
||||
using namespace css;
|
||||
|
||||
class SheetViewTest : public ScTiledRenderingTest
|
||||
@@ -3724,6 +3730,100 @@ CPPUNIT_TEST_FIXTURE(SyncTest, testSync_DeleteSparklineGroup_DefaultAndSheetView
|
||||
}
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(SyncTest, testSync_CreatePivotTable_DefaultAndSheetView)
|
||||
{
|
||||
// test sync to sheet view when creating a new pivot table
|
||||
ScModelObj* pModelObj = createDoc("empty.ods");
|
||||
pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
|
||||
ScDocShell* pDocShell = dynamic_cast<ScDocShell*>(pModelObj->GetEmbeddedObject());
|
||||
ScDocument& rDocument = pDocShell->GetDocument();
|
||||
|
||||
// Set up source data: A1:B4 with headers and values
|
||||
rDocument.SetString(ScAddress(0, 0, 0), u"Category"_ustr);
|
||||
rDocument.SetString(ScAddress(1, 0, 0), u"Value"_ustr);
|
||||
rDocument.SetString(ScAddress(0, 1, 0), u"A"_ustr);
|
||||
rDocument.SetString(ScAddress(0, 2, 0), u"A"_ustr);
|
||||
rDocument.SetString(ScAddress(0, 3, 0), u"B"_ustr);
|
||||
rDocument.SetValue(ScAddress(1, 1, 0), 10.0);
|
||||
rDocument.SetValue(ScAddress(1, 2, 0), 20.0);
|
||||
rDocument.SetValue(ScAddress(1, 3, 0), 30.0);
|
||||
|
||||
setupViews();
|
||||
|
||||
// Create sheet view
|
||||
{
|
||||
switchToSheetView();
|
||||
createNewSheetViewInCurrentView();
|
||||
}
|
||||
|
||||
SCTAB nSheetViewTab = mpTabViewSheetView->GetViewData().GetTabNumber();
|
||||
SCTAB nDefaultViewTab = mpTabViewDefaultView->GetViewData().GetTabNumber();
|
||||
|
||||
// Create pivot table from default view
|
||||
{
|
||||
switchToDefaultView();
|
||||
|
||||
ScDPObject aDPObject(&rDocument);
|
||||
ScSheetSourceDesc aSheetDesc(&rDocument);
|
||||
aSheetDesc.SetSourceRange(ScRange(0, 0, nDefaultViewTab, 1, 3, nDefaultViewTab));
|
||||
aDPObject.SetSheetDesc(aSheetDesc);
|
||||
aDPObject.SetOutRange(ScRange(ScAddress(4, 0, nDefaultViewTab)));
|
||||
|
||||
ScDPSaveData aSaveData;
|
||||
ScDPSaveDimension* pDim = aSaveData.GetNewDimensionByName(u"Category"_ustr);
|
||||
pDim->SetOrientation(css::sheet::DataPilotFieldOrientation_ROW);
|
||||
pDim = aSaveData.GetNewDimensionByName(u"Value"_ustr);
|
||||
pDim->SetOrientation(css::sheet::DataPilotFieldOrientation_DATA);
|
||||
pDim->SetFunction(ScGeneralFunction::SUM);
|
||||
aDPObject.SetSaveData(aSaveData);
|
||||
|
||||
ScDBDocFunc aDBDocFunc(*pDocShell);
|
||||
bool bResult = aDBDocFunc.CreatePivotTable(aDPObject, true, true);
|
||||
CPPUNIT_ASSERT(bResult);
|
||||
|
||||
// Verify pivot table output on default view - cell E1 should have content
|
||||
CPPUNIT_ASSERT(!rDocument.GetString(ScAddress(4, 0, nDefaultViewTab)).isEmpty());
|
||||
|
||||
// Verify the pivot table output is synced to sheet view
|
||||
CPPUNIT_ASSERT_EQUAL(rDocument.GetString(ScAddress(4, 0, nDefaultViewTab)),
|
||||
rDocument.GetString(ScAddress(4, 0, nSheetViewTab)));
|
||||
CPPUNIT_ASSERT_EQUAL(rDocument.GetString(ScAddress(4, 1, nDefaultViewTab)),
|
||||
rDocument.GetString(ScAddress(4, 1, nSheetViewTab)));
|
||||
}
|
||||
|
||||
// Create pivot table from sheet view
|
||||
{
|
||||
switchToSheetView();
|
||||
|
||||
ScDPObject aDPObject(&rDocument);
|
||||
ScSheetSourceDesc aSheetDesc(&rDocument);
|
||||
aSheetDesc.SetSourceRange(ScRange(0, 0, nSheetViewTab, 1, 3, nSheetViewTab));
|
||||
aDPObject.SetSheetDesc(aSheetDesc);
|
||||
aDPObject.SetOutRange(ScRange(ScAddress(7, 0, nSheetViewTab)));
|
||||
|
||||
ScDPSaveData aSaveData;
|
||||
ScDPSaveDimension* pDim = aSaveData.GetNewDimensionByName(u"Category"_ustr);
|
||||
pDim->SetOrientation(css::sheet::DataPilotFieldOrientation_ROW);
|
||||
pDim = aSaveData.GetNewDimensionByName(u"Value"_ustr);
|
||||
pDim->SetOrientation(css::sheet::DataPilotFieldOrientation_DATA);
|
||||
pDim->SetFunction(ScGeneralFunction::SUM);
|
||||
aDPObject.SetSaveData(aSaveData);
|
||||
|
||||
ScDBDocFunc aDBDocFunc(*pDocShell);
|
||||
bool bResult = aDBDocFunc.CreatePivotTable(aDPObject, true, true);
|
||||
CPPUNIT_ASSERT(bResult);
|
||||
|
||||
// Verify pivot table created on default view - cell H1 should have content
|
||||
CPPUNIT_ASSERT(!rDocument.GetString(ScAddress(7, 0, nDefaultViewTab)).isEmpty());
|
||||
|
||||
// Verify the pivot table output is synced to sheet view
|
||||
CPPUNIT_ASSERT_EQUAL(rDocument.GetString(ScAddress(7, 0, nDefaultViewTab)),
|
||||
rDocument.GetString(ScAddress(7, 0, nSheetViewTab)));
|
||||
CPPUNIT_ASSERT_EQUAL(rDocument.GetString(ScAddress(7, 1, nDefaultViewTab)),
|
||||
rDocument.GetString(ScAddress(7, 1, nSheetViewTab)));
|
||||
}
|
||||
}
|
||||
|
||||
CPPUNIT_PLUGIN_IMPLEMENT();
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
||||
@@ -93,7 +93,7 @@ public:
|
||||
bool bRecord, bool bApi, bool bAllowMove = false );
|
||||
|
||||
bool RemovePivotTable(const ScDPObject& rDPObj, bool bRecord, bool bApi);
|
||||
bool CreatePivotTable(const ScDPObject& rDPObj, bool bRecord, bool bApi);
|
||||
SC_DLLPUBLIC bool CreatePivotTable(const ScDPObject& rDPObj, bool bRecord, bool bApi);
|
||||
bool UpdatePivotTable(ScDPObject& rDPObj, bool bRecord, bool bApi);
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,12 +21,12 @@ class CreatePivotTableOperation : public Operation
|
||||
{
|
||||
private:
|
||||
ScDocShell& mrDocShell;
|
||||
ScDPObject const& mrDPObj;
|
||||
ScDPObject const& mrDPObject;
|
||||
|
||||
bool runImplementation() override;
|
||||
|
||||
public:
|
||||
CreatePivotTableOperation(ScDocShell& rDocShell, ScDPObject const& rDPObj, bool bRecord,
|
||||
CreatePivotTableOperation(ScDocShell& rDocShell, ScDPObject const& rDPObject, bool bRecord,
|
||||
bool bApi);
|
||||
};
|
||||
} // end sc namespace
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <vcl/weld/Window.hxx>
|
||||
|
||||
#include <dpsave.hxx>
|
||||
#include <dpshttab.hxx>
|
||||
#include <undodat.hxx>
|
||||
#include <scresid.hxx>
|
||||
#include <hints.hxx>
|
||||
@@ -23,11 +24,11 @@
|
||||
namespace sc
|
||||
{
|
||||
CreatePivotTableOperation::CreatePivotTableOperation(ScDocShell& rDocShell,
|
||||
ScDPObject const& rDPObj, bool bRecord,
|
||||
ScDPObject const& rDPObject, bool bRecord,
|
||||
bool bApi)
|
||||
: Operation(OperationType::PivotTableCreate, bRecord, bApi)
|
||||
, mrDocShell(rDocShell)
|
||||
, mrDPObj(rDPObj)
|
||||
, mrDPObject(rDPObject)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -36,55 +37,65 @@ bool CreatePivotTableOperation::runImplementation()
|
||||
ScDocShellModificator aModificator(mrDocShell);
|
||||
weld::WaitObject aWait(ScDocShell::GetActiveDialogParent());
|
||||
|
||||
if (!checkSheetViewProtection())
|
||||
return false;
|
||||
|
||||
// At least one cell in the output range should be editable. Check in advance.
|
||||
ScDocument& rDoc = mrDocShell.GetDocument();
|
||||
if (!rDoc.IsImportingXML()
|
||||
&& !sc::pivot::isEditable(mrDocShell, ScRange(mrDPObj.GetOutRange().aStart), mbApi))
|
||||
auto aOutputStartRange = convertRange(ScRange(mrDPObject.GetOutRange().aStart));
|
||||
if (!rDoc.IsImportingXML() && !sc::pivot::isEditable(mrDocShell, aOutputStartRange, mbApi))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ScDocumentUniquePtr pNewUndoDoc;
|
||||
|
||||
if (mbRecord && !rDoc.IsUndoEnabled())
|
||||
mbRecord = false;
|
||||
|
||||
// output range must be set at pNewObj
|
||||
std::unique_ptr<ScDPObject> pDestObj(new ScDPObject(mrDPObj));
|
||||
// output range must be set at pNewObject
|
||||
std::unique_ptr<ScDPObject> pDestObject(new ScDPObject(mrDPObject));
|
||||
|
||||
ScDPObject& rDestObj = *pDestObj;
|
||||
ScDPObject& rDestObject = *pDestObject;
|
||||
|
||||
// Convert ranges from sheet view to default view
|
||||
rDestObject.SetOutRange(convertRange(rDestObject.GetOutRange()));
|
||||
|
||||
const ScSheetSourceDesc* pSheetDesc = rDestObject.GetSheetDesc();
|
||||
if (pSheetDesc && !pSheetDesc->HasRangeName())
|
||||
{
|
||||
ScSheetSourceDesc aDesc(*pSheetDesc);
|
||||
aDesc.SetSourceRange(convertRange(aDesc.GetSourceRange()));
|
||||
rDestObject.SetSheetDesc(aDesc);
|
||||
}
|
||||
|
||||
// #i94570# When changing the output position in the dialog, a new table is created
|
||||
// with the settings from the old table, including the name.
|
||||
// So we have to check for duplicate names here (before inserting).
|
||||
if (rDoc.GetDPCollection()->GetByName(rDestObj.GetName()))
|
||||
rDestObj.SetName(OUString()); // ignore the invalid name, create a new name below
|
||||
if (rDoc.GetDPCollection()->GetByName(rDestObject.GetName()))
|
||||
rDestObject.SetName(OUString()); // ignore the invalid name, create a new name below
|
||||
|
||||
// Synchronize groups between linked tables
|
||||
{
|
||||
const ScDPDimensionSaveData* pGroups = nullptr;
|
||||
bool bRefFound = rDoc.GetDPCollection()->GetReferenceGroups(rDestObj, &pGroups);
|
||||
bool bRefFound = rDoc.GetDPCollection()->GetReferenceGroups(rDestObject, &pGroups);
|
||||
if (bRefFound)
|
||||
{
|
||||
ScDPSaveData* pSaveData = rDestObj.GetSaveData();
|
||||
ScDPSaveData* pSaveData = rDestObject.GetSaveData();
|
||||
if (pSaveData)
|
||||
pSaveData->SetDimensionData(pGroups);
|
||||
}
|
||||
}
|
||||
|
||||
rDoc.GetDPCollection()->InsertNewTable(std::move(pDestObj));
|
||||
rDoc.GetDPCollection()->InsertNewTable(std::move(pDestObject));
|
||||
|
||||
rDestObj.ReloadGroupTableData();
|
||||
rDestObj.SyncAllDimensionMembers();
|
||||
rDestObj.InvalidateData(); // before getting the new output area
|
||||
rDestObject.ReloadGroupTableData();
|
||||
rDestObject.SyncAllDimensionMembers();
|
||||
rDestObject.InvalidateData(); // before getting the new output area
|
||||
|
||||
// make sure the table has a name (not set by dialog)
|
||||
if (rDestObj.GetName().isEmpty())
|
||||
rDestObj.SetName(rDoc.GetDPCollection()->CreateNewName());
|
||||
if (rDestObject.GetName().isEmpty())
|
||||
rDestObject.SetName(rDoc.GetDPCollection()->CreateNewName());
|
||||
|
||||
bool bOverflow = false;
|
||||
ScRange aNewOut = rDestObj.GetNewOutputRange(bOverflow);
|
||||
ScRange aNewOut = rDestObject.GetNewOutputRange(bOverflow);
|
||||
|
||||
if (bOverflow)
|
||||
{
|
||||
@@ -132,17 +143,19 @@ bool CreatePivotTableOperation::runImplementation()
|
||||
if (mbRecord)
|
||||
sc::pivot::createUndoDoc(pNewUndoDoc, rDoc, aNewOut);
|
||||
|
||||
rDestObj.Output(aNewOut.aStart);
|
||||
rDestObject.Output(aNewOut.aStart);
|
||||
mrDocShell.PostPaintGridAll(); //! only necessary parts
|
||||
|
||||
if (mbRecord)
|
||||
{
|
||||
mrDocShell.GetUndoManager()->AddUndoAction(std::make_unique<ScUndoDataPilot>(
|
||||
mrDocShell, nullptr, std::move(pNewUndoDoc), nullptr, &rDestObj, false));
|
||||
mrDocShell, nullptr, std::move(pNewUndoDoc), nullptr, &rDestObject, false));
|
||||
}
|
||||
|
||||
syncSheetViews();
|
||||
|
||||
// notify API objects
|
||||
rDoc.BroadcastUno(ScDataPilotModifiedHint(rDestObj.GetName()));
|
||||
rDoc.BroadcastUno(ScDataPilotModifiedHint(rDestObject.GetName()));
|
||||
aModificator.SetDocumentModified();
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user