fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / filter / xml / xmlcelli.cxx
blob997275a0a288feb81221844d8c58f64b61882aef
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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"
39 #include "XMLTableShapeImportHelper.hxx"
40 #include "XMLStylesImportHelper.hxx"
41 #include "celltextparacontext.hxx"
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 #include "documentimport.hxx"
55 #include <datastream.hxx>
56 #include <rangeutl.hxx>
58 #include <xmloff/xmltkmap.hxx>
59 #include <xmloff/xmltoken.hxx>
60 #include <xmloff/nmspmap.hxx>
61 #include <xmloff/xmluconv.hxx>
62 #include <xmloff/families.hxx>
63 #include <xmloff/numehelp.hxx>
64 #include <xmloff/xmlnmspe.hxx>
65 #include <xmloff/prstylei.hxx>
66 #include <svl/zforlist.hxx>
67 #include <svx/svdocapt.hxx>
68 #include <editeng/outlobj.hxx>
69 #include <editeng/editobj.hxx>
70 #include <editeng/wghtitem.hxx>
71 #include <editeng/colritem.hxx>
72 #include <editeng/fhgtitem.hxx>
73 #include <editeng/postitem.hxx>
74 #include <editeng/fontitem.hxx>
75 #include <editeng/udlnitem.hxx>
76 #include <editeng/wrlmitem.hxx>
77 #include <editeng/crossedoutitem.hxx>
78 #include <editeng/charreliefitem.hxx>
79 #include <editeng/charscaleitem.hxx>
80 #include <editeng/contouritem.hxx>
81 #include <editeng/shdditem.hxx>
82 #include <editeng/kernitem.hxx>
83 #include <editeng/autokernitem.hxx>
84 #include <editeng/escapementitem.hxx>
85 #include <editeng/emphasismarkitem.hxx>
86 #include <editeng/langitem.hxx>
87 #include <svx/unoapi.hxx>
88 #include <svl/languageoptions.hxx>
89 #include <svl/sharedstringpool.hxx>
90 #include <svtools/miscopt.hxx>
91 #include <sax/tools/converter.hxx>
93 #include <com/sun/star/frame/XModel.hpp>
94 #include <com/sun/star/text/XText.hpp>
95 #include <com/sun/star/sheet/XSpreadsheets.hpp>
96 #include <com/sun/star/sheet/XSpreadsheet.hpp>
97 #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
99 #include <com/sun/star/sheet/XSheetCondition.hpp>
100 #include <com/sun/star/table/XCellRange.hpp>
101 #include <com/sun/star/table/CellAddress.hpp>
102 #include <com/sun/star/util/NumberFormat.hpp>
103 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
104 #include <com/sun/star/util/XNumberFormatTypes.hpp>
105 #include <com/sun/star/util/Date.hpp>
106 #include <com/sun/star/lang/Locale.hpp>
107 #include <com/sun/star/text/ControlCharacter.hpp>
108 #include <com/sun/star/table/XCell.hpp>
109 #include <com/sun/star/document/XActionLockable.hpp>
111 #include <com/sun/star/sheet/ValidationType.hpp>
112 #include <com/sun/star/sheet/ValidationAlertStyle.hpp>
113 #include <com/sun/star/sheet/ConditionOperator.hpp>
115 #include <rtl/ustrbuf.hxx>
116 #include <tools/date.hxx>
117 #include <i18nlangtag/lang.h>
118 #include <comphelper/extract.hxx>
120 using namespace com::sun::star;
121 using namespace xmloff::token;
123 ScXMLTableRowCellContext::ParaFormat::ParaFormat(ScEditEngineDefaulter& rEditEngine) :
124 maItemSet(rEditEngine.GetEmptyItemSet()) {}
126 ScXMLTableRowCellContext::Field::Field(SvxFieldData* pData) : mpData(pData) {}
128 ScXMLTableRowCellContext::Field::~Field()
130 delete mpData;
133 ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport,
134 sal_uInt16 nPrfx,
135 const OUString& rLName,
136 const ::com::sun::star::uno::Reference<
137 ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
138 const bool bTempIsCovered,
139 const sal_Int32 nTempRepeatedRows ) :
140 ScXMLImportContext(rImport, nPrfx, rLName),
141 mpEditEngine(GetScImport().GetEditEngine()),
142 mnCurParagraph(0),
143 pDetectiveObjVec(NULL),
144 pCellRangeSource(NULL),
145 fValue(0.0),
146 nMergedRows(1),
147 nMatrixRows(0),
148 nRepeatedRows(nTempRepeatedRows),
149 nMergedCols(1),
150 nMatrixCols(0),
151 nColsRepeated(1),
152 rXMLImport((ScXMLImport&)rImport),
153 eGrammar( formula::FormulaGrammar::GRAM_STORAGE_DEFAULT),
154 nCellType(util::NumberFormat::TEXT),
155 bIsMerged(false),
156 bIsMatrix(false),
157 bIsCovered(bTempIsCovered),
158 bIsEmpty(true),
159 mbNewValueType(false),
160 mbErrorValue(false),
161 bIsFirstTextImport(false),
162 bSolarMutexLocked(false),
163 bFormulaTextResult(false),
164 mbPossibleErrorCell(false),
165 mbCheckWithCompilerForError(false),
166 mbEditEngineHasText(false),
167 mbHasFormatRuns(false),
168 mbHasStyle(false)
170 rtl::math::setNan(&fValue); // NaN by default
172 rXMLImport.SetRemoveLastChar(false);
173 rXMLImport.GetTables().AddColumn(bTempIsCovered);
174 const sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
175 OUString aLocalName;
176 OUString* pStyleName = NULL;
177 OUString* pCurrencySymbol = NULL;
178 const SvXMLTokenMap& rTokenMap = rImport.GetTableRowCellAttrTokenMap();
179 for (sal_Int16 i = 0; i < nAttrCount; ++i)
181 sal_uInt16 nAttrPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(
182 xAttrList->getNameByIndex(i), &aLocalName);
184 const OUString& sValue = xAttrList->getValueByIndex(i);
185 sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName);
186 switch (nToken)
188 case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME:
189 pStyleName = new OUString(sValue);
190 mbHasStyle = true;
191 break;
192 case XML_TOK_TABLE_ROW_CELL_ATTR_CONTENT_VALIDATION_NAME:
193 OSL_ENSURE(!maContentValidationName, "here should be only one Validation Name");
194 if (!sValue.isEmpty())
195 maContentValidationName.reset(sValue);
196 break;
197 case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_ROWS:
198 bIsMerged = true;
199 nMergedRows = static_cast<SCROW>(sValue.toInt32());
200 break;
201 case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_COLS:
202 bIsMerged = true;
203 nMergedCols = static_cast<SCCOL>(sValue.toInt32());
204 break;
205 case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_COLS:
206 bIsMatrix = true;
207 nMatrixCols = static_cast<SCCOL>(sValue.toInt32());
208 break;
209 case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_ROWS:
210 bIsMatrix = true;
211 nMatrixRows = static_cast<SCROW>(sValue.toInt32());
212 break;
213 case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
214 nColsRepeated = static_cast<SCCOL>(std::min<sal_Int32>( MAXCOLCOUNT,
215 std::max( sValue.toInt32(), static_cast<sal_Int32>(1) ) ));
216 break;
217 case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE:
218 nCellType = GetScImport().GetCellType(sValue);
219 bIsEmpty = false;
220 break;
221 case XML_TOK_TABLE_ROW_CELL_ATTR_NEW_VALUE_TYPE:
222 if(sValue == "error")
223 mbErrorValue = true;
224 else
225 nCellType = GetScImport().GetCellType(sValue);
226 bIsEmpty = false;
227 mbNewValueType = true;
228 break;
229 case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE:
231 if (!sValue.isEmpty())
233 ::sax::Converter::convertDouble(fValue, sValue);
234 bIsEmpty = false;
236 //if office:value="0", let's get the text:p in case this is
237 //a special case in HasSpecialCaseFormulaText(). If it
238 //turns out not to be a special case, we'll use the 0 value.
239 if(fValue == 0.0)
240 bFormulaTextResult = true;
243 break;
244 case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE:
246 if (!sValue.isEmpty() && rXMLImport.SetNullDateOnUnitConverter())
248 rXMLImport.GetMM100UnitConverter().convertDateTime(fValue, sValue);
249 bIsEmpty = false;
252 break;
253 case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE:
255 if (!sValue.isEmpty())
257 ::sax::Converter::convertDuration(fValue, sValue);
258 bIsEmpty = false;
261 break;
262 case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE:
264 if (!sValue.isEmpty())
266 OSL_ENSURE(!maStringValue, "here should be only one string value");
267 maStringValue.reset(sValue);
268 bIsEmpty = false;
271 break;
272 case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE:
274 if (!sValue.isEmpty())
276 if ( IsXMLToken(sValue, XML_TRUE) )
277 fValue = 1.0;
278 else if ( IsXMLToken(sValue, XML_FALSE) )
279 fValue = 0.0;
280 else
281 ::sax::Converter::convertDouble(fValue, sValue);
282 bIsEmpty = false;
285 break;
286 case XML_TOK_TABLE_ROW_CELL_ATTR_FORMULA:
288 if (!sValue.isEmpty())
290 OSL_ENSURE(!maFormula, "here should be only one formula");
291 OUString aFormula, aFormulaNmsp;
292 rXMLImport.ExtractFormulaNamespaceGrammar( aFormula, aFormulaNmsp, eGrammar, sValue );
293 maFormula.reset( FormulaWithNamespace(aFormula, aFormulaNmsp) );
296 break;
297 case XML_TOK_TABLE_ROW_CELL_ATTR_CURRENCY:
298 pCurrencySymbol = new OUString(sValue);
299 break;
300 default:
304 if (maFormula)
306 if (nCellType == util::NumberFormat::TEXT)
307 bFormulaTextResult = true;
308 if(nCellType == util::NumberFormat::DATETIME)
309 nCellType = util::NumberFormat::UNDEFINED;
310 //if bIsEmpty is true at this point, then there is no office value.
311 //we must get the text:p (even if it is empty) in case this a special
312 //case in HasSpecialCaseFormulaText().
313 if(bIsEmpty)
314 bFormulaTextResult = true;
316 rXMLImport.GetStylesImportHelper()->SetAttributes(pStyleName, pCurrencySymbol, nCellType);
319 ScXMLTableRowCellContext::~ScXMLTableRowCellContext()
321 delete pDetectiveObjVec;
322 delete pCellRangeSource;
325 void ScXMLTableRowCellContext::LockSolarMutex()
327 if (!bSolarMutexLocked)
329 GetScImport().LockSolarMutex();
330 bSolarMutexLocked = true;
334 void ScXMLTableRowCellContext::UnlockSolarMutex()
336 if (bSolarMutexLocked)
338 GetScImport().UnlockSolarMutex();
339 bSolarMutexLocked = false;
343 namespace {
345 bool cellExists( const ScAddress& rCellPos )
347 return( rCellPos.Col() >= 0 && rCellPos.Row() >= 0 &&
348 rCellPos.Col() <= MAXCOL && rCellPos.Row() <= MAXROW );
353 void ScXMLTableRowCellContext::PushParagraphSpan(const OUString& rSpan, const OUString& rStyleName)
355 sal_Int32 nBegin = maParagraph.getLength();
356 sal_Int32 nEnd = nBegin + rSpan.getLength();
357 maParagraph.append(rSpan);
359 PushFormat(nBegin, nEnd, rStyleName);
362 void ScXMLTableRowCellContext::PushParagraphField(SvxFieldData* pData, const OUString& rStyleName)
364 mbHasFormatRuns = true;
365 maFields.push_back(new Field(pData));
366 Field& rField = maFields.back();
368 sal_Int32 nPos = maParagraph.getLength();
369 maParagraph.append('\1'); // Placeholder text for inserted field item.
370 rField.maSelection.nStartPara = mnCurParagraph;
371 rField.maSelection.nEndPara = mnCurParagraph;
372 rField.maSelection.nStartPos = nPos;
373 rField.maSelection.nEndPos = nPos+1;
375 PushFormat(nPos, nPos+1, rStyleName);
378 void ScXMLTableRowCellContext::PushFormat(sal_Int32 nBegin, sal_Int32 nEnd, const OUString& rStyleName)
380 if (rStyleName.isEmpty())
381 return;
383 // Get the style information from xmloff.
384 rtl::Reference<XMLPropertySetMapper> xMapper = GetImport().GetTextImport()->GetTextImportPropertySetMapper()->getPropertySetMapper();
385 if (!xMapper.is())
386 // We can't do anything without the mapper.
387 return;
389 sal_Int32 nEntryCount = xMapper->GetEntryCount();
391 SvXMLStylesContext* pAutoStyles = GetImport().GetAutoStyles();
393 // Style name for text span corresponds with the name of an automatic style.
394 const XMLPropStyleContext* pStyle = dynamic_cast<const XMLPropStyleContext*>(
395 pAutoStyles->FindStyleChildContext(XML_STYLE_FAMILY_TEXT_TEXT, rStyleName));
397 if (!pStyle)
398 // No style by that name found.
399 return;
401 const std::vector<XMLPropertyState>& rProps = pStyle->GetProperties();
402 if (rProps.empty())
403 return;
405 const ScXMLEditAttributeMap& rEditAttrMap = GetScImport().GetEditAttributeMap();
407 mbHasFormatRuns = true;
408 maFormats.push_back(new ParaFormat(*mpEditEngine));
409 ParaFormat& rFmt = maFormats.back();
410 rFmt.maSelection.nStartPara = rFmt.maSelection.nEndPara = mnCurParagraph;
411 rFmt.maSelection.nStartPos = nBegin;
412 rFmt.maSelection.nEndPos = nEnd;
414 // Store the used text styles for export.
415 ScSheetSaveData* pSheetData = ScModelObj::getImplementation(rXMLImport.GetModel())->GetSheetSaveData();
416 ScAddress aCellPos = rXMLImport.GetTables().GetCurrentCellPos();
417 pSheetData->AddTextStyle(rStyleName, aCellPos, rFmt.maSelection);
419 boost::scoped_ptr<SfxPoolItem> pPoolItem;
420 sal_uInt16 nLastItemID = EE_CHAR_END + 1;
422 std::vector<XMLPropertyState>::const_iterator it = rProps.begin(), itEnd = rProps.end();
423 for (; it != itEnd; ++it)
425 if (it->mnIndex == -1 || it->mnIndex >= nEntryCount)
426 continue;
428 const OUString& rName = xMapper->GetEntryAPIName(it->mnIndex);
429 const ScXMLEditAttributeMap::Entry* pEntry = rEditAttrMap.getEntryByAPIName(rName);
430 if (!pEntry)
431 continue;
433 if (nLastItemID != pEntry->mnItemID && pPoolItem)
435 // Flush the last item when the item ID changes.
436 rFmt.maItemSet.Put(*pPoolItem);
437 pPoolItem.reset();
440 switch (pEntry->mnItemID)
442 case EE_CHAR_FONTINFO:
443 case EE_CHAR_FONTINFO_CJK:
444 case EE_CHAR_FONTINFO_CTL:
446 // Font properties need to be consolidated into a single item.
447 if (!pPoolItem)
448 pPoolItem.reset(new SvxFontItem(pEntry->mnItemID));
450 pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
452 break;
453 case EE_CHAR_WEIGHT:
454 case EE_CHAR_WEIGHT_CJK:
455 case EE_CHAR_WEIGHT_CTL:
457 if (!pPoolItem)
458 pPoolItem.reset(new SvxWeightItem(WEIGHT_NORMAL, pEntry->mnItemID));
460 pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
462 break;
463 case EE_CHAR_FONTHEIGHT:
464 case EE_CHAR_FONTHEIGHT_CJK:
465 case EE_CHAR_FONTHEIGHT_CTL:
467 if (!pPoolItem)
468 pPoolItem.reset(new SvxFontHeightItem(240, 100, pEntry->mnItemID));
470 pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
472 break;
473 case EE_CHAR_ITALIC:
474 case EE_CHAR_ITALIC_CJK:
475 case EE_CHAR_ITALIC_CTL:
477 if (!pPoolItem)
478 pPoolItem.reset(new SvxPostureItem(ITALIC_NONE, pEntry->mnItemID));
480 pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
482 break;
483 case EE_CHAR_UNDERLINE:
485 if (!pPoolItem)
486 pPoolItem.reset(new SvxUnderlineItem(UNDERLINE_NONE, pEntry->mnItemID));
488 pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
490 break;
491 case EE_CHAR_OVERLINE:
493 if (!pPoolItem)
494 pPoolItem.reset(new SvxOverlineItem(UNDERLINE_NONE, pEntry->mnItemID));
496 pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
498 break;
499 case EE_CHAR_COLOR:
501 if (!pPoolItem)
502 pPoolItem.reset(new SvxColorItem(pEntry->mnItemID));
504 pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
506 break;
507 case EE_CHAR_WLM:
509 if (!pPoolItem)
510 pPoolItem.reset(new SvxWordLineModeItem(false, pEntry->mnItemID));
512 pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
514 break;
515 case EE_CHAR_STRIKEOUT:
517 if (!pPoolItem)
518 pPoolItem.reset(new SvxCrossedOutItem(STRIKEOUT_NONE, pEntry->mnItemID));
520 pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
522 break;
523 case EE_CHAR_RELIEF:
525 if (!pPoolItem)
526 pPoolItem.reset(new SvxCharReliefItem(RELIEF_NONE, pEntry->mnItemID));
528 pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
530 break;
531 case EE_CHAR_OUTLINE:
533 if (!pPoolItem)
534 pPoolItem.reset(new SvxContourItem(false, pEntry->mnItemID));
536 pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
538 break;
539 case EE_CHAR_SHADOW:
541 if (!pPoolItem)
542 pPoolItem.reset(new SvxShadowedItem(false, pEntry->mnItemID));
544 pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
546 break;
547 case EE_CHAR_KERNING:
549 if (!pPoolItem)
550 pPoolItem.reset(new SvxKerningItem(0, pEntry->mnItemID));
552 pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
554 break;
555 case EE_CHAR_PAIRKERNING:
557 if (!pPoolItem)
558 pPoolItem.reset(new SvxAutoKernItem(false, pEntry->mnItemID));
560 pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
562 break;
563 case EE_CHAR_FONTWIDTH:
565 if (!pPoolItem)
566 pPoolItem.reset(new SvxCharScaleWidthItem(100, pEntry->mnItemID));
568 pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
570 break;
571 case EE_CHAR_ESCAPEMENT:
573 if (!pPoolItem)
574 pPoolItem.reset(new SvxEscapementItem(pEntry->mnItemID));
576 pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
578 break;
579 case EE_CHAR_EMPHASISMARK:
581 if (!pPoolItem)
582 pPoolItem.reset(new SvxEmphasisMarkItem(EMPHASISMARK_NONE, pEntry->mnItemID));
584 pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
586 break;
587 case EE_CHAR_LANGUAGE:
588 case EE_CHAR_LANGUAGE_CJK:
589 case EE_CHAR_LANGUAGE_CTL:
591 if (!pPoolItem)
592 pPoolItem.reset(new SvxLanguageItem(LANGUAGE_DONTKNOW, pEntry->mnItemID));
594 pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
596 break;
597 default:
601 nLastItemID = pEntry->mnItemID;
604 if (pPoolItem)
605 rFmt.maItemSet.Put(*pPoolItem);
608 OUString ScXMLTableRowCellContext::GetFirstParagraph() const
610 if (!maFirstParagraph)
611 return mpEditEngine->GetText(0);
613 return *maFirstParagraph;
616 void ScXMLTableRowCellContext::PushParagraphFieldDate(const OUString& rStyleName)
618 PushParagraphField(new SvxDateField, rStyleName);
621 void ScXMLTableRowCellContext::PushParagraphFieldSheetName(const OUString& rStyleName)
623 SCTAB nTab = GetScImport().GetTables().GetCurrentCellPos().Tab();
624 PushParagraphField(new SvxTableField(nTab), rStyleName);
627 void ScXMLTableRowCellContext::PushParagraphFieldDocTitle(const OUString& rStyleName)
629 PushParagraphField(new SvxFileField, rStyleName);
632 void ScXMLTableRowCellContext::PushParagraphFieldURL(
633 const OUString& rURL, const OUString& rRep, const OUString& rStyleName)
635 OUString aAbsURL = GetScImport().GetAbsoluteReference(rURL);
636 PushParagraphField(new SvxURLField(aAbsURL, rRep, SVXURLFORMAT_REPR), rStyleName);
639 void ScXMLTableRowCellContext::PushParagraphEnd()
641 // EditEngine always has at least one paragraph even when its content is empty.
643 if (mbEditEngineHasText)
645 if (maFirstParagraph)
647 // Flush the cached first paragraph first.
648 mpEditEngine->Clear();
649 mpEditEngine->SetText(*maFirstParagraph);
650 maFirstParagraph.reset();
652 mpEditEngine->InsertParagraph(mpEditEngine->GetParagraphCount(), maParagraph.makeStringAndClear());
654 else if (mbHasFormatRuns)
656 mpEditEngine->Clear();
657 mpEditEngine->SetText(maParagraph.makeStringAndClear());
658 mbEditEngineHasText = true;
660 else if (mnCurParagraph == 0)
662 maFirstParagraph.reset(maParagraph.makeStringAndClear());
663 mbEditEngineHasText = true;
666 ++mnCurParagraph;
669 SvXMLImportContext *ScXMLTableRowCellContext::CreateChildContext( sal_uInt16 nPrefix,
670 const OUString& rLName,
671 const ::com::sun::star::uno::Reference<
672 ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
674 SvXMLImportContext *pContext = 0;
676 const SvXMLTokenMap& rTokenMap = rXMLImport.GetTableRowCellElemTokenMap();
677 bool bTextP(false);
678 switch( rTokenMap.Get( nPrefix, rLName ) )
680 case XML_TOK_TABLE_ROW_CELL_P:
682 bIsEmpty = false;
683 bTextP = true;
685 pContext = new ScXMLCellTextParaContext(rXMLImport, nPrefix, rLName, *this);
687 break;
688 case XML_TOK_TABLE_ROW_CELL_TABLE:
690 SAL_WARN("sc", "ScXMLTableRowCellContext::CreateChildContext: subtables are not supported");
692 break;
693 case XML_TOK_TABLE_ROW_CELL_ANNOTATION:
695 bIsEmpty = false;
696 OSL_ENSURE( !mxAnnotationData.get(), "ScXMLTableRowCellContext::CreateChildContext - multiple annotations in one cell" );
697 mxAnnotationData.reset( new ScXMLAnnotationData );
698 pContext = new ScXMLAnnotationContext( rXMLImport, nPrefix, rLName,
699 xAttrList, *mxAnnotationData, this);
701 break;
702 case XML_TOK_TABLE_ROW_CELL_DETECTIVE:
704 bIsEmpty = false;
705 if (!pDetectiveObjVec)
706 pDetectiveObjVec = new ScMyImpDetectiveObjVec();
707 pContext = new ScXMLDetectiveContext(
708 rXMLImport, nPrefix, rLName, pDetectiveObjVec );
710 break;
711 case XML_TOK_TABLE_ROW_CELL_CELL_RANGE_SOURCE:
713 bIsEmpty = false;
714 if (!pCellRangeSource)
715 pCellRangeSource = new ScMyImpCellRangeSource();
716 pContext = new ScXMLCellRangeSourceContext(
717 rXMLImport, nPrefix, rLName, xAttrList, pCellRangeSource );
719 break;
722 if (!pContext && !bTextP)
724 ScAddress aCellPos = rXMLImport.GetTables().GetCurrentCellPos();
725 uno::Reference<drawing::XShapes> xShapes (rXMLImport.GetTables().GetCurrentXShapes());
726 if (xShapes.is())
728 if (aCellPos.Col() > MAXCOL)
729 aCellPos.SetCol(MAXCOL);
730 if (aCellPos.Row() > MAXROW)
731 aCellPos.SetRow(MAXROW);
732 XMLTableShapeImportHelper* pTableShapeImport =
733 static_cast< XMLTableShapeImportHelper* >( rXMLImport.GetShapeImport().get() );
734 pTableShapeImport->SetOnTable(false);
735 com::sun::star::table::CellAddress aCellAddress;
736 ScUnoConversion::FillApiAddress( aCellAddress, aCellPos );
737 pTableShapeImport->SetCell(aCellAddress);
738 pContext = rXMLImport.GetShapeImport()->CreateGroupChildContext(
739 rXMLImport, nPrefix, rLName, xAttrList, xShapes);
740 if (pContext)
742 bIsEmpty = false;
743 rXMLImport.ProgressBarIncrement(false);
748 if( !pContext )
749 pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
751 return pContext;
754 void ScXMLTableRowCellContext::DoMerge( const ScAddress& rScAddress, const SCCOL nCols, const SCROW nRows )
756 SCCOL mergeToCol = rScAddress.Col() + nCols;
757 SCROW mergeToRow = rScAddress.Row() + nRows;
758 bool bInBounds = rScAddress.Col() <= MAXCOL && rScAddress.Row() <= MAXROW &&
759 mergeToCol <= MAXCOL && mergeToRow <= MAXROW;
760 if( bInBounds )
762 rXMLImport.GetDocument()->DoMerge( rScAddress.Tab(),
763 rScAddress.Col(), rScAddress.Row(), mergeToCol, mergeToRow );
767 namespace {
769 ScValidationMode validationTypeToMode( const sheet::ValidationType eVType )
771 ScValidationMode eMode;
772 switch( eVType )
774 case sheet::ValidationType_WHOLE: eMode = SC_VALID_WHOLE; break;
775 case sheet::ValidationType_DECIMAL: eMode = SC_VALID_DECIMAL; break;
776 case sheet::ValidationType_DATE: eMode = SC_VALID_DATE; break;
777 case sheet::ValidationType_TIME: eMode = SC_VALID_TIME; break;
778 case sheet::ValidationType_TEXT_LEN: eMode = SC_VALID_TEXTLEN; break;
779 case sheet::ValidationType_LIST: eMode = SC_VALID_LIST; break;
780 case sheet::ValidationType_CUSTOM: eMode = SC_VALID_CUSTOM; break;
781 default: eMode = SC_VALID_ANY; break;
783 return eMode;
786 ScValidErrorStyle validAlertToValidError( const sheet::ValidationAlertStyle eVAlertStyle )
788 ScValidErrorStyle eVErrStyle;
789 switch( eVAlertStyle )
791 case sheet::ValidationAlertStyle_STOP: eVErrStyle = SC_VALERR_STOP; break;
792 case sheet::ValidationAlertStyle_WARNING: eVErrStyle = SC_VALERR_WARNING; break;
793 case sheet::ValidationAlertStyle_MACRO: eVErrStyle = SC_VALERR_MACRO; break;
794 default: eVErrStyle = SC_VALERR_INFO; break;
795 //should INFO be the default? seems to be the most unobtrusive choice.
797 return eVErrStyle;
802 void ScXMLTableRowCellContext::SetContentValidation( const ScRange& rScRange )
804 if (maContentValidationName)
806 ScDocument* pDoc = rXMLImport.GetDocument();
807 ScMyImportValidation aValidation;
808 aValidation.eGrammar1 = aValidation.eGrammar2 = pDoc->GetStorageGrammar();
809 if( rXMLImport.GetValidation(*maContentValidationName, aValidation) )
811 ScValidationData aScValidationData(
812 validationTypeToMode(aValidation.aValidationType),
813 ScConditionEntry::GetModeFromApi(static_cast<sal_Int32>(aValidation.aOperator)),
814 aValidation.sFormula1, aValidation.sFormula2, pDoc, ScAddress(),
815 aValidation.sFormulaNmsp1, aValidation.sFormulaNmsp2,
816 aValidation.eGrammar1, aValidation.eGrammar2
819 aScValidationData.SetIgnoreBlank( aValidation.bIgnoreBlanks );
820 aScValidationData.SetListType( aValidation.nShowList );
822 // set strings for error / input even if disabled (and disable afterwards)
823 aScValidationData.SetInput( aValidation.sImputTitle, aValidation.sImputMessage );
824 if( !aValidation.bShowImputMessage )
825 aScValidationData.ResetInput();
826 aScValidationData.SetError( aValidation.sErrorTitle, aValidation.sErrorMessage, validAlertToValidError(aValidation.aAlertStyle) );
827 if( !aValidation.bShowErrorMessage )
828 aScValidationData.ResetError();
830 if( !aValidation.sBaseCellAddress.isEmpty() )
831 aScValidationData.SetSrcString( aValidation.sBaseCellAddress );
833 sal_uLong nIndex = pDoc->AddValidationEntry( aScValidationData );
835 ScPatternAttr aPattern( pDoc->GetPool() );
836 aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_VALIDDATA, nIndex ) );
837 if( rScRange.aStart == rScRange.aEnd ) //for a single cell
839 pDoc->ApplyPattern( rScRange.aStart.Col(), rScRange.aStart.Row(),
840 rScRange.aStart.Tab(), aPattern );
842 else //for repeating cells
844 pDoc->ApplyPatternAreaTab( rScRange.aStart.Col(), rScRange.aStart.Row(),
845 rScRange.aEnd.Col(), rScRange.aEnd.Row(),
846 rScRange.aStart.Tab(), aPattern );
849 // is the below still needed?
850 // For now, any sheet with validity is blocked from stream-copying.
851 // Later, the validation names could be stored along with the style names.
852 ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetImport().GetModel())->GetSheetSaveData();
853 pSheetData->BlockSheet( GetScImport().GetTables().GetCurrentSheet() );
858 void ScXMLTableRowCellContext::SetContentValidation( const ScAddress& rCellPos )
860 SetContentValidation( ScRange(rCellPos, rCellPos) );
863 void ScXMLTableRowCellContext::SetAnnotation(const ScAddress& rPos)
865 ScDocument* pDoc = rXMLImport.GetDocument();
866 if( !pDoc || !mxAnnotationData.get() )
867 return;
869 LockSolarMutex();
871 ScPostIt* pNote = 0;
873 uno::Reference< drawing::XShapes > xShapes = rXMLImport.GetTables().GetCurrentXShapes();
874 uno::Reference< container::XIndexAccess > xShapesIA( xShapes, uno::UNO_QUERY );
875 sal_Int32 nOldShapeCount = xShapesIA.is() ? xShapesIA->getCount() : 0;
877 OSL_ENSURE( !mxAnnotationData->mxShape.is() || mxAnnotationData->mxShapes.is(),
878 "ScXMLTableRowCellContext::SetAnnotation - shape without drawing page" );
879 if( mxAnnotationData->mxShape.is() && mxAnnotationData->mxShapes.is() )
881 OSL_ENSURE( mxAnnotationData->mxShapes.get() == xShapes.get(), "ScXMLTableRowCellContext::SetAnnotation - diffenet drawing pages" );
882 SdrObject* pObject = ::GetSdrObjectFromXShape( mxAnnotationData->mxShape );
883 OSL_ENSURE( pObject, "ScXMLTableRowCellContext::SetAnnotation - cannot get SdrObject from shape" );
885 /* Try to reuse the drawing object already created (but only if the
886 note is visible, and the object is a caption object). */
887 if( mxAnnotationData->mbShown && mxAnnotationData->mbUseShapePos )
889 if( SdrCaptionObj* pCaption = dynamic_cast< SdrCaptionObj* >( pObject ) )
891 OSL_ENSURE( !pCaption->GetLogicRect().IsEmpty(), "ScXMLTableRowCellContext::SetAnnotation - invalid caption rectangle" );
892 // create the cell note with the caption object
893 pNote = ScNoteUtil::CreateNoteFromCaption( *pDoc, rPos, *pCaption, true );
894 // forget pointer to object (do not create note again below)
895 pObject = 0;
899 // drawing object has not been used to create a note -> use shape data
900 if( pObject )
902 // rescue settings from drawing object before the shape is removed
903 ::std::unique_ptr< SfxItemSet > xItemSet( new SfxItemSet( pObject->GetMergedItemSet() ) );
904 ::std::unique_ptr< OutlinerParaObject > xOutlinerObj;
905 if( OutlinerParaObject* pOutlinerObj = pObject->GetOutlinerParaObject() )
906 xOutlinerObj.reset( new OutlinerParaObject( *pOutlinerObj ) );
907 Rectangle aCaptionRect;
908 if( mxAnnotationData->mbUseShapePos )
909 aCaptionRect = pObject->GetLogicRect();
910 // remove the shape from the drawing page, this invalidates pObject
911 mxAnnotationData->mxShapes->remove( mxAnnotationData->mxShape );
912 pObject = 0;
913 // update current number of existing objects
914 if( xShapesIA.is() )
915 nOldShapeCount = xShapesIA->getCount();
917 // an outliner object is required (empty note captions not allowed)
918 if( xOutlinerObj.get() )
920 // create cell note with all data from drawing object
921 pNote = ScNoteUtil::CreateNoteFromObjectData( *pDoc, rPos,
922 xItemSet.release(), xOutlinerObj.release(),
923 aCaptionRect, mxAnnotationData->mbShown, false );
927 else if( !mxAnnotationData->maSimpleText.isEmpty() )
929 // create note from simple text
930 pNote = ScNoteUtil::CreateNoteFromString( *pDoc, rPos,
931 mxAnnotationData->maSimpleText, mxAnnotationData->mbShown, false );
934 // set author and date
935 if( pNote )
937 double fDate;
938 if (rXMLImport.GetMM100UnitConverter().convertDateTime(fDate, mxAnnotationData->maCreateDate))
940 SvNumberFormatter* pNumForm = pDoc->GetFormatTable();
941 sal_uInt32 nfIndex = pNumForm->GetFormatIndex( NF_DATE_SYS_DDMMYYYY, LANGUAGE_SYSTEM );
942 OUString aDate;
943 Color* pColor = 0;
944 Color** ppColor = &pColor;
945 pNumForm->GetOutputString( fDate, nfIndex, aDate, ppColor );
946 pNote->SetDate( aDate );
948 pNote->SetAuthor( mxAnnotationData->maAuthor );
951 // register a shape that has been newly created in the ScNoteUtil functions
952 if( xShapesIA.is() && (nOldShapeCount < xShapesIA->getCount()) )
954 uno::Reference< drawing::XShape > xShape;
955 rXMLImport.GetShapeImport()->shapeWithZIndexAdded( xShape, xShapesIA->getCount() );
958 // store the style names for stream copying
959 ScSheetSaveData* pSheetData = ScModelObj::getImplementation(rXMLImport.GetModel())->GetSheetSaveData();
960 pSheetData->HandleNoteStyles( mxAnnotationData->maStyleName, mxAnnotationData->maTextStyle, rPos );
962 std::vector<ScXMLAnnotationStyleEntry>::const_iterator aIter = mxAnnotationData->maContentStyles.begin();
963 std::vector<ScXMLAnnotationStyleEntry>::const_iterator aEnd = mxAnnotationData->maContentStyles.end();
964 while (aIter != aEnd)
966 pSheetData->AddNoteContentStyle( aIter->mnFamily, aIter->maName, rPos, aIter->maSelection );
967 ++aIter;
971 // core implementation
972 void ScXMLTableRowCellContext::SetDetectiveObj( const ScAddress& rPosition )
974 if( cellExists(rPosition) && pDetectiveObjVec && pDetectiveObjVec->size() )
976 LockSolarMutex();
977 ScDetectiveFunc aDetFunc( rXMLImport.GetDocument(), rPosition.Tab() );
978 uno::Reference<container::XIndexAccess> xShapesIndex (rXMLImport.GetTables().GetCurrentXShapes(), uno::UNO_QUERY); // make draw page
979 ScMyImpDetectiveObjVec::iterator aItr(pDetectiveObjVec->begin());
980 ScMyImpDetectiveObjVec::iterator aEndItr(pDetectiveObjVec->end());
981 while(aItr != aEndItr)
983 aDetFunc.InsertObject( aItr->eObjType, rPosition, aItr->aSourceRange, aItr->bHasError );
984 if (xShapesIndex.is())
986 sal_Int32 nShapes = xShapesIndex->getCount();
987 uno::Reference < drawing::XShape > xShape;
988 rXMLImport.GetShapeImport()->shapeWithZIndexAdded(xShape, nShapes);
990 ++aItr;
995 // core implementation
996 void ScXMLTableRowCellContext::SetCellRangeSource( const ScAddress& rPosition )
998 if( cellExists(rPosition) && pCellRangeSource && !pCellRangeSource->sSourceStr.isEmpty() &&
999 !pCellRangeSource->sFilterName.isEmpty() && !pCellRangeSource->sURL.isEmpty() )
1001 ScDocument* pDoc = rXMLImport.GetDocument();
1002 if (pDoc)
1004 LockSolarMutex();
1005 ScRange aDestRange( rPosition.Col(), rPosition.Row(), rPosition.Tab(),
1006 rPosition.Col() + static_cast<SCCOL>(pCellRangeSource->nColumns - 1),
1007 rPosition.Row() + static_cast<SCROW>(pCellRangeSource->nRows - 1), rPosition.Tab() );
1008 OUString sFilterName( pCellRangeSource->sFilterName );
1009 OUString sSourceStr( pCellRangeSource->sSourceStr );
1010 ScAreaLink* pLink = new ScAreaLink( pDoc->GetDocumentShell(), pCellRangeSource->sURL,
1011 sFilterName, pCellRangeSource->sFilterOptions, sSourceStr, aDestRange, pCellRangeSource->nRefresh );
1012 sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
1013 pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, pCellRangeSource->sURL, &sFilterName, &sSourceStr );
1018 void ScXMLTableRowCellContext::SetFormulaCell(ScFormulaCell* pFCell) const
1020 if(pFCell)
1022 if(mbErrorValue)
1024 // don't do anything here
1025 // we need to recalc anyway
1027 else if( bFormulaTextResult && maStringValue )
1029 if( !IsPossibleErrorString() )
1031 ScDocument* pDoc = rXMLImport.GetDocument();
1032 pFCell->SetHybridString(pDoc->GetSharedStringPool().intern(*maStringValue));
1033 pFCell->ResetDirty();
1036 else if (!rtl::math::isNan(fValue))
1038 pFCell->SetHybridDouble(fValue);
1039 pFCell->ResetDirty();
1044 void ScXMLTableRowCellContext::PutTextCell( const ScAddress& rCurrentPos,
1045 const SCCOL nCurrentCol, const ::boost::optional< OUString >& pOUText )
1047 bool bDoIncrement = true;
1048 //matrix reference cells that contain text formula results;
1049 //cell was already put in document, just need to set text here.
1050 if( rXMLImport.GetTables().IsPartOfMatrix(rCurrentPos) )
1052 bDoIncrement = rXMLImport.GetDocument()->GetCellType(rCurrentPos) == CELLTYPE_FORMULA;
1053 if ( bDoIncrement )
1055 ScFormulaCell* pFCell = rXMLImport.GetDocument()->GetFormulaCell(rCurrentPos);
1056 OUString aCellString;
1057 if (maStringValue)
1058 aCellString = *maStringValue;
1059 else if (mbEditEngineHasText)
1060 aCellString = GetFirstParagraph();
1061 else if ( nCurrentCol > 0 && pOUText && !pOUText->isEmpty() )
1062 aCellString = *pOUText;
1063 else
1064 bDoIncrement = false;
1066 if(mbErrorValue)
1067 bDoIncrement = false;
1069 if(!aCellString.isEmpty())
1071 if (bDoIncrement && !IsPossibleErrorString() && pFCell)
1073 ScDocument* pDoc = rXMLImport.GetDocument();
1074 pFCell->SetHybridString(pDoc->GetSharedStringPool().intern(aCellString));
1075 pFCell->ResetDirty();
1077 else
1079 ScAddress aTopLeftMatrixCell;
1080 if (pFCell && pFCell->GetMatrixOrigin(aTopLeftMatrixCell))
1082 ScFormulaCell* pMatrixCell = rXMLImport.GetDocument()->GetFormulaCell(aTopLeftMatrixCell);
1083 if (pMatrixCell)
1084 pMatrixCell->SetDirty();
1086 else
1087 SAL_WARN("sc", "matrix cell without matrix");
1092 else //regular text cells
1094 ScDocumentImport& rDoc = rXMLImport.GetDoc();
1095 if (maStringValue)
1097 rDoc.setStringCell(rCurrentPos, *maStringValue);
1098 bDoIncrement = true;
1100 else if (mbEditEngineHasText)
1102 if (maFirstParagraph)
1104 // This is a normal text without format runs.
1105 rDoc.setStringCell(rCurrentPos, *maFirstParagraph);
1107 else
1109 // This text either has format runs, has field(s), or consists of multiple lines.
1111 ParaFormatsType::const_iterator it = maFormats.begin(), itEnd = maFormats.end();
1112 for (; it != itEnd; ++it)
1113 mpEditEngine->QuickSetAttribs(it->maItemSet, it->maSelection);
1117 FieldsType::const_iterator it = maFields.begin(), itEnd = maFields.end();
1118 for (; it != itEnd; ++it)
1119 mpEditEngine->QuickInsertField(SvxFieldItem(*it->mpData, EE_FEATURE_FIELD), it->maSelection);
1122 // This edit engine uses the SfxItemPool instance returned
1123 // from pDoc->GetEditPool() to create the text object, which
1124 // is a prerequisite for using this constructor of ScEditCell.
1125 rDoc.setEditCell(rCurrentPos, mpEditEngine->CreateTextObject());
1127 bDoIncrement = true;
1129 else if ( nCurrentCol > 0 && pOUText && !pOUText->isEmpty() )
1131 rDoc.setStringCell(rCurrentPos, *pOUText);
1132 bDoIncrement = true;
1134 else
1135 bDoIncrement = false;
1138 // #i56027# This is about setting simple text, not edit cells,
1139 // so ProgressBarIncrement must be called with bEditCell = FALSE.
1140 // Formatted text that is put into the cell by the child context
1141 // is handled in AddCellsToTable() (bIsEmpty is true then).
1142 if (bDoIncrement)
1143 rXMLImport.ProgressBarIncrement(false);
1146 void ScXMLTableRowCellContext::PutValueCell( const ScAddress& rCurrentPos )
1148 //matrix reference cells that contain value formula results;
1149 //cell was already put in document, just need to set value here.
1150 if( rXMLImport.GetTables().IsPartOfMatrix(rCurrentPos) )
1152 if (rXMLImport.GetDocument()->GetCellType(rCurrentPos) == CELLTYPE_FORMULA)
1154 ScFormulaCell* pFCell = rXMLImport.GetDocument()->GetFormulaCell(rCurrentPos);
1155 SetFormulaCell(pFCell);
1156 if (pFCell)
1157 pFCell->SetNeedNumberFormat( true );
1160 else //regular value cell
1162 // fdo#62250 absent values are not NaN, set to 0.0
1163 // PutValueCell() is called only for a known cell value type,
1164 // bIsEmpty==false in all these cases, no sense to check it here.
1165 if (::rtl::math::isNan( fValue))
1166 fValue = 0.0;
1168 // #i62435# Initialize the value cell's script type if the default
1169 // style's number format is latin-only. If the cell uses a different
1170 // format, the script type will be reset when the style is applied.
1172 rXMLImport.GetDoc().setNumericCell(rCurrentPos, fValue);
1174 rXMLImport.ProgressBarIncrement(false);
1177 namespace {
1179 bool isEmptyOrNote( ScDocument* pDoc, const ScAddress& rCurrentPos )
1181 CellType eType = pDoc->GetCellType(rCurrentPos);
1182 return (eType == CELLTYPE_NONE);
1187 void ScXMLTableRowCellContext::AddTextAndValueCell( const ScAddress& rCellPos,
1188 const ::boost::optional< OUString >& pOUText, ScAddress& rCurrentPos )
1190 ScMyTables& rTables = rXMLImport.GetTables();
1191 bool bWasEmpty = bIsEmpty;
1192 for (SCCOL i = 0; i < nColsRepeated; ++i)
1194 rCurrentPos.SetCol( rCellPos.Col() + i );
1196 // it makes no sense to import data after the last supported column
1197 // fdo#58539 & gnome#627150
1198 if(rCurrentPos.Col() > MAXCOL)
1199 break;
1201 if (i > 0)
1202 rTables.AddColumn(false);
1203 if (!bIsEmpty)
1205 for (SCROW j = 0; j < nRepeatedRows; ++j)
1207 rCurrentPos.SetRow( rCellPos.Row() + j );
1209 // it makes no sense to import data after last supported row
1210 // fdo#58539 & gnome#627150
1211 if(rCurrentPos.Row() > MAXROW)
1212 break;
1214 if( (rCurrentPos.Col() == 0) && (j > 0) )
1216 rTables.AddRow();
1217 rTables.AddColumn(false);
1219 if( cellExists(rCurrentPos) )
1221 if( ( !(bIsCovered) || isEmptyOrNote(rXMLImport.GetDocument(), rCurrentPos) ) )
1223 switch (nCellType)
1225 case util::NumberFormat::TEXT:
1227 PutTextCell( rCurrentPos, i, pOUText );
1229 break;
1230 case util::NumberFormat::NUMBER:
1231 case util::NumberFormat::PERCENT:
1232 case util::NumberFormat::CURRENCY:
1233 case util::NumberFormat::TIME:
1234 case util::NumberFormat::DATETIME:
1235 case util::NumberFormat::LOGICAL:
1237 PutValueCell( rCurrentPos );
1239 break;
1240 default:
1242 OSL_FAIL("no cell type given");
1244 break;
1248 SetAnnotation( rCurrentPos );
1249 SetDetectiveObj( rCurrentPos );
1250 SetCellRangeSource( rCurrentPos );
1252 else
1254 if (!bWasEmpty || mxAnnotationData.get())
1256 if (rCurrentPos.Row() > MAXROW)
1257 rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_ROW_OVERFLOW);
1258 else
1259 rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_COLUMN_OVERFLOW);
1264 else
1266 if ((i == 0) && (rCellPos.Col() == 0))
1268 for (sal_Int32 j = 1; j < nRepeatedRows; ++j)
1270 rTables.AddRow();
1271 rTables.AddColumn(false);
1278 bool ScXMLTableRowCellContext::HasSpecialContent() const
1280 return (mxAnnotationData.get() || pDetectiveObjVec || pCellRangeSource);
1283 bool ScXMLTableRowCellContext::CellsAreRepeated() const
1285 return ( (nColsRepeated > 1) || (nRepeatedRows > 1) );
1288 namespace {
1290 // from ScCellObj::GetOutputString_Imp(). all of it may not be necessary.
1291 OUString getOutputString( ScDocument* pDoc, const ScAddress& aCellPos )
1293 if (!pDoc)
1294 return OUString();
1296 CellType eType = pDoc->GetCellType(aCellPos);
1297 switch (eType)
1299 case CELLTYPE_NONE:
1300 return OUString();
1301 case CELLTYPE_EDIT:
1303 // GetString on EditCell replaces linebreaks with spaces;
1304 // however here we need line breaks
1305 const EditTextObject* pData = pDoc->GetEditText(aCellPos);
1306 if (pData)
1308 EditEngine& rEngine = pDoc->GetEditEngine();
1309 rEngine.SetText(*pData);
1310 return rEngine.GetText(LINEEND_LF);
1312 // also don't format EditCells per NumberFormatter
1314 break;
1315 default:
1317 // like in GetString for document (column)
1318 Color* pColor;
1319 sal_uLong nNumFmt = pDoc->GetNumberFormat(aCellPos);
1320 return ScCellFormat::GetString(
1321 *pDoc, aCellPos, nNumFmt, &pColor, *pDoc->GetFormatTable());
1325 return OUString();
1330 void ScXMLTableRowCellContext::AddNonFormulaCell( const ScAddress& rCellPos )
1332 ::boost::optional< OUString > pOUText;
1334 if( nCellType == util::NumberFormat::TEXT )
1336 if( cellExists(rCellPos) && CellsAreRepeated() )
1337 pOUText.reset( getOutputString(rXMLImport.GetDocument(), rCellPos) );
1339 if (!mbEditEngineHasText && !pOUText && !maStringValue)
1340 bIsEmpty = true;
1343 ScAddress aCurrentPos( rCellPos );
1344 if( HasSpecialContent() )
1345 bIsEmpty = false;
1347 AddTextAndValueCell( rCellPos, pOUText, aCurrentPos );
1349 if( CellsAreRepeated() )
1351 SCCOL nStartCol( rCellPos.Col() < MAXCOL ? rCellPos.Col() : MAXCOL );
1352 SCROW nStartRow( rCellPos.Row() < MAXROW ? rCellPos.Row() : MAXROW );
1353 SCCOL nEndCol( rCellPos.Col() + nColsRepeated - 1 < MAXCOL ? rCellPos.Col() + nColsRepeated - 1 : MAXCOL );
1354 SCROW nEndRow( rCellPos.Row() + nRepeatedRows - 1 < MAXROW ? rCellPos.Row() + nRepeatedRows - 1 : MAXROW );
1355 ScRange aScRange( nStartCol, nStartRow, rCellPos.Tab(), nEndCol, nEndRow, rCellPos.Tab() );
1356 SetContentValidation( aScRange );
1357 rXMLImport.GetStylesImportHelper()->AddRange( aScRange );
1359 else if( cellExists(rCellPos) )
1361 rXMLImport.GetStylesImportHelper()->AddCell(rCellPos);
1362 SetContentValidation( rCellPos );
1366 void ScXMLTableRowCellContext::PutFormulaCell( const ScAddress& rCellPos )
1368 ScDocument* pDoc = rXMLImport.GetDocument();
1369 ScDocumentImport& rDoc = rXMLImport.GetDoc();
1371 OUString aText = maFormula->first;
1373 ::boost::scoped_ptr<ScExternalRefManager::ApiGuard> pExtRefGuard (
1374 new ScExternalRefManager::ApiGuard(pDoc));
1376 if ( !aText.isEmpty() )
1378 if ( aText[0] == '=' && aText.getLength() > 1 )
1380 // temporary formula string as string tokens
1381 ScTokenArray *pCode = new ScTokenArray();
1383 OUString aFormulaNmsp = maFormula->second;
1384 if( eGrammar != formula::FormulaGrammar::GRAM_EXTERNAL )
1385 aFormulaNmsp.clear();
1386 pCode->AssignXMLString( aText, aFormulaNmsp );
1388 rDoc.getDoc().IncXMLImportedFormulaCount( aText.getLength() );
1389 ScFormulaCell* pNewCell = new ScFormulaCell(pDoc, rCellPos, pCode, eGrammar, MM_NONE);
1390 SetFormulaCell(pNewCell);
1391 rDoc.setFormulaCell(rCellPos, pNewCell);
1393 // Re-calculate to get number format only when style is not set.
1394 pNewCell->SetNeedNumberFormat(!mbHasStyle);
1396 else if ( aText[0] == '\'' && aText.getLength() > 1 )
1398 // for bEnglish, "'" at the beginning is always interpreted as text
1399 // marker and stripped
1400 rDoc.setStringCell(rCellPos, aText.copy(1));
1402 else
1404 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
1405 sal_uInt32 nEnglish = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
1406 double fVal;
1407 if ( pFormatter->IsNumberFormat( aText, nEnglish, fVal ) )
1408 rDoc.setNumericCell(rCellPos, fVal);
1409 //the (english) number format will not be set
1410 //search matching local format and apply it
1411 else
1412 rDoc.setStringCell(rCellPos, aText);
1417 void ScXMLTableRowCellContext::AddFormulaCell( const ScAddress& rCellPos )
1419 if( cellExists(rCellPos) )
1421 SetContentValidation( rCellPos );
1422 SAL_WARN_IF((nColsRepeated != 1) || (nRepeatedRows != 1), "sc", "repeated cells with formula not possible now");
1423 rXMLImport.GetStylesImportHelper()->AddCell(rCellPos);
1425 //add matrix
1426 if(bIsMatrix)
1428 if (nMatrixCols > 0 && nMatrixRows > 0)
1430 //matrix cells are put in the document, but we must set the
1431 //value/text of each matrix cell later
1432 rXMLImport.GetTables().AddMatrixRange(
1433 rCellPos.Col(), rCellPos.Row(),
1434 std::min<SCCOL>(rCellPos.Col() + nMatrixCols - 1, MAXCOL),
1435 std::min<SCROW>(rCellPos.Row() + nMatrixRows - 1, MAXROW),
1436 maFormula->first, maFormula->second, eGrammar);
1438 // Set the value/text of the top-left matrix position in its
1439 // cached result. For import, we only need to set the correct
1440 // matrix geometry and the value type of the top-left element.
1441 ScFormulaCell* pFCell = rXMLImport.GetDocument()->GetFormulaCell(rCellPos);
1442 if (pFCell)
1444 ScMatrixRef pMat(new ScMatrix(nMatrixCols, nMatrixRows));
1445 if (bFormulaTextResult && maStringValue)
1447 if (!IsPossibleErrorString())
1449 pFCell->SetResultMatrix(
1450 nMatrixCols, nMatrixRows, pMat, new formula::FormulaStringToken(*maStringValue));
1451 pFCell->ResetDirty();
1454 else if (!rtl::math::isNan(fValue))
1456 pFCell->SetResultMatrix(
1457 nMatrixCols, nMatrixRows, pMat, new formula::FormulaDoubleToken(fValue));
1458 pFCell->ResetDirty();
1463 else
1464 PutFormulaCell( rCellPos );
1466 SetAnnotation( rCellPos );
1467 SetDetectiveObj( rCellPos );
1468 SetCellRangeSource( rCellPos );
1469 rXMLImport.ProgressBarIncrement(false);
1471 else
1473 if (rCellPos.Row() > MAXROW)
1474 rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_ROW_OVERFLOW);
1475 else
1476 rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_COLUMN_OVERFLOW);
1480 //There are cases where a formula cell is exported with an office:value of 0 or
1481 //no office:value at all, but the formula cell will have a text:p value which
1482 //contains the intended formula result.
1483 //These cases include when a formula result:
1484 // - is blank
1485 // - has a constant error value beginning with "#" (such as "#VALUE!" or "#N/A")
1486 // - has an "Err:[###]" (where "[###]" is an error number)
1487 // Libreoffice 4.1+ with ODF1.2 extended write however calcext:value-type="error" in that case
1488 void ScXMLTableRowCellContext::HasSpecialCaseFormulaText()
1490 if (!mbEditEngineHasText || mbNewValueType)
1491 return;
1493 OUString aStr = GetFirstParagraph();
1495 if (aStr.isEmpty() || aStr.startsWith("Err:"))
1496 mbPossibleErrorCell = true;
1497 else if (aStr.startsWith("#"))
1498 mbCheckWithCompilerForError = true;
1501 bool ScXMLTableRowCellContext::IsPossibleErrorString() const
1503 if(mbNewValueType && !mbErrorValue)
1504 return false;
1505 else if(mbNewValueType && mbErrorValue)
1506 return true;
1507 return mbPossibleErrorCell || ( mbCheckWithCompilerForError && GetScImport().IsFormulaErrorConstant(*maStringValue) );
1510 void ScXMLTableRowCellContext::EndElement()
1512 HasSpecialCaseFormulaText();
1513 if( bFormulaTextResult && (mbPossibleErrorCell || mbCheckWithCompilerForError) )
1515 maStringValue.reset(GetFirstParagraph());
1516 nCellType = util::NumberFormat::TEXT;
1519 ScAddress aCellPos = rXMLImport.GetTables().GetCurrentCellPos();
1520 if( aCellPos.Col() > 0 && nRepeatedRows > 1 )
1521 aCellPos.SetRow( aCellPos.Row() - (nRepeatedRows - 1) );
1522 if( bIsMerged )
1523 DoMerge( aCellPos, nMergedCols - 1, nMergedRows - 1 );
1525 if (maFormula)
1526 AddFormulaCell(aCellPos);
1527 else
1528 AddNonFormulaCell(aCellPos);
1530 UnlockSolarMutex(); //if LockSolarMutex got used, we presumably need to ensure an UnlockSolarMutex
1532 bIsMerged = false;
1533 nMergedCols = 1;
1534 nMergedRows = 1;
1535 nColsRepeated = 1;
1538 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */