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 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "xmlcelli.hxx"
21 : #include "xmlimprt.hxx"
22 : #include "xmltabi.hxx"
23 : #include "xmlstyli.hxx"
24 : #include "xmlannoi.hxx"
25 : #include "global.hxx"
26 : #include "document.hxx"
27 : #include "cellsuno.hxx"
28 : #include "docuno.hxx"
29 : #include "unonames.hxx"
30 : #include "postit.hxx"
31 : #include "sheetdata.hxx"
32 : #include "docsh.hxx"
33 : #include "cellform.hxx"
34 : #include "validat.hxx"
35 : #include "patattr.hxx"
36 : #include "scitems.hxx"
37 : #include "docpool.hxx"
38 :
39 : #include "XMLTableShapeImportHelper.hxx"
40 : #include "XMLStylesImportHelper.hxx"
41 : #include "celltextparacontext.hxx"
42 :
43 : #include "arealink.hxx"
44 : #include <sfx2/linkmgr.hxx>
45 : #include "convuno.hxx"
46 : #include "XMLConverter.hxx"
47 : #include "scerrors.hxx"
48 : #include "editutil.hxx"
49 : #include "formulacell.hxx"
50 : #include "editattributemap.hxx"
51 : #include "stringutil.hxx"
52 : #include "tokenarray.hxx"
53 : #include "scmatrix.hxx"
54 :
55 : #include <xmloff/xmltkmap.hxx>
56 : #include <xmloff/xmltoken.hxx>
57 : #include <xmloff/nmspmap.hxx>
58 : #include <xmloff/xmluconv.hxx>
59 : #include <xmloff/families.hxx>
60 : #include <xmloff/numehelp.hxx>
61 : #include <xmloff/xmlnmspe.hxx>
62 : #include "xmloff/prstylei.hxx"
63 : #include <svl/zforlist.hxx>
64 : #include <svx/svdocapt.hxx>
65 : #include <editeng/outlobj.hxx>
66 : #include <editeng/editobj.hxx>
67 : #include "editeng/wghtitem.hxx"
68 : #include "editeng/colritem.hxx"
69 : #include "editeng/fhgtitem.hxx"
70 : #include "editeng/postitem.hxx"
71 : #include "editeng/fontitem.hxx"
72 : #include "editeng/udlnitem.hxx"
73 : #include "editeng/wrlmitem.hxx"
74 : #include "editeng/crossedoutitem.hxx"
75 : #include "editeng/charreliefitem.hxx"
76 : #include "editeng/charscaleitem.hxx"
77 : #include "editeng/contouritem.hxx"
78 : #include "editeng/shdditem.hxx"
79 : #include "editeng/kernitem.hxx"
80 : #include "editeng/autokernitem.hxx"
81 : #include "editeng/escapementitem.hxx"
82 : #include "editeng/emphasismarkitem.hxx"
83 : #include "editeng/langitem.hxx"
84 : #include <svx/unoapi.hxx>
85 : #include <svl/languageoptions.hxx>
86 : #include <sax/tools/converter.hxx>
87 :
88 : #include <com/sun/star/frame/XModel.hpp>
89 : #include <com/sun/star/text/XText.hpp>
90 : #include <com/sun/star/sheet/XSpreadsheets.hpp>
91 : #include <com/sun/star/sheet/XSpreadsheet.hpp>
92 : #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
93 :
94 : #include <com/sun/star/sheet/XSheetCondition.hpp>
95 : #include <com/sun/star/table/XCellRange.hpp>
96 : #include <com/sun/star/table/CellAddress.hpp>
97 : #include <com/sun/star/util/NumberFormat.hpp>
98 : #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
99 : #include <com/sun/star/util/XNumberFormatTypes.hpp>
100 : #include <com/sun/star/util/Date.hpp>
101 : #include <com/sun/star/lang/Locale.hpp>
102 : #include <com/sun/star/text/ControlCharacter.hpp>
103 : #include <com/sun/star/table/XCell.hpp>
104 : #include <com/sun/star/document/XActionLockable.hpp>
105 :
106 : #include <com/sun/star/sheet/ValidationType.hpp>
107 : #include <com/sun/star/sheet/ValidationAlertStyle.hpp>
108 : #include <com/sun/star/sheet/ConditionOperator.hpp>
109 :
110 : #include <rtl/ustrbuf.hxx>
111 : #include <tools/date.hxx>
112 : #include <i18nlangtag/lang.h>
113 : #include <comphelper/extract.hxx>
114 : #include <tools/string.hxx>
115 :
116 : using namespace com::sun::star;
117 : using namespace xmloff::token;
118 :
119 16 : ScXMLTableRowCellContext::ParaFormat::ParaFormat(ScEditEngineDefaulter& rEditEngine) :
120 16 : maItemSet(rEditEngine.GetEmptyItemSet()) {}
121 :
122 9 : ScXMLTableRowCellContext::Field::Field(SvxFieldData* pData) : mpData(pData) {}
123 :
124 18 : ScXMLTableRowCellContext::Field::~Field()
125 : {
126 9 : delete mpData;
127 9 : }
128 :
129 5652 : ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport,
130 : sal_uInt16 nPrfx,
131 : const OUString& rLName,
132 : const ::com::sun::star::uno::Reference<
133 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
134 : const bool bTempIsCovered,
135 : const sal_Int32 nTempRepeatedRows ) :
136 : ScXMLImportContext(rImport, nPrfx, rLName),
137 5652 : mpEditEngine(GetScImport().GetEditEngine()),
138 : mnCurParagraph(0),
139 : pDetectiveObjVec(NULL),
140 : pCellRangeSource(NULL),
141 : fValue(0.0),
142 : nMergedRows(1),
143 : nRepeatedRows(nTempRepeatedRows),
144 : nMergedCols(1),
145 : nColsRepeated(1),
146 : rXMLImport((ScXMLImport&)rImport),
147 : eGrammar( formula::FormulaGrammar::GRAM_STORAGE_DEFAULT),
148 : nCellType(util::NumberFormat::TEXT),
149 : bIsMerged(false),
150 : bIsMatrix(false),
151 : bIsCovered(bTempIsCovered),
152 : bIsEmpty(true),
153 : mbNewValueType(false),
154 : mbErrorValue(false),
155 : bIsFirstTextImport(false),
156 : bSolarMutexLocked(false),
157 : bFormulaTextResult(false),
158 : mbPossibleErrorCell(false),
159 : mbCheckWithCompilerForError(false),
160 11304 : mbEditEngineHasText(false)
161 : {
162 5652 : rtl::math::setNan(&fValue); // NaN by default
163 5652 : mpEditEngine->Clear();
164 :
165 5652 : rXMLImport.SetRemoveLastChar(false);
166 5652 : rXMLImport.GetTables().AddColumn(bTempIsCovered);
167 5652 : const sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
168 5652 : OUString aLocalName;
169 5652 : OUString* pStyleName = NULL;
170 5652 : OUString* pCurrencySymbol = NULL;
171 5652 : const SvXMLTokenMap& rTokenMap = rImport.GetTableRowCellAttrTokenMap();
172 13451 : for (sal_Int16 i = 0; i < nAttrCount; ++i)
173 : {
174 7799 : sal_uInt16 nAttrPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(
175 15598 : xAttrList->getNameByIndex(i), &aLocalName);
176 :
177 7799 : const OUString& sValue = xAttrList->getValueByIndex(i);
178 7799 : sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName);
179 7799 : switch (nToken)
180 : {
181 : case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME:
182 809 : pStyleName = new OUString(sValue);
183 809 : break;
184 : case XML_TOK_TABLE_ROW_CELL_ATTR_CONTENT_VALIDATION_NAME:
185 : OSL_ENSURE(!maContentValidationName, "here should be only one Validation Name");
186 14 : if (!sValue.isEmpty())
187 14 : maContentValidationName.reset(sValue);
188 14 : break;
189 : case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_ROWS:
190 5 : bIsMerged = true;
191 5 : nMergedRows = static_cast<SCROW>(sValue.toInt32());
192 5 : break;
193 : case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_COLS:
194 5 : bIsMerged = true;
195 5 : nMergedCols = static_cast<SCCOL>(sValue.toInt32());
196 5 : break;
197 : case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_COLS:
198 31 : bIsMatrix = true;
199 31 : nMatrixCols = static_cast<SCCOL>(sValue.toInt32());
200 31 : break;
201 : case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_ROWS:
202 31 : bIsMatrix = true;
203 31 : nMatrixRows = static_cast<SCROW>(sValue.toInt32());
204 31 : break;
205 : case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
206 : nColsRepeated = static_cast<SCCOL>(std::min<sal_Int32>( MAXCOLCOUNT,
207 561 : std::max( sValue.toInt32(), static_cast<sal_Int32>(1) ) ));
208 561 : break;
209 : case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE:
210 3101 : nCellType = GetScImport().GetCellType(sValue);
211 3101 : bIsEmpty = false;
212 3101 : break;
213 : case XML_TOK_TABLE_ROW_CELL_ATTR_NEW_VALUE_TYPE:
214 228 : if(sValue == "error")
215 0 : mbErrorValue = true;
216 : else
217 228 : nCellType = GetScImport().GetCellType(sValue);
218 228 : bIsEmpty = false;
219 228 : mbNewValueType = true;
220 228 : break;
221 : case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE:
222 : {
223 2430 : if (!sValue.isEmpty())
224 : {
225 2430 : ::sax::Converter::convertDouble(fValue, sValue);
226 2430 : bIsEmpty = false;
227 :
228 : //if office:value="0", let's get the text:p in case this is
229 : //a special case in HasSpecialCaseFormulaText(). If it
230 : //turns out not to be a special case, we'll use the 0 value.
231 2430 : if(fValue == 0.0)
232 64 : bFormulaTextResult = true;
233 : }
234 : }
235 2430 : break;
236 : case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE:
237 : {
238 8 : if (!sValue.isEmpty() && rXMLImport.SetNullDateOnUnitConverter())
239 : {
240 8 : rXMLImport.GetMM100UnitConverter().convertDateTime(fValue, sValue);
241 8 : bIsEmpty = false;
242 : }
243 : }
244 8 : break;
245 : case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE:
246 : {
247 3 : if (!sValue.isEmpty())
248 : {
249 3 : ::sax::Converter::convertDuration(fValue, sValue);
250 3 : bIsEmpty = false;
251 : }
252 : }
253 3 : break;
254 : case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE:
255 : {
256 32 : if (!sValue.isEmpty())
257 : {
258 : OSL_ENSURE(!maStringValue, "here should be only one string value");
259 32 : maStringValue.reset(sValue);
260 32 : bIsEmpty = false;
261 : }
262 : }
263 32 : break;
264 : case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE:
265 : {
266 142 : if (!sValue.isEmpty())
267 : {
268 142 : if ( IsXMLToken(sValue, XML_TRUE) )
269 65 : fValue = 1.0;
270 77 : else if ( IsXMLToken(sValue, XML_FALSE) )
271 75 : fValue = 0.0;
272 : else
273 2 : ::sax::Converter::convertDouble(fValue, sValue);
274 142 : bIsEmpty = false;
275 : }
276 : }
277 142 : break;
278 : case XML_TOK_TABLE_ROW_CELL_ATTR_FORMULA:
279 : {
280 395 : if (!sValue.isEmpty())
281 : {
282 : OSL_ENSURE(!maFormula, "here should be only one formula");
283 790 : OUString aFormula, aFormulaNmsp;
284 395 : rXMLImport.ExtractFormulaNamespaceGrammar( aFormula, aFormulaNmsp, eGrammar, sValue );
285 790 : maFormula.reset( FormulaWithNamespace(aFormula, aFormulaNmsp) );
286 : }
287 : }
288 395 : break;
289 : case XML_TOK_TABLE_ROW_CELL_ATTR_CURRENCY:
290 4 : pCurrencySymbol = new OUString(sValue);
291 4 : break;
292 : default:
293 : ;
294 : }
295 7799 : }
296 5652 : if (maFormula)
297 : {
298 395 : if (nCellType == util::NumberFormat::TEXT)
299 32 : bFormulaTextResult = true;
300 395 : if(nCellType == util::NumberFormat::DATETIME)
301 6 : nCellType = util::NumberFormat::UNDEFINED;
302 : //if bIsEmpty is true at this point, then there is no office value.
303 : //we must get the text:p (even if it is empty) in case this a special
304 : //case in HasSpecialCaseFormulaText().
305 395 : if(bIsEmpty)
306 0 : bFormulaTextResult = true;
307 : }
308 5652 : rXMLImport.GetStylesImportHelper()->SetAttributes(pStyleName, pCurrencySymbol, nCellType);
309 5652 : }
310 :
311 16956 : ScXMLTableRowCellContext::~ScXMLTableRowCellContext()
312 : {
313 5652 : delete pDetectiveObjVec;
314 5652 : delete pCellRangeSource;
315 11304 : }
316 :
317 8 : void ScXMLTableRowCellContext::LockSolarMutex()
318 : {
319 8 : if (!bSolarMutexLocked)
320 : {
321 8 : GetScImport().LockSolarMutex();
322 8 : bSolarMutexLocked = true;
323 : }
324 8 : }
325 :
326 5652 : void ScXMLTableRowCellContext::UnlockSolarMutex()
327 : {
328 5652 : if (bSolarMutexLocked)
329 : {
330 8 : GetScImport().UnlockSolarMutex();
331 8 : bSolarMutexLocked = false;
332 : }
333 5652 : }
334 :
335 : namespace {
336 :
337 17103 : bool cellExists( const ScAddress& rCellPos )
338 : {
339 51309 : return( rCellPos.Col() >= 0 && rCellPos.Row() >= 0 &&
340 51309 : rCellPos.Col() <= MAXCOL && rCellPos.Row() <= MAXROW );
341 : }
342 :
343 : }
344 :
345 3127 : void ScXMLTableRowCellContext::PushParagraphSpan(const OUString& rSpan, const OUString& rStyleName)
346 : {
347 3127 : sal_Int32 nBegin = maParagraph.getLength();
348 3127 : sal_Int32 nEnd = nBegin + rSpan.getLength();
349 3127 : maParagraph.append(rSpan);
350 :
351 3127 : PushFormat(nBegin, nEnd, rStyleName);
352 3127 : }
353 :
354 9 : void ScXMLTableRowCellContext::PushParagraphField(SvxFieldData* pData, const OUString& rStyleName)
355 : {
356 9 : maFields.push_back(new Field(pData));
357 9 : Field& rField = maFields.back();
358 :
359 9 : sal_Int32 nPos = maParagraph.getLength();
360 9 : maParagraph.append(sal_Unicode('\1')); // Placeholder text for inserted field item.
361 9 : rField.maSelection.nStartPara = mnCurParagraph;
362 9 : rField.maSelection.nEndPara = mnCurParagraph;
363 9 : rField.maSelection.nStartPos = nPos;
364 9 : rField.maSelection.nEndPos = nPos+1;
365 :
366 9 : PushFormat(nPos, nPos+1, rStyleName);
367 9 : }
368 :
369 3136 : void ScXMLTableRowCellContext::PushFormat(sal_Int32 nBegin, sal_Int32 nEnd, const OUString& rStyleName)
370 : {
371 3136 : if (rStyleName.isEmpty())
372 6240 : return;
373 :
374 : // Get the style information from xmloff.
375 16 : UniReference<XMLPropertySetMapper> xMapper = GetImport().GetTextImport()->GetTextImportPropertySetMapper()->getPropertySetMapper();
376 16 : if (!xMapper.is())
377 : // We can't do anything without the mapper.
378 0 : return;
379 :
380 16 : sal_Int32 nEntryCount = xMapper->GetEntryCount();
381 :
382 16 : SvXMLStylesContext* pAutoStyles = GetImport().GetAutoStyles();
383 :
384 : // Style name for text span corresponds with the name of an automatic style.
385 : const XMLPropStyleContext* pStyle = dynamic_cast<const XMLPropStyleContext*>(
386 16 : pAutoStyles->FindStyleChildContext(XML_STYLE_FAMILY_TEXT_TEXT, rStyleName));
387 :
388 16 : if (!pStyle)
389 : // No style by that name found.
390 0 : return;
391 :
392 16 : const std::vector<XMLPropertyState>& rProps = pStyle->GetProperties();
393 16 : if (rProps.empty())
394 0 : return;
395 :
396 16 : const ScXMLEditAttributeMap& rEditAttrMap = GetScImport().GetEditAttributeMap();
397 :
398 16 : maFormats.push_back(new ParaFormat(*mpEditEngine));
399 16 : ParaFormat& rFmt = maFormats.back();
400 16 : rFmt.maSelection.nStartPara = rFmt.maSelection.nEndPara = mnCurParagraph;
401 16 : rFmt.maSelection.nStartPos = nBegin;
402 16 : rFmt.maSelection.nEndPos = nEnd;
403 :
404 32 : boost::scoped_ptr<SfxPoolItem> pPoolItem;
405 16 : sal_uInt16 nLastItemID = EE_CHAR_END + 1;
406 :
407 16 : std::vector<XMLPropertyState>::const_iterator it = rProps.begin(), itEnd = rProps.end();
408 148 : for (; it != itEnd; ++it)
409 : {
410 132 : if (it->mnIndex == -1 || it->mnIndex >= nEntryCount)
411 0 : continue;
412 :
413 132 : const OUString& rName = xMapper->GetEntryAPIName(it->mnIndex);
414 132 : const ScXMLEditAttributeMap::Entry* pEntry = rEditAttrMap.getEntry(rName);
415 132 : if (!pEntry)
416 6 : continue;
417 :
418 126 : if (nLastItemID != pEntry->mnItemID && pPoolItem)
419 : {
420 : // Flush the last item when the item ID changes.
421 41 : rFmt.maItemSet.Put(*pPoolItem);
422 41 : pPoolItem.reset();
423 : }
424 :
425 126 : switch (pEntry->mnItemID)
426 : {
427 : case EE_CHAR_FONTINFO:
428 : case EE_CHAR_FONTINFO_CJK:
429 : case EE_CHAR_FONTINFO_CTL:
430 : {
431 : // Font properties need to be consolidated into a single item.
432 84 : if (!pPoolItem)
433 18 : pPoolItem.reset(new SvxFontItem(pEntry->mnItemID));
434 :
435 84 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
436 : }
437 84 : break;
438 : case EE_CHAR_WEIGHT:
439 : case EE_CHAR_WEIGHT_CJK:
440 : case EE_CHAR_WEIGHT_CTL:
441 : {
442 15 : if (!pPoolItem)
443 15 : pPoolItem.reset(new SvxWeightItem(WEIGHT_NORMAL, pEntry->mnItemID));
444 :
445 15 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
446 : }
447 15 : break;
448 : case EE_CHAR_FONTHEIGHT:
449 : case EE_CHAR_FONTHEIGHT_CJK:
450 : case EE_CHAR_FONTHEIGHT_CTL:
451 : {
452 6 : if (!pPoolItem)
453 6 : pPoolItem.reset(new SvxFontHeightItem(240, 100, pEntry->mnItemID));
454 :
455 6 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
456 : }
457 6 : break;
458 : case EE_CHAR_ITALIC:
459 : case EE_CHAR_ITALIC_CJK:
460 : case EE_CHAR_ITALIC_CTL:
461 : {
462 12 : if (!pPoolItem)
463 12 : pPoolItem.reset(new SvxPostureItem(ITALIC_NONE, pEntry->mnItemID));
464 :
465 12 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
466 : }
467 12 : break;
468 : case EE_CHAR_UNDERLINE:
469 : {
470 6 : if (!pPoolItem)
471 3 : pPoolItem.reset(new SvxUnderlineItem(UNDERLINE_NONE, pEntry->mnItemID));
472 :
473 6 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
474 : }
475 6 : break;
476 : case EE_CHAR_OVERLINE:
477 : {
478 0 : if (!pPoolItem)
479 0 : pPoolItem.reset(new SvxOverlineItem(UNDERLINE_NONE, pEntry->mnItemID));
480 :
481 0 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
482 : }
483 0 : break;
484 : case EE_CHAR_COLOR:
485 : {
486 2 : if (!pPoolItem)
487 2 : pPoolItem.reset(new SvxColorItem(pEntry->mnItemID));
488 :
489 2 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
490 : }
491 2 : break;
492 : case EE_CHAR_WLM:
493 : {
494 0 : if (!pPoolItem)
495 0 : pPoolItem.reset(new SvxWordLineModeItem(false, pEntry->mnItemID));
496 :
497 0 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
498 : }
499 0 : break;
500 : case EE_CHAR_STRIKEOUT:
501 : {
502 1 : if (!pPoolItem)
503 1 : pPoolItem.reset(new SvxCrossedOutItem(STRIKEOUT_NONE, pEntry->mnItemID));
504 :
505 1 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
506 : }
507 1 : break;
508 : case EE_CHAR_RELIEF:
509 : {
510 0 : if (!pPoolItem)
511 0 : pPoolItem.reset(new SvxCharReliefItem(RELIEF_NONE, pEntry->mnItemID));
512 :
513 0 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
514 : }
515 0 : break;
516 : case EE_CHAR_OUTLINE:
517 : {
518 0 : if (!pPoolItem)
519 0 : pPoolItem.reset(new SvxContourItem(false, pEntry->mnItemID));
520 :
521 0 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
522 : }
523 0 : break;
524 : case EE_CHAR_SHADOW:
525 : {
526 0 : if (!pPoolItem)
527 0 : pPoolItem.reset(new SvxShadowedItem(false, pEntry->mnItemID));
528 :
529 0 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
530 : }
531 0 : break;
532 : case EE_CHAR_KERNING:
533 : {
534 0 : if (!pPoolItem)
535 0 : pPoolItem.reset(new SvxKerningItem(0, pEntry->mnItemID));
536 :
537 0 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
538 : }
539 0 : break;
540 : case EE_CHAR_PAIRKERNING:
541 : {
542 0 : if (!pPoolItem)
543 0 : pPoolItem.reset(new SvxAutoKernItem(false, pEntry->mnItemID));
544 :
545 0 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
546 : }
547 0 : break;
548 : case EE_CHAR_FONTWIDTH:
549 : {
550 0 : if (!pPoolItem)
551 0 : pPoolItem.reset(new SvxCharScaleWidthItem(100, pEntry->mnItemID));
552 :
553 0 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
554 : }
555 0 : break;
556 : case EE_CHAR_ESCAPEMENT:
557 : {
558 0 : if (!pPoolItem)
559 0 : pPoolItem.reset(new SvxEscapementItem(pEntry->mnItemID));
560 :
561 0 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
562 : }
563 0 : break;
564 : case EE_CHAR_EMPHASISMARK:
565 : {
566 0 : if (!pPoolItem)
567 0 : pPoolItem.reset(new SvxEmphasisMarkItem(EMPHASISMARK_NONE, pEntry->mnItemID));
568 :
569 0 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
570 : }
571 0 : break;
572 : case EE_CHAR_LANGUAGE:
573 : case EE_CHAR_LANGUAGE_CJK:
574 : case EE_CHAR_LANGUAGE_CTL:
575 : {
576 0 : if (!pPoolItem)
577 0 : pPoolItem.reset(new SvxLanguageItem(LANGUAGE_DONTKNOW, pEntry->mnItemID));
578 :
579 0 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
580 : }
581 0 : break;
582 : default:
583 : ;
584 : }
585 :
586 126 : nLastItemID = pEntry->mnItemID;
587 : }
588 :
589 16 : if (pPoolItem)
590 32 : rFmt.maItemSet.Put(*pPoolItem);
591 : }
592 :
593 2 : void ScXMLTableRowCellContext::PushParagraphFieldDate(const OUString& rStyleName)
594 : {
595 2 : PushParagraphField(new SvxDateField, rStyleName);
596 2 : }
597 :
598 2 : void ScXMLTableRowCellContext::PushParagraphFieldSheetName(const OUString& rStyleName)
599 : {
600 2 : SCTAB nTab = GetScImport().GetTables().GetCurrentCellPos().Tab();
601 2 : PushParagraphField(new SvxTableField(nTab), rStyleName);
602 2 : }
603 :
604 2 : void ScXMLTableRowCellContext::PushParagraphFieldDocTitle(const OUString& rStyleName)
605 : {
606 2 : PushParagraphField(new SvxFileField, rStyleName);
607 2 : }
608 :
609 3 : void ScXMLTableRowCellContext::PushParagraphFieldURL(
610 : const OUString& rURL, const OUString& rRep, const OUString& rStyleName)
611 : {
612 3 : OUString aAbsURL = GetScImport().GetAbsoluteReference(rURL);
613 3 : PushParagraphField(new SvxURLField(aAbsURL, rRep, SVXURLFORMAT_REPR), rStyleName);
614 3 : }
615 :
616 3119 : void ScXMLTableRowCellContext::PushParagraphEnd()
617 : {
618 : // EditEngine always has at least one paragraph even when its content is empty.
619 :
620 3119 : if (mbEditEngineHasText)
621 13 : mpEditEngine->InsertParagraph(mpEditEngine->GetParagraphCount(), maParagraph.makeStringAndClear());
622 : else
623 : {
624 3106 : mpEditEngine->SetText(maParagraph.makeStringAndClear());
625 3106 : mbEditEngineHasText = true;
626 : }
627 :
628 3119 : ++mnCurParagraph;
629 3119 : }
630 :
631 3179 : SvXMLImportContext *ScXMLTableRowCellContext::CreateChildContext( sal_uInt16 nPrefix,
632 : const OUString& rLName,
633 : const ::com::sun::star::uno::Reference<
634 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
635 : {
636 3179 : SvXMLImportContext *pContext = 0;
637 :
638 3179 : const SvXMLTokenMap& rTokenMap = rXMLImport.GetTableRowCellElemTokenMap();
639 3179 : bool bTextP(false);
640 3179 : switch( rTokenMap.Get( nPrefix, rLName ) )
641 : {
642 : case XML_TOK_TABLE_ROW_CELL_P:
643 : {
644 3119 : bIsEmpty = false;
645 3119 : bTextP = true;
646 :
647 3119 : pContext = new ScXMLCellTextParaContext(rXMLImport, nPrefix, rLName, *this);
648 : }
649 3119 : break;
650 : case XML_TOK_TABLE_ROW_CELL_TABLE:
651 : {
652 : SAL_WARN("sc", "ScXMLTableRowCellContext::CreateChildContext: subtables are not supported");
653 : }
654 0 : break;
655 : case XML_TOK_TABLE_ROW_CELL_ANNOTATION:
656 : {
657 8 : bIsEmpty = false;
658 : OSL_ENSURE( !mxAnnotationData.get(), "ScXMLTableRowCellContext::CreateChildContext - multiple annotations in one cell" );
659 8 : mxAnnotationData.reset( new ScXMLAnnotationData );
660 : pContext = new ScXMLAnnotationContext( rXMLImport, nPrefix, rLName,
661 8 : xAttrList, *mxAnnotationData, this);
662 : }
663 8 : break;
664 : case XML_TOK_TABLE_ROW_CELL_DETECTIVE:
665 : {
666 0 : bIsEmpty = false;
667 0 : if (!pDetectiveObjVec)
668 0 : pDetectiveObjVec = new ScMyImpDetectiveObjVec();
669 : pContext = new ScXMLDetectiveContext(
670 0 : rXMLImport, nPrefix, rLName, pDetectiveObjVec );
671 : }
672 0 : break;
673 : case XML_TOK_TABLE_ROW_CELL_CELL_RANGE_SOURCE:
674 : {
675 0 : bIsEmpty = false;
676 0 : if (!pCellRangeSource)
677 0 : pCellRangeSource = new ScMyImpCellRangeSource();
678 : pContext = new ScXMLCellRangeSourceContext(
679 0 : rXMLImport, nPrefix, rLName, xAttrList, pCellRangeSource );
680 : }
681 0 : break;
682 : }
683 :
684 3179 : if (!pContext && !bTextP)
685 : {
686 52 : ScAddress aCellPos = rXMLImport.GetTables().GetCurrentCellPos();
687 52 : uno::Reference<drawing::XShapes> xShapes (rXMLImport.GetTables().GetCurrentXShapes());
688 52 : if (xShapes.is())
689 : {
690 52 : if (aCellPos.Col() > MAXCOL)
691 0 : aCellPos.SetCol(MAXCOL);
692 52 : if (aCellPos.Row() > MAXROW)
693 0 : aCellPos.SetRow(MAXROW);
694 : XMLTableShapeImportHelper* pTableShapeImport =
695 52 : static_cast< XMLTableShapeImportHelper* >( rXMLImport.GetShapeImport().get() );
696 52 : pTableShapeImport->SetOnTable(false);
697 52 : com::sun::star::table::CellAddress aCellAddress;
698 52 : ScUnoConversion::FillApiAddress( aCellAddress, aCellPos );
699 52 : pTableShapeImport->SetCell(aCellAddress);
700 : pContext = rXMLImport.GetShapeImport()->CreateGroupChildContext(
701 52 : rXMLImport, nPrefix, rLName, xAttrList, xShapes);
702 52 : if (pContext)
703 : {
704 52 : bIsEmpty = false;
705 52 : rXMLImport.ProgressBarIncrement(false);
706 : }
707 52 : }
708 : }
709 :
710 3179 : if( !pContext )
711 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
712 :
713 3179 : return pContext;
714 : }
715 :
716 5 : void ScXMLTableRowCellContext::DoMerge( const ScAddress& rScAddress, const SCCOL nCols, const SCROW nRows )
717 : {
718 5 : SCCOL mergeToCol = rScAddress.Col() + nCols;
719 5 : SCROW mergeToRow = rScAddress.Row() + nRows;
720 10 : bool bInBounds = rScAddress.Col() <= MAXCOL && rScAddress.Row() <= MAXROW &&
721 10 : mergeToCol <= MAXCOL && mergeToRow <= MAXROW;
722 5 : if( bInBounds )
723 : {
724 5 : rXMLImport.GetDocument()->DoMerge( rScAddress.Tab(),
725 10 : rScAddress.Col(), rScAddress.Row(), mergeToCol, mergeToRow );
726 : }
727 5 : }
728 :
729 : namespace {
730 :
731 14 : ScValidationMode validationTypeToMode( const sheet::ValidationType eVType )
732 : {
733 : ScValidationMode eMode;
734 14 : switch( eVType )
735 : {
736 10 : case sheet::ValidationType_WHOLE: eMode = SC_VALID_WHOLE; break;
737 4 : case sheet::ValidationType_DECIMAL: eMode = SC_VALID_DECIMAL; break;
738 0 : case sheet::ValidationType_DATE: eMode = SC_VALID_DATE; break;
739 0 : case sheet::ValidationType_TIME: eMode = SC_VALID_TIME; break;
740 0 : case sheet::ValidationType_TEXT_LEN: eMode = SC_VALID_TEXTLEN; break;
741 0 : case sheet::ValidationType_LIST: eMode = SC_VALID_LIST; break;
742 0 : case sheet::ValidationType_CUSTOM: eMode = SC_VALID_CUSTOM; break;
743 0 : default: eMode = SC_VALID_ANY; break;
744 : }
745 14 : return eMode;
746 : }
747 :
748 14 : ScValidErrorStyle validAlertToValidError( const sheet::ValidationAlertStyle eVAlertStyle )
749 : {
750 : ScValidErrorStyle eVErrStyle;
751 14 : switch( eVAlertStyle )
752 : {
753 10 : case sheet::ValidationAlertStyle_STOP: eVErrStyle = SC_VALERR_STOP; break;
754 4 : case sheet::ValidationAlertStyle_WARNING: eVErrStyle = SC_VALERR_WARNING; break;
755 0 : case sheet::ValidationAlertStyle_MACRO: eVErrStyle = SC_VALERR_MACRO; break;
756 0 : default: eVErrStyle = SC_VALERR_INFO; break;
757 : //should INFO be the default? seems to be the most unobtrusive choice.
758 : }
759 14 : return eVErrStyle;
760 : }
761 :
762 : }
763 :
764 5652 : void ScXMLTableRowCellContext::SetContentValidation( const ScRange& rScRange )
765 : {
766 5652 : if (maContentValidationName)
767 : {
768 14 : ScDocument* pDoc = rXMLImport.GetDocument();
769 14 : ScMyImportValidation aValidation;
770 14 : aValidation.eGrammar1 = aValidation.eGrammar2 = pDoc->GetStorageGrammar();
771 14 : if( rXMLImport.GetValidation(*maContentValidationName, aValidation) )
772 : {
773 : ScValidationData aScValidationData(
774 : validationTypeToMode(aValidation.aValidationType),
775 : ScConditionEntry::GetModeFromApi(static_cast<sal_Int32>(aValidation.aOperator)),
776 : aValidation.sFormula1, aValidation.sFormula2, pDoc, ScAddress(),
777 : aValidation.sFormulaNmsp1, aValidation.sFormulaNmsp2,
778 : aValidation.eGrammar1, aValidation.eGrammar2
779 14 : );
780 :
781 14 : aScValidationData.SetIgnoreBlank( aValidation.bIgnoreBlanks );
782 14 : aScValidationData.SetListType( aValidation.nShowList );
783 :
784 : // set strings for error / input even if disabled (and disable afterwards)
785 14 : aScValidationData.SetInput( aValidation.sImputTitle, aValidation.sImputMessage );
786 14 : if( !aValidation.bShowImputMessage )
787 14 : aScValidationData.ResetInput();
788 14 : aScValidationData.SetError( aValidation.sErrorTitle, aValidation.sErrorMessage, validAlertToValidError(aValidation.aAlertStyle) );
789 14 : if( !aValidation.bShowErrorMessage )
790 0 : aScValidationData.ResetError();
791 :
792 14 : if( !aValidation.sBaseCellAddress.isEmpty() )
793 14 : aScValidationData.SetSrcString( aValidation.sBaseCellAddress );
794 :
795 14 : sal_uLong nIndex = pDoc->AddValidationEntry( aScValidationData );
796 :
797 28 : ScPatternAttr aPattern( pDoc->GetPool() );
798 14 : aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_VALIDDATA, nIndex ) );
799 14 : if( rScRange.aStart == rScRange.aEnd ) //for a single cell
800 : {
801 9 : pDoc->ApplyPattern( rScRange.aStart.Col(), rScRange.aStart.Row(),
802 18 : rScRange.aStart.Tab(), aPattern );
803 : }
804 : else //for repeating cells
805 : {
806 5 : pDoc->ApplyPatternAreaTab( rScRange.aStart.Col(), rScRange.aStart.Row(),
807 5 : rScRange.aEnd.Col(), rScRange.aEnd.Row(),
808 15 : rScRange.aStart.Tab(), aPattern );
809 : }
810 :
811 : // is the below still needed?
812 : // For now, any sheet with validity is blocked from stream-copying.
813 : // Later, the validation names could be stored along with the style names.
814 14 : ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetImport().GetModel())->GetSheetSaveData();
815 28 : pSheetData->BlockSheet( GetScImport().GetTables().GetCurrentSheet() );
816 14 : }
817 : }
818 5652 : }
819 :
820 5073 : void ScXMLTableRowCellContext::SetContentValidation( const ScAddress& rCellPos )
821 : {
822 5073 : SetContentValidation( ScRange(rCellPos, rCellPos) );
823 5073 : }
824 :
825 3124 : void ScXMLTableRowCellContext::SetAnnotation(const ScAddress& rPos)
826 : {
827 3124 : ScDocument* pDoc = rXMLImport.GetDocument();
828 3124 : if( !pDoc || !mxAnnotationData.get() )
829 6240 : return;
830 :
831 8 : LockSolarMutex();
832 :
833 8 : ScPostIt* pNote = 0;
834 :
835 8 : uno::Reference< drawing::XShapes > xShapes = rXMLImport.GetTables().GetCurrentXShapes();
836 16 : uno::Reference< container::XIndexAccess > xShapesIA( xShapes, uno::UNO_QUERY );
837 8 : sal_Int32 nOldShapeCount = xShapesIA.is() ? xShapesIA->getCount() : 0;
838 :
839 : OSL_ENSURE( !mxAnnotationData->mxShape.is() || mxAnnotationData->mxShapes.is(),
840 : "ScXMLTableRowCellContext::SetAnnotation - shape without drawing page" );
841 8 : if( mxAnnotationData->mxShape.is() && mxAnnotationData->mxShapes.is() )
842 : {
843 : OSL_ENSURE( mxAnnotationData->mxShapes.get() == xShapes.get(), "ScXMLTableRowCellContext::SetAnnotation - diffenet drawing pages" );
844 8 : SdrObject* pObject = ::GetSdrObjectFromXShape( mxAnnotationData->mxShape );
845 : OSL_ENSURE( pObject, "ScXMLTableRowCellContext::SetAnnotation - cannot get SdrObject from shape" );
846 :
847 : /* Try to reuse the drawing object already created (but only if the
848 : note is visible, and the object is a caption object). */
849 8 : if( mxAnnotationData->mbShown && mxAnnotationData->mbUseShapePos )
850 : {
851 2 : if( SdrCaptionObj* pCaption = dynamic_cast< SdrCaptionObj* >( pObject ) )
852 : {
853 : OSL_ENSURE( !pCaption->GetLogicRect().IsEmpty(), "ScXMLTableRowCellContext::SetAnnotation - invalid caption rectangle" );
854 : // create the cell note with the caption object
855 2 : pNote = ScNoteUtil::CreateNoteFromCaption( *pDoc, rPos, *pCaption, true );
856 : // forget pointer to object (do not create note again below)
857 2 : pObject = 0;
858 : }
859 : }
860 :
861 : // drawing object has not been used to create a note -> use shape data
862 8 : if( pObject )
863 : {
864 : // rescue settings from drawing object before the shape is removed
865 6 : ::std::auto_ptr< SfxItemSet > xItemSet( new SfxItemSet( pObject->GetMergedItemSet() ) );
866 12 : ::std::auto_ptr< OutlinerParaObject > xOutlinerObj;
867 6 : if( OutlinerParaObject* pOutlinerObj = pObject->GetOutlinerParaObject() )
868 6 : xOutlinerObj.reset( new OutlinerParaObject( *pOutlinerObj ) );
869 6 : Rectangle aCaptionRect;
870 6 : if( mxAnnotationData->mbUseShapePos )
871 1 : aCaptionRect = pObject->GetLogicRect();
872 : // remove the shape from the drawing page, this invalidates pObject
873 6 : mxAnnotationData->mxShapes->remove( mxAnnotationData->mxShape );
874 6 : pObject = 0;
875 : // update current number of existing objects
876 6 : if( xShapesIA.is() )
877 6 : nOldShapeCount = xShapesIA->getCount();
878 :
879 : // an outliner object is required (empty note captions not allowed)
880 6 : if( xOutlinerObj.get() )
881 : {
882 : // create cell note with all data from drawing object
883 : pNote = ScNoteUtil::CreateNoteFromObjectData( *pDoc, rPos,
884 : xItemSet.release(), xOutlinerObj.release(),
885 6 : aCaptionRect, mxAnnotationData->mbShown, false );
886 6 : }
887 : }
888 : }
889 0 : else if( !mxAnnotationData->maSimpleText.isEmpty() )
890 : {
891 : // create note from simple text
892 : pNote = ScNoteUtil::CreateNoteFromString( *pDoc, rPos,
893 0 : mxAnnotationData->maSimpleText, mxAnnotationData->mbShown, false );
894 : }
895 :
896 : // set author and date
897 8 : if( pNote )
898 : {
899 : double fDate;
900 8 : rXMLImport.GetMM100UnitConverter().convertDateTime( fDate, mxAnnotationData->maCreateDate );
901 8 : SvNumberFormatter* pNumForm = pDoc->GetFormatTable();
902 8 : sal_uInt32 nfIndex = pNumForm->GetFormatIndex( NF_DATE_SYS_DDMMYYYY, LANGUAGE_SYSTEM );
903 8 : OUString aDate;
904 8 : Color* pColor = 0;
905 8 : Color** ppColor = &pColor;
906 8 : pNumForm->GetOutputString( fDate, nfIndex, aDate, ppColor );
907 8 : pNote->SetDate( aDate );
908 8 : pNote->SetAuthor( mxAnnotationData->maAuthor );
909 : }
910 :
911 : // register a shape that has been newly created in the ScNoteUtil functions
912 8 : if( xShapesIA.is() && (nOldShapeCount < xShapesIA->getCount()) )
913 : {
914 5 : uno::Reference< drawing::XShape > xShape;
915 5 : rXMLImport.GetShapeImport()->shapeWithZIndexAdded( xShape, xShapesIA->getCount() );
916 : }
917 :
918 : // store the style names for stream copying
919 8 : ScSheetSaveData* pSheetData = ScModelObj::getImplementation(rXMLImport.GetModel())->GetSheetSaveData();
920 8 : pSheetData->HandleNoteStyles( mxAnnotationData->maStyleName, mxAnnotationData->maTextStyle, rPos );
921 :
922 8 : std::vector<ScXMLAnnotationStyleEntry>::const_iterator aIter = mxAnnotationData->maContentStyles.begin();
923 8 : std::vector<ScXMLAnnotationStyleEntry>::const_iterator aEnd = mxAnnotationData->maContentStyles.end();
924 23 : while (aIter != aEnd)
925 : {
926 7 : pSheetData->AddNoteContentStyle( aIter->mnFamily, aIter->maName, rPos, aIter->maSelection );
927 7 : ++aIter;
928 8 : }
929 : }
930 :
931 : // core implementation
932 3124 : void ScXMLTableRowCellContext::SetDetectiveObj( const ScAddress& rPosition )
933 : {
934 3124 : if( cellExists(rPosition) && pDetectiveObjVec && pDetectiveObjVec->size() )
935 : {
936 0 : LockSolarMutex();
937 0 : ScDetectiveFunc aDetFunc( rXMLImport.GetDocument(), rPosition.Tab() );
938 0 : uno::Reference<container::XIndexAccess> xShapesIndex (rXMLImport.GetTables().GetCurrentXShapes(), uno::UNO_QUERY); // make draw page
939 0 : ScMyImpDetectiveObjVec::iterator aItr(pDetectiveObjVec->begin());
940 0 : ScMyImpDetectiveObjVec::iterator aEndItr(pDetectiveObjVec->end());
941 0 : while(aItr != aEndItr)
942 : {
943 0 : aDetFunc.InsertObject( aItr->eObjType, rPosition, aItr->aSourceRange, aItr->bHasError );
944 0 : if (xShapesIndex.is())
945 : {
946 0 : sal_Int32 nShapes = xShapesIndex->getCount();
947 0 : uno::Reference < drawing::XShape > xShape;
948 0 : rXMLImport.GetShapeImport()->shapeWithZIndexAdded(xShape, nShapes);
949 : }
950 0 : ++aItr;
951 0 : }
952 : }
953 3124 : }
954 :
955 : // core implementation
956 3124 : void ScXMLTableRowCellContext::SetCellRangeSource( const ScAddress& rPosition )
957 : {
958 9372 : if( cellExists(rPosition) && pCellRangeSource && !pCellRangeSource->sSourceStr.isEmpty() &&
959 3124 : !pCellRangeSource->sFilterName.isEmpty() && !pCellRangeSource->sURL.isEmpty() )
960 : {
961 0 : ScDocument* pDoc = rXMLImport.GetDocument();
962 0 : if (pDoc)
963 : {
964 0 : LockSolarMutex();
965 0 : ScRange aDestRange( rPosition.Col(), rPosition.Row(), rPosition.Tab(),
966 0 : rPosition.Col() + static_cast<SCCOL>(pCellRangeSource->nColumns - 1),
967 0 : rPosition.Row() + static_cast<SCROW>(pCellRangeSource->nRows - 1), rPosition.Tab() );
968 0 : String sFilterName( pCellRangeSource->sFilterName );
969 0 : String sSourceStr( pCellRangeSource->sSourceStr );
970 : ScAreaLink* pLink = new ScAreaLink( pDoc->GetDocumentShell(), pCellRangeSource->sURL,
971 0 : sFilterName, pCellRangeSource->sFilterOptions, sSourceStr, aDestRange, pCellRangeSource->nRefresh );
972 0 : sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
973 0 : pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, pCellRangeSource->sURL, &sFilterName, &sSourceStr );
974 : }
975 : }
976 3124 : }
977 :
978 401 : void ScXMLTableRowCellContext::SetFormulaCell(ScFormulaCell* pFCell) const
979 : {
980 401 : if(pFCell)
981 : {
982 401 : if(mbErrorValue)
983 : {
984 : // don't do anything here
985 : // we need to recalc anyway
986 : }
987 401 : else if( bFormulaTextResult && maStringValue )
988 : {
989 49 : if( !IsPossibleErrorString() )
990 : {
991 26 : pFCell->SetHybridString( *maStringValue );
992 26 : pFCell->ResetDirty();
993 : }
994 : }
995 352 : else if (!rtl::math::isNan(fValue))
996 : {
997 352 : pFCell->SetHybridDouble(fValue);
998 352 : pFCell->ResetDirty();
999 : }
1000 401 : pFCell->StartListeningTo(rXMLImport.GetDocument());
1001 : }
1002 401 : }
1003 :
1004 515 : void ScXMLTableRowCellContext::PutTextCell( const ScAddress& rCurrentPos,
1005 : const SCCOL nCurrentCol, const ::boost::optional< OUString >& pOUText )
1006 : {
1007 515 : bool bDoIncrement = true;
1008 : //matrix reference cells that contain text formula results;
1009 : //cell was already put in document, just need to set text here.
1010 515 : if( rXMLImport.GetTables().IsPartOfMatrix(rCurrentPos) )
1011 : {
1012 16 : bDoIncrement = rXMLImport.GetDocument()->GetCellType(rCurrentPos) == CELLTYPE_FORMULA;
1013 16 : if ( bDoIncrement )
1014 : {
1015 16 : ScFormulaCell* pFCell = rXMLImport.GetDocument()->GetFormulaCell(rCurrentPos);
1016 16 : OUString aCellString;
1017 16 : if (maStringValue)
1018 16 : aCellString = *maStringValue;
1019 0 : else if (mbEditEngineHasText)
1020 0 : aCellString = mpEditEngine->GetText(0);
1021 0 : else if ( nCurrentCol > 0 && pOUText && !pOUText->isEmpty() )
1022 0 : aCellString = *pOUText;
1023 : else
1024 0 : bDoIncrement = false;
1025 :
1026 16 : if(mbErrorValue)
1027 0 : bDoIncrement = false;
1028 :
1029 16 : if(!aCellString.isEmpty())
1030 : {
1031 12 : if (bDoIncrement && !IsPossibleErrorString())
1032 : {
1033 0 : pFCell->SetHybridString( aCellString );
1034 0 : pFCell->ResetDirty();
1035 : }
1036 : else
1037 : {
1038 12 : ScAddress aTopLeftMatrixCell;
1039 12 : if(pFCell->GetMatrixOrigin(aTopLeftMatrixCell))
1040 : {
1041 12 : ScFormulaCell* pMatrixCell = rXMLImport.GetDocument()->GetFormulaCell(aTopLeftMatrixCell);
1042 12 : pMatrixCell->SetDirty();
1043 : }
1044 : else
1045 : SAL_WARN("sc", "matrix cell without matrix");
1046 : }
1047 : }
1048 16 : pFCell->StartListeningTo(rXMLImport.GetDocument());
1049 : }
1050 : }
1051 : else //regular text cells
1052 : {
1053 499 : ScDocument* pDoc = rXMLImport.GetDocument();
1054 499 : if (maStringValue)
1055 : {
1056 0 : pDoc->SetTextCell(rCurrentPos, *maStringValue);
1057 0 : bDoIncrement = true;
1058 : }
1059 499 : else if (mbEditEngineHasText)
1060 : {
1061 496 : if (maFields.empty() && maFormats.empty() && mpEditEngine->GetParagraphCount() == 1)
1062 : {
1063 : // This is a normal text without format runs.
1064 478 : ScSetStringParam aParam;
1065 478 : aParam.setTextInput();
1066 478 : pDoc->SetString(rCurrentPos, mpEditEngine->GetText(), &aParam);
1067 : }
1068 : else
1069 : {
1070 : // This text either has format runs, has field(s), or consists of multiple lines.
1071 : {
1072 18 : ParaFormatsType::const_iterator it = maFormats.begin(), itEnd = maFormats.end();
1073 34 : for (; it != itEnd; ++it)
1074 16 : mpEditEngine->QuickSetAttribs(it->maItemSet, it->maSelection);
1075 : }
1076 :
1077 : {
1078 18 : FieldsType::const_iterator it = maFields.begin(), itEnd = maFields.end();
1079 27 : for (; it != itEnd; ++it)
1080 9 : mpEditEngine->QuickInsertField(SvxFieldItem(*it->mpData, EE_FEATURE_FIELD), it->maSelection);
1081 : }
1082 :
1083 : // This edit engine uses the SfxItemPool instance returned
1084 : // from pDoc->GetEditPool() to create the text object, which
1085 : // is a prerequisite for using this constructor of ScEditCell.
1086 18 : pDoc->SetEditText(rCurrentPos, mpEditEngine->CreateTextObject());
1087 : }
1088 496 : bDoIncrement = true;
1089 : }
1090 3 : else if ( nCurrentCol > 0 && pOUText && !pOUText->isEmpty() )
1091 : {
1092 0 : pDoc->SetTextCell(rCurrentPos, *pOUText);
1093 0 : bDoIncrement = true;
1094 : }
1095 : else
1096 3 : bDoIncrement = false;
1097 : }
1098 :
1099 : // #i56027# This is about setting simple text, not edit cells,
1100 : // so ProgressBarIncrement must be called with bEditCell = FALSE.
1101 : // Formatted text that is put into the cell by the child context
1102 : // is handled in AddCellsToTable() (bIsEmpty is true then).
1103 515 : if (bDoIncrement)
1104 512 : rXMLImport.ProgressBarIncrement(false);
1105 515 : }
1106 :
1107 2214 : void ScXMLTableRowCellContext::PutValueCell( const ScAddress& rCurrentPos )
1108 : {
1109 : //matrix reference cells that contain value formula results;
1110 : //cell was already put in document, just need to set value here.
1111 2214 : if( rXMLImport.GetTables().IsPartOfMatrix(rCurrentPos) )
1112 : {
1113 37 : if (rXMLImport.GetDocument()->GetCellType(rCurrentPos) == CELLTYPE_FORMULA)
1114 : {
1115 37 : ScFormulaCell* pFCell = rXMLImport.GetDocument()->GetFormulaCell(rCurrentPos);
1116 37 : SetFormulaCell(pFCell);
1117 37 : pFCell->SetNeedNumberFormat( true );
1118 : }
1119 : }
1120 : else //regular value cell
1121 : {
1122 : // #i62435# Initialize the value cell's script type if the default
1123 : // style's number format is latin-only. If the cell uses a different
1124 : // format, the script type will be reset when the style is applied.
1125 :
1126 2177 : ScDocument* pDoc = rXMLImport.GetDocument();
1127 2177 : pDoc->SetValue(rCurrentPos, fValue);
1128 2177 : if ( rXMLImport.IsLatinDefaultStyle() )
1129 2177 : pDoc->SetScriptType(rCurrentPos, SCRIPTTYPE_LATIN);
1130 : }
1131 2214 : rXMLImport.ProgressBarIncrement(false);
1132 2214 : }
1133 :
1134 : namespace {
1135 :
1136 0 : bool isEmptyOrNote( ScDocument* pDoc, const ScAddress& rCurrentPos )
1137 : {
1138 0 : CellType eType = pDoc->GetCellType(rCurrentPos);
1139 0 : return (eType == CELLTYPE_NONE);
1140 : }
1141 :
1142 : }
1143 :
1144 5257 : void ScXMLTableRowCellContext::AddTextAndValueCell( const ScAddress& rCellPos,
1145 : const ::boost::optional< OUString >& pOUText, ScAddress& rCurrentPos )
1146 : {
1147 5257 : ScMyTables& rTables = rXMLImport.GetTables();
1148 5257 : bool bWasEmpty = bIsEmpty;
1149 35232 : for (SCCOL i = 0; i < nColsRepeated; ++i)
1150 : {
1151 29975 : rCurrentPos.SetCol( rCellPos.Col() + i );
1152 :
1153 : // it makes no sense to import data after the last supported column
1154 : // fdo#58539 & gnome#627150
1155 29975 : if(rCurrentPos.Col() > MAXCOL)
1156 0 : break;
1157 :
1158 29975 : if (i > 0)
1159 24718 : rTables.AddColumn(false);
1160 29975 : if (!bIsEmpty)
1161 : {
1162 5458 : for (SCROW j = 0; j < nRepeatedRows; ++j)
1163 : {
1164 2729 : rCurrentPos.SetRow( rCellPos.Row() + j );
1165 :
1166 : // it makes no sense to import data after last supported row
1167 : // fdo#58539 & gnome#627150
1168 2729 : if(rCurrentPos.Row() > MAXROW)
1169 0 : break;
1170 :
1171 2729 : if( (rCurrentPos.Col() == 0) && (j > 0) )
1172 : {
1173 0 : rTables.AddRow();
1174 0 : rTables.AddColumn(false);
1175 : }
1176 2729 : if( cellExists(rCurrentPos) )
1177 : {
1178 2729 : if( ( !(bIsCovered) || isEmptyOrNote(rXMLImport.GetDocument(), rCurrentPos) ) )
1179 : {
1180 2729 : switch (nCellType)
1181 : {
1182 : case util::NumberFormat::TEXT:
1183 : {
1184 515 : PutTextCell( rCurrentPos, i, pOUText );
1185 : }
1186 515 : break;
1187 : case util::NumberFormat::NUMBER:
1188 : case util::NumberFormat::PERCENT:
1189 : case util::NumberFormat::CURRENCY:
1190 : case util::NumberFormat::TIME:
1191 : case util::NumberFormat::DATETIME:
1192 : case util::NumberFormat::LOGICAL:
1193 : {
1194 2214 : PutValueCell( rCurrentPos );
1195 : }
1196 2214 : break;
1197 : default:
1198 : {
1199 : OSL_FAIL("no cell type given");
1200 : }
1201 0 : break;
1202 : }
1203 : }
1204 :
1205 2729 : SetAnnotation( rCurrentPos );
1206 2729 : SetDetectiveObj( rCurrentPos );
1207 2729 : SetCellRangeSource( rCurrentPos );
1208 : }
1209 : else
1210 : {
1211 0 : if (!bWasEmpty || mxAnnotationData.get())
1212 : {
1213 0 : if (rCurrentPos.Row() > MAXROW)
1214 0 : rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_ROW_OVERFLOW);
1215 : else
1216 0 : rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_COLUMN_OVERFLOW);
1217 : }
1218 : }
1219 : }
1220 : }
1221 : else
1222 : {
1223 27246 : if ((i == 0) && (rCellPos.Col() == 0))
1224 : {
1225 19922693 : for (sal_Int32 j = 1; j < nRepeatedRows; ++j)
1226 : {
1227 19922183 : rTables.AddRow();
1228 19922183 : rTables.AddColumn(false);
1229 : }
1230 : }
1231 : }
1232 : }
1233 5257 : }
1234 :
1235 5257 : bool ScXMLTableRowCellContext::HasSpecialContent() const
1236 : {
1237 5257 : return (mxAnnotationData.get() || pDetectiveObjVec || pCellRangeSource);
1238 : }
1239 :
1240 8310 : bool ScXMLTableRowCellContext::CellsAreRepeated() const
1241 : {
1242 8310 : return ( (nColsRepeated > 1) || (nRepeatedRows > 1) );
1243 : }
1244 :
1245 : namespace {
1246 :
1247 : // from ScCellObj::GetOutputString_Imp(). all of it may not be necessary.
1248 573 : OUString getOutputString( ScDocument* pDoc, const ScAddress& aCellPos )
1249 : {
1250 573 : if (!pDoc)
1251 0 : return EMPTY_OUSTRING;
1252 :
1253 573 : CellType eType = pDoc->GetCellType(aCellPos);
1254 573 : switch (eType)
1255 : {
1256 : case CELLTYPE_NONE:
1257 573 : return EMPTY_OUSTRING;
1258 : case CELLTYPE_EDIT:
1259 : {
1260 : // GetString an der EditCell macht Leerzeichen aus Umbruechen,
1261 : // hier werden die Umbrueche aber gebraucht
1262 0 : const EditTextObject* pData = pDoc->GetEditText(aCellPos);
1263 0 : if (pData)
1264 : {
1265 0 : EditEngine& rEngine = pDoc->GetEditEngine();
1266 0 : rEngine.SetText(*pData);
1267 0 : return rEngine.GetText(LINEEND_LF);
1268 : }
1269 : // Edit-Zellen auch nicht per NumberFormatter formatieren
1270 : // (passend zur Ausgabe)
1271 : }
1272 0 : break;
1273 : default:
1274 : {
1275 : // wie in GetString am Dokument (column)
1276 : Color* pColor;
1277 0 : sal_uLong nNumFmt = pDoc->GetNumberFormat(aCellPos);
1278 : return ScCellFormat::GetString(
1279 0 : *pDoc, aCellPos, nNumFmt, &pColor, *pDoc->GetFormatTable());
1280 : }
1281 : }
1282 :
1283 0 : return EMPTY_OUSTRING;
1284 : }
1285 :
1286 : }
1287 :
1288 5257 : void ScXMLTableRowCellContext::AddNonFormulaCell( const ScAddress& rCellPos )
1289 : {
1290 5257 : ::boost::optional< OUString > pOUText;
1291 :
1292 5257 : if( nCellType == util::NumberFormat::TEXT )
1293 : {
1294 3053 : if( cellExists(rCellPos) && CellsAreRepeated() )
1295 573 : pOUText.reset( getOutputString(rXMLImport.GetDocument(), rCellPos) );
1296 :
1297 3053 : if (!mbEditEngineHasText && !pOUText && !maStringValue)
1298 1974 : bIsEmpty = true;
1299 : }
1300 :
1301 5257 : ScAddress aCurrentPos( rCellPos );
1302 5257 : if( HasSpecialContent() )
1303 8 : bIsEmpty = false;
1304 :
1305 5257 : AddTextAndValueCell( rCellPos, pOUText, aCurrentPos );
1306 :
1307 5257 : if( CellsAreRepeated() )
1308 : {
1309 579 : SCCOL nStartCol( rCellPos.Col() < MAXCOL ? rCellPos.Col() : MAXCOL );
1310 579 : SCROW nStartRow( rCellPos.Row() < MAXROW ? rCellPos.Row() : MAXROW );
1311 579 : SCCOL nEndCol( rCellPos.Col() + nColsRepeated - 1 < MAXCOL ? rCellPos.Col() + nColsRepeated - 1 : MAXCOL );
1312 579 : SCROW nEndRow( rCellPos.Row() + nRepeatedRows - 1 < MAXROW ? rCellPos.Row() + nRepeatedRows - 1 : MAXROW );
1313 579 : ScRange aScRange( nStartCol, nStartRow, rCellPos.Tab(), nEndCol, nEndRow, rCellPos.Tab() );
1314 579 : SetContentValidation( aScRange );
1315 579 : rXMLImport.GetStylesImportHelper()->AddRange( aScRange );
1316 : }
1317 4678 : else if( cellExists(rCellPos) )
1318 : {
1319 4678 : rXMLImport.GetStylesImportHelper()->AddCell(rCellPos);
1320 4678 : SetContentValidation( rCellPos );
1321 5257 : }
1322 5257 : }
1323 :
1324 364 : void ScXMLTableRowCellContext::PutFormulaCell( const ScAddress& rCellPos )
1325 : {
1326 364 : ScDocument* pDoc = rXMLImport.GetDocument();
1327 :
1328 364 : OUString aText = maFormula->first;
1329 728 : OUString aFormulaNmsp = maFormula->second;
1330 :
1331 : ::boost::scoped_ptr<ScExternalRefManager::ApiGuard> pExtRefGuard (
1332 728 : new ScExternalRefManager::ApiGuard(pDoc));
1333 :
1334 :
1335 364 : if ( !aText.isEmpty() )
1336 : {
1337 364 : if ( aText[0] == '=' && aText.getLength() > 1 )
1338 : {
1339 : // temporary formula string as string tokens
1340 364 : boost::scoped_ptr<ScTokenArray> pCode(new ScTokenArray);
1341 364 : pCode->AddStringXML( aText );
1342 364 : if( (eGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) && !aFormulaNmsp.isEmpty() )
1343 0 : pCode->AddStringXML( aFormulaNmsp );
1344 :
1345 364 : pDoc->IncXMLImportedFormulaCount( aText.getLength() );
1346 364 : ScFormulaCell* pNewCell = new ScFormulaCell(pDoc, rCellPos, pCode.get(), eGrammar, MM_NONE);
1347 364 : SetFormulaCell(pNewCell);
1348 364 : pNewCell = pDoc->SetFormulaCell(rCellPos, pNewCell);
1349 364 : if (pNewCell)
1350 364 : pNewCell->SetNeedNumberFormat( true );
1351 : }
1352 0 : else if ( aText[0] == '\'' && aText.getLength() > 1 )
1353 : {
1354 : // for bEnglish, "'" at the beginning is always interpreted as text
1355 : // marker and stripped
1356 0 : pDoc->SetTextCell(rCellPos, aText.copy(1));
1357 : }
1358 : else
1359 : {
1360 0 : SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
1361 0 : sal_uInt32 nEnglish = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
1362 : double fVal;
1363 0 : if ( pFormatter->IsNumberFormat( aText, nEnglish, fVal ) )
1364 0 : pDoc->SetValue(rCellPos, fVal);
1365 : //the (english) number format will not be set
1366 : //search matching local format and apply it
1367 : else
1368 0 : pDoc->SetTextCell(rCellPos, aText);
1369 : }
1370 364 : }
1371 364 : }
1372 :
1373 395 : void ScXMLTableRowCellContext::AddFormulaCell( const ScAddress& rCellPos )
1374 : {
1375 395 : if( cellExists(rCellPos) )
1376 : {
1377 395 : SetContentValidation( rCellPos );
1378 : SAL_WARN_IF((nColsRepeated != 1) || (nRepeatedRows != 1), "sc", "repeated cells with formula not possible now");
1379 395 : rXMLImport.GetStylesImportHelper()->AddCell(rCellPos);
1380 :
1381 : //add matrix
1382 395 : if(bIsMatrix)
1383 : {
1384 31 : if (nMatrixCols > 0 && nMatrixRows > 0)
1385 : {
1386 : //matrix cells are put in the document, but we must set the
1387 : //value/text of each matrix cell later
1388 31 : rXMLImport.GetTables().AddMatrixRange(
1389 31 : rCellPos.Col(), rCellPos.Row(),
1390 62 : std::min<SCCOL>(rCellPos.Col() + nMatrixCols - 1, MAXCOL),
1391 62 : std::min<SCROW>(rCellPos.Row() + nMatrixRows - 1, MAXROW),
1392 155 : maFormula->first, maFormula->second, eGrammar);
1393 :
1394 : // Set the value/text of the top-left matrix position in its
1395 : // cached result. For import, we only need to set the correct
1396 : // matrix geometry and the value type of the top-left element.
1397 :
1398 31 : ScFormulaCell* pFCell = rXMLImport.GetDocument()->GetFormulaCell(rCellPos);
1399 :
1400 31 : ScMatrixRef pMat(new ScMatrix(nMatrixCols, nMatrixRows));
1401 31 : if (bFormulaTextResult && maStringValue)
1402 : {
1403 12 : if (!IsPossibleErrorString())
1404 : {
1405 : pFCell->SetResultMatrix(
1406 6 : nMatrixCols, nMatrixRows, pMat, new formula::FormulaStringToken(*maStringValue));
1407 6 : pFCell->ResetDirty();
1408 : }
1409 : }
1410 19 : else if (!rtl::math::isNan(fValue))
1411 : {
1412 : pFCell->SetResultMatrix(
1413 19 : nMatrixCols, nMatrixRows, pMat, new formula::FormulaDoubleToken(fValue));
1414 19 : pFCell->ResetDirty();
1415 : }
1416 31 : pFCell->StartListeningTo(rXMLImport.GetDocument());
1417 : }
1418 : }
1419 : else
1420 364 : PutFormulaCell( rCellPos );
1421 :
1422 395 : SetAnnotation( rCellPos );
1423 395 : SetDetectiveObj( rCellPos );
1424 395 : SetCellRangeSource( rCellPos );
1425 395 : rXMLImport.ProgressBarIncrement(false);
1426 : }
1427 : else
1428 : {
1429 0 : if (rCellPos.Row() > MAXROW)
1430 0 : rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_ROW_OVERFLOW);
1431 : else
1432 0 : rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_COLUMN_OVERFLOW);
1433 : }
1434 395 : }
1435 :
1436 : //There are cases where a formula cell is exported with an office:value of 0 or
1437 : //no office:value at all, but the formula cell will have a text:p value which
1438 : //contains the intended formula result.
1439 : //These cases include when a formula result:
1440 : // - is blank
1441 : // - has a constant error value beginning with "#" (such as "#VALUE!" or "#N/A")
1442 : // - has an "Err:[###]" (where "[###]" is an error number)
1443 : // Libreoffice 4.1+ with ODF1.2 extended write however calcext:value-type="error" in that case
1444 5652 : void ScXMLTableRowCellContext::HasSpecialCaseFormulaText()
1445 : {
1446 5652 : if (!mbEditEngineHasText || mbNewValueType)
1447 8426 : return;
1448 :
1449 2878 : OUString aStr = mpEditEngine->GetText(0);
1450 2878 : if (aStr.isEmpty() || aStr.startsWith("Err:"))
1451 27 : mbPossibleErrorCell = true;
1452 2851 : else if (aStr.startsWith("#"))
1453 18 : mbCheckWithCompilerForError = true;
1454 : }
1455 :
1456 73 : bool ScXMLTableRowCellContext::IsPossibleErrorString() const
1457 : {
1458 73 : if(mbNewValueType && !mbErrorValue)
1459 0 : return false;
1460 73 : else if(mbNewValueType && mbErrorValue)
1461 0 : return true;
1462 73 : return mbPossibleErrorCell || ( mbCheckWithCompilerForError && GetScImport().IsFormulaErrorConstant(*maStringValue) );
1463 : }
1464 :
1465 :
1466 5652 : void ScXMLTableRowCellContext::EndElement()
1467 : {
1468 5652 : HasSpecialCaseFormulaText();
1469 5652 : if( bFormulaTextResult && (mbPossibleErrorCell || mbCheckWithCompilerForError) )
1470 : {
1471 45 : maStringValue.reset(mpEditEngine->GetText(0));
1472 45 : nCellType = util::NumberFormat::TEXT;
1473 : }
1474 :
1475 5652 : ScAddress aCellPos = rXMLImport.GetTables().GetCurrentCellPos();
1476 5652 : if( aCellPos.Col() > 0 && nRepeatedRows > 1 )
1477 9 : aCellPos.SetRow( aCellPos.Row() - (nRepeatedRows - 1) );
1478 5652 : if( bIsMerged )
1479 5 : DoMerge( aCellPos, nMergedCols - 1, nMergedRows - 1 );
1480 :
1481 5652 : if (maFormula)
1482 395 : AddFormulaCell(aCellPos);
1483 : else
1484 5257 : AddNonFormulaCell(aCellPos);
1485 :
1486 5652 : UnlockSolarMutex(); //if LockSolarMutex got used, we presumably need to ensure an UnlockSolarMutex
1487 :
1488 5652 : bIsMerged = false;
1489 5652 : nMergedCols = 1;
1490 5652 : nMergedRows = 1;
1491 5652 : nColsRepeated = 1;
1492 5745 : }
1493 :
1494 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|