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 pBlockPos->miCellPos =
389 rCells.set(pBlockPos->miCellPos, rPos.Row(), pCell);
390}
391
393 const ScRange& rRange, const ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGram)
394{
395 const ScAddress& rBasePos = rRange.aStart;
396
397 ScTable* pTab = mpImpl->mrDoc.FetchTable(rBasePos.Tab());
398 if (!pTab)
399 return;
400
401 sc::ColumnBlockPosition* pBlockPos = mpImpl->getBlockPosition(rBasePos.Tab(), rBasePos.Col());
402
403 if (!pBlockPos)
404 return;
405
406 if (utl::ConfigManager::IsFuzzing()) //just too slow
407 return;
408
409 sc::CellStoreType& rCells = pTab->aCol[rBasePos.Col()].maCells;
410
411 // Set the master cell.
412 ScFormulaCell* pCell = new ScFormulaCell(mpImpl->mrDoc, rBasePos, rArray, eGram, ScMatrixMode::Formula);
413
414 mpImpl->mrDoc.CheckLinkFormulaNeedingCheck( *pCell->GetCode());
415
416 pBlockPos->miCellPos =
417 rCells.set(pBlockPos->miCellPos, rBasePos.Row(), pCell);
418
419 // Matrix formulas currently need re-calculation on import.
420 pCell->SetMatColsRows(
421 rRange.aEnd.Col()-rRange.aStart.Col()+1, rRange.aEnd.Row()-rRange.aStart.Row()+1);
422
423 // Set the reference cells.
424 ScSingleRefData aRefData;
425 aRefData.InitFlags();
426 aRefData.SetColRel(true);
427 aRefData.SetRowRel(true);
428 aRefData.SetTabRel(true);
429 aRefData.SetAddress(mpImpl->mrDoc.GetSheetLimits(), rBasePos, rBasePos);
430
431 ScTokenArray aArr(mpImpl->mrDoc); // consists only of one single reference token.
432 formula::FormulaToken* t = aArr.AddMatrixSingleReference(aRefData);
433
434 ScAddress aPos = rBasePos;
435 for (SCROW nRow = rRange.aStart.Row()+1; nRow <= rRange.aEnd.Row(); ++nRow)
436 {
437 // Token array must be cloned so that each formula cell receives its own copy.
438 aPos.SetRow(nRow);
439 // Reference in each cell must point to the origin cell relative to the current cell.
440 aRefData.SetAddress(mpImpl->mrDoc.GetSheetLimits(), rBasePos, aPos);
441 *t->GetSingleRef() = aRefData;
442 ScTokenArray aTokArr(aArr.CloneValue());
443 pCell = new ScFormulaCell(mpImpl->mrDoc, aPos, aTokArr, eGram, ScMatrixMode::Reference);
444 pBlockPos->miCellPos =
445 rCells.set(pBlockPos->miCellPos, aPos.Row(), pCell);
446 }
447
448 for (SCCOL nCol = rRange.aStart.Col()+1; nCol <= rRange.aEnd.Col(); ++nCol)
449 {
450 pBlockPos = mpImpl->getBlockPosition(rBasePos.Tab(), nCol);
451 if (!pBlockPos)
452 return;
453
454 sc::CellStoreType& rColCells = pTab->aCol[nCol].maCells;
455
456 aPos.SetCol(nCol);
457 for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
458 {
459 aPos.SetRow(nRow);
460 aRefData.SetAddress(mpImpl->mrDoc.GetSheetLimits(), rBasePos, aPos);
461 *t->GetSingleRef() = aRefData;
462 ScTokenArray aTokArr(aArr.CloneValue());
463 pCell = new ScFormulaCell(mpImpl->mrDoc, aPos, aTokArr, eGram, ScMatrixMode::Reference);
464 pBlockPos->miCellPos =
465 rColCells.set(pBlockPos->miCellPos, aPos.Row(), pCell);
466 }
467 }
468}
469
471{
472 SCTAB nTab = rRange.aStart.Tab();
473 SCCOL nCol1 = rRange.aStart.Col();
474 SCROW nRow1 = rRange.aStart.Row();
475 SCCOL nCol2 = rRange.aEnd.Col();
476 SCROW nRow2 = rRange.aEnd.Row();
477
478 ScTable* pTab = mpImpl->mrDoc.FetchTable(nTab);
479 if (!pTab)
480 return;
481
482 ScDocument& rDoc = mpImpl->mrDoc;
483 ScRefAddress aRef;
484 OUStringBuffer aFormulaBuf;
485 aFormulaBuf.append('=');
486 aFormulaBuf.append(ScCompiler::GetNativeSymbol(ocTableOp));
487 aFormulaBuf.append(ScCompiler::GetNativeSymbol(ocOpen));
488
489 OUString aSep = ScCompiler::GetNativeSymbol(ocSep);
490 if (rParam.meMode == ScTabOpParam::Column) // column only
491 {
492 aRef.Set(rParam.aRefFormulaCell.GetAddress(), true, false, false);
493 aFormulaBuf.append(aRef.GetRefString(rDoc, nTab));
494 aFormulaBuf.append(aSep);
495 aFormulaBuf.append(rParam.aRefColCell.GetRefString(rDoc, nTab));
496 aFormulaBuf.append(aSep);
497 aRef.Set(nCol1, nRow1, nTab, false, true, true);
498 aFormulaBuf.append(aRef.GetRefString(rDoc, nTab));
499 nCol1++;
500 nCol2 = std::min( nCol2, static_cast<SCCOL>(rParam.aRefFormulaEnd.Col() -
501 rParam.aRefFormulaCell.Col() + nCol1 + 1));
502 }
503 else if (rParam.meMode == ScTabOpParam::Row) // row only
504 {
505 aRef.Set(rParam.aRefFormulaCell.GetAddress(), false, true, false);
506 aFormulaBuf.append(aRef.GetRefString(rDoc, nTab));
507 aFormulaBuf.append(aSep);
508 aFormulaBuf.append(rParam.aRefRowCell.GetRefString(rDoc, nTab));
509 aFormulaBuf.append(aSep);
510 aRef.Set(nCol1, nRow1, nTab, true, false, true);
511 aFormulaBuf.append(aRef.GetRefString(rDoc, nTab));
512 ++nRow1;
513 nRow2 = std::min(
514 nRow2, rParam.aRefFormulaEnd.Row() - rParam.aRefFormulaCell.Row() + nRow1 + 1);
515 }
516 else // both
517 {
518 aFormulaBuf.append(rParam.aRefFormulaCell.GetRefString(rDoc, nTab));
519 aFormulaBuf.append(aSep);
520 aFormulaBuf.append(rParam.aRefColCell.GetRefString(rDoc, nTab));
521 aFormulaBuf.append(aSep);
522 aRef.Set(nCol1, nRow1 + 1, nTab, false, true, true);
523 aFormulaBuf.append(aRef.GetRefString(rDoc, nTab));
524 aFormulaBuf.append(aSep);
525 aFormulaBuf.append(rParam.aRefRowCell.GetRefString(rDoc, nTab));
526 aFormulaBuf.append(aSep);
527 aRef.Set(nCol1 + 1, nRow1, nTab, true, false, true);
528 aFormulaBuf.append(aRef.GetRefString(rDoc, nTab));
529 ++nCol1;
530 ++nRow1;
531 }
532
533 aFormulaBuf.append(ScCompiler::GetNativeSymbol(ocClose));
534
535 ScFormulaCell aRefCell(
536 rDoc, ScAddress(nCol1, nRow1, nTab), aFormulaBuf.makeStringAndClear(),
538
539 for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
540 {
541 sc::ColumnBlockPosition* pBlockPos = mpImpl->getBlockPosition(nTab, nCol);
542
543 if (!pBlockPos)
544 // Something went horribly wrong.
545 return;
546
547 sc::CellStoreType& rColCells = pTab->aCol[nCol].maCells;
548
549 for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
550 {
551 ScAddress aPos(nCol, nRow, nTab);
552 ScFormulaCell* pCell = new ScFormulaCell(aRefCell, rDoc, aPos);
553 pBlockPos->miCellPos =
554 rColCells.set(pBlockPos->miCellPos, nRow, pCell);
555 }
556 }
557}
558
560{
561 ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
562 if (!pTab)
563 return;
564
565 sc::ColumnBlockPosition* pBlockPos = mpImpl->getBlockPosition(rPos.Tab(), rPos.Col());
566
567 if (!pBlockPos)
568 return;
569
570 sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
571 ScRefCellValue aRefCell = pTab->aCol[rPos.Col()].GetCellValue(*pBlockPos, rPos.Row());
572
573 switch (aRefCell.getType())
574 {
575 case CELLTYPE_VALUE:
576 {
577 std::vector<double> aCopied(nFillSize, aRefCell.getDouble());
578 pBlockPos->miCellPos = rCells.set(
579 pBlockPos->miCellPos, rPos.Row()+1, aCopied.begin(), aCopied.end());
580 break;
581 }
582 case CELLTYPE_STRING:
583 {
584 std::vector<svl::SharedString> aCopied(nFillSize, *aRefCell.getSharedString());
585 pBlockPos->miCellPos = rCells.set(
586 pBlockPos->miCellPos, rPos.Row()+1, aCopied.begin(), aCopied.end());
587 break;
588 }
589 default:
590 break;
591 }
592}
593
594void ScDocumentImport::setAttrEntries( SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, Attrs&& rAttrs )
595{
596 ScTable* pTab = mpImpl->mrDoc.FetchTable(nTab);
597 if (!pTab)
598 return;
599
600 for(SCCOL nCol = nColStart; nCol <= nColEnd; ++nCol )
601 {
602 ColAttr* pColAttr = mpImpl->getColAttr(nTab, nCol);
603 if (pColAttr)
604 pColAttr->mbLatinNumFmtOnly = rAttrs.mbLatinNumFmtOnly;
605 }
606
607 pTab->SetAttrEntries( nColStart, nColEnd, std::move( rAttrs.mvData ));
608}
609
610void ScDocumentImport::setRowsVisible(SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, bool bVisible)
611{
612 if (!bVisible)
613 {
614 getDoc().ShowRows(nRowStart, nRowEnd, nTab, false);
615 getDoc().SetDrawPageSize(nTab);
616 getDoc().UpdatePageBreaks( nTab );
617 }
618 else
619 {
620 assert(false);
621 }
622}
623
624void ScDocumentImport::setMergedCells(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
625{
626 ScTable* pTab = mpImpl->mrDoc.FetchTable(nTab);
627 if (!pTab)
628 return;
629
630 pTab->SetMergedCells(nCol1, nRow1, nCol2, nRow2);
631}
632
633namespace {
634
635class CellStoreInitializer
636{
637 // The pimpl pattern here is intentional.
638 //
639 // The problem with having the attributes in CellStoreInitializer
640 // directly is that, as a functor, it might be copied around. In
641 // that case miPos in _copied_ object points to maAttrs in the
642 // original object, not in the copy. So later, deep in mdds, we end
643 // up comparing iterators from different sequences.
644 //
645 // This could be solved by defining copy constructor and operator=,
646 // but given the limited usage of the class, I think it is simpler
647 // to let copies share the state.
648 struct Impl
649 {
651 sc::CellTextAttrStoreType::iterator miPos;
652 SvtScriptType mnScriptNumeric;
653
654 explicit Impl(const ScSheetLimits& rSheetLimits, const SvtScriptType nScriptNumeric)
655 : maAttrs(rSheetLimits.GetMaxRowCount()), miPos(maAttrs.begin()), mnScriptNumeric(nScriptNumeric)
656 {}
657 };
658
659 ScDocumentImportImpl& mrDocImpl;
660 SCTAB mnTab;
661 SCCOL mnCol;
662
663public:
664 CellStoreInitializer( ScDocumentImportImpl& rDocImpl, SCTAB nTab, SCCOL nCol ) :
665 mrDocImpl(rDocImpl),
666 mnTab(nTab),
667 mnCol(nCol),
668 mpImpl(std::make_shared<Impl>(rDocImpl.mrDoc.GetSheetLimits(), mrDocImpl.mnDefaultScriptNumeric))
669 {}
670
671 std::shared_ptr<Impl> mpImpl;
672
673 void operator() (const sc::CellStoreType::value_type& node)
674 {
675 if (node.type == sc::element_type_empty)
676 return;
677
678 // Fill with default values for non-empty cell segments.
679 sc::CellTextAttr aDefault;
680 switch (node.type)
681 {
683 {
684 aDefault.mnScriptType = mpImpl->mnScriptNumeric;
685 const ColAttr* p = mrDocImpl.getColAttr(mnTab, mnCol);
686 if (p && p->mbLatinNumFmtOnly)
687 aDefault.mnScriptType = SvtScriptType::LATIN;
688 }
689 break;
691 {
692 const ColAttr* p = mrDocImpl.getColAttr(mnTab, mnCol);
693 if (p && p->mbLatinNumFmtOnly)
694 {
695 // We can assume latin script type if the block only
696 // contains formula cells with numeric results.
697 ScFormulaCell** pp = &sc::formula_block::at(*node.data, 0);
698 ScFormulaCell** ppEnd = pp + node.size;
699 bool bNumResOnly = true;
700 for (; pp != ppEnd; ++pp)
701 {
702 const ScFormulaCell& rCell = **pp;
703 if (!rCell.IsValueNoError())
704 {
705 bNumResOnly = false;
706 break;
707 }
708 }
709
710 if (bNumResOnly)
711 aDefault.mnScriptType = SvtScriptType::LATIN;
712 }
713 }
714 break;
715 default:
716 ;
717 }
718
719 std::vector<sc::CellTextAttr> aDefaults(node.size, aDefault);
720 mpImpl->miPos = mpImpl->maAttrs.set(mpImpl->miPos, node.position, aDefaults.begin(), aDefaults.end());
721
722 if (node.type != sc::element_type_formula)
723 return;
724
725 if (mrDocImpl.mbFuzzing) // skip listening when fuzzing
726 return;
727
728 // Have all formula cells start listening to the document.
729 ScFormulaCell** pp = &sc::formula_block::at(*node.data, 0);
730 ScFormulaCell** ppEnd = pp + node.size;
731 for (; pp != ppEnd; ++pp)
732 {
733 ScFormulaCell& rFC = **pp;
734 if (rFC.IsSharedTop())
735 {
736 // Register formula cells as a group.
738 pp += rFC.GetSharedLength() - 1; // Move to the last one in the group.
739 }
740 else
741 rFC.StartListeningTo(mrDocImpl.maListenCxt);
742 }
743 }
744
745 void swap(sc::CellTextAttrStoreType& rAttrs)
746 {
747 mpImpl->maAttrs.swap(rAttrs);
748 }
749};
750
751}
752
754{
755 // Populate the text width and script type arrays in all columns. Also
756 // activate all formula cells.
757 for (auto& rxTab : mpImpl->mrDoc.maTabs)
758 {
759 if (!rxTab)
760 continue;
761
762 ScTable& rTab = *rxTab;
763 SCCOL nNumCols = rTab.aCol.size();
764 for (SCCOL nColIdx = 0; nColIdx < nNumCols; ++nColIdx)
765 initColumn(rTab.aCol[nColIdx]);
766 }
767
768 mpImpl->mrDoc.finalizeOutlineImport();
769}
770
772{
773 rCol.RegroupFormulaCells();
774
775 CellStoreInitializer aFunc(*mpImpl, rCol.nTab, rCol.nCol);
776 std::for_each(rCol.maCells.begin(), rCol.maCells.end(), aFunc);
777 aFunc.swap(rCol.maCellTextAttrs);
778
779 rCol.CellStorageModified();
780}
781
782namespace {
783
784class CellStoreAfterImportBroadcaster
785{
786public:
787
788 CellStoreAfterImportBroadcaster() {}
789
790 void operator() (const sc::CellStoreType::value_type& node)
791 {
792 if (node.type == sc::element_type_formula)
793 {
794 // Broadcast all formula cells marked for recalc.
795 ScFormulaCell** pp = &sc::formula_block::at(*node.data, 0);
796 ScFormulaCell** ppEnd = pp + node.size;
797 for (; pp != ppEnd; ++pp)
798 {
799 if ((*pp)->GetCode()->IsRecalcModeMustAfterImport())
800 (*pp)->SetDirty();
801 }
802 }
803 }
804};
805
806}
807
809{
810 sc::AutoCalcSwitch aACSwitch( mpImpl->mrDoc, false);
811 ScBulkBroadcast aBulkBroadcast( mpImpl->mrDoc.GetBASM(), SfxHintId::ScDataChanged);
812
813 for (auto& rxTab : mpImpl->mrDoc.maTabs)
814 {
815 if (!rxTab)
816 continue;
817
818 ScTable& rTab = *rxTab;
819 SCCOL nNumCols = rTab.aCol.size();
820 for (SCCOL nColIdx = 0; nColIdx < nNumCols; ++nColIdx)
822 }
823}
824
826{
827 CellStoreAfterImportBroadcaster aFunc;
828 std::for_each(rCol.maCells.begin(), rCol.maCells.end(), aFunc);
829}
830
831
833{
834 SvNumberFormatter* pFormatter = mpImpl->mrDoc.GetFormatTable();
835 sal_uInt32 nKey = rPatAttr.GetNumberFormat(pFormatter);
836 return isLatinScript(nKey);
837}
838
839bool ScDocumentImport::isLatinScript(sal_uInt32 nFormat)
840{
841 auto it = mpImpl->maIsLatinScriptMap.find(nFormat);
842 if (it != mpImpl->maIsLatinScriptMap.end())
843 return it->second;
844 bool b = sc::NumFmtUtil::isLatinScript(nFormat, mpImpl->mrDoc);
845 mpImpl->maIsLatinScriptMap.emplace(nFormat, b);
846 return b;
847}
848
849/* 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:1647
SCCOL nCol
Definition: column.hxx:203
sc::CellTextAttrStoreType maCellTextAttrs
Definition: column.hxx:187
SCTAB nTab
Definition: column.hxx:204
void RegroupFormulaCells(std::vector< ScAddress > *pGroupPos=nullptr)
Regroup formula cells for the entire column.
Definition: column3.cxx:3624
sc::CellStoreType maCells
Definition: column.hxx:196
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:6330
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:891
SC_DLLPUBLIC void SetDrawPageSize(SCTAB nTab)
Definition: documen9.cxx:195
SC_DLLPUBLIC void ShowRows(SCROW nRow1, SCROW nRow2, SCTAB nTab, bool bShow)
Definition: document.cxx:4367
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:315
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:1301
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:2490
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:3001
void SetAttrEntries(SCCOL nStartCol, SCCOL nEndCol, std::vector< ScAttrEntry > &&vNewData)
Definition: table2.cxx:2900
ScColContainer aCol
Definition: table.hxx:160
void SetMergedCells(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: table2.cxx:2344
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:31
static void startListeningAsGroup(StartListeningContext &rCxt, ScFormulaCell **ppSharedTop)
Have all formula cells belonging to a group start listening to their references.
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:275
@ CELLTYPE_STRING
Definition: global.hxx:273
@ CELLTYPE_FORMULA
Definition: global.hxx:274
@ CELLTYPE_VALUE
Definition: global.hxx:272
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:50
mdds::mtv::soa::multi_type_vector< CellFunc, CellStoreTrait > CellStoreType
const mdds::mtv::element_t element_type_numeric
Mapped standard element types (for convenience).
Definition: mtvelements.hxx:56
mdds::mtv::soa::multi_type_vector< CTAttrFunc > CellTextAttrStoreType
const mdds::mtv::element_t element_type_empty
Definition: mtvelements.hxx:57
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:100
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