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