1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
26 #include "document.hxx"
27 #include "cellsuno.hxx"
29 #include "unonames.hxx"
31 #include "sheetdata.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()
133 ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport
& rImport
,
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()),
143 pDetectiveObjVec(NULL
),
144 pCellRangeSource(NULL
),
148 nRepeatedRows(nTempRepeatedRows
),
152 rXMLImport((ScXMLImport
&)rImport
),
153 eGrammar( formula::FormulaGrammar::GRAM_STORAGE_DEFAULT
),
154 nCellType(util::NumberFormat::TEXT
),
157 bIsCovered(bTempIsCovered
),
159 mbNewValueType(false),
161 bIsFirstTextImport(false),
162 bSolarMutexLocked(false),
163 bFormulaTextResult(false),
164 mbPossibleErrorCell(false),
165 mbCheckWithCompilerForError(false),
166 mbEditEngineHasText(false),
167 mbHasFormatRuns(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;
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
);
188 case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME
:
189 pStyleName
= new OUString(sValue
);
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
);
197 case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_ROWS
:
199 nMergedRows
= static_cast<SCROW
>(sValue
.toInt32());
201 case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_COLS
:
203 nMergedCols
= static_cast<SCCOL
>(sValue
.toInt32());
205 case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_COLS
:
207 nMatrixCols
= static_cast<SCCOL
>(sValue
.toInt32());
209 case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_ROWS
:
211 nMatrixRows
= static_cast<SCROW
>(sValue
.toInt32());
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) ) ));
217 case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE
:
218 nCellType
= GetScImport().GetCellType(sValue
);
221 case XML_TOK_TABLE_ROW_CELL_ATTR_NEW_VALUE_TYPE
:
222 if(sValue
== "error")
225 nCellType
= GetScImport().GetCellType(sValue
);
227 mbNewValueType
= true;
229 case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE
:
231 if (!sValue
.isEmpty())
233 ::sax::Converter::convertDouble(fValue
, sValue
);
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.
240 bFormulaTextResult
= true;
244 case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE
:
246 if (!sValue
.isEmpty() && rXMLImport
.SetNullDateOnUnitConverter())
248 rXMLImport
.GetMM100UnitConverter().convertDateTime(fValue
, sValue
);
253 case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE
:
255 if (!sValue
.isEmpty())
257 ::sax::Converter::convertDuration(fValue
, sValue
);
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
);
272 case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE
:
274 if (!sValue
.isEmpty())
276 if ( IsXMLToken(sValue
, XML_TRUE
) )
278 else if ( IsXMLToken(sValue
, XML_FALSE
) )
281 ::sax::Converter::convertDouble(fValue
, sValue
);
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
) );
297 case XML_TOK_TABLE_ROW_CELL_ATTR_CURRENCY
:
298 pCurrencySymbol
= new OUString(sValue
);
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().
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;
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())
383 // Get the style information from xmloff.
384 rtl::Reference
<XMLPropertySetMapper
> xMapper
= GetImport().GetTextImport()->GetTextImportPropertySetMapper()->getPropertySetMapper();
386 // We can't do anything without the mapper.
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
));
398 // No style by that name found.
401 const std::vector
<XMLPropertyState
>& rProps
= pStyle
->GetProperties();
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
)
428 const OUString
& rName
= xMapper
->GetEntryAPIName(it
->mnIndex
);
429 const ScXMLEditAttributeMap::Entry
* pEntry
= rEditAttrMap
.getEntryByAPIName(rName
);
433 if (nLastItemID
!= pEntry
->mnItemID
&& pPoolItem
)
435 // Flush the last item when the item ID changes.
436 rFmt
.maItemSet
.Put(*pPoolItem
);
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.
448 pPoolItem
.reset(new SvxFontItem(pEntry
->mnItemID
));
450 pPoolItem
->PutValue(it
->maValue
, pEntry
->mnFlag
);
454 case EE_CHAR_WEIGHT_CJK
:
455 case EE_CHAR_WEIGHT_CTL
:
458 pPoolItem
.reset(new SvxWeightItem(WEIGHT_NORMAL
, pEntry
->mnItemID
));
460 pPoolItem
->PutValue(it
->maValue
, pEntry
->mnFlag
);
463 case EE_CHAR_FONTHEIGHT
:
464 case EE_CHAR_FONTHEIGHT_CJK
:
465 case EE_CHAR_FONTHEIGHT_CTL
:
468 pPoolItem
.reset(new SvxFontHeightItem(240, 100, pEntry
->mnItemID
));
470 pPoolItem
->PutValue(it
->maValue
, pEntry
->mnFlag
);
474 case EE_CHAR_ITALIC_CJK
:
475 case EE_CHAR_ITALIC_CTL
:
478 pPoolItem
.reset(new SvxPostureItem(ITALIC_NONE
, pEntry
->mnItemID
));
480 pPoolItem
->PutValue(it
->maValue
, pEntry
->mnFlag
);
483 case EE_CHAR_UNDERLINE
:
486 pPoolItem
.reset(new SvxUnderlineItem(UNDERLINE_NONE
, pEntry
->mnItemID
));
488 pPoolItem
->PutValue(it
->maValue
, pEntry
->mnFlag
);
491 case EE_CHAR_OVERLINE
:
494 pPoolItem
.reset(new SvxOverlineItem(UNDERLINE_NONE
, pEntry
->mnItemID
));
496 pPoolItem
->PutValue(it
->maValue
, pEntry
->mnFlag
);
502 pPoolItem
.reset(new SvxColorItem(pEntry
->mnItemID
));
504 pPoolItem
->PutValue(it
->maValue
, pEntry
->mnFlag
);
510 pPoolItem
.reset(new SvxWordLineModeItem(false, pEntry
->mnItemID
));
512 pPoolItem
->PutValue(it
->maValue
, pEntry
->mnFlag
);
515 case EE_CHAR_STRIKEOUT
:
518 pPoolItem
.reset(new SvxCrossedOutItem(STRIKEOUT_NONE
, pEntry
->mnItemID
));
520 pPoolItem
->PutValue(it
->maValue
, pEntry
->mnFlag
);
526 pPoolItem
.reset(new SvxCharReliefItem(RELIEF_NONE
, pEntry
->mnItemID
));
528 pPoolItem
->PutValue(it
->maValue
, pEntry
->mnFlag
);
531 case EE_CHAR_OUTLINE
:
534 pPoolItem
.reset(new SvxContourItem(false, pEntry
->mnItemID
));
536 pPoolItem
->PutValue(it
->maValue
, pEntry
->mnFlag
);
542 pPoolItem
.reset(new SvxShadowedItem(false, pEntry
->mnItemID
));
544 pPoolItem
->PutValue(it
->maValue
, pEntry
->mnFlag
);
547 case EE_CHAR_KERNING
:
550 pPoolItem
.reset(new SvxKerningItem(0, pEntry
->mnItemID
));
552 pPoolItem
->PutValue(it
->maValue
, pEntry
->mnFlag
);
555 case EE_CHAR_PAIRKERNING
:
558 pPoolItem
.reset(new SvxAutoKernItem(false, pEntry
->mnItemID
));
560 pPoolItem
->PutValue(it
->maValue
, pEntry
->mnFlag
);
563 case EE_CHAR_FONTWIDTH
:
566 pPoolItem
.reset(new SvxCharScaleWidthItem(100, pEntry
->mnItemID
));
568 pPoolItem
->PutValue(it
->maValue
, pEntry
->mnFlag
);
571 case EE_CHAR_ESCAPEMENT
:
574 pPoolItem
.reset(new SvxEscapementItem(pEntry
->mnItemID
));
576 pPoolItem
->PutValue(it
->maValue
, pEntry
->mnFlag
);
579 case EE_CHAR_EMPHASISMARK
:
582 pPoolItem
.reset(new SvxEmphasisMarkItem(EMPHASISMARK_NONE
, pEntry
->mnItemID
));
584 pPoolItem
->PutValue(it
->maValue
, pEntry
->mnFlag
);
587 case EE_CHAR_LANGUAGE
:
588 case EE_CHAR_LANGUAGE_CJK
:
589 case EE_CHAR_LANGUAGE_CTL
:
592 pPoolItem
.reset(new SvxLanguageItem(LANGUAGE_DONTKNOW
, pEntry
->mnItemID
));
594 pPoolItem
->PutValue(it
->maValue
, pEntry
->mnFlag
);
601 nLastItemID
= pEntry
->mnItemID
;
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;
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();
678 switch( rTokenMap
.Get( nPrefix
, rLName
) )
680 case XML_TOK_TABLE_ROW_CELL_P
:
685 pContext
= new ScXMLCellTextParaContext(rXMLImport
, nPrefix
, rLName
, *this);
688 case XML_TOK_TABLE_ROW_CELL_TABLE
:
690 SAL_WARN("sc", "ScXMLTableRowCellContext::CreateChildContext: subtables are not supported");
693 case XML_TOK_TABLE_ROW_CELL_ANNOTATION
:
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);
702 case XML_TOK_TABLE_ROW_CELL_DETECTIVE
:
705 if (!pDetectiveObjVec
)
706 pDetectiveObjVec
= new ScMyImpDetectiveObjVec();
707 pContext
= new ScXMLDetectiveContext(
708 rXMLImport
, nPrefix
, rLName
, pDetectiveObjVec
);
711 case XML_TOK_TABLE_ROW_CELL_CELL_RANGE_SOURCE
:
714 if (!pCellRangeSource
)
715 pCellRangeSource
= new ScMyImpCellRangeSource();
716 pContext
= new ScXMLCellRangeSourceContext(
717 rXMLImport
, nPrefix
, rLName
, xAttrList
, pCellRangeSource
);
722 if (!pContext
&& !bTextP
)
724 ScAddress aCellPos
= rXMLImport
.GetTables().GetCurrentCellPos();
725 uno::Reference
<drawing::XShapes
> xShapes (rXMLImport
.GetTables().GetCurrentXShapes());
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
);
743 rXMLImport
.ProgressBarIncrement(false);
749 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLName
);
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
;
762 rXMLImport
.GetDocument()->DoMerge( rScAddress
.Tab(),
763 rScAddress
.Col(), rScAddress
.Row(), mergeToCol
, mergeToRow
);
769 ScValidationMode
validationTypeToMode( const sheet::ValidationType eVType
)
771 ScValidationMode eMode
;
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;
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.
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() )
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)
899 // drawing object has not been used to create a note -> use shape data
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
);
913 // update current number of existing objects
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
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
);
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
);
971 // core implementation
972 void ScXMLTableRowCellContext::SetDetectiveObj( const ScAddress
& rPosition
)
974 if( cellExists(rPosition
) && pDetectiveObjVec
&& pDetectiveObjVec
->size() )
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
);
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();
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
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
;
1055 ScFormulaCell
* pFCell
= rXMLImport
.GetDocument()->GetFormulaCell(rCurrentPos
);
1056 OUString aCellString
;
1058 aCellString
= *maStringValue
;
1059 else if (mbEditEngineHasText
)
1060 aCellString
= GetFirstParagraph();
1061 else if ( nCurrentCol
> 0 && pOUText
&& !pOUText
->isEmpty() )
1062 aCellString
= *pOUText
;
1064 bDoIncrement
= false;
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();
1079 ScAddress aTopLeftMatrixCell
;
1080 if (pFCell
&& pFCell
->GetMatrixOrigin(aTopLeftMatrixCell
))
1082 ScFormulaCell
* pMatrixCell
= rXMLImport
.GetDocument()->GetFormulaCell(aTopLeftMatrixCell
);
1084 pMatrixCell
->SetDirty();
1087 SAL_WARN("sc", "matrix cell without matrix");
1092 else //regular text cells
1094 ScDocumentImport
& rDoc
= rXMLImport
.GetDoc();
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
);
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;
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).
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
);
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
))
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);
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
)
1202 rTables
.AddColumn(false);
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
)
1214 if( (rCurrentPos
.Col() == 0) && (j
> 0) )
1217 rTables
.AddColumn(false);
1219 if( cellExists(rCurrentPos
) )
1221 if( ( !(bIsCovered
) || isEmptyOrNote(rXMLImport
.GetDocument(), rCurrentPos
) ) )
1225 case util::NumberFormat::TEXT
:
1227 PutTextCell( rCurrentPos
, i
, pOUText
);
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
);
1242 OSL_FAIL("no cell type given");
1248 SetAnnotation( rCurrentPos
);
1249 SetDetectiveObj( rCurrentPos
);
1250 SetCellRangeSource( rCurrentPos
);
1254 if (!bWasEmpty
|| mxAnnotationData
.get())
1256 if (rCurrentPos
.Row() > MAXROW
)
1257 rXMLImport
.SetRangeOverflowType(SCWARN_IMPORT_ROW_OVERFLOW
);
1259 rXMLImport
.SetRangeOverflowType(SCWARN_IMPORT_COLUMN_OVERFLOW
);
1266 if ((i
== 0) && (rCellPos
.Col() == 0))
1268 for (sal_Int32 j
= 1; j
< nRepeatedRows
; ++j
)
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) );
1290 // from ScCellObj::GetOutputString_Imp(). all of it may not be necessary.
1291 OUString
getOutputString( ScDocument
* pDoc
, const ScAddress
& aCellPos
)
1296 CellType eType
= pDoc
->GetCellType(aCellPos
);
1303 // GetString on EditCell replaces linebreaks with spaces;
1304 // however here we need line breaks
1305 const EditTextObject
* pData
= pDoc
->GetEditText(aCellPos
);
1308 EditEngine
& rEngine
= pDoc
->GetEditEngine();
1309 rEngine
.SetText(*pData
);
1310 return rEngine
.GetText(LINEEND_LF
);
1312 // also don't format EditCells per NumberFormatter
1317 // like in GetString for document (column)
1319 sal_uLong nNumFmt
= pDoc
->GetNumberFormat(aCellPos
);
1320 return ScCellFormat::GetString(
1321 *pDoc
, aCellPos
, nNumFmt
, &pColor
, *pDoc
->GetFormatTable());
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
)
1343 ScAddress
aCurrentPos( rCellPos
);
1344 if( HasSpecialContent() )
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));
1404 SvNumberFormatter
* pFormatter
= pDoc
->GetFormatTable();
1405 sal_uInt32 nEnglish
= pFormatter
->GetStandardIndex(LANGUAGE_ENGLISH_US
);
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
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
);
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
);
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();
1464 PutFormulaCell( rCellPos
);
1466 SetAnnotation( rCellPos
);
1467 SetDetectiveObj( rCellPos
);
1468 SetCellRangeSource( rCellPos
);
1469 rXMLImport
.ProgressBarIncrement(false);
1473 if (rCellPos
.Row() > MAXROW
)
1474 rXMLImport
.SetRangeOverflowType(SCWARN_IMPORT_ROW_OVERFLOW
);
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:
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
)
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
)
1505 else if(mbNewValueType
&& mbErrorValue
)
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) );
1523 DoMerge( aCellPos
, nMergedCols
- 1, nMergedRows
- 1 );
1526 AddFormulaCell(aCellPos
);
1528 AddNonFormulaCell(aCellPos
);
1530 UnlockSolarMutex(); //if LockSolarMutex got used, we presumably need to ensure an UnlockSolarMutex
1538 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */