1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "chart2uno.hxx"
22 #include "miscuno.hxx"
23 #include "document.hxx"
24 #include "formulacell.hxx"
25 #include "chartpos.hxx"
26 #include "unonames.hxx"
27 #include "globstr.hrc"
28 #include "convuno.hxx"
29 #include "rangeutl.hxx"
31 #include "unoreflist.hxx"
32 #include "compiler.hxx"
33 #include "reftokenhelper.hxx"
34 #include "chartlis.hxx"
35 #include "tokenuno.hxx"
37 #include "cellvalue.hxx"
38 #include "tokenarray.hxx"
39 #include "scmatrix.hxx"
41 #include <formula/opcode.hxx>
42 #include <svl/sharedstring.hxx>
44 #include <sfx2/objsh.hxx>
45 #include <vcl/svapp.hxx>
47 #include <com/sun/star/beans/UnknownPropertyException.hpp>
48 #include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
49 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
50 #include <com/sun/star/table/XCellRange.hpp>
51 #include <com/sun/star/table/CellAddress.hpp>
52 #include <com/sun/star/text/XText.hpp>
53 #include <comphelper/extract.hxx>
54 #include <comphelper/processfactory.hxx>
56 #include <rtl/math.hxx>
57 #include <boost/checked_delete.hpp>
59 SC_SIMPLE_SERVICE_INFO( ScChart2DataProvider
, "ScChart2DataProvider",
60 "com.sun.star.chart2.data.DataProvider")
61 SC_SIMPLE_SERVICE_INFO( ScChart2DataSource
, "ScChart2DataSource",
62 "com.sun.star.chart2.data.DataSource")
63 SC_SIMPLE_SERVICE_INFO( ScChart2DataSequence
, "ScChart2DataSequence",
64 "com.sun.star.chart2.data.DataSequence")
66 using namespace ::com::sun::star
;
67 using namespace ::formula
;
68 using ::com::sun::star::uno::Sequence
;
69 using ::com::sun::star::uno::Reference
;
70 using ::std::auto_ptr
;
73 using ::std::distance
;
74 using ::std::unary_function
;
75 using ::boost::shared_ptr
;
79 const SfxItemPropertyMapEntry
* lcl_GetDataProviderPropertyMap()
81 static const SfxItemPropertyMapEntry aDataProviderPropertyMap_Impl
[] =
83 { OUString(SC_UNONAME_INCLUDEHIDDENCELLS
), 0, getBooleanCppuType(), 0, 0 },
84 { OUString(SC_UNONAME_USE_INTERNAL_DATA_PROVIDER
), 0, getBooleanCppuType(), 0, 0 },
85 { OUString(), 0, css::uno::Type(), 0, 0 }
87 return aDataProviderPropertyMap_Impl
;
90 const SfxItemPropertyMapEntry
* lcl_GetDataSequencePropertyMap()
92 static const SfxItemPropertyMapEntry aDataSequencePropertyMap_Impl
[] =
94 {OUString(SC_UNONAME_HIDDENVALUES
), 0, getCppuType((uno::Sequence
<sal_Int32
>*)0 ), 0, 0 },
95 {OUString(SC_UNONAME_ROLE
), 0, cppu::UnoType
<com::sun::star::chart2::data::DataSequenceRole
>::get(), 0, 0 },
96 {OUString(SC_UNONAME_INCLUDEHIDDENCELLS
), 0, getBooleanCppuType(), 0, 0 },
97 { OUString(), 0, css::uno::Type(), 0, 0 }
99 return aDataSequencePropertyMap_Impl
;
102 template< typename T
>
103 ::com::sun::star::uno::Sequence
< T
> lcl_VectorToSequence(
104 const ::std::vector
< T
> & rCont
)
106 ::com::sun::star::uno::Sequence
< T
> aResult( rCont
.size());
107 ::std::copy( rCont
.begin(), rCont
.end(), aResult
.getArray());
111 struct lcl_appendTableNumber
: public ::std::unary_function
< SCTAB
, void >
113 lcl_appendTableNumber( OUStringBuffer
& rBuffer
) :
116 void operator() ( SCTAB nTab
)
118 // there is no append with SCTAB or sal_Int16
119 m_rBuffer
.append( static_cast< sal_Int32
>( nTab
));
120 m_rBuffer
.append( ' ' );
123 OUStringBuffer
& m_rBuffer
;
126 OUString
lcl_createTableNumberList( const ::std::list
< SCTAB
> & rTableList
)
128 OUStringBuffer aBuffer
;
129 ::std::for_each( rTableList
.begin(), rTableList
.end(), lcl_appendTableNumber( aBuffer
));
130 // remove last trailing ' '
131 if( !aBuffer
.isEmpty() )
132 aBuffer
.setLength( aBuffer
.getLength() - 1 );
133 return aBuffer
.makeStringAndClear();
136 uno::Reference
< frame::XModel
> lcl_GetXModel( ScDocument
* pDoc
)
138 uno::Reference
< frame::XModel
> xModel
;
139 SfxObjectShell
* pObjSh( pDoc
? pDoc
->GetDocumentShell() : 0 );
141 xModel
.set( pObjSh
->GetModel());
145 struct TokenTable
: boost::noncopyable
149 vector
<FormulaToken
*> maTokens
;
151 void init( SCCOL nColCount
, SCROW nRowCount
)
153 mnColCount
= nColCount
;
154 mnRowCount
= nRowCount
;
155 maTokens
.reserve(mnColCount
*mnRowCount
);
159 std::for_each(maTokens
.begin(), maTokens
.end(), boost::checked_deleter
<FormulaToken
>());
162 void push_back( FormulaToken
* pToken
)
164 maTokens
.push_back( pToken
);
165 OSL_ENSURE( maTokens
.size()<= static_cast<sal_uInt32
>( mnColCount
*mnRowCount
), "too much tokens" );
168 sal_uInt32
getIndex(SCCOL nCol
, SCROW nRow
) const
170 OSL_ENSURE( nCol
<mnColCount
, "wrong column index" );
171 OSL_ENSURE( nRow
<mnRowCount
, "wrong row index" );
172 sal_uInt32 nRet
= static_cast<sal_uInt32
>(nCol
*mnRowCount
+ nRow
);
173 OSL_ENSURE( maTokens
.size()>= static_cast<sal_uInt32
>( mnColCount
*mnRowCount
), "too few tokens" );
177 vector
<ScTokenRef
>* getColRanges(SCCOL nCol
) const;
178 vector
<ScTokenRef
>* getRowRanges(SCROW nRow
) const;
179 vector
<ScTokenRef
>* getAllRanges() const;
182 vector
<ScTokenRef
>* TokenTable::getColRanges(SCCOL nCol
) const
184 if (nCol
>= mnColCount
)
189 SAL_WNODEPRECATED_DECLARATIONS_PUSH
190 auto_ptr
< vector
<ScTokenRef
> > pTokens(new vector
<ScTokenRef
>);
191 SAL_WNODEPRECATED_DECLARATIONS_POP
192 sal_uInt32 nLast
= getIndex(nCol
, mnRowCount
-1);
193 for (sal_uInt32 i
= getIndex(nCol
, 0); i
<= nLast
; ++i
)
195 FormulaToken
* p
= maTokens
[i
];
199 ScTokenRef
pCopy(static_cast<ScToken
*>(p
->Clone()));
200 ScRefTokenHelper::join(*pTokens
, pCopy
, ScAddress());
202 return pTokens
.release();
205 vector
<ScTokenRef
>* TokenTable::getRowRanges(SCROW nRow
) const
207 if (nRow
>= mnRowCount
)
212 SAL_WNODEPRECATED_DECLARATIONS_PUSH
213 auto_ptr
< vector
<ScTokenRef
> > pTokens(new vector
<ScTokenRef
>);
214 SAL_WNODEPRECATED_DECLARATIONS_POP
215 sal_uInt32 nLast
= getIndex(mnColCount
-1, nRow
);
216 for (sal_uInt32 i
= getIndex(0, nRow
); i
<= nLast
; i
+= mnRowCount
)
218 FormulaToken
* p
= maTokens
[i
];
222 ScTokenRef
p2(static_cast<ScToken
*>(p
->Clone()));
223 ScRefTokenHelper::join(*pTokens
, p2
, ScAddress());
225 return pTokens
.release();
228 vector
<ScTokenRef
>* TokenTable::getAllRanges() const
230 SAL_WNODEPRECATED_DECLARATIONS_PUSH
231 auto_ptr
< vector
<ScTokenRef
> > pTokens(new vector
<ScTokenRef
>);
232 SAL_WNODEPRECATED_DECLARATIONS_POP
233 sal_uInt32 nStop
= mnColCount
*mnRowCount
;
234 for (sal_uInt32 i
= 0; i
< nStop
; i
++)
236 FormulaToken
* p
= maTokens
[i
];
240 ScTokenRef
p2(static_cast<ScToken
*>(p
->Clone()));
241 ScRefTokenHelper::join(*pTokens
, p2
, ScAddress());
243 return pTokens
.release();
246 typedef std::map
<sal_uInt32
, FormulaToken
*> FormulaTokenMap
;
247 typedef std::map
<sal_uInt32
, FormulaTokenMap
*> FormulaTokenMapMap
;
249 class Chart2PositionMap
252 Chart2PositionMap(SCCOL nColCount
, SCROW nRowCount
,
253 bool bFillRowHeader
, bool bFillColumnHeader
, FormulaTokenMapMap
& rCols
,
255 ~Chart2PositionMap();
257 SCCOL
getDataColCount() const { return mnDataColCount
; }
258 SCROW
getDataRowCount() const { return mnDataRowCount
; }
260 vector
<ScTokenRef
>* getLeftUpperCornerRanges() const;
261 vector
<ScTokenRef
>* getAllColHeaderRanges() const;
262 vector
<ScTokenRef
>* getAllRowHeaderRanges() const;
264 vector
<ScTokenRef
>* getColHeaderRanges(SCCOL nChartCol
) const;
265 vector
<ScTokenRef
>* getRowHeaderRanges(SCROW nChartRow
) const;
267 vector
<ScTokenRef
>* getDataColRanges(SCCOL nCol
) const;
268 vector
<ScTokenRef
>* getDataRowRanges(SCROW nRow
) const;
271 SCCOL mnDataColCount
;
272 SCROW mnDataRowCount
;
274 TokenTable maLeftUpperCorner
; //nHeaderColCount*nHeaderRowCount
275 TokenTable maColHeaders
; //mnDataColCount*nHeaderRowCount
276 TokenTable maRowHeaders
; //nHeaderColCount*mnDataRowCount
277 TokenTable maData
;//mnDataColCount*mnDataRowCount
280 Chart2PositionMap::Chart2PositionMap(SCCOL nAllColCount
, SCROW nAllRowCount
,
281 bool bFillRowHeader
, bool bFillColumnHeader
, FormulaTokenMapMap
& rCols
, ScDocument
* pDoc
)
283 // if bFillRowHeader is true, at least the first column serves as a row header.
284 // If more than one column is pure text all the first pure text columns are used as header.
285 // Likewise, if bFillColumnHeader is true, at least the first row serves as a column header.
286 // If more than one row is pure text all the first pure text rows are used as header.
288 SCROW nHeaderRowCount
= (bFillColumnHeader
&& nAllColCount
&& nAllRowCount
) ? 1 : 0;
289 SCCOL nHeaderColCount
= (bFillRowHeader
&& nAllColCount
&& nAllRowCount
) ? 1 : 0;
291 if( nHeaderColCount
|| nHeaderRowCount
)
293 const SCCOL nInitialHeaderColCount
= nHeaderColCount
;
294 //check whether there is more than one text column or row that should be added to the headers
295 SCROW nSmallestValueRowIndex
= nAllRowCount
;
296 bool bFoundValues
= false;
297 bool bFoundAnything
= false;
298 FormulaTokenMapMap::const_iterator it1
= rCols
.begin();
299 for (SCCOL nCol
= 0; nCol
< nAllColCount
; ++nCol
)
301 if (it1
!= rCols
.end() && nCol
>=nHeaderColCount
)
303 bool bFoundValuesInRow
= false;
304 FormulaTokenMap
* pCol
= it1
->second
;
305 FormulaTokenMap::const_iterator it2
= pCol
->begin();
306 for (SCROW nRow
= 0; !bFoundValuesInRow
&& nRow
< nSmallestValueRowIndex
&& it2
!= pCol
->end(); ++nRow
)
308 FormulaToken
* pToken
= it2
->second
;
309 if (pToken
&& nRow
>=nHeaderRowCount
)
312 bool bExternal
= false;
313 StackVar eType
= pToken
->GetType();
314 if( eType
==svExternal
|| eType
==svExternalSingleRef
|| eType
==svExternalDoubleRef
|| eType
==svExternalName
)
315 bExternal
= true;//lllll todo correct?
316 ScTokenRef
pSharedToken(static_cast<ScToken
*>(pToken
->Clone()));
317 ScRefTokenHelper::getRangeFromToken(aRange
, pSharedToken
, ScAddress(), bExternal
);
318 SCCOL nCol1
=0, nCol2
=0;
319 SCROW nRow1
=0, nRow2
=0;
320 SCTAB nTab1
=0, nTab2
=0;
321 aRange
.GetVars( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
322 if (pDoc
&& pDoc
->HasValueData( nCol1
, nRow1
, nTab1
))
324 bFoundValuesInRow
= bFoundValues
= bFoundAnything
= true;
325 nSmallestValueRowIndex
= std::min( nSmallestValueRowIndex
, nRow
);
327 if( !bFoundAnything
)
329 if (pDoc
&& pDoc
->HasData( nCol1
, nRow1
, nTab1
) )
330 bFoundAnything
= true;
335 if(!bFoundValues
&& nHeaderColCount
>0)
342 if(nHeaderRowCount
>0)
345 nHeaderRowCount
= nSmallestValueRowIndex
;
346 else if( nAllRowCount
>1 )
347 nHeaderRowCount
= nAllRowCount
-1;
350 else //if the cells are completely empty, just use single header rows and columns
351 nHeaderColCount
= nInitialHeaderColCount
;
354 mnDataColCount
= nAllColCount
- nHeaderColCount
;
355 mnDataRowCount
= nAllRowCount
- nHeaderRowCount
;
357 maLeftUpperCorner
.init(nHeaderColCount
,nHeaderRowCount
);
358 maColHeaders
.init(mnDataColCount
,nHeaderRowCount
);
359 maRowHeaders
.init(nHeaderColCount
,mnDataRowCount
);
360 maData
.init(mnDataColCount
,mnDataRowCount
);
362 FormulaTokenMapMap::const_iterator it1
= rCols
.begin();
363 for (SCCOL nCol
= 0; nCol
< nAllColCount
; ++nCol
)
365 if (it1
!= rCols
.end())
367 FormulaTokenMap
* pCol
= it1
->second
;
368 FormulaTokenMap::const_iterator it2
= pCol
->begin();
369 for (SCROW nRow
= 0; nRow
< nAllRowCount
; ++nRow
)
371 FormulaToken
* pToken
= NULL
;
372 if (it2
!= pCol
->end())
374 pToken
= it2
->second
;
378 if( nCol
< nHeaderColCount
)
380 if( nRow
< nHeaderRowCount
)
381 maLeftUpperCorner
.push_back(pToken
);
383 maRowHeaders
.push_back(pToken
);
385 else if( nRow
< nHeaderRowCount
)
386 maColHeaders
.push_back(pToken
);
388 maData
.push_back(pToken
);
395 Chart2PositionMap::~Chart2PositionMap()
397 maLeftUpperCorner
.clear();
398 maColHeaders
.clear();
399 maRowHeaders
.clear();
403 vector
<ScTokenRef
>* Chart2PositionMap::getLeftUpperCornerRanges() const
405 return maLeftUpperCorner
.getAllRanges();
407 vector
<ScTokenRef
>* Chart2PositionMap::getAllColHeaderRanges() const
409 return maColHeaders
.getAllRanges();
411 vector
<ScTokenRef
>* Chart2PositionMap::getAllRowHeaderRanges() const
413 return maRowHeaders
.getAllRanges();
415 vector
<ScTokenRef
>* Chart2PositionMap::getColHeaderRanges(SCCOL nCol
) const
417 return maColHeaders
.getColRanges( nCol
);
419 vector
<ScTokenRef
>* Chart2PositionMap::getRowHeaderRanges(SCROW nRow
) const
421 return maRowHeaders
.getRowRanges( nRow
);
424 vector
<ScTokenRef
>* Chart2PositionMap::getDataColRanges(SCCOL nCol
) const
426 return maData
.getColRanges( nCol
);
429 vector
<ScTokenRef
>* Chart2PositionMap::getDataRowRanges(SCROW nRow
) const
431 return maData
.getRowRanges( nRow
);
435 * Designed to be a drop-in replacement for ScChartPositioner, in order to
436 * handle external references.
438 class Chart2Positioner
: boost::noncopyable
450 Chart2Positioner(ScDocument
* pDoc
, const vector
<ScTokenRef
>& rRefTokens
) :
451 mrRefTokens(rRefTokens
),
459 mbDummyUpperLeft(false)
467 void setHeaders(bool bColHeaders
, bool bRowHeaders
)
469 mbColHeaders
= bColHeaders
;
470 mbRowHeaders
= bRowHeaders
;
473 Chart2PositionMap
* getPositionMap()
476 return mpPositionMap
.get();
480 void invalidateGlue();
482 void calcGlueState(SCCOL nCols
, SCROW nRows
);
483 void createPositionMap();
486 const vector
<ScTokenRef
>& mrRefTokens
;
487 boost::scoped_ptr
<Chart2PositionMap
> mpPositionMap
;
494 bool mbDummyUpperLeft
:1;
497 void Chart2Positioner::invalidateGlue()
499 meGlue
= GLUETYPE_NA
;
500 mpPositionMap
.reset();
503 void Chart2Positioner::glueState()
505 if (meGlue
!= GLUETYPE_NA
)
508 mbDummyUpperLeft
= false;
509 if (mrRefTokens
.size() <= 1)
511 // Source data consists of only one data range.
512 const ScTokenRef
& p
= mrRefTokens
.front();
513 ScComplexRefData aData
;
514 if (ScRefTokenHelper::getDoubleRefDataFromToken(aData
, p
))
516 if (aData
.Ref1
.Tab() == aData
.Ref2
.Tab())
517 meGlue
= GLUETYPE_NONE
;
519 meGlue
= GLUETYPE_COLS
;
520 mnStartCol
= aData
.Ref1
.Col();
521 mnStartRow
= aData
.Ref1
.Row();
532 ScComplexRefData aData
;
533 ScRefTokenHelper::getDoubleRefDataFromToken(aData
, mrRefTokens
.front());
534 mnStartCol
= aData
.Ref1
.Col();
535 mnStartRow
= aData
.Ref1
.Row();
539 for (vector
<ScTokenRef
>::const_iterator itr
= mrRefTokens
.begin(), itrEnd
= mrRefTokens
.end()
540 ; itr
!= itrEnd
; ++itr
)
542 ScRefTokenHelper::getDoubleRefDataFromToken(aData
, *itr
);
543 SCCOLROW n1
= aData
.Ref1
.Col();
544 SCCOLROW n2
= aData
.Ref2
.Col();
550 mnStartCol
= static_cast<SCCOL
>(n1
);
552 nEndCol
= static_cast<SCCOL
>(n2
);
554 n1
= aData
.Ref1
.Row();
555 n2
= aData
.Ref2
.Row();
562 mnStartRow
= static_cast<SCROW
>(n1
);
564 nEndRow
= static_cast<SCROW
>(n2
);
567 if (mnStartCol
== nEndCol
)
569 // All source data is in a single column.
570 meGlue
= GLUETYPE_ROWS
;
574 if (mnStartRow
== nEndRow
)
576 // All source data is in a single row.
577 meGlue
= GLUETYPE_COLS
;
582 SCCOL nC
= nEndCol
- mnStartCol
+ 1;
585 SCROW nR
= nEndRow
- mnStartRow
+ 1;
587 // #i103540# prevent invalid vector size
588 if ((nC
<= 0) || (nR
<= 0))
596 calcGlueState(nC
, nR
);
599 enum State
{ Hole
= 0, Occupied
= 1, Free
= 2, Glue
= 3 };
601 void Chart2Positioner::calcGlueState(SCCOL nColSize
, SCROW nRowSize
)
603 // TODO: This code can use some space optimization. Using an array to
604 // store individual cell's states is terribly inefficient esp for large
605 // data ranges; let's use flat_segment_tree to reduce memory usage here.
607 sal_uInt32 nCR
= static_cast<sal_uInt32
>(nColSize
*nRowSize
);
609 vector
<State
> aCellStates(nCR
, Hole
);
611 // Mark all referenced cells "occupied".
612 for (vector
<ScTokenRef
>::const_iterator itr
= mrRefTokens
.begin(), itrEnd
= mrRefTokens
.end();
613 itr
!= itrEnd
; ++itr
)
615 ScComplexRefData aData
;
616 ScRefTokenHelper::getDoubleRefDataFromToken(aData
, *itr
);
617 SCCOL nCol1
= aData
.Ref1
.Col() - mnStartCol
;
618 SCCOL nCol2
= aData
.Ref2
.Col() - mnStartCol
;
619 SCROW nRow1
= aData
.Ref1
.Row() - mnStartRow
;
620 SCROW nRow2
= aData
.Ref2
.Row() - mnStartRow
;
621 for (SCCOL nCol
= nCol1
; nCol
<= nCol2
; ++nCol
)
622 for (SCROW nRow
= nRow1
; nRow
<= nRow2
; ++nRow
)
624 size_t i
= nCol
*nRowSize
+ nRow
;
625 aCellStates
[i
] = Occupied
;
629 // If at least one cell in either the first column or first row is empty,
630 // we don't glue at all unless the whole column or row is empty; we expect
631 // all cells in the first column / row to be fully populated. If we have
632 // empty column or row, then we do glue by the column or row,
636 bool bGlueCols
= false;
637 for (SCCOL nCol
= 0; bGlue
&& nCol
< nColSize
; ++nCol
)
639 for (SCROW nRow
= 0; bGlue
&& nRow
< nRowSize
; ++nRow
)
641 size_t i
= nCol
*nRowSize
+ nRow
;
642 if (aCellStates
[i
] == Occupied
)
644 if (nCol
== 0 || nRow
== 0)
650 aCellStates
[i
] = Free
;
652 size_t nLast
= (nCol
+1)*nRowSize
- 1; // index for the last cell in the column.
653 if (bGlue
&& aCellStates
[nLast
] == Free
)
655 // Whole column is empty.
656 aCellStates
[nLast
] = Glue
;
661 bool bGlueRows
= false;
662 for (SCROW nRow
= 0; bGlue
&& nRow
< nRowSize
; ++nRow
)
665 for (SCCOL nCol
= 0; bGlue
&& nCol
< nColSize
; ++nCol
, i
+= nRowSize
)
667 if (aCellStates
[i
] == Occupied
)
669 if (nCol
== 0 || nRow
== 0)
675 aCellStates
[i
] = Free
;
677 i
= (nColSize
-1)*nRowSize
+ nRow
; // index for the row position in the last column.
678 if (bGlue
&& aCellStates
[i
] == Free
)
680 // Whole row is empty.
681 aCellStates
[i
] = Glue
;
687 for (sal_uInt32 n
= 1; bGlue
&& n
< nCR
; ++n
, ++i
)
688 if (aCellStates
[i
] == Hole
)
693 if (bGlueCols
&& bGlueRows
)
694 meGlue
= GLUETYPE_BOTH
;
696 meGlue
= GLUETYPE_ROWS
;
698 meGlue
= GLUETYPE_COLS
;
699 if (aCellStates
.front() != Occupied
)
700 mbDummyUpperLeft
= true;
703 meGlue
= GLUETYPE_NONE
;
706 void Chart2Positioner::createPositionMap()
708 if (meGlue
== GLUETYPE_NA
&& mpPositionMap
.get())
709 mpPositionMap
.reset();
711 if (mpPositionMap
.get())
716 bool bNoGlue
= (meGlue
== GLUETYPE_NONE
);
717 SAL_WNODEPRECATED_DECLARATIONS_PUSH
718 auto_ptr
<FormulaTokenMapMap
> pCols(new FormulaTokenMapMap
);
719 SAL_WNODEPRECATED_DECLARATIONS_POP
720 FormulaTokenMap
* pCol
= NULL
;
721 SCROW nNoGlueRow
= 0;
722 for (vector
<ScTokenRef
>::const_iterator itr
= mrRefTokens
.begin(), itrEnd
= mrRefTokens
.end();
723 itr
!= itrEnd
; ++itr
)
725 const ScTokenRef
& pToken
= *itr
;
727 bool bExternal
= ScRefTokenHelper::isExternalRef(pToken
);
728 sal_uInt16 nFileId
= bExternal
? pToken
->GetIndex() : 0;
729 svl::SharedString aTabName
= svl::SharedString::getEmptyString();
731 aTabName
= pToken
->GetString();
733 ScComplexRefData aData
;
734 if( !ScRefTokenHelper::getDoubleRefDataFromToken(aData
, *itr
) )
736 const ScSingleRefData
& s
= aData
.Ref1
;
737 const ScSingleRefData
& e
= aData
.Ref2
;
738 SCCOL nCol1
= s
.Col(), nCol2
= e
.Col();
739 SCROW nRow1
= s
.Row(), nRow2
= e
.Row();
740 SCTAB nTab1
= s
.Tab(), nTab2
= e
.Tab();
742 for (SCTAB nTab
= nTab1
; nTab
<= nTab2
; ++nTab
)
744 // columns on secondary sheets are appended; we treat them as if
745 // all columns are on the same sheet. TODO: We can't assume that
746 // the column range is 16-bit; remove that restriction.
747 sal_uInt32 nInsCol
= (static_cast<sal_uInt32
>(nTab
) << 16) |
748 (bNoGlue
? 0 : static_cast<sal_uInt32
>(nCol1
));
750 for (SCCOL nCol
= nCol1
; nCol
<= nCol2
; ++nCol
, ++nInsCol
)
752 FormulaTokenMapMap::const_iterator it
= pCols
->find(nInsCol
);
753 if (it
== pCols
->end())
755 pCol
= new FormulaTokenMap
;
756 (*pCols
)[ nInsCol
] = pCol
;
761 sal_uInt32 nInsRow
= static_cast<sal_uInt32
>(bNoGlue
? nNoGlueRow
: nRow1
);
762 for (SCROW nRow
= nRow1
; nRow
<= nRow2
; ++nRow
, ++nInsRow
)
764 ScSingleRefData aCellData
;
765 aCellData
.InitFlags();
766 aCellData
.SetFlag3D(true);
767 aCellData
.SetColRel(false);
768 aCellData
.SetRowRel(false);
769 aCellData
.SetTabRel(false);
770 aCellData
.SetAbsCol(nCol
);
771 aCellData
.SetAbsRow(nRow
);
772 aCellData
.SetAbsTab(nTab
);
774 if (pCol
->find(nInsRow
) == pCol
->end())
777 (*pCol
)[ nInsRow
] = new ScExternalSingleRefToken(nFileId
, aTabName
, aCellData
);
779 (*pCol
)[ nInsRow
] = new ScSingleRefToken(aCellData
);
784 nNoGlueRow
+= nRow2
- nRow1
+ 1;
787 bool bFillRowHeader
= mbRowHeaders
;
788 bool bFillColumnHeader
= mbColHeaders
;
790 SCSIZE nAllColCount
= static_cast<SCSIZE
>(pCols
->size());
791 SCSIZE nAllRowCount
= 0;
794 pCol
= pCols
->begin()->second
;
795 if (mbDummyUpperLeft
)
796 if (pCol
->find(0) == pCol
->end())
797 (*pCol
)[ 0 ] = NULL
; // Dummy fuer Beschriftung
798 nAllRowCount
= static_cast<SCSIZE
>(pCol
->size());
801 if( nAllColCount
!=0 && nAllRowCount
!=0 )
805 FormulaTokenMap
* pFirstCol
= pCols
->begin()->second
;
806 for (FormulaTokenMap::const_iterator it1
= pFirstCol
->begin(); it1
!= pFirstCol
->end(); ++it1
)
808 sal_uInt32 nKey
= it1
->first
;
809 for (FormulaTokenMapMap::const_iterator it2
= pCols
->begin(); it2
!= pCols
->end(); ++it2
)
812 if (pCol
->find(nKey
) == pCol
->end())
813 (*pCol
)[ nKey
] = NULL
;
819 new Chart2PositionMap(
820 static_cast<SCCOL
>(nAllColCount
), static_cast<SCROW
>(nAllRowCount
),
821 bFillRowHeader
, bFillColumnHeader
, *pCols
, mpDoc
));
823 // Destroy all column instances.
824 for (FormulaTokenMapMap::const_iterator it
= pCols
->begin(); it
!= pCols
->end(); ++it
)
832 * Function object to create a range string from a token list.
834 class Tokens2RangeString
: public unary_function
<ScTokenRef
, void>
837 Tokens2RangeString(ScDocument
* pDoc
, FormulaGrammar::Grammar eGram
, sal_Unicode cRangeSep
) :
838 mpRangeStr(new OUStringBuffer
),
841 mcRangeSep(cRangeSep
),
846 Tokens2RangeString(const Tokens2RangeString
& r
) :
847 mpRangeStr(r
.mpRangeStr
),
849 meGrammar(r
.meGrammar
),
850 mcRangeSep(r
.mcRangeSep
),
855 void operator() (const ScTokenRef
& rToken
)
857 ScCompiler
aCompiler(mpDoc
, ScAddress(0,0,0));
858 aCompiler
.SetGrammar(meGrammar
);
860 aCompiler
.CreateStringFromToken(aStr
, rToken
.get());
864 mpRangeStr
->append(mcRangeSep
);
865 mpRangeStr
->append(aStr
);
868 void getString(OUString
& rStr
)
870 rStr
= mpRangeStr
->makeStringAndClear();
874 shared_ptr
<OUStringBuffer
> mpRangeStr
;
876 FormulaGrammar::Grammar meGrammar
;
877 sal_Unicode mcRangeSep
;
882 * Function object to convert a list of tokens into a string form suitable
883 * for ODF export. In ODF, a range is expressed as
885 * (start cell address):(end cell address)
887 * and each address doesn't include any '$' symbols.
889 class Tokens2RangeStringXML
: public unary_function
<ScTokenRef
, void>
892 Tokens2RangeStringXML(ScDocument
* pDoc
) :
893 mpRangeStr(new OUStringBuffer
),
901 Tokens2RangeStringXML(const Tokens2RangeStringXML
& r
) :
902 mpRangeStr(r
.mpRangeStr
),
904 mcRangeSep(r
.mcRangeSep
),
905 mcAddrSep(r
.mcAddrSep
),
910 void operator() (const ScTokenRef
& rToken
)
915 mpRangeStr
->append(mcRangeSep
);
917 ScTokenRef aStart
, aEnd
;
918 bool bValidToken
= splitRangeToken(rToken
, aStart
, aEnd
);
919 OSL_ENSURE(bValidToken
, "invalid token");
922 ScCompiler
aCompiler(mpDoc
, ScAddress(0,0,0));
923 aCompiler
.SetGrammar(FormulaGrammar::GRAM_ENGLISH
);
926 aCompiler
.CreateStringFromToken(aStr
, aStart
.get());
927 mpRangeStr
->append(aStr
);
929 mpRangeStr
->append(mcAddrSep
);
932 aCompiler
.CreateStringFromToken(aStr
, aEnd
.get());
933 mpRangeStr
->append(aStr
);
937 void getString(OUString
& rStr
)
939 rStr
= mpRangeStr
->makeStringAndClear();
943 bool splitRangeToken(const ScTokenRef
& pToken
, ScTokenRef
& rStart
, ScTokenRef
& rEnd
) const
945 ScComplexRefData aData
;
946 bool bIsRefToken
= ScRefTokenHelper::getDoubleRefDataFromToken(aData
, pToken
);
947 OSL_ENSURE(bIsRefToken
, "invalid token");
950 bool bExternal
= ScRefTokenHelper::isExternalRef(pToken
);
951 sal_uInt16 nFileId
= bExternal
? pToken
->GetIndex() : 0;
952 svl::SharedString aTabName
= svl::SharedString::getEmptyString();
954 aTabName
= pToken
->GetString();
956 // In saving to XML, we don't prepend address with '$'.
957 setRelative(aData
.Ref1
);
958 setRelative(aData
.Ref2
);
960 // In XML, the range must explicitly specify sheet name.
961 aData
.Ref1
.SetFlag3D(true);
962 aData
.Ref2
.SetFlag3D(true);
965 rStart
.reset(new ScExternalSingleRefToken(nFileId
, aTabName
, aData
.Ref1
));
967 rStart
.reset(new ScSingleRefToken(aData
.Ref1
));
970 rEnd
.reset(new ScExternalSingleRefToken(nFileId
, aTabName
, aData
.Ref2
));
972 rEnd
.reset(new ScSingleRefToken(aData
.Ref2
));
976 void setRelative(ScSingleRefData
& rData
) const
978 rData
.SetColRel(true);
979 rData
.SetRowRel(true);
980 rData
.SetTabRel(true);
984 shared_ptr
<OUStringBuffer
> mpRangeStr
;
986 sal_Unicode mcRangeSep
;
987 sal_Unicode mcAddrSep
;
991 void lcl_convertTokensToString(OUString
& rStr
, const vector
<ScTokenRef
>& rTokens
, ScDocument
* pDoc
)
993 const sal_Unicode cRangeSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
994 FormulaGrammar::Grammar eGrammar
= pDoc
->GetGrammar();
995 Tokens2RangeString
func(pDoc
, eGrammar
, cRangeSep
);
996 func
= ::std::for_each(rTokens
.begin(), rTokens
.end(), func
);
997 func
.getString(rStr
);
1000 } // anonymous namespace
1002 // DataProvider ==============================================================
1004 ScChart2DataProvider::ScChart2DataProvider( ScDocument
* pDoc
)
1005 : m_pDocument( pDoc
)
1006 , m_aPropSet(lcl_GetDataProviderPropertyMap())
1007 , m_bIncludeHiddenCells( true)
1010 m_pDocument
->AddUnoObject( *this);
1013 ScChart2DataProvider::~ScChart2DataProvider()
1016 m_pDocument
->RemoveUnoObject( *this);
1020 void ScChart2DataProvider::Notify( SfxBroadcaster
& /*rBC*/, const SfxHint
& rHint
)
1022 if ( rHint
.ISA( SfxSimpleHint
) &&
1023 ((const SfxSimpleHint
&)rHint
).GetId() == SFX_HINT_DYING
)
1029 sal_Bool SAL_CALL
ScChart2DataProvider::createDataSourcePossible( const uno::Sequence
< beans::PropertyValue
>& aArguments
)
1030 throw (uno::RuntimeException
, std::exception
)
1032 SolarMutexGuard aGuard
;
1036 OUString aRangeRepresentation
;
1037 for(sal_Int32 i
= 0; i
< aArguments
.getLength(); ++i
)
1039 if ( aArguments
[i
].Name
== "CellRangeRepresentation" )
1041 aArguments
[i
].Value
>>= aRangeRepresentation
;
1045 vector
<ScTokenRef
> aTokens
;
1046 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
1047 ScRefTokenHelper::compileRangeRepresentation(
1048 aTokens
, aRangeRepresentation
, m_pDocument
, cSep
, m_pDocument
->GetGrammar(), true);
1049 return !aTokens
.empty();
1055 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1056 Reference
< chart2::data::XLabeledDataSequence
> lcl_createLabeledDataSequenceFromTokens(
1057 auto_ptr
< vector
< ScTokenRef
> > pValueTokens
, auto_ptr
< vector
< ScTokenRef
> > pLabelTokens
,
1058 ScDocument
* pDoc
, const Reference
< chart2::data::XDataProvider
>& xDP
, bool bIncludeHiddenCells
)
1060 Reference
< chart2::data::XLabeledDataSequence
> xResult
;
1061 bool bHasValues
= pValueTokens
.get() && !pValueTokens
->empty();
1062 bool bHasLabel
= pLabelTokens
.get() && !pLabelTokens
->empty();
1063 if( bHasValues
|| bHasLabel
)
1067 Reference
< uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
1068 if ( xContext
.is() )
1070 xResult
.set( chart2::data::LabeledDataSequence::create(xContext
), uno::UNO_QUERY_THROW
);
1074 Reference
< chart2::data::XDataSequence
> xSeq( new ScChart2DataSequence( pDoc
, xDP
, pValueTokens
.release(), bIncludeHiddenCells
) );
1075 xResult
->setValues( xSeq
);
1079 Reference
< chart2::data::XDataSequence
> xLabelSeq( new ScChart2DataSequence( pDoc
, xDP
, pLabelTokens
.release(), bIncludeHiddenCells
) );
1080 xResult
->setLabel( xLabelSeq
);
1083 catch( const uno::Exception
& )
1089 SAL_WNODEPRECATED_DECLARATIONS_POP
1093 * Check the current list of reference tokens, and add the upper left
1094 * corner of the minimum range that encloses all ranges if certain
1095 * conditions are met.
1097 * @param rRefTokens list of reference tokens
1099 * @return true if the corner was added, false otherwise.
1101 bool lcl_addUpperLeftCornerIfMissing(vector
<ScTokenRef
>& rRefTokens
,
1102 SCROW nCornerRowCount
=1, SCCOL nCornerColumnCount
=1)
1107 if (rRefTokens
.empty())
1110 SCCOL nMinCol
= MAXCOLCOUNT
;
1111 SCROW nMinRow
= MAXROWCOUNT
;
1116 sal_uInt16 nFileId
= 0;
1117 svl::SharedString aExtTabName
;
1118 bool bExternal
= false;
1120 vector
<ScTokenRef
>::const_iterator itr
= rRefTokens
.begin(), itrEnd
= rRefTokens
.end();
1122 // Get the first ref token.
1123 ScTokenRef pToken
= *itr
;
1124 switch (pToken
->GetType())
1128 const ScSingleRefData
& rData
= pToken
->GetSingleRef();
1129 nMinCol
= rData
.Col();
1130 nMinRow
= rData
.Row();
1131 nMaxCol
= rData
.Col();
1132 nMaxRow
= rData
.Row();
1138 const ScComplexRefData
& rData
= pToken
->GetDoubleRef();
1139 nMinCol
= min(rData
.Ref1
.Col(), rData
.Ref2
.Col());
1140 nMinRow
= min(rData
.Ref1
.Row(), rData
.Ref2
.Row());
1141 nMaxCol
= max(rData
.Ref1
.Col(), rData
.Ref2
.Col());
1142 nMaxRow
= max(rData
.Ref1
.Row(), rData
.Ref2
.Row());
1143 nTab
= rData
.Ref1
.Tab();
1146 case svExternalSingleRef
:
1148 const ScSingleRefData
& rData
= pToken
->GetSingleRef();
1149 nMinCol
= rData
.Col();
1150 nMinRow
= rData
.Row();
1151 nMaxCol
= rData
.Col();
1152 nMaxRow
= rData
.Row();
1154 nFileId
= pToken
->GetIndex();
1155 aExtTabName
= pToken
->GetString();
1159 case svExternalDoubleRef
:
1161 const ScComplexRefData
& rData
= pToken
->GetDoubleRef();
1162 nMinCol
= min(rData
.Ref1
.Col(), rData
.Ref2
.Col());
1163 nMinRow
= min(rData
.Ref1
.Row(), rData
.Ref2
.Row());
1164 nMaxCol
= max(rData
.Ref1
.Col(), rData
.Ref2
.Col());
1165 nMaxRow
= max(rData
.Ref1
.Row(), rData
.Ref2
.Row());
1166 nTab
= rData
.Ref1
.Tab();
1167 nFileId
= pToken
->GetIndex();
1168 aExtTabName
= pToken
->GetString();
1176 // Determine the minimum range enclosing all data ranges. Also make sure
1177 // that they are all on the same table.
1179 for (++itr
; itr
!= itrEnd
; ++itr
)
1182 switch (pToken
->GetType())
1186 const ScSingleRefData
& rData
= pToken
->GetSingleRef();
1188 nMinCol
= min(nMinCol
, rData
.Col());
1189 nMinRow
= min(nMinRow
, rData
.Row());
1190 nMaxCol
= max(nMaxCol
, rData
.Col());
1191 nMaxRow
= max(nMaxRow
, rData
.Row());
1192 if (nTab
!= rData
.Tab() || bExternal
)
1198 const ScComplexRefData
& rData
= pToken
->GetDoubleRef();
1200 nMinCol
= min(nMinCol
, rData
.Ref1
.Col());
1201 nMinCol
= min(nMinCol
, rData
.Ref2
.Col());
1202 nMinRow
= min(nMinRow
, rData
.Ref1
.Row());
1203 nMinRow
= min(nMinRow
, rData
.Ref2
.Row());
1205 nMaxCol
= max(nMaxCol
, rData
.Ref1
.Col());
1206 nMaxCol
= max(nMaxCol
, rData
.Ref2
.Col());
1207 nMaxRow
= max(nMaxRow
, rData
.Ref1
.Row());
1208 nMaxRow
= max(nMaxRow
, rData
.Ref2
.Row());
1210 if (nTab
!= rData
.Ref1
.Tab() || bExternal
)
1214 case svExternalSingleRef
:
1219 if (nFileId
!= pToken
->GetIndex() || aExtTabName
!= pToken
->GetString())
1222 const ScSingleRefData
& rData
= pToken
->GetSingleRef();
1224 nMinCol
= min(nMinCol
, rData
.Col());
1225 nMinRow
= min(nMinRow
, rData
.Row());
1226 nMaxCol
= max(nMaxCol
, rData
.Col());
1227 nMaxRow
= max(nMaxRow
, rData
.Row());
1230 case svExternalDoubleRef
:
1235 if (nFileId
!= pToken
->GetIndex() || aExtTabName
!= pToken
->GetString())
1238 const ScComplexRefData
& rData
= pToken
->GetDoubleRef();
1240 nMinCol
= min(nMinCol
, rData
.Ref1
.Col());
1241 nMinCol
= min(nMinCol
, rData
.Ref2
.Col());
1242 nMinRow
= min(nMinRow
, rData
.Ref1
.Row());
1243 nMinRow
= min(nMinRow
, rData
.Ref2
.Row());
1245 nMaxCol
= max(nMaxCol
, rData
.Ref1
.Col());
1246 nMaxCol
= max(nMaxCol
, rData
.Ref2
.Col());
1247 nMaxRow
= max(nMaxRow
, rData
.Ref1
.Row());
1248 nMaxRow
= max(nMaxRow
, rData
.Ref2
.Row());
1256 if (nMinRow
>= nMaxRow
|| nMinCol
>= nMaxCol
||
1257 nMinRow
>= MAXROWCOUNT
|| nMinCol
>= MAXCOLCOUNT
||
1258 nMaxRow
>= MAXROWCOUNT
|| nMaxCol
>= MAXCOLCOUNT
)
1260 // Invalid range. Bail out.
1264 // Check if the following conditions are met:
1266 // 1) The upper-left corner cell is not included.
1267 // 2) The three adjacent cells of that corner cell are included.
1269 bool bRight
= false, bBottom
= false, bDiagonal
= false;
1270 for (itr
= rRefTokens
.begin(); itr
!= itrEnd
; ++itr
)
1273 switch (pToken
->GetType())
1276 case svExternalSingleRef
:
1278 const ScSingleRefData
& rData
= pToken
->GetSingleRef();
1279 if (rData
.Col() == nMinCol
&& rData
.Row() == nMinRow
)
1280 // The corner cell is contained.
1283 if (rData
.Col() == nMinCol
+nCornerColumnCount
&& rData
.Row() == nMinRow
)
1286 if (rData
.Col() == nMinCol
&& rData
.Row() == nMinRow
+nCornerRowCount
)
1289 if (rData
.Col() == nMinCol
+nCornerColumnCount
&& rData
.Row() == nMinRow
+nCornerRowCount
)
1294 case svExternalDoubleRef
:
1296 const ScComplexRefData
& rData
= pToken
->GetDoubleRef();
1297 const ScSingleRefData
& r1
= rData
.Ref1
;
1298 const ScSingleRefData
& r2
= rData
.Ref2
;
1299 if (r1
.Col() <= nMinCol
&& nMinCol
<= r2
.Col() &&
1300 r1
.Row() <= nMinRow
&& nMinRow
<= r2
.Row())
1301 // The corner cell is contained.
1304 if (r1
.Col() <= nMinCol
+nCornerColumnCount
&& nMinCol
+nCornerColumnCount
<= r2
.Col() &&
1305 r1
.Row() <= nMinRow
&& nMinRow
<= r2
.Row())
1308 if (r1
.Col() <= nMinCol
&& nMinCol
<= r2
.Col() &&
1309 r1
.Row() <= nMinRow
+nCornerRowCount
&& nMinRow
+nCornerRowCount
<= r2
.Row())
1312 if (r1
.Col() <= nMinCol
+nCornerColumnCount
&& nMinCol
+nCornerColumnCount
<= r2
.Col() &&
1313 r1
.Row() <= nMinRow
+nCornerRowCount
&& nMinRow
+nCornerRowCount
<= r2
.Row())
1322 if (!bRight
|| !bBottom
|| !bDiagonal
)
1323 // Not all the adjacent cells are included. Bail out.
1326 ScSingleRefData aData
;
1328 aData
.SetFlag3D(true);
1329 aData
.SetAbsCol(nMinCol
);
1330 aData
.SetAbsRow(nMinRow
);
1331 aData
.SetAbsTab(nTab
);
1333 if( nCornerRowCount
==1 && nCornerColumnCount
==1 )
1338 new ScExternalSingleRefToken(nFileId
, aExtTabName
, aData
));
1339 ScRefTokenHelper::join(rRefTokens
, pCorner
, ScAddress());
1343 ScTokenRef
pCorner(new ScSingleRefToken(aData
));
1344 ScRefTokenHelper::join(rRefTokens
, pCorner
, ScAddress());
1349 ScSingleRefData
aDataEnd(aData
);
1350 aDataEnd
.IncCol(nCornerColumnCount
-1);
1351 aDataEnd
.IncRow(nCornerRowCount
-1);
1358 new ScExternalDoubleRefToken(nFileId
, aExtTabName
, r
));
1359 ScRefTokenHelper::join(rRefTokens
, pCorner
, ScAddress());
1363 ScTokenRef
pCorner(new ScDoubleRefToken(r
));
1364 ScRefTokenHelper::join(rRefTokens
, pCorner
, ScAddress());
1371 #define SHRINK_RANGE_THRESHOLD 10000
1373 class ShrinkRefTokenToDataRange
: std::unary_function
<ScTokenRef
, void>
1377 ShrinkRefTokenToDataRange(ScDocument
* pDoc
) : mpDoc(pDoc
) {}
1378 void operator() (ScTokenRef
& rRef
)
1380 if (ScRefTokenHelper::isExternalRef(rRef
))
1383 // Don't assume an ScDoubleRefToken if it isn't. It can be at least an
1384 // ScSingleRefToken, then there isn't anything to shrink.
1385 if (rRef
->GetType() != svDoubleRef
)
1388 ScComplexRefData
& rData
= rRef
->GetDoubleRef();
1389 ScSingleRefData
& s
= rData
.Ref1
;
1390 ScSingleRefData
& e
= rData
.Ref2
;
1392 if(abs((e
.Col()-s
.Col())*(e
.Row()-s
.Row())) < SHRINK_RANGE_THRESHOLD
)
1395 SCCOL nMinCol
= MAXCOL
, nMaxCol
= 0;
1396 SCROW nMinRow
= MAXROW
, nMaxRow
= 0;
1398 // Determine the smallest range that encompasses the data ranges of all sheets.
1399 SCTAB nTab1
= s
.Tab(), nTab2
= e
.Tab();
1400 for (SCTAB nTab
= nTab1
; nTab
<= nTab2
; ++nTab
)
1402 SCCOL nCol1
= 0, nCol2
= MAXCOL
;
1403 SCROW nRow1
= 0, nRow2
= MAXROW
;
1404 mpDoc
->ShrinkToDataArea(nTab
, nCol1
, nRow1
, nCol2
, nRow2
);
1405 nMinCol
= std::min(nMinCol
, nCol1
);
1406 nMinRow
= std::min(nMinRow
, nRow1
);
1407 nMaxCol
= std::max(nMaxCol
, nCol2
);
1408 nMaxRow
= std::max(nMaxRow
, nRow2
);
1411 // Shrink range to the data range if applicable.
1412 if (s
.Col() < nMinCol
)
1413 s
.SetAbsCol(nMinCol
);
1414 if (s
.Row() < nMinRow
)
1415 s
.SetAbsRow(nMinRow
);
1416 if (e
.Col() > nMaxCol
)
1417 e
.SetAbsCol(nMaxCol
);
1418 if (e
.Row() > nMaxRow
)
1419 e
.SetAbsRow(nMaxRow
);
1423 void shrinkToDataRange(ScDocument
* pDoc
, vector
<ScTokenRef
>& rRefTokens
)
1425 std::for_each(rRefTokens
.begin(), rRefTokens
.end(), ShrinkRefTokenToDataRange(pDoc
));
1430 uno::Reference
< chart2::data::XDataSource
> SAL_CALL
1431 ScChart2DataProvider::createDataSource(
1432 const uno::Sequence
< beans::PropertyValue
>& aArguments
)
1433 throw( lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
)
1435 SolarMutexGuard aGuard
;
1436 if ( ! m_pDocument
)
1437 throw uno::RuntimeException();
1439 uno::Reference
< chart2::data::XDataSource
> xResult
;
1441 bool bCategories
= false;
1442 bool bOrientCol
= true;
1443 OUString aRangeRepresentation
;
1444 uno::Sequence
< sal_Int32
> aSequenceMapping
;
1445 bool bTimeBased
= false;
1446 for(sal_Int32 i
= 0; i
< aArguments
.getLength(); ++i
)
1448 if ( aArguments
[i
].Name
== "DataRowSource" )
1450 chart::ChartDataRowSource eSource
= chart::ChartDataRowSource_COLUMNS
;
1451 if( ! (aArguments
[i
].Value
>>= eSource
))
1453 sal_Int32
nSource(0);
1454 if( aArguments
[i
].Value
>>= nSource
)
1455 eSource
= (static_cast< chart::ChartDataRowSource
>( nSource
));
1457 bOrientCol
= (eSource
== chart::ChartDataRowSource_COLUMNS
);
1459 else if ( aArguments
[i
].Name
== "FirstCellAsLabel" )
1461 bLabel
= ::cppu::any2bool(aArguments
[i
].Value
);
1463 else if ( aArguments
[i
].Name
== "HasCategories" )
1465 bCategories
= ::cppu::any2bool(aArguments
[i
].Value
);
1467 else if ( aArguments
[i
].Name
== "CellRangeRepresentation" )
1469 aArguments
[i
].Value
>>= aRangeRepresentation
;
1471 else if ( aArguments
[i
].Name
== "SequenceMapping" )
1473 aArguments
[i
].Value
>>= aSequenceMapping
;
1475 else if ( aArguments
[i
].Name
== "TimeBased" )
1477 aArguments
[i
].Value
>>= bTimeBased
;
1481 vector
<ScTokenRef
> aRefTokens
;
1482 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
1483 ScRefTokenHelper::compileRangeRepresentation(
1484 aRefTokens
, aRangeRepresentation
, m_pDocument
, cSep
, m_pDocument
->GetGrammar(), true);
1485 if (aRefTokens
.empty())
1486 // Invalid range representation. Bail out.
1487 throw lang::IllegalArgumentException();
1489 SCTAB nTimeBasedStart
= MAXTAB
;
1490 SCTAB nTimeBasedEnd
= 0;
1493 // limit to first sheet
1494 for(vector
<ScTokenRef
>::iterator itr
= aRefTokens
.begin(),
1495 itrEnd
= aRefTokens
.end(); itr
!= itrEnd
; ++itr
)
1497 if ((*itr
)->GetType() != svDoubleRef
)
1500 ScComplexRefData
& rData
= (*itr
)->GetDoubleRef();
1501 ScSingleRefData
& s
= rData
.Ref1
;
1502 ScSingleRefData
& e
= rData
.Ref2
;
1504 nTimeBasedStart
= std::min(nTimeBasedStart
, s
.Tab());
1505 nTimeBasedEnd
= std::min(nTimeBasedEnd
, e
.Tab());
1507 if(s
.Tab() != e
.Tab())
1508 e
.SetAbsTab(s
.Tab());
1513 shrinkToDataRange(m_pDocument
, aRefTokens
);
1516 lcl_addUpperLeftCornerIfMissing(aRefTokens
); //#i90669#
1518 bool bColHeaders
= (bOrientCol
? bLabel
: bCategories
);
1519 bool bRowHeaders
= (bOrientCol
? bCategories
: bLabel
);
1521 Chart2Positioner
aChPositioner(m_pDocument
, aRefTokens
);
1522 aChPositioner
.setHeaders(bColHeaders
, bRowHeaders
);
1524 const Chart2PositionMap
* pChartMap
= aChPositioner
.getPositionMap();
1526 // No chart position map instance. Bail out.
1529 ScChart2DataSource
* pDS
= NULL
;
1530 ::std::list
< Reference
< chart2::data::XLabeledDataSequence
> > aSeqs
;
1535 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1536 auto_ptr
< vector
<ScTokenRef
> > pValueTokens(NULL
);
1537 SAL_WNODEPRECATED_DECLARATIONS_POP
1539 pValueTokens
.reset(pChartMap
->getAllRowHeaderRanges());
1541 pValueTokens
.reset(pChartMap
->getAllColHeaderRanges());
1543 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1544 auto_ptr
< vector
<ScTokenRef
> > pLabelTokens(
1545 pChartMap
->getLeftUpperCornerRanges());
1546 SAL_WNODEPRECATED_DECLARATIONS_POP
1548 Reference
< chart2::data::XLabeledDataSequence
> xCategories
= lcl_createLabeledDataSequenceFromTokens(
1549 pValueTokens
, pLabelTokens
, m_pDocument
, this, m_bIncludeHiddenCells
); //ownership of pointers is transferred!
1550 if ( xCategories
.is() )
1552 aSeqs
.push_back( xCategories
);
1556 // Fill Serieses (values and label)
1557 sal_Int32 nCount
= bOrientCol
? pChartMap
->getDataColCount() : pChartMap
->getDataRowCount();
1558 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
1560 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1561 auto_ptr
< vector
<ScTokenRef
> > pValueTokens(NULL
);
1562 auto_ptr
< vector
<ScTokenRef
> > pLabelTokens(NULL
);
1563 SAL_WNODEPRECATED_DECLARATIONS_POP
1566 pValueTokens
.reset(pChartMap
->getDataColRanges(static_cast<SCCOL
>(i
)));
1567 pLabelTokens
.reset(pChartMap
->getColHeaderRanges(static_cast<SCCOL
>(i
)));
1571 pValueTokens
.reset(pChartMap
->getDataRowRanges(static_cast<SCROW
>(i
)));
1572 pLabelTokens
.reset(pChartMap
->getRowHeaderRanges(static_cast<SCROW
>(i
)));
1574 Reference
< chart2::data::XLabeledDataSequence
> xChartSeries
= lcl_createLabeledDataSequenceFromTokens(
1575 pValueTokens
, pLabelTokens
, m_pDocument
, this, m_bIncludeHiddenCells
); //ownership of pointers is transferred!
1576 if ( xChartSeries
.is() && xChartSeries
->getValues().is() && xChartSeries
->getValues()->getData().getLength() )
1578 aSeqs
.push_back( xChartSeries
);
1582 pDS
= new ScChart2DataSource(m_pDocument
);
1583 ::std::list
< Reference
< chart2::data::XLabeledDataSequence
> >::iterator
aItr( aSeqs
.begin() );
1584 ::std::list
< Reference
< chart2::data::XLabeledDataSequence
> >::iterator
aEndItr( aSeqs
.end() );
1586 //reorder labeled sequences according to aSequenceMapping
1587 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> > aSeqVector
;
1588 while(aItr
!= aEndItr
)
1590 aSeqVector
.push_back(*aItr
);
1594 ::std::map
< sal_Int32
, Reference
< chart2::data::XLabeledDataSequence
> > aSequenceMap
;
1595 for( sal_Int32 nNewIndex
= 0; nNewIndex
< aSequenceMapping
.getLength(); nNewIndex
++ )
1597 // note: assuming that the values in the sequence mapping are always non-negative
1598 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> >::size_type
nOldIndex( static_cast< sal_uInt32
>( aSequenceMapping
[nNewIndex
] ) );
1599 if( nOldIndex
< aSeqVector
.size() )
1601 pDS
->AddLabeledSequence( aSeqVector
[nOldIndex
] );
1602 aSeqVector
[nOldIndex
] = 0;
1606 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> >::iterator
aVectorItr( aSeqVector
.begin() );
1607 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> >::iterator
aVectorEndItr( aSeqVector
.end() );
1608 while(aVectorItr
!= aVectorEndItr
)
1610 Reference
< chart2::data::XLabeledDataSequence
> xSeq( *aVectorItr
);
1613 pDS
->AddLabeledSequence( xSeq
);
1626 * Function object to create a list of table numbers from a token list.
1628 class InsertTabNumber
: public unary_function
<ScTokenRef
, void>
1632 mpTabNumList(new list
<SCTAB
>())
1636 InsertTabNumber(const InsertTabNumber
& r
) :
1637 mpTabNumList(r
.mpTabNumList
)
1641 void operator() (const ScTokenRef
& pToken
) const
1643 if (!ScRefTokenHelper::isRef(pToken
))
1646 const ScSingleRefData
& r
= pToken
->GetSingleRef();
1647 mpTabNumList
->push_back(r
.Tab());
1650 void getList(list
<SCTAB
>& rList
)
1652 mpTabNumList
->swap(rList
);
1655 shared_ptr
< list
<SCTAB
> > mpTabNumList
;
1662 void initRangeAnalyzer( const vector
<ScTokenRef
>& rTokens
);
1663 void analyzeRange( sal_Int32
& rnDataInRows
, sal_Int32
& rnDataInCols
,
1664 bool& rbRowSourceAmbiguous
) const;
1665 bool inSameSingleRow( RangeAnalyzer
& rOther
);
1666 bool inSameSingleColumn( RangeAnalyzer
& rOther
);
1667 SCROW
getRowCount() { return mnRowCount
; }
1668 SCCOL
getColumnCount() { return mnColumnCount
; }
1674 SCCOL mnColumnCount
;
1676 SCCOL mnStartColumn
;
1680 RangeAnalyzer::RangeAnalyzer()
1682 , mbAmbiguous(false)
1690 void RangeAnalyzer::initRangeAnalyzer( const vector
<ScTokenRef
>& rTokens
)
1697 if( rTokens
.empty() )
1704 vector
<ScTokenRef
>::const_iterator itr
= rTokens
.begin(), itrEnd
= rTokens
.end();
1705 for (; itr
!= itrEnd
; ++itr
)
1707 ScTokenRef aRefToken
= *itr
;
1708 StackVar eVar
= aRefToken
->GetType();
1709 if (eVar
== svDoubleRef
|| eVar
== svExternalDoubleRef
)
1711 const ScComplexRefData
& r
= aRefToken
->GetDoubleRef();
1712 if (r
.Ref1
.Tab() == r
.Ref2
.Tab())
1714 mnColumnCount
= std::max
<SCCOL
>(mnColumnCount
, static_cast<SCCOL
>(abs(r
.Ref2
.Col() - r
.Ref1
.Col())+1));
1715 mnRowCount
= std::max
<SCROW
>(mnRowCount
, static_cast<SCROW
>(abs(r
.Ref2
.Row() - r
.Ref1
.Row())+1));
1716 if( mnStartColumn
== -1 )
1718 mnStartColumn
= r
.Ref1
.Col();
1719 mnStartRow
= r
.Ref1
.Row();
1723 if (mnStartColumn
!= r
.Ref1
.Col() && mnStartRow
!= r
.Ref1
.Row())
1730 else if (eVar
== svSingleRef
|| eVar
== svExternalSingleRef
)
1732 const ScSingleRefData
& r
= aRefToken
->GetSingleRef();
1733 mnColumnCount
= std::max
<SCCOL
>( mnColumnCount
, 1);
1734 mnRowCount
= std::max
<SCROW
>( mnRowCount
, 1);
1735 if( mnStartColumn
== -1 )
1737 mnStartColumn
= r
.Col();
1738 mnStartRow
= r
.Row();
1742 if (mnStartColumn
!= r
.Col() && mnStartRow
!= r
.Row())
1751 void RangeAnalyzer::analyzeRange( sal_Int32
& rnDataInRows
,
1752 sal_Int32
& rnDataInCols
,
1753 bool& rbRowSourceAmbiguous
) const
1755 if(!mbEmpty
&& !mbAmbiguous
)
1757 if( mnRowCount
==1 && mnColumnCount
>1 )
1759 else if( mnColumnCount
==1 && mnRowCount
>1 )
1761 else if( mnRowCount
>1 && mnColumnCount
>1 )
1762 rbRowSourceAmbiguous
= true;
1765 rbRowSourceAmbiguous
= true;
1768 bool RangeAnalyzer::inSameSingleRow( RangeAnalyzer
& rOther
)
1770 if( mnStartRow
==rOther
.mnStartRow
&&
1771 mnRowCount
==1 && rOther
.mnRowCount
==1 )
1776 bool RangeAnalyzer::inSameSingleColumn( RangeAnalyzer
& rOther
)
1778 if( mnStartColumn
==rOther
.mnStartColumn
&&
1779 mnColumnCount
==1 && rOther
.mnColumnCount
==1 )
1784 } //end anonymous namespace
1786 uno::Sequence
< beans::PropertyValue
> SAL_CALL
ScChart2DataProvider::detectArguments(
1787 const uno::Reference
< chart2::data::XDataSource
>& xDataSource
)
1788 throw (uno::RuntimeException
, std::exception
)
1790 ::std::vector
< beans::PropertyValue
> aResult
;
1791 bool bRowSourceDetected
= false;
1792 bool bFirstCellAsLabel
= false;
1793 bool bHasCategories
= false;
1796 bool bHasCategoriesLabels
= false;
1797 vector
<ScTokenRef
> aAllCategoriesValuesTokens
;
1798 vector
<ScTokenRef
> aAllSeriesLabelTokens
;
1800 chart::ChartDataRowSource eRowSource
= chart::ChartDataRowSource_COLUMNS
;
1802 vector
<ScTokenRef
> aAllTokens
;
1804 // parse given data source and collect infos
1806 SolarMutexGuard aGuard
;
1807 OSL_ENSURE( m_pDocument
, "No Document -> no detectArguments" );
1808 if(!m_pDocument
||!xDataSource
.is())
1809 return lcl_VectorToSequence( aResult
);
1811 sal_Int32 nDataInRows
= 0;
1812 sal_Int32 nDataInCols
= 0;
1813 bool bRowSourceAmbiguous
= false;
1815 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSequences( xDataSource
->getDataSequences());
1816 const sal_Int32
nCount( aSequences
.getLength());
1817 RangeAnalyzer aPrevLabel
,aPrevValues
;
1818 for( sal_Int32 nIdx
=0; nIdx
<nCount
; ++nIdx
)
1820 Reference
< chart2::data::XLabeledDataSequence
> xLS(aSequences
[nIdx
]);
1823 bool bThisIsCategories
= false;
1826 Reference
< beans::XPropertySet
> xSeqProp( xLS
->getValues(), uno::UNO_QUERY
);
1828 if( xSeqProp
.is() && (xSeqProp
->getPropertyValue("Role") >>= aRole
) &&
1829 aRole
== "categories" )
1830 bThisIsCategories
= bHasCategories
= true;
1833 RangeAnalyzer aLabel
,aValues
;
1835 Reference
< chart2::data::XDataSequence
> xLabel( xLS
->getLabel());
1838 bFirstCellAsLabel
= true;
1839 vector
<ScTokenRef
> aTokens
;
1840 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
1841 ScRefTokenHelper::compileRangeRepresentation(
1842 aTokens
, xLabel
->getSourceRangeRepresentation(), m_pDocument
, cSep
, m_pDocument
->GetGrammar(), true);
1843 aLabel
.initRangeAnalyzer(aTokens
);
1844 vector
<ScTokenRef
>::const_iterator itr
= aTokens
.begin(), itrEnd
= aTokens
.end();
1845 for (; itr
!= itrEnd
; ++itr
)
1847 ScRefTokenHelper::join(aAllTokens
, *itr
, ScAddress());
1848 if(!bThisIsCategories
)
1849 ScRefTokenHelper::join(aAllSeriesLabelTokens
, *itr
, ScAddress());
1851 if(bThisIsCategories
)
1852 bHasCategoriesLabels
=true;
1855 Reference
< chart2::data::XDataSequence
> xValues( xLS
->getValues());
1858 vector
<ScTokenRef
> aTokens
;
1859 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
1860 ScRefTokenHelper::compileRangeRepresentation(
1861 aTokens
, xValues
->getSourceRangeRepresentation(), m_pDocument
, cSep
, m_pDocument
->GetGrammar(), true);
1862 aValues
.initRangeAnalyzer(aTokens
);
1863 vector
<ScTokenRef
>::const_iterator itr
= aTokens
.begin(), itrEnd
= aTokens
.end();
1864 for (; itr
!= itrEnd
; ++itr
)
1866 ScRefTokenHelper::join(aAllTokens
, *itr
, ScAddress());
1867 if(bThisIsCategories
)
1868 ScRefTokenHelper::join(aAllCategoriesValuesTokens
, *itr
, ScAddress());
1872 if(!bThisIsCategories
|| nCount
==1) //categories might span multiple rows *and* columns, so they should be used for detection only if nothing else is available
1874 if (!bRowSourceAmbiguous
)
1876 aValues
.analyzeRange(nDataInRows
,nDataInCols
,bRowSourceAmbiguous
);
1877 aLabel
.analyzeRange(nDataInRows
,nDataInCols
,bRowSourceAmbiguous
);
1878 if (nDataInRows
> 1 && nDataInCols
> 1)
1879 bRowSourceAmbiguous
= true;
1880 else if( !bRowSourceAmbiguous
&& !nDataInRows
&& !nDataInCols
)
1882 if( aValues
.inSameSingleColumn( aLabel
) )
1884 else if( aValues
.inSameSingleRow( aLabel
) )
1888 //#i86188# also detect a single column split into rows correctly
1889 if( aValues
.inSameSingleColumn( aPrevValues
) )
1891 else if( aValues
.inSameSingleRow( aPrevValues
) )
1893 else if( aLabel
.inSameSingleColumn( aPrevLabel
) )
1895 else if( aLabel
.inSameSingleRow( aPrevLabel
) )
1901 aPrevValues
=aValues
;
1906 if (!bRowSourceAmbiguous
)
1908 bRowSourceDetected
= true;
1909 eRowSource
= ( nDataInRows
> 0
1910 ? chart::ChartDataRowSource_ROWS
1911 : chart::ChartDataRowSource_COLUMNS
);
1915 // set DataRowSource to the better of the two ambiguities
1916 eRowSource
= ( nDataInRows
> nDataInCols
1917 ? chart::ChartDataRowSource_ROWS
1918 : chart::ChartDataRowSource_COLUMNS
);
1925 list
<SCTAB
> aTableNumList
;
1926 InsertTabNumber func
;
1927 func
= ::std::for_each(aAllTokens
.begin(), aAllTokens
.end(), func
);
1928 func
.getList(aTableNumList
);
1930 beans::PropertyValue( OUString("TableNumberList"), -1,
1931 uno::makeAny( lcl_createTableNumberList( aTableNumList
) ),
1932 beans::PropertyState_DIRECT_VALUE
));
1935 // DataRowSource (calculated before)
1936 if( bRowSourceDetected
)
1939 beans::PropertyValue( OUString("DataRowSource"), -1,
1940 uno::makeAny( eRowSource
), beans::PropertyState_DIRECT_VALUE
));
1944 if( bRowSourceDetected
)
1947 beans::PropertyValue( OUString("HasCategories"), -1,
1948 uno::makeAny( bHasCategories
), beans::PropertyState_DIRECT_VALUE
));
1952 if( bRowSourceDetected
)
1955 beans::PropertyValue( OUString("FirstCellAsLabel"), -1,
1956 uno::makeAny( bFirstCellAsLabel
), beans::PropertyState_DIRECT_VALUE
));
1959 // Add the left upper corner to the range if it is missing.
1960 if (bRowSourceDetected
&& bFirstCellAsLabel
&& bHasCategories
&& !bHasCategoriesLabels
)
1962 RangeAnalyzer aTop
,aLeft
;
1963 if( eRowSource
==chart::ChartDataRowSource_COLUMNS
)
1965 aTop
.initRangeAnalyzer(aAllSeriesLabelTokens
);
1966 aLeft
.initRangeAnalyzer(aAllCategoriesValuesTokens
);
1970 aTop
.initRangeAnalyzer(aAllCategoriesValuesTokens
);
1971 aLeft
.initRangeAnalyzer(aAllSeriesLabelTokens
);
1973 lcl_addUpperLeftCornerIfMissing(aAllTokens
, aTop
.getRowCount(), aLeft
.getColumnCount());//e.g. #i91212#
1976 // Get range string.
1977 lcl_convertTokensToString(sRangeRep
, aAllTokens
, m_pDocument
);
1979 // add cell range property
1981 beans::PropertyValue( OUString("CellRangeRepresentation"), -1,
1982 uno::makeAny( sRangeRep
), beans::PropertyState_DIRECT_VALUE
));
1985 bool bSequencesReordered
= true;//todo detect this above or detect this sequence mapping cheaper ...
1986 if( bSequencesReordered
&& bRowSourceDetected
)
1988 bool bDifferentIndexes
= false;
1990 std::vector
< sal_Int32
> aSequenceMappingVector
;
1992 uno::Reference
< chart2::data::XDataSource
> xCompareDataSource
;
1995 xCompareDataSource
.set( this->createDataSource( lcl_VectorToSequence( aResult
) ) );
1997 catch( const lang::IllegalArgumentException
& )
1999 // creation of data source to compare didn't work, so we cannot
2000 // create a sequence mapping
2003 if( xDataSource
.is() && xCompareDataSource
.is() )
2005 uno::Sequence
< uno::Reference
< chart2::data::XLabeledDataSequence
> > aOldSequences(
2006 xCompareDataSource
->getDataSequences() );
2007 uno::Sequence
< uno::Reference
< chart2::data::XLabeledDataSequence
> > aNewSequences(
2008 xDataSource
->getDataSequences());
2012 OUString aOldValues
;
2013 OUString aNewValues
;
2016 for( sal_Int32 nNewIndex
= 0; nNewIndex
< aNewSequences
.getLength(); nNewIndex
++ )
2018 uno::Reference
< chart2::data::XLabeledDataSequence
> xNew( aNewSequences
[nNewIndex
] );
2019 for( sal_Int32 nOldIndex
= 0; nOldIndex
< aOldSequences
.getLength(); nOldIndex
++ )
2021 uno::Reference
< chart2::data::XLabeledDataSequence
> xOld( aOldSequences
[nOldIndex
] );
2023 if( xOld
.is() && xNew
.is() )
2025 aOldLabel
= aNewLabel
= aOldValues
= aNewValues
= aEmpty
;
2026 if( xOld
.is() && xOld
->getLabel().is() )
2027 aOldLabel
= xOld
->getLabel()->getSourceRangeRepresentation();
2028 if( xNew
.is() && xNew
->getLabel().is() )
2029 aNewLabel
= xNew
->getLabel()->getSourceRangeRepresentation();
2030 if( xOld
.is() && xOld
->getValues().is() )
2031 aOldValues
= xOld
->getValues()->getSourceRangeRepresentation();
2032 if( xNew
.is() && xNew
->getValues().is() )
2033 aNewValues
= xNew
->getValues()->getSourceRangeRepresentation();
2035 if( aOldLabel
.equals(aNewLabel
)
2036 && ( aOldValues
.equals(aNewValues
) ) )
2038 if( nOldIndex
!=nNewIndex
)
2039 bDifferentIndexes
= true;
2040 aSequenceMappingVector
.push_back(nOldIndex
);
2048 if( bDifferentIndexes
&& !aSequenceMappingVector
.empty() )
2051 beans::PropertyValue( OUString("SequenceMapping"), -1,
2052 uno::makeAny( lcl_VectorToSequence(aSequenceMappingVector
) )
2053 , beans::PropertyState_DIRECT_VALUE
));
2057 return lcl_VectorToSequence( aResult
);
2060 sal_Bool SAL_CALL
ScChart2DataProvider::createDataSequenceByRangeRepresentationPossible( const OUString
& aRangeRepresentation
)
2061 throw (uno::RuntimeException
, std::exception
)
2063 SolarMutexGuard aGuard
;
2067 vector
<ScTokenRef
> aTokens
;
2068 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
2069 ScRefTokenHelper::compileRangeRepresentation(
2070 aTokens
, aRangeRepresentation
, m_pDocument
, cSep
, m_pDocument
->GetGrammar(), true);
2071 return !aTokens
.empty();
2074 uno::Reference
< chart2::data::XDataSequence
> SAL_CALL
2075 ScChart2DataProvider::createDataSequenceByRangeRepresentation(
2076 const OUString
& aRangeRepresentation
)
2077 throw (lang::IllegalArgumentException
,
2078 uno::RuntimeException
, std::exception
)
2080 SolarMutexGuard aGuard
;
2081 uno::Reference
< chart2::data::XDataSequence
> xResult
;
2083 OSL_ENSURE( m_pDocument
, "No Document -> no createDataSequenceByRangeRepresentation" );
2084 if(!m_pDocument
|| aRangeRepresentation
.isEmpty())
2087 vector
<ScTokenRef
> aRefTokens
;
2088 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
2089 ScRefTokenHelper::compileRangeRepresentation(
2090 aRefTokens
, aRangeRepresentation
, m_pDocument
, cSep
, m_pDocument
->GetGrammar(), true);
2091 if (aRefTokens
.empty())
2094 shrinkToDataRange(m_pDocument
, aRefTokens
);
2096 // ScChart2DataSequence manages the life cycle of pRefTokens.
2097 vector
<ScTokenRef
>* pRefTokens
= new vector
<ScTokenRef
>();
2098 pRefTokens
->swap(aRefTokens
);
2099 xResult
.set(new ScChart2DataSequence(m_pDocument
, this, pRefTokens
, m_bIncludeHiddenCells
));
2104 uno::Reference
< sheet::XRangeSelection
> SAL_CALL
ScChart2DataProvider::getRangeSelection()
2105 throw (uno::RuntimeException
, std::exception
)
2107 uno::Reference
< sheet::XRangeSelection
> xResult
;
2109 uno::Reference
< frame::XModel
> xModel( lcl_GetXModel( m_pDocument
));
2111 xResult
.set( xModel
->getCurrentController(), uno::UNO_QUERY
);
2116 sal_Bool SAL_CALL
ScChart2DataProvider::createDataSequenceByFormulaTokensPossible(
2117 const Sequence
<sheet::FormulaToken
>& aTokens
)
2118 throw (uno::RuntimeException
, std::exception
)
2120 if (aTokens
.getLength() <= 0)
2124 if (!ScTokenConversion::ConvertToTokenArray(*m_pDocument
, aCode
, aTokens
))
2127 sal_uInt16 n
= aCode
.GetLen();
2131 const formula::FormulaToken
* pFirst
= aCode
.First();
2132 const formula::FormulaToken
* pLast
= aCode
.GetArray()[n
-1];
2133 for (const formula::FormulaToken
* p
= aCode
.First(); p
; p
= aCode
.Next())
2135 switch (p
->GetType())
2139 switch (p
->GetOpCode())
2142 // separators are allowed.
2146 // open paran is allowed only as the first token.
2151 // close paren is allowed only as the last token.
2161 case svExternalSingleRef
:
2162 case svExternalDoubleRef
:
2172 Reference
<chart2::data::XDataSequence
> SAL_CALL
2173 ScChart2DataProvider::createDataSequenceByFormulaTokens(
2174 const Sequence
<sheet::FormulaToken
>& aTokens
)
2175 throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
)
2177 Reference
<chart2::data::XDataSequence
> xResult
;
2178 if (aTokens
.getLength() <= 0)
2182 if (!ScTokenConversion::ConvertToTokenArray(*m_pDocument
, aCode
, aTokens
))
2185 sal_uInt16 n
= aCode
.GetLen();
2189 vector
<ScTokenRef
> aRefTokens
;
2190 const formula::FormulaToken
* pFirst
= aCode
.First();
2191 const formula::FormulaToken
* pLast
= aCode
.GetArray()[n
-1];
2192 for (const formula::FormulaToken
* p
= aCode
.First(); p
; p
= aCode
.Next())
2194 switch (p
->GetType())
2198 switch (p
->GetOpCode())
2201 // separators are allowed.
2205 // open paran is allowed only as the first token.
2206 throw lang::IllegalArgumentException();
2210 // close paren is allowed only as the last token.
2211 throw lang::IllegalArgumentException();
2214 throw lang::IllegalArgumentException();
2221 case svExternalSingleRef
:
2222 case svExternalDoubleRef
:
2224 ScTokenRef
pNew(static_cast<ScToken
*>(p
->Clone()));
2225 aRefTokens
.push_back(pNew
);
2229 throw lang::IllegalArgumentException();
2233 if (aRefTokens
.empty())
2236 shrinkToDataRange(m_pDocument
, aRefTokens
);
2238 // ScChart2DataSequence manages the life cycle of pRefTokens.
2239 vector
<ScTokenRef
>* pRefTokens
= new vector
<ScTokenRef
>();
2240 pRefTokens
->swap(aRefTokens
);
2241 xResult
.set(new ScChart2DataSequence(m_pDocument
, this, pRefTokens
, m_bIncludeHiddenCells
));
2245 // XRangeXMLConversion ---------------------------------------------------
2247 OUString SAL_CALL
ScChart2DataProvider::convertRangeToXML( const OUString
& sRangeRepresentation
)
2248 throw ( uno::RuntimeException
, lang::IllegalArgumentException
, std::exception
)
2254 if (sRangeRepresentation
.isEmpty())
2255 // Empty data range is allowed.
2258 vector
<ScTokenRef
> aRefTokens
;
2259 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
2260 ScRefTokenHelper::compileRangeRepresentation(
2261 aRefTokens
, sRangeRepresentation
, m_pDocument
, cSep
, m_pDocument
->GetGrammar(), true);
2262 if (aRefTokens
.empty())
2263 throw lang::IllegalArgumentException();
2265 Tokens2RangeStringXML
converter(m_pDocument
);
2266 converter
= ::std::for_each(aRefTokens
.begin(), aRefTokens
.end(), converter
);
2267 converter
.getString(aRet
);
2272 OUString SAL_CALL
ScChart2DataProvider::convertRangeFromXML( const OUString
& sXMLRange
)
2273 throw ( uno::RuntimeException
, lang::IllegalArgumentException
, std::exception
)
2275 const sal_Unicode cSep
= ' ';
2276 const sal_Unicode cQuote
= '\'';
2280 // #i74062# When loading flat XML, this is called before the referenced sheets are in the document,
2281 // so the conversion has to take place directly with the strings, without looking up the sheets.
2283 OUStringBuffer sRet
;
2284 sal_Int32 nOffset
= 0;
2285 while( nOffset
>= 0 )
2288 ScRangeStringConverter::GetTokenByOffset( sToken
, sXMLRange
, nOffset
, cSep
, cQuote
);
2291 // convert one address (remove dots)
2293 OUString
aUIString(sToken
);
2295 sal_Int32 nIndex
= ScRangeStringConverter::IndexOf( sToken
, ':', 0, cQuote
);
2296 if ( nIndex
>= 0 && nIndex
< aUIString
.getLength() - 1 &&
2297 aUIString
[nIndex
+ 1] == '.' )
2298 aUIString
= aUIString
.replaceAt( nIndex
+ 1, 1, "" );
2300 if ( aUIString
[0] == '.' )
2301 aUIString
= aUIString
.copy( 1 );
2303 if( !sRet
.isEmpty() )
2305 sRet
.append( aUIString
);
2309 return sRet
.makeStringAndClear();
2313 ScRangeStringConverter::GetStringFromXMLRangeString(aRet
, sXMLRange
, m_pDocument
);
2317 // DataProvider XPropertySet -------------------------------------------------
2319 uno::Reference
< beans::XPropertySetInfo
> SAL_CALL
2320 ScChart2DataProvider::getPropertySetInfo() throw( uno::RuntimeException
, std::exception
)
2322 SolarMutexGuard aGuard
;
2323 static uno::Reference
<beans::XPropertySetInfo
> aRef
=
2324 new SfxItemPropertySetInfo( m_aPropSet
.getPropertyMap() );
2329 void SAL_CALL
ScChart2DataProvider::setPropertyValue(
2330 const OUString
& rPropertyName
, const uno::Any
& rValue
)
2331 throw( beans::UnknownPropertyException
,
2332 beans::PropertyVetoException
,
2333 lang::IllegalArgumentException
,
2334 lang::WrappedTargetException
, uno::RuntimeException
, std::exception
)
2336 if ( rPropertyName
== SC_UNONAME_INCLUDEHIDDENCELLS
)
2338 if ( !(rValue
>>= m_bIncludeHiddenCells
))
2339 throw lang::IllegalArgumentException();
2342 throw beans::UnknownPropertyException();
2346 uno::Any SAL_CALL
ScChart2DataProvider::getPropertyValue(
2347 const OUString
& rPropertyName
)
2348 throw( beans::UnknownPropertyException
,
2349 lang::WrappedTargetException
, uno::RuntimeException
, std::exception
)
2352 if ( rPropertyName
== SC_UNONAME_INCLUDEHIDDENCELLS
)
2353 aRet
<<= m_bIncludeHiddenCells
;
2354 else if (rPropertyName
== SC_UNONAME_USE_INTERNAL_DATA_PROVIDER
)
2356 // This is a read-only property.
2357 aRet
<<= m_pDocument
->PastingDrawFromOtherDoc();
2360 throw beans::UnknownPropertyException();
2365 void SAL_CALL
ScChart2DataProvider::addPropertyChangeListener(
2366 const OUString
& /*rPropertyName*/,
2367 const uno::Reference
< beans::XPropertyChangeListener
>& /*xListener*/)
2368 throw( beans::UnknownPropertyException
,
2369 lang::WrappedTargetException
, uno::RuntimeException
, std::exception
)
2371 OSL_FAIL( "Not yet implemented" );
2375 void SAL_CALL
ScChart2DataProvider::removePropertyChangeListener(
2376 const OUString
& /*rPropertyName*/,
2377 const uno::Reference
< beans::XPropertyChangeListener
>& /*rListener*/)
2378 throw( beans::UnknownPropertyException
,
2379 lang::WrappedTargetException
, uno::RuntimeException
, std::exception
)
2381 OSL_FAIL( "Not yet implemented" );
2385 void SAL_CALL
ScChart2DataProvider::addVetoableChangeListener(
2386 const OUString
& /*rPropertyName*/,
2387 const uno::Reference
< beans::XVetoableChangeListener
>& /*rListener*/)
2388 throw( beans::UnknownPropertyException
,
2389 lang::WrappedTargetException
, uno::RuntimeException
, std::exception
)
2391 OSL_FAIL( "Not yet implemented" );
2395 void SAL_CALL
ScChart2DataProvider::removeVetoableChangeListener(
2396 const OUString
& /*rPropertyName*/,
2397 const uno::Reference
< beans::XVetoableChangeListener
>& /*rListener*/ )
2398 throw( beans::UnknownPropertyException
,
2399 lang::WrappedTargetException
, uno::RuntimeException
, std::exception
)
2401 OSL_FAIL( "Not yet implemented" );
2404 // DataSource ================================================================
2406 ScChart2DataSource::ScChart2DataSource( ScDocument
* pDoc
)
2407 : m_pDocument( pDoc
)
2410 m_pDocument
->AddUnoObject( *this);
2414 ScChart2DataSource::~ScChart2DataSource()
2417 m_pDocument
->RemoveUnoObject( *this);
2421 void ScChart2DataSource::Notify( SfxBroadcaster
& /*rBC*/, const SfxHint
& rHint
)
2423 if ( rHint
.ISA( SfxSimpleHint
) &&
2424 ((const SfxSimpleHint
&)rHint
).GetId() == SFX_HINT_DYING
)
2431 uno::Sequence
< uno::Reference
< chart2::data::XLabeledDataSequence
> > SAL_CALL
2432 ScChart2DataSource::getDataSequences() throw ( uno::RuntimeException
, std::exception
)
2434 SolarMutexGuard aGuard
;
2436 LabeledList::const_iterator
aItr(m_aLabeledSequences
.begin());
2437 LabeledList::const_iterator
aEndItr(m_aLabeledSequences
.end());
2439 uno::Sequence
< uno::Reference
< chart2::data::XLabeledDataSequence
> > aRet(m_aLabeledSequences
.size());
2442 while (aItr
!= aEndItr
)
2452 void ScChart2DataSource::AddLabeledSequence(const uno::Reference
< chart2::data::XLabeledDataSequence
>& xNew
)
2454 m_aLabeledSequences
.push_back(xNew
);
2457 // DataSequence ==============================================================
2459 ScChart2DataSequence::Item::Item() :
2460 mfValue(0.0), mbIsValue(false)
2462 ::rtl::math::setNan(&mfValue
);
2465 ScChart2DataSequence::HiddenRangeListener::HiddenRangeListener(ScChart2DataSequence
& rParent
) :
2470 ScChart2DataSequence::HiddenRangeListener::~HiddenRangeListener()
2474 void ScChart2DataSequence::HiddenRangeListener::notify()
2476 mrParent
.setDataChangedHint(true);
2479 ScChart2DataSequence::ScChart2DataSequence( ScDocument
* pDoc
,
2480 const uno::Reference
< chart2::data::XDataProvider
>& xDP
,
2481 vector
<ScTokenRef
>* pTokens
,
2482 bool bIncludeHiddenCells
)
2483 : m_bIncludeHiddenCells( bIncludeHiddenCells
)
2485 , m_pDocument( pDoc
)
2486 , m_pTokens(pTokens
)
2487 , m_pRangeIndices(NULL
)
2488 , m_pExtRefListener(NULL
)
2489 , m_xDataProvider( xDP
)
2490 , m_aPropSet(lcl_GetDataSequencePropertyMap())
2491 , m_pHiddenListener(NULL
)
2492 , m_pValueListener( NULL
)
2493 , m_bGotDataChangedHint(false)
2494 , m_bExtDataRebuildQueued(false)
2495 , mbTimeBased(false)
2496 , mnTimeBasedStart(0)
2500 OSL_ENSURE(pTokens
, "reference token list is null");
2504 m_pDocument
->AddUnoObject( *this);
2505 m_nObjectId
= m_pDocument
->GetNewUnoId();
2507 // FIXME: real implementation of identifier and it's mapping to ranges.
2508 // Reuse ScChartListener?
2510 // BM: don't use names of named ranges but the UI range strings
2512 // rRangeList->Format( aStr, SCR_ABS_3D, m_pDocument );
2513 // m_aIdentifier = aStr;
2515 // m_aIdentifier = "ID_";
2516 // static sal_Int32 nID = 0;
2517 // m_aIdentifier += OUString::valueOf( ++nID);
2520 ScChart2DataSequence::~ScChart2DataSequence()
2524 m_pDocument
->RemoveUnoObject( *this);
2525 if (m_pHiddenListener
.get())
2527 ScChartListenerCollection
* pCLC
= m_pDocument
->GetChartListenerCollection();
2529 pCLC
->EndListeningHiddenRange(m_pHiddenListener
.get());
2531 StopListeningToAllExternalRefs();
2534 delete m_pValueListener
;
2537 void ScChart2DataSequence::RefChanged()
2539 if( m_pValueListener
&& !m_aValueListeners
.empty() )
2541 m_pValueListener
->EndListeningAll();
2545 ScChartListenerCollection
* pCLC
= NULL
;
2546 if (m_pHiddenListener
.get())
2548 pCLC
= m_pDocument
->GetChartListenerCollection();
2550 pCLC
->EndListeningHiddenRange(m_pHiddenListener
.get());
2553 vector
<ScTokenRef
>::const_iterator itr
= m_pTokens
->begin(), itrEnd
= m_pTokens
->end();
2554 for (; itr
!= itrEnd
; ++itr
)
2557 if (!ScRefTokenHelper::getRangeFromToken(aRange
, *itr
, ScAddress()))
2560 m_pDocument
->StartListeningArea(aRange
, m_pValueListener
);
2562 pCLC
->StartListeningHiddenRange(aRange
, m_pHiddenListener
.get());
2568 void ScChart2DataSequence::BuildDataCache()
2570 m_bExtDataRebuildQueued
= false;
2572 if (!m_aDataArray
.empty())
2575 if (!m_pTokens
.get())
2577 OSL_FAIL("m_pTokens == NULL! Something is wrong.");
2581 StopListeningToAllExternalRefs();
2583 ::std::list
<sal_Int32
> aHiddenValues
;
2584 sal_Int32 nDataCount
= 0;
2585 sal_Int32 nHiddenValueCount
= 0;
2587 for (vector
<ScTokenRef
>::const_iterator itr
= m_pTokens
->begin(), itrEnd
= m_pTokens
->end();
2588 itr
!= itrEnd
; ++itr
)
2590 if (ScRefTokenHelper::isExternalRef(*itr
))
2592 nDataCount
+= FillCacheFromExternalRef(*itr
);
2597 if (!ScRefTokenHelper::getRangeFromToken(aRange
, *itr
, ScAddress()))
2600 SCCOL nLastCol
= -1;
2601 SCROW nLastRow
= -1;
2602 for (SCTAB nTab
= aRange
.aStart
.Tab(); nTab
<= aRange
.aEnd
.Tab(); ++nTab
)
2604 for (SCCOL nCol
= aRange
.aStart
.Col(); nCol
<= aRange
.aEnd
.Col(); ++nCol
)
2606 for (SCROW nRow
= aRange
.aStart
.Row(); nRow
<= aRange
.aEnd
.Row(); ++nRow
)
2608 bool bColHidden
= m_pDocument
->ColHidden(nCol
, nTab
, NULL
, &nLastCol
);
2609 bool bRowHidden
= m_pDocument
->RowHidden(nRow
, nTab
, NULL
, &nLastRow
);
2611 if (bColHidden
|| bRowHidden
)
2614 ++nHiddenValueCount
;
2615 aHiddenValues
.push_back(nDataCount
-1);
2617 if( !m_bIncludeHiddenCells
)
2621 m_aDataArray
.push_back(Item());
2622 Item
& rItem
= m_aDataArray
.back();
2625 ScAddress
aAdr(nCol
, nRow
, nTab
);
2626 rItem
.maString
= m_pDocument
->GetString(aAdr
);
2628 switch (m_pDocument
->GetCellType(aAdr
))
2630 case CELLTYPE_VALUE
:
2631 rItem
.mfValue
= m_pDocument
->GetValue(aAdr
);
2632 rItem
.mbIsValue
= true;
2634 case CELLTYPE_FORMULA
:
2636 ScFormulaCell
* pFCell
= m_pDocument
->GetFormulaCell(aAdr
);
2639 sal_uInt16 nErr
= pFCell
->GetErrCode();
2643 if (pFCell
->IsValue())
2645 rItem
.mfValue
= pFCell
->GetValue();
2646 rItem
.mbIsValue
= true;
2652 case CELLTYPE_STRING
:
2662 // convert the hidden cell list to sequence.
2663 m_aHiddenValues
.realloc(nHiddenValueCount
);
2664 sal_Int32
* pArr
= m_aHiddenValues
.getArray();
2665 ::std::list
<sal_Int32
>::const_iterator itr
= aHiddenValues
.begin(), itrEnd
= aHiddenValues
.end();
2666 for (;itr
!= itrEnd
; ++itr
, ++pArr
)
2669 // Clear the data series cache when the array is re-built.
2670 m_aMixedDataCache
.realloc(0);
2673 void ScChart2DataSequence::RebuildDataCache()
2675 if (!m_bExtDataRebuildQueued
)
2677 m_aDataArray
.clear();
2678 m_pDocument
->BroadcastUno(ScHint(SC_HINT_DATACHANGED
, ScAddress()));
2679 m_bExtDataRebuildQueued
= true;
2680 m_bGotDataChangedHint
= true;
2684 sal_Int32
ScChart2DataSequence::FillCacheFromExternalRef(const ScTokenRef
& pToken
)
2686 ScExternalRefManager
* pRefMgr
= m_pDocument
->GetExternalRefManager();
2688 if (!ScRefTokenHelper::getRangeFromToken(aRange
, pToken
, ScAddress(), true))
2691 sal_uInt16 nFileId
= pToken
->GetIndex();
2692 OUString aTabName
= pToken
->GetString().getString();
2693 ScExternalRefCache::TokenArrayRef pArray
= pRefMgr
->getDoubleRefTokens(nFileId
, aTabName
, aRange
, NULL
);
2695 // no external data exists for this range.
2698 // Start listening for this external document.
2699 ExternalRefListener
* pExtRefListener
= GetExtRefListener();
2700 pRefMgr
->addLinkListener(nFileId
, pExtRefListener
);
2701 pExtRefListener
->addFileId(nFileId
);
2703 ScExternalRefCache::TableTypeRef pTable
= pRefMgr
->getCacheTable(nFileId
, aTabName
, false, NULL
);
2704 sal_Int32 nDataCount
= 0;
2705 for (FormulaToken
* p
= pArray
->First(); p
; p
= pArray
->Next())
2707 // Cached external range is always represented as a single
2708 // matrix token, although that might change in the future when
2709 // we introduce a new token type to store multi-table range
2712 if (p
->GetType() != svMatrix
)
2714 OSL_FAIL("Cached array is not a matrix token.");
2718 const ScMatrix
* pMat
= static_cast<ScToken
*>(p
)->GetMatrix();
2719 SCSIZE nCSize
, nRSize
;
2720 pMat
->GetDimensions(nCSize
, nRSize
);
2721 for (SCSIZE nC
= 0; nC
< nCSize
; ++nC
)
2723 for (SCSIZE nR
= 0; nR
< nRSize
; ++nR
)
2725 if (pMat
->IsValue(nC
, nR
) || pMat
->IsBoolean(nC
, nR
))
2727 m_aDataArray
.push_back(Item());
2728 Item
& rItem
= m_aDataArray
.back();
2731 rItem
.mbIsValue
= true;
2732 rItem
.mfValue
= pMat
->GetDouble(nC
, nR
);
2734 SvNumberFormatter
* pFormatter
= m_pDocument
->GetFormatTable();
2737 const double fVal
= rItem
.mfValue
;
2738 Color
* pColor
= NULL
;
2739 sal_uInt32 nFmt
= 0;
2742 // Get the correct format index from the cache.
2743 SCCOL nCol
= aRange
.aStart
.Col() + static_cast<SCCOL
>(nC
);
2744 SCROW nRow
= aRange
.aStart
.Row() + static_cast<SCROW
>(nR
);
2745 pTable
->getCell(nCol
, nRow
, &nFmt
);
2747 pFormatter
->GetOutputString(fVal
, nFmt
, rItem
.maString
, &pColor
);
2750 else if (pMat
->IsString(nC
, nR
))
2752 m_aDataArray
.push_back(Item());
2753 Item
& rItem
= m_aDataArray
.back();
2756 rItem
.mbIsValue
= false;
2757 rItem
.maString
= pMat
->GetString(nC
, nR
).getString();
2765 void ScChart2DataSequence::UpdateTokensFromRanges(const ScRangeList
& rRanges
)
2767 if (!m_pRangeIndices
.get())
2770 for ( size_t i
= 0, nCount
= rRanges
.size(); i
< nCount
; ++i
)
2773 const ScRange
* pRange
= rRanges
[i
];
2774 OSL_ENSURE(pRange
, "range object is NULL.");
2776 ScRefTokenHelper::getTokenFromRange(pToken
, *pRange
);
2777 sal_uInt32 nOrigPos
= (*m_pRangeIndices
)[i
];
2778 (*m_pTokens
)[nOrigPos
] = pToken
;
2783 // any change of the range address is broadcast to value (modify) listeners
2784 if ( !m_aValueListeners
.empty() )
2785 m_bGotDataChangedHint
= true;
2788 ScChart2DataSequence::ExternalRefListener
* ScChart2DataSequence::GetExtRefListener()
2790 if (!m_pExtRefListener
.get())
2791 m_pExtRefListener
.reset(new ExternalRefListener(*this, m_pDocument
));
2793 return m_pExtRefListener
.get();
2796 void ScChart2DataSequence::StopListeningToAllExternalRefs()
2798 if (!m_pExtRefListener
.get())
2801 const boost::unordered_set
<sal_uInt16
>& rFileIds
= m_pExtRefListener
->getAllFileIds();
2802 boost::unordered_set
<sal_uInt16
>::const_iterator itr
= rFileIds
.begin(), itrEnd
= rFileIds
.end();
2803 ScExternalRefManager
* pRefMgr
= m_pDocument
->GetExternalRefManager();
2804 for (; itr
!= itrEnd
; ++itr
)
2805 pRefMgr
->removeLinkListener(*itr
, m_pExtRefListener
.get());
2807 m_pExtRefListener
.reset();
2810 void ScChart2DataSequence::CopyData(const ScChart2DataSequence
& r
)
2814 OSL_FAIL("document instance is NULL!?");
2818 list
<Item
> aDataArray(r
.m_aDataArray
);
2819 m_aDataArray
.swap(aDataArray
);
2821 m_aHiddenValues
= r
.m_aHiddenValues
;
2822 m_aRole
= r
.m_aRole
;
2824 if (r
.m_pRangeIndices
.get())
2825 m_pRangeIndices
.reset(new vector
<sal_uInt32
>(*r
.m_pRangeIndices
));
2827 if (r
.m_pExtRefListener
.get())
2829 // Re-register all external files that the old instance was
2832 ScExternalRefManager
* pRefMgr
= m_pDocument
->GetExternalRefManager();
2833 m_pExtRefListener
.reset(new ExternalRefListener(*this, m_pDocument
));
2834 const boost::unordered_set
<sal_uInt16
>& rFileIds
= r
.m_pExtRefListener
->getAllFileIds();
2835 boost::unordered_set
<sal_uInt16
>::const_iterator itr
= rFileIds
.begin(), itrEnd
= rFileIds
.end();
2836 for (; itr
!= itrEnd
; ++itr
)
2838 pRefMgr
->addLinkListener(*itr
, m_pExtRefListener
.get());
2839 m_pExtRefListener
->addFileId(*itr
);
2844 void ScChart2DataSequence::Notify( SfxBroadcaster
& /*rBC*/, const SfxHint
& rHint
)
2846 if ( rHint
.ISA( SfxSimpleHint
) )
2848 sal_uLong nId
= static_cast<const SfxSimpleHint
&>(rHint
).GetId();
2849 if ( nId
==SFX_HINT_DYING
)
2853 else if ( nId
== SFX_HINT_DATACHANGED
)
2855 // delayed broadcast as in ScCellRangesBase
2857 if ( m_bGotDataChangedHint
&& m_pDocument
)
2859 m_aDataArray
.clear();
2860 lang::EventObject aEvent
;
2861 aEvent
.Source
.set((cppu::OWeakObject
*)this);
2865 for ( sal_uInt16 n
=0; n
<m_aValueListeners
.size(); n
++ )
2866 m_pDocument
->AddUnoListenerCall( m_aValueListeners
[n
], aEvent
);
2869 m_bGotDataChangedHint
= false;
2872 else if ( nId
== SC_HINT_CALCALL
)
2874 // broadcast from DoHardRecalc - set m_bGotDataChangedHint
2875 // (SFX_HINT_DATACHANGED follows separately)
2877 if ( !m_aValueListeners
.empty() )
2878 m_bGotDataChangedHint
= true;
2881 else if ( rHint
.ISA( ScUpdateRefHint
) )
2883 // Create a range list from the token list, have the range list
2884 // updated, and bring the change back to the token list.
2886 ScRangeList aRanges
;
2887 m_pRangeIndices
.reset(new vector
<sal_uInt32
>());
2888 vector
<ScTokenRef
>::const_iterator itrBeg
= m_pTokens
->begin(), itrEnd
= m_pTokens
->end();
2889 for (vector
<ScTokenRef
>::const_iterator itr
= itrBeg
;itr
!= itrEnd
; ++itr
)
2891 if (!ScRefTokenHelper::isExternalRef(*itr
))
2894 ScRefTokenHelper::getRangeFromToken(aRange
, *itr
, ScAddress());
2895 aRanges
.Append(aRange
);
2896 sal_uInt32 nPos
= distance(itrBeg
, itr
);
2897 m_pRangeIndices
->push_back(nPos
);
2901 OSL_ENSURE(m_pRangeIndices
->size() == static_cast<size_t>(aRanges
.size()),
2902 "range list and range index list have different sizes.");
2904 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2905 auto_ptr
<ScRangeList
> pUndoRanges
;
2906 SAL_WNODEPRECATED_DECLARATIONS_POP
2907 if ( m_pDocument
->HasUnoRefUndo() )
2908 pUndoRanges
.reset(new ScRangeList(aRanges
));
2910 const ScUpdateRefHint
& rRef
= (const ScUpdateRefHint
&)rHint
;
2911 bool bChanged
= aRanges
.UpdateReference(
2912 rRef
.GetMode(), m_pDocument
, rRef
.GetRange(), rRef
.GetDx(), rRef
.GetDy(), rRef
.GetDz());
2916 OSL_ENSURE(m_pRangeIndices
->size() == aRanges
.size(),
2917 "range list and range index list have different sizes after the reference update.");
2919 // Bring the change back from the range list to the token list.
2920 UpdateTokensFromRanges(aRanges
);
2922 if (pUndoRanges
.get())
2923 m_pDocument
->AddUnoRefChange(m_nObjectId
, *pUndoRanges
);
2926 else if ( rHint
.ISA( ScUnoRefUndoHint
) )
2928 const ScUnoRefUndoHint
& rUndoHint
= static_cast<const ScUnoRefUndoHint
&>(rHint
);
2932 if (rUndoHint
.GetObjectId() != m_nObjectId
)
2935 // The hint object provides the old ranges. Restore the old state
2936 // from these ranges.
2938 if (!m_pRangeIndices
.get() || m_pRangeIndices
->empty())
2940 OSL_FAIL(" faulty range indices");
2944 const ScRangeList
& rRanges
= rUndoHint
.GetRanges();
2946 size_t nCount
= rRanges
.size();
2947 if (nCount
!= m_pRangeIndices
->size())
2949 OSL_FAIL("range count and range index count differ.");
2953 UpdateTokensFromRanges(rRanges
);
2960 IMPL_LINK( ScChart2DataSequence
, ValueListenerHdl
, SfxHint
*, pHint
)
2962 if ( m_pDocument
&& pHint
&& pHint
->ISA( SfxSimpleHint
) &&
2963 ((const SfxSimpleHint
*)pHint
)->GetId() & SC_HINT_DATACHANGED
)
2965 // This may be called several times for a single change, if several formulas
2966 // in the range are notified. So only a flag is set that is checked when
2967 // SFX_HINT_DATACHANGED is received.
2969 setDataChangedHint(true);
2974 ScChart2DataSequence::ExternalRefListener::ExternalRefListener(
2975 ScChart2DataSequence
& rParent
, ScDocument
* pDoc
) :
2976 ScExternalRefManager::LinkListener(),
2982 ScChart2DataSequence::ExternalRefListener::~ExternalRefListener()
2984 if (!mpDoc
|| mpDoc
->IsInDtorClear())
2985 // The document is being destroyed. Do nothing.
2988 // Make sure to remove all pointers to this object.
2989 mpDoc
->GetExternalRefManager()->removeLinkListener(this);
2992 void ScChart2DataSequence::ExternalRefListener::notify(sal_uInt16 nFileId
, ScExternalRefManager::LinkUpdateType eType
)
2996 case ScExternalRefManager::LINK_MODIFIED
:
2998 if (maFileIds
.count(nFileId
))
2999 // We are listening to this external document.
3000 mrParent
.RebuildDataCache();
3003 case ScExternalRefManager::LINK_BROKEN
:
3004 removeFileId(nFileId
);
3009 void ScChart2DataSequence::ExternalRefListener::addFileId(sal_uInt16 nFileId
)
3011 maFileIds
.insert(nFileId
);
3014 void ScChart2DataSequence::ExternalRefListener::removeFileId(sal_uInt16 nFileId
)
3016 maFileIds
.erase(nFileId
);
3019 const boost::unordered_set
<sal_uInt16
>& ScChart2DataSequence::ExternalRefListener::getAllFileIds()
3024 uno::Sequence
< uno::Any
> SAL_CALL
ScChart2DataSequence::getData()
3025 throw (uno::RuntimeException
, std::exception
)
3027 SolarMutexGuard aGuard
;
3029 throw uno::RuntimeException();
3033 if (!m_aMixedDataCache
.getLength())
3035 // Build a cache for the 1st time...
3037 sal_Int32 nCount
= m_aDataArray
.size();
3038 m_aMixedDataCache
.realloc(nCount
);
3039 uno::Any
* pArr
= m_aMixedDataCache
.getArray();
3040 ::std::list
<Item
>::const_iterator itr
= m_aDataArray
.begin(), itrEnd
= m_aDataArray
.end();
3041 for (; itr
!= itrEnd
; ++itr
, ++pArr
)
3044 *pArr
<<= itr
->mfValue
;
3046 *pArr
<<= itr
->maString
;
3049 return m_aMixedDataCache
;
3052 // XNumericalDataSequence --------------------------------------------------
3054 uno::Sequence
< double > SAL_CALL
ScChart2DataSequence::getNumericalData()
3055 throw (uno::RuntimeException
, std::exception
)
3057 SolarMutexGuard aGuard
;
3059 throw uno::RuntimeException();
3064 ::rtl::math::setNan(&fNAN
);
3066 sal_Int32 nCount
= m_aDataArray
.size();
3067 uno::Sequence
<double> aSeq(nCount
);
3068 double* pArr
= aSeq
.getArray();
3069 ::std::list
<Item
>::const_iterator itr
= m_aDataArray
.begin(), itrEnd
= m_aDataArray
.end();
3070 for (; itr
!= itrEnd
; ++itr
, ++pArr
)
3071 *pArr
= itr
->mbIsValue
? itr
->mfValue
: fNAN
;
3076 // XTextualDataSequence --------------------------------------------------
3078 uno::Sequence
< OUString
> SAL_CALL
ScChart2DataSequence::getTextualData()
3079 throw (uno::RuntimeException
, std::exception
)
3081 SolarMutexGuard aGuard
;
3082 uno::Sequence
<OUString
> aSeq
;
3084 throw uno::RuntimeException();
3088 sal_Int32 nCount
= m_aDataArray
.size();
3091 aSeq
= uno::Sequence
<OUString
>(nCount
);
3092 OUString
* pArr
= aSeq
.getArray();
3093 ::std::list
<Item
>::const_iterator itr
= m_aDataArray
.begin(), itrEnd
= m_aDataArray
.end();
3094 for(; itr
!= itrEnd
; ++itr
, ++pArr
)
3095 *pArr
= itr
->maString
;
3097 else if ( m_pTokens
.get() && m_pTokens
->front() )
3099 if( m_pTokens
->front()->GetType() == svString
)
3101 aSeq
= uno::Sequence
<OUString
>(1);
3102 aSeq
[0] = m_pTokens
->front()->GetString().getString();
3109 OUString SAL_CALL
ScChart2DataSequence::getSourceRangeRepresentation()
3110 throw ( uno::RuntimeException
, std::exception
)
3112 SolarMutexGuard aGuard
;
3114 OSL_ENSURE( m_pDocument
, "No Document -> no SourceRangeRepresentation" );
3115 if (m_pDocument
&& m_pTokens
.get())
3116 lcl_convertTokensToString(aStr
, *m_pTokens
, m_pDocument
);
3124 * This function object is used to accumulatively count the numbers of
3125 * columns and rows in all reference tokens.
3127 class AccumulateRangeSize
: public unary_function
<ScTokenRef
, void>
3130 AccumulateRangeSize() :
3131 mnCols(0), mnRows(0) {}
3133 AccumulateRangeSize(const AccumulateRangeSize
& r
) :
3134 mnCols(r
.mnCols
), mnRows(r
.mnRows
) {}
3136 void operator() (const ScTokenRef
& pToken
)
3139 bool bExternal
= ScRefTokenHelper::isExternalRef(pToken
);
3140 ScRefTokenHelper::getRangeFromToken(r
, pToken
, ScAddress(), bExternal
);
3142 mnCols
+= r
.aEnd
.Col() - r
.aStart
.Col() + 1;
3143 mnRows
+= r
.aEnd
.Row() - r
.aStart
.Row() + 1;
3146 SCCOL
getCols() const { return mnCols
; }
3147 SCROW
getRows() const { return mnRows
; }
3154 * This function object is used to generate label strings from a list of
3157 class GenerateLabelStrings
: public unary_function
<ScTokenRef
, void>
3160 GenerateLabelStrings(sal_Int32 nSize
, chart2::data::LabelOrigin eOrigin
, bool bColumn
) :
3161 mpLabels(new Sequence
<OUString
>(nSize
)),
3164 mbColumn(bColumn
) {}
3166 GenerateLabelStrings(const GenerateLabelStrings
& r
) :
3167 mpLabels(r
.mpLabels
),
3168 meOrigin(r
.meOrigin
),
3170 mbColumn(r
.mbColumn
) {}
3172 void operator() (const ScTokenRef
& pToken
)
3174 bool bExternal
= ScRefTokenHelper::isExternalRef(pToken
);
3176 ScRefTokenHelper::getRangeFromToken(aRange
, pToken
, ScAddress(), bExternal
);
3177 OUString
* pArr
= mpLabels
->getArray();
3180 for (SCCOL nCol
= aRange
.aStart
.Col(); nCol
<= aRange
.aEnd
.Col(); ++nCol
)
3182 if ( meOrigin
!= chart2::data::LabelOrigin_LONG_SIDE
)
3184 OUString aString
= ScGlobal::GetRscString(STR_COLUMN
);
3186 ScAddress
aPos( nCol
, 0, 0 );
3187 OUString
aColStr(aPos
.Format(SCA_VALID_COL
, NULL
));
3189 pArr
[mnCount
] = aString
;
3191 else //only indices for categories
3192 pArr
[mnCount
] = OUString::number( mnCount
+1 );
3198 for (sal_Int32 nRow
= aRange
.aStart
.Row(); nRow
<= aRange
.aEnd
.Row(); ++nRow
)
3200 if (meOrigin
!= chart2::data::LabelOrigin_LONG_SIDE
)
3202 OUString aString
= ScGlobal::GetRscString(STR_ROW
) +
3203 " " + OUString::number( nRow
+1 );
3204 pArr
[mnCount
] = aString
;
3206 else //only indices for categories
3207 pArr
[mnCount
] = OUString::number( mnCount
+1 );
3213 Sequence
<OUString
> getLabels() const { return *mpLabels
; }
3216 shared_ptr
< Sequence
<OUString
> > mpLabels
;
3217 chart2::data::LabelOrigin meOrigin
;
3224 uno::Sequence
< OUString
> SAL_CALL
ScChart2DataSequence::generateLabel(chart2::data::LabelOrigin eOrigin
)
3225 throw (uno::RuntimeException
, std::exception
)
3227 SolarMutexGuard aGuard
;
3229 throw uno::RuntimeException();
3231 if (!m_pTokens
.get())
3232 return Sequence
<OUString
>();
3234 // Determine the total size of all ranges.
3235 AccumulateRangeSize func
;
3236 func
= ::std::for_each(m_pTokens
->begin(), m_pTokens
->end(), func
);
3237 SCCOL nCols
= func
.getCols();
3238 SCROW nRows
= func
.getRows();
3240 // Detemine whether this is column-major or row-major.
3241 bool bColumn
= true;
3242 if ((eOrigin
== chart2::data::LabelOrigin_SHORT_SIDE
) ||
3243 (eOrigin
== chart2::data::LabelOrigin_LONG_SIDE
))
3247 if (eOrigin
== chart2::data::LabelOrigin_SHORT_SIDE
)
3252 else if (nCols
> nRows
)
3254 if (eOrigin
== chart2::data::LabelOrigin_SHORT_SIDE
)
3260 return Sequence
<OUString
>();
3263 // Generate label strings based on the info so far.
3264 sal_Int32 nCount
= bColumn
? nCols
: nRows
;
3265 GenerateLabelStrings
genLabels(nCount
, eOrigin
, bColumn
);
3266 genLabels
= ::std::for_each(m_pTokens
->begin(), m_pTokens
->end(), genLabels
);
3267 Sequence
<OUString
> aSeq
= genLabels
.getLabels();
3274 sal_uLong
getDisplayNumberFormat(ScDocument
* pDoc
, const ScAddress
& rPos
)
3276 sal_uLong nFormat
= pDoc
->GetNumberFormat(rPos
); // original format from cell.
3282 ::sal_Int32 SAL_CALL
ScChart2DataSequence::getNumberFormatKeyByIndex( ::sal_Int32 nIndex
)
3283 throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
, std::exception
)
3285 // index -1 means a heuristic value for the entire sequence
3286 bool bGetSeriesFormat
= (nIndex
== -1);
3288 SolarMutexGuard aGuard
;
3289 if ( !m_pDocument
|| !m_pTokens
.get())
3292 // TODO: Handle external references too.
3294 sal_Int32 nCount
= 0;
3296 ScRangeList aRanges
;
3297 ScRefTokenHelper::getRangeListFromTokens(aRanges
, *m_pTokens
, ScAddress());
3298 for (size_t i
= 0, n
= aRanges
.size(); i
< n
; ++i
)
3300 ScRange
* p
= aRanges
[i
];
3301 for (SCTAB nTab
= p
->aStart
.Tab(); nTab
<= p
->aEnd
.Tab(); ++nTab
)
3303 for (SCCOL nCol
= p
->aStart
.Col(); nCol
<= p
->aEnd
.Col(); ++nCol
)
3305 if (!m_bIncludeHiddenCells
)
3307 // Skip hidden columns.
3308 SCCOL nLastCol
= -1;
3309 bool bColHidden
= m_pDocument
->ColHidden(nCol
, nTab
, NULL
, &nLastCol
);
3317 for (SCROW nRow
= p
->aStart
.Row(); nRow
<= p
->aEnd
.Row(); ++nRow
)
3319 if (!m_bIncludeHiddenCells
)
3321 // Skip hidden rows.
3322 SCROW nLastRow
= -1;
3323 bool bRowHidden
= m_pDocument
->RowHidden(nRow
, nTab
, NULL
, &nLastRow
);
3331 ScAddress
aPos(nCol
, nRow
, nTab
);
3333 if( bGetSeriesFormat
)
3335 // TODO: use nicer heuristic
3336 // return format of first non-empty cell
3337 ScRefCellValue aCell
;
3338 aCell
.assign(*m_pDocument
, aPos
);
3339 if (!aCell
.isEmpty())
3340 return static_cast<sal_Int32
>(getDisplayNumberFormat(m_pDocument
, aPos
));
3342 else if( nCount
== nIndex
)
3344 return static_cast<sal_Int32
>(getDisplayNumberFormat(m_pDocument
, aPos
));
3354 // XCloneable ================================================================
3356 uno::Reference
< util::XCloneable
> SAL_CALL
ScChart2DataSequence::createClone()
3357 throw (uno::RuntimeException
, std::exception
)
3359 SolarMutexGuard aGuard
;
3361 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3362 auto_ptr
< vector
<ScTokenRef
> > pTokensNew
;
3363 SAL_WNODEPRECATED_DECLARATIONS_POP
3364 if (m_pTokens
.get())
3367 pTokensNew
.reset(new vector
<ScTokenRef
>);
3368 pTokensNew
->reserve(m_pTokens
->size());
3369 vector
<ScTokenRef
>::const_iterator itr
= m_pTokens
->begin(), itrEnd
= m_pTokens
->end();
3370 for (; itr
!= itrEnd
; ++itr
)
3372 ScTokenRef
p(static_cast<ScToken
*>((*itr
)->Clone()));
3373 pTokensNew
->push_back(p
);
3377 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3378 auto_ptr
<ScChart2DataSequence
> p(new ScChart2DataSequence(m_pDocument
, m_xDataProvider
, pTokensNew
.release(), m_bIncludeHiddenCells
));
3379 SAL_WNODEPRECATED_DECLARATIONS_POP
3381 Reference
< util::XCloneable
> xClone(p
.release());
3386 // XModifyBroadcaster ========================================================
3388 void SAL_CALL
ScChart2DataSequence::addModifyListener( const uno::Reference
< util::XModifyListener
>& aListener
)
3389 throw (uno::RuntimeException
, std::exception
)
3391 // like ScCellRangesBase::addModifyListener
3392 SolarMutexGuard aGuard
;
3393 if (!m_pTokens
.get() || m_pTokens
->empty())
3396 ScRangeList aRanges
;
3397 ScRefTokenHelper::getRangeListFromTokens(aRanges
, *m_pTokens
, ScAddress());
3398 uno::Reference
<util::XModifyListener
> *pObj
=
3399 new uno::Reference
<util::XModifyListener
>( aListener
);
3400 m_aValueListeners
.push_back( pObj
);
3402 if ( m_aValueListeners
.size() == 1 )
3404 if (!m_pValueListener
)
3405 m_pValueListener
= new ScLinkListener( LINK( this, ScChart2DataSequence
, ValueListenerHdl
) );
3407 if (!m_pHiddenListener
.get())
3408 m_pHiddenListener
.reset(new HiddenRangeListener(*this));
3412 ScChartListenerCollection
* pCLC
= m_pDocument
->GetChartListenerCollection();
3413 vector
<ScTokenRef
>::const_iterator itr
= m_pTokens
->begin(), itrEnd
= m_pTokens
->end();
3414 for (; itr
!= itrEnd
; ++itr
)
3417 if (!ScRefTokenHelper::getRangeFromToken(aRange
, *itr
, ScAddress()))
3420 m_pDocument
->StartListeningArea( aRange
, m_pValueListener
);
3422 pCLC
->StartListeningHiddenRange(aRange
, m_pHiddenListener
.get());
3426 acquire(); // don't lose this object (one ref for all listeners)
3430 void SAL_CALL
ScChart2DataSequence::removeModifyListener( const uno::Reference
< util::XModifyListener
>& aListener
)
3431 throw (uno::RuntimeException
, std::exception
)
3433 // like ScCellRangesBase::removeModifyListener
3435 SolarMutexGuard aGuard
;
3436 if (!m_pTokens
.get() || m_pTokens
->empty())
3439 acquire(); // in case the listeners have the last ref - released below
3441 sal_uInt16 nCount
= m_aValueListeners
.size();
3442 for ( sal_uInt16 n
=nCount
; n
--; )
3444 uno::Reference
<util::XModifyListener
>& rObj
= m_aValueListeners
[n
];
3445 if ( rObj
== aListener
)
3447 m_aValueListeners
.erase( m_aValueListeners
.begin() + n
);
3449 if ( m_aValueListeners
.empty() )
3451 if (m_pValueListener
)
3452 m_pValueListener
->EndListeningAll();
3454 if (m_pHiddenListener
.get() && m_pDocument
)
3456 ScChartListenerCollection
* pCLC
= m_pDocument
->GetChartListenerCollection();
3458 pCLC
->EndListeningHiddenRange(m_pHiddenListener
.get());
3461 release(); // release the ref for the listeners
3468 release(); // might delete this object
3471 // DataSequence XPropertySet -------------------------------------------------
3473 uno::Reference
< beans::XPropertySetInfo
> SAL_CALL
3474 ScChart2DataSequence::getPropertySetInfo() throw( uno::RuntimeException
, std::exception
)
3476 SolarMutexGuard aGuard
;
3477 static uno::Reference
<beans::XPropertySetInfo
> aRef
=
3478 new SfxItemPropertySetInfo( m_aPropSet
.getPropertyMap() );
3483 void SAL_CALL
ScChart2DataSequence::setPropertyValue(
3484 const OUString
& rPropertyName
, const uno::Any
& rValue
)
3485 throw( beans::UnknownPropertyException
,
3486 beans::PropertyVetoException
,
3487 lang::IllegalArgumentException
,
3488 lang::WrappedTargetException
, uno::RuntimeException
, std::exception
)
3490 if ( rPropertyName
== SC_UNONAME_ROLE
)
3492 if ( !(rValue
>>= m_aRole
))
3493 throw lang::IllegalArgumentException();
3495 else if ( rPropertyName
== SC_UNONAME_INCLUDEHIDDENCELLS
)
3497 bool bOldValue
= m_bIncludeHiddenCells
;
3498 if ( !(rValue
>>= m_bIncludeHiddenCells
))
3499 throw lang::IllegalArgumentException();
3500 if( bOldValue
!= m_bIncludeHiddenCells
)
3501 m_aDataArray
.clear();//data array is dirty now
3503 else if( rPropertyName
== "TimeBased" )
3505 bool bTimeBased
= mbTimeBased
;
3506 rValue
>>= bTimeBased
;
3507 mbTimeBased
= bTimeBased
;
3510 throw beans::UnknownPropertyException();
3511 // TODO: support optional properties
3515 uno::Any SAL_CALL
ScChart2DataSequence::getPropertyValue(const OUString
& rPropertyName
)
3516 throw(beans::UnknownPropertyException
,
3517 lang::WrappedTargetException
,
3518 uno::RuntimeException
,
3522 if ( rPropertyName
== SC_UNONAME_ROLE
)
3524 else if ( rPropertyName
== SC_UNONAME_INCLUDEHIDDENCELLS
)
3525 aRet
<<= m_bIncludeHiddenCells
;
3526 else if ( rPropertyName
== SC_UNONAME_HIDDENVALUES
)
3528 // This property is read-only thus cannot be set externally via
3529 // setPropertyValue(...).
3531 aRet
<<= m_aHiddenValues
;
3533 else if (rPropertyName
== "TimeBased")
3535 aRet
<<= mbTimeBased
;
3538 throw beans::UnknownPropertyException();
3539 // TODO: support optional properties
3544 void SAL_CALL
ScChart2DataSequence::addPropertyChangeListener(
3545 const OUString
& /*rPropertyName*/,
3546 const uno::Reference
< beans::XPropertyChangeListener
>& /*xListener*/)
3547 throw( beans::UnknownPropertyException
,
3548 lang::WrappedTargetException
, uno::RuntimeException
, std::exception
)
3550 // FIXME: real implementation
3551 OSL_FAIL( "Not yet implemented" );
3555 void SAL_CALL
ScChart2DataSequence::removePropertyChangeListener(
3556 const OUString
& /*rPropertyName*/,
3557 const uno::Reference
< beans::XPropertyChangeListener
>& /*rListener*/)
3558 throw( beans::UnknownPropertyException
,
3559 lang::WrappedTargetException
, uno::RuntimeException
, std::exception
)
3561 // FIXME: real implementation
3562 OSL_FAIL( "Not yet implemented" );
3566 void SAL_CALL
ScChart2DataSequence::addVetoableChangeListener(
3567 const OUString
& /*rPropertyName*/,
3568 const uno::Reference
< beans::XVetoableChangeListener
>& /*rListener*/)
3569 throw( beans::UnknownPropertyException
,
3570 lang::WrappedTargetException
, uno::RuntimeException
, std::exception
)
3572 // FIXME: real implementation
3573 OSL_FAIL( "Not yet implemented" );
3577 void SAL_CALL
ScChart2DataSequence::removeVetoableChangeListener(
3578 const OUString
& /*rPropertyName*/,
3579 const uno::Reference
< beans::XVetoableChangeListener
>& /*rListener*/)
3580 throw( beans::UnknownPropertyException
,
3581 lang::WrappedTargetException
, uno::RuntimeException
, std::exception
)
3583 // FIXME: real implementation
3584 OSL_FAIL( "Not yet implemented" );
3587 void ScChart2DataSequence::setDataChangedHint(bool b
)
3589 m_bGotDataChangedHint
= b
;
3592 sal_Bool
ScChart2DataSequence::switchToNext(sal_Bool bWrap
)
3593 throw (uno::RuntimeException
, std::exception
)
3595 if(!m_pTokens
|| !mbTimeBased
)
3598 if(mnCurrentTab
>= mnTimeBasedEnd
)
3601 setToPointInTime(0);
3605 for(vector
<ScTokenRef
>::iterator itr
= m_pTokens
->begin(),
3606 itrEnd
= m_pTokens
->end(); itr
!= itrEnd
; ++itr
)
3608 if ((*itr
)->GetType() != svDoubleRef
)
3611 ScComplexRefData
& rData
= (*itr
)->GetDoubleRef();
3612 ScSingleRefData
& s
= rData
.Ref1
;
3613 ScSingleRefData
& e
= rData
.Ref2
;
3626 void ScChart2DataSequence::setRange(sal_Int32 nStart
, sal_Int32 nEnd
)
3627 throw (uno::RuntimeException
, std::exception
)
3629 mnTimeBasedStart
= nStart
;
3630 mnTimeBasedEnd
= nEnd
;
3631 mnCurrentTab
= mnTimeBasedStart
;
3634 sal_Bool
ScChart2DataSequence::setToPointInTime(sal_Int32 nPoint
)
3635 throw (uno::RuntimeException
, std::exception
)
3640 if(nPoint
> mnTimeBasedEnd
- mnTimeBasedStart
)
3643 SCTAB nTab
= mnTimeBasedStart
+ nPoint
;
3644 for(vector
<ScTokenRef
>::iterator itr
= m_pTokens
->begin(),
3645 itrEnd
= m_pTokens
->end(); itr
!= itrEnd
; ++itr
)
3647 if ((*itr
)->GetType() != svDoubleRef
)
3650 ScComplexRefData
& rData
= (*itr
)->GetDoubleRef();
3651 ScSingleRefData
& s
= rData
.Ref1
;
3652 ScSingleRefData
& e
= rData
.Ref2
;
3658 mnCurrentTab
= nTab
;
3665 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */