1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
13 #include <editeng/editobj.hxx>
14 #include <editeng/wghtitem.hxx>
15 #include <editeng/eeitem.hxx>
17 #include <editutil.hxx>
19 #include <TableFillingAndNavigationTools.hxx>
20 #include <formulacell.hxx>
21 #include <docfunc.hxx>
24 FormulaTemplate::FormulaTemplate(ScDocument
* pDoc
)
29 void FormulaTemplate::setTemplate(const OUString
& aTemplate
)
31 mTemplate
= aTemplate
;
34 void FormulaTemplate::setTemplate(const char* aTemplate
)
36 mTemplate
= OUString::createFromAscii(aTemplate
);
39 const OUString
& FormulaTemplate::getTemplate()
41 for (const auto& [rVariable
, rRange
] : mRangeReplacementMap
)
43 applyRange(rVariable
, rRange
, mbUse3D
);
45 for (const auto& [rVariable
, rAddress
] : mAddressReplacementMap
)
47 applyAddress(rVariable
, rAddress
, mbUse3D
);
52 void FormulaTemplate::autoReplaceRange(const OUString
& aVariable
, const ScRange
& rRange
)
54 mRangeReplacementMap
[aVariable
] = rRange
;
57 void FormulaTemplate::autoReplaceAddress(const OUString
& aVariable
, ScAddress
const & aAddress
)
60 mAddressReplacementMap
[aVariable
] = aAddress
;
63 void FormulaTemplate::applyRange(std::u16string_view aVariable
, const ScRange
& aRange
, bool b3D
)
65 ScRefFlags nFlag
= b3D
? ScRefFlags::RANGE_ABS_3D
: ScRefFlags::RANGE_ABS
;
66 OUString aString
= aRange
.Format(*mpDoc
, nFlag
, mpDoc
->GetAddressConvention());
67 mTemplate
= mTemplate
.replaceAll(aVariable
, aString
);
70 void FormulaTemplate::applyRangeList(std::u16string_view aVariable
, const ScRangeList
& aRangeList
, sal_Unicode cDelimiter
)
73 aRangeList
.Format(aString
, ScRefFlags::RANGE_ABS_3D
, *mpDoc
, mpDoc
->GetAddressConvention(), cDelimiter
);
74 mTemplate
= mTemplate
.replaceAll(aVariable
, aString
);
77 void FormulaTemplate::applyAddress(std::u16string_view aVariable
, const ScAddress
& aAddress
, bool b3D
)
79 ScRefFlags nFlag
= b3D
? ScRefFlags::ADDR_ABS_3D
: ScRefFlags::ADDR_ABS
;
80 OUString aString
= aAddress
.Format(nFlag
, mpDoc
, mpDoc
->GetAddressConvention());
81 mTemplate
= mTemplate
.replaceAll(aVariable
, aString
);
84 void FormulaTemplate::applyString(std::u16string_view aVariable
, std::u16string_view aValue
)
86 mTemplate
= mTemplate
.replaceAll(aVariable
, aValue
);
89 void FormulaTemplate::applyNumber(std::u16string_view aVariable
, sal_Int32 aValue
)
91 mTemplate
= mTemplate
.replaceAll(aVariable
, OUString::number(aValue
));
94 AddressWalker::AddressWalker(const ScAddress
& aInitialAddress
) :
95 mCurrentAddress(aInitialAddress
),
96 mMinimumAddress(aInitialAddress
),
97 mMaximumAddress(aInitialAddress
)
99 mAddressStack
.push_back(mCurrentAddress
);
102 void AddressWalker::resetColumn()
104 mCurrentAddress
.SetCol(mAddressStack
.back().Col());
107 void AddressWalker::resetRow()
109 mCurrentAddress
.SetRow(mAddressStack
.back().Row());
112 void AddressWalker::reset()
114 mCurrentAddress
= mAddressStack
.back();
117 void AddressWalker::newLine()
123 ScAddress
AddressWalker::current(SCCOL aRelCol
, SCROW aRelRow
, SCTAB aRelTab
)
126 mCurrentAddress
.Col() + aRelCol
,
127 mCurrentAddress
.Row() + aRelRow
,
128 mCurrentAddress
.Tab() + aRelTab
);
131 void AddressWalker::nextColumn()
133 mCurrentAddress
.IncCol();
135 if(mMaximumAddress
.Col() < mCurrentAddress
.Col())
136 mMaximumAddress
.SetCol(mCurrentAddress
.Col());
139 void AddressWalker::nextRow()
141 mCurrentAddress
.IncRow();
142 if(mMaximumAddress
.Row() < mCurrentAddress
.Row())
143 mMaximumAddress
.SetRow(mCurrentAddress
.Row());
146 void AddressWalker::push(SCCOL aRelativeCol
, SCROW aRelativeRow
, SCTAB aRelativeTab
)
148 mCurrentAddress
= current(aRelativeCol
, aRelativeRow
, aRelativeTab
);
149 mAddressStack
.push_back(mCurrentAddress
);
152 AddressWalkerWriter::AddressWalkerWriter(const ScAddress
& aInitialAddress
, ScDocShell
* pDocShell
, ScDocument
& rDocument
,
153 formula::FormulaGrammar::Grammar eGrammar
) :
154 AddressWalker(aInitialAddress
),
155 mpDocShell(pDocShell
),
156 mrDocument(rDocument
),
160 void AddressWalkerWriter::writeFormula(const OUString
& aFormula
)
162 mpDocShell
->GetDocFunc().SetFormulaCell(mCurrentAddress
,
163 new ScFormulaCell(mrDocument
, mCurrentAddress
, aFormula
, meGrammar
), true);
166 void AddressWalkerWriter::writeFormulas(const std::vector
<OUString
>& rFormulas
)
168 size_t nLength
= rFormulas
.size();
172 const size_t nMaxLen
= mpDocShell
->GetDocument().MaxRow() - mCurrentAddress
.Row() + 1;
173 // If not done already, trim the length to fit.
174 if (nLength
> nMaxLen
)
177 std::vector
<ScFormulaCell
*> aFormulaCells(nLength
);
178 ScAddress
aAddr(mCurrentAddress
);
179 for (size_t nIdx
= 0; nIdx
< nLength
; ++nIdx
)
181 aFormulaCells
[nIdx
] = new ScFormulaCell(mrDocument
, aAddr
, rFormulas
[nIdx
], meGrammar
);
185 mpDocShell
->GetDocFunc().SetFormulaCells(mCurrentAddress
, aFormulaCells
, true);
188 void AddressWalkerWriter::writeMatrixFormula(const OUString
& aFormula
, SCCOL nCols
, SCROW nRows
)
191 aRange
.aStart
= mCurrentAddress
;
192 aRange
.aEnd
= mCurrentAddress
;
194 aRange
.aEnd
.IncCol(nCols
- 1);
196 aRange
.aEnd
.IncRow(nRows
- 1);
197 mpDocShell
->GetDocFunc().EnterMatrix(aRange
, nullptr, nullptr, aFormula
, false, false, OUString(), meGrammar
);
200 void AddressWalkerWriter::writeString(const OUString
& aString
)
202 mpDocShell
->GetDocFunc().SetStringCell(mCurrentAddress
, aString
, true);
205 void AddressWalkerWriter::writeString(const char* aCharArray
)
207 writeString(OUString::createFromAscii(aCharArray
));
210 void AddressWalkerWriter::writeBoldString(const OUString
& aString
)
212 ScFieldEditEngine
& rEngine
= mrDocument
.GetEditEngine();
213 rEngine
.SetTextCurrentDefaults(aString
);
214 SfxItemSet aItemSet
= rEngine
.GetEmptyItemSet();
215 SvxWeightItem
aWeight(WEIGHT_BOLD
, EE_CHAR_WEIGHT
);
216 aItemSet
.Put(aWeight
);
217 rEngine
.QuickSetAttribs(aItemSet
, ESelection(0, 0, 0, aString
.getLength()) );
218 std::unique_ptr
<EditTextObject
> pEditText(rEngine
.CreateTextObject());
219 mpDocShell
->GetDocFunc().SetEditCell(mCurrentAddress
, *pEditText
, true);
222 void AddressWalkerWriter::writeValue(double aValue
)
224 mpDocShell
->GetDocFunc().SetValueCell(mCurrentAddress
, aValue
, true);
229 DataCellIterator::DataCellIterator(const ScRange
& aInputRange
, bool aByColumn
)
230 : mInputRange(aInputRange
)
231 , mByColumn(aByColumn
)
236 mCol
= aInputRange
.aStart
.Col();
238 mRow
= aInputRange
.aStart
.Row();
241 bool DataCellIterator::hasNext() const
244 return mCol
<= mInputRange
.aEnd
.Col();
246 return mRow
<= mInputRange
.aEnd
.Row();
249 void DataCellIterator::next()
257 ScAddress
DataCellIterator::get()
259 return getRelative(0);
262 ScAddress
DataCellIterator::getRelative(int aDelta
)
266 SCCOL aNewColumn
= mCol
+ aDelta
;
267 if(aNewColumn
< mInputRange
.aStart
.Col() || aNewColumn
> mInputRange
.aEnd
.Col())
270 aResult
.SetInvalid();
273 return ScAddress(aNewColumn
, mInputRange
.aStart
.Row(), mInputRange
.aStart
.Tab());
277 SCROW aNewRow
= mRow
+ aDelta
;
278 if(aNewRow
< mInputRange
.aStart
.Row() || aNewRow
> mInputRange
.aEnd
.Row())
281 aResult
.SetInvalid();
284 return ScAddress(mInputRange
.aStart
.Col(), aNewRow
, mInputRange
.aStart
.Tab());
290 DataRangeIterator::DataRangeIterator(const ScRange
& aInputRange
) :
291 mInputRange(aInputRange
),
295 DataRangeIterator::~DataRangeIterator()
298 sal_Int32
DataRangeIterator::index()
303 // DataRangeByColumnIterator
305 DataRangeByColumnIterator::DataRangeByColumnIterator(const ScRange
& aInputRange
)
306 : DataRangeIterator(aInputRange
)
307 , mCol(aInputRange
.aStart
.Col())
310 bool DataRangeByColumnIterator::hasNext()
312 return mCol
<= mInputRange
.aEnd
.Col();
315 void DataRangeByColumnIterator::next()
321 ScRange
DataRangeByColumnIterator::get()
324 ScAddress(mCol
, mInputRange
.aStart
.Row(), mInputRange
.aStart
.Tab()),
325 ScAddress(mCol
, mInputRange
.aEnd
.Row(), mInputRange
.aEnd
.Tab())
329 size_t DataRangeByColumnIterator::size()
331 return mInputRange
.aEnd
.Row() - mInputRange
.aStart
.Row() + 1;
334 void DataRangeByColumnIterator::reset()
336 mCol
= mInputRange
.aStart
.Col();
339 DataCellIterator
DataRangeByColumnIterator::iterateCells()
341 return DataCellIterator(get(), false);
344 // DataRangeByRowIterator
346 DataRangeByRowIterator::DataRangeByRowIterator(const ScRange
& aInputRange
)
347 : DataRangeIterator(aInputRange
)
348 , mRow(aInputRange
.aStart
.Row())
351 bool DataRangeByRowIterator::hasNext()
353 return mRow
<= mInputRange
.aEnd
.Row();
356 void DataRangeByRowIterator::next()
362 ScRange
DataRangeByRowIterator::get()
365 ScAddress(mInputRange
.aStart
.Col(), mRow
, mInputRange
.aStart
.Tab()),
366 ScAddress(mInputRange
.aEnd
.Col(), mRow
, mInputRange
.aEnd
.Tab())
370 size_t DataRangeByRowIterator::size()
372 return mInputRange
.aEnd
.Col() - mInputRange
.aStart
.Col() + 1;
375 void DataRangeByRowIterator::reset()
377 mRow
= mInputRange
.aStart
.Row();
380 DataCellIterator
DataRangeByRowIterator::iterateCells()
382 return DataCellIterator(get(), true);
386 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */