summaryrefslogtreecommitdiffstats
path: root/sc/source/ui/StatisticsDialogs/TableFillingAndNavigationTools.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui/StatisticsDialogs/TableFillingAndNavigationTools.cxx')
-rw-r--r--sc/source/ui/StatisticsDialogs/TableFillingAndNavigationTools.cxx386
1 files changed, 386 insertions, 0 deletions
diff --git a/sc/source/ui/StatisticsDialogs/TableFillingAndNavigationTools.cxx b/sc/source/ui/StatisticsDialogs/TableFillingAndNavigationTools.cxx
new file mode 100644
index 0000000000..be84311285
--- /dev/null
+++ b/sc/source/ui/StatisticsDialogs/TableFillingAndNavigationTools.cxx
@@ -0,0 +1,386 @@
+/* -*- 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/.
+ *
+ */
+
+#include <memory>
+
+#include <editeng/editobj.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/eeitem.hxx>
+
+#include <editutil.hxx>
+
+#include <TableFillingAndNavigationTools.hxx>
+#include <formulacell.hxx>
+#include <docfunc.hxx>
+#include <docsh.hxx>
+
+FormulaTemplate::FormulaTemplate(ScDocument* pDoc)
+ : mpDoc(pDoc)
+ , mbUse3D(true)
+{}
+
+void FormulaTemplate::setTemplate(const OUString& aTemplate)
+{
+ mTemplate = aTemplate;
+}
+
+void FormulaTemplate::setTemplate(const char* aTemplate)
+{
+ mTemplate = OUString::createFromAscii(aTemplate);
+}
+
+const OUString& FormulaTemplate::getTemplate()
+{
+ for (const auto& [rVariable, rRange] : mRangeReplacementMap)
+ {
+ applyRange(rVariable, rRange, mbUse3D);
+ }
+ for (const auto& [rVariable, rAddress] : mAddressReplacementMap)
+ {
+ applyAddress(rVariable, rAddress, mbUse3D);
+ }
+ return mTemplate;
+}
+
+void FormulaTemplate::autoReplaceRange(const OUString& aVariable, const ScRange& rRange)
+{
+ mRangeReplacementMap[aVariable] = rRange;
+}
+
+void FormulaTemplate::autoReplaceAddress(const OUString& aVariable, ScAddress const & aAddress)
+{
+
+ mAddressReplacementMap[aVariable] = aAddress;
+}
+
+void FormulaTemplate::applyRange(std::u16string_view aVariable, const ScRange& aRange, bool b3D)
+{
+ ScRefFlags nFlag = b3D ? ScRefFlags::RANGE_ABS_3D : ScRefFlags::RANGE_ABS;
+ OUString aString = aRange.Format(*mpDoc, nFlag, mpDoc->GetAddressConvention());
+ mTemplate = mTemplate.replaceAll(aVariable, aString);
+}
+
+void FormulaTemplate::applyRangeList(std::u16string_view aVariable, const ScRangeList& aRangeList, sal_Unicode cDelimiter)
+{
+ OUString aString;
+ aRangeList.Format(aString, ScRefFlags::RANGE_ABS_3D, *mpDoc, mpDoc->GetAddressConvention(), cDelimiter);
+ mTemplate = mTemplate.replaceAll(aVariable, aString);
+}
+
+void FormulaTemplate::applyAddress(std::u16string_view aVariable, const ScAddress& aAddress, bool b3D)
+{
+ ScRefFlags nFlag = b3D ? ScRefFlags::ADDR_ABS_3D : ScRefFlags::ADDR_ABS;
+ OUString aString = aAddress.Format(nFlag, mpDoc, mpDoc->GetAddressConvention());
+ mTemplate = mTemplate.replaceAll(aVariable, aString);
+}
+
+void FormulaTemplate::applyString(std::u16string_view aVariable, std::u16string_view aValue)
+{
+ mTemplate = mTemplate.replaceAll(aVariable, aValue);
+}
+
+void FormulaTemplate::applyNumber(std::u16string_view aVariable, sal_Int32 aValue)
+{
+ mTemplate = mTemplate.replaceAll(aVariable, OUString::number(aValue));
+}
+
+AddressWalker::AddressWalker(const ScAddress& aInitialAddress) :
+ mCurrentAddress(aInitialAddress),
+ mMinimumAddress(aInitialAddress),
+ mMaximumAddress(aInitialAddress)
+{
+ mAddressStack.push_back(mCurrentAddress);
+}
+
+void AddressWalker::resetColumn()
+{
+ mCurrentAddress.SetCol(mAddressStack.back().Col());
+}
+
+void AddressWalker::resetRow()
+{
+ mCurrentAddress.SetRow(mAddressStack.back().Row());
+}
+
+void AddressWalker::reset()
+{
+ mCurrentAddress = mAddressStack.back();
+}
+
+void AddressWalker::newLine()
+{
+ resetColumn();
+ nextRow();
+}
+
+ScAddress AddressWalker::current(SCCOL aRelCol, SCROW aRelRow, SCTAB aRelTab)
+{
+ return ScAddress(
+ mCurrentAddress.Col() + aRelCol,
+ mCurrentAddress.Row() + aRelRow,
+ mCurrentAddress.Tab() + aRelTab);
+}
+
+void AddressWalker::nextColumn()
+{
+ mCurrentAddress.IncCol();
+
+ if(mMaximumAddress.Col() < mCurrentAddress.Col())
+ mMaximumAddress.SetCol(mCurrentAddress.Col());
+}
+
+void AddressWalker::nextRow()
+{
+ mCurrentAddress.IncRow();
+ if(mMaximumAddress.Row() < mCurrentAddress.Row())
+ mMaximumAddress.SetRow(mCurrentAddress.Row());
+}
+
+void AddressWalker::push(SCCOL aRelativeCol, SCROW aRelativeRow, SCTAB aRelativeTab)
+{
+ mCurrentAddress = current(aRelativeCol, aRelativeRow, aRelativeTab);
+ mAddressStack.push_back(mCurrentAddress);
+}
+
+AddressWalkerWriter::AddressWalkerWriter(const ScAddress& aInitialAddress, ScDocShell* pDocShell, ScDocument& rDocument,
+ formula::FormulaGrammar::Grammar eGrammar ) :
+ AddressWalker(aInitialAddress),
+ mpDocShell(pDocShell),
+ mrDocument(rDocument),
+ meGrammar(eGrammar)
+{}
+
+void AddressWalkerWriter::writeFormula(const OUString& aFormula)
+{
+ mpDocShell->GetDocFunc().SetFormulaCell(mCurrentAddress,
+ new ScFormulaCell(mrDocument, mCurrentAddress, aFormula, meGrammar), true);
+}
+
+void AddressWalkerWriter::writeFormulas(const std::vector<OUString>& rFormulas)
+{
+ size_t nLength = rFormulas.size();
+ if (!nLength)
+ return;
+
+ const size_t nMaxLen = mpDocShell->GetDocument().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(mrDocument, 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;
+ aRange.aStart = mCurrentAddress;
+ aRange.aEnd = mCurrentAddress;
+ if (nCols > 1)
+ aRange.aEnd.IncCol(nCols - 1);
+ if (nRows > 1)
+ aRange.aEnd.IncRow(nRows - 1);
+ mpDocShell->GetDocFunc().EnterMatrix(aRange, nullptr, nullptr, aFormula, false, false, OUString(), meGrammar );
+}
+
+void AddressWalkerWriter::writeString(const OUString& aString)
+{
+ mpDocShell->GetDocFunc().SetStringCell(mCurrentAddress, aString, true);
+}
+
+void AddressWalkerWriter::writeString(const char* aCharArray)
+{
+ writeString(OUString::createFromAscii(aCharArray));
+}
+
+void AddressWalkerWriter::writeBoldString(const OUString& aString)
+{
+ ScFieldEditEngine& rEngine = mrDocument.GetEditEngine();
+ rEngine.SetTextCurrentDefaults(aString);
+ SfxItemSet aItemSet = rEngine.GetEmptyItemSet();
+ SvxWeightItem aWeight(WEIGHT_BOLD, EE_CHAR_WEIGHT);
+ aItemSet.Put(aWeight);
+ rEngine.QuickSetAttribs(aItemSet, ESelection(0, 0, 0, aString.getLength()) );
+ std::unique_ptr<EditTextObject> pEditText(rEngine.CreateTextObject());
+ mpDocShell->GetDocFunc().SetEditCell(mCurrentAddress, *pEditText, true);
+}
+
+void AddressWalkerWriter::writeValue(double aValue)
+{
+ mpDocShell->GetDocFunc().SetValueCell(mCurrentAddress, aValue, true);
+}
+
+// DataCellIterator
+
+DataCellIterator::DataCellIterator(const ScRange& aInputRange, bool aByColumn)
+ : mInputRange(aInputRange)
+ , mByColumn(aByColumn)
+ , mCol(0)
+ , mRow(0)
+{
+ if(aByColumn)
+ mCol = aInputRange.aStart.Col();
+ else
+ mRow = aInputRange.aStart.Row();
+}
+
+bool DataCellIterator::hasNext() const
+{
+ if(mByColumn)
+ return mCol <= mInputRange.aEnd.Col();
+ else
+ return mRow <= mInputRange.aEnd.Row();
+}
+
+void DataCellIterator::next()
+{
+ if(mByColumn)
+ mCol++;
+ else
+ mRow++;
+}
+
+ScAddress DataCellIterator::get()
+{
+ return getRelative(0);
+}
+
+ScAddress DataCellIterator::getRelative(int aDelta)
+{
+ if(mByColumn)
+ {
+ SCCOL aNewColumn = mCol + aDelta;
+ if(aNewColumn < mInputRange.aStart.Col() || aNewColumn > mInputRange.aEnd.Col())
+ {
+ ScAddress aResult;
+ aResult.SetInvalid();
+ return aResult;
+ }
+ return ScAddress(aNewColumn, mInputRange.aStart.Row(), mInputRange.aStart.Tab());
+ }
+ else
+ {
+ SCROW aNewRow = mRow + aDelta;
+ if(aNewRow < mInputRange.aStart.Row() || aNewRow > mInputRange.aEnd.Row())
+ {
+ ScAddress aResult;
+ aResult.SetInvalid();
+ return aResult;
+ }
+ return ScAddress(mInputRange.aStart.Col(), aNewRow, mInputRange.aStart.Tab());
+ }
+}
+
+// DataRangeIterator
+
+DataRangeIterator::DataRangeIterator(const ScRange& aInputRange) :
+ mInputRange(aInputRange),
+ mIndex(0)
+{}
+
+DataRangeIterator::~DataRangeIterator()
+{}
+
+sal_Int32 DataRangeIterator::index()
+{
+ return mIndex;
+}
+
+// DataRangeByColumnIterator
+
+DataRangeByColumnIterator::DataRangeByColumnIterator(const ScRange& aInputRange)
+ : DataRangeIterator(aInputRange)
+ , mCol(aInputRange.aStart.Col())
+{}
+
+bool DataRangeByColumnIterator::hasNext()
+{
+ return mCol <= mInputRange.aEnd.Col();
+}
+
+void DataRangeByColumnIterator::next()
+{
+ mCol++;
+ mIndex++;
+}
+
+ScRange DataRangeByColumnIterator::get()
+{
+ return ScRange(
+ ScAddress(mCol, mInputRange.aStart.Row(), mInputRange.aStart.Tab()),
+ ScAddress(mCol, mInputRange.aEnd.Row(), mInputRange.aEnd.Tab())
+ );
+}
+
+size_t DataRangeByColumnIterator::size()
+{
+ return mInputRange.aEnd.Row() - mInputRange.aStart.Row() + 1;
+}
+
+void DataRangeByColumnIterator::reset()
+{
+ mCol = mInputRange.aStart.Col();
+}
+
+DataCellIterator DataRangeByColumnIterator::iterateCells()
+{
+ return DataCellIterator(get(), false);
+}
+
+// DataRangeByRowIterator
+
+DataRangeByRowIterator::DataRangeByRowIterator(const ScRange& aInputRange)
+ : DataRangeIterator(aInputRange)
+ , mRow(aInputRange.aStart.Row())
+{}
+
+bool DataRangeByRowIterator::hasNext()
+{
+ return mRow <= mInputRange.aEnd.Row();
+}
+
+void DataRangeByRowIterator::next()
+{
+ mRow++;
+ mIndex++;
+}
+
+ScRange DataRangeByRowIterator::get()
+{
+ return ScRange(
+ ScAddress(mInputRange.aStart.Col(), mRow, mInputRange.aStart.Tab()),
+ ScAddress(mInputRange.aEnd.Col(), mRow, mInputRange.aEnd.Tab())
+ );
+}
+
+size_t DataRangeByRowIterator::size()
+{
+ return mInputRange.aEnd.Col() - mInputRange.aStart.Col() + 1;
+}
+
+void DataRangeByRowIterator::reset()
+{
+ mRow = mInputRange.aStart.Row();
+}
+
+DataCellIterator DataRangeByRowIterator::iterateCells()
+{
+ return DataCellIterator(get(), true);
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */