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