LibreOffice Module sc (master) 1
documentimport.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 */
9
10#include <documentimport.hxx>
11#include <document.hxx>
12#include <table.hxx>
13#include <column.hxx>
14#include <formulacell.hxx>
15#include <docoptio.hxx>
16#include <mtvelements.hxx>
17#include <tokenarray.hxx>
18#include <stringutil.hxx>
19#include <compiler.hxx>
20#include <paramisc.hxx>
21#include <listenercontext.hxx>
22#include <attarray.hxx>
23#include <sharedformula.hxx>
24#include <bcaslot.hxx>
25#include <scopetools.hxx>
26#include <numformat.hxx>
27
28#include <o3tl/safeint.hxx>
32#include <unordered_map>
33
34namespace {
35
36struct ColAttr
37{
38 bool mbLatinNumFmtOnly;
39
40 ColAttr() : mbLatinNumFmtOnly(false) {}
41};
42
43struct TabAttr
44{
45 std::vector<ColAttr> maCols;
46};
47
48}
49
51{
54 std::vector<sc::TableColumnBlockPositionSet> maBlockPosSet;
57 std::vector<TabAttr> maTabAttrs;
58 std::unordered_map<sal_uInt32, bool> maIsLatinScriptMap;
59
61 mrDoc(rDoc),
62 maListenCxt(rDoc),
64 mbFuzzing(utl::ConfigManager::IsFuzzing())
65 {}
66
67 bool isValid( size_t nTab, size_t nCol )
68 {
69 return (nTab <= o3tl::make_unsigned(MAXTAB) && nCol <= o3tl::make_unsigned(mrDoc.MaxCol()));
70 }
71
72 ColAttr* getColAttr( size_t nTab, size_t nCol )
73 {
74 if (!isValid(nTab, nCol))
75 return nullptr;
76
77 if (nTab >= maTabAttrs.size())
78 maTabAttrs.resize(nTab+1);
79
80 TabAttr& rTab = maTabAttrs[nTab];
81 if (nCol >= rTab.maCols.size())
82 rTab.maCols.resize(nCol+1);
83
84 return &rTab.maCols[nCol];
85 }
86
88 {
89 if (!isValid(nTab, nCol))
90 return nullptr;
91
92 if (o3tl::make_unsigned(nTab) >= maBlockPosSet.size())
93 {
94 for (SCTAB i = maBlockPosSet.size(); i <= nTab; ++i)
95 maBlockPosSet.emplace_back(mrDoc, i);
96 }
97
99 return rTab.getBlockPosition(nCol);
100 }
101
103 {
104 if (o3tl::make_unsigned(nTab) >= maBlockPosSet.size())
105 return;
106
108 rTab.invalidate();
109 }
110
112 {
113 size_t n = mrDoc.GetTableCount();
114 for (size_t i = maBlockPosSet.size(); i < n; ++i)
115 maBlockPosSet.emplace_back(mrDoc, i);
116
117 if (maTabAttrs.size() < n)
118 maTabAttrs.resize(n);
119 }
120};
121
122ScDocumentImport::Attrs::Attrs() : mbLatinNumFmtOnly(false) {}
123
125
127
129{
130}
131
133{
134 return mpImpl->mrDoc;
135}
136
138{
139 return mpImpl->mrDoc;
140}
141
143{
144 mpImpl->initForSheets();
145}
146
148{
149 mpImpl->mnDefaultScriptNumeric = nScript;
150}
151
153{
154 ScTable* pTab = mpImpl->mrDoc.FetchTable(nTab);
155 if (!pTab)
156 return;
157
158 pTab->ApplyStyleArea(0, 0, getDoc().MaxCol(), getDoc().MaxRow(), rStyle);
159}
160
161SCTAB ScDocumentImport::getSheetIndex(const OUString& rName) const
162{
163 SCTAB nTab = -1;
164 if (!mpImpl->mrDoc.GetTable(rName, nTab))
165 return -1;
166
167 return nTab;
168}
169
171{
172 return mpImpl->mrDoc.maTabs.size();
173}
174
175bool ScDocumentImport::appendSheet(const OUString& rName)
176{
177 SCTAB nTabCount = mpImpl->mrDoc.maTabs.size();
178 if (!ValidTab(nTabCount))
179 return false;
180
181 mpImpl->mrDoc.maTabs.emplace_back(new ScTable(mpImpl->mrDoc, nTabCount, rName));
182 return true;
183}
184
185void ScDocumentImport::setSheetName(SCTAB nTab, const OUString& rName)
186{
187 mpImpl->mrDoc.SetTabNameOnLoad(nTab, rName);
188}
189
190void ScDocumentImport::setOriginDate(sal_uInt16 nYear, sal_uInt16 nMonth, sal_uInt16 nDay)
191{
192 if (!mpImpl->mrDoc.pDocOptions)
193 mpImpl->mrDoc.pDocOptions.reset( new ScDocOptions );
194
195 mpImpl->mrDoc.pDocOptions->SetDate(nDay, nMonth, nYear);
196}
197
199{
200 mpImpl->invalidateBlockPositionSet(nTab);
201}
202
203void ScDocumentImport::setAutoInput(const ScAddress& rPos, const OUString& rStr, const ScSetStringParam* pStringParam)
204{
205 ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
206 if (!pTab)
207 return;
208
209 sc::ColumnBlockPosition* pBlockPos = mpImpl->getBlockPosition(rPos.Tab(), rPos.Col());
210
211 if (!pBlockPos)
212 return;
213
214 // If ScSetStringParam was given, ScColumn::ParseString() shall take care
215 // of checking. Ensure caller said so.
216 assert(!pStringParam || pStringParam->mbCheckLinkFormula);
217
218 ScCellValue aCell;
219 pTab->aCol[rPos.Col()].ParseString(
220 aCell, rPos.Row(), rPos.Tab(), rStr, mpImpl->mrDoc.GetAddressConvention(), pStringParam);
221
222 sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
223 switch (aCell.getType())
224 {
225 case CELLTYPE_STRING:
226 // string is copied.
227 pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), *aCell.getSharedString());
228 break;
229 case CELLTYPE_EDIT:
230 // Cell takes the ownership of the text object.
231 pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), aCell.releaseEditText());
232 break;
233 case CELLTYPE_VALUE:
234 pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), aCell.getDouble());
235 break;
236 case CELLTYPE_FORMULA:
237 if (!pStringParam)
238 mpImpl->mrDoc.CheckLinkFormulaNeedingCheck( *aCell.getFormula()->GetCode());
239 // This formula cell instance is directly placed in the document without copying.
240 pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), aCell.releaseFormula());
241 break;
242 default:
243 pBlockPos->miCellPos = rCells.set_empty(pBlockPos->miCellPos, rPos.Row(), rPos.Row());
244 }
245}
246
247void ScDocumentImport::setNumericCell(const ScAddress& rPos, double fVal)
248{
249 ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
250 if (!pTab)
251 return;
252
253 sc::ColumnBlockPosition* pBlockPos = mpImpl->getBlockPosition(rPos.Tab(), rPos.Col());
254
255 if (!pBlockPos)
256 return;
257
258 sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
259 pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), fVal);
260}
261
262void ScDocumentImport::setStringCell(const ScAddress& rPos, const OUString& rStr)
263{
264 ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
265 if (!pTab)
266 return;
267
268 sc::ColumnBlockPosition* pBlockPos = mpImpl->getBlockPosition(rPos.Tab(), rPos.Col());
269
270 if (!pBlockPos)
271 return;
272
273 svl::SharedString aSS = mpImpl->mrDoc.GetSharedStringPool().intern(rStr);
274 if (!aSS.getData())
275 return;
276
277 sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
278 pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), aSS);
279}
280
281void ScDocumentImport::setEditCell(const ScAddress& rPos, std::unique_ptr<EditTextObject> pEditText)
282{
283 ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
284 if (!pTab)
285 return;
286
287 sc::ColumnBlockPosition* pBlockPos = mpImpl->getBlockPosition(rPos.Tab(), rPos.Col());
288
289 if (!pBlockPos)
290 return;
291
292 pEditText->NormalizeString(mpImpl->mrDoc.GetSharedStringPool());
293 sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
294 pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), pEditText.release());
295}
296
298 const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar,
299 const double* pResult )
300{
301 ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
302 if (!pTab)
303 return;
304
305 sc::ColumnBlockPosition* pBlockPos = mpImpl->getBlockPosition(rPos.Tab(), rPos.Col());
306
307 if (!pBlockPos)
308 return;
309
310 std::unique_ptr<ScFormulaCell> pFC =
311 std::make_unique<ScFormulaCell>(mpImpl->mrDoc, rPos, rFormula, eGrammar);
312
313 mpImpl->mrDoc.CheckLinkFormulaNeedingCheck( *pFC->GetCode());
314
315 if (pResult)
316 {
317 // Set cached result to this formula cell.
318 pFC->SetResultDouble(*pResult);
319 }
320
321 sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
322 pBlockPos->miCellPos =
323 rCells.set(pBlockPos->miCellPos, rPos.Row(), pFC.release());
324}
325
327 const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar,
328 const OUString& rResult )
329{
330 ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
331 if (!pTab)
332 return;
333
334 sc::ColumnBlockPosition* pBlockPos = mpImpl->getBlockPosition(rPos.Tab(), rPos.Col());
335
336 if (!pBlockPos)
337 return;
338
339 std::unique_ptr<ScFormulaCell> pFC =
340 std::make_unique<ScFormulaCell>(mpImpl->mrDoc, rPos, rFormula, eGrammar);
341
342 mpImpl->mrDoc.CheckLinkFormulaNeedingCheck( *pFC->GetCode());
343
344 // Set cached result to this formula cell.
345 pFC->SetHybridString(mpImpl->mrDoc.GetSharedStringPool().intern(rResult));
346
347 sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
348 pBlockPos->miCellPos =
349 rCells.set(pBlockPos->miCellPos, rPos.Row(), pFC.release());
350}
351
352void ScDocumentImport::setFormulaCell(const ScAddress& rPos, std::unique_ptr<ScTokenArray> pArray)
353{
354 ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
355 if (!pTab)
356 return;
357
358 sc::ColumnBlockPosition* pBlockPos = mpImpl->getBlockPosition(rPos.Tab(), rPos.Col());
359
360 if (!pBlockPos)
361 return;
362
363 std::unique_ptr<ScFormulaCell> pFC =
364 std::make_unique<ScFormulaCell>(mpImpl->mrDoc, rPos, std::move(pArray));
365
366 mpImpl->mrDoc.CheckLinkFormulaNeedingCheck( *pFC->GetCode());
367
368 sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
369 pBlockPos->miCellPos =
370 rCells.set(pBlockPos->miCellPos, rPos.Row(), pFC.release());
371}
372
374{
375 ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
376 if (!pTab)
377 return;
378
379 sc::ColumnBlockPosition* pBlockPos = mpImpl->getBlockPosition(rPos.Tab(), rPos.Col());
380
381 if (!pBlockPos)
382 return;
383
384 if (pCell)
385 mpImpl->mrDoc.CheckLinkFormulaNeedingCheck( *pCell->GetCode());
386
387 sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
388
389 sc::CellStoreType::position_type aPos = rCells.position(rPos.Row());
390 if (aPos.first != rCells.end() && aPos.first->type == sc::element_type_formula)
391 {
392 ScFormulaCell* p = sc::formula_block::at(*aPos.first->data, aPos.second);
394 }
395
396 pBlockPos->miCellPos =
397 rCells.set(pBlockPos->miCellPos, rPos.Row(), pCell);
398}
399
401 const ScRange& rRange, const ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGram)
402{
403 const ScAddress& rBasePos = rRange.aStart;
404
405 ScTable* pTab = mpImpl->mrDoc.FetchTable(rBasePos.Tab());
406 if (!pTab)
407 return;
408
409 sc::ColumnBlockPosition* pBlockPos = mpImpl->getBlockPosition(rBasePos.Tab(), rBasePos.Col());
410
411 if (!pBlockPos)
412 return;
413
414 if (utl::ConfigManager::IsFuzzing()) //just too slow
415 return;
416
417 sc::CellStoreType& rCells = pTab->aCol[rBasePos.Col()].maCells;
418
419 // Set the master cell.
420 ScFormulaCell* pCell = new ScFormulaCell(mpImpl->mrDoc, rBasePos, rArray, eGram, ScMatrixMode::Formula);
421
422 mpImpl->mrDoc.CheckLinkFormulaNeedingCheck( *pCell->GetCode());
423
424 pBlockPos->miCellPos =
425 rCells.set(pBlockPos->miCellPos, rBasePos.Row(), pCell);
426
427 // Matrix formulas currently need re-calculation on import.
428 pCell->SetMatColsRows(
429 rRange.aEnd.Col()-rRange.aStart.Col()+1, rRange.aEnd.Row()-rRange.aStart.Row()+1);
430
431 // Set the reference cells.
432 ScSingleRefData aRefData;
433 aRefData.InitFlags();
434 aRefData.SetColRel(true);
435 aRefData.SetRowRel(true);
436 aRefData.SetTabRel(true);
437 aRefData.SetAddress(mpImpl->mrDoc.GetSheetLimits(), rBasePos, rBasePos);
438
439 ScTokenArray aArr(mpImpl->mrDoc); // consists only of one single reference token.
440 formula::FormulaToken* t = aArr.AddMatrixSingleReference(aRefData);
441
442 ScAddress aPos = rBasePos;
443 for (SCROW nRow = rRange.aStart.Row()+1; nRow <= rRange.aEnd.Row(); ++nRow)
444 {
445 // Token array must be cloned so that each formula cell receives its own copy.
446 aPos.SetRow(nRow);
447 // Reference in each cell must point to the origin cell relative to the current cell.
448 aRefData.SetAddress(mpImpl->mrDoc.GetSheetLimits(), rBasePos, aPos);
449 *t->GetSingleRef() = aRefData;
450 ScTokenArray aTokArr(aArr.CloneValue());
451 pCell = new ScFormulaCell(mpImpl->mrDoc, aPos, aTokArr, eGram, ScMatrixMode::Reference);
452 pBlockPos->miCellPos =
453 rCells.set(pBlockPos->miCellPos, aPos.Row(), pCell);
454 }
455
456 for (SCCOL nCol = rRange.aStart.Col()+1; nCol <= rRange.aEnd.Col(); ++nCol)
457 {
458 pBlockPos = mpImpl->getBlockPosition(rBasePos.Tab(), nCol);
459 if (!pBlockPos)
460 return;
461
462 sc::CellStoreType& rColCells = pTab->aCol[nCol].maCells;
463
464 aPos.SetCol(nCol);
465 for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
466 {
467 aPos.SetRow(nRow);
468 aRefData.SetAddress(mpImpl->mrDoc.GetSheetLimits(), rBasePos, aPos);
469 *t->GetSingleRef() = aRefData;
470 ScTokenArray aTokArr(aArr.CloneValue());
471 pCell = new ScFormulaCell(mpImpl->mrDoc, aPos, aTokArr, eGram, ScMatrixMode::Reference);
472 pBlockPos->miCellPos =
473 rColCells.set(pBlockPos->miCellPos, aPos.Row(), pCell);
474 }
475 }
476}
477
479{
480 SCTAB nTab = rRange.aStart.Tab();
481 SCCOL nCol1 = rRange.aStart.Col();
482 SCROW nRow1 = rRange.aStart.Row();
483 SCCOL nCol2 = rRange.aEnd.Col();
484 SCROW nRow2 = rRange.aEnd.Row();
485
486 ScTable* pTab = mpImpl->mrDoc.FetchTable(nTab);
487 if (!pTab)
488 return;
489
490 ScDocument& rDoc = mpImpl->mrDoc;
491 ScRefAddress aRef;
492 OUStringBuffer aFormulaBuf("="
495
496 OUString aSep = ScCompiler::GetNativeSymbol(ocSep);
497 if (rParam.meMode == ScTabOpParam::Column) // column only
498 {
499 aRef.Set(rParam.aRefFormulaCell.GetAddress(), true, false, false);
500 aFormulaBuf.append(aRef.GetRefString(rDoc, nTab)
501 + aSep
502 + rParam.aRefColCell.GetRefString(rDoc, nTab)
503 + aSep);
504 aRef.Set(nCol1, nRow1, nTab, false, true, true);
505 aFormulaBuf.append(aRef.GetRefString(rDoc, nTab));
506 nCol1++;
507 nCol2 = std::min( nCol2, static_cast<SCCOL>(rParam.aRefFormulaEnd.Col() -
508 rParam.aRefFormulaCell.Col() + nCol1 + 1));
509 }
510 else if (rParam.meMode == ScTabOpParam::Row) // row only
511 {
512 aRef.Set(rParam.aRefFormulaCell.GetAddress(), false, true, false);
513 aFormulaBuf.append(aRef.GetRefString(rDoc, nTab)
514 + aSep
515 + rParam.aRefRowCell.GetRefString(rDoc, nTab)
516 + aSep);
517 aRef.Set(nCol1, nRow1, nTab, true, false, true);
518 aFormulaBuf.append(aRef.GetRefString(rDoc, nTab));
519 ++nRow1;
520 nRow2 = std::min(
521 nRow2, rParam.aRefFormulaEnd.Row() - rParam.aRefFormulaCell.Row() + nRow1 + 1);
522 }
523 else // both
524 {
525 aFormulaBuf.append(rParam.aRefFormulaCell.GetRefString(rDoc, nTab)
526 + aSep
527 + rParam.aRefColCell.GetRefString(rDoc, nTab)
528 + aSep);
529 aRef.Set(nCol1, nRow1 + 1, nTab, false, true, true);
530 aFormulaBuf.append(aRef.GetRefString(rDoc, nTab)
531 + aSep
532 + rParam.aRefRowCell.GetRefString(rDoc, nTab)
533 + aSep);
534 aRef.Set(nCol1 + 1, nRow1, nTab, true, false, true);
535 aFormulaBuf.append(aRef.GetRefString(rDoc, nTab));
536 ++nCol1;
537 ++nRow1;
538 }
539
540 aFormulaBuf.append(ScCompiler::GetNativeSymbol(ocClose));
541
542 ScFormulaCell aRefCell(
543 rDoc, ScAddress(nCol1, nRow1, nTab), aFormulaBuf.makeStringAndClear(),
545
546 for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
547 {
548 sc::ColumnBlockPosition* pBlockPos = mpImpl->getBlockPosition(nTab, nCol);
549
550 if (!pBlockPos)
551 // Something went horribly wrong.
552 return;
553
554 sc::CellStoreType& rColCells = pTab->aCol[nCol].maCells;
555
556 for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
557 {
558 ScAddress aPos(nCol, nRow, nTab);
559 ScFormulaCell* pCell = new ScFormulaCell(aRefCell, rDoc, aPos);
560 pBlockPos->miCellPos =
561 rColCells.set(pBlockPos->miCellPos, nRow, pCell);
562 }
563 }
564}
565
567{
568 ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
569 if (!pTab)
570 return;
571
572 sc::ColumnBlockPosition* pBlockPos = mpImpl->getBlockPosition(rPos.Tab(), rPos.Col());
573
574 if (!pBlockPos)
575 return;
576
577 sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
578 ScRefCellValue aRefCell = pTab->aCol[rPos.Col()].GetCellValue(*pBlockPos, rPos.Row());
579
580 switch (aRefCell.getType())
581 {
582 case CELLTYPE_VALUE:
583 {
584 std::vector<double> aCopied(nFillSize, aRefCell.getDouble());
585 pBlockPos->miCellPos = rCells.set(
586 pBlockPos->miCellPos, rPos.Row()+1, aCopied.begin(), aCopied.end());
587 break;
588 }
589 case CELLTYPE_STRING:
590 {
591 std::vector<svl::SharedString> aCopied(nFillSize, *aRefCell.getSharedString());
592 pBlockPos->miCellPos = rCells.set(
593 pBlockPos->miCellPos, rPos.Row()+1, aCopied.begin(), aCopied.end());
594 break;
595 }
596 default:
597 break;
598 }
599}
600
601void ScDocumentImport::setAttrEntries( SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, Attrs&& rAttrs )
602{
603 ScTable* pTab = mpImpl->mrDoc.FetchTable(nTab);
604 if (!pTab)
605 return;
606
607 for(SCCOL nCol = nColStart; nCol <= nColEnd; ++nCol )
608 {
609 ColAttr* pColAttr = mpImpl->getColAttr(nTab, nCol);
610 if (pColAttr)
611 pColAttr->mbLatinNumFmtOnly = rAttrs.mbLatinNumFmtOnly;
612 }
613
614 pTab->SetAttrEntries( nColStart, nColEnd, std::move( rAttrs.mvData ));
615}
616
617void ScDocumentImport::setRowsVisible(SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, bool bVisible)
618{
619 if (!bVisible)
620 {
621 getDoc().ShowRows(nRowStart, nRowEnd, nTab, false);
622 getDoc().SetDrawPageSize(nTab);
623 getDoc().UpdatePageBreaks( nTab );
624 }
625 else
626 {
627 assert(false);
628 }
629}
630
631void ScDocumentImport::setMergedCells(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
632{
633 ScTable* pTab = mpImpl->mrDoc.FetchTable(nTab);
634 if (!pTab)
635 return;
636
637 pTab->SetMergedCells(nCol1, nRow1, nCol2, nRow2);
638}
639
640namespace {
641
642class CellStoreInitializer
643{
644 // The pimpl pattern here is intentional.
645 //
646 // The problem with having the attributes in CellStoreInitializer
647 // directly is that, as a functor, it might be copied around. In
648 // that case miPos in _copied_ object points to maAttrs in the
649 // original object, not in the copy. So later, deep in mdds, we end
650 // up comparing iterators from different sequences.
651 //
652 // This could be solved by defining copy constructor and operator=,
653 // but given the limited usage of the class, I think it is simpler
654 // to let copies share the state.
655 struct Impl
656 {
658 sc::CellTextAttrStoreType::iterator miPos;
659 SvtScriptType mnScriptNumeric;
660
661 explicit Impl(const ScSheetLimits& rSheetLimits, const SvtScriptType nScriptNumeric)
662 : maAttrs(rSheetLimits.GetMaxRowCount()), miPos(maAttrs.begin()), mnScriptNumeric(nScriptNumeric)
663 {}
664 };
665
666 ScDocumentImportImpl& mrDocImpl;
667 SCTAB mnTab;
668 SCCOL mnCol;
669
670public:
671 CellStoreInitializer( ScDocumentImportImpl& rDocImpl, SCTAB nTab, SCCOL nCol ) :
672 mrDocImpl(rDocImpl),
673 mnTab(nTab),
674 mnCol(nCol),
675 mpImpl(std::make_shared<Impl>(rDocImpl.mrDoc.GetSheetLimits(), mrDocImpl.mnDefaultScriptNumeric))
676 {}
677
678 std::shared_ptr<Impl> mpImpl;
679
680 void operator() (const sc::CellStoreType::value_type& node)
681 {
682 if (node.type == sc::element_type_empty)
683 return;
684
685 // Fill with default values for non-empty cell segments.
686 sc::CellTextAttr aDefault;
687 switch (node.type)
688 {
690 {
691 aDefault.mnScriptType = mpImpl->mnScriptNumeric;
692 const ColAttr* p = mrDocImpl.getColAttr(mnTab, mnCol);
693 if (p && p->mbLatinNumFmtOnly)
694 aDefault.mnScriptType = SvtScriptType::LATIN;
695 }
696 break;
698 {
699 const ColAttr* p = mrDocImpl.getColAttr(mnTab, mnCol);
700 if (p && p->mbLatinNumFmtOnly)
701 {
702 // We can assume latin script type if the block only
703 // contains formula cells with numeric results.
704 ScFormulaCell** pp = &sc::formula_block::at(*node.data, 0);
705 ScFormulaCell** ppEnd = pp + node.size;
706 bool bNumResOnly = true;
707 for (; pp != ppEnd; ++pp)
708 {
709 const ScFormulaCell& rCell = **pp;
710 if (!rCell.IsValueNoError())
711 {
712 bNumResOnly = false;
713 break;
714 }
715 }
716
717 if (bNumResOnly)
718 aDefault.mnScriptType = SvtScriptType::LATIN;
719 }
720 }
721 break;
722 default:
723 ;
724 }
725
726 std::vector<sc::CellTextAttr> aDefaults(node.size, aDefault);
727 mpImpl->miPos = mpImpl->maAttrs.set(mpImpl->miPos, node.position, aDefaults.begin(), aDefaults.end());
728
729 if (node.type != sc::element_type_formula)
730 return;
731
732 if (mrDocImpl.mbFuzzing) // skip listening when fuzzing
733 return;
734
735 // Have all formula cells start listening to the document.
736 ScFormulaCell** pp = &sc::formula_block::at(*node.data, 0);
737 ScFormulaCell** ppEnd = pp + node.size;
738 for (; pp != ppEnd; ++pp)
739 {
740 ScFormulaCell& rFC = **pp;
741 if (rFC.IsSharedTop())
742 {
743 // Register formula cells as a group.
745 pp += rFC.GetSharedLength() - 1; // Move to the last one in the group.
746 }
747 else
748 rFC.StartListeningTo(mrDocImpl.maListenCxt);
749 }
750 }
751
752 void swap(sc::CellTextAttrStoreType& rAttrs)
753 {
754 mpImpl->maAttrs.swap(rAttrs);
755 }
756};
757
758}
759
761{
762 // Populate the text width and script type arrays in all columns. Also
763 // activate all formula cells.
764 for (auto& rxTab : mpImpl->mrDoc.maTabs)
765 {
766 if (!rxTab)
767 continue;
768
769 ScTable& rTab = *rxTab;
770 SCCOL nNumCols = rTab.aCol.size();
771 for (SCCOL nColIdx = 0; nColIdx < nNumCols; ++nColIdx)
772 initColumn(rTab.aCol[nColIdx]);
773 }
774
775 mpImpl->mrDoc.finalizeOutlineImport();
776}
777
779{
780 rCol.RegroupFormulaCells();
781
782 CellStoreInitializer aFunc(*mpImpl, rCol.nTab, rCol.nCol);
783 std::for_each(rCol.maCells.begin(), rCol.maCells.end(), aFunc);
784 aFunc.swap(rCol.maCellTextAttrs);
785
786 rCol.CellStorageModified();
787}
788
789namespace {
790
791class CellStoreAfterImportBroadcaster
792{
793public:
794
795 CellStoreAfterImportBroadcaster() {}
796
797 void operator() (const sc::CellStoreType::value_type& node)
798 {
799 if (node.type == sc::element_type_formula)
800 {
801 // Broadcast all formula cells marked for recalc.
802 ScFormulaCell** pp = &sc::formula_block::at(*node.data, 0);
803 ScFormulaCell** ppEnd = pp + node.size;
804 for (; pp != ppEnd; ++pp)
805 {
806 if ((*pp)->GetCode()->IsRecalcModeMustAfterImport())
807 (*pp)->SetDirty();
808 }
809 }
810 }
811};
812
813}
814
816{
817 sc::AutoCalcSwitch aACSwitch( mpImpl->mrDoc, false);
818 ScBulkBroadcast aBulkBroadcast( mpImpl->mrDoc.GetBASM(), SfxHintId::ScDataChanged);
819
820 for (auto& rxTab : mpImpl->mrDoc.maTabs)
821 {
822 if (!rxTab)
823 continue;
824
825 ScTable& rTab = *rxTab;
826 SCCOL nNumCols = rTab.aCol.size();
827 for (SCCOL nColIdx = 0; nColIdx < nNumCols; ++nColIdx)
829 }
830}
831
833{
834 CellStoreAfterImportBroadcaster aFunc;
835 std::for_each(rCol.maCells.begin(), rCol.maCells.end(), aFunc);
836}
837
838
840{
841 SvNumberFormatter* pFormatter = mpImpl->mrDoc.GetFormatTable();
842 sal_uInt32 nKey = rPatAttr.GetNumberFormat(pFormatter);
843 return isLatinScript(nKey);
844}
845
846bool ScDocumentImport::isLatinScript(sal_uInt32 nFormat)
847{
848 auto it = mpImpl->maIsLatinScriptMap.find(nFormat);
849 if (it != mpImpl->maIsLatinScriptMap.end())
850 return it->second;
851 bool b = sc::NumFmtUtil::isLatinScript(nFormat, mpImpl->mrDoc);
852 mpImpl->maIsLatinScriptMap.emplace(nFormat, b);
853 return b;
854}
855
856/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
XPropertyListType t
bool ValidTab(SCTAB nTab)
Definition: address.hxx:111
const SCTAB MAXTAB
Definition: address.hxx:70
SCTAB Tab() const
Definition: address.hxx:283
void SetCol(SCCOL nColP)
Definition: address.hxx:291
SCROW Row() const
Definition: address.hxx:274
void SetRow(SCROW nRowP)
Definition: address.hxx:287
SCCOL Col() const
Definition: address.hxx:279
SCCOL size() const
void CellStorageModified()
Called whenever the state of cell array gets modified i.e.
Definition: column2.cxx:1680
SCCOL nCol
Definition: column.hxx:204
sc::CellTextAttrStoreType maCellTextAttrs
Definition: column.hxx:188
SCTAB nTab
Definition: column.hxx:205
void RegroupFormulaCells(std::vector< ScAddress > *pGroupPos=nullptr)
Regroup formula cells for the entire column.
Definition: column3.cxx:3658
sc::CellStoreType maCells
Definition: column.hxx:197
void setRowsVisible(SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, bool bVisible)
void setMatrixCells(const ScRange &rRange, const ScTokenArray &rArray, formula::FormulaGrammar::Grammar eGrammar)
void setOriginDate(sal_uInt16 nYear, sal_uInt16 nMonth, sal_uInt16 nDay)
void initColumn(ScColumn &rCol)
void initForSheets()
Initialize the storage for all sheets after all the sheet instances have been created in the document...
void setMergedCells(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
void setEditCell(const ScAddress &rPos, std::unique_ptr< EditTextObject > pEditText)
void broadcastRecalcAfterImport()
Broadcast all formula cells that are marked with FormulaTokenArray::IsRecalcModeMustAfterImport() for...
void setStringCell(const ScAddress &rPos, const OUString &rStr)
bool appendSheet(const OUString &rName)
void setDefaultNumericScript(SvtScriptType nScript)
void setFormulaCell(const ScAddress &rPos, const OUString &rFormula, formula::FormulaGrammar::Grammar eGrammar, const double *pResult=nullptr)
void setTableOpCells(const ScRange &rRange, const ScTabOpParam &rParam)
ScDocument & getDoc()
bool isLatinScript(sal_uInt32 nFormat)
small cache for hot call during import
void setSheetName(SCTAB nTab, const OUString &rName)
ScDocumentImport()=delete
void invalidateBlockPositionSet(SCTAB nTab)
static void broadcastRecalcAfterImportColumn(ScColumn &rCol)
SCTAB getSheetCount() const
std::unique_ptr< ScDocumentImportImpl > mpImpl
void setAttrEntries(SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, Attrs &&rAttrs)
Set an array of cell attributes to specified range of columns.
SCTAB getSheetIndex(const OUString &rName) const
void setNumericCell(const ScAddress &rPos, double fVal)
void fillDownCells(const ScAddress &rPos, SCROW nFillSize)
void setAutoInput(const ScAddress &rPos, const OUString &rStr, const ScSetStringParam *pStringParam=nullptr)
void setCellStyleToSheet(SCTAB nTab, const ScStyleSheet &rStyle)
Apply specified cell style to an entire sheet.
void UpdatePageBreaks(SCTAB nTab, const ScRange *pUserArea=nullptr)
Definition: document.cxx:6210
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:892
SC_DLLPUBLIC void SetDrawPageSize(SCTAB nTab)
Definition: documen9.cxx:203
SC_DLLPUBLIC void ShowRows(SCROW nRow1, SCROW nRow2, SCTAB nTab, bool bShow)
Definition: document.cxx:4309
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:297
SCROW GetSharedLength() const
bool IsValueNoError()
bool IsSharedTop() const
void StartListeningTo(ScDocument &rDoc)
void SetDirty(bool bDirtyFlag=true)
void SetMatColsRows(SCCOL nCols, SCROW nRows)
ScTokenArray * GetCode()
sal_uInt32 GetNumberFormat(SvNumberFormatter *) const
Definition: patattr.cxx:1398
ScAddress aEnd
Definition: address.hxx:498
ScAddress aStart
Definition: address.hxx:497
SCCOL Col() const
Definition: address.hxx:886
OUString GetRefString(const ScDocument &rDocument, SCTAB nActTab, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1) const
Definition: address.cxx:2488
const ScAddress & GetAddress() const
Definition: address.hxx:881
void Set(const ScAddress &rAdr, bool bNewRelCol, bool bNewRelRow, bool bNewRelTab)
Definition: address.hxx:914
SCROW Row() const
Definition: address.hxx:890
void ApplyStyleArea(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, const ScStyleSheet &rStyle)
Definition: table2.cxx:3013
void SetAttrEntries(SCCOL nStartCol, SCCOL nEndCol, std::vector< ScAttrEntry > &&vNewData)
Definition: table2.cxx:2914
ScColContainer aCol
Definition: table.hxx:162
void SetMergedCells(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: table2.cxx:2345
static const OUString & GetNativeSymbol(OpCode eOp)
Temporarily switch on/off auto calculation mode.
Definition: scopetools.hxx:27
static bool isLatinScript(const ScPatternAttr &rPat, ScDocument &rDoc)
Check if the attribute pattern has a number format that only produces latin script output.
Definition: numformat.cxx:32
static void startListeningAsGroup(StartListeningContext &rCxt, ScFormulaCell **ppSharedTop)
Have all formula cells belonging to a group start listening to their references.
static void unshareFormulaCell(const CellStoreType::position_type &aPos, ScFormulaCell &rCell)
Turn a shared formula cell into a non-shared one, and split it off from the adjacent formula cell gro...
Set of column block positions only for one table.
ColumnBlockPosition * getBlockPosition(SCCOL nCol)
rtl_uString * getData()
static bool IsFuzzing()
sal_Int32 mnCol
UNKNOWN
@ CELLTYPE_EDIT
Definition: global.hxx:277
@ CELLTYPE_STRING
Definition: global.hxx:275
@ CELLTYPE_FORMULA
Definition: global.hxx:276
@ CELLTYPE_VALUE
Definition: global.hxx:274
void * p
sal_Int64 n
SvtScriptType
int i
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
void swap(cow_wrapper< T, P > &a, cow_wrapper< T, P > &b)
std::shared_ptr< T > make_shared(Args &&... args)
enumrange< T >::Iterator begin(enumrange< T >)
const mdds::mtv::element_t element_type_formula
Definition: mtvelements.hxx:49
mdds::mtv::soa::multi_type_vector< CellStoreTraits > CellStoreType
Cell container.
const mdds::mtv::element_t element_type_numeric
Mapped standard element types (for convenience).
Definition: mtvelements.hxx:55
mdds::mtv::soa::multi_type_vector< CellTextAttrTraits > CellTextAttrStoreType
Cell text attribute container.
const mdds::mtv::element_t element_type_empty
Definition: mtvelements.hxx:56
const SvxPageUsage aArr[]
ocClose
ocOpen
ocSep
ocTableOp
Store arbitrary cell value of any kind.
Definition: cellvalue.hxx:32
ScFormulaCell * releaseFormula()
Definition: cellvalue.hxx:63
const svl::SharedString * getSharedString() const
Definition: cellvalue.hxx:60
EditTextObject * releaseEditText()
Definition: cellvalue.hxx:62
CellType getType() const
Definition: cellvalue.cxx:296
ScFormulaCell * getFormula() const
Definition: cellvalue.hxx:59
double getDouble() const
Definition: cellvalue.hxx:58
ColAttr * getColAttr(size_t nTab, size_t nCol)
std::unordered_map< sal_uInt32, bool > maIsLatinScriptMap
sc::StartListeningContext maListenCxt
ScDocumentImportImpl(ScDocument &rDoc)
sc::ColumnBlockPosition * getBlockPosition(SCTAB nTab, SCCOL nCol)
bool isValid(size_t nTab, size_t nCol)
SvtScriptType mnDefaultScriptNumeric
void invalidateBlockPositionSet(SCTAB nTab)
std::vector< TabAttr > maTabAttrs
std::vector< sc::TableColumnBlockPositionSet > maBlockPosSet
This is very similar to ScCellValue, except that it references the original value instead of copying ...
Definition: cellvalue.hxx:108
double getDouble() const
Definition: cellvalue.hxx:134
const svl::SharedString * getSharedString() const
Definition: cellvalue.hxx:135
CellType getType() const
Definition: cellvalue.hxx:133
Store parameters used in the ScDocument::SetString() method.
Definition: stringutil.hxx:35
bool mbCheckLinkFormula
When true and the string results in a compiled formula, check the formula tokens for presence of func...
Definition: stringutil.hxx:103
Single reference (one address) into the sheet.
Definition: refdata.hxx:30
void SetAddress(const ScSheetLimits &rLimits, const ScAddress &rAddr, const ScAddress &rPos)
Definition: refdata.cxx:213
void SetRowRel(bool bVal)
Definition: refdata.hxx:66
void SetTabRel(bool bVal)
Definition: refdata.hxx:68
void InitFlags()
No default ctor, because used in ScRawToken union, set InitFlags!
Definition: refdata.hxx:54
void SetColRel(bool bVal)
Definition: refdata.hxx:64
Parameter for data table aka multiple operations.
Definition: paramisc.hxx:46
ScRefAddress aRefFormulaEnd
Definition: paramisc.hxx:50
ScRefAddress aRefColCell
Definition: paramisc.hxx:52
ScRefAddress aRefFormulaCell
Definition: paramisc.hxx:49
ScRefAddress aRefRowCell
Definition: paramisc.hxx:51
SvtScriptType mnScriptType
Store position data for column array storage.
CellStoreType::iterator miCellPos
bool bVisible
sal_Int16 SCTAB
Definition: types.hxx:22
sal_Int16 SCCOL
Definition: types.hxx:21
sal_Int32 SCROW
Definition: types.hxx:17