Kaydet (Commit) 1bfbe2a4 authored tarafından Dennis Francis's avatar Dennis Francis Kaydeden (comit) Eike Rathke

tdf#99938 : Allow batch of formula-cells to be written...

using a single undo document from ScMovingAverageDialog
rather than write tons of formula-cells to the document
one by one thus creating that many number of undo docs
unnecessarily.

Change-Id: I2528e0ab47f83e0c5ea40c73d00db5af14f656e0
Reviewed-on: https://gerrit.libreoffice.org/71823
Tested-by: Jenkins
Reviewed-by: 's avatarEike Rathke <erack@redhat.com>
üst 6b2cff82
......@@ -15,6 +15,7 @@
#include <vector>
class ScColumn;
class ScFormulaCell;
namespace svl {
......@@ -63,6 +64,7 @@ public:
void swapNonEmpty( ScColumn& rCol );
void assign( const std::vector<double>& rVals );
void assign( const std::vector<ScFormulaCell*>& rVals );
size_t size() const;
......
......@@ -10,6 +10,7 @@
#include <memory>
#include <cellvalues.hxx>
#include <column.hxx>
#include <formulacell.hxx>
#include <cassert>
......@@ -98,6 +99,25 @@ void CellValues::assign( const std::vector<double>& rVals )
mpImpl->maCellTextAttrs.set(0, aDefaults.begin(), aDefaults.end());
}
void CellValues::assign( const std::vector<ScFormulaCell*>& rVals )
{
std::vector<ScFormulaCell*> aCopyVals(rVals.size());
size_t nIdx = 0;
for (const auto* pCell : rVals)
{
aCopyVals[nIdx] = pCell->Clone();
++nIdx;
}
mpImpl->maCells.resize(aCopyVals.size());
mpImpl->maCells.set(0, aCopyVals.begin(), aCopyVals.end());
// Set default text attributes.
std::vector<CellTextAttr> aDefaults(rVals.size(), CellTextAttr());
mpImpl->maCellTextAttrs.resize(rVals.size());
mpImpl->maCellTextAttrs.set(0, aDefaults.begin(), aDefaults.end());
}
size_t CellValues::size() const
{
assert(mpImpl->maCells.size() == mpImpl->maCellTextAttrs.size());
......@@ -154,7 +174,7 @@ void CellValues::copyCellsTo( ScColumn& rCol, SCROW nRow ) const
const CellStoreType& rSrc = mpImpl->maCells;
// Caller must ensure the destination is long enough.
assert(rSrc.size() + static_cast<size_t>(nRow) < rDest.size());
assert(rSrc.size() + static_cast<size_t>(nRow) <= rDest.size());
SCROW nCurRow = nRow;
CellStoreType::iterator itPos = rDest.begin();
......@@ -219,7 +239,7 @@ void CellValues::copyCellTextAttrsTo( ScColumn& rCol, SCROW nRow ) const
const CellTextAttrStoreType& rSrc = mpImpl->maCellTextAttrs;
// Caller must ensure the destination is long enough.
assert(rSrc.size() + static_cast<size_t>(nRow) < rDest.size());
assert(rSrc.size() + static_cast<size_t>(nRow) <= rDest.size());
SCROW nCurRow = nRow;
CellTextAttrStoreType::iterator itPos = rDest.begin();
......
......@@ -75,6 +75,7 @@ ScRange ScMovingAverageDialog::ApplyOutput(ScDocShell* pDocShell)
output.nextRow();
DataCellIterator aDataCellIterator = pIterator->iterateCells();
std::vector<OUString> aFormulas;
for (; aDataCellIterator.hasNext(); aDataCellIterator.next())
{
......@@ -98,14 +99,15 @@ ScRange ScMovingAverageDialog::ApplyOutput(ScDocShell* pDocShell)
{
aTemplate.setTemplate("=AVERAGE(%RANGE%)");
aTemplate.applyRange("%RANGE%", ScRange(aIntervalStart, aIntervalEnd));
output.writeFormula(aTemplate.getTemplate());
aFormulas.push_back(aTemplate.getTemplate());
}
else
{
output.writeFormula("=#N/A");
aFormulas.push_back("=#N/A");
}
output.nextRow();
}
output.writeFormulas(aFormulas);
output.nextColumn();
}
return ScRange(output.mMinimumAddress, output.mMaximumAddress);
......
......@@ -163,6 +163,28 @@ void AddressWalkerWriter::writeFormula(const OUString& aFormula)
new ScFormulaCell(mpDocument, mCurrentAddress, aFormula, meGrammar), true);
}
void AddressWalkerWriter::writeFormulas(const std::vector<OUString>& rFormulas)
{
size_t nLength = rFormulas.size();
if (!nLength)
return;
const size_t nMaxLen = MAXROW - mCurrentAddress.Row() + 1;
// If not done already, trim the length to fit.
if (nLength > nMaxLen)
nLength = nMaxLen;
std::vector<ScFormulaCell*> aFormulaCells(nLength);
ScAddress aAddr(mCurrentAddress);
for (size_t nIdx = 0; nIdx < nLength; ++nIdx)
{
aFormulaCells[nIdx] = new ScFormulaCell(mpDocument, aAddr, rFormulas[nIdx], meGrammar);
aAddr.IncRow(1);
}
mpDocShell->GetDocFunc().SetFormulaCells(mCurrentAddress, aFormulaCells, true);
}
void AddressWalkerWriter::writeMatrixFormula(const OUString& aFormula, SCCOL nCols, SCROW nRows)
{
ScRange aRange;
......
......@@ -1023,6 +1023,61 @@ bool ScDocFunc::SetFormulaCell( const ScAddress& rPos, ScFormulaCell* pCell, boo
return true;
}
bool ScDocFunc::SetFormulaCells( const ScAddress& rPos, std::vector<ScFormulaCell*>& rCells, bool bInteraction )
{
const size_t nLength = rCells.size();
if (rPos.Row() + nLength - 1 > MAXROW)
// out of bound
return false;
ScRange aRange(rPos);
aRange.aEnd.IncRow(nLength - 1);
ScDocShellModificator aModificator( rDocShell );
ScDocument& rDoc = rDocShell.GetDocument();
bool bUndo = rDoc.IsUndoEnabled();
std::unique_ptr<sc::UndoSetCells> pUndoObj;
if (bUndo)
{
pUndoObj.reset(new sc::UndoSetCells(&rDocShell, rPos));
rDoc.TransferCellValuesTo(rPos, nLength, pUndoObj->GetOldValues());
}
rDoc.SetFormulaCells(rPos, rCells);
// For performance reasons API calls may disable calculation while
// operating and recalculate once when done. If through user interaction
// and AutoCalc is disabled, calculate the formula (without its
// dependencies) once so the result matches the current document's content.
if (bInteraction && !rDoc.GetAutoCalc())
{
for (auto* pCell : rCells)
{
// calculate just the cell once and set Dirty again
pCell->Interpret();
pCell->SetDirtyVar();
rDoc.PutInFormulaTree( pCell);
}
}
if (bUndo)
{
pUndoObj->SetNewValues(rCells);
SfxUndoManager* pUndoMgr = rDocShell.GetUndoManager();
pUndoMgr->AddUndoAction(std::move(pUndoObj));
}
rDocShell.PostPaint(aRange, PaintPartFlags::Grid);
aModificator.SetDocumentModified();
// #103934#; notify editline and cell in edit mode
if (!bInteraction)
NotifyInputHandler( rPos );
return true;
}
void ScDocFunc::NotifyInputHandler( const ScAddress& rPos )
{
ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
......
......@@ -80,6 +80,7 @@ public:
formula::FormulaGrammar::Grammar eGrammar );
void writeFormula(const OUString& aFormula);
void writeFormulas(const std::vector<OUString>& rFormulas);
void writeMatrixFormula(const OUString& aFormula, SCCOL nCols = 1, SCROW nRows = 1);
void writeString(const OUString& aString);
void writeString(const char* aCharArray);
......
......@@ -104,10 +104,11 @@ public:
bool SetStringOrEditCell( const ScAddress& rPos, const OUString& rStr, bool bInteraction );
/**
* This method takes ownership of the formula cell instance. The caller
* Below two methods take ownership of the formula cell instance(s). The caller
* must not delete it after passing it to this call.
*/
bool SetFormulaCell( const ScAddress& rPos, ScFormulaCell* pCell, bool bInteraction );
bool SetFormulaCells( const ScAddress& rPos, std::vector<ScFormulaCell*>& rCells, bool bInteraction );
void PutData( const ScAddress& rPos, ScEditEngineDefaulter& rEngine, bool bApi );
bool SetCellText(
const ScAddress& rPos, const OUString& rText, bool bInterpret, bool bEnglish, bool bApi,
......
......@@ -32,6 +32,7 @@
class ScDocShell;
class ScPatternAttr;
class ScRangeName;
class ScFormulaCell;
class ScUndoCursorAttr: public ScSimpleUndo
{
......@@ -361,6 +362,7 @@ public:
CellValues& GetOldValues() { return maOldValues;}
void SetNewValues( const std::vector<double>& rVals );
void SetNewValues( const std::vector<ScFormulaCell*>& rVals );
};
} // namespace sc
......
......@@ -11,6 +11,7 @@
#include <globstr.hrc>
#include <scresid.hxx>
#include <cellvalues.hxx>
#include <formulacell.hxx>
namespace sc {
......@@ -60,6 +61,11 @@ void UndoSetCells::SetNewValues( const std::vector<double>& rVals )
maNewValues.assign(rVals);
}
void UndoSetCells::SetNewValues( const std::vector<ScFormulaCell*>& rVals )
{
maNewValues.assign(rVals);
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment