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 "XMLTextPContext.hxx"
41 : #include "XMLStylesImportHelper.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 "cell.hxx"
50 :
51 :
52 : #include <xmloff/xmltkmap.hxx>
53 : #include <xmloff/xmltoken.hxx>
54 : #include <xmloff/nmspmap.hxx>
55 : #include <xmloff/xmluconv.hxx>
56 : #include <xmloff/families.hxx>
57 : #include <xmloff/numehelp.hxx>
58 : #include <xmloff/xmlnmspe.hxx>
59 : #include <svl/zforlist.hxx>
60 : #include <svx/svdocapt.hxx>
61 : #include <editeng/outlobj.hxx>
62 : #include <editeng/editobj.hxx>
63 : #include <svx/unoapi.hxx>
64 : #include <svl/languageoptions.hxx>
65 : #include <sax/tools/converter.hxx>
66 :
67 : #include <com/sun/star/frame/XModel.hpp>
68 : #include <com/sun/star/text/XText.hpp>
69 : #include <com/sun/star/sheet/XSpreadsheets.hpp>
70 : #include <com/sun/star/sheet/XSpreadsheet.hpp>
71 : #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
72 :
73 : #include <com/sun/star/sheet/XSheetCondition.hpp>
74 : #include <com/sun/star/table/XCellRange.hpp>
75 : #include <com/sun/star/table/CellAddress.hpp>
76 : #include <com/sun/star/util/NumberFormat.hpp>
77 : #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
78 : #include <com/sun/star/util/XNumberFormatTypes.hpp>
79 : #include <com/sun/star/util/Date.hpp>
80 : #include <com/sun/star/lang/Locale.hpp>
81 : #include <com/sun/star/text/ControlCharacter.hpp>
82 :
83 : #include <com/sun/star/sheet/ValidationType.hpp>
84 : #include <com/sun/star/sheet/ValidationAlertStyle.hpp>
85 : #include <com/sun/star/sheet/ConditionOperator.hpp>
86 :
87 : #include <rtl/ustrbuf.hxx>
88 : #include <tools/date.hxx>
89 : #include <i18npool/lang.h>
90 : #include <comphelper/extract.hxx>
91 : #include <tools/string.hxx>
92 :
93 : using namespace com::sun::star;
94 : using namespace xmloff::token;
95 :
96 : using rtl::OUString;
97 :
98 : //------------------------------------------------------------------
99 :
100 3232 : ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport,
101 : sal_uInt16 nPrfx,
102 : const ::rtl::OUString& rLName,
103 : const ::com::sun::star::uno::Reference<
104 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
105 : const bool bTempIsCovered,
106 : const sal_Int32 nTempRepeatedRows ) :
107 : SvXMLImportContext( rImport, nPrfx, rLName ),
108 : pContentValidationName(NULL),
109 : pDetectiveObjVec(NULL),
110 : pCellRangeSource(NULL),
111 : fValue(0.0),
112 : nMergedRows(1),
113 : nRepeatedRows(nTempRepeatedRows),
114 : nMergedCols(1),
115 : nColsRepeated(1),
116 : rXMLImport((ScXMLImport&)rImport),
117 : eGrammar( formula::FormulaGrammar::GRAM_STORAGE_DEFAULT),
118 : nCellType(util::NumberFormat::TEXT),
119 : bIsMerged(false),
120 : bIsMatrix(false),
121 : bIsCovered(bTempIsCovered),
122 : bIsEmpty(true),
123 : bHasTextImport(false),
124 : bIsFirstTextImport(false),
125 : bSolarMutexLocked(false),
126 3232 : bFormulaTextResult(false)
127 : {
128 3232 : rtl::math::setNan(&fValue); // NaN by default
129 :
130 3232 : rXMLImport.SetRemoveLastChar(false);
131 3232 : rXMLImport.GetTables().AddColumn(bTempIsCovered);
132 3232 : const sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
133 3232 : rtl::OUString aLocalName;
134 3232 : rtl::OUString* pStyleName = NULL;
135 3232 : rtl::OUString* pCurrencySymbol = NULL;
136 3232 : const SvXMLTokenMap& rTokenMap = rImport.GetTableRowCellAttrTokenMap();
137 7461 : for (sal_Int16 i = 0; i < nAttrCount; ++i)
138 : {
139 4229 : sal_uInt16 nAttrPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(
140 8458 : xAttrList->getNameByIndex(i), &aLocalName);
141 :
142 4229 : const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
143 4229 : sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName);
144 4229 : switch (nToken)
145 : {
146 : case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME:
147 128 : pStyleName = new rtl::OUString(sValue);
148 128 : break;
149 : case XML_TOK_TABLE_ROW_CELL_ATTR_CONTENT_VALIDATION_NAME:
150 : OSL_ENSURE(!pContentValidationName, "here should be only one Validation Name");
151 14 : pContentValidationName = new rtl::OUString(sValue);
152 14 : break;
153 : case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_ROWS:
154 5 : bIsMerged = true;
155 5 : nMergedRows = static_cast<SCROW>(sValue.toInt32());
156 5 : break;
157 : case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_COLS:
158 5 : bIsMerged = true;
159 5 : nMergedCols = static_cast<SCCOL>(sValue.toInt32());
160 5 : break;
161 : case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_COLS:
162 25 : bIsMatrix = true;
163 25 : nMatrixCols = static_cast<SCCOL>(sValue.toInt32());
164 25 : break;
165 : case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_ROWS:
166 25 : bIsMatrix = true;
167 25 : nMatrixRows = static_cast<SCROW>(sValue.toInt32());
168 25 : break;
169 : case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
170 303 : nColsRepeated = static_cast<SCCOL>(std::max( sValue.toInt32(), static_cast<sal_Int32>(1) ));
171 303 : break;
172 : case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE:
173 1805 : nCellType = GetScImport().GetCellType(sValue);
174 1805 : bIsEmpty = false;
175 1805 : break;
176 : case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE:
177 : {
178 1387 : if (!sValue.isEmpty())
179 : {
180 1387 : ::sax::Converter::convertDouble(fValue, sValue);
181 1387 : bIsEmpty = false;
182 :
183 : //if office:value="0", let's get the text:p in case this is
184 : //a special case in HasSpecialCaseFormulaText(). If it
185 : //turns out not to be a special case, we'll use the 0 value.
186 1387 : if(fValue == 0.0)
187 47 : bFormulaTextResult = true;
188 : }
189 : }
190 1387 : break;
191 : case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE:
192 : {
193 2 : if (!sValue.isEmpty() && rXMLImport.SetNullDateOnUnitConverter())
194 : {
195 2 : rXMLImport.GetMM100UnitConverter().convertDateTime(fValue, sValue);
196 2 : bIsEmpty = false;
197 : }
198 : }
199 2 : break;
200 : case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE:
201 : {
202 1 : if (!sValue.isEmpty())
203 : {
204 1 : ::sax::Converter::convertDuration(fValue, sValue);
205 1 : bIsEmpty = false;
206 : }
207 : }
208 1 : break;
209 : case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE:
210 : {
211 28 : if (!sValue.isEmpty())
212 : {
213 : OSL_ENSURE(!pOUTextValue, "here should be only one string value");
214 28 : pOUTextValue.reset(sValue);
215 28 : bIsEmpty = false;
216 : }
217 : }
218 28 : break;
219 : case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE:
220 : {
221 140 : if (!sValue.isEmpty())
222 : {
223 140 : if ( IsXMLToken(sValue, XML_TRUE) )
224 65 : fValue = 1.0;
225 75 : else if ( IsXMLToken(sValue, XML_FALSE) )
226 75 : fValue = 0.0;
227 : else
228 0 : ::sax::Converter::convertDouble(fValue, sValue);
229 140 : bIsEmpty = false;
230 : }
231 : }
232 140 : break;
233 : case XML_TOK_TABLE_ROW_CELL_ATTR_FORMULA:
234 : {
235 359 : if (!sValue.isEmpty())
236 : {
237 : OSL_ENSURE(!pOUFormula, "here should be only one formula");
238 359 : rtl::OUString aFormula, aFormulaNmsp;
239 359 : rXMLImport.ExtractFormulaNamespaceGrammar( aFormula, aFormulaNmsp, eGrammar, sValue );
240 359 : pOUFormula.reset( FormulaWithNamespace( aFormula, aFormulaNmsp ) );
241 : }
242 : }
243 359 : break;
244 : case XML_TOK_TABLE_ROW_CELL_ATTR_CURRENCY:
245 2 : pCurrencySymbol = new rtl::OUString(sValue);
246 2 : break;
247 : default:
248 : ;
249 : }
250 4229 : }
251 3232 : if (pOUFormula)
252 : {
253 359 : if (nCellType == util::NumberFormat::TEXT)
254 28 : bFormulaTextResult = true;
255 359 : if(nCellType == util::NumberFormat::DATETIME)
256 2 : nCellType = util::NumberFormat::UNDEFINED;
257 : //if bIsEmpty is true at this point, then there is no office value.
258 : //we must get the text:p (even if it is empty) in case this a special
259 : //case in HasSpecialCaseFormulaText().
260 359 : if(bIsEmpty)
261 0 : bFormulaTextResult = true;
262 : }
263 3232 : rXMLImport.GetStylesImportHelper()->SetAttributes(pStyleName, pCurrencySymbol, nCellType);
264 3232 : }
265 :
266 9696 : ScXMLTableRowCellContext::~ScXMLTableRowCellContext()
267 : {
268 3232 : delete pContentValidationName;
269 3232 : delete pDetectiveObjVec;
270 3232 : delete pCellRangeSource;
271 6464 : }
272 :
273 1 : void ScXMLTableRowCellContext::LockSolarMutex()
274 : {
275 1 : if (!bSolarMutexLocked)
276 : {
277 1 : GetScImport().LockSolarMutex();
278 1 : bSolarMutexLocked = true;
279 : }
280 1 : }
281 :
282 3232 : void ScXMLTableRowCellContext::UnlockSolarMutex()
283 : {
284 3232 : if (bSolarMutexLocked)
285 : {
286 1 : GetScImport().UnlockSolarMutex();
287 1 : bSolarMutexLocked = false;
288 : }
289 3232 : }
290 :
291 : namespace {
292 :
293 9762 : bool cellExists( const ScAddress& rCellPos )
294 : {
295 19524 : return( rCellPos.Col() >= 0 && rCellPos.Row() >= 0 &&
296 19524 : rCellPos.Col() <= MAXCOL && rCellPos.Row() <= MAXROW );
297 : }
298 :
299 : }
300 :
301 2 : void ScXMLTableRowCellContext::SetCursorOnTextImport(const rtl::OUString& rOUTempText)
302 : {
303 2 : ScAddress aCellPos = rXMLImport.GetTables().GetCurrentCellPos();
304 2 : if (cellExists(aCellPos))
305 : {
306 2 : sal_Int32 nCol = static_cast<sal_Int32>( aCellPos.Col() );
307 2 : sal_Int32 nRow = static_cast<sal_Int32>( aCellPos.Row() );
308 2 : uno::Reference<table::XCellRange> xCellRange(rXMLImport.GetTables().GetCurrentXCellRange());
309 2 : if (xCellRange.is())
310 : {
311 2 : xBaseCell.set( xCellRange->getCellByPosition(nCol, nRow) );
312 2 : if (xBaseCell.is())
313 : {
314 2 : xLockable.set(xBaseCell, uno::UNO_QUERY);
315 2 : if (xLockable.is())
316 2 : xLockable->addActionLock();
317 2 : uno::Reference<text::XText> xText(xBaseCell, uno::UNO_QUERY);
318 2 : if (xText.is())
319 : {
320 2 : uno::Reference<text::XTextCursor> xTextCursor(xText->createTextCursor());
321 2 : if (xTextCursor.is())
322 : {
323 2 : xTextCursor->setString(rOUTempText);
324 2 : xTextCursor->gotoEnd(false);
325 2 : rXMLImport.GetTextImport()->SetCursor(xTextCursor);
326 2 : }
327 2 : }
328 : }
329 2 : }
330 : }
331 : else
332 : {
333 : OSL_FAIL("this method should only be called for a existing cell");
334 : }
335 2 : }
336 :
337 1809 : SvXMLImportContext *ScXMLTableRowCellContext::CreateChildContext( sal_uInt16 nPrefix,
338 : const ::rtl::OUString& rLName,
339 : const ::com::sun::star::uno::Reference<
340 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
341 : {
342 1809 : SvXMLImportContext *pContext = 0;
343 :
344 1809 : const SvXMLTokenMap& rTokenMap = rXMLImport.GetTableRowCellElemTokenMap();
345 1809 : bool bTextP(false);
346 1809 : switch( rTokenMap.Get( nPrefix, rLName ) )
347 : {
348 : case XML_TOK_TABLE_ROW_CELL_P:
349 : {
350 1806 : bIsEmpty = false;
351 1806 : bTextP = true;
352 :
353 1806 : ScAddress aCellPos = rXMLImport.GetTables().GetCurrentCellPos();
354 :
355 1806 : if( ((nCellType == util::NumberFormat::TEXT) || bFormulaTextResult) )
356 : {
357 323 : if (!bHasTextImport)
358 : {
359 322 : bIsFirstTextImport = true;
360 322 : bHasTextImport = true;
361 322 : pContext = new ScXMLTextPContext(rXMLImport, nPrefix, rLName, xAttrList, this);
362 : }
363 : else
364 : {
365 1 : if (cellExists(aCellPos))
366 : {
367 1 : if (bIsFirstTextImport && !rXMLImport.GetRemoveLastChar())
368 : {
369 1 : if (pOUTextContent)
370 : {
371 1 : SetCursorOnTextImport(*pOUTextContent);
372 1 : pOUTextContent.reset();
373 : }
374 : else
375 0 : SetCursorOnTextImport(rtl::OUString());
376 1 : rXMLImport.SetRemoveLastChar(true);
377 1 : uno::Reference < text::XTextCursor > xTextCursor(rXMLImport.GetTextImport()->GetCursor());
378 1 : if (xTextCursor.is())
379 : {
380 1 : uno::Reference < text::XText > xText (xTextCursor->getText());
381 1 : uno::Reference < text::XTextRange > xTextRange (xTextCursor, uno::UNO_QUERY);
382 1 : if (xText.is() && xTextRange.is())
383 1 : xText->insertControlCharacter(xTextRange, text::ControlCharacter::PARAGRAPH_BREAK, false);
384 1 : }
385 : }
386 : pContext = rXMLImport.GetTextImport()->CreateTextChildContext(
387 1 : rXMLImport, nPrefix, rLName, xAttrList);
388 1 : bIsFirstTextImport = false;
389 : }
390 : }
391 : }
392 : }
393 1806 : break;
394 : case XML_TOK_TABLE_ROW_CELL_TABLE:
395 : {
396 : SAL_WARN("sc", "ScXMLTableRowCellContext::CreateChildContext: subtables are not supported");
397 : }
398 0 : break;
399 : case XML_TOK_TABLE_ROW_CELL_ANNOTATION:
400 : {
401 1 : bIsEmpty = false;
402 : OSL_ENSURE( !mxAnnotationData.get(), "ScXMLTableRowCellContext::CreateChildContext - multiple annotations in one cell" );
403 1 : mxAnnotationData.reset( new ScXMLAnnotationData );
404 : pContext = new ScXMLAnnotationContext( rXMLImport, nPrefix, rLName,
405 1 : xAttrList, *mxAnnotationData, this);
406 : }
407 1 : break;
408 : case XML_TOK_TABLE_ROW_CELL_DETECTIVE:
409 : {
410 0 : bIsEmpty = false;
411 0 : if (!pDetectiveObjVec)
412 0 : pDetectiveObjVec = new ScMyImpDetectiveObjVec();
413 : pContext = new ScXMLDetectiveContext(
414 0 : rXMLImport, nPrefix, rLName, pDetectiveObjVec );
415 : }
416 0 : break;
417 : case XML_TOK_TABLE_ROW_CELL_CELL_RANGE_SOURCE:
418 : {
419 0 : bIsEmpty = false;
420 0 : if (!pCellRangeSource)
421 0 : pCellRangeSource = new ScMyImpCellRangeSource();
422 : pContext = new ScXMLCellRangeSourceContext(
423 0 : rXMLImport, nPrefix, rLName, xAttrList, pCellRangeSource );
424 : }
425 0 : break;
426 : }
427 :
428 1809 : if (!pContext && !bTextP)
429 : {
430 2 : ScAddress aCellPos = rXMLImport.GetTables().GetCurrentCellPos();
431 2 : uno::Reference<drawing::XShapes> xShapes (rXMLImport.GetTables().GetCurrentXShapes());
432 2 : if (xShapes.is())
433 : {
434 2 : if (aCellPos.Col() > MAXCOL)
435 0 : aCellPos.SetCol(MAXCOL);
436 2 : if (aCellPos.Row() > MAXROW)
437 0 : aCellPos.SetRow(MAXROW);
438 : XMLTableShapeImportHelper* pTableShapeImport =
439 2 : static_cast< XMLTableShapeImportHelper* >( rXMLImport.GetShapeImport().get() );
440 2 : pTableShapeImport->SetOnTable(false);
441 2 : com::sun::star::table::CellAddress aCellAddress;
442 2 : ScUnoConversion::FillApiAddress( aCellAddress, aCellPos );
443 2 : pTableShapeImport->SetCell(aCellAddress);
444 : pContext = rXMLImport.GetShapeImport()->CreateGroupChildContext(
445 2 : rXMLImport, nPrefix, rLName, xAttrList, xShapes);
446 2 : if (pContext)
447 : {
448 2 : bIsEmpty = false;
449 2 : rXMLImport.ProgressBarIncrement(false);
450 : }
451 2 : }
452 : }
453 :
454 1809 : if( !pContext )
455 1483 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
456 :
457 1809 : return pContext;
458 : }
459 :
460 5 : void ScXMLTableRowCellContext::DoMerge( const ScAddress& rScAddress, const SCCOL nCols, const SCROW nRows )
461 : {
462 5 : SCCOL mergeToCol = rScAddress.Col() + nCols;
463 5 : SCROW mergeToRow = rScAddress.Row() + nRows;
464 10 : bool bInBounds = rScAddress.Col() <= MAXCOL && rScAddress.Row() <= MAXROW &&
465 10 : mergeToCol <= MAXCOL && mergeToRow <= MAXROW;
466 5 : if( bInBounds )
467 : {
468 5 : rXMLImport.GetDocument()->DoMerge( rScAddress.Tab(),
469 10 : rScAddress.Col(), rScAddress.Row(), mergeToCol, mergeToRow );
470 : }
471 5 : }
472 :
473 : namespace {
474 :
475 14 : ScValidationMode validationTypeToMode( const sheet::ValidationType eVType )
476 : {
477 : ScValidationMode eMode;
478 14 : switch( eVType )
479 : {
480 10 : case sheet::ValidationType_WHOLE: eMode = SC_VALID_WHOLE; break;
481 4 : case sheet::ValidationType_DECIMAL: eMode = SC_VALID_DECIMAL; break;
482 0 : case sheet::ValidationType_DATE: eMode = SC_VALID_DATE; break;
483 0 : case sheet::ValidationType_TIME: eMode = SC_VALID_TIME; break;
484 0 : case sheet::ValidationType_TEXT_LEN: eMode = SC_VALID_TEXTLEN; break;
485 0 : case sheet::ValidationType_LIST: eMode = SC_VALID_LIST; break;
486 0 : case sheet::ValidationType_CUSTOM: eMode = SC_VALID_CUSTOM; break;
487 0 : default: eMode = SC_VALID_ANY; break;
488 : }
489 14 : return eMode;
490 : }
491 :
492 14 : ScValidErrorStyle validAlertToValidError( const sheet::ValidationAlertStyle eVAlertStyle )
493 : {
494 : ScValidErrorStyle eVErrStyle;
495 14 : switch( eVAlertStyle )
496 : {
497 10 : case sheet::ValidationAlertStyle_STOP: eVErrStyle = SC_VALERR_STOP; break;
498 4 : case sheet::ValidationAlertStyle_WARNING: eVErrStyle = SC_VALERR_WARNING; break;
499 0 : case sheet::ValidationAlertStyle_MACRO: eVErrStyle = SC_VALERR_MACRO; break;
500 0 : default: eVErrStyle = SC_VALERR_INFO; break;
501 : //should INFO be the default? seems to be the most unobtrusive choice.
502 : }
503 14 : return eVErrStyle;
504 : }
505 :
506 : }
507 :
508 3232 : void ScXMLTableRowCellContext::SetContentValidation( const ScRange& rScRange )
509 : {
510 3232 : if( pContentValidationName && !pContentValidationName->isEmpty() )
511 : {
512 14 : ScDocument* pDoc = rXMLImport.GetDocument();
513 14 : ScMyImportValidation aValidation;
514 14 : aValidation.eGrammar1 = aValidation.eGrammar2 = pDoc->GetStorageGrammar();
515 14 : if( rXMLImport.GetValidation(*pContentValidationName, aValidation) )
516 : {
517 : ScValidationData aScValidationData(
518 : validationTypeToMode(aValidation.aValidationType),
519 : ScConditionEntry::GetModeFromApi(static_cast<sal_Int32>(aValidation.aOperator)),
520 : aValidation.sFormula1, aValidation.sFormula2, pDoc, ScAddress(),
521 : aValidation.sFormulaNmsp1, aValidation.sFormulaNmsp2,
522 : aValidation.eGrammar1, aValidation.eGrammar2
523 14 : );
524 :
525 14 : aScValidationData.SetIgnoreBlank( aValidation.bIgnoreBlanks );
526 14 : aScValidationData.SetListType( aValidation.nShowList );
527 :
528 : // set strings for error / input even if disabled (and disable afterwards)
529 14 : aScValidationData.SetInput( aValidation.sImputTitle, aValidation.sImputMessage );
530 14 : if( !aValidation.bShowImputMessage )
531 14 : aScValidationData.ResetInput();
532 14 : aScValidationData.SetError( aValidation.sErrorTitle, aValidation.sErrorMessage, validAlertToValidError(aValidation.aAlertStyle) );
533 14 : if( !aValidation.bShowErrorMessage )
534 0 : aScValidationData.ResetError();
535 :
536 14 : if( !aValidation.sBaseCellAddress.isEmpty() )
537 14 : aScValidationData.SetSrcString( aValidation.sBaseCellAddress );
538 :
539 14 : sal_uLong nIndex = pDoc->AddValidationEntry( aScValidationData );
540 :
541 14 : ScPatternAttr aPattern( pDoc->GetPool() );
542 14 : aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_VALIDDATA, nIndex ) );
543 14 : if( rScRange.aStart == rScRange.aEnd ) //for a single cell
544 : {
545 9 : pDoc->ApplyPattern( rScRange.aStart.Col(), rScRange.aStart.Row(),
546 18 : rScRange.aStart.Tab(), aPattern );
547 : }
548 : else //for repeating cells
549 : {
550 5 : pDoc->ApplyPatternAreaTab( rScRange.aStart.Col(), rScRange.aStart.Row(),
551 5 : rScRange.aEnd.Col(), rScRange.aEnd.Row(),
552 15 : rScRange.aStart.Tab(), aPattern );
553 : }
554 :
555 : // is the below still needed?
556 : // For now, any sheet with validity is blocked from stream-copying.
557 : // Later, the validation names could be stored along with the style names.
558 14 : ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetImport().GetModel())->GetSheetSaveData();
559 14 : pSheetData->BlockSheet( GetScImport().GetTables().GetCurrentSheet() );
560 14 : }
561 : }
562 3232 : }
563 :
564 2923 : void ScXMLTableRowCellContext::SetContentValidation( const ScAddress& rCellPos )
565 : {
566 2923 : SetContentValidation( ScRange(rCellPos, rCellPos) );
567 2923 : }
568 :
569 1837 : void ScXMLTableRowCellContext::SetAnnotation(const ScAddress& rPos)
570 : {
571 1837 : ScDocument* pDoc = rXMLImport.GetDocument();
572 1837 : if( !pDoc || !mxAnnotationData.get() )
573 1837 : return;
574 :
575 1 : LockSolarMutex();
576 :
577 1 : ScPostIt* pNote = 0;
578 :
579 1 : uno::Reference< drawing::XShapes > xShapes = rXMLImport.GetTables().GetCurrentXShapes();
580 1 : uno::Reference< container::XIndexAccess > xShapesIA( xShapes, uno::UNO_QUERY );
581 1 : sal_Int32 nOldShapeCount = xShapesIA.is() ? xShapesIA->getCount() : 0;
582 :
583 : OSL_ENSURE( !mxAnnotationData->mxShape.is() || mxAnnotationData->mxShapes.is(),
584 : "ScXMLTableRowCellContext::SetAnnotation - shape without drawing page" );
585 1 : if( mxAnnotationData->mxShape.is() && mxAnnotationData->mxShapes.is() )
586 : {
587 : OSL_ENSURE( mxAnnotationData->mxShapes.get() == xShapes.get(), "ScXMLTableRowCellContext::SetAnnotation - diffenet drawing pages" );
588 1 : SdrObject* pObject = ::GetSdrObjectFromXShape( mxAnnotationData->mxShape );
589 : OSL_ENSURE( pObject, "ScXMLTableRowCellContext::SetAnnotation - cannot get SdrObject from shape" );
590 :
591 : /* Try to reuse the drawing object already created (but only if the
592 : note is visible, and the object is a caption object). */
593 1 : if( mxAnnotationData->mbShown && mxAnnotationData->mbUseShapePos )
594 : {
595 0 : if( SdrCaptionObj* pCaption = dynamic_cast< SdrCaptionObj* >( pObject ) )
596 : {
597 : OSL_ENSURE( !pCaption->GetLogicRect().IsEmpty(), "ScXMLTableRowCellContext::SetAnnotation - invalid caption rectangle" );
598 : // create the cell note with the caption object
599 0 : pNote = ScNoteUtil::CreateNoteFromCaption( *pDoc, rPos, *pCaption, true );
600 : // forget pointer to object (do not create note again below)
601 0 : pObject = 0;
602 : }
603 : }
604 :
605 : // drawing object has not been used to create a note -> use shape data
606 1 : if( pObject )
607 : {
608 : // rescue settings from drawing object before the shape is removed
609 1 : ::std::auto_ptr< SfxItemSet > xItemSet( new SfxItemSet( pObject->GetMergedItemSet() ) );
610 1 : ::std::auto_ptr< OutlinerParaObject > xOutlinerObj;
611 1 : if( OutlinerParaObject* pOutlinerObj = pObject->GetOutlinerParaObject() )
612 1 : xOutlinerObj.reset( new OutlinerParaObject( *pOutlinerObj ) );
613 1 : Rectangle aCaptionRect;
614 1 : if( mxAnnotationData->mbUseShapePos )
615 1 : aCaptionRect = pObject->GetLogicRect();
616 : // remove the shape from the drawing page, this invalidates pObject
617 1 : mxAnnotationData->mxShapes->remove( mxAnnotationData->mxShape );
618 1 : pObject = 0;
619 : // update current number of existing objects
620 1 : if( xShapesIA.is() )
621 1 : nOldShapeCount = xShapesIA->getCount();
622 :
623 : // an outliner object is required (empty note captions not allowed)
624 1 : if( xOutlinerObj.get() )
625 : {
626 : // create cell note with all data from drawing object
627 : pNote = ScNoteUtil::CreateNoteFromObjectData( *pDoc, rPos,
628 : xItemSet.release(), xOutlinerObj.release(),
629 1 : aCaptionRect, mxAnnotationData->mbShown, false );
630 1 : }
631 : }
632 : }
633 0 : else if( !mxAnnotationData->maSimpleText.isEmpty() )
634 : {
635 : // create note from simple text
636 : pNote = ScNoteUtil::CreateNoteFromString( *pDoc, rPos,
637 0 : mxAnnotationData->maSimpleText, mxAnnotationData->mbShown, false );
638 : }
639 :
640 : // set author and date
641 1 : if( pNote )
642 : {
643 : double fDate;
644 1 : rXMLImport.GetMM100UnitConverter().convertDateTime( fDate, mxAnnotationData->maCreateDate );
645 1 : SvNumberFormatter* pNumForm = pDoc->GetFormatTable();
646 1 : sal_uInt32 nfIndex = pNumForm->GetFormatIndex( NF_DATE_SYS_DDMMYYYY, LANGUAGE_SYSTEM );
647 1 : String aDate;
648 1 : Color* pColor = 0;
649 1 : Color** ppColor = &pColor;
650 1 : pNumForm->GetOutputString( fDate, nfIndex, aDate, ppColor );
651 1 : pNote->SetDate( aDate );
652 1 : pNote->SetAuthor( mxAnnotationData->maAuthor );
653 : }
654 :
655 : // register a shape that has been newly created in the ScNoteUtil functions
656 1 : if( xShapesIA.is() && (nOldShapeCount < xShapesIA->getCount()) )
657 : {
658 0 : uno::Reference< drawing::XShape > xShape;
659 0 : rXMLImport.GetShapeImport()->shapeWithZIndexAdded( xShape, xShapesIA->getCount() );
660 : }
661 :
662 : // store the style names for stream copying
663 1 : ScSheetSaveData* pSheetData = ScModelObj::getImplementation(rXMLImport.GetModel())->GetSheetSaveData();
664 1 : pSheetData->HandleNoteStyles( mxAnnotationData->maStyleName, mxAnnotationData->maTextStyle, rPos );
665 :
666 1 : std::vector<ScXMLAnnotationStyleEntry>::const_iterator aIter = mxAnnotationData->maContentStyles.begin();
667 1 : std::vector<ScXMLAnnotationStyleEntry>::const_iterator aEnd = mxAnnotationData->maContentStyles.end();
668 3 : while (aIter != aEnd)
669 : {
670 1 : pSheetData->AddNoteContentStyle( aIter->mnFamily, aIter->maName, rPos, aIter->maSelection );
671 1 : ++aIter;
672 1 : }
673 : }
674 :
675 : // core implementation
676 1837 : void ScXMLTableRowCellContext::SetDetectiveObj( const ScAddress& rPosition )
677 : {
678 1837 : if( cellExists(rPosition) && pDetectiveObjVec && pDetectiveObjVec->size() )
679 : {
680 0 : LockSolarMutex();
681 0 : ScDetectiveFunc aDetFunc( rXMLImport.GetDocument(), rPosition.Tab() );
682 0 : uno::Reference<container::XIndexAccess> xShapesIndex (rXMLImport.GetTables().GetCurrentXShapes(), uno::UNO_QUERY); // make draw page
683 0 : ScMyImpDetectiveObjVec::iterator aItr(pDetectiveObjVec->begin());
684 0 : ScMyImpDetectiveObjVec::iterator aEndItr(pDetectiveObjVec->end());
685 0 : while(aItr != aEndItr)
686 : {
687 0 : aDetFunc.InsertObject( aItr->eObjType, rPosition, aItr->aSourceRange, aItr->bHasError );
688 0 : if (xShapesIndex.is())
689 : {
690 0 : sal_Int32 nShapes = xShapesIndex->getCount();
691 0 : uno::Reference < drawing::XShape > xShape;
692 0 : rXMLImport.GetShapeImport()->shapeWithZIndexAdded(xShape, nShapes);
693 : }
694 0 : ++aItr;
695 0 : }
696 : }
697 1837 : }
698 :
699 : // core implementation
700 1837 : void ScXMLTableRowCellContext::SetCellRangeSource( const ScAddress& rPosition )
701 : {
702 1837 : if( cellExists(rPosition) && pCellRangeSource && !pCellRangeSource->sSourceStr.isEmpty() &&
703 0 : !pCellRangeSource->sFilterName.isEmpty() && !pCellRangeSource->sURL.isEmpty() )
704 : {
705 0 : ScDocument* pDoc = rXMLImport.GetDocument();
706 0 : if (pDoc)
707 : {
708 0 : LockSolarMutex();
709 0 : ScRange aDestRange( rPosition.Col(), rPosition.Row(), rPosition.Tab(),
710 0 : rPosition.Col() + static_cast<SCCOL>(pCellRangeSource->nColumns - 1),
711 0 : rPosition.Row() + static_cast<SCROW>(pCellRangeSource->nRows - 1), rPosition.Tab() );
712 0 : String sFilterName( pCellRangeSource->sFilterName );
713 0 : String sSourceStr( pCellRangeSource->sSourceStr );
714 : ScAreaLink* pLink = new ScAreaLink( pDoc->GetDocumentShell(), pCellRangeSource->sURL,
715 0 : sFilterName, pCellRangeSource->sFilterOptions, sSourceStr, aDestRange, pCellRangeSource->nRefresh );
716 0 : sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
717 0 : pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, pCellRangeSource->sURL, &sFilterName, &sSourceStr );
718 : }
719 : }
720 1837 : }
721 :
722 394 : void ScXMLTableRowCellContext::SetFormulaCell(ScFormulaCell* pFCell) const
723 : {
724 394 : if(pFCell)
725 : {
726 394 : if( bFormulaTextResult && pOUTextValue )
727 : {
728 48 : pFCell->SetHybridString( *pOUTextValue );
729 48 : pFCell->ResetDirty();
730 : }
731 346 : else if (!rtl::math::isNan(fValue))
732 : {
733 346 : pFCell->SetHybridDouble(fValue);
734 346 : pFCell->ResetDirty();
735 : }
736 :
737 : // Leave the cell dirty when the cached result is not given.
738 : }
739 394 : }
740 :
741 281 : void ScXMLTableRowCellContext::PutTextCell( const ScAddress& rCurrentPos,
742 : const SCCOL nCurrentCol, const ::boost::optional< rtl::OUString >& pOUText )
743 : {
744 281 : bool bDoIncrement = true;
745 : //matrix reference cells that contain text formula results;
746 : //cell was already put in document, just need to set text here.
747 281 : if( rXMLImport.GetTables().IsPartOfMatrix(rCurrentPos) )
748 : {
749 10 : ScBaseCell* pCell = rXMLImport.GetDocument()->GetCell( rCurrentPos );
750 10 : bDoIncrement = ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA );
751 10 : if ( bDoIncrement )
752 : {
753 10 : ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
754 10 : if (pOUTextValue && !pOUTextValue->isEmpty())
755 8 : pFCell->SetHybridString( *pOUTextValue );
756 2 : else if (pOUTextContent && !pOUTextContent->isEmpty())
757 0 : pFCell->SetHybridString( *pOUTextContent );
758 2 : else if ( nCurrentCol > 0 && pOUText && !pOUText->isEmpty() )
759 0 : pFCell->SetHybridString( *pOUText );
760 : else
761 2 : bDoIncrement = false;
762 10 : pFCell->ResetDirty();
763 : }
764 : }
765 : else //regular text cells
766 : {
767 271 : ScBaseCell* pNewCell = NULL;
768 271 : ScDocument* pDoc = rXMLImport.GetDocument();
769 271 : if (pOUTextValue && !pOUTextValue->isEmpty())
770 0 : pNewCell = ScBaseCell::CreateTextCell( *pOUTextValue, pDoc );
771 271 : else if (pOUTextContent && !pOUTextContent->isEmpty())
772 250 : pNewCell = ScBaseCell::CreateTextCell( *pOUTextContent, pDoc );
773 21 : else if ( nCurrentCol > 0 && pOUText && !pOUText->isEmpty() )
774 0 : pNewCell = ScBaseCell::CreateTextCell( *pOUText, pDoc );
775 :
776 271 : bDoIncrement = pNewCell != NULL;
777 271 : if ( bDoIncrement )
778 250 : pDoc->PutCell( rCurrentPos, pNewCell );
779 : }
780 : // #i56027# This is about setting simple text, not edit cells,
781 : // so ProgressBarIncrement must be called with bEditCell = FALSE.
782 : // Formatted text that is put into the cell by the child context
783 : // is handled in AddCellsToTable() (bIsEmpty is true then).
784 281 : if (bDoIncrement || bHasTextImport)
785 260 : rXMLImport.ProgressBarIncrement(false);
786 281 : }
787 :
788 1197 : void ScXMLTableRowCellContext::PutValueCell( const ScAddress& rCurrentPos )
789 : {
790 : //matrix reference cells that contain value formula results;
791 : //cell was already put in document, just need to set value here.
792 1197 : if( rXMLImport.GetTables().IsPartOfMatrix(rCurrentPos) )
793 : {
794 35 : ScBaseCell* pCell = rXMLImport.GetDocument()->GetCell( rCurrentPos );
795 35 : if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
796 : {
797 35 : ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
798 35 : SetFormulaCell(pFCell);
799 : }
800 : }
801 : else //regular value cell
802 : {
803 : // #i62435# Initialize the value cell's script type
804 : // if the default style's number format is latin-only.
805 : // If the cell uses a different format, the script type
806 : // will be reset when the style is applied.
807 :
808 1162 : ScBaseCell* pNewCell = new ScValueCell(fValue);
809 1162 : if ( rXMLImport.IsLatinDefaultStyle() )
810 1162 : pNewCell->SetScriptType( SCRIPTTYPE_LATIN );
811 : rXMLImport.GetDocument()->PutCell(
812 1162 : rCurrentPos.Col(), rCurrentPos.Row(),
813 2324 : rCurrentPos.Tab(), pNewCell );
814 : }
815 1197 : rXMLImport.ProgressBarIncrement(false);
816 1197 : }
817 :
818 : namespace {
819 :
820 0 : bool isEmptyOrNote( ScDocument* pDoc, const ScAddress& rCurrentPos )
821 : {
822 0 : ScBaseCell* pCell = pDoc->GetCell( rCurrentPos );
823 0 : return ( !pCell || pCell->GetCellType() == CELLTYPE_NOTE );
824 : }
825 :
826 : }
827 :
828 2873 : void ScXMLTableRowCellContext::AddTextAndValueCells( const ScAddress& rCellPos,
829 : const ::boost::optional< rtl::OUString >& pOUText, ScAddress& rCurrentPos )
830 : {
831 2873 : ScMyTables& rTables = rXMLImport.GetTables();
832 2873 : bool bWasEmpty = bIsEmpty;
833 6873 : for (SCCOL i = 0; i < nColsRepeated; ++i)
834 : {
835 4000 : rCurrentPos.SetCol( rCellPos.Col() + i );
836 4000 : if (i > 0)
837 1127 : rTables.AddColumn(false);
838 4000 : if (!bIsEmpty)
839 : {
840 2950 : for (SCROW j = 0; j < nRepeatedRows; ++j)
841 : {
842 1478 : rCurrentPos.SetRow( rCellPos.Row() + j );
843 1478 : if( (rCurrentPos.Col() == 0) && (j > 0) )
844 : {
845 0 : rTables.AddRow();
846 0 : rTables.AddColumn(false);
847 : }
848 1478 : if( cellExists(rCurrentPos) )
849 : {
850 1478 : if( ( !(bIsCovered) || isEmptyOrNote(rXMLImport.GetDocument(), rCurrentPos) ) )
851 : {
852 1478 : switch (nCellType)
853 : {
854 : case util::NumberFormat::TEXT:
855 : {
856 281 : PutTextCell( rCurrentPos, i, pOUText );
857 : }
858 281 : break;
859 : case util::NumberFormat::NUMBER:
860 : case util::NumberFormat::PERCENT:
861 : case util::NumberFormat::CURRENCY:
862 : case util::NumberFormat::TIME:
863 : case util::NumberFormat::DATETIME:
864 : case util::NumberFormat::LOGICAL:
865 : {
866 1197 : PutValueCell( rCurrentPos );
867 : }
868 1197 : break;
869 : default:
870 : {
871 : OSL_FAIL("no cell type given");
872 : }
873 0 : break;
874 : }
875 : }
876 :
877 1478 : SetAnnotation( rCurrentPos );
878 1478 : SetDetectiveObj( rCurrentPos );
879 1478 : SetCellRangeSource( rCurrentPos );
880 : }
881 : else
882 : {
883 0 : if (!bWasEmpty || mxAnnotationData.get())
884 : {
885 0 : if (rCurrentPos.Row() > MAXROW)
886 0 : rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_ROW_OVERFLOW);
887 : else
888 0 : rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_COLUMN_OVERFLOW);
889 : }
890 : }
891 : }
892 : }
893 : else
894 : {
895 : // #i56027# If the child context put formatted text into the cell,
896 : // bIsEmpty is true and ProgressBarIncrement has to be called
897 : // with bEditCell = TRUE.
898 2528 : if (bHasTextImport)
899 2 : rXMLImport.ProgressBarIncrement(true);
900 2528 : if ((i == 0) && (rCellPos.Col() == 0))
901 : {
902 3145843 : for (sal_Int32 j = 1; j < nRepeatedRows; ++j)
903 : {
904 3145723 : rTables.AddRow();
905 3145723 : rTables.AddColumn(false);
906 : }
907 : }
908 : }
909 : }
910 2873 : }
911 :
912 2873 : bool ScXMLTableRowCellContext::HasSpecialContent() const
913 : {
914 14 : return ( (pContentValidationName && !pContentValidationName->isEmpty()) ||
915 2887 : mxAnnotationData.get() || pDetectiveObjVec || pCellRangeSource );
916 : }
917 :
918 4557 : bool ScXMLTableRowCellContext::CellsAreRepeated() const
919 : {
920 4557 : return ( (nColsRepeated > 1) || (nRepeatedRows > 1) );
921 : }
922 :
923 : namespace {
924 :
925 : // from ScCellObj::GetOutputString_Imp(). all of it may not be necessary.
926 305 : rtl::OUString getOutputString(ScDocument* pDoc, const ScAddress& aCellPos)
927 : {
928 305 : rtl::OUString aVal;
929 305 : if ( pDoc )
930 : {
931 305 : ScBaseCell* pCell = pDoc->GetCell( aCellPos );
932 305 : if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE )
933 : {
934 0 : if ( pCell->GetCellType() == CELLTYPE_EDIT )
935 : {
936 : // GetString an der EditCell macht Leerzeichen aus Umbruechen,
937 : // hier werden die Umbrueche aber gebraucht
938 0 : const EditTextObject* pData = ( static_cast< ScEditCell* >(pCell) )->GetData();
939 0 : if (pData)
940 : {
941 0 : EditEngine& rEngine = pDoc->GetEditEngine();
942 0 : rEngine.SetText( *pData );
943 0 : aVal = rEngine.GetText( LINEEND_LF );
944 : }
945 : // Edit-Zellen auch nicht per NumberFormatter formatieren
946 : // (passend zur Ausgabe)
947 : }
948 : else
949 : {
950 : // wie in GetString am Dokument (column)
951 : Color* pColor;
952 0 : sal_uLong nNumFmt = pDoc->GetNumberFormat( aCellPos );
953 0 : ScCellFormat::GetString( pCell, nNumFmt, aVal, &pColor, *pDoc->GetFormatTable() );
954 : }
955 : }
956 : }
957 305 : return aVal;
958 : }
959 :
960 : }
961 :
962 2873 : void ScXMLTableRowCellContext::AddNonFormulaCells( const ScAddress& rCellPos )
963 : {
964 2873 : ::boost::optional< rtl::OUString > pOUText;
965 :
966 2873 : if( nCellType == util::NumberFormat::TEXT )
967 : {
968 1684 : if( cellExists(rCellPos) && CellsAreRepeated() )
969 305 : pOUText.reset( getOutputString(rXMLImport.GetDocument(), rCellPos) );
970 :
971 1684 : if( !pOUTextContent && !pOUText && !pOUTextValue )
972 1125 : bIsEmpty = true;
973 : }
974 :
975 2873 : ScAddress aCurrentPos( rCellPos );
976 2873 : if( HasSpecialContent() )
977 15 : bIsEmpty = false;
978 :
979 2873 : AddTextAndValueCells( rCellPos, pOUText, aCurrentPos );
980 :
981 2873 : if( CellsAreRepeated() )
982 : {
983 309 : SCCOL nStartCol( rCellPos.Col() < MAXCOL ? rCellPos.Col() : MAXCOL );
984 309 : SCROW nStartRow( rCellPos.Row() < MAXROW ? rCellPos.Row() : MAXROW );
985 309 : SCCOL nEndCol( rCellPos.Col() + nColsRepeated - 1 < MAXCOL ? rCellPos.Col() + nColsRepeated - 1 : MAXCOL );
986 309 : SCROW nEndRow( rCellPos.Row() + nRepeatedRows - 1 < MAXROW ? rCellPos.Row() + nRepeatedRows - 1 : MAXROW );
987 309 : ScRange aScRange( nStartCol, nStartRow, rCellPos.Tab(), nEndCol, nEndRow, rCellPos.Tab() );
988 309 : SetContentValidation( aScRange );
989 309 : rXMLImport.GetStylesImportHelper()->AddRange( aScRange );
990 : }
991 2564 : else if( cellExists(rCellPos) )
992 : {
993 2564 : rXMLImport.GetStylesImportHelper()->AddCell(rCellPos);
994 2564 : SetContentValidation( rCellPos );
995 2873 : }
996 2873 : }
997 :
998 334 : void ScXMLTableRowCellContext::PutFormulaCell( const ScAddress& rCellPos )
999 : {
1000 334 : ScDocument* pDoc = rXMLImport.GetDocument();
1001 :
1002 334 : rtl::OUString aText = pOUFormula->first;
1003 334 : rtl::OUString aFormulaNmsp = pOUFormula->second;
1004 :
1005 334 : ::boost::scoped_ptr<ScExternalRefManager::ApiGuard> pExtRefGuard;
1006 334 : pExtRefGuard.reset(new ScExternalRefManager::ApiGuard(pDoc));
1007 :
1008 334 : ScBaseCell* pNewCell = NULL;
1009 :
1010 334 : if ( !aText.isEmpty() )
1011 : {
1012 334 : if ( aText[0] == '=' && aText.getLength() > 1 )
1013 : {
1014 : // temporary formula string as string tokens
1015 334 : ScTokenArray* pCode = new ScTokenArray;
1016 334 : pCode->AddStringXML( aText );
1017 334 : if( (eGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) && !aFormulaNmsp.isEmpty() )
1018 0 : pCode->AddStringXML( aFormulaNmsp );
1019 :
1020 334 : pDoc->IncXMLImportedFormulaCount( aText.getLength() );
1021 334 : pNewCell = new ScFormulaCell( pDoc, rCellPos, pCode, eGrammar, MM_NONE );
1022 334 : delete pCode;
1023 :
1024 334 : ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pNewCell);
1025 334 : SetFormulaCell(pFCell);
1026 : }
1027 0 : else if ( aText[0] == '\'' && aText.getLength() > 1 )
1028 : {
1029 : // for bEnglish, "'" at the beginning is always interpreted as text
1030 : // marker and stripped
1031 0 : pNewCell = ScBaseCell::CreateTextCell( aText.copy( 1 ), pDoc );
1032 : }
1033 : else
1034 : {
1035 0 : SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
1036 0 : sal_uInt32 nEnglish = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
1037 : double fVal;
1038 0 : if ( pFormatter->IsNumberFormat( aText, nEnglish, fVal ) )
1039 0 : pNewCell = new ScValueCell( fVal );
1040 : //the (english) number format will not be set
1041 : //search matching local format and apply it
1042 : else
1043 0 : pNewCell = ScBaseCell::CreateTextCell( aText, pDoc );
1044 : }
1045 334 : pDoc->PutCell( rCellPos, pNewCell );
1046 334 : }
1047 334 : }
1048 :
1049 359 : void ScXMLTableRowCellContext::AddFormulaCell( const ScAddress& rCellPos )
1050 : {
1051 359 : if( cellExists(rCellPos) )
1052 : {
1053 359 : SetContentValidation( rCellPos );
1054 : OSL_ENSURE(((nColsRepeated == 1) && (nRepeatedRows == 1)), "repeated cells with formula not possible now");
1055 359 : rXMLImport.GetStylesImportHelper()->AddCell(rCellPos);
1056 :
1057 : //add matrix
1058 359 : if(bIsMatrix)
1059 : {
1060 25 : if (nMatrixCols > 0 && nMatrixRows > 0)
1061 : {
1062 : //matrix cells are put in the document, but we must set the
1063 : //value/text of each matrix cell later
1064 25 : rXMLImport.GetTables().AddMatrixRange(
1065 25 : rCellPos.Col(), rCellPos.Row(),
1066 25 : rCellPos.Col() + nMatrixCols - 1,
1067 25 : rCellPos.Row() + nMatrixRows - 1,
1068 125 : pOUFormula->first, pOUFormula->second, eGrammar);
1069 :
1070 : //set the value/text of the first matrix position (top-left).
1071 : //the value/text of the matrix reference cells will be set later.
1072 : ScFormulaCell* pFCell =
1073 25 : static_cast<ScFormulaCell*>( rXMLImport.GetDocument()->GetCell(rCellPos) );
1074 25 : SetFormulaCell(pFCell);
1075 : }
1076 : }
1077 : else
1078 334 : PutFormulaCell( rCellPos );
1079 :
1080 359 : SetAnnotation( rCellPos );
1081 359 : SetDetectiveObj( rCellPos );
1082 359 : SetCellRangeSource( rCellPos );
1083 359 : rXMLImport.ProgressBarIncrement(false);
1084 : }
1085 : else
1086 : {
1087 0 : if (rCellPos.Row() > MAXROW)
1088 0 : rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_ROW_OVERFLOW);
1089 : else
1090 0 : rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_COLUMN_OVERFLOW);
1091 : }
1092 359 : }
1093 :
1094 : //There are cases where a formula cell is exported with an office:value of 0 or
1095 : //no office:value at all, but the formula cell will have a text:p value which
1096 : //contains the intended formula result.
1097 : //These cases include when a formula result:
1098 : // - is blank
1099 : // - has a constant error value beginning with "#" (such as "#VALUE!" or "#N/A")
1100 : // - has an "Err:[###]" (where "[###]" is an error number)
1101 75 : bool ScXMLTableRowCellContext::HasSpecialCaseFormulaText() const
1102 : {
1103 286 : if( pOUTextContent &&
1104 148 : ( pOUTextContent->isEmpty() || (pOUTextContent->indexOf("#") > -1) ||
1105 138 : (pOUTextContent->indexOf("Err:") > -1) )
1106 : )
1107 30 : return true;
1108 45 : return false;
1109 : }
1110 :
1111 :
1112 3232 : void ScXMLTableRowCellContext::EndElement()
1113 : {
1114 3232 : if( bHasTextImport && rXMLImport.GetRemoveLastChar() )
1115 : {
1116 2 : UniReference< XMLTextImportHelper > aTextImport = rXMLImport.GetTextImport();
1117 2 : if( aTextImport->GetCursor().is() )
1118 : {
1119 2 : if( aTextImport->GetCursor()->goLeft(1, true) )
1120 : {
1121 2 : aTextImport->GetText()->insertString(
1122 2 : aTextImport->GetCursorAsRange(), rtl::OUString(), true );
1123 : }
1124 2 : aTextImport->ResetCursor();
1125 2 : }
1126 : }
1127 :
1128 3232 : if( bFormulaTextResult && HasSpecialCaseFormulaText() )
1129 : {
1130 30 : pOUTextValue.reset(*pOUTextContent);
1131 30 : nCellType = util::NumberFormat::TEXT;
1132 : }
1133 :
1134 3232 : ScAddress aCellPos = rXMLImport.GetTables().GetCurrentCellPos();
1135 3232 : if( aCellPos.Col() > 0 && nRepeatedRows > 1 )
1136 9 : aCellPos.SetRow( aCellPos.Row() - (nRepeatedRows - 1) );
1137 3232 : if( bIsMerged )
1138 5 : DoMerge( aCellPos, nMergedCols - 1, nMergedRows - 1 );
1139 3232 : if( !pOUFormula )
1140 2873 : AddNonFormulaCells( aCellPos );
1141 : else // if ( pOUFormula )
1142 359 : AddFormulaCell( aCellPos );
1143 :
1144 3232 : UnlockSolarMutex(); //if LockSolarMutex got used, we presumably need to ensure an UnlockSolarMutex
1145 :
1146 3232 : bIsMerged = false;
1147 3232 : nMergedCols = 1;
1148 3232 : nMergedRows = 1;
1149 3232 : nColsRepeated = 1;
1150 3232 : }
1151 :
1152 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|