26 #include <osl/diagnose.h>
30 #include <document.hxx>
34 #include <globstr.hrc>
35 #include <stlpool.hxx>
36 #include <stlsheet.hxx>
38 #include <unonames.hxx>
39 #include <strings.hrc>
43 #include <com/sun/star/beans/XPropertySet.hpp>
44 #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
45 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
46 #include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
47 #include <com/sun/star/sheet/DataPilotTableResultData.hpp>
48 #include <com/sun/star/sheet/MemberResultFlags.hpp>
49 #include <com/sun/star/sheet/DataResultFlags.hpp>
50 #include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
51 #include <com/sun/star/sheet/GeneralFunction2.hpp>
52 #include <com/sun/star/sheet/MemberResult.hpp>
53 #include <com/sun/star/sheet/XDataPilotMemberResults.hpp>
54 #include <com/sun/star/sheet/XDataPilotResults.hpp>
55 #include <com/sun/star/sheet/XDimensionsSupplier.hpp>
56 #include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
57 #include <com/sun/star/sheet/XLevelsSupplier.hpp>
58 #include <com/sun/star/sheet/XMembersAccess.hpp>
59 #include <com/sun/star/sheet/XMembersSupplier.hpp>
61 #include <string_view>
66 using ::com::sun::star::beans::XPropertySet;
67 using ::com::sun::star::uno::Sequence;
68 using ::com::sun::star::uno::UNO_QUERY;
69 using ::com::sun::star::uno::Reference;
70 using ::com::sun::star::sheet::DataPilotTablePositionData;
71 using ::com::sun::star::sheet::DataPilotTableResultData;
73 #define SC_DP_FRAME_INNER_BOLD 20
74 #define SC_DP_FRAME_OUTER_BOLD 40
76 #define SC_DP_FRAME_COLOR Color(0,0,0) //( 0x20, 0x40, 0x68 )
88 bool mbHasHiddenMember:1;
93 const OUString &aName,
const OUString &aCaption,
bool bHasHiddenMember,
bool bDataLayout,
bool bPageDim) :
94 mnDim(nDim), mnHier(nHier), mnLevel(nLevel), mnDimPos(nDimPos), mnSrcNumFmt(nSrcNumFmt), maResult(aResult),
95 maName(aName), maCaption(aCaption), mbHasHiddenMember(bHasHiddenMember), mbDataLayout(bDataLayout),
106 struct ScDPOutLevelDataComparator
120 ::std::vector< bool > mbNeedLineCols;
121 ::std::vector< SCCOL > mnCols;
123 ::std::vector< bool > mbNeedLineRows;
124 ::std::vector< SCROW > mnRows;
129 SCCOL mnDataStartCol;
130 SCROW mnDataStartRow;
135 ScDPOutputImpl(
ScDocument* pDoc, sal_uInt16 nTab,
142 bool AddRow(
SCROW nRow );
143 bool AddCol(
SCCOL nCol );
145 void OutputDataArea();
146 void OutputBlockFrame (
SCCOL nStartCol,
SCROW nStartRow,
SCCOL nEndCol,
SCROW nEndRow,
bool bHori =
false );
150 void ScDPOutputImpl::OutputDataArea()
152 AddRow( mnDataStartRow );
153 AddCol( mnDataStartCol );
155 mnCols.push_back( mnTabEndCol+1);
156 mnRows.push_back( mnTabEndRow+1);
158 bool bAllRows = ( ( mnTabEndRow - mnDataStartRow + 2 ) == static_cast<SCROW>(mnRows.size()) );
160 std::sort( mnCols.begin(), mnCols.end());
161 std::sort( mnRows.begin(), mnRows.end());
163 for(
SCCOL nCol = 0; nCol < static_cast<SCCOL>(mnCols.size())-1; nCol ++ )
167 if ( nCol < static_cast<SCCOL>(mnCols.size())-2)
169 for (
SCROW i = nCol%2; i < static_cast<SCROW>(mnRows.size())-2;
i +=2 )
170 OutputBlockFrame( mnCols[nCol], mnRows[i], mnCols[nCol+1]-1, mnRows[i+1]-1 );
171 if ( mnRows.size()>=2 )
172 OutputBlockFrame( mnCols[nCol], mnRows[mnRows.size()-2], mnCols[nCol+1]-1, mnRows[mnRows.size()-1]-1 );
176 for (
SCROW i = 0 ; i < static_cast<SCROW>(mnRows.size())-1; i++ )
177 OutputBlockFrame( mnCols[nCol], mnRows[i], mnCols[nCol+1]-1, mnRows[i+1]-1 );
181 OutputBlockFrame( mnCols[nCol], mnRows.front(), mnCols[nCol+1]-1, mnRows.back()-1, bAllRows );
184 if ( mnTabStartCol != mnDataStartCol )
186 if ( mnTabStartRow != mnDataStartRow )
187 OutputBlockFrame( mnTabStartCol, mnTabStartRow, mnDataStartCol-1, mnDataStartRow-1 );
188 OutputBlockFrame( mnTabStartCol, mnDataStartRow, mnDataStartCol-1, mnTabEndRow );
191 OutputBlockFrame( mnDataStartCol, mnTabStartRow, mnTabEndCol, mnDataStartRow-1 );
194 ScDPOutputImpl::ScDPOutputImpl(
ScDocument* pDoc, sal_uInt16 nTab,
203 mnTabStartCol( nTabStartCol ),
204 mnTabStartRow( nTabStartRow ),
205 mnDataStartCol ( nDataStartCol ),
206 mnDataStartRow ( nDataStartRow ),
207 mnTabEndCol( nTabEndCol ),
208 mnTabEndRow( nTabEndRow )
210 mbNeedLineCols.resize( nTabEndCol-nDataStartCol+1,
false );
211 mbNeedLineRows.resize( nTabEndRow-nDataStartRow+1,
false );
215 bool ScDPOutputImpl::AddRow(
SCROW nRow )
217 if ( !mbNeedLineRows[ nRow - mnDataStartRow ] )
219 mbNeedLineRows[ nRow - mnDataStartRow ] =
true;
220 mnRows.push_back( nRow );
227 bool ScDPOutputImpl::AddCol(
SCCOL nCol )
230 if ( !mbNeedLineCols[ nCol - mnDataStartCol ] )
232 mbNeedLineCols[ nCol - mnDataStartCol ] =
true;
233 mnCols.push_back( nCol );
240 void ScDPOutputImpl::OutputBlockFrame (
SCCOL nStartCol,
SCROW nStartRow,
SCCOL nEndCol,
SCROW nEndRow,
bool bHori )
248 if ( nStartCol == mnTabStartCol )
249 aBox.SetLine(&aOutLine, SvxBoxItemLine::LEFT);
251 aBox.SetLine(&aLine, SvxBoxItemLine::LEFT);
253 if ( nStartRow == mnTabStartRow )
254 aBox.SetLine(&aOutLine, SvxBoxItemLine::TOP);
256 aBox.SetLine(&aLine, SvxBoxItemLine::TOP);
258 if ( nEndCol == mnTabEndCol )
259 aBox.SetLine(&aOutLine, SvxBoxItemLine::RIGHT);
261 aBox.SetLine(&aLine, SvxBoxItemLine::RIGHT);
263 if ( nEndRow == mnTabEndRow )
264 aBox.SetLine(&aOutLine, SvxBoxItemLine::BOTTOM);
266 aBox.SetLine(&aLine, SvxBoxItemLine::BOTTOM);
269 aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::VERT,
false );
272 aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::HORI);
273 aBoxInfo.SetLine( &aLine, SvxBoxInfoItemLine::HORI );
276 aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::HORI,
false );
278 aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::DISTANCE,
false);
280 mpDoc->ApplyFrameAreaTab(
ScRange(nStartCol, nStartRow, mnTab, nEndCol, nEndRow , mnTab), aBox, aBoxInfo);
288 if ( nCol1 > nCol2 || nRow1 > nRow2 )
290 OSL_FAIL(
"SetStyleById: invalid range");
294 OUString aStyleName =
ScResId(pStrId);
301 pStyle =
static_cast<ScStyleSheet*
>( &pStlPool->
Make( aStyleName, SfxStyleFamily::Para,
302 SfxStyleSearchBits::UserDefined ) );
305 if (strcmp(pStrId, STR_PIVOT_STYLENAME_RESULT) == 0 || strcmp(pStrId, STR_PIVOT_STYLENAME_TITLE) == 0){
310 if (strcmp(pStrId, STR_PIVOT_STYLENAME_CATEGORY) == 0 || strcmp(pStrId, STR_PIVOT_STYLENAME_TITLE) == 0)
323 aBox.SetLine(&aLine, SvxBoxItemLine::LEFT);
324 aBox.SetLine(&aLine, SvxBoxItemLine::TOP);
325 aBox.SetLine(&aLine, SvxBoxItemLine::RIGHT);
326 aBox.SetLine(&aLine, SvxBoxItemLine::BOTTOM);
328 aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::HORI,
false);
329 aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::VERT,
false);
330 aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::DISTANCE,
false);
335 void lcl_FillNumberFormats( std::unique_ptr<sal_uInt32[]>& rFormats, sal_Int32& rCount,
336 const uno::Reference<sheet::XDataPilotMemberResults>& xLevRes,
337 const uno::Reference<container::XIndexAccess>& xDims )
345 uno::Sequence<sheet::MemberResult> aResult = xLevRes->getResults();
354 std::vector <OUString> aDataNames;
355 std::vector <sal_uInt32> aDataFormats;
358 for ( ; nDim < nDimCount ; nDim++)
360 uno::Reference<uno::XInterface> xDim(xDims->getByIndex(nDim), uno::UNO_QUERY);
361 uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
362 uno::Reference<container::XNamed> xDimName( xDim, uno::UNO_QUERY );
363 if ( xDimProp.is() && xDimName.is() )
365 sheet::DataPilotFieldOrientation eDimOrient =
368 sheet::DataPilotFieldOrientation_HIDDEN );
369 if ( eDimOrient == sheet::DataPilotFieldOrientation_DATA )
371 aDataNames.push_back(xDimName->getName());
375 aDataFormats.push_back(nFormat);
380 if (aDataFormats.empty())
383 const sheet::MemberResult* pArray = aResult.getConstArray();
386 sal_uInt32* pNumFmt =
new sal_uInt32[nSize];
387 if (aDataFormats.size() == 1)
392 pNumFmt[nPos] = nFormat;
400 if ( !(pArray[nPos].
Flags & sheet::MemberResultFlags::CONTINUE) )
401 aName = pArray[nPos].Name;
403 sal_uInt32 nFormat = 0;
404 for (
size_t i=0; i<aDataFormats.size(); i++)
405 if (aName == aDataNames[i])
407 nFormat = aDataFormats[i];
410 pNumFmt[
nPos] = nFormat;
414 rFormats.reset( pNumFmt );
418 sal_uInt32 lcl_GetFirstNumberFormat(
const uno::Reference<container::XIndexAccess>& xDims )
423 uno::Reference<beans::XPropertySet> xDimProp(xDims->getByIndex(nDim), uno::UNO_QUERY);
426 sheet::DataPilotFieldOrientation eDimOrient =
429 sheet::DataPilotFieldOrientation_HIDDEN );
430 if ( eDimOrient == sheet::DataPilotFieldOrientation_DATA )
444 bool lcl_MemberEmpty(
const uno::Sequence<sheet::MemberResult>& rSeq )
448 return std::none_of(rSeq.begin(), rSeq.end(),
449 [](
const sheet::MemberResult& rMem) {
450 return rMem.Flags & sheet::MemberResultFlags::HASMEMBER; });
457 uno::Sequence<sheet::MemberResult> getVisiblePageMembersAsResults(
const uno::Reference<uno::XInterface>& xLevel )
460 return uno::Sequence<sheet::MemberResult>();
462 uno::Reference<sheet::XMembersSupplier> xMSupplier(xLevel, UNO_QUERY);
463 if (!xMSupplier.is())
464 return uno::Sequence<sheet::MemberResult>();
466 uno::Reference<sheet::XMembersAccess> xNA = xMSupplier->getMembers();
468 return uno::Sequence<sheet::MemberResult>();
470 std::vector<sheet::MemberResult> aRes;
471 const uno::Sequence<OUString> aNames = xNA->getElementNames();
472 for (
const OUString& rName : aNames)
474 xNA->getByName(rName);
476 uno::Reference<beans::XPropertySet> xMemPS(xNA->getByName(rName), UNO_QUERY);
481 if (aCaption.isEmpty())
490 rtl::math::setNan(&fValue);
491 aRes.emplace_back(rName, aCaption, 0, fValue);
495 if (aNames.getLength() ==
static_cast<sal_Int32
>(aRes.size()))
497 return uno::Sequence<sheet::MemberResult>();
516 bResultsError(false),
518 bSizeOverflow(false),
519 mbHeaderLayout(false)
524 uno::Reference<sheet::XDataPilotResults> xResult(
xSource, uno::UNO_QUERY );
525 if (
xSource.is() && xResult.is() )
529 uno::Reference<container::XIndexAccess> xDims =
534 uno::Reference<uno::XInterface> xDim(xDims->getByIndex(nDim), uno::UNO_QUERY);
535 uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
536 uno::Reference<sheet::XHierarchiesSupplier> xDimSupp( xDim, uno::UNO_QUERY );
537 if ( xDimProp.is() && xDimSupp.is() )
539 sheet::DataPilotFieldOrientation eDimOrient =
542 sheet::DataPilotFieldOrientation_HIDDEN );
552 if ( eDimOrient != sheet::DataPilotFieldOrientation_HIDDEN )
554 uno::Reference<container::XIndexAccess> xHiers =
559 if ( nHierarchy >= xHiers->getCount() )
562 uno::Reference<sheet::XLevelsSupplier> xHierSupp(xHiers->getByIndex(nHierarchy),
564 if ( xHierSupp.is() )
566 uno::Reference<container::XIndexAccess> xLevels =
571 uno::Reference<uno::XInterface> xLevel(xLevels->getByIndex(nLev),
573 uno::Reference<container::XNamed> xLevNam( xLevel, uno::UNO_QUERY );
574 uno::Reference<sheet::XDataPilotMemberResults> xLevRes(
575 xLevel, uno::UNO_QUERY );
576 if ( xLevNam.is() && xLevRes.is() )
578 OUString aName = xLevNam->getName();
586 switch ( eDimOrient )
588 case sheet::DataPilotFieldOrientation_COLUMN:
590 uno::Sequence<sheet::MemberResult> aResult = xLevRes->getResults();
591 if (!lcl_MemberEmpty(aResult))
593 ScDPOutLevelData tmp(nDim, nHierarchy, nLev, nDimPos, nNumFmt, aResult, aName,
594 aCaption, bHasHiddenMember, bIsDataLayout,
false);
599 case sheet::DataPilotFieldOrientation_ROW:
601 uno::Sequence<sheet::MemberResult> aResult = xLevRes->getResults();
602 if (!lcl_MemberEmpty(aResult))
604 ScDPOutLevelData tmp(nDim, nHierarchy, nLev, nDimPos, nNumFmt, aResult, aName,
605 aCaption, bHasHiddenMember, bIsDataLayout,
false);
610 case sheet::DataPilotFieldOrientation_PAGE:
612 uno::Sequence<sheet::MemberResult> aResult = getVisiblePageMembersAsResults(xLevel);
614 ScDPOutLevelData tmp(nDim, nHierarchy, nLev, nDimPos, nNumFmt, aResult, aName,
615 aCaption, bHasHiddenMember,
false,
true);
628 OSL_ENSURE( nLevCount == 1,
"data layout: multiple levels?" );
629 if ( eDimOrient == sheet::DataPilotFieldOrientation_COLUMN )
631 else if ( eDimOrient == sheet::DataPilotFieldOrientation_ROW )
638 else if ( bIsDataLayout )
655 aData = xResult->getResults();
657 catch (
const uno::RuntimeException&)
665 uno::Reference<beans::XPropertySet> xSrcProp(
xSource, uno::UNO_QUERY );
666 if ( !xSrcProp.is() )
676 catch(
const uno::Exception&)
694 if ( nFlags & sheet::DataResultFlags::ERROR )
696 pDoc->
SetError( nCol, nRow, nTab, FormulaError::NoValue );
698 else if ( nFlags & sheet::DataResultFlags::HASDATA )
700 pDoc->
SetValue( nCol, nRow, nTab, rData.Value );
704 OSL_ENSURE(
bSizesValid,
"DataCell: !bSizesValid" );
705 sal_uInt32 nFormat = 0;
706 bool bApplyFormat =
false;
709 if ( nCol >= nDataStartCol )
721 if ( nRow >= nDataStartRow )
744 const sheet::MemberResult& rData,
bool bColHeader,
tools::Long nLevel )
748 if ( nFlags & sheet::MemberResultFlags::HASMEMBER )
750 bool bNumeric = (nFlags & sheet::MemberResultFlags::NUMERIC) != 0;
751 if (bNumeric && std::isfinite( rData.Value))
753 pDoc->
SetValue( nCol, nRow, nTab, rData.Value);
763 pDoc->
SetString(nCol, nRow, nTab, rData.Caption, &aParam);
767 if ( !(nFlags & sheet::MemberResultFlags::SUBTOTAL) )
770 ScDPOutputImpl outputimp( pDoc, nTab,
771 nTabStartCol, nTabStartRow,
772 nDataStartCol, nDataStartRow, nTabEndCol, nTabEndRow );
776 outputimp.OutputBlockFrame( nCol,
nMemberStartRow+static_cast<SCROW>(nLevel), nCol,nDataStartRow-1 );
778 lcl_SetStyleById( pDoc,nTab, nCol,
nMemberStartRow+static_cast<SCROW>(nLevel), nCol,nDataStartRow-1,
779 STR_PIVOT_STYLENAME_TITLE );
780 lcl_SetStyleById( pDoc,nTab, nCol,nDataStartRow, nCol,nTabEndRow,
781 STR_PIVOT_STYLENAME_RESULT );
785 outputimp.OutputBlockFrame(
nMemberStartCol+static_cast<SCCOL>(nLevel),nRow, nDataStartCol-1,nRow );
786 lcl_SetStyleById( pDoc,nTab,
nMemberStartCol+static_cast<SCCOL>(nLevel),nRow, nDataStartCol-1,nRow,
787 STR_PIVOT_STYLENAME_TITLE );
788 lcl_SetStyleById( pDoc,nTab, nDataStartCol,nRow, nTabEndCol,nRow,
789 STR_PIVOT_STYLENAME_RESULT );
804 lcl_SetFrame( pDoc,nTab, nCol,nRow, nCol,nRow, 20 );
815 pDoc->
ApplyFlagsTab(nCol+1, nRow, nCol+1, nRow, nTab, nMergeFlag);
822 pDoc->
ApplyFlagsTab(nCol, nRow, nCol, nRow, nTab, nMergeFlag);
825 lcl_SetStyleById( pDoc,nTab, nCol,nRow, nCol,nRow, STR_PIVOT_STYLENAME_FIELDNAME );
843 const uno::Sequence<sheet::DataResult>* pRowAry =
aData.getConstArray();
878 if ( !
pPageFields.empty() && nTabEndCol < nTabStartCol + 1 )
879 nTabEndCol = nTabStartCol + 1;
895 return DataPilotTablePositionType::NOT_IN_TABLE;
900 if (nCol < nTabStartCol || nRow < nTabStartRow || nCol > nTabEndCol || nRow > nTabEndRow)
901 return DataPilotTablePositionType::NOT_IN_TABLE;
904 if (nCol >= nDataStartCol && nCol <= nTabEndCol && nRow >= nDataStartRow && nRow <= nTabEndRow)
905 return DataPilotTablePositionType::RESULT;
907 bool bInColHeader = (nRow >= nTabStartRow && nRow <
nDataStartRow);
908 bool bInRowHeader = (nCol >= nTabStartCol && nCol <
nDataStartCol);
910 if (bInColHeader && bInRowHeader)
912 return DataPilotTablePositionType::OTHER;
916 if (nRow == nTabStartRow)
919 return DataPilotTablePositionType::OTHER;
927 return DataPilotTablePositionType::OTHER;
933 const uno::Sequence<sheet::DataResult>* pRowAry =
aData.getConstArray();
951 for (
size_t nField=0; nField<
pPageFields.size(); ++nField)
957 SCCOL nFldCol = nHdrCol + 1;
959 OUString aPageValue =
ScResId(SCSTR_ALL);
960 const uno::Sequence<sheet::MemberResult>& rRes =
pPageFields[nField].maResult;
961 sal_Int32
n = rRes.getLength();
964 if (rRes[0].Caption.isEmpty())
965 aPageValue =
ScResId(STR_EMPTYDATA);
967 aPageValue = rRes[0].Caption;
970 aPageValue =
ScResId(SCSTR_MULTIPLE);
974 pDoc->
SetString(nFldCol, nHdrRow, nTab, aPageValue, &aParam);
976 lcl_SetFrame( pDoc,nTab, nFldCol,nHdrRow, nFldCol,nHdrRow, 20 );
990 if ( nDataStartRow > nTabStartRow )
991 lcl_SetStyleById( pDoc, nTab, nTabStartCol, nTabStartRow, nTabEndCol, nDataStartRow-1,
992 STR_PIVOT_STYLENAME_TOP );
993 lcl_SetStyleById( pDoc, nTab, nDataStartCol, nDataStartRow, nTabEndCol, nTabEndRow,
994 STR_PIVOT_STYLENAME_INNER );
997 ScDPOutputImpl outputimp( pDoc, nTab,
998 nTabStartCol, nTabStartRow,
999 nDataStartCol, nDataStartRow, nTabEndCol, nTabEndRow );
1000 for (
size_t nField=0; nField<
pColFields.size(); nField++)
1002 SCCOL nHdrCol = nDataStartCol +
static_cast<SCCOL>(nField);
1006 const uno::Sequence<sheet::MemberResult> rSequence =
pColFields[nField].maResult;
1007 const sheet::MemberResult* pArray = rSequence.getConstArray();
1008 tools::Long nThisColCount = rSequence.getLength();
1009 OSL_ENSURE( nThisColCount ==
nColCount,
"count mismatch" );
1010 for (
tools::Long nCol=0; nCol<nThisColCount; nCol++)
1012 SCCOL nColPos = nDataStartCol +
static_cast<SCCOL>(nCol);
1013 HeaderCell( nColPos, nRowPos, nTab, pArray[nCol],
true, nField );
1014 if ( ( pArray[nCol].
Flags & sheet::MemberResultFlags::HASMEMBER ) &&
1015 !( pArray[nCol].
Flags & sheet::MemberResultFlags::SUBTOTAL ) )
1018 while ( nEnd+1 < nThisColCount && ( pArray[nEnd+1].
Flags & sheet::MemberResultFlags::CONTINUE ) )
1020 SCCOL nEndColPos = nDataStartCol +
static_cast<SCCOL>(nEnd);
1025 outputimp.AddCol( nColPos );
1026 if ( nColPos + 1 == nEndColPos )
1027 outputimp.OutputBlockFrame( nColPos,nRowPos, nEndColPos,nRowPos+1,
true );
1030 outputimp.OutputBlockFrame( nColPos,nRowPos, nEndColPos,nRowPos );
1032 lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nEndColPos,nDataStartRow-1, STR_PIVOT_STYLENAME_CATEGORY );
1035 lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nColPos,nDataStartRow-1, STR_PIVOT_STYLENAME_CATEGORY );
1037 else if ( pArray[nCol].
Flags & sheet::MemberResultFlags::SUBTOTAL )
1038 outputimp.AddCol( nColPos );
1044 outputimp.OutputBlockFrame( nDataStartCol,nTabStartRow, nTabEndCol,nRowPos-1 );
1048 std::vector<bool> vbSetBorder;
1049 vbSetBorder.resize( nTabEndRow - nDataStartRow + 1,
false );
1050 for (
size_t nField=0; nField<
pRowFields.size(); nField++)
1052 SCCOL nHdrCol = nTabStartCol +
static_cast<SCCOL>(nField);
1053 SCROW nHdrRow = nDataStartRow - 1;
1057 const uno::Sequence<sheet::MemberResult> rSequence =
pRowFields[nField].maResult;
1058 const sheet::MemberResult* pArray = rSequence.getConstArray();
1059 sal_Int32 nThisRowCount = rSequence.getLength();
1060 OSL_ENSURE( nThisRowCount ==
nRowCount,
"count mismatch" );
1061 for (sal_Int32 nRow=0; nRow<nThisRowCount; nRow++)
1063 SCROW nRowPos = nDataStartRow +
static_cast<SCROW>(nRow);
1064 HeaderCell( nColPos, nRowPos, nTab, pArray[nRow],
false, nField );
1065 if ( ( pArray[nRow].
Flags & sheet::MemberResultFlags::HASMEMBER ) &&
1066 !( pArray[nRow].
Flags & sheet::MemberResultFlags::SUBTOTAL ) )
1071 while ( nEnd+1 < nThisRowCount && ( pArray[nEnd+1].
Flags & sheet::MemberResultFlags::CONTINUE ) )
1073 SCROW nEndRowPos = nDataStartRow +
static_cast<SCROW>(nEnd);
1074 outputimp.AddRow( nRowPos );
1075 if ( !vbSetBorder[ nRow ] )
1077 outputimp.OutputBlockFrame( nColPos, nRowPos, nTabEndCol, nEndRowPos );
1078 vbSetBorder[ nRow ] =
true;
1080 outputimp.OutputBlockFrame( nColPos, nRowPos, nColPos, nEndRowPos );
1083 outputimp.OutputBlockFrame( nColPos+1, nRowPos, nColPos+1, nEndRowPos );
1085 lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nDataStartCol-1,nEndRowPos, STR_PIVOT_STYLENAME_CATEGORY );
1088 lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nDataStartCol-1,nRowPos, STR_PIVOT_STYLENAME_CATEGORY );
1090 else if ( pArray[nRow].
Flags & sheet::MemberResultFlags::SUBTOTAL )
1091 outputimp.AddRow( nRowPos );
1109 for (sal_Int32 nRow=0; nRow<
nRowCount; nRow++)
1111 SCROW nRowPos = nDataStartRow +
static_cast<SCROW>(nRow);
1112 const sheet::DataResult* pColAry = pRowAry[nRow].getConstArray();
1113 sal_Int32 nThisColCount = pRowAry[nRow].getLength();
1114 OSL_ENSURE( nThisColCount ==
nColCount,
"count mismatch" );
1115 for (sal_Int32 nCol=0; nCol<nThisColCount; nCol++)
1117 SCCOL nColPos = nDataStartCol +
static_cast<SCCOL>(nCol);
1118 DataCell( nColPos, nRowPos, nTab, pColAry[nCol] );
1122 outputimp.OutputDataArea();
1132 switch (nRegionType)
1134 case DataPilotOutputRangeType::RESULT:
1135 return ScRange(nDataStartCol, nDataStartRow, nTab, nTabEndCol, nTabEndRow, nTab);
1139 OSL_ENSURE(nRegionType == DataPilotOutputRangeType::WHOLE,
"ScDPOutput::GetOutputRange: unknown region type");
1159 void insertNames(
ScDPUniqueStringSet& rNames,
const uno::Sequence<sheet::MemberResult>& rMemberResults)
1161 for (
const sheet::MemberResult& rMemberResult : rMemberResults)
1163 if (rMemberResult.Flags & sheet::MemberResultFlags::HASMEMBER)
1164 rNames.insert(rMemberResult.Name);
1175 auto lFindDimension = [nDimension](
const ScDPOutLevelData& rField) {
return rField.mnDim == nDimension; };
1182 insertNames(rNames, colit->maResult);
1191 insertNames(rNames, rowit->maResult);
1203 void lcl_GetTableVars( sal_Int32& rGrandTotalCols, sal_Int32& rGrandTotalRows, sal_Int32& rDataLayoutIndex,
1204 std::vector<OUString>& rDataNames, std::vector<OUString>& rGivenNames,
1205 sheet::DataPilotFieldOrientation& rDataOrient,
1206 const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1208 rDataLayoutIndex = -1;
1209 rGrandTotalCols = 0;
1210 rGrandTotalRows = 0;
1211 rDataOrient = sheet::DataPilotFieldOrientation_HIDDEN;
1213 uno::Reference<beans::XPropertySet> xSrcProp( xSource, uno::UNO_QUERY );
1217 rGrandTotalCols = 1;
1222 rGrandTotalRows = 1;
1224 if ( !xSource.is() )
1229 sal_Int32 nDataCount = 0;
1231 uno::Reference<container::XIndexAccess> xDims =
new ScNameToIndexAccess( xSource->getDimensions() );
1235 uno::Reference<uno::XInterface> xDim(xDims->getByIndex(nDim), uno::UNO_QUERY);
1236 uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
1237 if ( xDimProp.is() )
1239 sheet::DataPilotFieldOrientation eDimOrient =
1242 sheet::DataPilotFieldOrientation_HIDDEN );
1246 rDataLayoutIndex = nDim;
1247 rDataOrient = eDimOrient;
1249 if ( eDimOrient == sheet::DataPilotFieldOrientation_DATA )
1251 OUString aSourceName;
1252 OUString aGivenName;
1260 OUString strLayoutName;
1262 if( ( aValue >>= strLayoutName ) && !strLayoutName.isEmpty() )
1263 aGivenName = strLayoutName;
1266 catch(
const uno::Exception&)
1269 rDataNames.push_back( aSourceName );
1270 rGivenNames.push_back( aGivenName );
1277 if ( ( rDataOrient == sheet::DataPilotFieldOrientation_COLUMN ) && bColGrand )
1278 rGrandTotalCols = nDataCount;
1279 else if ( ( rDataOrient == sheet::DataPilotFieldOrientation_ROW ) && bRowGrand )
1280 rGrandTotalRows = nDataCount;
1300 switch (rPosData.PositionType)
1302 case DataPilotTablePositionType::RESULT:
1304 vector<DataPilotFieldFilter> aFilters;
1306 sal_Int32 nSize = aFilters.size();
1308 DataPilotTableResultData aResData;
1309 aResData.FieldFilters.realloc(nSize);
1310 for (sal_Int32 i = 0; i < nSize; ++i)
1311 aResData.FieldFilters[i] = aFilters[i];
1313 aResData.DataFieldIndex = 0;
1319 if (nDataFieldCount > 0)
1320 aResData.DataFieldIndex = (nRow -
nDataStartRow) % nDataFieldCount;
1324 if (
aData.getLength() > nRow - nDataStartRow &&
1326 aResData.Result =
aData[nRow-nDataStartRow][nCol-nDataStartCol];
1328 rPosData.PositionData <<= aResData;
1337 const uno::Sequence<sheet::MemberResult> rSequence =
pColFields[nField].maResult;
1338 if (!rSequence.hasElements())
1340 const sheet::MemberResult* pArray = rSequence.getConstArray();
1344 while (nItem > 0 && ( pArray[nItem].
Flags & sheet::MemberResultFlags::CONTINUE) )
1350 DataPilotTableHeaderData aHeaderData;
1351 aHeaderData.MemberName = pArray[nItem].Name;
1352 aHeaderData.Flags = pArray[nItem].Flags;
1353 aHeaderData.Dimension =
static_cast<sal_Int32
>(
pColFields[nField].mnDim);
1354 aHeaderData.Hierarchy =
static_cast<sal_Int32
>(
pColFields[nField].mnHier);
1355 aHeaderData.Level =
static_cast<sal_Int32
>(
pColFields[nField].mnLevel);
1357 rPosData.PositionData <<= aHeaderData;
1366 const uno::Sequence<sheet::MemberResult> rSequence =
pRowFields[nField].maResult;
1367 if (!rSequence.hasElements())
1369 const sheet::MemberResult* pArray = rSequence.getConstArray();
1373 while ( nItem > 0 && (pArray[nItem].
Flags & sheet::MemberResultFlags::CONTINUE) )
1379 DataPilotTableHeaderData aHeaderData;
1380 aHeaderData.MemberName = pArray[nItem].Name;
1381 aHeaderData.Flags = pArray[nItem].Flags;
1382 aHeaderData.Dimension =
static_cast<sal_Int32
>(
pRowFields[nField].mnDim);
1383 aHeaderData.Hierarchy =
static_cast<sal_Int32
>(
pRowFields[nField].mnHier);
1384 aHeaderData.Level =
static_cast<sal_Int32
>(
pRowFields[nField].mnLevel);
1386 rPosData.PositionData <<= aHeaderData;
1401 if (nDataFieldCount == 0)
1406 sal_Int32 nGrandTotalCols;
1407 sal_Int32 nGrandTotalRows;
1408 sal_Int32 nDataLayoutIndex;
1409 std::vector<OUString> aDataNames;
1410 std::vector<OUString> aGivenNames;
1411 sheet::DataPilotFieldOrientation eDataOrient;
1412 lcl_GetTableVars( nGrandTotalCols, nGrandTotalRows, nDataLayoutIndex, aDataNames, aGivenNames, eDataOrient, xSource );
1423 if (nCol < nDataStartCol || nCol > nTabEndCol || nRow < nDataStartRow || nRow > nTabEndRow)
1429 bool bFilterByCol = (nCol <= static_cast<SCCOL>(nTabEndCol - nGrandTotalCols));
1430 bool bFilterByRow = (nRow <= static_cast<SCROW>(nTabEndRow - nGrandTotalRows));
1433 for (
size_t nColField = 0; nColField <
pColFields.size() && bFilterByCol; ++nColField)
1435 if (
pColFields[nColField].mnDim == nDataLayoutIndex)
1439 sheet::DataPilotFieldFilter
filter;
1440 filter.FieldName =
pColFields[nColField].maName;
1442 const uno::Sequence<sheet::MemberResult> rSequence =
pColFields[nColField].maResult;
1443 const sheet::MemberResult* pArray = rSequence.getConstArray();
1445 OSL_ENSURE(nDataStartCol + rSequence.getLength() - 1 ==
nTabEndCol,
"ScDPOutput::GetDataFieldCellData: error in geometric assumption");
1449 while ( nItem > 0 && (pArray[nItem].
Flags & sheet::MemberResultFlags::CONTINUE) )
1452 filter.MatchValueName = pArray[nItem].Name;
1453 rFilters.push_back(filter);
1457 for (
size_t nRowField = 0; nRowField <
pRowFields.size() && bFilterByRow; ++nRowField)
1459 if (
pRowFields[nRowField].mnDim == nDataLayoutIndex)
1463 sheet::DataPilotFieldFilter
filter;
1464 filter.FieldName =
pRowFields[nRowField].maName;
1466 const uno::Sequence<sheet::MemberResult> rSequence =
pRowFields[nRowField].maResult;
1467 const sheet::MemberResult* pArray = rSequence.getConstArray();
1469 OSL_ENSURE(nDataStartRow + rSequence.getLength() - 1 ==
nTabEndRow,
"ScDPOutput::GetDataFieldCellData: error in geometric assumption");
1473 while ( nItem > 0 && (pArray[nItem].
Flags & sheet::MemberResultFlags::CONTINUE) )
1476 filter.MatchValueName = pArray[nItem].Name;
1477 rFilters.push_back(filter);
1485 OUString lcl_GetDataFieldName( std::u16string_view rSourceName, sal_Int16 eFunc )
1487 const char* pStrId =
nullptr;
1490 case sheet::GeneralFunction2::SUM: pStrId = STR_FUN_TEXT_SUM;
break;
1492 case sheet::GeneralFunction2::COUNTNUMS: pStrId = STR_FUN_TEXT_COUNT;
break;
1493 case sheet::GeneralFunction2::AVERAGE: pStrId = STR_FUN_TEXT_AVG;
break;
1494 case sheet::GeneralFunction2::MEDIAN: pStrId = STR_FUN_TEXT_MEDIAN;
break;
1495 case sheet::GeneralFunction2::MAX: pStrId = STR_FUN_TEXT_MAX;
break;
1496 case sheet::GeneralFunction2::MIN: pStrId = STR_FUN_TEXT_MIN;
break;
1497 case sheet::GeneralFunction2::PRODUCT: pStrId = STR_FUN_TEXT_PRODUCT;
break;
1498 case sheet::GeneralFunction2::STDEV:
1499 case sheet::GeneralFunction2::STDEVP: pStrId = STR_FUN_TEXT_STDDEV;
break;
1500 case sheet::GeneralFunction2::VAR:
1501 case sheet::GeneralFunction2::VARP: pStrId = STR_FUN_TEXT_VAR;
break;
1503 case sheet::GeneralFunction2::AUTO:
break;
1512 return ScResId(pStrId) +
" - " + rSourceName;
1518 OUString& rSourceName, OUString& rGivenName,
const uno::Reference<uno::XInterface>& xDim )
1520 uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
1521 uno::Reference<container::XNamed> xDimName( xDim, uno::UNO_QUERY );
1522 if ( !(xDimProp.is() && xDimName.is()) )
1535 rGivenName = lcl_GetDataFieldName( rSourceName, eFunc );
1566 rOrient = sheet::DataPilotFieldOrientation_COLUMN;
1575 rOrient = sheet::DataPilotFieldOrientation_ROW;
1585 rOrient = sheet::DataPilotFieldOrientation_PAGE;
1592 rOrient = sheet::DataPilotFieldOrientation_HIDDEN;
1614 if ( nCol >= nDataStartCol && nCol <= nTabEndCol &&
1626 nTabEndCol, nMemberStartRow + nField -1 );
1628 bool bFound =
false;
1629 bool bBeforeDrag =
false;
1630 bool bAfterDrag =
false;
1636 if ( nField <
nPos )
1638 else if ( nField >
nPos )
1662 rOrient = sheet::DataPilotFieldOrientation_COLUMN;
1670 bool bSpecial = ( nRow+1 >= nDataStartRow && nRow <= nTabEndRow &&
1671 pRowFields.empty() && nCol == nTabStartCol && bMouseLeft );
1673 if ( bSpecial || ( nRow+1 >= nDataStartRow && nRow <= nTabEndRow &&
1680 nTabStartCol + nField - 1, nTabEndRow );
1682 bool bFound =
false;
1683 bool bBeforeDrag =
false;
1684 bool bAfterDrag =
false;
1690 if ( nField <
nPos )
1692 else if ( nField >
nPos )
1716 rOrient = sheet::DataPilotFieldOrientation_ROW;
1738 bool bFound =
false;
1739 bool bBeforeDrag =
false;
1740 bool bAfterDrag =
false;
1746 if ( nField <
nPos )
1748 else if ( nField >
nPos )
1772 rOrient = sheet::DataPilotFieldOrientation_PAGE;
constexpr TypedWhichId< SvxWeightItem > ATTR_CTL_FONT_WEIGHT(118)
virtual sal_Int32 SAL_CALL getCount() override
SC_DLLPUBLIC void ApplyStyleAreaTab(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScStyleSheet &rStyle)
Store parameters used in the ScDocument::SetString() method.
bool mbHandleApostrophe
When true, treat input with a leading apostrophe as an escape character for a numeric value content...
constexpr TypedWhichId< SvxBoxItem > ATTR_BORDER(150)
virtual bool SetParent(const OUString &rParentName) override
static sal_Int32 GetLongProperty(const css::uno::Reference< css::beans::XPropertySet > &xProp, const OUString &rName)
#define SC_DP_FRAME_INNER_BOLD
void setTextInput()
Call this whenever you need to unconditionally set input as text, no matter what the input is...
static css::uno::Sequence< ValueType > VectorToSequence(const std::vector< ValueType > &rVector)
static void GetDataDimensionNames(OUString &rSourceName, OUString &rGivenName, const css::uno::Reference< css::uno::XInterface > &xDim)
#define SC_DP_FRAME_OUTER_BOLD
ScDPOutLevelData(tools::Long nDim, tools::Long nHier, tools::Long nLevel, tools::Long nDimPos, sal_uInt32 nSrcNumFmt, const uno::Sequence< sheet::MemberResult > &aResult, const OUString &aName, const OUString &aCaption, bool bHasHiddenMember, bool bDataLayout, bool bPageDim)
void GetMemberResultNames(ScDPUniqueStringSet &rNames, tools::Long nDimension)
#define SC_UNO_DP_COLGRAND
SC_DLLPUBLIC bool ApplyFlagsTab(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, ScMF nFlags)
bool mbHasHiddenMember
Caption is the name visible in the output table.
#define SC_DP_FRAME_COLOR
constexpr TypedWhichId< SvxBoxInfoItem > ATTR_BORDER_INNER(151)
static EnumT GetEnumProperty(const css::uno::Reference< css::beans::XPropertySet > &xProp, const OUString &rName, EnumT nDefault)
SC_DLLPUBLIC void SetValue(SCCOL nCol, SCROW nRow, SCTAB nTab, const double &rVal)
#define SC_UNO_DP_POSITION
static OUString GetStringProperty(const css::uno::Reference< css::beans::XPropertySet > &xProp, const OUString &rName, const OUString &rDefault)
SC_DLLPUBLIC void ApplyAttr(SCCOL nCol, SCROW nRow, SCTAB nTab, const SfxPoolItem &rAttr)
css::uno::Sequence< css::uno::Sequence< css::sheet::DataResult > > aData
sal_Int32 GetPositionType(const ScAddress &rPos)
Query which sub-area of the table the cell is in.
bool GetDataResultPositionData(::std::vector< css::sheet::DataPilotFieldFilter > &rFilters, const ScAddress &rPos)
Get filtering criteria based on the position of the cell within data field region.
TextFormatPolicy meSetTextNumFormat
Determine when to set the 'Text' number format to the cell where the input string is being set...
std::unique_ptr< sal_uInt32[]> pRowNumFmt
#define SC_UNO_DP_LAYOUTNAME
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
uno::Sequence< sheet::MemberResult > maResult
Prevailing number format used in the source data.
std::vector< ScDPOutLevelData > pPageFields
bool GetHeaderDrag(const ScAddress &rPos, bool bMouseLeft, bool bMouseTop, tools::Long nDragDim, tools::Rectangle &rPosRect, css::sheet::DataPilotFieldOrientation &rOrient, tools::Long &rDimPos)
void SetError(SCCOL nCol, SCROW nRow, SCTAB nTab, const FormulaError nError)
ScRange GetOutputRange(sal_Int32 nRegionType=css::sheet::DataPilotOutputRangeType::WHOLE)
Refresh?
static void lcl_DoFilterButton(ScDocument *pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab)
css::uno::Reference< css::sheet::XDimensionsSupplier > xSource
tools::Long GetHeaderDim(const ScAddress &rPos, css::sheet::DataPilotFieldOrientation &rOrient)
std::vector< ScDPOutLevelData > pRowFields
SC_DLLPUBLIC bool SetString(SCCOL nCol, SCROW nRow, SCTAB nTab, const OUString &rString, const ScSetStringParam *pParam=nullptr)
dp button with popup arrow
void ApplyFrameAreaTab(const ScRange &rRange, const SvxBoxItem &rLineOuter, const SvxBoxInfoItem &rLineInner)
#define SC_UNO_DP_FUNCTION2
ScDPOutput(ScDocument *pD, const css::uno::Reference< css::sheet::XDimensionsSupplier > &xSrc, const ScAddress &rPos, bool bFilter)
void HeaderCell(SCCOL nCol, SCROW nRow, SCTAB nTab, const css::sheet::MemberResult &rData, bool bColHeader, tools::Long nLevel)
void SetHeaderLayout(bool bUseGrid)
static SC_DLLPUBLIC OUString getSourceDimensionName(const OUString &rName)
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
static bool GetBoolProperty(const css::uno::Reference< css::beans::XPropertySet > &xProp, const OUString &rName, bool bDefault=false)
sal_Int32 GetHeaderRows() const
std::vector< ScDPOutLevelData > pColFields
OUString ScResId(const char *pId)
OUString maCaption
Name is the internal field name.
constexpr TypedWhichId< SfxUInt32Item > ATTR_VALUE_FORMAT(146)
void GetPositionData(const ScAddress &rPos, css::sheet::DataPilotTablePositionData &rPosData)
void FieldCell(SCCOL nCol, SCROW nRow, SCTAB nTab, const ScDPOutLevelData &rData, bool bInTable)
#define SC_UNO_DP_HAS_HIDDEN_MEMBER
#define SC_UNO_DP_ROWGRAND
#define SC_UNO_DP_DATAFIELDCOUNT
#define SC_UNO_DP_ORIENTATION
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
bool mbDetectNumberFormat
When true, we try to detect special number format (dates etc) from the input string, when false, we only try to detect a basic decimal number format.
#define SC_UNO_DP_USEDHIERARCHY
void SetPosition(const ScAddress &rPos)
#define SC_UNO_DP_DATADESC
std::unordered_set< OUString > ScDPUniqueStringSet
#define SC_UNONAME_NUMFMT
void DataCell(SCCOL nCol, SCROW nRow, SCTAB nTab, const css::sheet::DataResult &rData)
virtual SfxStyleSheetBase & Make(const OUString &, SfxStyleFamily eFam, SfxStyleSearchBits nMask=SfxStyleSearchBits::All) override
#define SC_UNO_DP_ISVISIBLE
OUString aDataDescription
virtual SC_DLLPUBLIC SfxItemSet & GetItemSet() override
constexpr TypedWhichId< SvxWeightItem > ATTR_FONT_WEIGHT(102)
constexpr TypedWhichId< SvxHorJustifyItem > ATTR_HOR_JUSTIFY(129)
bool GetHeaderLayout() const
static sal_Int16 GetShortProperty(const css::uno::Reference< css::beans::XPropertySet > &xProp, const OUString &rName, sal_Int16 nDefault)
Set Text number format if the input string can be parsed as a number or formula text.
SC_DLLPUBLIC ScStyleSheetPool * GetStyleSheetPool() const
#define SC_UNO_DP_ISDATALAYOUT
void setNumericInput()
Call this whenever you need to maximize the chance of input being detected as a numeric value (number...
SC_DLLPUBLIC void DeleteAreaTab(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab, InsertDeleteFlags nDelFlag)
virtual SfxStyleSheetBase * Find(const OUString &, SfxStyleFamily eFam, SfxStyleSearchBits n=SfxStyleSearchBits::All)
constexpr TypedWhichId< SvxWeightItem > ATTR_CJK_FONT_WEIGHT(113)
bool IsFilterButton(const ScAddress &rPos)
#define SC_UNO_DP_NUMBERFO
std::unique_ptr< sal_uInt32[]> pColNumFmt