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