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 392 : ScXMLTableRowCellContext::ParaFormat::ParaFormat(ScEditEngineDefaulter& rEditEngine) :
124 392 : maItemSet(rEditEngine.GetEmptyItemSet()) {}
125 :
126 16 : ScXMLTableRowCellContext::Field::Field(SvxFieldData* pData) : mpData(pData) {}
127 :
128 16 : ScXMLTableRowCellContext::Field::~Field()
129 : {
130 16 : delete mpData;
131 16 : }
132 :
133 14558 : 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 14558 : 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 29116 : mbHasStyle(false)
169 : {
170 14558 : rtl::math::setNan(&fValue); // NaN by default
171 :
172 14558 : rXMLImport.SetRemoveLastChar(false);
173 14558 : rXMLImport.GetTables().AddColumn(bTempIsCovered);
174 14558 : const sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
175 14558 : OUString aLocalName;
176 14558 : OUString* pStyleName = NULL;
177 14558 : OUString* pCurrencySymbol = NULL;
178 14558 : const SvXMLTokenMap& rTokenMap = rImport.GetTableRowCellAttrTokenMap();
179 41668 : for (sal_Int16 i = 0; i < nAttrCount; ++i)
180 : {
181 27110 : sal_uInt16 nAttrPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(
182 54220 : xAttrList->getNameByIndex(i), &aLocalName);
183 :
184 27110 : const OUString& sValue = xAttrList->getValueByIndex(i);
185 27110 : sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName);
186 27110 : switch (nToken)
187 : {
188 : case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME:
189 4006 : pStyleName = new OUString(sValue);
190 4006 : mbHasStyle = true;
191 4006 : break;
192 : case XML_TOK_TABLE_ROW_CELL_ATTR_CONTENT_VALIDATION_NAME:
193 : OSL_ENSURE(!maContentValidationName, "here should be only one Validation Name");
194 14 : if (!sValue.isEmpty())
195 14 : maContentValidationName.reset(sValue);
196 14 : break;
197 : case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_ROWS:
198 8 : bIsMerged = true;
199 8 : nMergedRows = static_cast<SCROW>(sValue.toInt32());
200 8 : break;
201 : case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_COLS:
202 8 : bIsMerged = true;
203 8 : nMergedCols = static_cast<SCCOL>(sValue.toInt32());
204 8 : break;
205 : case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_COLS:
206 45 : bIsMatrix = true;
207 45 : nMatrixCols = static_cast<SCCOL>(sValue.toInt32());
208 45 : break;
209 : case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_ROWS:
210 45 : bIsMatrix = true;
211 45 : nMatrixRows = static_cast<SCROW>(sValue.toInt32());
212 45 : break;
213 : case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
214 : nColsRepeated = static_cast<SCCOL>(std::min<sal_Int32>( MAXCOLCOUNT,
215 2615 : std::max( sValue.toInt32(), static_cast<sal_Int32>(1) ) ));
216 2615 : break;
217 : case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE:
218 8719 : nCellType = GetScImport().GetCellType(sValue);
219 8719 : bIsEmpty = false;
220 8719 : break;
221 : case XML_TOK_TABLE_ROW_CELL_ATTR_NEW_VALUE_TYPE:
222 4629 : if(sValue == "error")
223 22 : mbErrorValue = true;
224 : else
225 4607 : nCellType = GetScImport().GetCellType(sValue);
226 4629 : bIsEmpty = false;
227 4629 : mbNewValueType = true;
228 4629 : break;
229 : case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE:
230 : {
231 4331 : if (!sValue.isEmpty())
232 : {
233 4331 : ::sax::Converter::convertDouble(fValue, sValue);
234 4331 : 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 4331 : if(fValue == 0.0)
240 88 : bFormulaTextResult = true;
241 : }
242 : }
243 4331 : break;
244 : case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE:
245 : {
246 236 : if (!sValue.isEmpty() && rXMLImport.SetNullDateOnUnitConverter())
247 : {
248 236 : rXMLImport.GetMM100UnitConverter().convertDateTime(fValue, sValue);
249 236 : bIsEmpty = false;
250 : }
251 : }
252 236 : break;
253 : case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE:
254 : {
255 220 : if (!sValue.isEmpty())
256 : {
257 220 : ::sax::Converter::convertDuration(fValue, sValue);
258 220 : bIsEmpty = false;
259 : }
260 : }
261 220 : break;
262 : case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE:
263 : {
264 187 : if (!sValue.isEmpty())
265 : {
266 : OSL_ENSURE(!maStringValue, "here should be only one string value");
267 165 : maStringValue.reset(sValue);
268 165 : bIsEmpty = false;
269 : }
270 : }
271 187 : break;
272 : case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE:
273 : {
274 474 : if (!sValue.isEmpty())
275 : {
276 474 : if ( IsXMLToken(sValue, XML_TRUE) )
277 207 : fValue = 1.0;
278 267 : else if ( IsXMLToken(sValue, XML_FALSE) )
279 263 : fValue = 0.0;
280 : else
281 4 : ::sax::Converter::convertDouble(fValue, sValue);
282 474 : bIsEmpty = false;
283 : }
284 : }
285 474 : break;
286 : case XML_TOK_TABLE_ROW_CELL_ATTR_FORMULA:
287 : {
288 1550 : if (!sValue.isEmpty())
289 : {
290 : OSL_ENSURE(!maFormula, "here should be only one formula");
291 3100 : OUString aFormula, aFormulaNmsp;
292 1550 : rXMLImport.ExtractFormulaNamespaceGrammar( aFormula, aFormulaNmsp, eGrammar, sValue );
293 3100 : maFormula.reset( FormulaWithNamespace(aFormula, aFormulaNmsp) );
294 : }
295 : }
296 1550 : break;
297 : case XML_TOK_TABLE_ROW_CELL_ATTR_CURRENCY:
298 23 : pCurrencySymbol = new OUString(sValue);
299 23 : break;
300 : default:
301 : ;
302 : }
303 27110 : }
304 14558 : if (maFormula)
305 : {
306 1550 : if (nCellType == util::NumberFormat::TEXT)
307 189 : bFormulaTextResult = true;
308 1550 : if(nCellType == util::NumberFormat::DATETIME)
309 6 : 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 1550 : if(bIsEmpty)
314 5 : bFormulaTextResult = true;
315 : }
316 14558 : rXMLImport.GetStylesImportHelper()->SetAttributes(pStyleName, pCurrencySymbol, nCellType);
317 14558 : }
318 :
319 43674 : ScXMLTableRowCellContext::~ScXMLTableRowCellContext()
320 : {
321 14558 : delete pDetectiveObjVec;
322 14558 : delete pCellRangeSource;
323 29116 : }
324 :
325 16 : void ScXMLTableRowCellContext::LockSolarMutex()
326 : {
327 16 : if (!bSolarMutexLocked)
328 : {
329 16 : GetScImport().LockSolarMutex();
330 16 : bSolarMutexLocked = true;
331 : }
332 16 : }
333 :
334 14558 : void ScXMLTableRowCellContext::UnlockSolarMutex()
335 : {
336 14558 : if (bSolarMutexLocked)
337 : {
338 16 : GetScImport().UnlockSolarMutex();
339 16 : bSolarMutexLocked = false;
340 : }
341 14558 : }
342 :
343 : namespace {
344 :
345 47388 : bool cellExists( const ScAddress& rCellPos )
346 : {
347 142164 : return( rCellPos.Col() >= 0 && rCellPos.Row() >= 0 &&
348 142164 : rCellPos.Col() <= MAXCOL && rCellPos.Row() <= MAXROW );
349 : }
350 :
351 : }
352 :
353 8819 : void ScXMLTableRowCellContext::PushParagraphSpan(const OUString& rSpan, const OUString& rStyleName)
354 : {
355 8819 : sal_Int32 nBegin = maParagraph.getLength();
356 8819 : sal_Int32 nEnd = nBegin + rSpan.getLength();
357 8819 : maParagraph.append(rSpan);
358 :
359 8819 : PushFormat(nBegin, nEnd, rStyleName);
360 8819 : }
361 :
362 16 : void ScXMLTableRowCellContext::PushParagraphField(SvxFieldData* pData, const OUString& rStyleName)
363 : {
364 16 : mbHasFormatRuns = true;
365 16 : maFields.push_back(new Field(pData));
366 16 : Field& rField = maFields.back();
367 :
368 16 : sal_Int32 nPos = maParagraph.getLength();
369 16 : maParagraph.append('\1'); // Placeholder text for inserted field item.
370 16 : rField.maSelection.nStartPara = mnCurParagraph;
371 16 : rField.maSelection.nEndPara = mnCurParagraph;
372 16 : rField.maSelection.nStartPos = nPos;
373 16 : rField.maSelection.nEndPos = nPos+1;
374 :
375 16 : PushFormat(nPos, nPos+1, rStyleName);
376 16 : }
377 :
378 8835 : void ScXMLTableRowCellContext::PushFormat(sal_Int32 nBegin, sal_Int32 nEnd, const OUString& rStyleName)
379 : {
380 8835 : if (rStyleName.isEmpty())
381 16873 : return;
382 :
383 : // Get the style information from xmloff.
384 405 : rtl::Reference<XMLPropertySetMapper> xMapper = GetImport().GetTextImport()->GetTextImportPropertySetMapper()->getPropertySetMapper();
385 405 : if (!xMapper.is())
386 : // We can't do anything without the mapper.
387 0 : return;
388 :
389 405 : sal_Int32 nEntryCount = xMapper->GetEntryCount();
390 :
391 405 : 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 405 : pAutoStyles->FindStyleChildContext(XML_STYLE_FAMILY_TEXT_TEXT, rStyleName));
396 :
397 405 : if (!pStyle)
398 : // No style by that name found.
399 0 : return;
400 :
401 405 : const std::vector<XMLPropertyState>& rProps = pStyle->GetProperties();
402 405 : if (rProps.empty())
403 13 : return;
404 :
405 392 : const ScXMLEditAttributeMap& rEditAttrMap = GetScImport().GetEditAttributeMap();
406 :
407 392 : mbHasFormatRuns = true;
408 392 : maFormats.push_back(new ParaFormat(*mpEditEngine));
409 392 : ParaFormat& rFmt = maFormats.back();
410 392 : rFmt.maSelection.nStartPara = rFmt.maSelection.nEndPara = mnCurParagraph;
411 392 : rFmt.maSelection.nStartPos = nBegin;
412 392 : rFmt.maSelection.nEndPos = nEnd;
413 :
414 : // Store the used text styles for export.
415 392 : ScSheetSaveData* pSheetData = ScModelObj::getImplementation(rXMLImport.GetModel())->GetSheetSaveData();
416 392 : ScAddress aCellPos = rXMLImport.GetTables().GetCurrentCellPos();
417 392 : pSheetData->AddTextStyle(rStyleName, aCellPos, rFmt.maSelection);
418 :
419 784 : boost::scoped_ptr<SfxPoolItem> pPoolItem;
420 392 : sal_uInt16 nLastItemID = EE_CHAR_END + 1;
421 :
422 392 : std::vector<XMLPropertyState>::const_iterator it = rProps.begin(), itEnd = rProps.end();
423 7540 : for (; it != itEnd; ++it)
424 : {
425 7148 : if (it->mnIndex == -1 || it->mnIndex >= nEntryCount)
426 0 : continue;
427 :
428 7148 : const OUString& rName = xMapper->GetEntryAPIName(it->mnIndex);
429 7148 : const ScXMLEditAttributeMap::Entry* pEntry = rEditAttrMap.getEntryByAPIName(rName);
430 7148 : if (!pEntry)
431 0 : continue;
432 :
433 7148 : if (nLastItemID != pEntry->mnItemID && pPoolItem)
434 : {
435 : // Flush the last item when the item ID changes.
436 2393 : rFmt.maItemSet.Put(*pPoolItem);
437 2393 : pPoolItem.reset();
438 : }
439 :
440 7148 : 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 5440 : if (!pPoolItem)
448 1088 : pPoolItem.reset(new SvxFontItem(pEntry->mnItemID));
449 :
450 5440 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
451 : }
452 5440 : break;
453 : case EE_CHAR_WEIGHT:
454 : case EE_CHAR_WEIGHT_CJK:
455 : case EE_CHAR_WEIGHT_CTL:
456 : {
457 99 : if (!pPoolItem)
458 99 : pPoolItem.reset(new SvxWeightItem(WEIGHT_NORMAL, pEntry->mnItemID));
459 :
460 99 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
461 : }
462 99 : break;
463 : case EE_CHAR_FONTHEIGHT:
464 : case EE_CHAR_FONTHEIGHT_CJK:
465 : case EE_CHAR_FONTHEIGHT_CTL:
466 : {
467 1086 : if (!pPoolItem)
468 1086 : pPoolItem.reset(new SvxFontHeightItem(240, 100, pEntry->mnItemID));
469 :
470 1086 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
471 : }
472 1086 : break;
473 : case EE_CHAR_ITALIC:
474 : case EE_CHAR_ITALIC_CJK:
475 : case EE_CHAR_ITALIC_CTL:
476 : {
477 69 : if (!pPoolItem)
478 69 : pPoolItem.reset(new SvxPostureItem(ITALIC_NONE, pEntry->mnItemID));
479 :
480 69 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
481 : }
482 69 : break;
483 : case EE_CHAR_UNDERLINE:
484 : {
485 30 : if (!pPoolItem)
486 24 : pPoolItem.reset(new SvxUnderlineItem(UNDERLINE_NONE, pEntry->mnItemID));
487 :
488 30 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
489 : }
490 30 : break;
491 : case EE_CHAR_OVERLINE:
492 : {
493 2 : if (!pPoolItem)
494 1 : pPoolItem.reset(new SvxOverlineItem(UNDERLINE_NONE, pEntry->mnItemID));
495 :
496 2 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
497 : }
498 2 : break;
499 : case EE_CHAR_COLOR:
500 : {
501 358 : if (!pPoolItem)
502 358 : pPoolItem.reset(new SvxColorItem(pEntry->mnItemID));
503 :
504 358 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
505 : }
506 358 : 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 2 : if (!pPoolItem)
518 2 : pPoolItem.reset(new SvxCrossedOutItem(STRIKEOUT_NONE, pEntry->mnItemID));
519 :
520 2 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
521 : }
522 2 : 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 4 : if (!pPoolItem)
534 4 : pPoolItem.reset(new SvxContourItem(false, pEntry->mnItemID));
535 :
536 4 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
537 : }
538 4 : break;
539 : case EE_CHAR_SHADOW:
540 : {
541 4 : if (!pPoolItem)
542 4 : pPoolItem.reset(new SvxShadowedItem(false, pEntry->mnItemID));
543 :
544 4 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
545 : }
546 4 : 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 8 : if (!pPoolItem)
574 4 : pPoolItem.reset(new SvxEscapementItem(pEntry->mnItemID));
575 :
576 8 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
577 : }
578 8 : 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 46 : if (!pPoolItem)
592 46 : pPoolItem.reset(new SvxLanguageItem(LANGUAGE_DONTKNOW, pEntry->mnItemID));
593 :
594 46 : pPoolItem->PutValue(it->maValue, pEntry->mnFlag);
595 : }
596 46 : break;
597 : default:
598 : ;
599 : }
600 :
601 7148 : nLastItemID = pEntry->mnItemID;
602 : }
603 :
604 392 : if (pPoolItem)
605 784 : rFmt.maItemSet.Put(*pPoolItem);
606 : }
607 :
608 4496 : OUString ScXMLTableRowCellContext::GetFirstParagraph() const
609 : {
610 4496 : if (!maFirstParagraph)
611 376 : return mpEditEngine->GetText(0);
612 :
613 4120 : return *maFirstParagraph;
614 : }
615 :
616 2 : void ScXMLTableRowCellContext::PushParagraphFieldDate(const OUString& rStyleName)
617 : {
618 2 : PushParagraphField(new SvxDateField, rStyleName);
619 2 : }
620 :
621 2 : void ScXMLTableRowCellContext::PushParagraphFieldSheetName(const OUString& rStyleName)
622 : {
623 2 : SCTAB nTab = GetScImport().GetTables().GetCurrentCellPos().Tab();
624 2 : PushParagraphField(new SvxTableField(nTab), rStyleName);
625 2 : }
626 :
627 2 : void ScXMLTableRowCellContext::PushParagraphFieldDocTitle(const OUString& rStyleName)
628 : {
629 2 : PushParagraphField(new SvxFileField, rStyleName);
630 2 : }
631 :
632 10 : void ScXMLTableRowCellContext::PushParagraphFieldURL(
633 : const OUString& rURL, const OUString& rRep, const OUString& rStyleName)
634 : {
635 10 : OUString aAbsURL = GetScImport().GetAbsoluteReference(rURL);
636 10 : PushParagraphField(new SvxURLField(aAbsURL, rRep, SVXURLFORMAT_REPR), rStyleName);
637 10 : }
638 :
639 8814 : void ScXMLTableRowCellContext::PushParagraphEnd()
640 : {
641 : // EditEngine always has at least one paragraph even when its content is empty.
642 :
643 8814 : if (mbEditEngineHasText)
644 : {
645 28 : if (maFirstParagraph)
646 : {
647 : // Flush the cached first paragraph first.
648 10 : mpEditEngine->Clear();
649 10 : mpEditEngine->SetText(*maFirstParagraph);
650 10 : maFirstParagraph.reset();
651 : }
652 28 : mpEditEngine->InsertParagraph(mpEditEngine->GetParagraphCount(), maParagraph.makeStringAndClear());
653 : }
654 8786 : else if (mbHasFormatRuns)
655 : {
656 390 : mpEditEngine->Clear();
657 390 : mpEditEngine->SetText(maParagraph.makeStringAndClear());
658 390 : mbEditEngineHasText = true;
659 : }
660 8396 : else if (mnCurParagraph == 0)
661 : {
662 8396 : maFirstParagraph.reset(maParagraph.makeStringAndClear());
663 8396 : mbEditEngineHasText = true;
664 : }
665 :
666 8814 : ++mnCurParagraph;
667 8814 : }
668 :
669 8892 : 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 8892 : SvXMLImportContext *pContext = 0;
675 :
676 8892 : const SvXMLTokenMap& rTokenMap = rXMLImport.GetTableRowCellElemTokenMap();
677 8892 : bool bTextP(false);
678 8892 : switch( rTokenMap.Get( nPrefix, rLName ) )
679 : {
680 : case XML_TOK_TABLE_ROW_CELL_P:
681 : {
682 8814 : bIsEmpty = false;
683 8814 : bTextP = true;
684 :
685 8814 : pContext = new ScXMLCellTextParaContext(rXMLImport, nPrefix, rLName, *this);
686 : }
687 8814 : 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 16 : bIsEmpty = false;
696 : OSL_ENSURE( !mxAnnotationData.get(), "ScXMLTableRowCellContext::CreateChildContext - multiple annotations in one cell" );
697 16 : mxAnnotationData.reset( new ScXMLAnnotationData );
698 : pContext = new ScXMLAnnotationContext( rXMLImport, nPrefix, rLName,
699 16 : xAttrList, *mxAnnotationData, this);
700 : }
701 16 : break;
702 : case XML_TOK_TABLE_ROW_CELL_DETECTIVE:
703 : {
704 5 : bIsEmpty = false;
705 5 : if (!pDetectiveObjVec)
706 5 : pDetectiveObjVec = new ScMyImpDetectiveObjVec();
707 : pContext = new ScXMLDetectiveContext(
708 5 : rXMLImport, nPrefix, rLName, pDetectiveObjVec );
709 : }
710 5 : 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 8892 : if (!pContext && !bTextP)
723 : {
724 57 : ScAddress aCellPos = rXMLImport.GetTables().GetCurrentCellPos();
725 57 : uno::Reference<drawing::XShapes> xShapes (rXMLImport.GetTables().GetCurrentXShapes());
726 57 : if (xShapes.is())
727 : {
728 57 : if (aCellPos.Col() > MAXCOL)
729 0 : aCellPos.SetCol(MAXCOL);
730 57 : if (aCellPos.Row() > MAXROW)
731 0 : aCellPos.SetRow(MAXROW);
732 : XMLTableShapeImportHelper* pTableShapeImport =
733 57 : static_cast< XMLTableShapeImportHelper* >( rXMLImport.GetShapeImport().get() );
734 57 : pTableShapeImport->SetOnTable(false);
735 57 : com::sun::star::table::CellAddress aCellAddress;
736 57 : ScUnoConversion::FillApiAddress( aCellAddress, aCellPos );
737 57 : pTableShapeImport->SetCell(aCellAddress);
738 : pContext = rXMLImport.GetShapeImport()->CreateGroupChildContext(
739 57 : rXMLImport, nPrefix, rLName, xAttrList, xShapes);
740 57 : if (pContext)
741 : {
742 57 : bIsEmpty = false;
743 57 : rXMLImport.ProgressBarIncrement(false);
744 : }
745 57 : }
746 : }
747 :
748 8892 : if( !pContext )
749 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
750 :
751 8892 : return pContext;
752 : }
753 :
754 8 : void ScXMLTableRowCellContext::DoMerge( const ScAddress& rScAddress, const SCCOL nCols, const SCROW nRows )
755 : {
756 8 : SCCOL mergeToCol = rScAddress.Col() + nCols;
757 8 : SCROW mergeToRow = rScAddress.Row() + nRows;
758 16 : bool bInBounds = rScAddress.Col() <= MAXCOL && rScAddress.Row() <= MAXROW &&
759 16 : mergeToCol <= MAXCOL && mergeToRow <= MAXROW;
760 8 : if( bInBounds )
761 : {
762 8 : rXMLImport.GetDocument()->DoMerge( rScAddress.Tab(),
763 16 : rScAddress.Col(), rScAddress.Row(), mergeToCol, mergeToRow );
764 : }
765 8 : }
766 :
767 : namespace {
768 :
769 14 : ScValidationMode validationTypeToMode( const sheet::ValidationType eVType )
770 : {
771 : ScValidationMode eMode;
772 14 : switch( eVType )
773 : {
774 10 : case sheet::ValidationType_WHOLE: eMode = SC_VALID_WHOLE; break;
775 4 : 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 14 : return eMode;
784 : }
785 :
786 14 : ScValidErrorStyle validAlertToValidError( const sheet::ValidationAlertStyle eVAlertStyle )
787 : {
788 : ScValidErrorStyle eVErrStyle;
789 14 : switch( eVAlertStyle )
790 : {
791 10 : case sheet::ValidationAlertStyle_STOP: eVErrStyle = SC_VALERR_STOP; break;
792 4 : 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 14 : return eVErrStyle;
798 : }
799 :
800 : }
801 :
802 14558 : void ScXMLTableRowCellContext::SetContentValidation( const ScRange& rScRange )
803 : {
804 14558 : if (maContentValidationName)
805 : {
806 14 : ScDocument* pDoc = rXMLImport.GetDocument();
807 14 : ScMyImportValidation aValidation;
808 14 : aValidation.eGrammar1 = aValidation.eGrammar2 = pDoc->GetStorageGrammar();
809 14 : 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 14 : );
818 :
819 14 : aScValidationData.SetIgnoreBlank( aValidation.bIgnoreBlanks );
820 14 : aScValidationData.SetListType( aValidation.nShowList );
821 :
822 : // set strings for error / input even if disabled (and disable afterwards)
823 14 : aScValidationData.SetInput( aValidation.sImputTitle, aValidation.sImputMessage );
824 14 : if( !aValidation.bShowImputMessage )
825 14 : aScValidationData.ResetInput();
826 14 : aScValidationData.SetError( aValidation.sErrorTitle, aValidation.sErrorMessage, validAlertToValidError(aValidation.aAlertStyle) );
827 14 : if( !aValidation.bShowErrorMessage )
828 0 : aScValidationData.ResetError();
829 :
830 14 : if( !aValidation.sBaseCellAddress.isEmpty() )
831 14 : aScValidationData.SetSrcString( aValidation.sBaseCellAddress );
832 :
833 14 : sal_uLong nIndex = pDoc->AddValidationEntry( aScValidationData );
834 :
835 28 : ScPatternAttr aPattern( pDoc->GetPool() );
836 14 : aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_VALIDDATA, nIndex ) );
837 14 : if( rScRange.aStart == rScRange.aEnd ) //for a single cell
838 : {
839 9 : pDoc->ApplyPattern( rScRange.aStart.Col(), rScRange.aStart.Row(),
840 18 : rScRange.aStart.Tab(), aPattern );
841 : }
842 : else //for repeating cells
843 : {
844 5 : pDoc->ApplyPatternAreaTab( rScRange.aStart.Col(), rScRange.aStart.Row(),
845 5 : rScRange.aEnd.Col(), rScRange.aEnd.Row(),
846 15 : 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 14 : ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetImport().GetModel())->GetSheetSaveData();
853 28 : pSheetData->BlockSheet( GetScImport().GetTables().GetCurrentSheet() );
854 14 : }
855 : }
856 14558 : }
857 :
858 11939 : void ScXMLTableRowCellContext::SetContentValidation( const ScAddress& rCellPos )
859 : {
860 11939 : SetContentValidation( ScRange(rCellPos, rCellPos) );
861 11939 : }
862 :
863 9294 : void ScXMLTableRowCellContext::SetAnnotation(const ScAddress& rPos)
864 : {
865 9294 : ScDocument* pDoc = rXMLImport.GetDocument();
866 9294 : if( !pDoc || !mxAnnotationData.get() )
867 18572 : return;
868 :
869 16 : LockSolarMutex();
870 :
871 16 : ScPostIt* pNote = 0;
872 :
873 16 : uno::Reference< drawing::XShapes > xShapes = rXMLImport.GetTables().GetCurrentXShapes();
874 32 : uno::Reference< container::XIndexAccess > xShapesIA( xShapes, uno::UNO_QUERY );
875 16 : 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 16 : if( mxAnnotationData->mxShape.is() && mxAnnotationData->mxShapes.is() )
880 : {
881 : OSL_ENSURE( mxAnnotationData->mxShapes.get() == xShapes.get(), "ScXMLTableRowCellContext::SetAnnotation - diffenet drawing pages" );
882 16 : 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 16 : if( mxAnnotationData->mbShown && mxAnnotationData->mbUseShapePos )
888 : {
889 3 : 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 3 : pNote = ScNoteUtil::CreateNoteFromCaption( *pDoc, rPos, *pCaption, true );
894 : // forget pointer to object (do not create note again below)
895 3 : pObject = 0;
896 : }
897 : }
898 :
899 : // drawing object has not been used to create a note -> use shape data
900 16 : if( pObject )
901 : {
902 : // rescue settings from drawing object before the shape is removed
903 13 : ::std::unique_ptr< SfxItemSet > xItemSet( new SfxItemSet( pObject->GetMergedItemSet() ) );
904 26 : ::std::unique_ptr< OutlinerParaObject > xOutlinerObj;
905 13 : if( OutlinerParaObject* pOutlinerObj = pObject->GetOutlinerParaObject() )
906 13 : xOutlinerObj.reset( new OutlinerParaObject( *pOutlinerObj ) );
907 13 : Rectangle aCaptionRect;
908 13 : if( mxAnnotationData->mbUseShapePos )
909 7 : aCaptionRect = pObject->GetLogicRect();
910 : // remove the shape from the drawing page, this invalidates pObject
911 13 : mxAnnotationData->mxShapes->remove( mxAnnotationData->mxShape );
912 13 : pObject = 0;
913 : // update current number of existing objects
914 13 : if( xShapesIA.is() )
915 13 : nOldShapeCount = xShapesIA->getCount();
916 :
917 : // an outliner object is required (empty note captions not allowed)
918 13 : 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 13 : aCaptionRect, mxAnnotationData->mbShown, false );
924 13 : }
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 16 : if( pNote )
936 : {
937 : double fDate;
938 16 : if (rXMLImport.GetMM100UnitConverter().convertDateTime(fDate, mxAnnotationData->maCreateDate))
939 : {
940 15 : SvNumberFormatter* pNumForm = pDoc->GetFormatTable();
941 15 : sal_uInt32 nfIndex = pNumForm->GetFormatIndex( NF_DATE_SYS_DDMMYYYY, LANGUAGE_SYSTEM );
942 15 : OUString aDate;
943 15 : Color* pColor = 0;
944 15 : Color** ppColor = &pColor;
945 15 : pNumForm->GetOutputString( fDate, nfIndex, aDate, ppColor );
946 15 : pNote->SetDate( aDate );
947 : }
948 16 : pNote->SetAuthor( mxAnnotationData->maAuthor );
949 : }
950 :
951 : // register a shape that has been newly created in the ScNoteUtil functions
952 16 : if( xShapesIA.is() && (nOldShapeCount < xShapesIA->getCount()) )
953 : {
954 5 : uno::Reference< drawing::XShape > xShape;
955 5 : rXMLImport.GetShapeImport()->shapeWithZIndexAdded( xShape, xShapesIA->getCount() );
956 : }
957 :
958 : // store the style names for stream copying
959 16 : ScSheetSaveData* pSheetData = ScModelObj::getImplementation(rXMLImport.GetModel())->GetSheetSaveData();
960 16 : pSheetData->HandleNoteStyles( mxAnnotationData->maStyleName, mxAnnotationData->maTextStyle, rPos );
961 :
962 16 : std::vector<ScXMLAnnotationStyleEntry>::const_iterator aIter = mxAnnotationData->maContentStyles.begin();
963 16 : std::vector<ScXMLAnnotationStyleEntry>::const_iterator aEnd = mxAnnotationData->maContentStyles.end();
964 49 : while (aIter != aEnd)
965 : {
966 17 : pSheetData->AddNoteContentStyle( aIter->mnFamily, aIter->maName, rPos, aIter->maSelection );
967 17 : ++aIter;
968 16 : }
969 : }
970 :
971 : // core implementation
972 9294 : void ScXMLTableRowCellContext::SetDetectiveObj( const ScAddress& rPosition )
973 : {
974 9294 : if( cellExists(rPosition) && pDetectiveObjVec && pDetectiveObjVec->size() )
975 : {
976 0 : LockSolarMutex();
977 0 : ScDetectiveFunc aDetFunc( rXMLImport.GetDocument(), rPosition.Tab() );
978 0 : uno::Reference<container::XIndexAccess> xShapesIndex (rXMLImport.GetTables().GetCurrentXShapes(), uno::UNO_QUERY); // make draw page
979 0 : ScMyImpDetectiveObjVec::iterator aItr(pDetectiveObjVec->begin());
980 0 : ScMyImpDetectiveObjVec::iterator aEndItr(pDetectiveObjVec->end());
981 0 : while(aItr != aEndItr)
982 : {
983 0 : aDetFunc.InsertObject( aItr->eObjType, rPosition, aItr->aSourceRange, aItr->bHasError );
984 0 : if (xShapesIndex.is())
985 : {
986 0 : sal_Int32 nShapes = xShapesIndex->getCount();
987 0 : uno::Reference < drawing::XShape > xShape;
988 0 : rXMLImport.GetShapeImport()->shapeWithZIndexAdded(xShape, nShapes);
989 : }
990 0 : ++aItr;
991 0 : }
992 : }
993 9294 : }
994 :
995 : // core implementation
996 9294 : void ScXMLTableRowCellContext::SetCellRangeSource( const ScAddress& rPosition )
997 : {
998 27882 : if( cellExists(rPosition) && pCellRangeSource && !pCellRangeSource->sSourceStr.isEmpty() &&
999 9294 : !pCellRangeSource->sFilterName.isEmpty() && !pCellRangeSource->sURL.isEmpty() )
1000 : {
1001 0 : ScDocument* pDoc = rXMLImport.GetDocument();
1002 0 : if (pDoc)
1003 : {
1004 0 : LockSolarMutex();
1005 0 : ScRange aDestRange( rPosition.Col(), rPosition.Row(), rPosition.Tab(),
1006 0 : rPosition.Col() + static_cast<SCCOL>(pCellRangeSource->nColumns - 1),
1007 0 : rPosition.Row() + static_cast<SCROW>(pCellRangeSource->nRows - 1), rPosition.Tab() );
1008 0 : OUString sFilterName( pCellRangeSource->sFilterName );
1009 0 : OUString sSourceStr( pCellRangeSource->sSourceStr );
1010 : ScAreaLink* pLink = new ScAreaLink( pDoc->GetDocumentShell(), pCellRangeSource->sURL,
1011 0 : sFilterName, pCellRangeSource->sFilterOptions, sSourceStr, aDestRange, pCellRangeSource->nRefresh );
1012 0 : sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
1013 0 : pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, pCellRangeSource->sURL, &sFilterName, &sSourceStr );
1014 : }
1015 : }
1016 9294 : }
1017 :
1018 1542 : void ScXMLTableRowCellContext::SetFormulaCell(ScFormulaCell* pFCell) const
1019 : {
1020 1542 : if(pFCell)
1021 : {
1022 1542 : if(mbErrorValue)
1023 : {
1024 : // don't do anything here
1025 : // we need to recalc anyway
1026 : }
1027 1520 : else if( bFormulaTextResult && maStringValue )
1028 : {
1029 165 : if( !IsPossibleErrorString() )
1030 : {
1031 156 : ScDocument* pDoc = rXMLImport.GetDocument();
1032 156 : pFCell->SetHybridString(pDoc->GetSharedStringPool().intern(*maStringValue));
1033 156 : pFCell->ResetDirty();
1034 : }
1035 : }
1036 1355 : else if (!rtl::math::isNan(fValue))
1037 : {
1038 1351 : pFCell->SetHybridDouble(fValue);
1039 1351 : pFCell->ResetDirty();
1040 : }
1041 : }
1042 1542 : }
1043 :
1044 3673 : void ScXMLTableRowCellContext::PutTextCell( const ScAddress& rCurrentPos,
1045 : const SCCOL nCurrentCol, const ::boost::optional< OUString >& pOUText )
1046 : {
1047 3673 : 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 3673 : if( rXMLImport.GetTables().IsPartOfMatrix(rCurrentPos) )
1051 : {
1052 16 : bDoIncrement = rXMLImport.GetDocument()->GetCellType(rCurrentPos) == CELLTYPE_FORMULA;
1053 16 : if ( bDoIncrement )
1054 : {
1055 16 : ScFormulaCell* pFCell = rXMLImport.GetDocument()->GetFormulaCell(rCurrentPos);
1056 16 : OUString aCellString;
1057 16 : if (maStringValue)
1058 16 : aCellString = *maStringValue;
1059 0 : else if (mbEditEngineHasText)
1060 0 : aCellString = GetFirstParagraph();
1061 0 : else if ( nCurrentCol > 0 && pOUText && !pOUText->isEmpty() )
1062 0 : aCellString = *pOUText;
1063 : else
1064 0 : bDoIncrement = false;
1065 :
1066 16 : if(mbErrorValue)
1067 0 : bDoIncrement = false;
1068 :
1069 16 : if(!aCellString.isEmpty())
1070 : {
1071 12 : if (bDoIncrement && !IsPossibleErrorString() && pFCell)
1072 : {
1073 0 : ScDocument* pDoc = rXMLImport.GetDocument();
1074 0 : pFCell->SetHybridString(pDoc->GetSharedStringPool().intern(aCellString));
1075 0 : pFCell->ResetDirty();
1076 : }
1077 : else
1078 : {
1079 12 : ScAddress aTopLeftMatrixCell;
1080 12 : if (pFCell && pFCell->GetMatrixOrigin(aTopLeftMatrixCell))
1081 : {
1082 12 : ScFormulaCell* pMatrixCell = rXMLImport.GetDocument()->GetFormulaCell(aTopLeftMatrixCell);
1083 12 : if (pMatrixCell)
1084 12 : pMatrixCell->SetDirty();
1085 : }
1086 : else
1087 : SAL_WARN("sc", "matrix cell without matrix");
1088 : }
1089 16 : }
1090 : }
1091 : }
1092 : else //regular text cells
1093 : {
1094 3657 : ScDocumentImport& rDoc = rXMLImport.GetDoc();
1095 3657 : if (maStringValue)
1096 : {
1097 3 : rDoc.setStringCell(rCurrentPos, *maStringValue);
1098 3 : bDoIncrement = true;
1099 : }
1100 3654 : else if (mbEditEngineHasText)
1101 : {
1102 3643 : if (maFirstParagraph)
1103 : {
1104 : // This is a normal text without format runs.
1105 3247 : rDoc.setStringCell(rCurrentPos, *maFirstParagraph);
1106 : }
1107 : else
1108 : {
1109 : // This text either has format runs, has field(s), or consists of multiple lines.
1110 : {
1111 396 : ParaFormatsType::const_iterator it = maFormats.begin(), itEnd = maFormats.end();
1112 784 : for (; it != itEnd; ++it)
1113 388 : mpEditEngine->QuickSetAttribs(it->maItemSet, it->maSelection);
1114 : }
1115 :
1116 : {
1117 396 : FieldsType::const_iterator it = maFields.begin(), itEnd = maFields.end();
1118 412 : for (; it != itEnd; ++it)
1119 16 : mpEditEngine->QuickInsertField(SvxFieldItem(*it->mpData, EE_FEATURE_FIELD), it->maSelection);
1120 : }
1121 :
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 396 : rDoc.setEditCell(rCurrentPos, mpEditEngine->CreateTextObject());
1126 : }
1127 3643 : bDoIncrement = true;
1128 : }
1129 11 : else if ( nCurrentCol > 0 && pOUText && !pOUText->isEmpty() )
1130 : {
1131 0 : rDoc.setStringCell(rCurrentPos, *pOUText);
1132 0 : bDoIncrement = true;
1133 : }
1134 : else
1135 11 : bDoIncrement = false;
1136 : }
1137 :
1138 : // #i56027# This is about setting simple text, not edit cells,
1139 : // so ProgressBarIncrement must be called with bEditCell = FALSE.
1140 : // Formatted text that is put into the cell by the child context
1141 : // is handled in AddCellsToTable() (bIsEmpty is true then).
1142 3673 : if (bDoIncrement)
1143 3662 : rXMLImport.ProgressBarIncrement(false);
1144 3673 : }
1145 :
1146 4071 : void ScXMLTableRowCellContext::PutValueCell( const ScAddress& rCurrentPos )
1147 : {
1148 : //matrix reference cells that contain value formula results;
1149 : //cell was already put in document, just need to set value here.
1150 4071 : if( rXMLImport.GetTables().IsPartOfMatrix(rCurrentPos) )
1151 : {
1152 37 : if (rXMLImport.GetDocument()->GetCellType(rCurrentPos) == CELLTYPE_FORMULA)
1153 : {
1154 37 : ScFormulaCell* pFCell = rXMLImport.GetDocument()->GetFormulaCell(rCurrentPos);
1155 37 : SetFormulaCell(pFCell);
1156 37 : if (pFCell)
1157 37 : pFCell->SetNeedNumberFormat( true );
1158 : }
1159 : }
1160 : else //regular value cell
1161 : {
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 4034 : if (::rtl::math::isNan( fValue))
1166 6 : fValue = 0.0;
1167 :
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.
1171 :
1172 4034 : rXMLImport.GetDoc().setNumericCell(rCurrentPos, fValue);
1173 : }
1174 4071 : rXMLImport.ProgressBarIncrement(false);
1175 4071 : }
1176 :
1177 : namespace {
1178 :
1179 0 : bool isEmptyOrNote( ScDocument* pDoc, const ScAddress& rCurrentPos )
1180 : {
1181 0 : CellType eType = pDoc->GetCellType(rCurrentPos);
1182 0 : return (eType == CELLTYPE_NONE);
1183 : }
1184 :
1185 : }
1186 :
1187 13008 : void ScXMLTableRowCellContext::AddTextAndValueCell( const ScAddress& rCellPos,
1188 : const ::boost::optional< OUString >& pOUText, ScAddress& rCurrentPos )
1189 : {
1190 13008 : ScMyTables& rTables = rXMLImport.GetTables();
1191 13008 : bool bWasEmpty = bIsEmpty;
1192 317895 : for (SCCOL i = 0; i < nColsRepeated; ++i)
1193 : {
1194 304887 : rCurrentPos.SetCol( rCellPos.Col() + i );
1195 :
1196 : // it makes no sense to import data after the last supported column
1197 : // fdo#58539 & gnome#627150
1198 304887 : if(rCurrentPos.Col() > MAXCOL)
1199 0 : break;
1200 :
1201 304887 : if (i > 0)
1202 291879 : rTables.AddColumn(false);
1203 304887 : if (!bIsEmpty)
1204 : {
1205 15488 : for (SCROW j = 0; j < nRepeatedRows; ++j)
1206 : {
1207 7744 : rCurrentPos.SetRow( rCellPos.Row() + j );
1208 :
1209 : // it makes no sense to import data after last supported row
1210 : // fdo#58539 & gnome#627150
1211 7744 : if(rCurrentPos.Row() > MAXROW)
1212 0 : break;
1213 :
1214 7744 : if( (rCurrentPos.Col() == 0) && (j > 0) )
1215 : {
1216 0 : rTables.AddRow();
1217 0 : rTables.AddColumn(false);
1218 : }
1219 7744 : if( cellExists(rCurrentPos) )
1220 : {
1221 7744 : if( ( !(bIsCovered) || isEmptyOrNote(rXMLImport.GetDocument(), rCurrentPos) ) )
1222 : {
1223 7744 : switch (nCellType)
1224 : {
1225 : case util::NumberFormat::TEXT:
1226 : {
1227 3673 : PutTextCell( rCurrentPos, i, pOUText );
1228 : }
1229 3673 : break;
1230 : case util::NumberFormat::NUMBER:
1231 : case util::NumberFormat::PERCENT:
1232 : case util::NumberFormat::CURRENCY:
1233 : case util::NumberFormat::TIME:
1234 : case util::NumberFormat::DATETIME:
1235 : case util::NumberFormat::LOGICAL:
1236 : {
1237 4071 : PutValueCell( rCurrentPos );
1238 : }
1239 4071 : break;
1240 : default:
1241 : {
1242 : OSL_FAIL("no cell type given");
1243 : }
1244 0 : break;
1245 : }
1246 : }
1247 :
1248 7744 : SetAnnotation( rCurrentPos );
1249 7744 : SetDetectiveObj( rCurrentPos );
1250 7744 : SetCellRangeSource( rCurrentPos );
1251 : }
1252 : else
1253 : {
1254 0 : if (!bWasEmpty || mxAnnotationData.get())
1255 : {
1256 0 : if (rCurrentPos.Row() > MAXROW)
1257 0 : rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_ROW_OVERFLOW);
1258 : else
1259 0 : rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_COLUMN_OVERFLOW);
1260 : }
1261 : }
1262 : }
1263 : }
1264 : else
1265 : {
1266 297143 : if ((i == 0) && (rCellPos.Col() == 0))
1267 : {
1268 39845894 : for (sal_Int32 j = 1; j < nRepeatedRows; ++j)
1269 : {
1270 39844817 : rTables.AddRow();
1271 39844817 : rTables.AddColumn(false);
1272 : }
1273 : }
1274 : }
1275 : }
1276 13008 : }
1277 :
1278 13008 : bool ScXMLTableRowCellContext::HasSpecialContent() const
1279 : {
1280 13008 : return (mxAnnotationData.get() || pDetectiveObjVec || pCellRangeSource);
1281 : }
1282 :
1283 22125 : bool ScXMLTableRowCellContext::CellsAreRepeated() const
1284 : {
1285 22125 : return ( (nColsRepeated > 1) || (nRepeatedRows > 1) );
1286 : }
1287 :
1288 : namespace {
1289 :
1290 : // from ScCellObj::GetOutputString_Imp(). all of it may not be necessary.
1291 2479 : OUString getOutputString( ScDocument* pDoc, const ScAddress& aCellPos )
1292 : {
1293 2479 : if (!pDoc)
1294 0 : return OUString();
1295 :
1296 2479 : CellType eType = pDoc->GetCellType(aCellPos);
1297 2479 : switch (eType)
1298 : {
1299 : case CELLTYPE_NONE:
1300 2479 : return OUString();
1301 : case CELLTYPE_EDIT:
1302 : {
1303 : // GetString on EditCell replaces linebreaks with spaces;
1304 : // however here we need line breaks
1305 0 : const EditTextObject* pData = pDoc->GetEditText(aCellPos);
1306 0 : if (pData)
1307 : {
1308 0 : EditEngine& rEngine = pDoc->GetEditEngine();
1309 0 : rEngine.SetText(*pData);
1310 0 : return rEngine.GetText(LINEEND_LF);
1311 : }
1312 : // also don't format EditCells per NumberFormatter
1313 : }
1314 0 : break;
1315 : default:
1316 : {
1317 : // like in GetString for document (column)
1318 : Color* pColor;
1319 0 : sal_uLong nNumFmt = pDoc->GetNumberFormat(aCellPos);
1320 : return ScCellFormat::GetString(
1321 0 : *pDoc, aCellPos, nNumFmt, &pColor, *pDoc->GetFormatTable());
1322 : }
1323 : }
1324 :
1325 0 : return OUString();
1326 : }
1327 :
1328 : }
1329 :
1330 13008 : void ScXMLTableRowCellContext::AddNonFormulaCell( const ScAddress& rCellPos )
1331 : {
1332 13008 : ::boost::optional< OUString > pOUText;
1333 :
1334 13008 : if( nCellType == util::NumberFormat::TEXT )
1335 : {
1336 9117 : if( cellExists(rCellPos) && CellsAreRepeated() )
1337 2479 : pOUText.reset( getOutputString(rXMLImport.GetDocument(), rCellPos) );
1338 :
1339 9117 : if (!mbEditEngineHasText && !pOUText && !maStringValue)
1340 2988 : bIsEmpty = true;
1341 : }
1342 :
1343 13008 : ScAddress aCurrentPos( rCellPos );
1344 13008 : if( HasSpecialContent() )
1345 21 : bIsEmpty = false;
1346 :
1347 13008 : AddTextAndValueCell( rCellPos, pOUText, aCurrentPos );
1348 :
1349 13008 : if( CellsAreRepeated() )
1350 : {
1351 2619 : SCCOL nStartCol( rCellPos.Col() < MAXCOL ? rCellPos.Col() : MAXCOL );
1352 2619 : SCROW nStartRow( rCellPos.Row() < MAXROW ? rCellPos.Row() : MAXROW );
1353 2619 : SCCOL nEndCol( rCellPos.Col() + nColsRepeated - 1 < MAXCOL ? rCellPos.Col() + nColsRepeated - 1 : MAXCOL );
1354 2619 : SCROW nEndRow( rCellPos.Row() + nRepeatedRows - 1 < MAXROW ? rCellPos.Row() + nRepeatedRows - 1 : MAXROW );
1355 2619 : ScRange aScRange( nStartCol, nStartRow, rCellPos.Tab(), nEndCol, nEndRow, rCellPos.Tab() );
1356 2619 : SetContentValidation( aScRange );
1357 2619 : rXMLImport.GetStylesImportHelper()->AddRange( aScRange );
1358 : }
1359 10389 : else if( cellExists(rCellPos) )
1360 : {
1361 10389 : rXMLImport.GetStylesImportHelper()->AddCell(rCellPos);
1362 10389 : SetContentValidation( rCellPos );
1363 13008 : }
1364 13008 : }
1365 :
1366 1505 : void ScXMLTableRowCellContext::PutFormulaCell( const ScAddress& rCellPos )
1367 : {
1368 1505 : ScDocument* pDoc = rXMLImport.GetDocument();
1369 1505 : ScDocumentImport& rDoc = rXMLImport.GetDoc();
1370 :
1371 1505 : OUString aText = maFormula->first;
1372 :
1373 : ::boost::scoped_ptr<ScExternalRefManager::ApiGuard> pExtRefGuard (
1374 3010 : new ScExternalRefManager::ApiGuard(pDoc));
1375 :
1376 1505 : if ( !aText.isEmpty() )
1377 : {
1378 1505 : if ( aText[0] == '=' && aText.getLength() > 1 )
1379 : {
1380 : // temporary formula string as string tokens
1381 1505 : ScTokenArray *pCode = new ScTokenArray();
1382 :
1383 1505 : OUString aFormulaNmsp = maFormula->second;
1384 1505 : if( eGrammar != formula::FormulaGrammar::GRAM_EXTERNAL )
1385 1505 : aFormulaNmsp.clear();
1386 1505 : pCode->AssignXMLString( aText, aFormulaNmsp );
1387 :
1388 1505 : rDoc.getDoc().IncXMLImportedFormulaCount( aText.getLength() );
1389 1505 : ScFormulaCell* pNewCell = new ScFormulaCell(pDoc, rCellPos, pCode, eGrammar, MM_NONE);
1390 1505 : SetFormulaCell(pNewCell);
1391 1505 : rDoc.setFormulaCell(rCellPos, pNewCell);
1392 :
1393 : // Re-calculate to get number format only when style is not set.
1394 1505 : pNewCell->SetNeedNumberFormat(!mbHasStyle);
1395 : }
1396 0 : else if ( aText[0] == '\'' && aText.getLength() > 1 )
1397 : {
1398 : // for bEnglish, "'" at the beginning is always interpreted as text
1399 : // marker and stripped
1400 0 : rDoc.setStringCell(rCellPos, aText.copy(1));
1401 : }
1402 : else
1403 : {
1404 0 : SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
1405 0 : sal_uInt32 nEnglish = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
1406 : double fVal;
1407 0 : if ( pFormatter->IsNumberFormat( aText, nEnglish, fVal ) )
1408 0 : rDoc.setNumericCell(rCellPos, fVal);
1409 : //the (english) number format will not be set
1410 : //search matching local format and apply it
1411 : else
1412 0 : rDoc.setStringCell(rCellPos, aText);
1413 : }
1414 1505 : }
1415 1505 : }
1416 :
1417 1550 : void ScXMLTableRowCellContext::AddFormulaCell( const ScAddress& rCellPos )
1418 : {
1419 1550 : if( cellExists(rCellPos) )
1420 : {
1421 1550 : SetContentValidation( rCellPos );
1422 : SAL_WARN_IF((nColsRepeated != 1) || (nRepeatedRows != 1), "sc", "repeated cells with formula not possible now");
1423 1550 : rXMLImport.GetStylesImportHelper()->AddCell(rCellPos);
1424 :
1425 : //add matrix
1426 1550 : if(bIsMatrix)
1427 : {
1428 45 : if (nMatrixCols > 0 && nMatrixRows > 0)
1429 : {
1430 : //matrix cells are put in the document, but we must set the
1431 : //value/text of each matrix cell later
1432 45 : rXMLImport.GetTables().AddMatrixRange(
1433 45 : rCellPos.Col(), rCellPos.Row(),
1434 90 : std::min<SCCOL>(rCellPos.Col() + nMatrixCols - 1, MAXCOL),
1435 90 : std::min<SCROW>(rCellPos.Row() + nMatrixRows - 1, MAXROW),
1436 225 : maFormula->first, maFormula->second, eGrammar);
1437 :
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 45 : ScFormulaCell* pFCell = rXMLImport.GetDocument()->GetFormulaCell(rCellPos);
1442 45 : if (pFCell)
1443 : {
1444 45 : ScMatrixRef pMat(new ScMatrix(nMatrixCols, nMatrixRows));
1445 45 : if (bFormulaTextResult && maStringValue)
1446 : {
1447 12 : if (!IsPossibleErrorString())
1448 : {
1449 : pFCell->SetResultMatrix(
1450 6 : nMatrixCols, nMatrixRows, pMat, new formula::FormulaStringToken(*maStringValue));
1451 6 : pFCell->ResetDirty();
1452 : }
1453 : }
1454 33 : else if (!rtl::math::isNan(fValue))
1455 : {
1456 : pFCell->SetResultMatrix(
1457 33 : nMatrixCols, nMatrixRows, pMat, new formula::FormulaDoubleToken(fValue));
1458 33 : pFCell->ResetDirty();
1459 45 : }
1460 : }
1461 : }
1462 : }
1463 : else
1464 1505 : PutFormulaCell( rCellPos );
1465 :
1466 1550 : SetAnnotation( rCellPos );
1467 1550 : SetDetectiveObj( rCellPos );
1468 1550 : SetCellRangeSource( rCellPos );
1469 1550 : rXMLImport.ProgressBarIncrement(false);
1470 : }
1471 : else
1472 : {
1473 0 : if (rCellPos.Row() > MAXROW)
1474 0 : rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_ROW_OVERFLOW);
1475 : else
1476 0 : rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_COLUMN_OVERFLOW);
1477 : }
1478 1550 : }
1479 :
1480 : //There are cases where a formula cell is exported with an office:value of 0 or
1481 : //no office:value at all, but the formula cell will have a text:p value which
1482 : //contains the intended formula result.
1483 : //These cases include when a formula result:
1484 : // - is blank
1485 : // - has a constant error value beginning with "#" (such as "#VALUE!" or "#N/A")
1486 : // - has an "Err:[###]" (where "[###]" is an error number)
1487 : // Libreoffice 4.1+ with ODF1.2 extended write however calcext:value-type="error" in that case
1488 14558 : void ScXMLTableRowCellContext::HasSpecialCaseFormulaText()
1489 : {
1490 14558 : if (!mbEditEngineHasText || mbNewValueType)
1491 24651 : return;
1492 :
1493 4465 : OUString aStr = GetFirstParagraph();
1494 :
1495 4465 : if (aStr.isEmpty() || aStr.startsWith("Err:"))
1496 17 : mbPossibleErrorCell = true;
1497 4448 : else if (aStr.startsWith("#"))
1498 14 : mbCheckWithCompilerForError = true;
1499 : }
1500 :
1501 189 : bool ScXMLTableRowCellContext::IsPossibleErrorString() const
1502 : {
1503 189 : if(mbNewValueType && !mbErrorValue)
1504 152 : return false;
1505 37 : else if(mbNewValueType && mbErrorValue)
1506 0 : return true;
1507 37 : return mbPossibleErrorCell || ( mbCheckWithCompilerForError && GetScImport().IsFormulaErrorConstant(*maStringValue) );
1508 : }
1509 :
1510 14558 : void ScXMLTableRowCellContext::EndElement()
1511 : {
1512 14558 : HasSpecialCaseFormulaText();
1513 14558 : if( bFormulaTextResult && (mbPossibleErrorCell || mbCheckWithCompilerForError) )
1514 : {
1515 31 : maStringValue.reset(GetFirstParagraph());
1516 31 : nCellType = util::NumberFormat::TEXT;
1517 : }
1518 :
1519 14558 : ScAddress aCellPos = rXMLImport.GetTables().GetCurrentCellPos();
1520 14558 : if( aCellPos.Col() > 0 && nRepeatedRows > 1 )
1521 38 : aCellPos.SetRow( aCellPos.Row() - (nRepeatedRows - 1) );
1522 14558 : if( bIsMerged )
1523 8 : DoMerge( aCellPos, nMergedCols - 1, nMergedRows - 1 );
1524 :
1525 14558 : if (maFormula)
1526 1550 : AddFormulaCell(aCellPos);
1527 : else
1528 13008 : AddNonFormulaCell(aCellPos);
1529 :
1530 14558 : UnlockSolarMutex(); //if LockSolarMutex got used, we presumably need to ensure an UnlockSolarMutex
1531 :
1532 14558 : bIsMerged = false;
1533 14558 : nMergedCols = 1;
1534 14558 : nMergedRows = 1;
1535 14558 : nColsRepeated = 1;
1536 14714 : }
1537 :
1538 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|