Display special first/last date names correctly.

This commit is contained in:
Kohei Yoshida 2012-03-06 01:38:14 -05:00 committed by Kohei Yoshida
parent c2f8b7a17e
commit 5e7daf4ab9
16 changed files with 206 additions and 92 deletions

View file

@ -106,6 +106,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
sc/source/core/data/dpdimsave \
sc/source/core/data/dpgroup \
sc/source/core/data/dpitemdata \
sc/source/core/data/dpnumgroupinfo \
sc/source/core/data/dpobject \
sc/source/core/data/dpoutput \
sc/source/core/data/dpoutputgeometry \

View file

@ -36,23 +36,11 @@
#include "dptabdat.hxx"
#include "scdllapi.h"
#include "dpitemdata.hxx"
#include "dpnumgroupinfo.hxx"
class ScDocument;
class SvNumberFormatter;
struct ScDPNumGroupInfo
{
bool mbEnable:1;
bool mbDateValues:1;
bool mbAutoStart:1;
bool mbAutoEnd:1;
double mfStart;
double mfEnd;
double mfStep;
SC_DLLPUBLIC ScDPNumGroupInfo();
};
// ScDPDateGroupHelper is used as part of ScDPGroupDimension (additional dim.)
// or ScDPNumGroupDimension (innermost, replaces the original dim.).
// Source index, name and result collection are stored at the parent.

View file

@ -51,6 +51,9 @@ class SC_DLLPUBLIC ScDPItemData
public:
enum Type { GroupValue = 0, Value = 1, String = 2, Error = 3, Empty = 4 };
static const sal_Int32 DateFirst;
static const sal_Int32 DateLast;
struct GroupValueAttr
{
sal_Int32 mnGroupType;

49
sc/inc/dpnumgroupinfo.hxx Normal file
View file

@ -0,0 +1,49 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* Version: MPL 1.1 / GPLv3+ / LGPLv3+
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License or as specified alternatively below. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* Major Contributor(s):
* Copyright (C) 2012 Kohei Yoshida <kohei.yoshida@suse.com>
*
* All Rights Reserved.
*
* For minor contributions see the git repository.
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 3 or later (the "GPLv3+"), or
* the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
* in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
* instead of those above.
*/
#ifndef __SC_DPNUMGROUPINFO_HXX__
#define __SC_DPNUMGROUPINFO_HXX__
#include "scdllapi.h"
struct ScDPNumGroupInfo
{
bool mbEnable:1;
bool mbDateValues:1;
bool mbAutoStart:1;
bool mbAutoEnd:1;
double mfStart;
double mfEnd;
double mfStep;
SC_DLLPUBLIC ScDPNumGroupInfo();
};
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View file

@ -128,7 +128,6 @@ public:
ScDPTableData(ScDocument* pDoc);
virtual ~ScDPTableData();
rtl::OUString GetFormattedString(const ScDPItemData& rItem) const;
rtl::OUString GetFormattedString(long nDim, const ScDPItemData& rItem) const;
long GetDatePart( long nDateVal, long nHierarchy, long nLevel );

View file

@ -45,8 +45,8 @@
struct ScQueryParam;
class ScDPObject;
class ScDPItemDataPool;
class ScDPItemData;
struct ScDPNumGroupInfo;
/**
* This class represents the cached data part of the datapilot cache table
@ -63,6 +63,11 @@ public:
struct GroupItems : boost::noncopyable
{
DataListType maItems;
double mfStart;
double mfEnd;
GroupItems();
GroupItems(const ScDPNumGroupInfo& rInfo);
};
struct Field : boost::noncopyable
@ -107,13 +112,8 @@ private:
*/
mutable ObjectSetType maRefObjects;
struct GroupField : boost::noncopyable
{
DataListType maItems; /// Unique values in the field.
};
typedef boost::ptr_vector<Field> FieldsType;
typedef boost::ptr_vector<GroupField> GroupFieldsType;
typedef boost::ptr_vector<GroupItems> GroupFieldsType;
FieldsType maFields;
GroupFieldsType maGroupFields;
@ -130,10 +130,9 @@ public:
SCROW GetIdByItemData(long nDim, const rtl::OUString& sItemData) const;
SCROW GetIdByItemData(long nDim, const ScDPItemData& rItem) const;
rtl::OUString GetFormattedString(const ScDPItemData& rItem) const;
rtl::OUString GetFormattedString(long nDim, const ScDPItemData& rItem) const;
void AppendGroupField();
void ResetGroupItems(long nDim);
void ResetGroupItems(long nDim, const ScDPNumGroupInfo& rNumInfo);
SCROW SetGroupItem(long nDim, const ScDPItemData& rData);
void ClearGroupFields();
@ -172,6 +171,7 @@ private:
void Clear();
void AddLabel(const rtl::OUString& rLabel);
bool AddData(long nDim, ScDPItemData* pData, sal_uLong nNumFormat);
const GroupItems* GetGroupItems(long nDim) const;
};
#endif

View file

@ -758,6 +758,7 @@ public:
bool IsNamedItem(SCROW nIndex) const;
SC_DLLPUBLIC const ::rtl::OUString* GetLayoutName() const;
long GetDim() const;
sal_Int32 Compare( const ScDPMember& rOther ) const; // visible order

View file

@ -44,7 +44,8 @@ public:
static rtl::OUString createDuplicateDimensionName(const rtl::OUString& rOriginal, size_t nDupCount);
static rtl::OUString getDateGroupName(
sal_Int32 nDatePart, sal_Int32 nValue, SvNumberFormatter* pFormatter);
sal_Int32 nDatePart, sal_Int32 nValue, SvNumberFormatter* pFormatter,
double fStart, double fEnd);
};
#endif

View file

@ -110,14 +110,6 @@ private:
const sal_uInt16 SC_DP_LEAPYEAR = 1648; // arbitrary leap year for date calculations
// part values for the extra "<" and ">" entries (same for all parts)
const sal_Int32 SC_DP_DATE_FIRST = -1;
const sal_Int32 SC_DP_DATE_LAST = 10000;
ScDPNumGroupInfo::ScDPNumGroupInfo() :
mbEnable(false), mbDateValues(false), mbAutoStart(false), mbAutoEnd(false),
mfStart(0.0), mfEnd(0.0), mfStep(0.0) {}
namespace {
sal_Bool lcl_Search( SCCOL nSourceDim, const ScDPCache* pCache , const std::vector< SCROW >& vIdx, SCROW nNew , SCROW& rIndex)
@ -355,10 +347,10 @@ bool ScDPGroupDateFilter::match( const ScDPItemData & rCellData ) const
// is included, while an end date with a time value is not.)
if ( rCellData.GetValue() < mpNumInfo->mfStart && !approxEqual(rCellData.GetValue(), mpNumInfo->mfStart) )
return static_cast<sal_Int32>(mfMatchValue) == SC_DP_DATE_FIRST;
return static_cast<sal_Int32>(mfMatchValue) == ScDPItemData::DateFirst;
if ( rCellData.GetValue() > mpNumInfo->mfEnd && !approxEqual(rCellData.GetValue(), mpNumInfo->mfEnd) )
return static_cast<sal_Int32>(mfMatchValue) == SC_DP_DATE_LAST;
return static_cast<sal_Int32>(mfMatchValue) == ScDPItemData::DateLast;
if (mnDatePart == DataPilotFieldGroupBy::HOURS || mnDatePart == DataPilotFieldGroupBy::MINUTES ||
mnDatePart == DataPilotFieldGroupBy::SECONDS)
@ -459,9 +451,9 @@ sal_Int32 lcl_GetDatePartValue( double fValue, sal_Int32 nDatePart, SvNumberForm
if ( pNumInfo )
{
if ( fValue < pNumInfo->mfStart && !rtl::math::approxEqual( fValue, pNumInfo->mfStart ) )
return SC_DP_DATE_FIRST;
return ScDPItemData::DateFirst;
if ( fValue > pNumInfo->mfEnd && !rtl::math::approxEqual( fValue, pNumInfo->mfEnd ) )
return SC_DP_DATE_LAST;
return ScDPItemData::DateLast;
}
sal_Int32 nResult = 0;
@ -522,14 +514,6 @@ sal_Int32 lcl_GetDatePartValue( double fValue, sal_Int32 nDatePart, SvNumberForm
return nResult;
}
String lcl_GetSpecialDateName( double fValue, bool bFirst, SvNumberFormatter* pFormatter )
{
rtl::OUStringBuffer aBuffer;
aBuffer.append((sal_Unicode)( bFirst ? '<' : '>' ));
lcl_AppendDateStr( aBuffer, fValue, pFormatter );
return aBuffer.makeStringAndClear();
}
bool isDateInGroup(const ScDPItemData& rGroupItem, const ScDPItemData& rChildItem)
{
stack_printer __stack_printer__("::isDateInGroup");
@ -544,8 +528,8 @@ bool isDateInGroup(const ScDPItemData& rGroupItem, const ScDPItemData& rChildIte
fprintf(stdout, "isDateInGroup: group part = %d group values = %d child part = %d child value = %d\n",
nGroupPart, nGroupValue, nChildPart, nChildValue);
if (nGroupValue == SC_DP_DATE_FIRST || nGroupValue == SC_DP_DATE_LAST ||
nChildValue == SC_DP_DATE_FIRST || nChildValue == SC_DP_DATE_LAST)
if (nGroupValue == ScDPItemData::DateFirst || nGroupValue == ScDPItemData::DateLast ||
nChildValue == ScDPItemData::DateFirst || nChildValue == ScDPItemData::DateLast)
{
// first/last entry matches only itself
return nGroupValue == nChildValue;
@ -652,30 +636,21 @@ void ScDPDateGroupHelper::FillColumnEntries(
OSL_FAIL("invalid date part");
}
pCache->ResetGroupItems(mnGroupDim);
pCache->ResetGroupItems(mnGroupDim, aNumInfo);
fprintf(stdout, "ScDPDateGroupHelper::FillColumnEntries: source dim = %d group dim = %d\n",
nSourceDim, mnGroupDim);
for ( sal_Int32 nValue = nStart; nValue <= nEnd; nValue++ )
{
rtl::OUString aName = ScDPUtil::getDateGroupName( nDatePart, nValue, pFormatter );
fprintf(stdout, "ScDPDateGroupHelper::FillColumnEntries: name = '%s'\n",
rtl::OUStringToOString(aName, RTL_TEXTENCODING_UTF8).getStr());
SCROW nId = pCache->SetGroupItem(mnGroupDim, ScDPItemData(nDatePart, nValue));
rEntries.push_back(nId);
}
// add first/last entry (min/max)
rtl::OUString aFirstName = lcl_GetSpecialDateName( aNumInfo.mfStart, true, pFormatter );
fprintf(stdout, "ScDPDateGroupHelper::FillColumnEntries: first = '%s'\n",
rtl::OUStringToOString(aFirstName, RTL_TEXTENCODING_UTF8).getStr());
SCROW nId = pCache->SetGroupItem(mnGroupDim, ScDPItemData(nDatePart, SC_DP_DATE_LAST));
SCROW nId = pCache->SetGroupItem(mnGroupDim, ScDPItemData(nDatePart, ScDPItemData::DateFirst));
rEntries.push_back(nId);
rtl::OUString aLastName = lcl_GetSpecialDateName( aNumInfo.mfEnd, false, pFormatter );
fprintf(stdout, "ScDPDateGroupHelper::FillColumnEntries: last = '%s'\n",
rtl::OUStringToOString(aLastName, RTL_TEXTENCODING_UTF8).getStr());
nId = pCache->SetGroupItem(mnGroupDim, ScDPItemData(nDatePart, SC_DP_DATE_LAST));
nId = pCache->SetGroupItem(mnGroupDim, ScDPItemData(nDatePart, ScDPItemData::DateLast));
rEntries.push_back(nId);
std::vector<SCROW>::const_iterator it = rEntries.begin(), itEnd = rEntries.end();
@ -1396,10 +1371,12 @@ void ScDPGroupTableData::FillGroupValues(SCROW* pItemDataIndex, long nCount, con
if ( pData ->IsValue() )
{
SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
const ScDPNumGroupInfo& rNumInfo = pDateHelper->GetNumInfo();
sal_Int32 nPartValue = lcl_GetDatePartValue(
pData->GetValue(), pDateHelper->GetDatePart(), pFormatter,
&pDateHelper->GetNumInfo() );
rtl::OUString aName = ScDPUtil::getDateGroupName(pDateHelper->GetDatePart(), nPartValue, pFormatter);
&rNumInfo);
rtl::OUString aName = ScDPUtil::getDateGroupName(
pDateHelper->GetDatePart(), nPartValue, pFormatter, rNumInfo.mfStart, rNumInfo.mfEnd);
fprintf(stdout, "ScDPGroupTableData::FillGroupValues: column = %d source dim = %d group by = %d value = %d name = '%s'\n",
nColumn, nSourceDim,
pDateHelper->GetDatePart(), nPartValue,

View file

@ -34,6 +34,9 @@
#include "globstr.hrc"
#include "dptabdat.hxx"
const sal_Int32 ScDPItemData::DateFirst = -1;
const sal_Int32 ScDPItemData::DateLast = 10000;
sal_Int32 ScDPItemData::Compare(const ScDPItemData& rA, const ScDPItemData& rB)
{
if (rA.meType != rB.meType)

View file

@ -0,0 +1,35 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* Version: MPL 1.1 / GPLv3+ / LGPLv3+
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License or as specified alternatively below. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* Major Contributor(s):
* Copyright (C) 2012 Kohei Yoshida <kohei.yoshida@suse.com>
*
* All Rights Reserved.
*
* For minor contributions see the git repository.
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 3 or later (the "GPLv3+"), or
* the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
* in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
* instead of those above.
*/
#include "dpnumgroupinfo.hxx"
ScDPNumGroupInfo::ScDPNumGroupInfo() :
mbEnable(false), mbDateValues(false), mbAutoStart(false), mbAutoEnd(false),
mfStart(0.0), mfEnd(0.0), mfStep(0.0) {}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View file

@ -73,12 +73,6 @@ ScDPTableData::~ScDPTableData()
{
}
rtl::OUString ScDPTableData::GetFormattedString(const ScDPItemData& rItem) const
{
const ScDPCache* pCache = GetCacheTable().getCache();
return pCache->GetFormattedString(rItem);
}
rtl::OUString ScDPTableData::GetFormattedString(long nDim, const ScDPItemData& rItem) const
{
const ScDPCache* pCache = GetCacheTable().getCache();

View file

@ -38,6 +38,7 @@
#include "docoptio.hxx"
#include "dpitemdata.hxx"
#include "dputil.hxx"
#include "dpnumgroupinfo.hxx"
#include <rtl/math.hxx>
#include <unotools/textsearch.hxx>
@ -220,9 +221,11 @@ ScDPItemData* lcl_GetItemValue(
}
// -----------------------------------------------------------------------
//class ScDPTableDataCache
//To cache the pivot table data source
ScDPCache::GroupItems::GroupItems() :
mfStart(0.0), mfEnd(0.0) {}
ScDPCache::GroupItems::GroupItems(const ScDPNumGroupInfo& rInfo) :
mfStart(rInfo.mfStart), mfEnd(rInfo.mfEnd) {}
bool ScDPCache::operator== ( const ScDPCache& r ) const
{
@ -694,6 +697,21 @@ bool ScDPCache::AddData(long nDim, ScDPItemData* pData, sal_uLong nNumFormat)
return true;
}
const ScDPCache::GroupItems* ScDPCache::GetGroupItems(long nDim) const
{
if (nDim < 0)
return NULL;
long nSourceCount = static_cast<long>(maFields.size());
if (nDim < nSourceCount)
return maFields[nDim].mpGroup.get();
nDim -= nSourceCount;
if (nDim < static_cast<long>(maGroupFields.size()))
return &maGroupFields[nDim];
return NULL;
}
rtl::OUString ScDPCache::GetDimensionName( sal_uInt16 nColumn ) const
{
@ -1018,21 +1036,13 @@ SCROW ScDPCache::GetIdByItemData(long nDim, const ScDPItemData& rItem) const
return -1;
}
rtl::OUString ScDPCache::GetFormattedString(const ScDPItemData& rItem) const
{
if (rItem.GetType() == ScDPItemData::GroupValue)
{
ScDPItemData::GroupValueAttr aAttr = rItem.GetGroupValue();
return ScDPUtil::getDateGroupName(
aAttr.mnGroupType, aAttr.mnValue, mpDoc->GetFormatTable());
}
return rItem.GetString();
}
rtl::OUString ScDPCache::GetFormattedString(long nDim, const ScDPItemData& rItem) const
{
if (rItem.IsValue())
if (nDim < 0)
return rItem.GetString();
ScDPItemData::Type eType = rItem.GetType();
if (eType == ScDPItemData::Value)
{
// Format value using the stored number format.
sal_uLong nNumFormat = GetNumberFormat(nDim);
@ -1046,15 +1056,29 @@ rtl::OUString ScDPCache::GetFormattedString(long nDim, const ScDPItemData& rItem
}
}
return GetFormattedString(rItem);
if (eType == ScDPItemData::GroupValue)
{
ScDPItemData::GroupValueAttr aAttr = rItem.GetGroupValue();
double fStart = 0.0, fEnd = 0.0;
const GroupItems* p = GetGroupItems(nDim);
if (p)
{
fStart = p->mfStart;
fEnd = p->mfEnd;
}
return ScDPUtil::getDateGroupName(
aAttr.mnGroupType, aAttr.mnValue, mpDoc->GetFormatTable(), fStart, fEnd);
}
return rItem.GetString();
}
void ScDPCache::AppendGroupField()
{
maGroupFields.push_back(new GroupField);
maGroupFields.push_back(new GroupItems);
}
void ScDPCache::ResetGroupItems(long nDim)
void ScDPCache::ResetGroupItems(long nDim, const ScDPNumGroupInfo& rNumInfo)
{
if (nDim < 0)
return;
@ -1062,13 +1086,18 @@ void ScDPCache::ResetGroupItems(long nDim)
long nSourceCount = static_cast<long>(maFields.size());
if (nDim < nSourceCount)
{
maFields.at(nDim).mpGroup.reset(new GroupItems);
maFields.at(nDim).mpGroup.reset(new GroupItems(rNumInfo));
return;
}
nDim -= nSourceCount;
if (nDim < static_cast<long>(maGroupFields.size()))
maGroupFields[nDim].maItems.clear();
{
GroupItems& rGI = maGroupFields[nDim];
rGI.maItems.clear();
rGI.mfStart = rNumInfo.mfStart;
rGI.mfEnd = rNumInfo.mfEnd;
}
}
SCROW ScDPCache::SetGroupItem(long nDim, const ScDPItemData& rData)

View file

@ -1439,7 +1439,13 @@ void ScDPResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pS
aName = pResultData->GetSource()->GetData()->GetFormattedString(nDim, aItemData);
}
else
aName = pResultData->GetSource()->GetData()->GetFormattedString(aItemData);
{
long nDim = -1;
const ScDPMember* pMem = GetDPMember();
if (pMem)
nDim = pMem->GetDim();
aName = pResultData->GetSource()->GetData()->GetFormattedString(nDim, aItemData);
}
ScDPItemData::Type eType = aItemData.GetType();
bIsNumeric = eType == ScDPItemData::Value || ScDPItemData::GroupValue;

View file

@ -2625,9 +2625,14 @@ const OUString* ScDPMember::GetLayoutName() const
return mpLayoutName.get();
}
long ScDPMember::GetDim() const
{
return nDim;
}
rtl::OUString ScDPMember::GetNameStr() const
{
return pSource->GetData()->GetFormattedString(GetItemData());
return pSource->GetData()->GetFormattedString(nDim, GetItemData());
}
::rtl::OUString SAL_CALL ScDPMember::getName() throw(uno::RuntimeException)

View file

@ -28,6 +28,7 @@
#include "dputil.hxx"
#include "global.hxx"
#include "dpitemdata.hxx"
#include "comphelper/string.hxx"
#include "unotools/localedatawrapper.hxx"
@ -43,7 +44,7 @@ namespace {
const sal_uInt16 SC_DP_LEAPYEAR = 1648; // arbitrary leap year for date calculations
String getTwoDigitString( sal_Int32 nValue )
rtl::OUString getTwoDigitString(sal_Int32 nValue)
{
String aRet = String::CreateFromInt32( nValue );
if ( aRet.Len() < 2 )
@ -51,6 +52,22 @@ String getTwoDigitString( sal_Int32 nValue )
return aRet;
}
void appendDateStr(rtl::OUStringBuffer& rBuffer, double fValue, SvNumberFormatter* pFormatter)
{
sal_uLong nFormat = pFormatter->GetStandardFormat( NUMBERFORMAT_DATE, ScGlobal::eLnge );
rtl::OUString aString;
pFormatter->GetInputLineString(fValue, nFormat, aString);
rBuffer.append(aString);
}
rtl::OUString getSpecialDateName(double fValue, bool bFirst, SvNumberFormatter* pFormatter)
{
rtl::OUStringBuffer aBuffer;
aBuffer.append(sal_Unicode(bFirst ? '<' : '>'));
appendDateStr(aBuffer, fValue, pFormatter);
return aBuffer.makeStringAndClear();
}
}
bool ScDPUtil::isDuplicateDimension(const rtl::OUString& rName)
@ -80,8 +97,14 @@ rtl::OUString ScDPUtil::createDuplicateDimensionName(const rtl::OUString& rOrigi
}
rtl::OUString ScDPUtil::getDateGroupName(
sal_Int32 nDatePart, sal_Int32 nValue, SvNumberFormatter* pFormatter)
sal_Int32 nDatePart, sal_Int32 nValue, SvNumberFormatter* pFormatter,
double fStart, double fEnd)
{
if (nValue == ScDPItemData::DateFirst)
return getSpecialDateName(fStart, true, pFormatter);
if (nValue == ScDPItemData::DateLast)
return getSpecialDateName(fEnd, false, pFormatter);
switch ( nDatePart )
{
case sheet::DataPilotFieldGroupBy::YEARS:
@ -122,7 +145,7 @@ rtl::OUString ScDPUtil::getDateGroupName(
OSL_FAIL("invalid date part");
}
return rtl::OUString();
return rtl::OUString::createFromAscii("FIXME: unhandled value");
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */