/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
const ScFormulaCell* SharedFormulaUtil::getSharedTopFormulaCell(const CellStoreType::position_type& aPos)
{ if (aPos.first->type != sc::element_type_formula) // Not a formula cell block. return nullptr;
sc::formula_block::iterator it = sc::formula_block::begin(*aPos.first->data);
std::advance(it, aPos.second); const ScFormulaCell* pCell = *it; if (!pCell->IsShared()) // Not a shared formula. return nullptr;
if (aPos.first->type != sc::element_type_formula) // Not a formula cell block. returnfalse;
if (aPos.second == 0) // Split position coincides with the block border. Nothing to do. returnfalse;
sc::formula_block::iterator it = sc::formula_block::begin(*aPos.first->data);
std::advance(it, aPos.second);
ScFormulaCell& rTop = **it; if (!rTop.IsShared()) // Not a shared formula. returnfalse;
if (nRow == rTop.GetSharedTopRow()) // Already the top cell of a shared group. returnfalse;
#if USE_FORMULA_GROUP_LISTENER // At least group area listeners will have to be adapted. As long as // there's no update mechanism and no separated handling of group area and // other listeners, all listeners of this group's top cell are to be reset. if (nLength2)
{ // If a context exists it has to be used to not interfere with // ScColumn::maBroadcasters iterators, which the EndListeningTo() // without context would do when removing a broadcaster that had its // last listener removed. if (pCxt)
rPrevTop.EndListeningTo(*pCxt); else
rPrevTop.EndListeningTo( rPrevTop.GetDocument(), nullptr, ScAddress( ScAddress::UNINITIALIZED));
rPrevTop.SetNeedsListening(true);
// The new group or remaining single cell needs a new listening.
rTop.SetNeedsListening(true);
} #endif
if (xGroup->mnLength == 1)
{ // The top group consists of only one cell. Ungroup this.
ScFormulaCellGroupRef xNone;
rPrevTop.SetCellGroup(xNone);
}
// Apply the lower group object to the lower cells.
assert ((xGroup2 == nullptr || xGroup2->mpTopCell->aPos.Row() + size_t(xGroup2->mnLength) <= aPos.first->position + aPos.first->size)
&& "Shared formula region goes beyond the formula block.");
sc::formula_block::iterator itEnd = it;
std::advance(itEnd, nLength2); for (; it != itEnd; ++it)
{
ScFormulaCell& rCell = **it;
rCell.SetCellGroup(xGroup2);
}
ScFormulaCell::CompareState eState = rCell1.CompareByTokenArray(rCell2); if (eState == ScFormulaCell::NotEqual) returnfalse;
// Formula tokens equal those of the previous formula cell.
ScFormulaCellGroupRef xGroup1 = rCell1.GetCellGroup();
ScFormulaCellGroupRef xGroup2 = rCell2.GetCellGroup(); if (xGroup1)
{ if (xGroup2)
{ // Both cell 1 and cell 2 are shared. Merge them together. if (xGroup1.get() == xGroup2.get()) // They belong to the same group. returnfalse;
// Set the group object from cell 1 to all cells in group 2.
xGroup1->mnLength += xGroup2->mnLength;
size_t nOffset = rPos.second + 1; // position of cell 2 for (size_t i = 0, n = xGroup2->mnLength; i < n; ++i)
{
ScFormulaCell& rCell = *sc::formula_block::at(*rPos.first->data, nOffset+i);
rCell.SetCellGroup(xGroup1);
}
} else
{ // cell 1 is shared but cell 2 is not.
rCell2.SetCellGroup(xGroup1);
++xGroup1->mnLength;
}
} else
{ if (xGroup2)
{ // cell 1 is not shared, but cell 2 is already shared.
rCell1.SetCellGroup(xGroup2);
xGroup2->mpTopCell = &rCell1;
++xGroup2->mnLength;
} else
{ // neither cells are shared.
assert(rCell1.aPos.Row() == static_cast<SCROW>(rPos.first->position + rPos.second));
xGroup1 = rCell1.CreateCellGroup(2, eState == ScFormulaCell::EqualInvariant);
rCell2.SetCellGroup(xGroup1);
}
}
returntrue;
}
bool SharedFormulaUtil::joinFormulaCellAbove( const CellStoreType::position_type& aPos )
{ if (aPos.first->type != sc::element_type_formula) // This is not a formula cell. returnfalse;
if (aPos.second == 0) // This cell is already the top cell in a formula block; the previous // cell is not a formula cell. returnfalse;
void SharedFormulaUtil::unshareFormulaCell(const CellStoreType::position_type& aPos, ScFormulaCell& rCell)
{ if (!rCell.IsShared()) return;
ScFormulaCellGroupRef xNone;
sc::CellStoreType::iterator it = aPos.first;
// This formula cell is shared. Adjust the shared group. if (rCell.aPos.Row() == rCell.GetSharedTopRow())
{ // Top of the shared range. const ScFormulaCellGroupRef& xGroup = rCell.GetCellGroup(); if (xGroup->mnLength == 2)
{ // Group consists of only two cells. Mark the second one non-shared.
assert (aPos.second+1 < aPos.first->size
&& "There is no next formula cell but there should be!");
ScFormulaCell& rNext = *sc::formula_block::at(*it->data, aPos.second+1);
rNext.SetCellGroup(xNone);
} else
{ // Move the top cell to the next formula cell down.
ScFormulaCell& rNext = *sc::formula_block::at(*it->data, aPos.second+1);
xGroup->mpTopCell = &rNext;
}
--xGroup->mnLength;
} elseif (rCell.aPos.Row() == rCell.GetSharedTopRow() + rCell.GetSharedLength() - 1)
{ // Bottom of the shared range. const ScFormulaCellGroupRef& xGroup = rCell.GetCellGroup(); if (xGroup->mnLength == 2)
{ // Mark the top cell non-shared.
assert(aPos.second != 0 && "There is no previous formula cell but there should be!");
ScFormulaCell& rPrev = *sc::formula_block::at(*it->data, aPos.second-1);
rPrev.SetCellGroup(xNone);
} else
{ // Just shorten the shared range length by one.
--xGroup->mnLength;
}
} else
{ // In the middle of the shared range. Split it into two groups. const ScFormulaCellGroupRef& xGroup = rCell.GetCellGroup();
SCROW nEndRow = xGroup->mpTopCell->aPos.Row() + xGroup->mnLength - 1;
xGroup->mnLength = rCell.aPos.Row() - xGroup->mpTopCell->aPos.Row(); // Shorten the top group. if (xGroup->mnLength == 1)
{ // Make the top cell non-shared.
assert(aPos.second != 0 && "There is no previous formula cell but there should be!");
ScFormulaCell& rPrev = *sc::formula_block::at(*it->data, aPos.second-1);
rPrev.SetCellGroup(xNone);
}
// Sort and remove duplicates.
std::sort(rRows.begin(), rRows.end());
rRows.erase(std::unique(rRows.begin(), rRows.end()), rRows.end());
// Add next cell positions to the list (to ensure that each position becomes a single cell).
std::vector<SCROW> aRows2; for (constauto& rRow : rRows)
{ if (rRow > rDoc.MaxRow()) break;
aRows2.push_back(rRow);
if (rRow < rDoc.MaxRow())
aRows2.push_back(rRow+1);
}
// Remove duplicates again (the vector should still be sorted).
aRows2.erase(std::unique(aRows2.begin(), aRows2.end()), aRows2.end());
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.