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