Line data Source code
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 "globalnames.hxx"
17 : #include "mtvelements.hxx"
18 : #include "tokenarray.hxx"
19 : #include "stringutil.hxx"
20 : #include "compiler.hxx"
21 : #include "paramisc.hxx"
22 : #include "listenercontext.hxx"
23 : #include <attarray.hxx>
24 : #include <sharedformula.hxx>
25 :
26 : #include <svl/sharedstringpool.hxx>
27 : #include <svl/languageoptions.hxx>
28 :
29 : #include <vector>
30 :
31 : namespace {
32 :
33 : struct ColAttr
34 : {
35 : bool mbLatinNumFmtOnly;
36 :
37 35646 : ColAttr() : mbLatinNumFmtOnly(false) {}
38 : };
39 :
40 1324 : struct TabAttr
41 : {
42 : std::vector<ColAttr> maCols;
43 : };
44 :
45 : typedef std::vector<TabAttr> TabAttrsType;
46 :
47 : }
48 :
49 1071 : struct ScDocumentImportImpl
50 : {
51 : ScDocument& mrDoc;
52 : sc::StartListeningContext maListenCxt;
53 : sc::ColumnBlockPositionSet maBlockPosSet;
54 : SvtScriptType mnDefaultScriptNumeric;
55 :
56 : TabAttrsType maTabAttrs;
57 :
58 1071 : ScDocumentImportImpl(ScDocument& rDoc) :
59 : mrDoc(rDoc),
60 : maListenCxt(rDoc),
61 : maBlockPosSet(rDoc),
62 1071 : mnDefaultScriptNumeric(SvtScriptType::UNKNOWN) {}
63 :
64 40625 : ColAttr* getColAttr( size_t nTab, size_t nCol )
65 : {
66 40625 : if (nTab > static_cast<size_t>(MAXTAB) || nCol > static_cast<size_t>(MAXCOL))
67 0 : return NULL;
68 :
69 40625 : if (nTab >= maTabAttrs.size())
70 461 : maTabAttrs.resize(nTab+1);
71 :
72 40625 : TabAttr& rTab = maTabAttrs[nTab];
73 40625 : if (nCol >= rTab.maCols.size())
74 34816 : rTab.maCols.resize(nCol+1);
75 :
76 40625 : return &rTab.maCols[nCol];
77 : }
78 : };
79 :
80 34052 : ScDocumentImport::Attrs::Attrs() : mpData(NULL), mnSize(0), mbLatinNumFmtOnly(false) {}
81 :
82 1071 : ScDocumentImport::ScDocumentImport(ScDocument& rDoc) : mpImpl(new ScDocumentImportImpl(rDoc)) {}
83 1071 : ScDocumentImport::~ScDocumentImport()
84 : {
85 1071 : delete mpImpl;
86 1071 : }
87 :
88 33670 : ScDocument& ScDocumentImport::getDoc()
89 : {
90 33670 : return mpImpl->mrDoc;
91 : }
92 :
93 0 : const ScDocument& ScDocumentImport::getDoc() const
94 : {
95 0 : return mpImpl->mrDoc;
96 : }
97 :
98 197 : void ScDocumentImport::setDefaultNumericScript(SvtScriptType nScript)
99 : {
100 197 : mpImpl->mnDefaultScriptNumeric = nScript;
101 197 : }
102 :
103 268 : void ScDocumentImport::setCellStyleToSheet(SCTAB nTab, const ScStyleSheet& rStyle)
104 : {
105 268 : ScTable* pTab = mpImpl->mrDoc.FetchTable(nTab);
106 268 : if (!pTab)
107 268 : return;
108 :
109 268 : pTab->ApplyStyleArea(0, 0, MAXCOL, MAXROW, rStyle);
110 : }
111 :
112 0 : SCTAB ScDocumentImport::getSheetIndex(const OUString& rName) const
113 : {
114 0 : SCTAB nTab = -1;
115 0 : if (!mpImpl->mrDoc.GetTable(rName, nTab))
116 0 : return -1;
117 :
118 0 : return nTab;
119 : }
120 :
121 0 : SCTAB ScDocumentImport::getSheetCount() const
122 : {
123 0 : return mpImpl->mrDoc.maTabs.size();
124 : }
125 :
126 0 : bool ScDocumentImport::appendSheet(const OUString& rName)
127 : {
128 0 : SCTAB nTabCount = mpImpl->mrDoc.maTabs.size();
129 0 : if (!ValidTab(nTabCount))
130 0 : return false;
131 :
132 0 : mpImpl->mrDoc.maTabs.push_back(new ScTable(&mpImpl->mrDoc, nTabCount, rName));
133 0 : return true;
134 : }
135 :
136 0 : void ScDocumentImport::setOriginDate(sal_uInt16 nYear, sal_uInt16 nMonth, sal_uInt16 nDay)
137 : {
138 0 : if (!mpImpl->mrDoc.pDocOptions)
139 0 : mpImpl->mrDoc.pDocOptions = new ScDocOptions;
140 :
141 0 : mpImpl->mrDoc.pDocOptions->SetDate(nDay, nMonth, nYear);
142 0 : }
143 :
144 274 : void ScDocumentImport::setAutoInput(const ScAddress& rPos, const OUString& rStr, ScSetStringParam* pStringParam)
145 : {
146 274 : ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
147 274 : if (!pTab)
148 0 : return;
149 :
150 : sc::ColumnBlockPosition* pBlockPos =
151 274 : mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
152 :
153 274 : if (!pBlockPos)
154 0 : return;
155 :
156 274 : ScCellValue aCell;
157 274 : pTab->aCol[rPos.Col()].ParseString(
158 548 : aCell, rPos.Row(), rPos.Tab(), rStr, mpImpl->mrDoc.GetAddressConvention(), pStringParam);
159 :
160 274 : sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
161 274 : switch (aCell.meType)
162 : {
163 : case CELLTYPE_STRING:
164 : // string is copied.
165 173 : pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), *aCell.mpString);
166 173 : break;
167 : case CELLTYPE_EDIT:
168 : // Cell takes the ownership of the text object.
169 0 : pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), aCell.mpEditText);
170 0 : aCell.mpEditText = NULL;
171 0 : break;
172 : case CELLTYPE_VALUE:
173 101 : pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), aCell.mfValue);
174 101 : break;
175 : case CELLTYPE_FORMULA:
176 : // This formula cell instance is directly placed in the document without copying.
177 0 : pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), aCell.mpFormula);
178 0 : aCell.mpFormula = NULL;
179 0 : break;
180 : default:
181 0 : pBlockPos->miCellPos = rCells.set_empty(pBlockPos->miCellPos, rPos.Row(), rPos.Row());
182 274 : }
183 : }
184 :
185 24020 : void ScDocumentImport::setNumericCell(const ScAddress& rPos, double fVal)
186 : {
187 24020 : ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
188 24020 : if (!pTab)
189 0 : return;
190 :
191 : sc::ColumnBlockPosition* pBlockPos =
192 24020 : mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
193 :
194 24020 : if (!pBlockPos)
195 0 : return;
196 :
197 24020 : sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
198 24020 : pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), fVal);
199 : }
200 :
201 81415 : void ScDocumentImport::setStringCell(const ScAddress& rPos, const OUString& rStr)
202 : {
203 81415 : ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
204 81415 : if (!pTab)
205 0 : return;
206 :
207 : sc::ColumnBlockPosition* pBlockPos =
208 81415 : mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
209 :
210 81415 : if (!pBlockPos)
211 0 : return;
212 :
213 81415 : svl::SharedString aSS = mpImpl->mrDoc.GetSharedStringPool().intern(rStr);
214 81415 : if (!aSS.getData())
215 0 : return;
216 :
217 81415 : sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
218 81415 : pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), aSS);
219 : }
220 :
221 480 : void ScDocumentImport::setEditCell(const ScAddress& rPos, EditTextObject* pEditText)
222 : {
223 480 : ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
224 480 : if (!pTab)
225 0 : return;
226 :
227 : sc::ColumnBlockPosition* pBlockPos =
228 480 : mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
229 :
230 480 : if (!pBlockPos)
231 0 : return;
232 :
233 480 : pEditText->NormalizeString(mpImpl->mrDoc.GetSharedStringPool());
234 480 : sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
235 480 : pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), pEditText);
236 : }
237 :
238 0 : void ScDocumentImport::setFormulaCell(
239 : const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar)
240 : {
241 0 : ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
242 0 : if (!pTab)
243 0 : return;
244 :
245 : sc::ColumnBlockPosition* pBlockPos =
246 0 : mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
247 :
248 0 : if (!pBlockPos)
249 0 : return;
250 :
251 0 : sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
252 0 : pBlockPos->miCellPos =
253 0 : rCells.set(pBlockPos->miCellPos, rPos.Row(), new ScFormulaCell(&mpImpl->mrDoc, rPos, rFormula, eGrammar));
254 : }
255 :
256 34 : void ScDocumentImport::setFormulaCell(const ScAddress& rPos, ScTokenArray* pArray)
257 : {
258 34 : ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
259 34 : if (!pTab)
260 0 : return;
261 :
262 : sc::ColumnBlockPosition* pBlockPos =
263 34 : mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
264 :
265 34 : if (!pBlockPos)
266 0 : return;
267 :
268 34 : sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
269 136 : pBlockPos->miCellPos =
270 102 : rCells.set(pBlockPos->miCellPos, rPos.Row(), new ScFormulaCell(&mpImpl->mrDoc, rPos, pArray));
271 : }
272 :
273 7268 : void ScDocumentImport::setFormulaCell(const ScAddress& rPos, ScFormulaCell* pCell)
274 : {
275 7268 : ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
276 7268 : if (!pTab)
277 0 : return;
278 :
279 : sc::ColumnBlockPosition* pBlockPos =
280 7268 : mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
281 :
282 7268 : if (!pBlockPos)
283 0 : return;
284 :
285 7268 : sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
286 14536 : pBlockPos->miCellPos =
287 14536 : rCells.set(pBlockPos->miCellPos, rPos.Row(), pCell);
288 : }
289 :
290 53 : void ScDocumentImport::setMatrixCells(
291 : const ScRange& rRange, const ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGram)
292 : {
293 53 : const ScAddress& rBasePos = rRange.aStart;
294 :
295 53 : ScTable* pTab = mpImpl->mrDoc.FetchTable(rBasePos.Tab());
296 53 : if (!pTab)
297 0 : return;
298 :
299 : sc::ColumnBlockPosition* pBlockPos =
300 53 : mpImpl->maBlockPosSet.getBlockPosition(rBasePos.Tab(), rBasePos.Col());
301 :
302 53 : if (!pBlockPos)
303 0 : return;
304 :
305 53 : sc::CellStoreType& rCells = pTab->aCol[rBasePos.Col()].maCells;
306 :
307 : // Set the master cell.
308 53 : ScFormulaCell* pCell = new ScFormulaCell(&mpImpl->mrDoc, rBasePos, rArray, eGram, MM_FORMULA);
309 :
310 106 : pBlockPos->miCellPos =
311 106 : rCells.set(pBlockPos->miCellPos, rBasePos.Row(), pCell);
312 :
313 : // Matrix formulas currently need re-calculation on import.
314 : pCell->SetMatColsRows(
315 53 : rRange.aEnd.Col()-rRange.aStart.Col()+1, rRange.aEnd.Row()-rRange.aStart.Row()+1, true);
316 :
317 : // Set the reference cells.
318 : ScSingleRefData aRefData;
319 53 : aRefData.InitFlags();
320 53 : aRefData.SetColRel(true);
321 53 : aRefData.SetRowRel(true);
322 53 : aRefData.SetTabRel(true);
323 53 : aRefData.SetAddress(rBasePos, rBasePos);
324 :
325 53 : ScTokenArray aArr; // consists only of one single reference token.
326 53 : formula::FormulaToken* t = aArr.AddMatrixSingleReference(aRefData);
327 :
328 53 : ScAddress aPos = rBasePos;
329 94 : for (SCROW nRow = rRange.aStart.Row()+1; nRow <= rRange.aEnd.Row(); ++nRow)
330 : {
331 : // Token array must be cloned so that each formula cell receives its own copy.
332 41 : aPos.SetRow(nRow);
333 : // Reference in each cell must point to the origin cell relative to the current cell.
334 41 : aRefData.SetAddress(rBasePos, aPos);
335 41 : *t->GetSingleRef() = aRefData;
336 41 : boost::scoped_ptr<ScTokenArray> pTokArr(aArr.Clone());
337 41 : pCell = new ScFormulaCell(&mpImpl->mrDoc, aPos, *pTokArr, eGram, MM_REFERENCE);
338 82 : pBlockPos->miCellPos =
339 82 : rCells.set(pBlockPos->miCellPos, aPos.Row(), pCell);
340 41 : }
341 :
342 91 : for (SCCOL nCol = rRange.aStart.Col()+1; nCol <= rRange.aEnd.Col(); ++nCol)
343 : {
344 38 : pBlockPos = mpImpl->maBlockPosSet.getBlockPosition(rBasePos.Tab(), nCol);
345 38 : if (!pBlockPos)
346 0 : return;
347 :
348 38 : sc::CellStoreType& rColCells = pTab->aCol[nCol].maCells;
349 :
350 38 : aPos.SetCol(nCol);
351 90 : for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
352 : {
353 52 : aPos.SetRow(nRow);
354 52 : aRefData.SetAddress(rBasePos, aPos);
355 52 : *t->GetSingleRef() = aRefData;
356 52 : boost::scoped_ptr<ScTokenArray> pTokArr(aArr.Clone());
357 52 : pCell = new ScFormulaCell(&mpImpl->mrDoc, aPos, *pTokArr, eGram, MM_REFERENCE);
358 104 : pBlockPos->miCellPos =
359 104 : rColCells.set(pBlockPos->miCellPos, aPos.Row(), pCell);
360 52 : }
361 53 : }
362 : }
363 :
364 5 : void ScDocumentImport::setTableOpCells(const ScRange& rRange, const ScTabOpParam& rParam)
365 : {
366 5 : SCTAB nTab = rRange.aStart.Tab();
367 5 : SCCOL nCol1 = rRange.aStart.Col();
368 5 : SCROW nRow1 = rRange.aStart.Row();
369 5 : SCCOL nCol2 = rRange.aEnd.Col();
370 5 : SCROW nRow2 = rRange.aEnd.Row();
371 :
372 5 : ScTable* pTab = mpImpl->mrDoc.FetchTable(nTab);
373 5 : if (!pTab)
374 0 : return;
375 :
376 5 : ScDocument* pDoc = &mpImpl->mrDoc;
377 5 : ScRefAddress aRef;
378 5 : OUStringBuffer aFormulaBuf;
379 5 : aFormulaBuf.append('=');
380 5 : aFormulaBuf.append(ScCompiler::GetNativeSymbol(ocTableOp));
381 5 : aFormulaBuf.append(ScCompiler::GetNativeSymbol(ocOpen));
382 :
383 10 : OUString aSep = ScCompiler::GetNativeSymbol(ocSep);
384 5 : if (rParam.meMode == ScTabOpParam::Column) // column only
385 : {
386 2 : aRef.Set(rParam.aRefFormulaCell.GetAddress(), true, false, false);
387 2 : aFormulaBuf.append(aRef.GetRefString(pDoc, nTab));
388 2 : aFormulaBuf.append(aSep);
389 2 : aFormulaBuf.append(rParam.aRefColCell.GetRefString(pDoc, nTab));
390 2 : aFormulaBuf.append(aSep);
391 2 : aRef.Set(nCol1, nRow1, nTab, false, true, true);
392 2 : aFormulaBuf.append(aRef.GetRefString(pDoc, nTab));
393 2 : nCol1++;
394 2 : nCol2 = std::min( nCol2, (SCCOL)(rParam.aRefFormulaEnd.Col() -
395 2 : rParam.aRefFormulaCell.Col() + nCol1 + 1));
396 : }
397 3 : else if (rParam.meMode == ScTabOpParam::Row) // row only
398 : {
399 1 : aRef.Set(rParam.aRefFormulaCell.GetAddress(), false, true, false);
400 1 : aFormulaBuf.append(aRef.GetRefString(pDoc, nTab));
401 1 : aFormulaBuf.append(aSep);
402 1 : aFormulaBuf.append(rParam.aRefRowCell.GetRefString(pDoc, nTab));
403 1 : aFormulaBuf.append(aSep);
404 1 : aRef.Set(nCol1, nRow1, nTab, true, false, true);
405 1 : aFormulaBuf.append(aRef.GetRefString(pDoc, nTab));
406 1 : ++nRow1;
407 : nRow2 = std::min(
408 1 : nRow2, rParam.aRefFormulaEnd.Row() - rParam.aRefFormulaCell.Row() + nRow1 + 1);
409 : }
410 : else // both
411 : {
412 2 : aFormulaBuf.append(rParam.aRefFormulaCell.GetRefString(pDoc, nTab));
413 2 : aFormulaBuf.append(aSep);
414 2 : aFormulaBuf.append(rParam.aRefColCell.GetRefString(pDoc, nTab));
415 2 : aFormulaBuf.append(aSep);
416 2 : aRef.Set(nCol1, nRow1 + 1, nTab, false, true, true);
417 2 : aFormulaBuf.append(aRef.GetRefString(pDoc, nTab));
418 2 : aFormulaBuf.append(aSep);
419 2 : aFormulaBuf.append(rParam.aRefRowCell.GetRefString(pDoc, nTab));
420 2 : aFormulaBuf.append(aSep);
421 2 : aRef.Set(nCol1 + 1, nRow1, nTab, true, false, true);
422 2 : aFormulaBuf.append(aRef.GetRefString(pDoc, nTab));
423 2 : ++nCol1;
424 2 : ++nRow1;
425 : }
426 :
427 5 : aFormulaBuf.append(ScCompiler::GetNativeSymbol(ocClose));
428 :
429 : ScFormulaCell aRefCell(
430 : pDoc, ScAddress(nCol1, nRow1, nTab), aFormulaBuf.makeStringAndClear(),
431 10 : formula::FormulaGrammar::GRAM_NATIVE, MM_NONE);
432 :
433 26 : for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
434 : {
435 : sc::ColumnBlockPosition* pBlockPos =
436 21 : mpImpl->maBlockPosSet.getBlockPosition(nTab, nCol);
437 :
438 21 : if (!pBlockPos)
439 : // Something went horribly wrong.
440 0 : return;
441 :
442 21 : sc::CellStoreType& rColCells = pTab->aCol[nCol].maCells;
443 :
444 186 : for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
445 : {
446 165 : ScAddress aPos(nCol, nRow, nTab);
447 165 : ScFormulaCell* pCell = new ScFormulaCell(aRefCell, *pDoc, aPos);
448 330 : pBlockPos->miCellPos =
449 165 : rColCells.set(pBlockPos->miCellPos, nRow, pCell);
450 : }
451 5 : }
452 : }
453 :
454 34052 : void ScDocumentImport::setAttrEntries( SCTAB nTab, SCCOL nCol, Attrs& rAttrs )
455 : {
456 34052 : ScTable* pTab = mpImpl->mrDoc.FetchTable(nTab);
457 34052 : if (!pTab)
458 0 : return;
459 :
460 34052 : ScColumn* pCol = pTab->FetchColumn(nCol);
461 34052 : if (!pCol)
462 0 : return;
463 :
464 34052 : ColAttr* pColAttr = mpImpl->getColAttr(nTab, nCol);
465 34052 : if (pColAttr)
466 34052 : pColAttr->mbLatinNumFmtOnly = rAttrs.mbLatinNumFmtOnly;
467 :
468 34052 : pCol->pAttrArray->SetAttrEntries(rAttrs.mpData, rAttrs.mnSize);
469 : }
470 :
471 : namespace {
472 :
473 4249600 : class CellStoreInitializer
474 : {
475 : // The pimpl pattern here is intentional.
476 : //
477 : // The problem with having the attributes in CellStoreInitializer
478 : // directly is that, as a functor, it might be copied around. In
479 : // that case miPos in _copied_ object points ot maAttrs in the
480 : // original object, not in the copy. So later, deep in mdds, we end
481 : // up comparing iterators from different sequences.
482 : //
483 : // This could be solved by defining copy constructor and operator=,
484 : // but given the limited usage of the class, I think it is simpler
485 : // to let copies share the state.
486 849920 : struct Impl
487 : {
488 : sc::CellTextAttrStoreType maAttrs;
489 : sc::CellTextAttrStoreType::iterator miPos;
490 : SvtScriptType mnScriptNumeric;
491 :
492 849920 : Impl(const sal_uInt32 nMaxRowCount, const SvtScriptType nScriptNumeric)
493 849920 : : maAttrs(nMaxRowCount), miPos(maAttrs.begin()), mnScriptNumeric(nScriptNumeric)
494 849920 : {}
495 : };
496 :
497 : ScDocumentImportImpl& mrDocImpl;
498 : SCTAB mnTab;
499 : SCCOL mnCol;
500 :
501 : public:
502 849920 : CellStoreInitializer( ScDocumentImportImpl& rDocImpl, SCTAB nTab, SCCOL nCol ) :
503 : mrDocImpl(rDocImpl),
504 : mnTab(nTab),
505 : mnCol(nCol),
506 849920 : mpImpl(new Impl(MAXROWCOUNT, mrDocImpl.mnDefaultScriptNumeric))
507 849920 : {}
508 :
509 : boost::shared_ptr<Impl> mpImpl;
510 :
511 867748 : void operator() (const sc::CellStoreType::value_type& node)
512 : {
513 867748 : if (node.type == sc::element_type_empty)
514 1724822 : return;
515 :
516 : // Fill with default values for non-empty cell segments.
517 10674 : sc::CellTextAttr aDefault;
518 10674 : switch (node.type)
519 : {
520 : case sc::element_type_numeric:
521 : {
522 4875 : aDefault.mnScriptType = mpImpl->mnScriptNumeric;
523 4875 : const ColAttr* p = mrDocImpl.getColAttr(mnTab, mnCol);
524 4875 : if (p && p->mbLatinNumFmtOnly)
525 261 : aDefault.mnScriptType = SvtScriptType::LATIN;
526 : }
527 4875 : break;
528 : case sc::element_type_formula:
529 : {
530 1698 : const ColAttr* p = mrDocImpl.getColAttr(mnTab, mnCol);
531 1698 : if (p && p->mbLatinNumFmtOnly)
532 : {
533 : // We can assume latin script type if the block only
534 : // contains formula cells with numeric results.
535 126 : ScFormulaCell** pp = &sc::formula_block::at(*node.data, 0);
536 126 : ScFormulaCell** ppEnd = pp + node.size;
537 126 : bool bNumResOnly = true;
538 699 : for (; pp != ppEnd; ++pp)
539 : {
540 622 : const ScFormulaCell& rCell = **pp;
541 622 : if (!rCell.IsValueNoError())
542 : {
543 49 : bNumResOnly = false;
544 49 : break;
545 : }
546 : }
547 :
548 126 : if (bNumResOnly)
549 77 : aDefault.mnScriptType = SvtScriptType::LATIN;
550 : }
551 : }
552 1698 : break;
553 : default:
554 : ;
555 : }
556 :
557 10674 : std::vector<sc::CellTextAttr> aDefaults(node.size, aDefault);
558 10674 : mpImpl->miPos = mpImpl->maAttrs.set(mpImpl->miPos, node.position, aDefaults.begin(), aDefaults.end());
559 :
560 10674 : if (node.type == sc::element_type_formula)
561 : {
562 : // Have all formula cells start listening to the document.
563 1698 : ScFormulaCell** pp = &sc::formula_block::at(*node.data, 0);
564 1698 : ScFormulaCell** ppEnd = pp + node.size;
565 5985 : for (; pp != ppEnd; ++pp)
566 : {
567 4287 : ScFormulaCell& rFC = **pp;
568 4287 : if (rFC.IsSharedTop())
569 : {
570 : // Register formula cells as a group.
571 787 : sc::SharedFormulaUtil::startListeningAsGroup(mrDocImpl.maListenCxt, pp);
572 787 : pp += rFC.GetSharedLength() - 1; // Move to the last one in the group.
573 : }
574 : else
575 3500 : rFC.StartListeningTo(mrDocImpl.maListenCxt);
576 : }
577 10674 : }
578 : }
579 :
580 849920 : void swap(sc::CellTextAttrStoreType& rAttrs)
581 : {
582 849920 : mpImpl->maAttrs.swap(rAttrs);
583 849920 : }
584 : };
585 :
586 : }
587 :
588 429 : void ScDocumentImport::finalize()
589 : {
590 : // Populate the text width and script type arrays in all columns. Also
591 : // activate all formula cells.
592 429 : ScDocument::TableContainer::iterator itTab = mpImpl->mrDoc.maTabs.begin(), itTabEnd = mpImpl->mrDoc.maTabs.end();
593 1259 : for (; itTab != itTabEnd; ++itTab)
594 : {
595 830 : if (!*itTab)
596 0 : continue;
597 :
598 830 : ScTable& rTab = **itTab;
599 830 : ScColumn* pCol = &rTab.aCol[0];
600 830 : ScColumn* pColEnd = pCol + static_cast<size_t>(MAXCOLCOUNT);
601 850750 : for (; pCol != pColEnd; ++pCol)
602 849920 : initColumn(*pCol);
603 : }
604 429 : }
605 :
606 849920 : void ScDocumentImport::initColumn(ScColumn& rCol)
607 : {
608 849920 : rCol.RegroupFormulaCells();
609 :
610 849920 : CellStoreInitializer aFunc(*mpImpl, rCol.nTab, rCol.nCol);
611 849920 : std::for_each(rCol.maCells.begin(), rCol.maCells.end(), aFunc);
612 849920 : aFunc.swap(rCol.maCellTextAttrs);
613 :
614 849920 : rCol.CellStorageModified();
615 850076 : }
616 :
617 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|