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