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 "stlalgorithm.hxx"
36 #include "tokenuno.hxx"
38 #include "cellvalue.hxx"
39 #include "tokenarray.hxx"
40 #include "scmatrix.hxx"
42 #include "formula/opcode.hxx"
43 #include "svl/sharedstring.hxx"
45 #include <sfx2/objsh.hxx>
46 #include <vcl/svapp.hxx>
48 #include <com/sun/star/beans/UnknownPropertyException.hpp>
49 #include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
50 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
51 #include <com/sun/star/table/XCellRange.hpp>
52 #include <com/sun/star/table/CellAddress.hpp>
53 #include <com/sun/star/text/XText.hpp>
54 #include <comphelper/extract.hxx>
55 #include <comphelper/processfactory.hxx>
57 #include <rtl/math.hxx>
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 { MAP_CHAR_LEN(SC_UNONAME_INCLUDEHIDDENCELLS
), 0, &getBooleanCppuType(), 0, 0 },
84 { MAP_CHAR_LEN(SC_UNONAME_USE_INTERNAL_DATA_PROVIDER
), 0, &getBooleanCppuType(), 0, 0 },
87 return aDataProviderPropertyMap_Impl
;
90 const SfxItemPropertyMapEntry
* lcl_GetDataSequencePropertyMap()
92 static const SfxItemPropertyMapEntry aDataSequencePropertyMap_Impl
[] =
94 {MAP_CHAR_LEN(SC_UNONAME_HIDDENVALUES
), 0, &getCppuType((uno::Sequence
<sal_Int32
>*)0 ), 0, 0 },
95 {MAP_CHAR_LEN(SC_UNONAME_ROLE
), 0, &getCppuType((::com::sun::star::chart2::data::DataSequenceRole
*)0), 0, 0 },
96 {MAP_CHAR_LEN(SC_UNONAME_INCLUDEHIDDENCELLS
), 0, &getBooleanCppuType(), 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(), ScDeleteObjectByPtr
<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 // ============================================================================
248 typedef std::map
<sal_uInt32
, FormulaToken
*> FormulaTokenMap
;
249 typedef std::map
<sal_uInt32
, FormulaTokenMap
*> FormulaTokenMapMap
;
251 class Chart2PositionMap
254 Chart2PositionMap(SCCOL nColCount
, SCROW nRowCount
,
255 bool bFillRowHeader
, bool bFillColumnHeader
, FormulaTokenMapMap
& rCols
,
257 ~Chart2PositionMap();
259 SCCOL
getDataColCount() const { return mnDataColCount
; }
260 SCROW
getDataRowCount() const { return mnDataRowCount
; }
262 vector
<ScTokenRef
>* getLeftUpperCornerRanges() const;
263 vector
<ScTokenRef
>* getAllColHeaderRanges() const;
264 vector
<ScTokenRef
>* getAllRowHeaderRanges() const;
266 vector
<ScTokenRef
>* getColHeaderRanges(SCCOL nChartCol
) const;
267 vector
<ScTokenRef
>* getRowHeaderRanges(SCROW nChartRow
) const;
269 vector
<ScTokenRef
>* getDataColRanges(SCCOL nCol
) const;
270 vector
<ScTokenRef
>* getDataRowRanges(SCROW nRow
) const;
273 SCCOL mnDataColCount
;
274 SCROW mnDataRowCount
;
276 TokenTable maLeftUpperCorner
; //nHeaderColCount*nHeaderRowCount
277 TokenTable maColHeaders
; //mnDataColCount*nHeaderRowCount
278 TokenTable maRowHeaders
; //nHeaderColCount*mnDataRowCount
279 TokenTable maData
;//mnDataColCount*mnDataRowCount
282 Chart2PositionMap::Chart2PositionMap(SCCOL nAllColCount
, SCROW nAllRowCount
,
283 bool bFillRowHeader
, bool bFillColumnHeader
, FormulaTokenMapMap
& rCols
, ScDocument
* pDoc
)
285 // if bFillRowHeader is true, at least the first column serves as a row header.
286 // If more than one column is pure text all the first pure text columns are used as header.
287 // Likewise, if bFillColumnHeader is true, at least the first row serves as a column header.
288 // If more than one row is pure text all the first pure text rows are used as header.
290 SCROW nHeaderRowCount
= (bFillColumnHeader
&& nAllColCount
&& nAllRowCount
) ? 1 : 0;
291 SCCOL nHeaderColCount
= (bFillRowHeader
&& nAllColCount
&& nAllRowCount
) ? 1 : 0;
293 if( nHeaderColCount
|| nHeaderRowCount
)
295 const SCCOL nInitialHeaderColCount
= nHeaderColCount
;
296 //check whether there is more than one text column or row that should be added to the headers
297 SCROW nSmallestValueRowIndex
= nAllRowCount
;
298 bool bFoundValues
= false;
299 bool bFoundAnything
= false;
300 FormulaTokenMapMap::const_iterator it1
= rCols
.begin();
301 for (SCCOL nCol
= 0; nCol
< nAllColCount
; ++nCol
)
303 if (it1
!= rCols
.end() && nCol
>=nHeaderColCount
)
305 bool bFoundValuesInRow
= false;
306 FormulaTokenMap
* pCol
= it1
->second
;
307 FormulaTokenMap::const_iterator it2
= pCol
->begin();
308 for (SCROW nRow
= 0; !bFoundValuesInRow
&& nRow
< nSmallestValueRowIndex
&& it2
!= pCol
->end(); ++nRow
)
310 FormulaToken
* pToken
= it2
->second
;
311 if (pToken
&& nRow
>=nHeaderRowCount
)
314 bool bExternal
= false;
315 StackVar eType
= pToken
->GetType();
316 if( eType
==svExternal
|| eType
==svExternalSingleRef
|| eType
==svExternalDoubleRef
|| eType
==svExternalName
)
317 bExternal
= true;//lllll todo correct?
318 ScTokenRef
pSharedToken(static_cast<ScToken
*>(pToken
->Clone()));
319 ScRefTokenHelper::getRangeFromToken(aRange
, pSharedToken
, ScAddress(), bExternal
);
320 SCCOL nCol1
=0, nCol2
=0;
321 SCROW nRow1
=0, nRow2
=0;
322 SCTAB nTab1
=0, nTab2
=0;
323 aRange
.GetVars( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
324 if (pDoc
&& pDoc
->HasValueData( nCol1
, nRow1
, nTab1
))
326 bFoundValuesInRow
= bFoundValues
= bFoundAnything
= true;
327 nSmallestValueRowIndex
= std::min( nSmallestValueRowIndex
, nRow
);
329 if( !bFoundAnything
)
331 if (pDoc
&& pDoc
->HasData( nCol1
, nRow1
, nTab1
) )
332 bFoundAnything
= true;
337 if(!bFoundValues
&& nHeaderColCount
>0)
344 if(nHeaderRowCount
>0)
347 nHeaderRowCount
= nSmallestValueRowIndex
;
348 else if( nAllRowCount
>1 )
349 nHeaderRowCount
= nAllRowCount
-1;
352 else //if the cells are completely empty, just use single header rows and columns
353 nHeaderColCount
= nInitialHeaderColCount
;
356 mnDataColCount
= nAllColCount
- nHeaderColCount
;
357 mnDataRowCount
= nAllRowCount
- nHeaderRowCount
;
359 maLeftUpperCorner
.init(nHeaderColCount
,nHeaderRowCount
);
360 maColHeaders
.init(mnDataColCount
,nHeaderRowCount
);
361 maRowHeaders
.init(nHeaderColCount
,mnDataRowCount
);
362 maData
.init(mnDataColCount
,mnDataRowCount
);
364 FormulaTokenMapMap::const_iterator it1
= rCols
.begin();
365 for (SCCOL nCol
= 0; nCol
< nAllColCount
; ++nCol
)
367 if (it1
!= rCols
.end())
369 FormulaTokenMap
* pCol
= it1
->second
;
370 FormulaTokenMap::const_iterator it2
= pCol
->begin();
371 for (SCROW nRow
= 0; nRow
< nAllRowCount
; ++nRow
)
373 FormulaToken
* pToken
= NULL
;
374 if (it2
!= pCol
->end())
376 pToken
= it2
->second
;
380 if( nCol
< nHeaderColCount
)
382 if( nRow
< nHeaderRowCount
)
383 maLeftUpperCorner
.push_back(pToken
);
385 maRowHeaders
.push_back(pToken
);
387 else if( nRow
< nHeaderRowCount
)
388 maColHeaders
.push_back(pToken
);
390 maData
.push_back(pToken
);
397 Chart2PositionMap::~Chart2PositionMap()
399 maLeftUpperCorner
.clear();
400 maColHeaders
.clear();
401 maRowHeaders
.clear();
405 vector
<ScTokenRef
>* Chart2PositionMap::getLeftUpperCornerRanges() const
407 return maLeftUpperCorner
.getAllRanges();
409 vector
<ScTokenRef
>* Chart2PositionMap::getAllColHeaderRanges() const
411 return maColHeaders
.getAllRanges();
413 vector
<ScTokenRef
>* Chart2PositionMap::getAllRowHeaderRanges() const
415 return maRowHeaders
.getAllRanges();
417 vector
<ScTokenRef
>* Chart2PositionMap::getColHeaderRanges(SCCOL nCol
) const
419 return maColHeaders
.getColRanges( nCol
);
421 vector
<ScTokenRef
>* Chart2PositionMap::getRowHeaderRanges(SCROW nRow
) const
423 return maRowHeaders
.getRowRanges( nRow
);
426 vector
<ScTokenRef
>* Chart2PositionMap::getDataColRanges(SCCOL nCol
) const
428 return maData
.getColRanges( nCol
);
431 vector
<ScTokenRef
>* Chart2PositionMap::getDataRowRanges(SCROW nRow
) const
433 return maData
.getRowRanges( nRow
);
436 // ----------------------------------------------------------------------------
439 * Designed to be a drop-in replacement for ScChartPositioner, in order to
440 * handle external references.
442 class Chart2Positioner
: boost::noncopyable
454 Chart2Positioner(ScDocument
* pDoc
, const vector
<ScTokenRef
>& rRefTokens
) :
455 mrRefTokens(rRefTokens
),
461 mbDummyUpperLeft(false)
469 void setHeaders(bool bColHeaders
, bool bRowHeaders
)
471 mbColHeaders
= bColHeaders
;
472 mbRowHeaders
= bRowHeaders
;
475 Chart2PositionMap
* getPositionMap()
478 return mpPositionMap
.get();
482 void invalidateGlue();
484 void calcGlueState(SCCOL nCols
, SCROW nRows
);
485 void createPositionMap();
488 const vector
<ScTokenRef
>& mrRefTokens
;
489 boost::scoped_ptr
<Chart2PositionMap
> mpPositionMap
;
496 bool mbDummyUpperLeft
:1;
499 void Chart2Positioner::invalidateGlue()
501 meGlue
= GLUETYPE_NA
;
502 mpPositionMap
.reset(NULL
);
505 void Chart2Positioner::glueState()
507 if (meGlue
!= GLUETYPE_NA
)
510 mbDummyUpperLeft
= false;
511 if (mrRefTokens
.size() <= 1)
513 // Source data consists of only one data range.
514 const ScTokenRef
& p
= mrRefTokens
.front();
515 ScComplexRefData aData
;
516 if (ScRefTokenHelper::getDoubleRefDataFromToken(aData
, p
))
518 if (aData
.Ref1
.Tab() == aData
.Ref2
.Tab())
519 meGlue
= GLUETYPE_NONE
;
521 meGlue
= GLUETYPE_COLS
;
522 mnStartCol
= aData
.Ref1
.Col();
523 mnStartRow
= aData
.Ref1
.Row();
534 ScComplexRefData aData
;
535 ScRefTokenHelper::getDoubleRefDataFromToken(aData
, mrRefTokens
.front());
536 mnStartCol
= aData
.Ref1
.Col();
537 mnStartRow
= aData
.Ref1
.Row();
541 for (vector
<ScTokenRef
>::const_iterator itr
= mrRefTokens
.begin(), itrEnd
= mrRefTokens
.end()
542 ; itr
!= itrEnd
; ++itr
)
544 ScRefTokenHelper::getDoubleRefDataFromToken(aData
, *itr
);
545 SCCOLROW n1
= aData
.Ref1
.Col();
546 SCCOLROW n2
= aData
.Ref2
.Col();
552 mnStartCol
= static_cast<SCCOL
>(n1
);
554 nEndCol
= static_cast<SCCOL
>(n2
);
556 n1
= aData
.Ref1
.Row();
557 n2
= aData
.Ref2
.Row();
564 mnStartRow
= static_cast<SCROW
>(n1
);
566 nEndRow
= static_cast<SCROW
>(n2
);
569 if (mnStartCol
== nEndCol
)
571 // All source data is in a single column.
572 meGlue
= GLUETYPE_ROWS
;
576 if (mnStartRow
== nEndRow
)
578 // All source data is in a single row.
579 meGlue
= GLUETYPE_COLS
;
584 SCCOL nC
= nEndCol
- mnStartCol
+ 1;
587 SCROW nR
= nEndRow
- mnStartRow
+ 1;
589 // #i103540# prevent invalid vector size
590 if ((nC
<= 0) || (nR
<= 0))
598 calcGlueState(nC
, nR
);
601 enum State
{ Hole
= 0, Occupied
= 1, Free
= 2, Glue
= 3 };
603 void Chart2Positioner::calcGlueState(SCCOL nColSize
, SCROW nRowSize
)
605 // TODO: This code can use some space optimization. Using an array to
606 // store individual cell's states is terribly inefficient esp for large
607 // data ranges; let's use flat_segment_tree to reduce memory usage here.
609 sal_uInt32 nCR
= static_cast<sal_uInt32
>(nColSize
*nRowSize
);
611 vector
<State
> aCellStates(nCR
, Hole
);
613 // Mark all referenced cells "occupied".
614 for (vector
<ScTokenRef
>::const_iterator itr
= mrRefTokens
.begin(), itrEnd
= mrRefTokens
.end();
615 itr
!= itrEnd
; ++itr
)
617 ScComplexRefData aData
;
618 ScRefTokenHelper::getDoubleRefDataFromToken(aData
, *itr
);
619 SCCOL nCol1
= aData
.Ref1
.Col() - mnStartCol
;
620 SCCOL nCol2
= aData
.Ref2
.Col() - mnStartCol
;
621 SCROW nRow1
= aData
.Ref1
.Row() - mnStartRow
;
622 SCROW nRow2
= aData
.Ref2
.Row() - mnStartRow
;
623 for (SCCOL nCol
= nCol1
; nCol
<= nCol2
; ++nCol
)
624 for (SCROW nRow
= nRow1
; nRow
<= nRow2
; ++nRow
)
626 size_t i
= nCol
*nRowSize
+ nRow
;
627 aCellStates
[i
] = Occupied
;
631 // If at least one cell in either the first column or first row is empty,
632 // we don't glue at all unless the whole column or row is empty; we expect
633 // all cells in the first column / row to be fully populated. If we have
634 // empty column or row, then we do glue by the column or row,
638 bool bGlueCols
= false;
639 for (SCCOL nCol
= 0; bGlue
&& nCol
< nColSize
; ++nCol
)
641 for (SCROW nRow
= 0; bGlue
&& nRow
< nRowSize
; ++nRow
)
643 size_t i
= nCol
*nRowSize
+ nRow
;
644 if (aCellStates
[i
] == Occupied
)
646 if (nCol
== 0 || nRow
== 0)
652 aCellStates
[i
] = Free
;
654 size_t nLast
= (nCol
+1)*nRowSize
- 1; // index for the last cell in the column.
655 if (bGlue
&& aCellStates
[nLast
] == Free
)
657 // Whole column is empty.
658 aCellStates
[nLast
] = Glue
;
663 bool bGlueRows
= false;
664 for (SCROW nRow
= 0; bGlue
&& nRow
< nRowSize
; ++nRow
)
667 for (SCCOL nCol
= 0; bGlue
&& nCol
< nColSize
; ++nCol
, i
+= nRowSize
)
669 if (aCellStates
[i
] == Occupied
)
671 if (nCol
== 0 || nRow
== 0)
677 aCellStates
[i
] = Free
;
679 i
= (nColSize
-1)*nRowSize
+ nRow
; // index for the row position in the last column.
680 if (bGlue
&& aCellStates
[i
] == Free
)
682 // Whole row is empty.
683 aCellStates
[i
] = Glue
;
689 for (sal_uInt32 n
= 1; bGlue
&& n
< nCR
; ++n
, ++i
)
690 if (aCellStates
[i
] == Hole
)
695 if (bGlueCols
&& bGlueRows
)
696 meGlue
= GLUETYPE_BOTH
;
698 meGlue
= GLUETYPE_ROWS
;
700 meGlue
= GLUETYPE_COLS
;
701 if (aCellStates
.front() != Occupied
)
702 mbDummyUpperLeft
= true;
705 meGlue
= GLUETYPE_NONE
;
708 void Chart2Positioner::createPositionMap()
710 if (meGlue
== GLUETYPE_NA
&& mpPositionMap
.get())
711 mpPositionMap
.reset(NULL
);
713 if (mpPositionMap
.get())
718 bool bNoGlue
= (meGlue
== GLUETYPE_NONE
);
719 SAL_WNODEPRECATED_DECLARATIONS_PUSH
720 auto_ptr
<FormulaTokenMapMap
> pCols(new FormulaTokenMapMap
);
721 SAL_WNODEPRECATED_DECLARATIONS_POP
722 FormulaTokenMap
* pCol
= NULL
;
723 SCROW nNoGlueRow
= 0;
724 for (vector
<ScTokenRef
>::const_iterator itr
= mrRefTokens
.begin(), itrEnd
= mrRefTokens
.end();
725 itr
!= itrEnd
; ++itr
)
727 const ScTokenRef
& pToken
= *itr
;
729 bool bExternal
= ScRefTokenHelper::isExternalRef(pToken
);
730 sal_uInt16 nFileId
= bExternal
? pToken
->GetIndex() : 0;
731 svl::SharedString aTabName
= svl::SharedString::getEmptyString();
733 aTabName
= pToken
->GetString();
735 ScComplexRefData aData
;
736 if( !ScRefTokenHelper::getDoubleRefDataFromToken(aData
, *itr
) )
738 const ScSingleRefData
& s
= aData
.Ref1
;
739 const ScSingleRefData
& e
= aData
.Ref2
;
740 SCCOL nCol1
= s
.Col(), nCol2
= e
.Col();
741 SCROW nRow1
= s
.Row(), nRow2
= e
.Row();
742 SCTAB nTab1
= s
.Tab(), nTab2
= e
.Tab();
744 for (SCTAB nTab
= nTab1
; nTab
<= nTab2
; ++nTab
)
746 // columns on secondary sheets are appended; we treat them as if
747 // all columns are on the same sheet. TODO: We can't assume that
748 // the column range is 16-bit; remove that restriction.
749 sal_uInt32 nInsCol
= (static_cast<sal_uInt32
>(nTab
) << 16) |
750 (bNoGlue
? 0 : static_cast<sal_uInt32
>(nCol1
));
752 for (SCCOL nCol
= nCol1
; nCol
<= nCol2
; ++nCol
, ++nInsCol
)
754 FormulaTokenMapMap::const_iterator it
= pCols
->find(nInsCol
);
755 if (it
== pCols
->end())
757 pCol
= new FormulaTokenMap
;
758 (*pCols
)[ nInsCol
] = pCol
;
763 sal_uInt32 nInsRow
= static_cast<sal_uInt32
>(bNoGlue
? nNoGlueRow
: nRow1
);
764 for (SCROW nRow
= nRow1
; nRow
<= nRow2
; ++nRow
, ++nInsRow
)
766 ScSingleRefData aCellData
;
767 aCellData
.InitFlags();
768 aCellData
.SetFlag3D(true);
769 aCellData
.SetColRel(false);
770 aCellData
.SetRowRel(false);
771 aCellData
.SetTabRel(false);
772 aCellData
.SetAbsCol(nCol
);
773 aCellData
.SetAbsRow(nRow
);
774 aCellData
.SetAbsTab(nTab
);
776 if (pCol
->find(nInsRow
) == pCol
->end())
779 (*pCol
)[ nInsRow
] = new ScExternalSingleRefToken(nFileId
, aTabName
, aCellData
);
781 (*pCol
)[ nInsRow
] = new ScSingleRefToken(aCellData
);
786 nNoGlueRow
+= nRow2
- nRow1
+ 1;
789 bool bFillRowHeader
= mbRowHeaders
;
790 bool bFillColumnHeader
= mbColHeaders
;
792 SCSIZE nAllColCount
= static_cast<SCSIZE
>(pCols
->size());
793 SCSIZE nAllRowCount
= 0;
796 pCol
= pCols
->begin()->second
;
797 if (mbDummyUpperLeft
)
798 if (pCol
->find(0) == pCol
->end())
799 (*pCol
)[ 0 ] = NULL
; // Dummy fuer Beschriftung
800 nAllRowCount
= static_cast<SCSIZE
>(pCol
->size());
803 if( nAllColCount
!=0 && nAllRowCount
!=0 )
807 FormulaTokenMap
* pFirstCol
= pCols
->begin()->second
;
808 for (FormulaTokenMap::const_iterator it1
= pFirstCol
->begin(); it1
!= pFirstCol
->end(); ++it1
)
810 sal_uInt32 nKey
= it1
->first
;
811 for (FormulaTokenMapMap::const_iterator it2
= pCols
->begin(); it2
!= pCols
->end(); ++it2
)
814 if (pCol
->find(nKey
) == pCol
->end())
815 (*pCol
)[ nKey
] = NULL
;
821 new Chart2PositionMap(
822 static_cast<SCCOL
>(nAllColCount
), static_cast<SCROW
>(nAllRowCount
),
823 bFillRowHeader
, bFillColumnHeader
, *pCols
, mpDoc
));
825 // Destroy all column instances.
826 for (FormulaTokenMapMap::const_iterator it
= pCols
->begin(); it
!= pCols
->end(); ++it
)
833 // ============================================================================
836 * Function object to create a range string from a token list.
838 class Tokens2RangeString
: public unary_function
<ScTokenRef
, void>
841 Tokens2RangeString(ScDocument
* pDoc
, FormulaGrammar::Grammar eGram
, sal_Unicode cRangeSep
) :
842 mpRangeStr(new OUStringBuffer
),
845 mcRangeSep(cRangeSep
),
850 Tokens2RangeString(const Tokens2RangeString
& r
) :
851 mpRangeStr(r
.mpRangeStr
),
853 meGrammar(r
.meGrammar
),
854 mcRangeSep(r
.mcRangeSep
),
859 void operator() (const ScTokenRef
& rToken
)
861 ScCompiler
aCompiler(mpDoc
, ScAddress(0,0,0));
862 aCompiler
.SetGrammar(meGrammar
);
864 aCompiler
.CreateStringFromToken(aStr
, rToken
.get());
868 mpRangeStr
->append(mcRangeSep
);
869 mpRangeStr
->append(aStr
);
872 void getString(OUString
& rStr
)
874 rStr
= mpRangeStr
->makeStringAndClear();
878 shared_ptr
<OUStringBuffer
> mpRangeStr
;
880 FormulaGrammar::Grammar meGrammar
;
881 sal_Unicode mcRangeSep
;
886 * Function object to convert a list of tokens into a string form suitable
887 * for ODF export. In ODF, a range is expressed as
889 * (start cell address):(end cell address)
891 * and each address doesn't include any '$' symbols.
893 class Tokens2RangeStringXML
: public unary_function
<ScTokenRef
, void>
896 Tokens2RangeStringXML(ScDocument
* pDoc
) :
897 mpRangeStr(new OUStringBuffer
),
905 Tokens2RangeStringXML(const Tokens2RangeStringXML
& r
) :
906 mpRangeStr(r
.mpRangeStr
),
908 mcRangeSep(r
.mcRangeSep
),
909 mcAddrSep(r
.mcAddrSep
),
914 void operator() (const ScTokenRef
& rToken
)
919 mpRangeStr
->append(mcRangeSep
);
921 ScTokenRef aStart
, aEnd
;
922 bool bValidToken
= splitRangeToken(rToken
, aStart
, aEnd
);
923 OSL_ENSURE(bValidToken
, "invalid token");
926 ScCompiler
aCompiler(mpDoc
, ScAddress(0,0,0));
927 aCompiler
.SetGrammar(FormulaGrammar::GRAM_ENGLISH
);
930 aCompiler
.CreateStringFromToken(aStr
, aStart
.get());
931 mpRangeStr
->append(aStr
);
933 mpRangeStr
->append(mcAddrSep
);
936 aCompiler
.CreateStringFromToken(aStr
, aEnd
.get());
937 mpRangeStr
->append(aStr
);
941 void getString(OUString
& rStr
)
943 rStr
= mpRangeStr
->makeStringAndClear();
947 bool splitRangeToken(const ScTokenRef
& pToken
, ScTokenRef
& rStart
, ScTokenRef
& rEnd
) const
949 ScComplexRefData aData
;
950 bool bIsRefToken
= ScRefTokenHelper::getDoubleRefDataFromToken(aData
, pToken
);
951 OSL_ENSURE(bIsRefToken
, "invalid token");
954 bool bExternal
= ScRefTokenHelper::isExternalRef(pToken
);
955 sal_uInt16 nFileId
= bExternal
? pToken
->GetIndex() : 0;
956 svl::SharedString aTabName
= svl::SharedString::getEmptyString();
958 aTabName
= pToken
->GetString();
960 // In saving to XML, we don't prepend address with '$'.
961 setRelative(aData
.Ref1
);
962 setRelative(aData
.Ref2
);
964 // In XML, the range must explicitly specify sheet name.
965 aData
.Ref1
.SetFlag3D(true);
966 aData
.Ref2
.SetFlag3D(true);
969 rStart
.reset(new ScExternalSingleRefToken(nFileId
, aTabName
, aData
.Ref1
));
971 rStart
.reset(new ScSingleRefToken(aData
.Ref1
));
974 rEnd
.reset(new ScExternalSingleRefToken(nFileId
, aTabName
, aData
.Ref2
));
976 rEnd
.reset(new ScSingleRefToken(aData
.Ref2
));
980 void setRelative(ScSingleRefData
& rData
) const
982 rData
.SetColRel(true);
983 rData
.SetRowRel(true);
984 rData
.SetTabRel(true);
988 shared_ptr
<OUStringBuffer
> mpRangeStr
;
990 sal_Unicode mcRangeSep
;
991 sal_Unicode mcAddrSep
;
995 void lcl_convertTokensToString(OUString
& rStr
, const vector
<ScTokenRef
>& rTokens
, ScDocument
* pDoc
)
997 const sal_Unicode cRangeSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
998 FormulaGrammar::Grammar eGrammar
= pDoc
->GetGrammar();
999 Tokens2RangeString
func(pDoc
, eGrammar
, cRangeSep
);
1000 func
= ::std::for_each(rTokens
.begin(), rTokens
.end(), func
);
1001 func
.getString(rStr
);
1004 } // anonymous namespace
1006 // DataProvider ==============================================================
1008 ScChart2DataProvider::ScChart2DataProvider( ScDocument
* pDoc
)
1009 : m_pDocument( pDoc
)
1010 , m_aPropSet(lcl_GetDataProviderPropertyMap())
1011 , m_bIncludeHiddenCells( sal_True
)
1014 m_pDocument
->AddUnoObject( *this);
1017 ScChart2DataProvider::~ScChart2DataProvider()
1020 m_pDocument
->RemoveUnoObject( *this);
1024 void ScChart2DataProvider::Notify( SfxBroadcaster
& /*rBC*/, const SfxHint
& rHint
)
1026 if ( rHint
.ISA( SfxSimpleHint
) &&
1027 ((const SfxSimpleHint
&)rHint
).GetId() == SFX_HINT_DYING
)
1033 ::sal_Bool SAL_CALL
ScChart2DataProvider::createDataSourcePossible( const uno::Sequence
< beans::PropertyValue
>& aArguments
)
1034 throw (uno::RuntimeException
)
1036 SolarMutexGuard aGuard
;
1040 OUString aRangeRepresentation
;
1041 for(sal_Int32 i
= 0; i
< aArguments
.getLength(); ++i
)
1043 if ( aArguments
[i
].Name
== "CellRangeRepresentation" )
1045 aArguments
[i
].Value
>>= aRangeRepresentation
;
1049 vector
<ScTokenRef
> aTokens
;
1050 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
1051 ScRefTokenHelper::compileRangeRepresentation(
1052 aTokens
, aRangeRepresentation
, m_pDocument
, cSep
, m_pDocument
->GetGrammar(), true);
1053 return !aTokens
.empty();
1059 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1060 Reference
< chart2::data::XLabeledDataSequence
> lcl_createLabeledDataSequenceFromTokens(
1061 auto_ptr
< vector
< ScTokenRef
> > pValueTokens
, auto_ptr
< vector
< ScTokenRef
> > pLabelTokens
,
1062 ScDocument
* pDoc
, const Reference
< chart2::data::XDataProvider
>& xDP
, bool bIncludeHiddenCells
)
1064 Reference
< chart2::data::XLabeledDataSequence
> xResult
;
1065 bool bHasValues
= pValueTokens
.get() && !pValueTokens
->empty();
1066 bool bHasLabel
= pLabelTokens
.get() && !pLabelTokens
->empty();
1067 if( bHasValues
|| bHasLabel
)
1071 Reference
< uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
1072 if ( xContext
.is() )
1074 xResult
.set( chart2::data::LabeledDataSequence::create(xContext
), uno::UNO_QUERY_THROW
);
1078 Reference
< chart2::data::XDataSequence
> xSeq( new ScChart2DataSequence( pDoc
, xDP
, pValueTokens
.release(), bIncludeHiddenCells
) );
1079 xResult
->setValues( xSeq
);
1083 Reference
< chart2::data::XDataSequence
> xLabelSeq( new ScChart2DataSequence( pDoc
, xDP
, pLabelTokens
.release(), bIncludeHiddenCells
) );
1084 xResult
->setLabel( xLabelSeq
);
1087 catch( const uno::Exception
& )
1093 SAL_WNODEPRECATED_DECLARATIONS_POP
1095 //----------------------------------------------------
1097 * Check the current list of reference tokens, and add the upper left
1098 * corner of the minimum range that encloses all ranges if certain
1099 * conditions are met.
1101 * @param rRefTokens list of reference tokens
1103 * @return true if the corner was added, false otherwise.
1105 bool lcl_addUpperLeftCornerIfMissing(vector
<ScTokenRef
>& rRefTokens
,
1106 SCROW nCornerRowCount
=1, SCCOL nCornerColumnCount
=1)
1111 if (rRefTokens
.empty())
1114 SCCOL nMinCol
= MAXCOLCOUNT
;
1115 SCROW nMinRow
= MAXROWCOUNT
;
1120 sal_uInt16 nFileId
= 0;
1121 svl::SharedString aExtTabName
;
1122 bool bExternal
= false;
1124 vector
<ScTokenRef
>::const_iterator itr
= rRefTokens
.begin(), itrEnd
= rRefTokens
.end();
1126 // Get the first ref token.
1127 ScTokenRef pToken
= *itr
;
1128 switch (pToken
->GetType())
1132 const ScSingleRefData
& rData
= pToken
->GetSingleRef();
1133 nMinCol
= rData
.Col();
1134 nMinRow
= rData
.Row();
1135 nMaxCol
= rData
.Col();
1136 nMaxRow
= rData
.Row();
1142 const ScComplexRefData
& rData
= pToken
->GetDoubleRef();
1143 nMinCol
= min(rData
.Ref1
.Col(), rData
.Ref2
.Col());
1144 nMinRow
= min(rData
.Ref1
.Row(), rData
.Ref2
.Row());
1145 nMaxCol
= max(rData
.Ref1
.Col(), rData
.Ref2
.Col());
1146 nMaxRow
= max(rData
.Ref1
.Row(), rData
.Ref2
.Row());
1147 nTab
= rData
.Ref1
.Tab();
1150 case svExternalSingleRef
:
1152 const ScSingleRefData
& rData
= pToken
->GetSingleRef();
1153 nMinCol
= rData
.Col();
1154 nMinRow
= rData
.Row();
1155 nMaxCol
= rData
.Col();
1156 nMaxRow
= rData
.Row();
1158 nFileId
= pToken
->GetIndex();
1159 aExtTabName
= pToken
->GetString();
1163 case svExternalDoubleRef
:
1165 const ScComplexRefData
& rData
= pToken
->GetDoubleRef();
1166 nMinCol
= min(rData
.Ref1
.Col(), rData
.Ref2
.Col());
1167 nMinRow
= min(rData
.Ref1
.Row(), rData
.Ref2
.Row());
1168 nMaxCol
= max(rData
.Ref1
.Col(), rData
.Ref2
.Col());
1169 nMaxRow
= max(rData
.Ref1
.Row(), rData
.Ref2
.Row());
1170 nTab
= rData
.Ref1
.Tab();
1171 nFileId
= pToken
->GetIndex();
1172 aExtTabName
= pToken
->GetString();
1180 // Determine the minimum range enclosing all data ranges. Also make sure
1181 // that they are all on the same table.
1183 for (++itr
; itr
!= itrEnd
; ++itr
)
1186 switch (pToken
->GetType())
1190 const ScSingleRefData
& rData
= pToken
->GetSingleRef();
1192 nMinCol
= min(nMinCol
, rData
.Col());
1193 nMinRow
= min(nMinRow
, rData
.Row());
1194 nMaxCol
= max(nMaxCol
, rData
.Col());
1195 nMaxRow
= max(nMaxRow
, rData
.Row());
1196 if (nTab
!= rData
.Tab() || bExternal
)
1202 const ScComplexRefData
& rData
= pToken
->GetDoubleRef();
1204 nMinCol
= min(nMinCol
, rData
.Ref1
.Col());
1205 nMinCol
= min(nMinCol
, rData
.Ref2
.Col());
1206 nMinRow
= min(nMinRow
, rData
.Ref1
.Row());
1207 nMinRow
= min(nMinRow
, rData
.Ref2
.Row());
1209 nMaxCol
= max(nMaxCol
, rData
.Ref1
.Col());
1210 nMaxCol
= max(nMaxCol
, rData
.Ref2
.Col());
1211 nMaxRow
= max(nMaxRow
, rData
.Ref1
.Row());
1212 nMaxRow
= max(nMaxRow
, rData
.Ref2
.Row());
1214 if (nTab
!= rData
.Ref1
.Tab() || bExternal
)
1218 case svExternalSingleRef
:
1223 if (nFileId
!= pToken
->GetIndex() || aExtTabName
!= pToken
->GetString())
1226 const ScSingleRefData
& rData
= pToken
->GetSingleRef();
1228 nMinCol
= min(nMinCol
, rData
.Col());
1229 nMinRow
= min(nMinRow
, rData
.Row());
1230 nMaxCol
= max(nMaxCol
, rData
.Col());
1231 nMaxRow
= max(nMaxRow
, rData
.Row());
1234 case svExternalDoubleRef
:
1239 if (nFileId
!= pToken
->GetIndex() || aExtTabName
!= pToken
->GetString())
1242 const ScComplexRefData
& rData
= pToken
->GetDoubleRef();
1244 nMinCol
= min(nMinCol
, rData
.Ref1
.Col());
1245 nMinCol
= min(nMinCol
, rData
.Ref2
.Col());
1246 nMinRow
= min(nMinRow
, rData
.Ref1
.Row());
1247 nMinRow
= min(nMinRow
, rData
.Ref2
.Row());
1249 nMaxCol
= max(nMaxCol
, rData
.Ref1
.Col());
1250 nMaxCol
= max(nMaxCol
, rData
.Ref2
.Col());
1251 nMaxRow
= max(nMaxRow
, rData
.Ref1
.Row());
1252 nMaxRow
= max(nMaxRow
, rData
.Ref2
.Row());
1260 if (nMinRow
>= nMaxRow
|| nMinCol
>= nMaxCol
||
1261 nMinRow
>= MAXROWCOUNT
|| nMinCol
>= MAXCOLCOUNT
||
1262 nMaxRow
>= MAXROWCOUNT
|| nMaxCol
>= MAXCOLCOUNT
)
1264 // Invalid range. Bail out.
1268 // Check if the following conditions are met:
1270 // 1) The upper-left corner cell is not included.
1271 // 2) The three adjacent cells of that corner cell are included.
1273 bool bRight
= false, bBottom
= false, bDiagonal
= false;
1274 for (itr
= rRefTokens
.begin(); itr
!= itrEnd
; ++itr
)
1277 switch (pToken
->GetType())
1280 case svExternalSingleRef
:
1282 const ScSingleRefData
& rData
= pToken
->GetSingleRef();
1283 if (rData
.Col() == nMinCol
&& rData
.Row() == nMinRow
)
1284 // The corner cell is contained.
1287 if (rData
.Col() == nMinCol
+nCornerColumnCount
&& rData
.Row() == nMinRow
)
1290 if (rData
.Col() == nMinCol
&& rData
.Row() == nMinRow
+nCornerRowCount
)
1293 if (rData
.Col() == nMinCol
+nCornerColumnCount
&& rData
.Row() == nMinRow
+nCornerRowCount
)
1298 case svExternalDoubleRef
:
1300 const ScComplexRefData
& rData
= pToken
->GetDoubleRef();
1301 const ScSingleRefData
& r1
= rData
.Ref1
;
1302 const ScSingleRefData
& r2
= rData
.Ref2
;
1303 if (r1
.Col() <= nMinCol
&& nMinCol
<= r2
.Col() &&
1304 r1
.Row() <= nMinRow
&& nMinRow
<= r2
.Row())
1305 // The corner cell is contained.
1308 if (r1
.Col() <= nMinCol
+nCornerColumnCount
&& nMinCol
+nCornerColumnCount
<= r2
.Col() &&
1309 r1
.Row() <= nMinRow
&& nMinRow
<= r2
.Row())
1312 if (r1
.Col() <= nMinCol
&& nMinCol
<= r2
.Col() &&
1313 r1
.Row() <= nMinRow
+nCornerRowCount
&& nMinRow
+nCornerRowCount
<= r2
.Row())
1316 if (r1
.Col() <= nMinCol
+nCornerColumnCount
&& nMinCol
+nCornerColumnCount
<= r2
.Col() &&
1317 r1
.Row() <= nMinRow
+nCornerRowCount
&& nMinRow
+nCornerRowCount
<= r2
.Row())
1326 if (!bRight
|| !bBottom
|| !bDiagonal
)
1327 // Not all the adjacent cells are included. Bail out.
1330 ScSingleRefData aData
;
1332 aData
.SetFlag3D(true);
1333 aData
.SetAbsCol(nMinCol
);
1334 aData
.SetAbsRow(nMinRow
);
1335 aData
.SetAbsTab(nTab
);
1337 if( nCornerRowCount
==1 && nCornerColumnCount
==1 )
1342 new ScExternalSingleRefToken(nFileId
, aExtTabName
, aData
));
1343 ScRefTokenHelper::join(rRefTokens
, pCorner
, ScAddress());
1347 ScTokenRef
pCorner(new ScSingleRefToken(aData
));
1348 ScRefTokenHelper::join(rRefTokens
, pCorner
, ScAddress());
1353 ScSingleRefData
aDataEnd(aData
);
1354 aDataEnd
.IncCol(nCornerColumnCount
-1);
1355 aDataEnd
.IncRow(nCornerRowCount
-1);
1362 new ScExternalDoubleRefToken(nFileId
, aExtTabName
, r
));
1363 ScRefTokenHelper::join(rRefTokens
, pCorner
, ScAddress());
1367 ScTokenRef
pCorner(new ScDoubleRefToken(r
));
1368 ScRefTokenHelper::join(rRefTokens
, pCorner
, ScAddress());
1375 class ShrinkRefTokenToDataRange
: std::unary_function
<ScTokenRef
, void>
1379 ShrinkRefTokenToDataRange(ScDocument
* pDoc
) : mpDoc(pDoc
) {}
1380 void operator() (ScTokenRef
& rRef
)
1382 if (ScRefTokenHelper::isExternalRef(rRef
))
1385 // Don't assume an ScDoubleRefToken if it isn't. It can be at least an
1386 // ScSingleRefToken, then there isn't anything to shrink.
1387 if (rRef
->GetType() != svDoubleRef
)
1390 ScComplexRefData
& rData
= rRef
->GetDoubleRef();
1391 ScSingleRefData
& s
= rData
.Ref1
;
1392 ScSingleRefData
& e
= rData
.Ref2
;
1394 SCCOL nMinCol
= MAXCOL
, nMaxCol
= 0;
1395 SCROW nMinRow
= MAXROW
, nMaxRow
= 0;
1397 // Determine the smallest range that encompasses the data ranges of all sheets.
1398 SCTAB nTab1
= s
.Tab(), nTab2
= e
.Tab();
1399 for (SCTAB nTab
= nTab1
; nTab
<= nTab2
; ++nTab
)
1401 SCCOL nCol1
= 0, nCol2
= MAXCOL
;
1402 SCROW nRow1
= 0, nRow2
= MAXROW
;
1403 mpDoc
->ShrinkToDataArea(nTab
, nCol1
, nRow1
, nCol2
, nRow2
);
1404 nMinCol
= std::min(nMinCol
, nCol1
);
1405 nMinRow
= std::min(nMinRow
, nRow1
);
1406 nMaxCol
= std::max(nMaxCol
, nCol2
);
1407 nMaxRow
= std::max(nMaxRow
, nRow2
);
1410 // Shrink range to the data range if applicable.
1411 if (s
.Col() < nMinCol
)
1412 s
.SetAbsCol(nMinCol
);
1413 if (s
.Row() < nMinRow
)
1414 s
.SetAbsRow(nMinRow
);
1415 if (e
.Col() > nMaxCol
)
1416 e
.SetAbsCol(nMaxCol
);
1417 if (e
.Row() > nMaxRow
)
1418 e
.SetAbsRow(nMaxRow
);
1422 void shrinkToDataRange(ScDocument
* pDoc
, vector
<ScTokenRef
>& rRefTokens
)
1424 std::for_each(rRefTokens
.begin(), rRefTokens
.end(), ShrinkRefTokenToDataRange(pDoc
));
1429 uno::Reference
< chart2::data::XDataSource
> SAL_CALL
1430 ScChart2DataProvider::createDataSource(
1431 const uno::Sequence
< beans::PropertyValue
>& aArguments
)
1432 throw( lang::IllegalArgumentException
, uno::RuntimeException
)
1434 SolarMutexGuard aGuard
;
1435 if ( ! m_pDocument
)
1436 throw uno::RuntimeException();
1438 uno::Reference
< chart2::data::XDataSource
> xResult
;
1440 bool bCategories
= false;
1441 bool bOrientCol
= true;
1442 OUString aRangeRepresentation
;
1443 uno::Sequence
< sal_Int32
> aSequenceMapping
;
1444 for(sal_Int32 i
= 0; i
< aArguments
.getLength(); ++i
)
1446 if ( aArguments
[i
].Name
== "DataRowSource" )
1448 chart::ChartDataRowSource eSource
= chart::ChartDataRowSource_COLUMNS
;
1449 if( ! (aArguments
[i
].Value
>>= eSource
))
1451 sal_Int32
nSource(0);
1452 if( aArguments
[i
].Value
>>= nSource
)
1453 eSource
= (static_cast< chart::ChartDataRowSource
>( nSource
));
1455 bOrientCol
= (eSource
== chart::ChartDataRowSource_COLUMNS
);
1457 else if ( aArguments
[i
].Name
== "FirstCellAsLabel" )
1459 bLabel
= ::cppu::any2bool(aArguments
[i
].Value
);
1461 else if ( aArguments
[i
].Name
== "HasCategories" )
1463 bCategories
= ::cppu::any2bool(aArguments
[i
].Value
);
1465 else if ( aArguments
[i
].Name
== "CellRangeRepresentation" )
1467 aArguments
[i
].Value
>>= aRangeRepresentation
;
1469 else if ( aArguments
[i
].Name
== "SequenceMapping" )
1471 aArguments
[i
].Value
>>= aSequenceMapping
;
1475 vector
<ScTokenRef
> aRefTokens
;
1476 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
1477 ScRefTokenHelper::compileRangeRepresentation(
1478 aRefTokens
, aRangeRepresentation
, m_pDocument
, cSep
, m_pDocument
->GetGrammar(), true);
1479 if (aRefTokens
.empty())
1480 // Invalid range representation. Bail out.
1481 throw lang::IllegalArgumentException();
1483 shrinkToDataRange(m_pDocument
, aRefTokens
);
1486 lcl_addUpperLeftCornerIfMissing(aRefTokens
); //#i90669#
1488 bool bColHeaders
= (bOrientCol
? bLabel
: bCategories
);
1489 bool bRowHeaders
= (bOrientCol
? bCategories
: bLabel
);
1491 Chart2Positioner
aChPositioner(m_pDocument
, aRefTokens
);
1492 aChPositioner
.setHeaders(bColHeaders
, bRowHeaders
);
1494 const Chart2PositionMap
* pChartMap
= aChPositioner
.getPositionMap();
1496 // No chart position map instance. Bail out.
1499 ScChart2DataSource
* pDS
= NULL
;
1500 ::std::list
< Reference
< chart2::data::XLabeledDataSequence
> > aSeqs
;
1505 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1506 auto_ptr
< vector
<ScTokenRef
> > pValueTokens(NULL
);
1507 SAL_WNODEPRECATED_DECLARATIONS_POP
1509 pValueTokens
.reset(pChartMap
->getAllRowHeaderRanges());
1511 pValueTokens
.reset(pChartMap
->getAllColHeaderRanges());
1513 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1514 auto_ptr
< vector
<ScTokenRef
> > pLabelTokens(NULL
);
1515 pLabelTokens
.reset(pChartMap
->getLeftUpperCornerRanges());
1516 SAL_WNODEPRECATED_DECLARATIONS_POP
1518 Reference
< chart2::data::XLabeledDataSequence
> xCategories
= lcl_createLabeledDataSequenceFromTokens(
1519 pValueTokens
, pLabelTokens
, m_pDocument
, this, m_bIncludeHiddenCells
); //ownership of pointers is transferred!
1520 if ( xCategories
.is() )
1522 aSeqs
.push_back( xCategories
);
1526 // Fill Serieses (values and label)
1527 sal_Int32 nCount
= bOrientCol
? pChartMap
->getDataColCount() : pChartMap
->getDataRowCount();
1528 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
1530 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1531 auto_ptr
< vector
<ScTokenRef
> > pValueTokens(NULL
);
1532 auto_ptr
< vector
<ScTokenRef
> > pLabelTokens(NULL
);
1533 SAL_WNODEPRECATED_DECLARATIONS_POP
1536 pValueTokens
.reset(pChartMap
->getDataColRanges(static_cast<SCCOL
>(i
)));
1537 pLabelTokens
.reset(pChartMap
->getColHeaderRanges(static_cast<SCCOL
>(i
)));
1541 pValueTokens
.reset(pChartMap
->getDataRowRanges(static_cast<SCROW
>(i
)));
1542 pLabelTokens
.reset(pChartMap
->getRowHeaderRanges(static_cast<SCROW
>(i
)));
1544 Reference
< chart2::data::XLabeledDataSequence
> xChartSeries
= lcl_createLabeledDataSequenceFromTokens(
1545 pValueTokens
, pLabelTokens
, m_pDocument
, this, m_bIncludeHiddenCells
); //ownership of pointers is transferred!
1546 if ( xChartSeries
.is() && xChartSeries
->getValues().is() && xChartSeries
->getValues()->getData().getLength() )
1548 aSeqs
.push_back( xChartSeries
);
1552 pDS
= new ScChart2DataSource(m_pDocument
);
1553 ::std::list
< Reference
< chart2::data::XLabeledDataSequence
> >::iterator
aItr( aSeqs
.begin() );
1554 ::std::list
< Reference
< chart2::data::XLabeledDataSequence
> >::iterator
aEndItr( aSeqs
.end() );
1556 //reorder labeled sequences according to aSequenceMapping
1557 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> > aSeqVector
;
1558 while(aItr
!= aEndItr
)
1560 aSeqVector
.push_back(*aItr
);
1564 ::std::map
< sal_Int32
, Reference
< chart2::data::XLabeledDataSequence
> > aSequenceMap
;
1565 for( sal_Int32 nNewIndex
= 0; nNewIndex
< aSequenceMapping
.getLength(); nNewIndex
++ )
1567 // note: assuming that the values in the sequence mapping are always non-negative
1568 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> >::size_type
nOldIndex( static_cast< sal_uInt32
>( aSequenceMapping
[nNewIndex
] ) );
1569 if( nOldIndex
< aSeqVector
.size() )
1571 pDS
->AddLabeledSequence( aSeqVector
[nOldIndex
] );
1572 aSeqVector
[nOldIndex
] = 0;
1576 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> >::iterator
aVectorItr( aSeqVector
.begin() );
1577 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> >::iterator
aVectorEndItr( aSeqVector
.end() );
1578 while(aVectorItr
!= aVectorEndItr
)
1580 Reference
< chart2::data::XLabeledDataSequence
> xSeq( *aVectorItr
);
1583 pDS
->AddLabeledSequence( xSeq
);
1596 * Function object to create a list of table numbers from a token list.
1598 class InsertTabNumber
: public unary_function
<ScTokenRef
, void>
1602 mpTabNumList(new list
<SCTAB
>())
1606 InsertTabNumber(const InsertTabNumber
& r
) :
1607 mpTabNumList(r
.mpTabNumList
)
1611 void operator() (const ScTokenRef
& pToken
) const
1613 if (!ScRefTokenHelper::isRef(pToken
))
1616 const ScSingleRefData
& r
= pToken
->GetSingleRef();
1617 mpTabNumList
->push_back(r
.Tab());
1620 void getList(list
<SCTAB
>& rList
)
1622 mpTabNumList
->swap(rList
);
1625 shared_ptr
< list
<SCTAB
> > mpTabNumList
;
1632 void initRangeAnalyzer( const vector
<ScTokenRef
>& rTokens
);
1633 void analyzeRange( sal_Int32
& rnDataInRows
, sal_Int32
& rnDataInCols
,
1634 bool& rbRowSourceAmbiguous
) const;
1635 bool inSameSingleRow( RangeAnalyzer
& rOther
);
1636 bool inSameSingleColumn( RangeAnalyzer
& rOther
);
1637 SCROW
getRowCount() { return mnRowCount
; }
1638 SCCOL
getColumnCount() { return mnColumnCount
; }
1644 SCCOL mnColumnCount
;
1646 SCCOL mnStartColumn
;
1650 RangeAnalyzer::RangeAnalyzer()
1652 , mbAmbiguous(false)
1660 void RangeAnalyzer::initRangeAnalyzer( const vector
<ScTokenRef
>& rTokens
)
1667 if( rTokens
.empty() )
1674 vector
<ScTokenRef
>::const_iterator itr
= rTokens
.begin(), itrEnd
= rTokens
.end();
1675 for (; itr
!= itrEnd
; ++itr
)
1677 ScTokenRef aRefToken
= *itr
;
1678 StackVar eVar
= aRefToken
->GetType();
1679 if (eVar
== svDoubleRef
|| eVar
== svExternalDoubleRef
)
1681 const ScComplexRefData
& r
= aRefToken
->GetDoubleRef();
1682 if (r
.Ref1
.Tab() == r
.Ref2
.Tab())
1684 mnColumnCount
= std::max
<SCCOL
>(mnColumnCount
, static_cast<SCCOL
>(abs(r
.Ref2
.Col() - r
.Ref1
.Col())+1));
1685 mnRowCount
= std::max
<SCROW
>(mnRowCount
, static_cast<SCROW
>(abs(r
.Ref2
.Row() - r
.Ref1
.Row())+1));
1686 if( mnStartColumn
== -1 )
1688 mnStartColumn
= r
.Ref1
.Col();
1689 mnStartRow
= r
.Ref1
.Row();
1693 if (mnStartColumn
!= r
.Ref1
.Col() && mnStartRow
!= r
.Ref1
.Row())
1700 else if (eVar
== svSingleRef
|| eVar
== svExternalSingleRef
)
1702 const ScSingleRefData
& r
= aRefToken
->GetSingleRef();
1703 mnColumnCount
= std::max
<SCCOL
>( mnColumnCount
, 1);
1704 mnRowCount
= std::max
<SCROW
>( mnRowCount
, 1);
1705 if( mnStartColumn
== -1 )
1707 mnStartColumn
= r
.Col();
1708 mnStartRow
= r
.Row();
1712 if (mnStartColumn
!= r
.Col() && mnStartRow
!= r
.Row())
1721 void RangeAnalyzer::analyzeRange( sal_Int32
& rnDataInRows
,
1722 sal_Int32
& rnDataInCols
,
1723 bool& rbRowSourceAmbiguous
) const
1725 if(!mbEmpty
&& !mbAmbiguous
)
1727 if( mnRowCount
==1 && mnColumnCount
>1 )
1729 else if( mnColumnCount
==1 && mnRowCount
>1 )
1731 else if( mnRowCount
>1 && mnColumnCount
>1 )
1732 rbRowSourceAmbiguous
= true;
1735 rbRowSourceAmbiguous
= true;
1738 bool RangeAnalyzer::inSameSingleRow( RangeAnalyzer
& rOther
)
1740 if( mnStartRow
==rOther
.mnStartRow
&&
1741 mnRowCount
==1 && rOther
.mnRowCount
==1 )
1746 bool RangeAnalyzer::inSameSingleColumn( RangeAnalyzer
& rOther
)
1748 if( mnStartColumn
==rOther
.mnStartColumn
&&
1749 mnColumnCount
==1 && rOther
.mnColumnCount
==1 )
1754 } //end anonymous namespace
1756 uno::Sequence
< beans::PropertyValue
> SAL_CALL
ScChart2DataProvider::detectArguments(
1757 const uno::Reference
< chart2::data::XDataSource
>& xDataSource
)
1758 throw (uno::RuntimeException
)
1760 ::std::vector
< beans::PropertyValue
> aResult
;
1761 bool bRowSourceDetected
= false;
1762 bool bFirstCellAsLabel
= false;
1763 bool bHasCategories
= false;
1766 bool bHasCategoriesLabels
= false;
1767 vector
<ScTokenRef
> aAllCategoriesValuesTokens
;
1768 vector
<ScTokenRef
> aAllSeriesLabelTokens
;
1770 chart::ChartDataRowSource eRowSource
= chart::ChartDataRowSource_COLUMNS
;
1772 vector
<ScTokenRef
> aAllTokens
;
1774 // parse given data source and collect infos
1776 SolarMutexGuard aGuard
;
1777 OSL_ENSURE( m_pDocument
, "No Document -> no detectArguments" );
1778 if(!m_pDocument
||!xDataSource
.is())
1779 return lcl_VectorToSequence( aResult
);
1781 sal_Int32 nDataInRows
= 0;
1782 sal_Int32 nDataInCols
= 0;
1783 bool bRowSourceAmbiguous
= false;
1785 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSequences( xDataSource
->getDataSequences());
1786 const sal_Int32
nCount( aSequences
.getLength());
1787 RangeAnalyzer aPrevLabel
,aPrevValues
;
1788 for( sal_Int32 nIdx
=0; nIdx
<nCount
; ++nIdx
)
1790 Reference
< chart2::data::XLabeledDataSequence
> xLS(aSequences
[nIdx
]);
1793 bool bThisIsCategories
= false;
1796 Reference
< beans::XPropertySet
> xSeqProp( xLS
->getValues(), uno::UNO_QUERY
);
1798 if( xSeqProp
.is() && (xSeqProp
->getPropertyValue("Role") >>= aRole
) &&
1799 aRole
== "categories" )
1800 bThisIsCategories
= bHasCategories
= true;
1803 RangeAnalyzer aLabel
,aValues
;
1805 Reference
< chart2::data::XDataSequence
> xLabel( xLS
->getLabel());
1808 bFirstCellAsLabel
= true;
1809 vector
<ScTokenRef
> aTokens
;
1810 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
1811 ScRefTokenHelper::compileRangeRepresentation(
1812 aTokens
, xLabel
->getSourceRangeRepresentation(), m_pDocument
, cSep
, m_pDocument
->GetGrammar(), true);
1813 aLabel
.initRangeAnalyzer(aTokens
);
1814 vector
<ScTokenRef
>::const_iterator itr
= aTokens
.begin(), itrEnd
= aTokens
.end();
1815 for (; itr
!= itrEnd
; ++itr
)
1817 ScRefTokenHelper::join(aAllTokens
, *itr
, ScAddress());
1818 if(!bThisIsCategories
)
1819 ScRefTokenHelper::join(aAllSeriesLabelTokens
, *itr
, ScAddress());
1821 if(bThisIsCategories
)
1822 bHasCategoriesLabels
=true;
1825 Reference
< chart2::data::XDataSequence
> xValues( xLS
->getValues());
1828 vector
<ScTokenRef
> aTokens
;
1829 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
1830 ScRefTokenHelper::compileRangeRepresentation(
1831 aTokens
, xValues
->getSourceRangeRepresentation(), m_pDocument
, cSep
, m_pDocument
->GetGrammar(), true);
1832 aValues
.initRangeAnalyzer(aTokens
);
1833 vector
<ScTokenRef
>::const_iterator itr
= aTokens
.begin(), itrEnd
= aTokens
.end();
1834 for (; itr
!= itrEnd
; ++itr
)
1836 ScRefTokenHelper::join(aAllTokens
, *itr
, ScAddress());
1837 if(bThisIsCategories
)
1838 ScRefTokenHelper::join(aAllCategoriesValuesTokens
, *itr
, ScAddress());
1842 if(!bThisIsCategories
|| nCount
==1) //categories might span multiple rows *and* columns, so they should be used for detection only if nothing else is available
1844 if (!bRowSourceAmbiguous
)
1846 aValues
.analyzeRange(nDataInRows
,nDataInCols
,bRowSourceAmbiguous
);
1847 aLabel
.analyzeRange(nDataInRows
,nDataInCols
,bRowSourceAmbiguous
);
1848 if (nDataInRows
> 1 && nDataInCols
> 1)
1849 bRowSourceAmbiguous
= true;
1850 else if( !bRowSourceAmbiguous
&& !nDataInRows
&& !nDataInCols
)
1852 if( aValues
.inSameSingleColumn( aLabel
) )
1854 else if( aValues
.inSameSingleRow( aLabel
) )
1858 //#i86188# also detect a single column split into rows correctly
1859 if( aValues
.inSameSingleColumn( aPrevValues
) )
1861 else if( aValues
.inSameSingleRow( aPrevValues
) )
1863 else if( aLabel
.inSameSingleColumn( aPrevLabel
) )
1865 else if( aLabel
.inSameSingleRow( aPrevLabel
) )
1871 aPrevValues
=aValues
;
1876 if (!bRowSourceAmbiguous
)
1878 bRowSourceDetected
= true;
1879 eRowSource
= ( nDataInRows
> 0
1880 ? chart::ChartDataRowSource_ROWS
1881 : chart::ChartDataRowSource_COLUMNS
);
1885 // set DataRowSource to the better of the two ambiguities
1886 eRowSource
= ( nDataInRows
> nDataInCols
1887 ? chart::ChartDataRowSource_ROWS
1888 : chart::ChartDataRowSource_COLUMNS
);
1895 list
<SCTAB
> aTableNumList
;
1896 InsertTabNumber func
;
1897 func
= ::std::for_each(aAllTokens
.begin(), aAllTokens
.end(), func
);
1898 func
.getList(aTableNumList
);
1900 beans::PropertyValue( OUString("TableNumberList"), -1,
1901 uno::makeAny( lcl_createTableNumberList( aTableNumList
) ),
1902 beans::PropertyState_DIRECT_VALUE
));
1905 // DataRowSource (calculated before)
1906 if( bRowSourceDetected
)
1909 beans::PropertyValue( OUString("DataRowSource"), -1,
1910 uno::makeAny( eRowSource
), beans::PropertyState_DIRECT_VALUE
));
1914 if( bRowSourceDetected
)
1917 beans::PropertyValue( OUString("HasCategories"), -1,
1918 uno::makeAny( bHasCategories
), beans::PropertyState_DIRECT_VALUE
));
1922 if( bRowSourceDetected
)
1925 beans::PropertyValue( OUString("FirstCellAsLabel"), -1,
1926 uno::makeAny( bFirstCellAsLabel
), beans::PropertyState_DIRECT_VALUE
));
1929 // Add the left upper corner to the range if it is missing.
1930 if (bRowSourceDetected
&& bFirstCellAsLabel
&& bHasCategories
&& !bHasCategoriesLabels
)
1932 RangeAnalyzer aTop
,aLeft
;
1933 if( eRowSource
==chart::ChartDataRowSource_COLUMNS
)
1935 aTop
.initRangeAnalyzer(aAllSeriesLabelTokens
);
1936 aLeft
.initRangeAnalyzer(aAllCategoriesValuesTokens
);
1940 aTop
.initRangeAnalyzer(aAllCategoriesValuesTokens
);
1941 aLeft
.initRangeAnalyzer(aAllSeriesLabelTokens
);
1943 lcl_addUpperLeftCornerIfMissing(aAllTokens
, aTop
.getRowCount(), aLeft
.getColumnCount());//e.g. #i91212#
1946 // Get range string.
1947 lcl_convertTokensToString(sRangeRep
, aAllTokens
, m_pDocument
);
1949 // add cell range property
1951 beans::PropertyValue( OUString("CellRangeRepresentation"), -1,
1952 uno::makeAny( sRangeRep
), beans::PropertyState_DIRECT_VALUE
));
1955 bool bSequencesReordered
= true;//todo detect this above or detect this sequence mapping cheaper ...
1956 if( bSequencesReordered
&& bRowSourceDetected
)
1958 bool bDifferentIndexes
= false;
1960 std::vector
< sal_Int32
> aSequenceMappingVector
;
1962 uno::Reference
< chart2::data::XDataSource
> xCompareDataSource
;
1965 xCompareDataSource
.set( this->createDataSource( lcl_VectorToSequence( aResult
) ) );
1967 catch( const lang::IllegalArgumentException
& )
1969 // creation of data source to compare didn't work, so we cannot
1970 // create a sequence mapping
1973 if( xDataSource
.is() && xCompareDataSource
.is() )
1975 uno::Sequence
< uno::Reference
< chart2::data::XLabeledDataSequence
> > aOldSequences(
1976 xCompareDataSource
->getDataSequences() );
1977 uno::Sequence
< uno::Reference
< chart2::data::XLabeledDataSequence
> > aNewSequences(
1978 xDataSource
->getDataSequences());
1982 OUString aOldValues
;
1983 OUString aNewValues
;
1986 for( sal_Int32 nNewIndex
= 0; nNewIndex
< aNewSequences
.getLength(); nNewIndex
++ )
1988 uno::Reference
< chart2::data::XLabeledDataSequence
> xNew( aNewSequences
[nNewIndex
] );
1989 for( sal_Int32 nOldIndex
= 0; nOldIndex
< aOldSequences
.getLength(); nOldIndex
++ )
1991 uno::Reference
< chart2::data::XLabeledDataSequence
> xOld( aOldSequences
[nOldIndex
] );
1993 if( xOld
.is() && xNew
.is() )
1995 aOldLabel
= aNewLabel
= aOldValues
= aNewValues
= aEmpty
;
1996 if( xOld
.is() && xOld
->getLabel().is() )
1997 aOldLabel
= xOld
->getLabel()->getSourceRangeRepresentation();
1998 if( xNew
.is() && xNew
->getLabel().is() )
1999 aNewLabel
= xNew
->getLabel()->getSourceRangeRepresentation();
2000 if( xOld
.is() && xOld
->getValues().is() )
2001 aOldValues
= xOld
->getValues()->getSourceRangeRepresentation();
2002 if( xNew
.is() && xNew
->getValues().is() )
2003 aNewValues
= xNew
->getValues()->getSourceRangeRepresentation();
2005 if( aOldLabel
.equals(aNewLabel
)
2006 && ( aOldValues
.equals(aNewValues
) ) )
2008 if( nOldIndex
!=nNewIndex
)
2009 bDifferentIndexes
= true;
2010 aSequenceMappingVector
.push_back(nOldIndex
);
2018 if( bDifferentIndexes
&& !aSequenceMappingVector
.empty() )
2021 beans::PropertyValue( OUString("SequenceMapping"), -1,
2022 uno::makeAny( lcl_VectorToSequence(aSequenceMappingVector
) )
2023 , beans::PropertyState_DIRECT_VALUE
));
2027 return lcl_VectorToSequence( aResult
);
2030 ::sal_Bool SAL_CALL
ScChart2DataProvider::createDataSequenceByRangeRepresentationPossible( const OUString
& aRangeRepresentation
)
2031 throw (uno::RuntimeException
)
2033 SolarMutexGuard aGuard
;
2037 vector
<ScTokenRef
> aTokens
;
2038 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
2039 ScRefTokenHelper::compileRangeRepresentation(
2040 aTokens
, aRangeRepresentation
, m_pDocument
, cSep
, m_pDocument
->GetGrammar(), true);
2041 return !aTokens
.empty();
2044 uno::Reference
< chart2::data::XDataSequence
> SAL_CALL
2045 ScChart2DataProvider::createDataSequenceByRangeRepresentation(
2046 const OUString
& aRangeRepresentation
)
2047 throw (lang::IllegalArgumentException
,
2048 uno::RuntimeException
)
2050 SolarMutexGuard aGuard
;
2051 uno::Reference
< chart2::data::XDataSequence
> xResult
;
2053 OSL_ENSURE( m_pDocument
, "No Document -> no createDataSequenceByRangeRepresentation" );
2054 if(!m_pDocument
|| aRangeRepresentation
.isEmpty())
2057 vector
<ScTokenRef
> aRefTokens
;
2058 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
2059 ScRefTokenHelper::compileRangeRepresentation(
2060 aRefTokens
, aRangeRepresentation
, m_pDocument
, cSep
, m_pDocument
->GetGrammar(), true);
2061 if (aRefTokens
.empty())
2064 shrinkToDataRange(m_pDocument
, aRefTokens
);
2066 // ScChart2DataSequence manages the life cycle of pRefTokens.
2067 vector
<ScTokenRef
>* pRefTokens
= new vector
<ScTokenRef
>();
2068 pRefTokens
->swap(aRefTokens
);
2069 xResult
.set(new ScChart2DataSequence(m_pDocument
, this, pRefTokens
, m_bIncludeHiddenCells
));
2074 uno::Reference
< sheet::XRangeSelection
> SAL_CALL
ScChart2DataProvider::getRangeSelection()
2075 throw (uno::RuntimeException
)
2077 uno::Reference
< sheet::XRangeSelection
> xResult
;
2079 uno::Reference
< frame::XModel
> xModel( lcl_GetXModel( m_pDocument
));
2081 xResult
.set( xModel
->getCurrentController(), uno::UNO_QUERY
);
2086 sal_Bool SAL_CALL
ScChart2DataProvider::createDataSequenceByFormulaTokensPossible(
2087 const Sequence
<sheet::FormulaToken
>& aTokens
)
2088 throw (uno::RuntimeException
)
2090 if (aTokens
.getLength() <= 0)
2094 if (!ScTokenConversion::ConvertToTokenArray(*m_pDocument
, aCode
, aTokens
))
2097 sal_uInt16 n
= aCode
.GetLen();
2101 const formula::FormulaToken
* pFirst
= aCode
.First();
2102 const formula::FormulaToken
* pLast
= aCode
.GetArray()[n
-1];
2103 for (const formula::FormulaToken
* p
= aCode
.First(); p
; p
= aCode
.Next())
2105 switch (p
->GetType())
2109 switch (p
->GetOpCode())
2112 // separators are allowed.
2116 // open paran is allowed only as the first token.
2121 // close paren is allowed only as the last token.
2131 case svExternalSingleRef
:
2132 case svExternalDoubleRef
:
2142 Reference
<chart2::data::XDataSequence
> SAL_CALL
2143 ScChart2DataProvider::createDataSequenceByFormulaTokens(
2144 const Sequence
<sheet::FormulaToken
>& aTokens
)
2145 throw (lang::IllegalArgumentException
, uno::RuntimeException
)
2147 Reference
<chart2::data::XDataSequence
> xResult
;
2148 if (aTokens
.getLength() <= 0)
2152 if (!ScTokenConversion::ConvertToTokenArray(*m_pDocument
, aCode
, aTokens
))
2155 sal_uInt16 n
= aCode
.GetLen();
2159 vector
<ScTokenRef
> aRefTokens
;
2160 const formula::FormulaToken
* pFirst
= aCode
.First();
2161 const formula::FormulaToken
* pLast
= aCode
.GetArray()[n
-1];
2162 for (const formula::FormulaToken
* p
= aCode
.First(); p
; p
= aCode
.Next())
2164 switch (p
->GetType())
2168 switch (p
->GetOpCode())
2171 // separators are allowed.
2175 // open paran is allowed only as the first token.
2176 throw lang::IllegalArgumentException();
2180 // close paren is allowed only as the last token.
2181 throw lang::IllegalArgumentException();
2184 throw lang::IllegalArgumentException();
2191 case svExternalSingleRef
:
2192 case svExternalDoubleRef
:
2194 ScTokenRef
pNew(static_cast<ScToken
*>(p
->Clone()));
2195 aRefTokens
.push_back(pNew
);
2199 throw lang::IllegalArgumentException();
2203 if (aRefTokens
.empty())
2206 shrinkToDataRange(m_pDocument
, aRefTokens
);
2208 // ScChart2DataSequence manages the life cycle of pRefTokens.
2209 vector
<ScTokenRef
>* pRefTokens
= new vector
<ScTokenRef
>();
2210 pRefTokens
->swap(aRefTokens
);
2211 xResult
.set(new ScChart2DataSequence(m_pDocument
, this, pRefTokens
, m_bIncludeHiddenCells
));
2215 // XRangeXMLConversion ---------------------------------------------------
2217 OUString SAL_CALL
ScChart2DataProvider::convertRangeToXML( const OUString
& sRangeRepresentation
)
2218 throw ( uno::RuntimeException
, lang::IllegalArgumentException
)
2224 if (sRangeRepresentation
.isEmpty())
2225 // Empty data range is allowed.
2228 vector
<ScTokenRef
> aRefTokens
;
2229 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
2230 ScRefTokenHelper::compileRangeRepresentation(
2231 aRefTokens
, sRangeRepresentation
, m_pDocument
, cSep
, m_pDocument
->GetGrammar(), true);
2232 if (aRefTokens
.empty())
2233 throw lang::IllegalArgumentException();
2235 Tokens2RangeStringXML
converter(m_pDocument
);
2236 converter
= ::std::for_each(aRefTokens
.begin(), aRefTokens
.end(), converter
);
2237 converter
.getString(aRet
);
2242 OUString SAL_CALL
ScChart2DataProvider::convertRangeFromXML( const OUString
& sXMLRange
)
2243 throw ( uno::RuntimeException
, lang::IllegalArgumentException
)
2245 const sal_Unicode cSep
= ' ';
2246 const sal_Unicode cQuote
= '\'';
2250 // #i74062# When loading flat XML, this is called before the referenced sheets are in the document,
2251 // so the conversion has to take place directly with the strings, without looking up the sheets.
2253 OUStringBuffer sRet
;
2254 sal_Int32 nOffset
= 0;
2255 while( nOffset
>= 0 )
2258 ScRangeStringConverter::GetTokenByOffset( sToken
, sXMLRange
, nOffset
, cSep
, cQuote
);
2261 // convert one address (remove dots)
2263 OUString
aUIString(sToken
);
2265 sal_Int32 nIndex
= ScRangeStringConverter::IndexOf( sToken
, ':', 0, cQuote
);
2266 if ( nIndex
>= 0 && nIndex
< aUIString
.getLength() - 1 &&
2267 aUIString
[nIndex
+ 1] == '.' )
2268 aUIString
= aUIString
.replaceAt( nIndex
+ 1, 1, "" );
2270 if ( aUIString
[0] == '.' )
2271 aUIString
= aUIString
.copy( 1 );
2273 if( !sRet
.isEmpty() )
2275 sRet
.append( aUIString
);
2279 return sRet
.makeStringAndClear();
2283 ScRangeStringConverter::GetStringFromXMLRangeString(aRet
, sXMLRange
, m_pDocument
);
2287 // DataProvider XPropertySet -------------------------------------------------
2289 uno::Reference
< beans::XPropertySetInfo
> SAL_CALL
2290 ScChart2DataProvider::getPropertySetInfo() throw( uno::RuntimeException
)
2292 SolarMutexGuard aGuard
;
2293 static uno::Reference
<beans::XPropertySetInfo
> aRef
=
2294 new SfxItemPropertySetInfo( m_aPropSet
.getPropertyMap() );
2299 void SAL_CALL
ScChart2DataProvider::setPropertyValue(
2300 const OUString
& rPropertyName
, const uno::Any
& rValue
)
2301 throw( beans::UnknownPropertyException
,
2302 beans::PropertyVetoException
,
2303 lang::IllegalArgumentException
,
2304 lang::WrappedTargetException
, uno::RuntimeException
)
2306 if ( rPropertyName
== SC_UNONAME_INCLUDEHIDDENCELLS
)
2308 if ( !(rValue
>>= m_bIncludeHiddenCells
))
2309 throw lang::IllegalArgumentException();
2312 throw beans::UnknownPropertyException();
2316 uno::Any SAL_CALL
ScChart2DataProvider::getPropertyValue(
2317 const OUString
& rPropertyName
)
2318 throw( beans::UnknownPropertyException
,
2319 lang::WrappedTargetException
, uno::RuntimeException
)
2322 if ( rPropertyName
== SC_UNONAME_INCLUDEHIDDENCELLS
)
2323 aRet
<<= m_bIncludeHiddenCells
;
2324 else if (rPropertyName
== SC_UNONAME_USE_INTERNAL_DATA_PROVIDER
)
2326 // This is a read-only property.
2327 aRet
<<= static_cast<sal_Bool
>(m_pDocument
->PastingDrawFromOtherDoc());
2330 throw beans::UnknownPropertyException();
2335 void SAL_CALL
ScChart2DataProvider::addPropertyChangeListener(
2336 const OUString
& /*rPropertyName*/,
2337 const uno::Reference
< beans::XPropertyChangeListener
>& /*xListener*/)
2338 throw( beans::UnknownPropertyException
,
2339 lang::WrappedTargetException
, uno::RuntimeException
)
2341 OSL_FAIL( "Not yet implemented" );
2345 void SAL_CALL
ScChart2DataProvider::removePropertyChangeListener(
2346 const OUString
& /*rPropertyName*/,
2347 const uno::Reference
< beans::XPropertyChangeListener
>& /*rListener*/)
2348 throw( beans::UnknownPropertyException
,
2349 lang::WrappedTargetException
, uno::RuntimeException
)
2351 OSL_FAIL( "Not yet implemented" );
2355 void SAL_CALL
ScChart2DataProvider::addVetoableChangeListener(
2356 const OUString
& /*rPropertyName*/,
2357 const uno::Reference
< beans::XVetoableChangeListener
>& /*rListener*/)
2358 throw( beans::UnknownPropertyException
,
2359 lang::WrappedTargetException
, uno::RuntimeException
)
2361 OSL_FAIL( "Not yet implemented" );
2365 void SAL_CALL
ScChart2DataProvider::removeVetoableChangeListener(
2366 const OUString
& /*rPropertyName*/,
2367 const uno::Reference
< beans::XVetoableChangeListener
>& /*rListener*/ )
2368 throw( beans::UnknownPropertyException
,
2369 lang::WrappedTargetException
, uno::RuntimeException
)
2371 OSL_FAIL( "Not yet implemented" );
2374 // DataSource ================================================================
2376 ScChart2DataSource::ScChart2DataSource( ScDocument
* pDoc
)
2377 : m_pDocument( pDoc
)
2380 m_pDocument
->AddUnoObject( *this);
2384 ScChart2DataSource::~ScChart2DataSource()
2387 m_pDocument
->RemoveUnoObject( *this);
2391 void ScChart2DataSource::Notify( SfxBroadcaster
& /*rBC*/, const SfxHint
& rHint
)
2393 if ( rHint
.ISA( SfxSimpleHint
) &&
2394 ((const SfxSimpleHint
&)rHint
).GetId() == SFX_HINT_DYING
)
2401 uno::Sequence
< uno::Reference
< chart2::data::XLabeledDataSequence
> > SAL_CALL
2402 ScChart2DataSource::getDataSequences() throw ( uno::RuntimeException
)
2404 SolarMutexGuard aGuard
;
2406 LabeledList::const_iterator
aItr(m_aLabeledSequences
.begin());
2407 LabeledList::const_iterator
aEndItr(m_aLabeledSequences
.end());
2409 uno::Sequence
< uno::Reference
< chart2::data::XLabeledDataSequence
> > aRet(m_aLabeledSequences
.size());
2412 while (aItr
!= aEndItr
)
2422 void ScChart2DataSource::AddLabeledSequence(const uno::Reference
< chart2::data::XLabeledDataSequence
>& xNew
)
2424 m_aLabeledSequences
.push_back(xNew
);
2428 // DataSequence ==============================================================
2430 ScChart2DataSequence::Item::Item() :
2431 mfValue(0.0), mbIsValue(false)
2433 ::rtl::math::setNan(&mfValue
);
2436 ScChart2DataSequence::HiddenRangeListener::HiddenRangeListener(ScChart2DataSequence
& rParent
) :
2441 ScChart2DataSequence::HiddenRangeListener::~HiddenRangeListener()
2445 void ScChart2DataSequence::HiddenRangeListener::notify()
2447 mrParent
.setDataChangedHint(true);
2450 ScChart2DataSequence::ScChart2DataSequence( ScDocument
* pDoc
,
2451 const uno::Reference
< chart2::data::XDataProvider
>& xDP
,
2452 vector
<ScTokenRef
>* pTokens
,
2453 bool bIncludeHiddenCells
)
2454 : m_bIncludeHiddenCells( bIncludeHiddenCells
)
2456 , m_pDocument( pDoc
)
2457 , m_pTokens(pTokens
)
2458 , m_pRangeIndices(NULL
)
2459 , m_pExtRefListener(NULL
)
2460 , m_xDataProvider( xDP
)
2461 , m_aPropSet(lcl_GetDataSequencePropertyMap())
2462 , m_pHiddenListener(NULL
)
2463 , m_pValueListener( NULL
)
2464 , m_bGotDataChangedHint(false)
2465 , m_bExtDataRebuildQueued(false)
2467 OSL_ENSURE(pTokens
, "reference token list is null");
2471 m_pDocument
->AddUnoObject( *this);
2472 m_nObjectId
= m_pDocument
->GetNewUnoId();
2474 // FIXME: real implementation of identifier and it's mapping to ranges.
2475 // Reuse ScChartListener?
2477 // BM: don't use names of named ranges but the UI range strings
2479 // rRangeList->Format( aStr, SCR_ABS_3D, m_pDocument );
2480 // m_aIdentifier = aStr;
2482 // m_aIdentifier = "ID_";
2483 // static sal_Int32 nID = 0;
2484 // m_aIdentifier += OUString::valueOf( ++nID);
2487 ScChart2DataSequence::~ScChart2DataSequence()
2491 m_pDocument
->RemoveUnoObject( *this);
2492 if (m_pHiddenListener
.get())
2494 ScChartListenerCollection
* pCLC
= m_pDocument
->GetChartListenerCollection();
2496 pCLC
->EndListeningHiddenRange(m_pHiddenListener
.get());
2498 StopListeningToAllExternalRefs();
2501 delete m_pValueListener
;
2504 void ScChart2DataSequence::RefChanged()
2506 if( m_pValueListener
&& !m_aValueListeners
.empty() )
2508 m_pValueListener
->EndListeningAll();
2512 ScChartListenerCollection
* pCLC
= NULL
;
2513 if (m_pHiddenListener
.get())
2515 pCLC
= m_pDocument
->GetChartListenerCollection();
2517 pCLC
->EndListeningHiddenRange(m_pHiddenListener
.get());
2520 vector
<ScTokenRef
>::const_iterator itr
= m_pTokens
->begin(), itrEnd
= m_pTokens
->end();
2521 for (; itr
!= itrEnd
; ++itr
)
2524 if (!ScRefTokenHelper::getRangeFromToken(aRange
, *itr
, ScAddress()))
2527 m_pDocument
->StartListeningArea(aRange
, m_pValueListener
);
2529 pCLC
->StartListeningHiddenRange(aRange
, m_pHiddenListener
.get());
2535 void ScChart2DataSequence::BuildDataCache()
2537 m_bExtDataRebuildQueued
= false;
2539 if (!m_aDataArray
.empty())
2542 if (!m_pTokens
.get())
2544 OSL_FAIL("m_pTokens == NULL! Something is wrong.");
2548 StopListeningToAllExternalRefs();
2550 ::std::list
<sal_Int32
> aHiddenValues
;
2551 sal_Int32 nDataCount
= 0;
2552 sal_Int32 nHiddenValueCount
= 0;
2554 for (vector
<ScTokenRef
>::const_iterator itr
= m_pTokens
->begin(), itrEnd
= m_pTokens
->end();
2555 itr
!= itrEnd
; ++itr
)
2557 if (ScRefTokenHelper::isExternalRef(*itr
))
2559 nDataCount
+= FillCacheFromExternalRef(*itr
);
2564 if (!ScRefTokenHelper::getRangeFromToken(aRange
, *itr
, ScAddress()))
2567 SCCOL nLastCol
= -1;
2568 SCROW nLastRow
= -1;
2569 for (SCTAB nTab
= aRange
.aStart
.Tab(); nTab
<= aRange
.aEnd
.Tab(); ++nTab
)
2571 for (SCCOL nCol
= aRange
.aStart
.Col(); nCol
<= aRange
.aEnd
.Col(); ++nCol
)
2573 for (SCROW nRow
= aRange
.aStart
.Row(); nRow
<= aRange
.aEnd
.Row(); ++nRow
)
2575 bool bColHidden
= m_pDocument
->ColHidden(nCol
, nTab
, NULL
, &nLastCol
);
2576 bool bRowHidden
= m_pDocument
->RowHidden(nRow
, nTab
, NULL
, &nLastRow
);
2578 if (bColHidden
|| bRowHidden
)
2581 ++nHiddenValueCount
;
2582 aHiddenValues
.push_back(nDataCount
-1);
2584 if( !m_bIncludeHiddenCells
)
2588 m_aDataArray
.push_back(Item());
2589 Item
& rItem
= m_aDataArray
.back();
2592 ScAddress
aAdr(nCol
, nRow
, nTab
);
2593 rItem
.maString
= m_pDocument
->GetString(aAdr
);
2595 switch (m_pDocument
->GetCellType(aAdr
))
2597 case CELLTYPE_VALUE
:
2598 rItem
.mfValue
= m_pDocument
->GetValue(aAdr
);
2599 rItem
.mbIsValue
= true;
2601 case CELLTYPE_FORMULA
:
2603 ScFormulaCell
* pFCell
= m_pDocument
->GetFormulaCell(aAdr
);
2604 sal_uInt16 nErr
= pFCell
->GetErrCode();
2608 if (pFCell
->IsValue())
2610 rItem
.mfValue
= pFCell
->GetValue();
2611 rItem
.mbIsValue
= true;
2617 case CELLTYPE_STRING
:
2627 // convert the hidden cell list to sequence.
2628 m_aHiddenValues
.realloc(nHiddenValueCount
);
2629 sal_Int32
* pArr
= m_aHiddenValues
.getArray();
2630 ::std::list
<sal_Int32
>::const_iterator itr
= aHiddenValues
.begin(), itrEnd
= aHiddenValues
.end();
2631 for (;itr
!= itrEnd
; ++itr
, ++pArr
)
2634 // Clear the data series cache when the array is re-built.
2635 m_aMixedDataCache
.realloc(0);
2638 void ScChart2DataSequence::RebuildDataCache()
2640 if (!m_bExtDataRebuildQueued
)
2642 m_aDataArray
.clear();
2643 m_pDocument
->BroadcastUno(ScHint(SC_HINT_DATACHANGED
, ScAddress()));
2644 m_bExtDataRebuildQueued
= true;
2645 m_bGotDataChangedHint
= true;
2649 sal_Int32
ScChart2DataSequence::FillCacheFromExternalRef(const ScTokenRef
& pToken
)
2651 ScExternalRefManager
* pRefMgr
= m_pDocument
->GetExternalRefManager();
2653 if (!ScRefTokenHelper::getRangeFromToken(aRange
, pToken
, ScAddress(), true))
2656 sal_uInt16 nFileId
= pToken
->GetIndex();
2657 OUString aTabName
= pToken
->GetString().getString();
2658 ScExternalRefCache::TokenArrayRef pArray
= pRefMgr
->getDoubleRefTokens(nFileId
, aTabName
, aRange
, NULL
);
2660 // no external data exists for this range.
2663 // Start listening for this external document.
2664 ExternalRefListener
* pExtRefListener
= GetExtRefListener();
2665 pRefMgr
->addLinkListener(nFileId
, pExtRefListener
);
2666 pExtRefListener
->addFileId(nFileId
);
2668 ScExternalRefCache::TableTypeRef pTable
= pRefMgr
->getCacheTable(nFileId
, aTabName
, false, NULL
);
2669 sal_Int32 nDataCount
= 0;
2670 for (FormulaToken
* p
= pArray
->First(); p
; p
= pArray
->Next())
2672 // Cached external range is always represented as a single
2673 // matrix token, although that might change in the future when
2674 // we introduce a new token type to store multi-table range
2677 if (p
->GetType() != svMatrix
)
2679 OSL_FAIL("Cached array is not a matrix token.");
2683 const ScMatrix
* pMat
= static_cast<ScToken
*>(p
)->GetMatrix();
2684 SCSIZE nCSize
, nRSize
;
2685 pMat
->GetDimensions(nCSize
, nRSize
);
2686 for (SCSIZE nC
= 0; nC
< nCSize
; ++nC
)
2688 for (SCSIZE nR
= 0; nR
< nRSize
; ++nR
)
2690 if (pMat
->IsValue(nC
, nR
) || pMat
->IsBoolean(nC
, nR
))
2692 m_aDataArray
.push_back(Item());
2693 Item
& rItem
= m_aDataArray
.back();
2696 rItem
.mbIsValue
= true;
2697 rItem
.mfValue
= pMat
->GetDouble(nC
, nR
);
2699 SvNumberFormatter
* pFormatter
= m_pDocument
->GetFormatTable();
2703 const double fVal
= rItem
.mfValue
;
2704 Color
* pColor
= NULL
;
2705 sal_uInt32 nFmt
= 0;
2708 // Get the correct format index from the cache.
2709 SCCOL nCol
= aRange
.aStart
.Col() + static_cast<SCCOL
>(nC
);
2710 SCROW nRow
= aRange
.aStart
.Row() + static_cast<SCROW
>(nR
);
2711 pTable
->getCell(nCol
, nRow
, &nFmt
);
2713 pFormatter
->GetOutputString(fVal
, nFmt
, aStr
, &pColor
);
2714 rItem
.maString
= aStr
;
2717 else if (pMat
->IsString(nC
, nR
))
2719 m_aDataArray
.push_back(Item());
2720 Item
& rItem
= m_aDataArray
.back();
2723 rItem
.mbIsValue
= false;
2724 rItem
.maString
= pMat
->GetString(nC
, nR
).getString();
2732 void ScChart2DataSequence::UpdateTokensFromRanges(const ScRangeList
& rRanges
)
2734 if (!m_pRangeIndices
.get())
2737 for ( size_t i
= 0, nCount
= rRanges
.size(); i
< nCount
; ++i
)
2740 const ScRange
* pRange
= rRanges
[i
];
2741 OSL_ENSURE(pRange
, "range object is NULL.");
2743 ScRefTokenHelper::getTokenFromRange(pToken
, *pRange
);
2744 sal_uInt32 nOrigPos
= (*m_pRangeIndices
)[i
];
2745 (*m_pTokens
)[nOrigPos
] = pToken
;
2750 // any change of the range address is broadcast to value (modify) listeners
2751 if ( !m_aValueListeners
.empty() )
2752 m_bGotDataChangedHint
= true;
2755 ScChart2DataSequence::ExternalRefListener
* ScChart2DataSequence::GetExtRefListener()
2757 if (!m_pExtRefListener
.get())
2758 m_pExtRefListener
.reset(new ExternalRefListener(*this, m_pDocument
));
2760 return m_pExtRefListener
.get();
2763 void ScChart2DataSequence::StopListeningToAllExternalRefs()
2765 if (!m_pExtRefListener
.get())
2768 const boost::unordered_set
<sal_uInt16
>& rFileIds
= m_pExtRefListener
->getAllFileIds();
2769 boost::unordered_set
<sal_uInt16
>::const_iterator itr
= rFileIds
.begin(), itrEnd
= rFileIds
.end();
2770 ScExternalRefManager
* pRefMgr
= m_pDocument
->GetExternalRefManager();
2771 for (; itr
!= itrEnd
; ++itr
)
2772 pRefMgr
->removeLinkListener(*itr
, m_pExtRefListener
.get());
2774 m_pExtRefListener
.reset(NULL
);
2777 void ScChart2DataSequence::CopyData(const ScChart2DataSequence
& r
)
2781 OSL_FAIL("document instance is NULL!?");
2785 list
<Item
> aDataArray(r
.m_aDataArray
);
2786 m_aDataArray
.swap(aDataArray
);
2788 m_aHiddenValues
= r
.m_aHiddenValues
;
2789 m_aRole
= r
.m_aRole
;
2791 if (r
.m_pRangeIndices
.get())
2792 m_pRangeIndices
.reset(new vector
<sal_uInt32
>(*r
.m_pRangeIndices
));
2794 if (r
.m_pExtRefListener
.get())
2796 // Re-register all external files that the old instance was
2799 ScExternalRefManager
* pRefMgr
= m_pDocument
->GetExternalRefManager();
2800 m_pExtRefListener
.reset(new ExternalRefListener(*this, m_pDocument
));
2801 const boost::unordered_set
<sal_uInt16
>& rFileIds
= r
.m_pExtRefListener
->getAllFileIds();
2802 boost::unordered_set
<sal_uInt16
>::const_iterator itr
= rFileIds
.begin(), itrEnd
= rFileIds
.end();
2803 for (; itr
!= itrEnd
; ++itr
)
2805 pRefMgr
->addLinkListener(*itr
, m_pExtRefListener
.get());
2806 m_pExtRefListener
->addFileId(*itr
);
2811 void ScChart2DataSequence::Notify( SfxBroadcaster
& /*rBC*/, const SfxHint
& rHint
)
2813 if ( rHint
.ISA( SfxSimpleHint
) )
2815 sal_uLong nId
= static_cast<const SfxSimpleHint
&>(rHint
).GetId();
2816 if ( nId
==SFX_HINT_DYING
)
2820 else if ( nId
== SFX_HINT_DATACHANGED
)
2822 // delayed broadcast as in ScCellRangesBase
2824 if ( m_bGotDataChangedHint
&& m_pDocument
)
2826 m_aDataArray
.clear();
2827 lang::EventObject aEvent
;
2828 aEvent
.Source
.set((cppu::OWeakObject
*)this);
2832 for ( sal_uInt16 n
=0; n
<m_aValueListeners
.size(); n
++ )
2833 m_pDocument
->AddUnoListenerCall( m_aValueListeners
[n
], aEvent
);
2836 m_bGotDataChangedHint
= false;
2839 else if ( nId
== SC_HINT_CALCALL
)
2841 // broadcast from DoHardRecalc - set m_bGotDataChangedHint
2842 // (SFX_HINT_DATACHANGED follows separately)
2844 if ( !m_aValueListeners
.empty() )
2845 m_bGotDataChangedHint
= true;
2848 else if ( rHint
.ISA( ScUpdateRefHint
) )
2850 // Create a range list from the token list, have the range list
2851 // updated, and bring the change back to the token list.
2853 ScRangeList aRanges
;
2854 m_pRangeIndices
.reset(new vector
<sal_uInt32
>());
2855 vector
<ScTokenRef
>::const_iterator itrBeg
= m_pTokens
->begin(), itrEnd
= m_pTokens
->end();
2856 for (vector
<ScTokenRef
>::const_iterator itr
= itrBeg
;itr
!= itrEnd
; ++itr
)
2858 if (!ScRefTokenHelper::isExternalRef(*itr
))
2861 ScRefTokenHelper::getRangeFromToken(aRange
, *itr
, ScAddress());
2862 aRanges
.Append(aRange
);
2863 sal_uInt32 nPos
= distance(itrBeg
, itr
);
2864 m_pRangeIndices
->push_back(nPos
);
2868 OSL_ENSURE(m_pRangeIndices
->size() == static_cast<size_t>(aRanges
.size()),
2869 "range list and range index list have different sizes.");
2871 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2872 auto_ptr
<ScRangeList
> pUndoRanges
;
2873 SAL_WNODEPRECATED_DECLARATIONS_POP
2874 if ( m_pDocument
->HasUnoRefUndo() )
2875 pUndoRanges
.reset(new ScRangeList(aRanges
));
2877 const ScUpdateRefHint
& rRef
= (const ScUpdateRefHint
&)rHint
;
2878 bool bChanged
= aRanges
.UpdateReference(
2879 rRef
.GetMode(), m_pDocument
, rRef
.GetRange(), rRef
.GetDx(), rRef
.GetDy(), rRef
.GetDz());
2883 OSL_ENSURE(m_pRangeIndices
->size() == aRanges
.size(),
2884 "range list and range index list have different sizes after the reference update.");
2886 // Bring the change back from the range list to the token list.
2887 UpdateTokensFromRanges(aRanges
);
2889 if (pUndoRanges
.get())
2890 m_pDocument
->AddUnoRefChange(m_nObjectId
, *pUndoRanges
);
2893 else if ( rHint
.ISA( ScUnoRefUndoHint
) )
2895 const ScUnoRefUndoHint
& rUndoHint
= static_cast<const ScUnoRefUndoHint
&>(rHint
);
2899 if (rUndoHint
.GetObjectId() != m_nObjectId
)
2902 // The hint object provides the old ranges. Restore the old state
2903 // from these ranges.
2905 if (!m_pRangeIndices
.get() || m_pRangeIndices
->empty())
2907 OSL_FAIL(" faulty range indices");
2911 const ScRangeList
& rRanges
= rUndoHint
.GetRanges();
2913 size_t nCount
= rRanges
.size();
2914 if (nCount
!= m_pRangeIndices
->size())
2916 OSL_FAIL("range count and range index count differ.");
2920 UpdateTokensFromRanges(rRanges
);
2927 IMPL_LINK( ScChart2DataSequence
, ValueListenerHdl
, SfxHint
*, pHint
)
2929 if ( m_pDocument
&& pHint
&& pHint
->ISA( SfxSimpleHint
) &&
2930 ((const SfxSimpleHint
*)pHint
)->GetId() & SC_HINT_DATACHANGED
)
2932 // This may be called several times for a single change, if several formulas
2933 // in the range are notified. So only a flag is set that is checked when
2934 // SFX_HINT_DATACHANGED is received.
2936 setDataChangedHint(true);
2941 // ----------------------------------------------------------------------------
2943 ScChart2DataSequence::ExternalRefListener::ExternalRefListener(
2944 ScChart2DataSequence
& rParent
, ScDocument
* pDoc
) :
2945 ScExternalRefManager::LinkListener(),
2951 ScChart2DataSequence::ExternalRefListener::~ExternalRefListener()
2953 if (!mpDoc
|| mpDoc
->IsInDtorClear())
2954 // The document is being destroyed. Do nothing.
2957 // Make sure to remove all pointers to this object.
2958 mpDoc
->GetExternalRefManager()->removeLinkListener(this);
2961 void ScChart2DataSequence::ExternalRefListener::notify(sal_uInt16 nFileId
, ScExternalRefManager::LinkUpdateType eType
)
2965 case ScExternalRefManager::LINK_MODIFIED
:
2967 if (maFileIds
.count(nFileId
))
2968 // We are listening to this external document.
2969 mrParent
.RebuildDataCache();
2972 case ScExternalRefManager::LINK_BROKEN
:
2973 removeFileId(nFileId
);
2978 void ScChart2DataSequence::ExternalRefListener::addFileId(sal_uInt16 nFileId
)
2980 maFileIds
.insert(nFileId
);
2983 void ScChart2DataSequence::ExternalRefListener::removeFileId(sal_uInt16 nFileId
)
2985 maFileIds
.erase(nFileId
);
2988 const boost::unordered_set
<sal_uInt16
>& ScChart2DataSequence::ExternalRefListener::getAllFileIds()
2993 // ----------------------------------------------------------------------------
2995 uno::Sequence
< uno::Any
> SAL_CALL
ScChart2DataSequence::getData()
2996 throw ( uno::RuntimeException
)
2998 SolarMutexGuard aGuard
;
3000 throw uno::RuntimeException();
3004 if (!m_aMixedDataCache
.getLength())
3006 // Build a cache for the 1st time...
3008 sal_Int32 nCount
= m_aDataArray
.size();
3009 m_aMixedDataCache
.realloc(nCount
);
3010 uno::Any
* pArr
= m_aMixedDataCache
.getArray();
3011 ::std::list
<Item
>::const_iterator itr
= m_aDataArray
.begin(), itrEnd
= m_aDataArray
.end();
3012 for (; itr
!= itrEnd
; ++itr
, ++pArr
)
3015 *pArr
<<= itr
->mfValue
;
3017 *pArr
<<= itr
->maString
;
3020 return m_aMixedDataCache
;
3023 // XNumericalDataSequence --------------------------------------------------
3025 uno::Sequence
< double > SAL_CALL
ScChart2DataSequence::getNumericalData()
3026 throw ( uno::RuntimeException
)
3028 SolarMutexGuard aGuard
;
3030 throw uno::RuntimeException();
3035 ::rtl::math::setNan(&fNAN
);
3037 sal_Int32 nCount
= m_aDataArray
.size();
3038 uno::Sequence
<double> aSeq(nCount
);
3039 double* pArr
= aSeq
.getArray();
3040 ::std::list
<Item
>::const_iterator itr
= m_aDataArray
.begin(), itrEnd
= m_aDataArray
.end();
3041 for (; itr
!= itrEnd
; ++itr
, ++pArr
)
3042 *pArr
= itr
->mbIsValue
? itr
->mfValue
: fNAN
;
3047 // XTextualDataSequence --------------------------------------------------
3049 uno::Sequence
< OUString
> SAL_CALL
ScChart2DataSequence::getTextualData( ) throw (uno::RuntimeException
)
3051 SolarMutexGuard aGuard
;
3052 uno::Sequence
<OUString
> aSeq
;
3054 throw uno::RuntimeException();
3058 sal_Int32 nCount
= m_aDataArray
.size();
3061 aSeq
= uno::Sequence
<OUString
>(nCount
);
3062 OUString
* pArr
= aSeq
.getArray();
3063 ::std::list
<Item
>::const_iterator itr
= m_aDataArray
.begin(), itrEnd
= m_aDataArray
.end();
3064 for(; itr
!= itrEnd
; ++itr
, ++pArr
)
3065 *pArr
= itr
->maString
;
3067 else if ( m_pTokens
.get() && m_pTokens
->front() )
3069 if( m_pTokens
->front()->GetType() == svString
)
3071 aSeq
= uno::Sequence
<OUString
>(1);
3072 aSeq
[0] = m_pTokens
->front()->GetString().getString();
3079 OUString SAL_CALL
ScChart2DataSequence::getSourceRangeRepresentation()
3080 throw ( uno::RuntimeException
)
3082 SolarMutexGuard aGuard
;
3084 OSL_ENSURE( m_pDocument
, "No Document -> no SourceRangeRepresentation" );
3085 if (m_pDocument
&& m_pTokens
.get())
3086 lcl_convertTokensToString(aStr
, *m_pTokens
, m_pDocument
);
3094 * This function object is used to accumulatively count the numbers of
3095 * columns and rows in all reference tokens.
3097 class AccumulateRangeSize
: public unary_function
<ScTokenRef
, void>
3100 AccumulateRangeSize() :
3101 mnCols(0), mnRows(0) {}
3103 AccumulateRangeSize(const AccumulateRangeSize
& r
) :
3104 mnCols(r
.mnCols
), mnRows(r
.mnRows
) {}
3106 void operator() (const ScTokenRef
& pToken
)
3109 bool bExternal
= ScRefTokenHelper::isExternalRef(pToken
);
3110 ScRefTokenHelper::getRangeFromToken(r
, pToken
, ScAddress(), bExternal
);
3112 mnCols
+= r
.aEnd
.Col() - r
.aStart
.Col() + 1;
3113 mnRows
+= r
.aEnd
.Row() - r
.aStart
.Row() + 1;
3116 SCCOL
getCols() const { return mnCols
; }
3117 SCROW
getRows() const { return mnRows
; }
3124 * This function object is used to generate label strings from a list of
3127 class GenerateLabelStrings
: public unary_function
<ScTokenRef
, void>
3130 GenerateLabelStrings(sal_Int32 nSize
, chart2::data::LabelOrigin eOrigin
, bool bColumn
) :
3131 mpLabels(new Sequence
<OUString
>(nSize
)),
3134 mbColumn(bColumn
) {}
3136 GenerateLabelStrings(const GenerateLabelStrings
& r
) :
3137 mpLabels(r
.mpLabels
),
3138 meOrigin(r
.meOrigin
),
3140 mbColumn(r
.mbColumn
) {}
3142 void operator() (const ScTokenRef
& pToken
)
3144 bool bExternal
= ScRefTokenHelper::isExternalRef(pToken
);
3146 ScRefTokenHelper::getRangeFromToken(aRange
, pToken
, ScAddress(), bExternal
);
3147 OUString
* pArr
= mpLabels
->getArray();
3150 for (SCCOL nCol
= aRange
.aStart
.Col(); nCol
<= aRange
.aEnd
.Col(); ++nCol
)
3152 if ( meOrigin
!= chart2::data::LabelOrigin_LONG_SIDE
)
3154 OUString aString
= ScGlobal::GetRscString(STR_COLUMN
);
3156 ScAddress
aPos( nCol
, 0, 0 );
3157 OUString
aColStr(aPos
.Format(SCA_VALID_COL
, NULL
));
3159 pArr
[mnCount
] = aString
;
3161 else //only indices for categories
3162 pArr
[mnCount
] = OUString::number( mnCount
+1 );
3168 for (sal_Int32 nRow
= aRange
.aStart
.Row(); nRow
<= aRange
.aEnd
.Row(); ++nRow
)
3170 if (meOrigin
!= chart2::data::LabelOrigin_LONG_SIDE
)
3172 OUString aString
= ScGlobal::GetRscString(STR_ROW
) +
3173 " " + OUString::number( nRow
+1 );
3174 pArr
[mnCount
] = aString
;
3176 else //only indices for categories
3177 pArr
[mnCount
] = OUString::number( mnCount
+1 );
3183 Sequence
<OUString
> getLabels() const { return *mpLabels
; }
3186 shared_ptr
< Sequence
<OUString
> > mpLabels
;
3187 chart2::data::LabelOrigin meOrigin
;
3194 uno::Sequence
< OUString
> SAL_CALL
ScChart2DataSequence::generateLabel(chart2::data::LabelOrigin eOrigin
)
3195 throw (uno::RuntimeException
)
3197 SolarMutexGuard aGuard
;
3199 throw uno::RuntimeException();
3201 if (!m_pTokens
.get())
3202 return Sequence
<OUString
>();
3204 // Determine the total size of all ranges.
3205 AccumulateRangeSize func
;
3206 func
= ::std::for_each(m_pTokens
->begin(), m_pTokens
->end(), func
);
3207 SCCOL nCols
= func
.getCols();
3208 SCROW nRows
= func
.getRows();
3210 // Detemine whether this is column-major or row-major.
3211 bool bColumn
= true;
3212 if ((eOrigin
== chart2::data::LabelOrigin_SHORT_SIDE
) ||
3213 (eOrigin
== chart2::data::LabelOrigin_LONG_SIDE
))
3217 if (eOrigin
== chart2::data::LabelOrigin_SHORT_SIDE
)
3222 else if (nCols
> nRows
)
3224 if (eOrigin
== chart2::data::LabelOrigin_SHORT_SIDE
)
3230 return Sequence
<OUString
>();
3233 // Generate label strings based on the info so far.
3234 sal_Int32 nCount
= bColumn
? nCols
: nRows
;
3235 GenerateLabelStrings
genLabels(nCount
, eOrigin
, bColumn
);
3236 genLabels
= ::std::for_each(m_pTokens
->begin(), m_pTokens
->end(), genLabels
);
3237 Sequence
<OUString
> aSeq
= genLabels
.getLabels();
3244 sal_uLong
getDisplayNumberFormat(ScDocument
* pDoc
, const ScAddress
& rPos
)
3246 sal_uLong nFormat
= pDoc
->GetNumberFormat(rPos
); // original format from cell.
3252 ::sal_Int32 SAL_CALL
ScChart2DataSequence::getNumberFormatKeyByIndex( ::sal_Int32 nIndex
)
3253 throw (lang::IndexOutOfBoundsException
,
3254 uno::RuntimeException
)
3256 // index -1 means a heuristic value for the entire sequence
3257 bool bGetSeriesFormat
= (nIndex
== -1);
3259 SolarMutexGuard aGuard
;
3260 if ( !m_pDocument
|| !m_pTokens
.get())
3263 // TODO: Handle external references too.
3265 sal_Int32 nCount
= 0;
3267 ScRangeList aRanges
;
3268 ScRefTokenHelper::getRangeListFromTokens(aRanges
, *m_pTokens
, ScAddress());
3269 for (size_t i
= 0, n
= aRanges
.size(); i
< n
; ++i
)
3271 ScRange
* p
= aRanges
[i
];
3272 for (SCTAB nTab
= p
->aStart
.Tab(); nTab
<= p
->aEnd
.Tab(); ++nTab
)
3274 for (SCCOL nCol
= p
->aStart
.Col(); nCol
<= p
->aEnd
.Col(); ++nCol
)
3276 if (!m_bIncludeHiddenCells
)
3278 // Skip hidden columns.
3279 SCCOL nLastCol
= -1;
3280 bool bColHidden
= m_pDocument
->ColHidden(nCol
, nTab
, NULL
, &nLastCol
);
3288 for (SCROW nRow
= p
->aStart
.Row(); nRow
<= p
->aEnd
.Row(); ++nRow
)
3290 if (!m_bIncludeHiddenCells
)
3292 // Skip hidden rows.
3293 SCROW nLastRow
= -1;
3294 bool bRowHidden
= m_pDocument
->RowHidden(nRow
, nTab
, NULL
, &nLastRow
);
3302 ScAddress
aPos(nCol
, nRow
, nTab
);
3304 if( bGetSeriesFormat
)
3306 // TODO: use nicer heuristic
3307 // return format of first non-empty cell
3308 ScRefCellValue aCell
;
3309 aCell
.assign(*m_pDocument
, aPos
);
3310 if (!aCell
.isEmpty())
3311 return static_cast<sal_Int32
>(getDisplayNumberFormat(m_pDocument
, aPos
));
3313 else if( nCount
== nIndex
)
3315 return static_cast<sal_Int32
>(getDisplayNumberFormat(m_pDocument
, aPos
));
3325 // XCloneable ================================================================
3327 uno::Reference
< util::XCloneable
> SAL_CALL
ScChart2DataSequence::createClone()
3328 throw (uno::RuntimeException
)
3330 SolarMutexGuard aGuard
;
3332 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3333 auto_ptr
< vector
<ScTokenRef
> > pTokensNew
;
3334 SAL_WNODEPRECATED_DECLARATIONS_POP
3335 if (m_pTokens
.get())
3338 pTokensNew
.reset(new vector
<ScTokenRef
>);
3339 pTokensNew
->reserve(m_pTokens
->size());
3340 vector
<ScTokenRef
>::const_iterator itr
= m_pTokens
->begin(), itrEnd
= m_pTokens
->end();
3341 for (; itr
!= itrEnd
; ++itr
)
3343 ScTokenRef
p(static_cast<ScToken
*>((*itr
)->Clone()));
3344 pTokensNew
->push_back(p
);
3348 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3349 auto_ptr
<ScChart2DataSequence
> p(new ScChart2DataSequence(m_pDocument
, m_xDataProvider
, pTokensNew
.release(), m_bIncludeHiddenCells
));
3350 SAL_WNODEPRECATED_DECLARATIONS_POP
3352 Reference
< util::XCloneable
> xClone(p
.release());
3357 // XModifyBroadcaster ========================================================
3359 void SAL_CALL
ScChart2DataSequence::addModifyListener( const uno::Reference
< util::XModifyListener
>& aListener
)
3360 throw (uno::RuntimeException
)
3362 // like ScCellRangesBase::addModifyListener
3363 SolarMutexGuard aGuard
;
3364 if (!m_pTokens
.get() || m_pTokens
->empty())
3367 ScRangeList aRanges
;
3368 ScRefTokenHelper::getRangeListFromTokens(aRanges
, *m_pTokens
, ScAddress());
3369 uno::Reference
<util::XModifyListener
> *pObj
=
3370 new uno::Reference
<util::XModifyListener
>( aListener
);
3371 m_aValueListeners
.push_back( pObj
);
3373 if ( m_aValueListeners
.size() == 1 )
3375 if (!m_pValueListener
)
3376 m_pValueListener
= new ScLinkListener( LINK( this, ScChart2DataSequence
, ValueListenerHdl
) );
3378 if (!m_pHiddenListener
.get())
3379 m_pHiddenListener
.reset(new HiddenRangeListener(*this));
3383 ScChartListenerCollection
* pCLC
= m_pDocument
->GetChartListenerCollection();
3384 vector
<ScTokenRef
>::const_iterator itr
= m_pTokens
->begin(), itrEnd
= m_pTokens
->end();
3385 for (; itr
!= itrEnd
; ++itr
)
3388 if (!ScRefTokenHelper::getRangeFromToken(aRange
, *itr
, ScAddress()))
3391 m_pDocument
->StartListeningArea( aRange
, m_pValueListener
);
3393 pCLC
->StartListeningHiddenRange(aRange
, m_pHiddenListener
.get());
3397 acquire(); // don't lose this object (one ref for all listeners)
3401 void SAL_CALL
ScChart2DataSequence::removeModifyListener( const uno::Reference
< util::XModifyListener
>& aListener
)
3402 throw (uno::RuntimeException
)
3404 // like ScCellRangesBase::removeModifyListener
3406 SolarMutexGuard aGuard
;
3407 if (!m_pTokens
.get() || m_pTokens
->empty())
3410 acquire(); // in case the listeners have the last ref - released below
3412 sal_uInt16 nCount
= m_aValueListeners
.size();
3413 for ( sal_uInt16 n
=nCount
; n
--; )
3415 uno::Reference
<util::XModifyListener
>& rObj
= m_aValueListeners
[n
];
3416 if ( rObj
== aListener
)
3418 m_aValueListeners
.erase( m_aValueListeners
.begin() + n
);
3420 if ( m_aValueListeners
.empty() )
3422 if (m_pValueListener
)
3423 m_pValueListener
->EndListeningAll();
3425 if (m_pHiddenListener
.get() && m_pDocument
)
3427 ScChartListenerCollection
* pCLC
= m_pDocument
->GetChartListenerCollection();
3429 pCLC
->EndListeningHiddenRange(m_pHiddenListener
.get());
3432 release(); // release the ref for the listeners
3439 release(); // might delete this object
3442 // DataSequence XPropertySet -------------------------------------------------
3444 uno::Reference
< beans::XPropertySetInfo
> SAL_CALL
3445 ScChart2DataSequence::getPropertySetInfo() throw( uno::RuntimeException
)
3447 SolarMutexGuard aGuard
;
3448 static uno::Reference
<beans::XPropertySetInfo
> aRef
=
3449 new SfxItemPropertySetInfo( m_aPropSet
.getPropertyMap() );
3454 void SAL_CALL
ScChart2DataSequence::setPropertyValue(
3455 const OUString
& rPropertyName
, const uno::Any
& rValue
)
3456 throw( beans::UnknownPropertyException
,
3457 beans::PropertyVetoException
,
3458 lang::IllegalArgumentException
,
3459 lang::WrappedTargetException
, uno::RuntimeException
)
3461 if ( rPropertyName
== SC_UNONAME_ROLE
)
3463 if ( !(rValue
>>= m_aRole
))
3464 throw lang::IllegalArgumentException();
3466 else if ( rPropertyName
== SC_UNONAME_INCLUDEHIDDENCELLS
)
3468 sal_Bool bOldValue
= m_bIncludeHiddenCells
;
3469 if ( !(rValue
>>= m_bIncludeHiddenCells
))
3470 throw lang::IllegalArgumentException();
3471 if( bOldValue
!= m_bIncludeHiddenCells
)
3472 m_aDataArray
.clear();//data array is dirty now
3475 throw beans::UnknownPropertyException();
3476 // TODO: support optional properties
3480 uno::Any SAL_CALL
ScChart2DataSequence::getPropertyValue(
3481 const OUString
& rPropertyName
)
3482 throw( beans::UnknownPropertyException
,
3483 lang::WrappedTargetException
, uno::RuntimeException
)
3486 if ( rPropertyName
== SC_UNONAME_ROLE
)
3488 else if ( rPropertyName
== SC_UNONAME_INCLUDEHIDDENCELLS
)
3489 aRet
<<= m_bIncludeHiddenCells
;
3490 else if ( rPropertyName
== SC_UNONAME_HIDDENVALUES
)
3492 // This property is read-only thus cannot be set externally via
3493 // setPropertyValue(...).
3495 aRet
<<= m_aHiddenValues
;
3498 throw beans::UnknownPropertyException();
3499 // TODO: support optional properties
3504 void SAL_CALL
ScChart2DataSequence::addPropertyChangeListener(
3505 const OUString
& /*rPropertyName*/,
3506 const uno::Reference
< beans::XPropertyChangeListener
>& /*xListener*/)
3507 throw( beans::UnknownPropertyException
,
3508 lang::WrappedTargetException
, uno::RuntimeException
)
3510 // FIXME: real implementation
3511 OSL_FAIL( "Not yet implemented" );
3515 void SAL_CALL
ScChart2DataSequence::removePropertyChangeListener(
3516 const OUString
& /*rPropertyName*/,
3517 const uno::Reference
< beans::XPropertyChangeListener
>& /*rListener*/)
3518 throw( beans::UnknownPropertyException
,
3519 lang::WrappedTargetException
, uno::RuntimeException
)
3521 // FIXME: real implementation
3522 OSL_FAIL( "Not yet implemented" );
3526 void SAL_CALL
ScChart2DataSequence::addVetoableChangeListener(
3527 const OUString
& /*rPropertyName*/,
3528 const uno::Reference
< beans::XVetoableChangeListener
>& /*rListener*/)
3529 throw( beans::UnknownPropertyException
,
3530 lang::WrappedTargetException
, uno::RuntimeException
)
3532 // FIXME: real implementation
3533 OSL_FAIL( "Not yet implemented" );
3537 void SAL_CALL
ScChart2DataSequence::removeVetoableChangeListener(
3538 const OUString
& /*rPropertyName*/,
3539 const uno::Reference
< beans::XVetoableChangeListener
>& /*rListener*/)
3540 throw( beans::UnknownPropertyException
,
3541 lang::WrappedTargetException
, uno::RuntimeException
)
3543 // FIXME: real implementation
3544 OSL_FAIL( "Not yet implemented" );
3547 void ScChart2DataSequence::setDataChangedHint(bool b
)
3549 m_bGotDataChangedHint
= b
;
3552 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */