diff options
author | Kohei Yoshida <kyoshida@novell.com> | 2010-06-15 05:33:03 +0200 |
---|---|---|
committer | Kohei Yoshida <kyoshida@novell.com> | 2010-06-15 05:33:03 +0200 |
commit | 90d71fa312796762f2a346f92932fa2c74cefbe1 (patch) | |
tree | 2326f5e91d04bb96f3861c5a3d74b95ef48d8a64 /sc/source | |
parent | a2a6891094cfa791ded8abb514cb8581ad0748b3 (diff) | |
parent | 5729138f6f974939f75ce5f9c4191f3d6680a22b (diff) |
calctabcolor: rebased to DEV300_m82.
Diffstat (limited to 'sc/source')
113 files changed, 3195 insertions, 2651 deletions
diff --git a/sc/source/core/data/cell.cxx b/sc/source/core/data/cell.cxx index 56be361f6d38..a70a9b86e186 100644 --- a/sc/source/core/data/cell.cxx +++ b/sc/source/core/data/cell.cxx @@ -819,6 +819,10 @@ ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, cons ScFormulaCell::~ScFormulaCell() { pDocument->RemoveFromFormulaTree( this ); + + if (pDocument->HasExternalRefManager()) + pDocument->GetExternalRefManager()->removeRefCell(this); + delete pCode; #ifdef DBG_UTIL eCellType = CELLTYPE_DESTROYED; diff --git a/sc/source/core/data/cell2.cxx b/sc/source/core/data/cell2.cxx index 9a3670d2a9e0..1aab26acf3aa 100644 --- a/sc/source/core/data/cell2.cxx +++ b/sc/source/core/data/cell2.cxx @@ -996,6 +996,8 @@ void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode, pDocument->RemoveFromFormulaTree( this ); // update formula count delete pCode; pCode = pRangeData->GetCode()->Clone(); + // #i18937# #i110008# call MoveRelWrap, but with the old position + ScCompiler::MoveRelWrap(*pCode, pDocument, aOldPos, pRangeData->GetMaxCol(), pRangeData->GetMaxRow()); ScCompiler aComp2(pDocument, aPos, *pCode); aComp2.SetGrammar(pDocument->GetGrammar()); aComp2.UpdateSharedFormulaReference( eUpdateRefMode, aOldPos, r, @@ -1036,17 +1038,6 @@ void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode, delete pOld; } - - pCode->Reset(); - for ( formula::FormulaToken* t = pCode->GetNextReferenceOrName(); t; t = pCode->GetNextReferenceOrName() ) - { - StackVar sv = t->GetType(); - if (sv == svExternalSingleRef || sv == svExternalDoubleRef || sv == svExternalName) - { - pDocument->GetExternalRefManager()->updateRefCell(aOldPos, aPos, eUpdateRefMode == URM_COPY); - break; - } - } } void ScFormulaCell::UpdateInsertTab(SCTAB nTable) diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index ee670d5ba0ef..6a5fe824197b 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -2100,22 +2100,6 @@ void ScColumn::CalcAfterLoad() } -bool ScColumn::MarkUsedExternalReferences() -{ - bool bAllMarked = false; - if (pItems) - { - for (SCSIZE i = 0; i < nCount && !bAllMarked; ++i) - { - ScBaseCell* pCell = pItems[i].pCell; - if ( pCell->GetCellType() == CELLTYPE_FORMULA ) - bAllMarked = ((ScFormulaCell*)pCell)->MarkUsedExternalReferences(); - } - } - return bAllMarked; -} - - void ScColumn::ResetChanged( SCROW nStartRow, SCROW nEndRow ) { if (pItems) diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 9e3ed1c7ef5e..4c8de67ba271 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -193,6 +193,7 @@ long ScColumn::GetNeededSize( SCROW nRow, OutputDevice* pDev, double nPPT = bWidth ? nPPTX : nPPTY; if (Search(nRow,nIndex)) { + ScBaseCell* pCell = pItems[nIndex].pCell; const ScPatternAttr* pPattern = rOptions.pPattern; if (!pPattern) pPattern = pAttrArray->GetPattern( nRow ); @@ -233,22 +234,26 @@ long ScColumn::GetNeededSize( SCROW nRow, OutputDevice* pDev, else eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&) pPattern->GetItem( ATTR_HOR_JUSTIFY )).GetValue(); - BOOL bBreak; + bool bBreak; if ( eHorJust == SVX_HOR_JUSTIFY_BLOCK ) - bBreak = TRUE; + bBreak = true; else if ( pCondSet && pCondSet->GetItemState(ATTR_LINEBREAK, TRUE, &pCondItem) == SFX_ITEM_SET) bBreak = ((const SfxBoolItem*)pCondItem)->GetValue(); else bBreak = ((const SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue(); + if (pCell->HasValueData()) + // Cell has a value. Disable line break. + bBreak = false; + // get other attributes from pattern and conditional formatting SvxCellOrientation eOrient = pPattern->GetCellOrientation( pCondSet ); BOOL bAsianVertical = ( eOrient == SVX_ORIENTATION_STACKED && ((const SfxBoolItem&)pPattern->GetItem( ATTR_VERTICAL_ASIAN, pCondSet )).GetValue() ); if ( bAsianVertical ) - bBreak = FALSE; + bBreak = false; if ( bWidth && bBreak ) // after determining bAsianVertical (bBreak may be reset) return 0; @@ -300,7 +305,6 @@ long ScColumn::GetNeededSize( SCROW nRow, OutputDevice* pDev, nIndent = ((const SfxUInt16Item&)pPattern->GetItem(ATTR_INDENT)).GetValue(); } - ScBaseCell* pCell = pItems[nIndex].pCell; BYTE nScript = pDocument->GetScriptType( nCol, nRow, nTab, pCell ); if (nScript == 0) nScript = ScGlobal::GetDefaultScriptType(); diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index dc206950b3ea..be7211138c1d 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -1249,7 +1249,7 @@ void ScColumn::StartListeningInArea( SCROW nRow1, SCROW nRow2 ) // TRUE = Zahlformat gesetzt BOOL ScColumn::SetString( SCROW nRow, SCTAB nTabP, const String& rString, formula::FormulaGrammar::AddressConvention eConv, - SvNumberFormatter* pFormatter, bool bDetectNumberFormat ) + SvNumberFormatter* pLangFormatter, bool bDetectNumberFormat ) { BOOL bNumFmtSet = FALSE; if (VALIDROW(nRow)) @@ -1261,8 +1261,11 @@ BOOL ScColumn::SetString( SCROW nRow, SCTAB nTabP, const String& rString, double nVal; sal_uInt32 nIndex, nOldIndex = 0; sal_Unicode cFirstChar; - if (!pFormatter) - pFormatter = pDocument->GetFormatTable(); + // #i110979# If a different NumberFormatter is passed in (pLangFormatter), + // its formats aren't valid in the document. + // Only use the language / LocaleDataWrapper from pLangFormatter, + // always the document's number formatter for IsNumberFormat. + SvNumberFormatter* pFormatter = pDocument->GetFormatTable(); SfxObjectShell* pDocSh = pDocument->GetDocumentShell(); if ( pDocSh ) bIsLoading = pDocSh->IsLoading(); @@ -1337,9 +1340,23 @@ BOOL ScColumn::SetString( SCROW nRow, SCTAB nTabP, const String& rString, if (bDetectNumberFormat) { + if ( pLangFormatter ) + { + // for number detection: valid format index for selected language + nIndex = pFormatter->GetStandardIndex( pLangFormatter->GetLanguage() ); + } + if (!pFormatter->IsNumberFormat(rString, nIndex, nVal)) break; + if ( pLangFormatter ) + { + // convert back to the original language if a built-in format was detected + const SvNumberformat* pOldFormat = pFormatter->GetEntry( nOldIndex ); + if ( pOldFormat ) + nIndex = pFormatter->GetFormatForLanguageIfBuiltIn( nIndex, pOldFormat->GetLanguage() ); + } + pNewCell = new ScValueCell( nVal ); if ( nIndex != nOldIndex) { @@ -1378,7 +1395,8 @@ BOOL ScColumn::SetString( SCROW nRow, SCTAB nTabP, const String& rString, else { // Only check if the string is a regular number. - const LocaleDataWrapper* pLocale = pFormatter->GetLocaleData(); + SvNumberFormatter* pLocaleSource = pLangFormatter ? pLangFormatter : pFormatter; + const LocaleDataWrapper* pLocale = pLocaleSource->GetLocaleData(); if (!pLocale) break; @@ -1467,8 +1485,9 @@ BOOL ScColumn::SetString( SCROW nRow, SCTAB nTabP, const String& rString, } -void ScColumn::GetFilterEntries(SCROW nStartRow, SCROW nEndRow, TypedScStrCollection& rStrings) +void ScColumn::GetFilterEntries(SCROW nStartRow, SCROW nEndRow, TypedScStrCollection& rStrings, bool& rHasDates) { + bool bHasDates = false; SvNumberFormatter* pFormatter = pDocument->GetFormatTable(); String aString; SCROW nRow = 0; @@ -1504,6 +1523,18 @@ void ScColumn::GetFilterEntries(SCROW nStartRow, SCROW nEndRow, TypedScStrCollec nValue = 0.0; } + if (pFormatter) + { + short nType = pFormatter->GetType(nFormat); + if ((nType & NUMBERFORMAT_DATE) && !(nType & NUMBERFORMAT_TIME)) + { + // special case for date values. Disregard the time + // element if the number format is of date type. + nValue = ::rtl::math::approxFloor(nValue); + bHasDates = true; + } + } + pData = new TypedStrData( aString, nValue, SC_STRTYPE_VALUE ); } #if 0 // DR @@ -1522,6 +1553,8 @@ void ScColumn::GetFilterEntries(SCROW nStartRow, SCROW nEndRow, TypedScStrCollec ++nIndex; } + + rHasDates = bHasDates; } // @@ -1905,11 +1938,15 @@ sal_Int32 ScColumn::GetMaxStringLen( SCROW nRowStart, SCROW nRowEnd, CharSet eCh } -xub_StrLen ScColumn::GetMaxNumberStringLen( USHORT& nPrecision, - SCROW nRowStart, SCROW nRowEnd ) const +xub_StrLen ScColumn::GetMaxNumberStringLen( + sal_uInt16& nPrecision, SCROW nRowStart, SCROW nRowEnd ) const { xub_StrLen nStringLen = 0; nPrecision = pDocument->GetDocOptions().GetStdPrecision(); + if ( nPrecision == SvNumberFormatter::UNLIMITED_PRECISION ) + // In case of unlimited precision, use 2 instead. + nPrecision = 2; + if ( pItems ) { String aString; @@ -1932,8 +1969,8 @@ xub_StrLen ScColumn::GetMaxNumberStringLen( USHORT& nPrecision, { if ( nFormat ) { // more decimals than standard? - USHORT nPrec = pNumFmt->GetFormatPrecision( nFormat ); - if ( nPrec > nPrecision ) + sal_uInt16 nPrec = pNumFmt->GetFormatPrecision( nFormat ); + if ( nPrec != SvNumberFormatter::UNLIMITED_PRECISION && nPrec > nPrecision ) nPrecision = nPrec; } if ( nPrecision ) diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index fa2d725937d4..2b71231c5210 100755 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -93,6 +93,7 @@ #include "tabprotection.hxx" #include "formulaparserpool.hxx" #include "clipparam.hxx" +#include <basic/basmgr.hxx> // pImpl because including lookupcache.hxx in document.hxx isn't wanted, and // dtor plus helpers are convenient. @@ -803,10 +804,6 @@ BOOL ScDocument::MoveTab( SCTAB nOldPos, SCTAB nNewPos ) if (pDrawLayer) DrawMovePage( static_cast<sal_uInt16>(nOldPos), static_cast<sal_uInt16>(nNewPos) ); - // Update cells containing external references. - if (pExternalRefMgr.get()) - pExternalRefMgr->updateRefMoveTable(nOldPos, nNewPos, false); - bValid = TRUE; } } @@ -926,16 +923,14 @@ BOOL ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, const ScMarkData* pOnlyM pTab[nNewPos]->SetPageStyle( pTab[nOldPos]->GetPageStyle() ); pTab[nNewPos]->SetPendingRowHeights( pTab[nOldPos]->IsPendingRowHeights() ); - - // Update cells containing external references. - if (pExternalRefMgr.get()) - pExternalRefMgr->updateRefMoveTable(nOldPos, nNewPos, true); } else SetAutoCalc( bOldAutoCalc ); return bValid; } +void VBA_InsertModule( ScDocument& rDoc, SCTAB nTab, String& sModuleName, String& sModuleSource ); + ULONG ScDocument::TransferTab( ScDocument* pSrcDoc, SCTAB nSrcPos, SCTAB nDestPos, BOOL bInsertNew, BOOL bResultsOnly ) @@ -1106,6 +1101,43 @@ ULONG ScDocument::TransferTab( ScDocument* pSrcDoc, SCTAB nSrcPos, } if (!bValid) nRetVal = 0; + BOOL bVbaEnabled = IsInVBAMode(); + + if ( bVbaEnabled ) + { + SfxObjectShell* pSrcShell = pSrcDoc ? pSrcDoc->GetDocumentShell() : NULL; + if ( pSrcShell ) + { + StarBASIC* pStarBASIC = pSrcShell ? pSrcShell->GetBasic() : NULL; + String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); + if ( pSrcShell && pSrcShell->GetBasicManager()->GetName().Len() > 0 ) + { + aLibName = pSrcShell->GetBasicManager()->GetName(); + pStarBASIC = pSrcShell->GetBasicManager()->GetLib( aLibName ); + } + + String sCodeName; + String sSource; + com::sun::star::uno::Reference< com::sun::star::script::XLibraryContainer > xLibContainer = pSrcShell->GetBasicContainer(); + com::sun::star::uno::Reference< com::sun::star::container::XNameContainer > xLib; + if( xLibContainer.is() ) + { + com::sun::star::uno::Any aLibAny = xLibContainer->getByName( aLibName ); + aLibAny >>= xLib; + } + + if( xLib.is() ) + { + String sSrcCodeName; + pSrcDoc->GetCodeName( nSrcPos, sSrcCodeName ); + rtl::OUString sRTLSource; + xLib->getByName( sSrcCodeName ) >>= sRTLSource; + sSource = sRTLSource; + } + VBA_InsertModule( *this, nDestPos, sCodeName, sSource ); + } + } + return nRetVal; } diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx index b31d124d88ff..4fe49b3728dd 100644 --- a/sc/source/core/data/documen3.cxx +++ b/sc/source/core/data/documen3.cxx @@ -485,11 +485,8 @@ void ScDocument::MarkUsedExternalReferences() // Charts. bool bAllMarked = pExternalRefMgr->markUsedByLinkListeners(); // Formula cells. - for (SCTAB nTab = 0; !bAllMarked && nTab < nMaxTableNumber; ++nTab) - { - if (pTab[nTab]) - bAllMarked = pTab[nTab]->MarkUsedExternalReferences(); - } + bAllMarked = pExternalRefMgr->markUsedExternalRefCells(); + /* NOTE: Conditional formats and validation objects are marked when * collecting them during export. */ } @@ -1283,7 +1280,8 @@ BOOL ScDocument::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, // GetFilterEntries - Eintraege fuer AutoFilter-Listbox // -BOOL ScDocument::GetFilterEntries( SCCOL nCol, SCROW nRow, SCTAB nTab, TypedScStrCollection& rStrings, bool bFilter ) +BOOL ScDocument::GetFilterEntries( + SCCOL nCol, SCROW nRow, SCTAB nTab, bool bFilter, TypedScStrCollection& rStrings, bool& rHasDates) { if ( ValidTab(nTab) && pTab[nTab] && pDBCollection ) { @@ -1320,11 +1318,11 @@ BOOL ScDocument::GetFilterEntries( SCCOL nCol, SCROW nRow, SCTAB nTab, TypedScSt if ( bFilter ) { - pTab[nTab]->GetFilteredFilterEntries( nCol, nStartRow, nEndRow, aParam, rStrings ); + pTab[nTab]->GetFilteredFilterEntries( nCol, nStartRow, nEndRow, aParam, rStrings, rHasDates ); } else { - pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings ); + pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates ); } return TRUE; @@ -1339,11 +1337,11 @@ BOOL ScDocument::GetFilterEntries( SCCOL nCol, SCROW nRow, SCTAB nTab, TypedScSt // BOOL ScDocument::GetFilterEntriesArea( SCCOL nCol, SCROW nStartRow, SCROW nEndRow, - SCTAB nTab, TypedScStrCollection& rStrings ) + SCTAB nTab, TypedScStrCollection& rStrings, bool& rHasDates ) { if ( ValidTab(nTab) && pTab[nTab] ) { - pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings ); + pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates ); return TRUE; } diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx index bb6b4cd295ce..148cc367534c 100644 --- a/sc/source/core/data/documen4.cxx +++ b/sc/source/core/data/documen4.cxx @@ -430,7 +430,7 @@ sal_Int32 ScDocument::GetMaxStringLen( SCTAB nTab, SCCOL nCol, return 0; } -xub_StrLen ScDocument::GetMaxNumberStringLen( USHORT& nPrecision, SCTAB nTab, +xub_StrLen ScDocument::GetMaxNumberStringLen( sal_uInt16& nPrecision, SCTAB nTab, SCCOL nCol, SCROW nRowStart, SCROW nRowEnd ) const { diff --git a/sc/source/core/data/documen5.cxx b/sc/source/core/data/documen5.cxx index d6653402c46a..d86d174ab414 100644 --- a/sc/source/core/data/documen5.cxx +++ b/sc/source/core/data/documen5.cxx @@ -705,6 +705,9 @@ void ScDocument::UpdateChartListenerCollection() SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); DBG_ASSERT(pPage,"Page ?"); + if (!pPage) + continue; + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); SdrObject* pObject = aIter.Next(); while (pObject) diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 3f25ad5a310e..7c08c4327183 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -51,6 +51,7 @@ #include <tools/tenccvt.hxx> #include <com/sun/star/text/WritingMode2.hpp> +#include <com/sun/star/script/XVBACompat.hpp> #include "document.hxx" #include "table.hxx" @@ -374,10 +375,6 @@ BOOL ScDocument::InsertTab( SCTAB nPos, const String& rName, if ( pChartListenerCollection ) pChartListenerCollection->UpdateScheduledSeriesRanges(); - // Update cells containing external references. - if (pExternalRefMgr.get()) - pExternalRefMgr->updateRefInsertTable(nPos); - SetDirty(); bValid = TRUE; } @@ -466,11 +463,6 @@ BOOL ScDocument::DeleteTab( SCTAB nTab, ScDocument* pRefUndoDoc ) // #81844# sheet names of references are not valid until sheet is deleted pChartListenerCollection->UpdateScheduledSeriesRanges(); - - // Update cells containing external references. - if (pExternalRefMgr.get()) - pExternalRefMgr->updateRefDeleteTable(nTab); - SetAutoCalc( bOldAutoCalc ); bValid = TRUE; } @@ -693,6 +685,10 @@ bool ScDocument::ShrinkToDataArea(SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow if (nRow2 < rEndRow) rEndRow = nRow2; + if (rStartCol > rEndCol || rStartRow > rEndRow) + // invalid range. + return false; + return true; // success! } @@ -707,11 +703,10 @@ bool ScDocument::ShrinkToUsedDataArea( SCTAB nTab, SCCOL& rStartCol, // zusammenhaengender Bereich void ScDocument::GetDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, - SCCOL& rEndCol, SCROW& rEndRow, BOOL bIncludeOld, bool bOnlyDown ) + SCCOL& rEndCol, SCROW& rEndRow, BOOL bIncludeOld, bool bOnlyDown ) const { - if (VALIDTAB(nTab)) - if (pTab[nTab]) - pTab[nTab]->GetDataArea( rStartCol, rStartRow, rEndCol, rEndRow, bIncludeOld, bOnlyDown ); + if (ValidTab(nTab) && pTab[nTab]) + pTab[nTab]->GetDataArea( rStartCol, rStartRow, rEndCol, rEndRow, bIncludeOld, bOnlyDown ); } @@ -4972,4 +4967,13 @@ void ScDocument::EnableUndo( bool bVal ) mbUndoEnabled = bVal; } - +bool ScDocument::IsInVBAMode() const +{ + bool bResult = false; + if ( pShell ) + { + com::sun::star::uno::Reference< com::sun::star::script::XVBACompat > xVBA( pShell->GetBasicContainer(), com::sun::star::uno::UNO_QUERY ); + bResult = xVBA->getVBACompatModeOn(); + } + return bResult; +} diff --git a/sc/source/core/data/dpcachetable.cxx b/sc/source/core/data/dpcachetable.cxx index ad5e921cb278..d97900e6b904 100644 --- a/sc/source/core/data/dpcachetable.cxx +++ b/sc/source/core/data/dpcachetable.cxx @@ -183,39 +183,9 @@ sal_Int32 ScDPCacheTable::getColSize() const return GetCache()->GetColumnCount(); } -namespace { - -/** - * While the macro interpret level is incremented, the formula cells are - * (semi-)guaranteed to be interpreted. - */ -class MacroInterpretIncrementer -{ -public: - MacroInterpretIncrementer(ScDocument* pDoc) : - mpDoc(pDoc) - { - mpDoc->IncMacroInterpretLevel(); - } - ~MacroInterpretIncrementer() - { - mpDoc->DecMacroInterpretLevel(); - } -private: - ScDocument* mpDoc; -}; - -} - void ScDPCacheTable::fillTable( const ScQueryParam& rQuery, BOOL* pSpecial, bool bIgnoreEmptyRows, bool bRepeatIfEmpty ) { - // Make sure the formula cells within the data range are interpreted - // during this call, for this method may be called from the interpretation - // of GETPIVOTDATA, which disables nested formula interpretation without - // increasing the macro level. - MacroInterpretIncrementer aMacroInc(GetCache()->GetDoc()); - if ( mpCache == NULL ) InitNoneCache( NULL ); //check cache diff --git a/sc/source/core/data/dpsave.cxx b/sc/source/core/data/dpsave.cxx index 72cf15285310..dd493bb0df6c 100644 --- a/sc/source/core/data/dpsave.cxx +++ b/sc/source/core/data/dpsave.cxx @@ -1325,6 +1325,8 @@ void ScDPSaveData::Refresh( const uno::Reference<sheet::XDimensionsSupplier>& xS pDim->Refresh( xSource, deletedDims ); } + + mbDimensionMembersBuilt = false; // there may be new members } catch(uno::Exception&) { diff --git a/sc/source/core/data/dpsdbtab.cxx b/sc/source/core/data/dpsdbtab.cxx index aae5797211b0..b966d9d458ea 100644 --- a/sc/source/core/data/dpsdbtab.cxx +++ b/sc/source/core/data/dpsdbtab.cxx @@ -237,15 +237,6 @@ long ScDatabaseDPData::GetColumnCount() // End Comments -void lcl_Reset( const uno::Reference<sdbc::XRowSet>& xRowSet ) - throw(sdbc::SQLException, uno::RuntimeException) -{ - // isBeforeFirst / beforeFirst is not always available - //! query if it is allowed - - xRowSet->execute(); // restart -} - String ScDatabaseDPData::getDimensionName(long nColumn) { if (getIsDataLayoutDimension(nColumn)) diff --git a/sc/source/core/data/dpshttab.cxx b/sc/source/core/data/dpshttab.cxx index 6254e3861db5..a1fa9d2d60a6 100755 --- a/sc/source/core/data/dpshttab.cxx +++ b/sc/source/core/data/dpshttab.cxx @@ -110,12 +110,6 @@ long ScSheetDPData::GetColumnCount() return aCacheTable.getColSize(); } -BOOL lcl_HasQuery( const ScQueryParam& rParam ) -{ - return rParam.GetEntryCount() > 0 && - rParam.GetEntry(0).bDoQuery; -} - String ScSheetDPData::getDimensionName(long nColumn) { CreateCacheTable(); diff --git a/sc/source/core/data/dptablecache.cxx b/sc/source/core/data/dptablecache.cxx index 42090e5203a2..8f25b70e41b6 100755 --- a/sc/source/core/data/dptablecache.cxx +++ b/sc/source/core/data/dptablecache.cxx @@ -243,7 +243,7 @@ BOOL ScDPItemData::operator==( const ScDPItemData& r ) const { if ( IsValue() ) { - if( HasDatePart() != r.HasDatePart() || HasDatePart() && mnDatePart != r.mnDatePart ) + if( (HasDatePart() != r.HasDatePart()) || (HasDatePart() && mnDatePart != r.mnDatePart) ) return FALSE; // Wang Xu Ming -- 1/9/2009 @@ -304,7 +304,7 @@ void ScDPItemData::dump() const DBG_TRACE1( "Numberformat= %o", nNumFormat ); DBG_TRACESTR(aString ); DBG_TRACE1( "fValue= %f", fValue ); - DBG_TRACE1( "bHasValue= %d", bHasValue ? 1:0); + DBG_TRACE1( "mbFlag= %d", mbFlag); } #endif //End @@ -489,8 +489,40 @@ bool ScDPTableDataCache::IsValid() const } // ----------------------------------------------------------------------- + +namespace { + +/** + * While the macro interpret level is incremented, the formula cells are + * (semi-)guaranteed to be interpreted. + */ +class MacroInterpretIncrementer +{ +public: + MacroInterpretIncrementer(ScDocument* pDoc) : + mpDoc(pDoc) + { + mpDoc->IncMacroInterpretLevel(); + } + ~MacroInterpretIncrementer() + { + mpDoc->DecMacroInterpretLevel(); + } +private: + ScDocument* mpDoc; +}; + +} + +// ----------------------------------------------------------------------- bool ScDPTableDataCache::InitFromDoc( ScDocument* pDoc, const ScRange& rRange ) { + // Make sure the formula cells within the data range are interpreted + // during this call, for this method may be called from the interpretation + // of GETPIVOTDATA, which disables nested formula interpretation without + // increasing the macro level. + MacroInterpretIncrementer aMacroInc(pDoc); + // SCROW nStartRow = rRange.aStart.Row(); // start of data SCROW nEndRow = rRange.aEnd.Row(); diff --git a/sc/source/core/data/dptabres.cxx b/sc/source/core/data/dptabres.cxx index 55f9fb771061..af8b74d546a8 100755 --- a/sc/source/core/data/dptabres.cxx +++ b/sc/source/core/data/dptabres.cxx @@ -290,7 +290,7 @@ void ScDPInitState::RemoveMember() --nCount; } -const SCROW ScDPInitState::GetNameIdForIndex( long nIndexValue ) const +SCROW ScDPInitState::GetNameIdForIndex( long nIndexValue ) const { for (long i=0; i<nCount; i++) if ( pIndex[i] == nIndexValue ) diff --git a/sc/source/core/data/global.cxx b/sc/source/core/data/global.cxx index 2081181b7537..48879bcdec93 100644 --- a/sc/source/core/data/global.cxx +++ b/sc/source/core/data/global.cxx @@ -144,15 +144,6 @@ long ScGlobal::nLastColWidthExtra = STD_EXTRA_WIDTH; static USHORT nPPTZoom = 0; // ScreenZoom used to determine nScreenPPTX/Y -// ... oder so? - -BOOL bOderSo; - -bool SC_DLLPUBLIC ScGetWriteTeamInfo() -{ - return bOderSo; -} - class SfxViewShell; SfxViewShell* pScActiveViewShell = NULL; //! als Member !!!!! USHORT nScClickMouseModifier = 0; //! dito @@ -517,12 +508,6 @@ String ScGlobal::GetLongErrorString(USHORT nErrNumber) break; } String aRes( GetRscString( nErrNumber ) ); - if( bOderSo ) - { - String aOderSo( GetRscString( STR_ODER_SO ) ); - aOderSo.SearchAndReplace( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("%s")), aRes ); - aRes = aOderSo; - } return aRes; } diff --git a/sc/source/core/data/global2.cxx b/sc/source/core/data/global2.cxx index d32ebdafbf78..3234340ae9dd 100644 --- a/sc/source/core/data/global2.cxx +++ b/sc/source/core/data/global2.cxx @@ -145,30 +145,32 @@ BOOL ScImportParam::operator==( const ScImportParam& rOther ) const //------------------------------------------------------------------------ // struct ScQueryParam: -ScQueryEntry::ScQueryEntry() +ScQueryEntry::ScQueryEntry() : + bDoQuery(FALSE), + bQueryByString(FALSE), + bQueryByDate(false), + nField(0), + eOp(SC_EQUAL), + eConnect(SC_AND), + pStr(new String), + nVal(0.0), + pSearchParam(NULL), + pSearchText(NULL) +{ +} + +ScQueryEntry::ScQueryEntry(const ScQueryEntry& r) : + bDoQuery(r.bDoQuery), + bQueryByString(r.bQueryByString), + bQueryByDate(r.bQueryByDate), + nField(r.nField), + eOp(r.eOp), + eConnect(r.eConnect), + pStr(new String(*r.pStr)), + nVal(r.nVal), + pSearchParam(NULL), + pSearchText(NULL) { - bDoQuery = FALSE; - bQueryByString = FALSE; - eOp = SC_EQUAL; - eConnect = SC_AND; - nField = 0; - nVal = 0.0; - pStr = new String; - pSearchParam = NULL; - pSearchText = NULL; -} - -ScQueryEntry::ScQueryEntry(const ScQueryEntry& r) -{ - bDoQuery = r.bDoQuery; - bQueryByString = r.bQueryByString; - eOp = r.eOp; - eConnect = r.eConnect; - nField = r.nField; - nVal = r.nVal; - pStr = new String(*r.pStr); - pSearchParam = NULL; - pSearchText = NULL; } ScQueryEntry::~ScQueryEntry() @@ -185,6 +187,7 @@ ScQueryEntry& ScQueryEntry::operator=( const ScQueryEntry& r ) { bDoQuery = r.bDoQuery; bQueryByString = r.bQueryByString; + bQueryByDate = r.bQueryByDate; eOp = r.eOp; eConnect = r.eConnect; nField = r.nField; @@ -205,6 +208,7 @@ void ScQueryEntry::Clear() { bDoQuery = FALSE; bQueryByString = FALSE; + bQueryByDate = false; eOp = SC_EQUAL; eConnect = SC_AND; nField = 0; @@ -223,6 +227,7 @@ BOOL ScQueryEntry::operator==( const ScQueryEntry& r ) const { return bDoQuery == r.bDoQuery && bQueryByString == r.bQueryByString + && bQueryByDate == r.bQueryByDate && eOp == r.eOp && eConnect == r.eConnect && nField == r.nField diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx index bf1f0fb95666..8b7ca593b2e9 100644 --- a/sc/source/core/data/table1.cxx +++ b/sc/source/core/data/table1.cxx @@ -115,8 +115,6 @@ // STATIC DATA ----------------------------------------------------------- -extern BOOL bIsOlk, bOderSo; - // ----------------------------------------------------------------------- ScTable::ScTable( ScDocument* pDoc, SCTAB nNewTab, const String& rNewName, @@ -232,9 +230,6 @@ void ScTable::GetName( String& rName ) const void ScTable::SetName( const String& rNewName ) { - String aMd( "D\344umling", RTL_TEXTENCODING_MS_1252 ); // ANSI - if( rNewName == aMd ) - bIsOlk = bOderSo = TRUE; aName = rNewName; aUpperName.Erase(); // invalidated if the name is changed @@ -700,7 +695,7 @@ BOOL ScTable::GetDataStart( SCCOL& rStartCol, SCROW& rStartRow ) const } void ScTable::GetDataArea( SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, - BOOL bIncludeOld, bool bOnlyDown ) const + BOOL bIncludeOld, bool bOnlyDown ) const { BOOL bLeft = FALSE; BOOL bRight = FALSE; diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 4dc7dddcaba1..69d16df7be58 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -1119,17 +1119,6 @@ void ScTable::CalcAfterLoad() } -bool ScTable::MarkUsedExternalReferences() -{ - bool bAllMarked = false; - for (SCCOL i=0; i <= MAXCOL && !bAllMarked; ++i) - { - bAllMarked = aCol[i].MarkUsedExternalReferences(); - } - return bAllMarked; -} - - void ScTable::ResetChanged( const ScRange& rRange ) { SCCOL nStartCol = rRange.aStart.Col(); diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx index 09a9f41929b5..7d295b6286a8 100644 --- a/sc/source/core/data/table3.cxx +++ b/sc/source/core/data/table3.cxx @@ -31,6 +31,7 @@ #include <rtl/math.hxx> #include <unotools/textsearch.hxx> #include <svl/zforlist.hxx> +#include <svl/zformat.hxx> #include <unotools/charclass.hxx> #include <unotools/collatorwrapper.hxx> #include <com/sun/star/i18n/CollatorOptions.hpp> @@ -989,6 +990,35 @@ BOOL ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam, } else nCellVal = GetValue( static_cast<SCCOL>(rEntry.nField), nRow ); + + /* NOTE: lcl_PrepareQuery() prepares a filter query such that if a + * date+time format was queried rEntry.bQueryByDate is not set. In + * case other queries wanted to use this mechanism they should do + * the same, in other words only if rEntry.nVal is an integer value + * rEntry.bQueryByDate should be true and the time fraction be + * stripped here. */ + if (rEntry.bQueryByDate) + { + sal_uInt32 nNumFmt = GetNumberFormat(static_cast<SCCOL>(rEntry.nField), nRow); + const SvNumberformat* pEntry = pDocument->GetFormatTable()->GetEntry(nNumFmt); + if (pEntry) + { + short nNumFmtType = pEntry->GetType(); + /* NOTE: Omitting the check for absence of + * NUMBERFORMAT_TIME would include also date+time formatted + * values of the same day. That may be desired in some + * cases, querying all time values of a day, but confusing + * in other cases. A user can always setup a standard + * filter query for x >= date AND x < date+1 */ + if ((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME)) + { + // The format is of date type. Strip off the time + // element. + nCellVal = ::rtl::math::approxFloor(nCellVal); + } + } + } + switch (rEntry.eOp) { case SC_EQUAL : @@ -1393,6 +1423,23 @@ static void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rPa sal_uInt32 nIndex = 0; rEntry.bQueryByString = !( pDoc->GetFormatTable()-> IsNumberFormat( *rEntry.pStr, nIndex, rEntry.nVal ) ); + if (rEntry.bQueryByDate) + { + if (!rEntry.bQueryByString && ((nIndex % SV_COUNTRY_LANGUAGE_OFFSET) != 0)) + { + const SvNumberformat* pEntry = pDoc->GetFormatTable()->GetEntry(nIndex); + if (pEntry) + { + short nNumFmtType = pEntry->GetType(); + if (!((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME))) + rEntry.bQueryByDate = false; // not a date only + } + else + rEntry.bQueryByDate = false; // what the ... not a date + } + else + rEntry.bQueryByDate = false; // not a date + } } else { @@ -1776,12 +1823,13 @@ BOOL ScTable::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL /* nEndCol * return TRUE; } -void ScTable::GetFilterEntries(SCCOL nCol, SCROW nRow1, SCROW nRow2, TypedScStrCollection& rStrings) +void ScTable::GetFilterEntries(SCCOL nCol, SCROW nRow1, SCROW nRow2, TypedScStrCollection& rStrings, bool& rHasDates) { - aCol[nCol].GetFilterEntries( nRow1, nRow2, rStrings ); + aCol[nCol].GetFilterEntries( nRow1, nRow2, rStrings, rHasDates ); } -void ScTable::GetFilteredFilterEntries( SCCOL nCol, SCROW nRow1, SCROW nRow2, const ScQueryParam& rParam, TypedScStrCollection& rStrings ) +void ScTable::GetFilteredFilterEntries( + SCCOL nCol, SCROW nRow1, SCROW nRow2, const ScQueryParam& rParam, TypedScStrCollection& rStrings, bool& rHasDates ) { // remove the entry for this column from the query parameter ScQueryParam aParam( rParam ); @@ -1799,15 +1847,18 @@ void ScTable::GetFilteredFilterEntries( SCCOL nCol, SCROW nRow1, SCROW nRow2, co BOOL* pSpecial = new BOOL[nEntryCount]; lcl_PrepareQuery( pDocument, this, aParam, pSpecial ); - + bool bHasDates = false; for ( SCROW j = nRow1; j <= nRow2; ++j ) { if ( ValidQuery( j, aParam, pSpecial ) ) { - aCol[nCol].GetFilterEntries( j, j, rStrings ); + bool bThisHasDates = false; + aCol[nCol].GetFilterEntries( j, j, rStrings, bThisHasDates ); + bHasDates |= bThisHasDates; } } + rHasDates = bHasDates; delete[] pSpecial; } @@ -1862,8 +1913,8 @@ sal_Int32 ScTable::GetMaxStringLen( SCCOL nCol, SCROW nRowStart, return 0; } -xub_StrLen ScTable::GetMaxNumberStringLen( USHORT& nPrecision, SCCOL nCol, - SCROW nRowStart, SCROW nRowEnd ) const +xub_StrLen ScTable::GetMaxNumberStringLen( + sal_uInt16& nPrecision, SCCOL nCol, SCROW nRowStart, SCROW nRowEnd ) const { if ( ValidCol(nCol) ) return aCol[nCol].GetMaxNumberStringLen( nPrecision, nRowStart, nRowEnd ); diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx index 2394bfb56799..edecaadb39f0 100644 --- a/sc/source/core/inc/interpre.hxx +++ b/sc/source/core/inc/interpre.hxx @@ -28,8 +28,6 @@ #ifndef SC_INTERPRE_HXX #define SC_INTERPRE_HXX -#define SC_SPEW_ENABLED 0 - #include <math.h> #include <rtl/math.hxx> #include "formula/errorcodes.hxx" @@ -38,10 +36,6 @@ #include "document.hxx" #include "scmatrix.hxx" -#if SC_SPEW_ENABLED -#include "scspew.hxx" -#endif - #include <math.h> #include <map> @@ -126,9 +120,6 @@ class ScInterpreter public: DECL_FIXEDMEMPOOL_NEWDEL( ScInterpreter ) -#if SC_SPEW_ENABLED - static ScSpew theSpew; -#endif static void GlobalExit(); // aus ScGlobal::Clear() gerufen @@ -171,6 +162,7 @@ private: short nFuncFmtType; // NumberFormatType of a function short nCurFmtType; // current NumberFormatType short nRetFmtType; // NumberFormatType of an expression + USHORT mnStringNoValueError; // the error set in ConvertStringToValue() if no value BOOL glSubTotal; // flag for subtotal functions BYTE cPar; // current count of parameters BOOL bCalcAsShown; // precision as shown @@ -539,11 +531,7 @@ void ScExternalRef(); void ScGetPivotData(); void ScHyperLink(); void ScBahtText(); -void ScCalcTeam(); -void ScAnswer(); void ScTTT(); -void ScSpewFunc(); -void ScGame(); //----------------Funktionen in interpr2.cxx--------------- diff --git a/sc/source/core/inc/sctictac.hxx b/sc/source/core/inc/sctictac.hxx deleted file mode 100644 index 1c8242150369..000000000000 --- a/sc/source/core/inc/sctictac.hxx +++ /dev/null @@ -1,131 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#ifndef SC_SCTICTAC_HXX -#define SC_SCTICTAC_HXX - -//#define TICTACTOE_MAIN -#ifdef TICTACTOE_MAIN -#define TICTACTOE_STDOUT -#else -//#define TICTACTOE_STDOUT -#endif -#ifndef TICTACTOE_STDOUT -#define TICTACTOE_SC -#endif - -#ifdef TICTACTOE_SC -class ScDocument; -#include "global.hxx" -#include "address.hxx" -#else -#include <tools/string.hxx> -#endif - -static const int ScTicTacToe_Squares = 9; -static const int ScTicTacToe_Possible_Wins = 8; -typedef sal_Unicode Square_Type; -typedef Square_Type Board_Type[ScTicTacToe_Squares]; - -class ScTicTacToe -{ -private: - /* Structure to hold a move and its heuristic */ - typedef struct { - int Square; - int Heuristic; - } Move_Heuristic_Type; - - static const Square_Type Empty; - static const Square_Type Human; - static const Square_Type Compi; - static const int Infinity; /* Higher value than any score */ - static const int Maximum_Moves; /* Maximum moves in a game */ - - Board_Type Board; -#ifdef TICTACTOE_SC - ScAddress aPos; // linke obere Ecke des Boards - ScDocument* pDoc; -#endif - ByteString aStdOut; - int Total_Nodes; /* Nodes searched with minimax */ - int nMove; - Square_Type aPlayer; - BOOL bInitialized; - - /* Array describing the eight combinations of three squares in a row */ - static const int Three_in_a_Row[ScTicTacToe_Possible_Wins][3]; - - /* Array used in heuristic formula for each move. */ - static const int Heuristic_Array[4][4]; - - - Square_Type Winner(); - inline Square_Type Other( Square_Type Player ); - inline void Play( int Square, Square_Type Player ); - int Evaluate( Square_Type Player ); - int BestMove( Square_Type Player, int *Square, - int Move_Nbr, int Alpha, int Beta ); - void Describe( int Score ); - void Move( int& Square ); - Square_Type TryMove( int& Square ); // return Winner() - void PromptHuman(); -#ifdef TICTACTOE_SC - // -1 == Fehler/Redraw, 0 == keine Aenderung, >0 == UserMoveSquare+1 - int GetStatus(); - void DrawBoard(); - void DrawPos( int nSquare, const String& rStr ); -#endif -#ifdef TICTACTOE_STDOUT - void Print(); -#endif - - ScTicTacToe( const ScTicTacToe& ); - ScTicTacToe& operator=( const ScTicTacToe& ); - -public: -#ifdef TICTACTOE_SC - ScTicTacToe( ScDocument* pDoc, const ScAddress& ); -#else - ScTicTacToe(); -#endif - ~ScTicTacToe() {} - void Initialize( BOOL bHumanFirst ); - Square_Type GetEmpty() { return Empty; } -#ifdef TICTACTOE_SC - Square_Type CalcMove(); // return Winner() -#endif -#ifdef TICTACTOE_STDOUT - void Game(); - void GetOutput( ByteString& rStr ); -#else - void GetOutput( String& rStr ); -#endif -}; - -#endif - diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index d2b1963c544d..5f4b86b7cd18 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -121,7 +121,7 @@ enum ScanState ssStop }; -static const sal_Char* pInternal[ 5 ] = { "GAME", "SPEW", "TTT", "STARCALCTEAM", "ANTWORT" }; +static const sal_Char* pInternal[ 1 ] = { "TTT" }; using namespace ::com::sun::star::i18n; diff --git a/sc/source/core/tool/dbcolect.cxx b/sc/source/core/tool/dbcolect.cxx index 4eea4db97a0a..7f94cb64c827 100644 --- a/sc/source/core/tool/dbcolect.cxx +++ b/sc/source/core/tool/dbcolect.cxx @@ -155,6 +155,7 @@ ScDBData::ScDBData( const ScDBData& rData ) : nQueryField[i] = rData.nQueryField[i]; eQueryOp[i] = rData.eQueryOp[i]; bQueryByString[i] = rData.bQueryByString[i]; + bQueryByDate[i] = rData.bQueryByDate[i]; pQueryStr[i] = new String( *(rData.pQueryStr[i]) ); nQueryVal[i] = rData.nQueryVal[i]; eQueryConnect[i] = rData.eQueryConnect[i]; @@ -244,6 +245,7 @@ ScDBData& ScDBData::operator= (const ScDBData& rData) nQueryField[i] = rData.nQueryField[i]; eQueryOp[i] = rData.eQueryOp[i]; bQueryByString[i] = rData.bQueryByString[i]; + bQueryByDate[i] = rData.bQueryByDate[i]; *pQueryStr[i] = *rData.pQueryStr[i]; nQueryVal[i] = rData.nQueryVal[i]; eQueryConnect[i] = rData.eQueryConnect[i]; @@ -512,6 +514,7 @@ void ScDBData::GetQueryParam( ScQueryParam& rQueryParam ) const rEntry.nField = nQueryField[i]; rEntry.eOp = eQueryOp[i]; rEntry.bQueryByString = bQueryByString[i]; + rEntry.bQueryByDate = bQueryByDate[i]; *rEntry.pStr = *pQueryStr[i]; rEntry.nVal = nQueryVal[i]; rEntry.eConnect = eQueryConnect[i]; @@ -543,6 +546,7 @@ void ScDBData::SetQueryParam(const ScQueryParam& rQueryParam) nQueryField[i] = rEntry.nField; eQueryOp[i] = rEntry.eOp; bQueryByString[i] = rEntry.bQueryByString; + bQueryByDate[i] = rEntry.bQueryByDate; *pQueryStr[i] = *rEntry.pStr; nQueryVal[i] = rEntry.nVal; eQueryConnect[i] = rEntry.eConnect; diff --git a/sc/source/core/tool/docoptio.cxx b/sc/source/core/tool/docoptio.cxx index a99b3c01dd1f..95ce357b3217 100644 --- a/sc/source/core/tool/docoptio.cxx +++ b/sc/source/core/tool/docoptio.cxx @@ -115,7 +115,7 @@ void ScDocOptions::ResetDocOptions() bIsIter = FALSE; nIterCount = 100; fIterEps = 1.0E-3; - nPrecStandardFormat = 2; + nPrecStandardFormat = SvNumberFormatter::UNLIMITED_PRECISION; nDay = 30; nMonth = 12; nYear = 1899; diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 94cd5c1a02e9..30aa0b8aa13e 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -2488,7 +2488,14 @@ void ScInterpreter::ScN() Pop(); } else + { + // Temporarily override the ConvertStringToValue() error for + // GetCellValue() / GetCellValueOrZero() + USHORT nSErr = mnStringNoValueError; + mnStringNoValueError = errCellNoValue; fVal = GetDouble(); + mnStringNoValueError = nSErr; + } if ( nGlobalError == NOTAVAILABLE || nGlobalError == errIllegalArgument ) nGlobalError = 0; // N(#NA) and N("text") are ok if ( !nGlobalError && nErr != NOTAVAILABLE ) diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index ffba9aafc511..2bf6a5680613 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -80,18 +80,8 @@ using ::std::auto_ptr; #define ADDIN_MAXSTRLEN 256 -// Implementiert in ui\miscdlgs\teamdlg.cxx - -extern void ShowTheTeam(); - -extern BOOL bOderSo; // in GLOBAL.CXX - //-----------------------------static data ----------------- -#if SC_SPEW_ENABLED -ScSpew ScInterpreter::theSpew; -#endif - //------------------------------------------------------------------------- // Funktionen fuer den Zugriff auf das Document //------------------------------------------------------------------------- @@ -261,7 +251,7 @@ double ScInterpreter::ConvertStringToValue( const String& rStr ) while (p < pStop && *p == ' ') ++p; if (p < pStop) - SetError( errNoValue); + SetError( mnStringNoValueError); break; case '-': case ':': @@ -281,7 +271,7 @@ double ScInterpreter::ConvertStringToValue( const String& rStr ) while (p < pStop && *p == ' ') ++p; if (p < pStop && !CharClass::isAsciiDigit(*p)) - SetError( errNoValue); + SetError( mnStringNoValueError); p = pLastStart; while (p < pStop && !nGlobalError && eState < blank) { @@ -291,7 +281,7 @@ double ScInterpreter::ConvertStringToValue( const String& rStr ) { // Maximum 2 digits per unit, except fractions. if (p - pLastStart >= 2 && eState != fraction) - SetError( errNoValue); + SetError( mnStringNoValueError); } else if (p > pLastStart) { @@ -300,7 +290,7 @@ double ScInterpreter::ConvertStringToValue( const String& rStr ) { nUnit[eState] = aStr.copy( pLastStart - pStart, p - pLastStart).toInt32(); if (nLimit[eState] && nLimit[eState] < nUnit[eState]) - SetError( errNoValue); + SetError( mnStringNoValueError); } pLastStart = p + 1; // hypothetical next start // Delimiters must match, a trailing delimiter @@ -311,11 +301,11 @@ double ScInterpreter::ConvertStringToValue( const String& rStr ) // Month must be followed by separator and // day, no trailing blanks. if (*p != '-' || (p+1 == pStop)) - SetError( errNoValue); + SetError( mnStringNoValueError); break; case day: if ((*p != 'T' || (p+1 == pStop)) && *p != ' ') - SetError( errNoValue); + SetError( mnStringNoValueError); // Take one blank as a valid delimiter // between date and time. break; @@ -323,17 +313,17 @@ double ScInterpreter::ConvertStringToValue( const String& rStr ) // Hour must be followed by separator and // minute, no trailing blanks. if (*p != ':' || (p+1 == pStop)) - SetError( errNoValue); + SetError( mnStringNoValueError); break; case minute: if ((*p != ':' || (p+1 == pStop)) && *p != ' ') - SetError( errNoValue); + SetError( mnStringNoValueError); if (*p == ' ') eState = done; break; case second: if (((*p != ',' && *p != '.') || (p+1 == pStop)) && *p != ' ') - SetError( errNoValue); + SetError( mnStringNoValueError); if (*p == ' ') eState = done; break; @@ -344,13 +334,13 @@ double ScInterpreter::ConvertStringToValue( const String& rStr ) case done: case blank: case stop: - SetError( errNoValue); + SetError( mnStringNoValueError); break; } eState = static_cast<State>(eState + 1); } else - SetError( errNoValue); + SetError( mnStringNoValueError); ++p; } if (eState == blank) @@ -358,14 +348,14 @@ double ScInterpreter::ConvertStringToValue( const String& rStr ) while (p < pStop && *p == ' ') ++p; if (p < pStop) - SetError( errNoValue); + SetError( mnStringNoValueError); eState = stop; } // Month without day, or hour without minute. if (eState == month || (eState == day && p <= pLastStart) || eState == hour || (eState == minute && p <= pLastStart)) - SetError( errNoValue); + SetError( mnStringNoValueError); if (!nGlobalError) { @@ -374,10 +364,10 @@ double ScInterpreter::ConvertStringToValue( const String& rStr ) { nUnit[eState] = aStr.copy( pLastStart - pStart, p - pLastStart).toInt32(); if (nLimit[eState] && nLimit[eState] < nUnit[eState]) - SetError( errNoValue); + SetError( mnStringNoValueError); } if (bDate && nUnit[hour] > 23) - SetError( errNoValue); + SetError( mnStringNoValueError); if (!nGlobalError) { if (bDate && nUnit[day] == 0) @@ -396,7 +386,7 @@ double ScInterpreter::ConvertStringToValue( const String& rStr ) } break; default: - SetError( errNoValue); + SetError( mnStringNoValueError); } if (nGlobalError) fValue = 0.0; @@ -3253,288 +3243,15 @@ void ScInterpreter::ScExternalRef() // --- internals ------------------------------------------------------------ -void ScInterpreter::ScAnswer() -{ - RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAnswer" ); - String aStr( GetString() ); - if( aStr.EqualsIgnoreCaseAscii( "Das Leben, das Universum und der ganze Rest" ) ) - { - PushInt( 42 ); - bOderSo = TRUE; - } - else - PushNoValue(); -} - - -void ScInterpreter::ScCalcTeam() -{ - RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCalcTeam" ); - static BOOL bShown = FALSE; - if( !bShown ) - { - ShowTheTeam(); - String aTeam( RTL_CONSTASCII_USTRINGPARAM( "Nebel, Benisch, Rentz, Rathke" ) ); - if ( (GetByte() == 1) && ::rtl::math::approxEqual( GetDouble(), 1996) ) - aTeam.AppendAscii( " (a word with 'B': -Olk, -Nietsch, -Daeumling)" ); - PushString( aTeam ); - bShown = TRUE; - } - else - PushInt( 42 ); -} - - -void ScInterpreter::ScSpewFunc() -{ - RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSpewFunc" ); - BOOL bRefresh = FALSE; - BOOL bClear = FALSE; - // Stack aufraeumen - BYTE nParamCount = GetByte(); - while ( nParamCount-- > 0) - { - switch ( GetStackType() ) - { - case svString: - case svSingleRef: - case svDoubleRef: - { - const sal_Unicode ch = GetString().GetChar(0); - if ( !bRefresh && ch < 256 ) - bRefresh = (tolower( (sal_uChar) ch ) == 'r'); - if ( !bClear && ch < 256 ) - bClear = (tolower( (sal_uChar) ch ) == 'c'); - } - break; - default: - PopError(); - } - } - String aStr; -#if SC_SPEW_ENABLED - if ( bRefresh ) - theSpew.Clear(); // GetSpew liest SpewRulesFile neu - theSpew.GetSpew( aStr ); - if ( bClear ) - theSpew.Clear(); // release Memory - xub_StrLen nPos = 0; - while ( (nPos = aStr.SearchAndReplace( '\n', ' ', nPos )) != STRING_NOTFOUND ) - nPos++; -#else - aStr.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "spitted out all spew :-(" ) ); -#endif - PushString( aStr ); -} - - -#include "sctictac.hxx" -#include "scmod.hxx" - -//extern "C" { static void SAL_CALL thisModule() {} } - -void ScInterpreter::ScGame() -{ - RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGame" ); - enum GameType { - SC_GAME_NONE, - SC_GAME_ONCE, - SC_GAME_START, - SC_GAME_TICTACTOE = SC_GAME_START, - SC_GAME_STARWARS, - SC_GAME_FROGGER, - SC_GAME_COUNT - }; - // ein grep im binary laeuft ins leere - static sal_Char sGameNone[] = "\14\36\6\137\10\27\36\13\100"; - static sal_Char sGameOnce[] = "\20\27\137\21\20\123\137\21\20\13\137\36\30\36\26\21\136"; - static sal_Char sGameTicTacToe[] = "\53\26\34\53\36\34\53\20\32"; - static sal_Char sGameStarWars[] = "\54\13\36\15\50\36\15\14"; - static sal_Char sGameFrogger[] = "\71\15\20\30\30\26\32"; - sal_Char* const pGames[SC_GAME_COUNT] = { - sGameNone, - sGameOnce, - sGameTicTacToe, - sGameStarWars, - sGameFrogger - }; -#if 0 -say what? -oh no, not again! -TicTacToe -StarWars -Froggie -// Routine um Datenblock zu erzeugen: -#include <stdio.h> -int main() -{ - int b = 1; - int c; - while ( (c = getchar()) != EOF ) - { - if ( b == 1 ) - { - printf( "\"" ); - b = 0; - } - if ( c != 10 ) - { - c ^= 0x7F; - printf( "\\%o", c ); - - } - else - { - printf( "\";\n" ); - b = 1; - } - } - return 0; -} -#endif - static BOOL bRun[SC_GAME_COUNT] = { FALSE }; - static BOOL bFirst = TRUE; - if ( bFirst ) - { - bFirst = FALSE; - for ( int j = SC_GAME_NONE; j < SC_GAME_COUNT; j++ ) - { - sal_Char* p = pGames[j]; - while ( *p ) - *p++ ^= 0x7F; - } - } - String aFuncResult; - GameType eGame = SC_GAME_NONE; - BYTE nParamCount = GetByte(); - if ( nParamCount >= 1 ) - { - String aStr( GetString() ); - nParamCount--; - for ( int j = SC_GAME_START; j < SC_GAME_COUNT; j++ ) - { - if ( aStr.EqualsAscii( pGames[j] ) ) - { - eGame = (GameType) j; - break; // for - } - } - if ( eGame != SC_GAME_NONE ) - { - // jedes Game nur ein einziges Mal starten, um nicht durch Recalc - // o.ae. mehrere Instanzen zu haben, ideal waere eine Abfrage an den - // Games, ob sie bereits laufen ... - if ( bRun[ eGame ] && eGame != SC_GAME_TICTACTOE ) - eGame = SC_GAME_ONCE; - else - { - bRun[ eGame ] = TRUE; - switch ( eGame ) - { - case SC_GAME_TICTACTOE : - { - static ScTicTacToe* pTicTacToe = NULL; - static ScRange aTTTrange; - static BOOL bHumanFirst = FALSE; - if ( nParamCount >= 1 ) - { - if ( GetStackType() == svDoubleRef ) - { - ScRange aRange; - PopDoubleRef( aRange ); - nParamCount--; - if ( aRange.aEnd.Col() - aRange.aStart.Col() == 2 - && aRange.aEnd.Row() - aRange.aStart.Row() == 2 ) - { - BOOL bOk; - if ( pTicTacToe ) - bOk = (aRange == aTTTrange); - else - { - bOk =TRUE; - aTTTrange = aRange; - pTicTacToe = new ScTicTacToe( pDok, - aRange.aStart ); - pTicTacToe->Initialize( bHumanFirst ); - } - // nur einmal und das auf dem gleichen Range - if ( !bOk ) - eGame = SC_GAME_ONCE; - else - { - Square_Type aWinner = pTicTacToe->CalcMove(); - pTicTacToe->GetOutput( aFuncResult ); - if ( aWinner != pTicTacToe->GetEmpty() ) - { - delete pTicTacToe; - pTicTacToe = NULL; - bRun[ eGame ] = FALSE; - bHumanFirst = !bHumanFirst; - } - pDok->GetDocumentShell()->Broadcast( - SfxSimpleHint( FID_DATACHANGED ) ); - pDok->ResetChanged( aRange ); - } - } - else - SetError( errIllegalArgument ); - } - else - SetError( errIllegalParameter ); - } - else - SetError( errIllegalParameter ); - } - break; - default: - { - // added to avoid warnings - } - } - } - } - } - // Stack aufraeumen - while ( nParamCount-- > 0) - Pop(); - if ( !aFuncResult.Len() ) - PushString( String( pGames[ eGame ], RTL_TEXTENCODING_ASCII_US ) ); - else - PushString( aFuncResult ); -} - void ScInterpreter::ScTTT() { // Temporaerer Test-Tanz, zum auspropieren von Funktionen etc. - BOOL bOk = TRUE; BYTE nParamCount = GetByte(); // do something, nParamCount bei Pops runterzaehlen! - if ( bOk && nParamCount ) - { - bOk = GetBool(); - --nParamCount; - } // Stack aufraeumen while ( nParamCount-- > 0) Pop(); - static const sal_Unicode __FAR_DATA sEyes[] = { ',',';',':','|','8','B', 0 }; - static const sal_Unicode __FAR_DATA sGoods[] = { ')',']','}', 0 }; - static const sal_Unicode __FAR_DATA sBads[] = { '(','[','{','/', 0 }; - sal_Unicode aFace[4]; - if ( bOk ) - { - aFace[0] = sEyes[ rand() % ((sizeof( sEyes )/sizeof(sal_Unicode)) - 1) ]; - aFace[1] = '-'; - aFace[2] = sGoods[ rand() % ((sizeof( sGoods )/sizeof(sal_Unicode)) - 1) ]; - } - else - { - aFace[0] = ':'; - aFace[1] = '-'; - aFace[2] = sBads[ rand() % ((sizeof( sBads )/sizeof(sal_Unicode)) - 1) ]; - } - aFace[3] = 0; - PushStringBuffer( aFace ); + PushError(errNoValue); } // ------------------------------------------------------------------------- @@ -3549,6 +3266,7 @@ ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc, pTokenMatrixMap( NULL ), pMyFormulaCell( pCell ), pFormatter( pDoc->GetFormatTable() ), + mnStringNoValueError( errNoValue), bCalcAsShown( pDoc->GetDocOptions().IsCalcAsShown() ) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTTT" ); @@ -3982,11 +3700,7 @@ StackVar ScInterpreter::Interpret() case ocAsc : ScAsc(); break; case ocUnicode : ScUnicode(); break; case ocUnichar : ScUnichar(); break; - case ocAnswer : ScAnswer(); break; - case ocTeam : ScCalcTeam(); break; case ocTTT : ScTTT(); break; - case ocSpew : ScSpewFunc(); break; - case ocGame : ScGame(); break; case ocNone : nFuncFmtType = NUMBERFORMAT_UNDEFINED; break; default : PushError( errUnknownOpCode); break; } diff --git a/sc/source/core/tool/makefile.mk b/sc/source/core/tool/makefile.mk index 6c730f3a1743..c0258e6f0575 100644 --- a/sc/source/core/tool/makefile.mk +++ b/sc/source/core/tool/makefile.mk @@ -104,7 +104,6 @@ SLOFILES = \ $(SLO)$/reftokenhelper.obj \ $(SLO)$/refupdat.obj \ $(SLO)$/scmatrix.obj \ - $(SLO)$/sctictac.obj \ $(SLO)$/stringutil.obj \ $(SLO)$/subtotal.obj \ $(SLO)$/token.obj \ diff --git a/sc/source/core/tool/queryparam.cxx b/sc/source/core/tool/queryparam.cxx index 47418ec85f4d..5b3b92f78ee4 100644 --- a/sc/source/core/tool/queryparam.cxx +++ b/sc/source/core/tool/queryparam.cxx @@ -171,7 +171,11 @@ ScQueryParamTable::~ScQueryParamTable() ScQueryParam::ScQueryParam() : ScQueryParamBase(), - ScQueryParamTable() + ScQueryParamTable(), + bDestPers(true), + nDestTab(0), + nDestCol(0), + nDestRow(0) { Clear(); } diff --git a/sc/source/core/tool/sctictac.cxx b/sc/source/core/tool/sctictac.cxx deleted file mode 100644 index d784f45deb87..000000000000 --- a/sc/source/core/tool/sctictac.cxx +++ /dev/null @@ -1,551 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_sc.hxx" - -/* Tic-Tac-Toe program by Steve Chapel schapel@cs.ucsb.edu - Uses alpha-beta pruning minimax search to play a "perfect" game. - The alpha-beta pruning can be removed, but will increase search time. - The heuristic and move ordering in BestMove() can also be removed with - an increase in search time. */ - -#include <stdio.h> -#include <ctype.h> - - -#include "sctictac.hxx" - -#ifdef TICTACTOE_SC -#include "document.hxx" -#include "cell.hxx" -#endif - -const Square_Type ScTicTacToe::Empty = ' '; -const Square_Type ScTicTacToe::Human = 'X'; -const Square_Type ScTicTacToe::Compi = 'O'; -const int ScTicTacToe::Infinity = 10; /* Higher value than any score */ -const int ScTicTacToe::Maximum_Moves = ScTicTacToe_Squares; /* Maximum moves in a game */ - -/* Array describing the eight combinations of three squares in a row */ -const int ScTicTacToe::Three_in_a_Row[ScTicTacToe_Possible_Wins][3] = { - { 0, 1, 2 }, - { 3, 4, 5 }, - { 6, 7, 8 }, - { 0, 3, 6 }, - { 1, 4, 7 }, - { 2, 5, 8 }, - { 0, 4, 8 }, - { 2, 4, 6 } -}; - -/* Array used in heuristic formula for each move. */ -const int ScTicTacToe::Heuristic_Array[4][4] = { - { 0, -10, -100, -1000 }, - { 10, 0, 0, 0 }, - { 100, 0, 0, 0 }, - { 1000, 0, 0, 0 } -}; - - -#ifdef TICTACTOE_SC -ScTicTacToe::ScTicTacToe( ScDocument* pDocP, const ScAddress& rPos ) : - aPos( rPos ), - pDoc( pDocP ), - aStdOut( "Computer plays O, you play X. " ), - bInitialized( FALSE ) -{ -} -#else -ScTicTacToe::ScTicTacToe() : - bInitialized( FALSE ), - aStdOut( "Computer plays O, you play X. " ) -{ -} -#endif - - -/* Return the other player */ -inline Square_Type ScTicTacToe::Other(Square_Type Player) -{ - return Player == Human ? Compi : Human; -} - - -/* Make a move on the board */ -inline void ScTicTacToe::Play(int Square, Square_Type Player) -{ - Board[Square] = Player; -} - - -#ifdef TICTACTOE_STDOUT - -void ScTicTacToe::GetOutput( ByteString& rStr ) -{ - rStr = aStdOut; - aStdOut.Erase(); -} - -#else // !TICTACTOE_STDOUT - -void ScTicTacToe::GetOutput( String& rStr ) -{ - rStr = String( aStdOut, gsl_getSystemTextEncoding() ); - aStdOut.Erase(); -} - -#endif // TICTACTOE_STDOUT - - -/* Clear the board */ -void ScTicTacToe::Initialize( BOOL bHumanFirst ) -{ - bInitialized = TRUE; - aPlayer = (bHumanFirst ? Human : Compi); - nMove = 1; - for (int i = 0; i < ScTicTacToe_Squares; i++) - Board[i] = Empty; -} - - -/* If a player has won, return the winner. If the game is a tie, - return 'C' (for cat). If the game is not over, return Empty. */ -Square_Type ScTicTacToe::Winner() -{ - int i; - for (i = 0; i < ScTicTacToe_Possible_Wins; i++) - { - Square_Type Possible_Winner = Board[Three_in_a_Row[i][0]]; - if (Possible_Winner != Empty && - Possible_Winner == Board[Three_in_a_Row[i][1]] && - Possible_Winner == Board[Three_in_a_Row[i][2]]) - return Possible_Winner; - } - - for (i = 0; i < ScTicTacToe_Squares; i++) - { - if (Board[i] == Empty) - return Empty; - } - - return 'C'; -} - - -/* Return a heuristic used to determine the order in which the - children of a node are searched */ -int ScTicTacToe::Evaluate(Square_Type Player) -{ - int i; - int Heuristic = 0; - for (i = 0; i < ScTicTacToe_Possible_Wins; i++) - { - int j; - int Players = 0, Others = 0; - for (j = 0; j < 3; j++) - { - Square_Type Piece = Board[Three_in_a_Row[i][j]]; - if (Piece == Player) - Players++; - else if (Piece == Other(Player)) - Others++; - } - Heuristic += Heuristic_Array[Players][Others]; - } - return Heuristic; -} - - -/* Return the score of the best move found for a board - The square to move to is returned in *Square */ -int ScTicTacToe::BestMove(Square_Type Player, int *Square, - int Move_Nbr, int Alpha, int Beta) -{ - int Best_Square = -1; - int Moves = 0; - int i; - Move_Heuristic_Type Move_Heuristic[ScTicTacToe_Squares]; - - Total_Nodes++; - - /* Find the heuristic for each move and sort moves in descending order */ - for (i = 0; i < ScTicTacToe_Squares; i++) - { - if (Board[i] == Empty) - { - int Heuristic; - int j; - Play(i, Player); - Heuristic = Evaluate(Player); - Play(i, Empty); - for (j = Moves-1; j >= 0 && - Move_Heuristic[j].Heuristic < Heuristic; j--) - { - Move_Heuristic[j + 1].Heuristic = Move_Heuristic[j].Heuristic; - Move_Heuristic[j + 1].Square = Move_Heuristic[j].Square; - } - Move_Heuristic[j + 1].Heuristic = Heuristic; - Move_Heuristic[j + 1].Square = i; - Moves++; - } - } - - for (i = 0; i < Moves; i++) - { - int Score; - int Sq = Move_Heuristic[i].Square; - Square_Type W; - - /* Make a move and get its score */ - Play(Sq, Player); - - W = Winner(); - if (W == Compi) - Score = (Maximum_Moves + 1) - Move_Nbr; - else if (W == Human) - Score = Move_Nbr - (Maximum_Moves + 1); - else if (W == 'C') - Score = 0; - else - Score = BestMove(Other(Player), Square, Move_Nbr + 1, - Alpha, Beta); - - Play(Sq, Empty); - - /* Perform alpha-beta pruning */ - if (Player == Compi) - { - if (Score >= Beta) - { - *Square = Sq; - return Score; - } - else if (Score > Alpha) - { - Alpha = Score; - Best_Square = Sq; - } - } - else - { - if (Score <= Alpha) - { - *Square = Sq; - return Score; - } - else if (Score < Beta) - { - Beta = Score; - Best_Square = Sq; - } - } - } - *Square = Best_Square; - if (Player == Compi) - return Alpha; - else - return Beta; -} - - -/* Provide an English description of the score returned by BestMove */ -void ScTicTacToe::Describe(int Score) -{ - if (Score < 0) - aStdOut += "You have a guaranteed win. "; - else if (Score == 0) - aStdOut += "I can guarantee a tie. "; - else - { - aStdOut += "I have a guaranteed win by move "; - aStdOut += ByteString::CreateFromInt32( Maximum_Moves - Score + 1 ); - aStdOut += ". "; - } -} - - -/* Have the human or the computer move */ -void ScTicTacToe::Move( int& Square ) -{ - if (aPlayer == Compi) - { - Total_Nodes = 0; - Describe(BestMove(aPlayer, &Square, nMove, -Infinity, Infinity)); - aStdOut += ByteString::CreateFromInt32( Total_Nodes ); - aStdOut += " nodes examined. "; - Play(Square, aPlayer); - aStdOut += "Move #"; - aStdOut += ByteString::CreateFromInt32( nMove ); - aStdOut += " - O moves to "; - aStdOut += ByteString::CreateFromInt32( Square + 1 ); - aStdOut += ". "; - aPlayer = Other( aPlayer ); - nMove++; - } - else - { - if ( Square < 0 || Square >= ScTicTacToe_Squares - || Board[Square] != Empty ) - Square = -1; - else - { - Play(Square, aPlayer); - aPlayer = Other( aPlayer ); - nMove++; - } - } -} - - -// Try a move -Square_Type ScTicTacToe::TryMove( int& Square ) -{ - if ( !bInitialized ) - Initialize( FALSE ); - - Square_Type W = Winner(); - if ( W == Empty ) - { - Move( Square ); -#ifdef TICTACTOE_STDOUT - if ( aStdOut.Len() ) - { - puts( aStdOut.GetBuffer() ); - aStdOut.Erase(); - } -#endif - W = Winner(); - } - if ( W == Empty ) - { - if ( aPlayer == Human ) - PromptHuman(); - } - else - { - if (W != 'C') - { - aStdOut += static_cast< char >(W); - aStdOut += " wins!"; - } - else - aStdOut += "It's a tie."; - } - return W; -} - - -void ScTicTacToe::PromptHuman() -{ - aStdOut += "Move #"; - aStdOut += ByteString::CreateFromInt32( nMove ); - aStdOut += " - What is X's move?"; -} - - -#ifdef TICTACTOE_SC - -void ScTicTacToe::DrawPos( int nSquare, const String& rStr ) -{ - pDoc->SetString( sal::static_int_cast<SCCOL>( aPos.Col()+(nSquare%3) ), - sal::static_int_cast<SCROW>( aPos.Row()+(nSquare/3) ), aPos.Tab(), rStr ); -} - - -void ScTicTacToe::DrawBoard() -{ - String aStr; - for ( USHORT j = 0; j < ScTicTacToe_Squares; j++ ) - { - aStr = Board[j]; - DrawPos( j, aStr ); - } -} - - -// -1 == Fehler/Redraw, 0 == keine Aenderung, >0 == UserMoveSquare+1 -int ScTicTacToe::GetStatus() -{ - SCCOL nCol; - SCROW nRow; - SCTAB nTab; - nCol = aPos.Col(); - nRow = aPos.Row(); - nTab = aPos.Tab(); - String aStr; - int nDiffs = 0; - int nSquare = 0; - for ( USHORT j = 0; j < ScTicTacToe_Squares; j++ ) - { - pDoc->GetString( nCol+(j%3), nRow+(j/3), nTab, aStr ); - if ( !aStr.Len() ) - { - if ( Board[j] != Empty ) - return -1; // wo was sein muss muss was sein - } - else - { - aStr.ToUpperAscii(); - if ( aStr.GetChar(0) != Board[j] ) - { - if ( Board[j] != Empty ) - return -1; // bestehendes ueberschrieben - // bei erstem Move hat Human angefangen - if ( ++nDiffs > 1 ) - return -1; // mehr als eine Aenderung - nSquare = j; - } - } - } - if ( nDiffs == 1 ) - return nSquare + 1; - return 0; -} - - -Square_Type ScTicTacToe::CalcMove() -{ - Square_Type W = Winner(); - int nStat = GetStatus(); - if ( nStat || (W == Empty && aPlayer == Compi) ) - { - if ( nStat == -1 || (nStat > 0 && aPlayer == Compi) ) - DrawBoard(); - if ( W == Empty && aPlayer == Human ) - { - if ( nStat > 0 ) - { - int nSquare = --nStat; - W = TryMove( nStat ); - if ( nStat == -1 ) - DrawPos( nSquare, String( ' ' ) ); - else - DrawPos( nStat, String( Human ) ); - } - else - PromptHuman(); - } - if ( W == Empty && aPlayer == Compi ) - { - W = TryMove( nStat ); // ComputerMove, nStat egal - DrawPos( nStat, String( Compi ) ); - } - } - else if ( W == Empty && aPlayer == Human ) - PromptHuman(); - return W; -} - -#endif // TICTACTOE_SC - - -#ifdef TICTACTOE_STDOUT -/* Print the board */ -void ScTicTacToe::Print() -{ - int i; - for (i = 0; i < ScTicTacToe_Squares; i += 3) - { - if (i > 0) - printf("---+---+---\n"); - printf(" %c | %c | %c \n", Board[i], Board[i + 1], Board[i + 2]); - } - printf("\n"); -} - - -/* Play a game of tic-tac-toe */ -void ScTicTacToe::Game() -{ - if ( !bInitialized ) - Initialize( FALSE ); - - int Square = (aPlayer == Compi ? 0 : -1); - Square_Type W = Winner(); - while( W == Empty ) - { - Print(); - W = TryMove( Square ); - if ( W == Empty ) - { - if ( aPlayer == Human ) - { - if ( Square != -1 ) - Print(); // empty board already printed if human moves first - do - { - puts( aStdOut.GetBuffer() ); - aStdOut.Erase(); - scanf("%d", &Square); - Square--; - W = TryMove( Square ); - } while ( Square == -1 ); - } - } - } - Print(); - puts( aStdOut.GetBuffer() ); - aStdOut.Erase(); -} -#endif // TICTACTOE_STDOUT - - -#ifdef TICTACTOE_MAIN -int main() -{ - char Answer[80]; - - printf("Welcome to Tic-Tac-Toe!\n\n"); - printf("Here is the board numbering:\n"); - printf(" 1 | 2 | 3\n"); - printf("---+---+---\n"); - printf(" 4 | 5 | 6\n"); - printf("---+---+---\n"); - printf(" 7 | 8 | 9\n"); - printf("\n"); -// printf("Computer plays X, you play O.\n"); - - ScTicTacToe aTTT; - ByteString aStr; - aTTT.GetOutput( aStr ); - puts( aStr.GetBuffer() ); - - do - { - printf("\nDo you want to move first? "); - scanf("%s", Answer); - aTTT.Initialize( toupper(Answer[0]) == 'Y' ); - aTTT.Game(); - printf("\nDo you want to play again? "); - scanf("%s", Answer); - } while (toupper(Answer[0]) == 'Y'); - - return 0; -} -#endif // TICTACTOE_MAIN - diff --git a/sc/source/filter/excel/excimp8.cxx b/sc/source/filter/excel/excimp8.cxx index e424ad2d95fe..a3ea403bf4c3 100644 --- a/sc/source/filter/excel/excimp8.cxx +++ b/sc/source/filter/excel/excimp8.cxx @@ -104,7 +104,6 @@ #include <com/sun/star/container/XNameContainer.hpp> #include <sfx2/app.hxx> - using namespace com::sun::star; @@ -257,8 +256,6 @@ void ImportExcel8::SheetProtection( void ) void ImportExcel8::ReadBasic( void ) { - bHasBasic = TRUE; - SfxObjectShell* pShell = GetDocShell(); SotStorageRef xRootStrg = GetRootStorage(); SvtFilterOptions* pFilterOpt = SvtFilterOptions::Get(); @@ -270,7 +267,18 @@ void ImportExcel8::ReadBasic( void ) if( bLoadCode || bLoadStrg ) { SvxImportMSVBasic aBasicImport( *pShell, *xRootStrg, bLoadCode, bLoadStrg ); - bool bAsComment = !bLoadExecutable; + bool bAsComment = !bLoadExecutable; + if ( !bAsComment ) + { + uno::Any aGlobs; + uno::Sequence< uno::Any > aArgs(1); + aArgs[ 0 ] <<= pShell->GetModel(); + aGlobs <<= ::comphelper::getProcessServiceFactory()->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.excel.Globals" ) ), aArgs ); + pShell->GetBasicManager()->SetGlobalUNOConstant( "VBAGlobals", aGlobs ); + BasicManager* pAppMgr = SFX_APP()->GetBasicManager(); + if ( pAppMgr ) + pAppMgr->SetGlobalUNOConstant( "ThisExcelDoc", aArgs[ 0 ] ); + } aBasicImport.Import( EXC_STORAGE_VBA_PROJECT, EXC_STORAGE_VBA, bAsComment ); } } @@ -286,6 +294,10 @@ void ImportExcel8::EndSheet( void ) void ImportExcel8::PostDocLoad( void ) { + // delay reading basic until sheet object ( codenames etc. ) are read + + if ( bHasBasic ) + ReadBasic(); // #i11776# filtered ranges before outlines and hidden rows if( pExcRoot->pAutoFilterBuffer ) pExcRoot->pAutoFilterBuffer->Apply(); diff --git a/sc/source/filter/excel/read.cxx b/sc/source/filter/excel/read.cxx index 99d722692a5e..79026e7b3a48 100644 --- a/sc/source/filter/excel/read.cxx +++ b/sc/source/filter/excel/read.cxx @@ -986,7 +986,7 @@ FltError ImportExcel8::Read( void ) case 0x22: Rec1904(); break; // 1904 [ 2345 ] case 0x56: Builtinfmtcnt(); break; // BUILTINFMTCNT[ 34 ] case 0x8D: Hideobj(); break; // HIDEOBJ [ 345 ] - case 0xD3: ReadBasic(); break; + case 0xD3: bHasBasic = true; break; case 0xDE: Olesize(); break; case 0x01BA: Codename( TRUE ); break; @@ -1212,7 +1212,9 @@ FltError ImportExcel8::Read( void ) pProgress.reset(); - AdjustRowHeight(); + if (pD->IsAdjustHeightEnabled()) + AdjustRowHeight(); + PostDocLoad(); pD->CalcAfterLoad(); diff --git a/sc/source/filter/excel/xechart.cxx b/sc/source/filter/excel/xechart.cxx index 1564b2db834e..b6b136da4b1e 100644 --- a/sc/source/filter/excel/xechart.cxx +++ b/sc/source/filter/excel/xechart.cxx @@ -39,6 +39,8 @@ #include <com/sun/star/chart/DataLabelPlacement.hpp> #include <com/sun/star/chart/ErrorBarStyle.hpp> #include <com/sun/star/chart/MissingValueTreatment.hpp> +#include <com/sun/star/chart/XChartDocument.hpp> +#include <com/sun/star/chart/XDiagramPositioning.hpp> #include <com/sun/star/chart2/XChartDocument.hpp> #include <com/sun/star/chart2/XDiagram.hpp> #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> @@ -52,6 +54,9 @@ #include <com/sun/star/chart2/CurveStyle.hpp> #include <com/sun/star/chart2/DataPointGeometry3D.hpp> #include <com/sun/star/chart2/DataPointLabel.hpp> +#include <com/sun/star/chart2/LegendExpansion.hpp> +#include <com/sun/star/chart2/LegendPosition.hpp> +#include <com/sun/star/chart2/RelativePosition.hpp> #include <com/sun/star/chart2/StackingDirection.hpp> #include <com/sun/star/chart2/TickmarkStyle.hpp> @@ -75,38 +80,47 @@ using ::com::sun::star::uno::Any; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::uno::UNO_SET_THROW; using ::com::sun::star::uno::Exception; using ::com::sun::star::beans::XPropertySet; using ::com::sun::star::i18n::XBreakIterator; using ::com::sun::star::frame::XModel; +using ::com::sun::star::drawing::XShape; using ::com::sun::star::drawing::XShapes; + +using ::com::sun::star::chart2::IncrementData; +using ::com::sun::star::chart2::RelativePosition; +using ::com::sun::star::chart2::ScaleData; +using ::com::sun::star::chart2::SubIncrement; +using ::com::sun::star::chart2::XAxis; using ::com::sun::star::chart2::XChartDocument; -using ::com::sun::star::chart2::XDiagram; -using ::com::sun::star::chart2::XCoordinateSystemContainer; -using ::com::sun::star::chart2::XCoordinateSystem; using ::com::sun::star::chart2::XChartTypeContainer; +using ::com::sun::star::chart2::XColorScheme; +using ::com::sun::star::chart2::XCoordinateSystem; +using ::com::sun::star::chart2::XCoordinateSystemContainer; using ::com::sun::star::chart2::XChartType; -using ::com::sun::star::chart2::XDataSeriesContainer; using ::com::sun::star::chart2::XDataSeries; -using ::com::sun::star::chart2::XRegressionCurveContainer; +using ::com::sun::star::chart2::XDataSeriesContainer; +using ::com::sun::star::chart2::XDiagram; +using ::com::sun::star::chart2::XFormattedString; +using ::com::sun::star::chart2::XLegend; using ::com::sun::star::chart2::XRegressionCurve; -using ::com::sun::star::chart2::XAxis; +using ::com::sun::star::chart2::XRegressionCurveContainer; using ::com::sun::star::chart2::XScaling; -using ::com::sun::star::chart2::ScaleData; -using ::com::sun::star::chart2::IncrementData; -using ::com::sun::star::chart2::SubIncrement; -using ::com::sun::star::chart2::XLegend; -using ::com::sun::star::chart2::XTitled; using ::com::sun::star::chart2::XTitle; -using ::com::sun::star::chart2::XFormattedString; -using ::com::sun::star::chart2::XColorScheme; +using ::com::sun::star::chart2::XTitled; + +using ::com::sun::star::chart2::data::XDataSequence; using ::com::sun::star::chart2::data::XDataSource; using ::com::sun::star::chart2::data::XLabeledDataSequence; -using ::com::sun::star::chart2::data::XDataSequence; using ::formula::FormulaGrammar; using ::formula::FormulaToken; +namespace cssc = ::com::sun::star::chart; +namespace cssc2 = ::com::sun::star::chart2; + // Helpers ==================================================================== namespace { @@ -160,13 +174,15 @@ bool lclIsAutoAnyOrGetScaledValue( double& rfValue, const Any& rAny, bool bLogSc // Common ===================================================================== /** Stores global data needed in various classes of the Chart export filter. */ -class XclExpChRootData : public XclChRootData +struct XclExpChRootData : public XclChRootData { -public: - explicit XclExpChRootData( XclExpChChart* pChartData ); + typedef ::std::vector< XclChFrBlock > XclChFrBlockVector; + + XclExpChChart& mrChartData; /// The chart data object. + XclChFrBlockVector maWrittenFrBlocks; /// Stack of future record levels already written out. + XclChFrBlockVector maUnwrittenFrBlocks; /// Stack of future record levels not yet written out. - /** Returns a reference to the parent chart data object. */ - inline XclExpChChart& GetChartData() const { return *mpChartData; } + inline explicit XclExpChRootData( XclExpChChart& rChartData ) : mrChartData( rChartData ) {} /** Registers a new future record level. */ void RegisterFutureRecBlock( const XclChFrBlock& rFrBlock ); @@ -174,22 +190,10 @@ public: void InitializeFutureRecBlock( XclExpStream& rStrm ); /** Finalizes the current future record level (writes CHFRBLOCKEND record if needed). */ void FinalizeFutureRecBlock( XclExpStream& rStrm ); - -private: - typedef ::std::vector< XclChFrBlock > XclChFrBlockVector; - - XclExpChChart* mpChartData; /// Pointer to the chart data object. - XclChFrBlockVector maWrittenFrBlocks; /// Stack of future record levels already written out. - XclChFrBlockVector maUnwrittenFrBlocks; /// Stack of future record levels not yet written out. }; // ---------------------------------------------------------------------------- -XclExpChRootData::XclExpChRootData( XclExpChChart* pChartData ) : - mpChartData( pChartData ) -{ -} - void XclExpChRootData::RegisterFutureRecBlock( const XclChFrBlock& rFrBlock ) { maUnwrittenFrBlocks.push_back( rFrBlock ); @@ -238,9 +242,9 @@ void XclExpChRootData::FinalizeFutureRecBlock( XclExpStream& rStrm ) // ---------------------------------------------------------------------------- -XclExpChRoot::XclExpChRoot( const XclExpRoot& rRoot, XclExpChChart* pChartData ) : +XclExpChRoot::XclExpChRoot( const XclExpRoot& rRoot, XclExpChChart& rChartData ) : XclExpRoot( rRoot ), - mxChData( new XclExpChRootData( pChartData ) ) + mxChData( new XclExpChRootData( rChartData ) ) { } @@ -248,29 +252,34 @@ XclExpChRoot::~XclExpChRoot() { } +Reference< XChartDocument > XclExpChRoot::GetChartDocument() const +{ + return mxChData->mxChartDoc; +} + XclExpChChart& XclExpChRoot::GetChartData() const { - return mxChData->GetChartData(); + return mxChData->mrChartData; } const XclChTypeInfo& XclExpChRoot::GetChartTypeInfo( XclChTypeId eType ) const { - return mxChData->GetTypeInfoProvider().GetTypeInfo( eType ); + return mxChData->mxTypeInfoProv->GetTypeInfo( eType ); } const XclChTypeInfo& XclExpChRoot::GetChartTypeInfo( const OUString& rServiceName ) const { - return mxChData->GetTypeInfoProvider().GetTypeInfoFromService( rServiceName ); + return mxChData->mxTypeInfoProv->GetTypeInfoFromService( rServiceName ); } const XclChFormatInfo& XclExpChRoot::GetFormatInfo( XclChObjectType eObjType ) const { - return mxChData->GetFormatInfoProvider().GetFormatInfo( eObjType ); + return mxChData->mxFmtInfoProv->GetFormatInfo( eObjType ); } -void XclExpChRoot::InitConversion( XChartDocRef xChartDoc ) const +void XclExpChRoot::InitConversion( XChartDocRef xChartDoc, const Rectangle& rChartRect ) const { - mxChData->InitConversion( xChartDoc ); + mxChData->InitConversion( GetRoot(), xChartDoc, rChartRect ); } void XclExpChRoot::FinishConversion() const @@ -291,11 +300,41 @@ void XclExpChRoot::SetSystemColor( Color& rColor, sal_uInt32& rnColorId, sal_uIn rnColorId = XclExpPalette::GetColorIdFromIndex( nSysColorIdx ); } +sal_Int32 XclExpChRoot::CalcChartXFromHmm( sal_Int32 nPosX ) const +{ + return ::limit_cast< sal_Int32, double >( (nPosX - mxChData->mnBorderGapX) / mxChData->mfUnitSizeX, 0, EXC_CHART_TOTALUNITS ); +} + +sal_Int32 XclExpChRoot::CalcChartYFromHmm( sal_Int32 nPosY ) const +{ + return ::limit_cast< sal_Int32, double >( (nPosY - mxChData->mnBorderGapY) / mxChData->mfUnitSizeY, 0, EXC_CHART_TOTALUNITS ); +} + +XclChRectangle XclExpChRoot::CalcChartRectFromHmm( const ::com::sun::star::awt::Rectangle& rRect ) const +{ + XclChRectangle aRect; + aRect.mnX = CalcChartXFromHmm( rRect.X ); + aRect.mnY = CalcChartYFromHmm( rRect.Y ); + aRect.mnWidth = CalcChartXFromHmm( rRect.Width ); + aRect.mnHeight = CalcChartYFromHmm( rRect.Height ); + return aRect; +} + +sal_Int32 XclExpChRoot::CalcChartXFromRelative( double fPosX ) const +{ + return CalcChartXFromHmm( static_cast< sal_Int32 >( fPosX * mxChData->maChartRect.GetWidth() + 0.5 ) ); +} + +sal_Int32 XclExpChRoot::CalcChartYFromRelative( double fPosY ) const +{ + return CalcChartYFromHmm( static_cast< sal_Int32 >( fPosY * mxChData->maChartRect.GetHeight() + 0.5 ) ); +} + void XclExpChRoot::ConvertLineFormat( XclChLineFormat& rLineFmt, const ScfPropertySet& rPropSet, XclChPropertyMode ePropMode ) const { GetChartPropSetHelper().ReadLineProperties( - rLineFmt, mxChData->GetLineDashTable(), rPropSet, ePropMode ); + rLineFmt, *mxChData->mxLineDashTable, rPropSet, ePropMode ); } bool XclExpChRoot::ConvertAreaFormat( XclChAreaFormat& rAreaFmt, @@ -309,7 +348,7 @@ void XclExpChRoot::ConvertEscherFormat( const ScfPropertySet& rPropSet, XclChPropertyMode ePropMode ) const { GetChartPropSetHelper().ReadEscherProperties( rEscherFmt, rPicFmt, - mxChData->GetGradientTable(), mxChData->GetHatchTable(), mxChData->GetBitmapTable(), rPropSet, ePropMode ); + *mxChData->mxGradientTable, *mxChData->mxHatchTable, *mxChData->mxBitmapTable, rPropSet, ePropMode ); } sal_uInt16 XclExpChRoot::ConvertFont( const ScfPropertySet& rPropSet, sal_Int16 nScript ) const @@ -404,6 +443,20 @@ void XclExpChFutureRecordBase::Save( XclExpStream& rStrm ) // Frame formatting =========================================================== +XclExpChFramePos::XclExpChFramePos( sal_uInt16 nTLMode, sal_uInt16 nBRMode ) : + XclExpRecord( EXC_ID_CHFRAMEPOS, 20 ) +{ + maData.mnTLMode = nTLMode; + maData.mnBRMode = nBRMode; +} + +void XclExpChFramePos::WriteBody( XclExpStream& rStrm ) +{ + rStrm << maData.mnTLMode << maData.mnBRMode << maData.maRect; +} + +// ---------------------------------------------------------------------------- + XclExpChLineFormat::XclExpChLineFormat( const XclExpChRoot& rRoot ) : XclExpRecord( EXC_ID_CHLINEFORMAT, (rRoot.GetBiff() == EXC_BIFF8) ? 12 : 10 ), mnColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT ) ) @@ -1118,6 +1171,36 @@ void XclExpChText::ConvertTitle( Reference< XTitle > xTitle, sal_uInt16 nTarget // rotation ConvertRotationBase( GetChRoot(), aTitleProp, true ); + + // manual text position - only for main title + mxFramePos.reset( new XclExpChFramePos( EXC_CHFRAMEPOS_PARENT, EXC_CHFRAMEPOS_PARENT ) ); + if( nTarget == EXC_CHOBJLINK_TITLE ) + { + Any aRelPos; + if( aTitleProp.GetAnyProperty( aRelPos, EXC_CHPROP_RELATIVEPOSITION ) && aRelPos.has< RelativePosition >() ) try + { + // calculate absolute position for CHTEXT record + Reference< cssc::XChartDocument > xChart1Doc( GetChartDocument(), UNO_QUERY_THROW ); + Reference< XShape > xTitleShape( xChart1Doc->getTitle(), UNO_SET_THROW ); + ::com::sun::star::awt::Point aPos = xTitleShape->getPosition(); + ::com::sun::star::awt::Size aSize = xTitleShape->getSize(); + ::com::sun::star::awt::Rectangle aRect( aPos.X, aPos.Y, aSize.Width, aSize.Height ); + maData.maRect = CalcChartRectFromHmm( aRect ); + ::insert_value( maData.mnFlags2, EXC_CHTEXT_POS_MOVED, 0, 4 ); + // manual title position implies manual plot area + GetChartData().SetManualPlotArea(); + // calculate the default title position in chart units + sal_Int32 nDefPosX = ::std::max< sal_Int32 >( (EXC_CHART_TOTALUNITS - maData.maRect.mnWidth) / 2, 0 ); + sal_Int32 nDefPosY = 85; + // set the position relative to the standard position + XclChRectangle& rFrameRect = mxFramePos->GetFramePosData().maRect; + rFrameRect.mnX = maData.maRect.mnX - nDefPosX; + rFrameRect.mnY = maData.maRect.mnY - nDefPosY; + } + catch( Exception& ) + { + } + } } else { @@ -1137,8 +1220,7 @@ bool XclExpChText::ConvertDataLabel( const ScfPropertySet& rPropSet, { SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_DATALABEL, rPointPos.mnPointIdx, rPointPos.mnSeriesIdx ); - namespace cssc = ::com::sun::star::chart2; - cssc::DataPointLabel aPointLabel; + cssc2::DataPointLabel aPointLabel; if( !rPropSet.GetProperty( aPointLabel, EXC_CHPROP_LABEL ) ) return false; @@ -1184,31 +1266,33 @@ bool XclExpChText::ConvertDataLabel( const ScfPropertySet& rPropSet, ConvertRotationBase( GetChRoot(), rPropSet, false ); // label placement sal_Int32 nPlacement = 0; + sal_uInt16 nLabelPos = EXC_CHTEXT_POS_AUTO; if( rPropSet.GetProperty( nPlacement, EXC_CHPROP_LABELPLACEMENT ) ) { using namespace ::com::sun::star::chart::DataLabelPlacement; if( nPlacement == rTypeInfo.mnDefaultLabelPos ) { - maData.mnPlacement = EXC_CHTEXT_POS_DEFAULT; + nLabelPos = EXC_CHTEXT_POS_DEFAULT; } else switch( nPlacement ) { - case AVOID_OVERLAP: maData.mnPlacement = EXC_CHTEXT_POS_AUTO; break; - case CENTER: maData.mnPlacement = EXC_CHTEXT_POS_CENTER; break; - case TOP: maData.mnPlacement = EXC_CHTEXT_POS_ABOVE; break; - case TOP_LEFT: maData.mnPlacement = EXC_CHTEXT_POS_LEFT; break; - case LEFT: maData.mnPlacement = EXC_CHTEXT_POS_LEFT; break; - case BOTTOM_LEFT: maData.mnPlacement = EXC_CHTEXT_POS_LEFT; break; - case BOTTOM: maData.mnPlacement = EXC_CHTEXT_POS_BELOW; break; - case BOTTOM_RIGHT: maData.mnPlacement = EXC_CHTEXT_POS_RIGHT; break; - case RIGHT: maData.mnPlacement = EXC_CHTEXT_POS_RIGHT; break; - case TOP_RIGHT: maData.mnPlacement = EXC_CHTEXT_POS_RIGHT; break; - case INSIDE: maData.mnPlacement = EXC_CHTEXT_POS_INSIDE; break; - case OUTSIDE: maData.mnPlacement = EXC_CHTEXT_POS_OUTSIDE; break; - case NEAR_ORIGIN: maData.mnPlacement = EXC_CHTEXT_POS_AXIS; break; + case AVOID_OVERLAP: nLabelPos = EXC_CHTEXT_POS_AUTO; break; + case CENTER: nLabelPos = EXC_CHTEXT_POS_CENTER; break; + case TOP: nLabelPos = EXC_CHTEXT_POS_ABOVE; break; + case TOP_LEFT: nLabelPos = EXC_CHTEXT_POS_LEFT; break; + case LEFT: nLabelPos = EXC_CHTEXT_POS_LEFT; break; + case BOTTOM_LEFT: nLabelPos = EXC_CHTEXT_POS_LEFT; break; + case BOTTOM: nLabelPos = EXC_CHTEXT_POS_BELOW; break; + case BOTTOM_RIGHT: nLabelPos = EXC_CHTEXT_POS_RIGHT; break; + case RIGHT: nLabelPos = EXC_CHTEXT_POS_RIGHT; break; + case TOP_RIGHT: nLabelPos = EXC_CHTEXT_POS_RIGHT; break; + case INSIDE: nLabelPos = EXC_CHTEXT_POS_INSIDE; break; + case OUTSIDE: nLabelPos = EXC_CHTEXT_POS_OUTSIDE; break; + case NEAR_ORIGIN: nLabelPos = EXC_CHTEXT_POS_AXIS; break; default: DBG_ERRORFILE( "XclExpChText::ConvertDataLabel - unknown label placement type" ); } } + ::insert_value( maData.mnFlags2, nLabelPos, 0, 4 ); // source link (contains number format) mxSrcLink.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE ) ); if( bShowValue || bShowPercent ) @@ -1255,6 +1339,8 @@ sal_uInt16 XclExpChText::GetAttLabelFlags() const void XclExpChText::WriteSubRecords( XclExpStream& rStrm ) { + // CHFRAMEPOS record + lclSaveRecord( rStrm, mxFramePos ); // CHFONT record lclSaveRecord( rStrm, mxFont ); // CHSOURCELINK group @@ -1279,7 +1365,7 @@ void XclExpChText::WriteBody( XclExpStream& rStrm ) if( GetBiff() == EXC_BIFF8 ) { rStrm << GetPalette().GetColorIndex( mnTextColorId ) - << maData.mnPlacement + << maData.mnFlags2 << maData.mnRotation; } } @@ -1604,7 +1690,6 @@ bool XclExpChSerErrorBar::Convert( XclExpChSourceLink& rValueLink, sal_uInt16& r bool bOk = rPropSet.GetProperty( nBarStyle, EXC_CHPROP_ERRORBARSTYLE ); if( bOk ) { - namespace cssc = ::com::sun::star::chart; switch( nBarStyle ) { case cssc::ErrorBarStyle::ABSOLUTE: @@ -2148,12 +2233,66 @@ void XclExpChLegend::Convert( const ScfPropertySet& rPropSet ) // text properties mxText.reset( new XclExpChText( GetChRoot() ) ); mxText->ConvertLegend( rPropSet ); - // special legend properties - GetChartPropSetHelper().ReadLegendProperties( maData, rPropSet ); + + // legend position + Any aRelPosAny; + rPropSet.GetAnyProperty( aRelPosAny, EXC_CHPROP_RELATIVEPOSITION ); + if( aRelPosAny.has< RelativePosition >() ) + { + try + { + /* The 'RelativePosition' property is used as indicator of manually + changed legend position, but due to the different anchor modes + used by this property (in the RelativePosition.Anchor member) + it cannot be used to calculate the position easily. For this, + the Chart1 API will be used instead. */ + Reference< ::com::sun::star::chart::XChartDocument > xChart1Doc( GetChartDocument(), UNO_QUERY_THROW ); + Reference< XShape > xChart1Legend( xChart1Doc->getLegend(), UNO_SET_THROW ); + // coordinates in CHLEGEND record written but not used by Excel + mxFramePos.reset( new XclExpChFramePos( EXC_CHFRAMEPOS_CHARTSIZE, EXC_CHFRAMEPOS_PARENT ) ); + XclChFramePos& rFramePos = mxFramePos->GetFramePosData(); + rFramePos.maRect.mnX = maData.maRect.mnX = CalcChartXFromHmm( xChart1Legend->getPosition().X ); + rFramePos.maRect.mnY = maData.maRect.mnY = CalcChartYFromHmm( xChart1Legend->getPosition().Y ); + // manual legend position implies manual plot area + GetChartData().SetManualPlotArea(); + maData.mnDockMode = EXC_CHLEGEND_NOTDOCKED; + } + catch( Exception& ) + { + OSL_ENSURE( false, "XclExpChLegend::Convert - cannot get legend shape" ); + maData.mnDockMode = EXC_CHLEGEND_RIGHT; + } + } + else + { + cssc2::LegendPosition eApiPos = cssc2::LegendPosition_CUSTOM; + rPropSet.GetProperty( eApiPos, EXC_CHPROP_ANCHORPOSITION ); + switch( eApiPos ) + { + case cssc2::LegendPosition_LINE_START: maData.mnDockMode = EXC_CHLEGEND_LEFT; break; + case cssc2::LegendPosition_LINE_END: maData.mnDockMode = EXC_CHLEGEND_RIGHT; break; + case cssc2::LegendPosition_PAGE_START: maData.mnDockMode = EXC_CHLEGEND_TOP; break; + case cssc2::LegendPosition_PAGE_END: maData.mnDockMode = EXC_CHLEGEND_BOTTOM; break; + default: + OSL_ENSURE( false, "XclExpChLegend::Convert - unrecognized legend position" ); + maData.mnDockMode = EXC_CHLEGEND_RIGHT; + } + } + + // legend expansion + cssc2::LegendExpansion eApiExpand = cssc2::LegendExpansion_BALANCED; + rPropSet.GetProperty( eApiExpand, EXC_CHPROP_EXPANSION ); + ::set_flag( maData.mnFlags, EXC_CHLEGEND_STACKED, eApiExpand != cssc2::LegendExpansion_WIDE ); + + // other flags + ::set_flag( maData.mnFlags, EXC_CHLEGEND_AUTOSERIES ); + const sal_uInt16 nAutoFlags = EXC_CHLEGEND_DOCKED | EXC_CHLEGEND_AUTOPOSX | EXC_CHLEGEND_AUTOPOSY; + ::set_flag( maData.mnFlags, nAutoFlags, maData.mnDockMode != EXC_CHLEGEND_NOTDOCKED ); } void XclExpChLegend::WriteSubRecords( XclExpStream& rStrm ) { + lclSaveRecord( rStrm, mxFramePos ); lclSaveRecord( rStrm, mxText ); lclSaveRecord( rStrm, mxFrame ); } @@ -2252,13 +2391,12 @@ void XclExpChTypeGroup::ConvertSeries( { // stacking direction (stacked/percent/deep 3d) from first series ScfPropertySet aSeriesProp( aSeriesVec.front() ); - namespace cssc = ::com::sun::star::chart2; - cssc::StackingDirection eStacking; + cssc2::StackingDirection eStacking; if( !aSeriesProp.GetProperty( eStacking, EXC_CHPROP_STACKINGDIR ) ) - eStacking = cssc::StackingDirection_NO_STACKING; + eStacking = cssc2::StackingDirection_NO_STACKING; // stacked or percent chart - if( maTypeInfo.mbSupportsStacking && (eStacking == cssc::StackingDirection_Y_STACKING) ) + if( maTypeInfo.mbSupportsStacking && (eStacking == cssc2::StackingDirection_Y_STACKING) ) { // percent overrides simple stacking maType.SetStacked( bPercent ); @@ -2275,7 +2413,7 @@ void XclExpChTypeGroup::ConvertSeries( } // deep 3d chart or clustered 3d chart (stacked is not clustered) - if( (eStacking == cssc::StackingDirection_NO_STACKING) && Is3dWallChart() ) + if( (eStacking == cssc2::StackingDirection_NO_STACKING) && Is3dWallChart() ) mxChart3d->SetClustered(); // varied point colors @@ -2396,7 +2534,8 @@ bool XclExpChTypeGroup::CreateStockSeries( Reference< XDataSeries > xDataSeries, void XclExpChTypeGroup::WriteBody( XclExpStream& rStrm ) { - rStrm << maData.maRect << maData.mnFlags << maData.mnGroupIdx; + rStrm.WriteZeroBytes( 16 ); + rStrm << maData.mnFlags << maData.mnGroupIdx; } // Axes ======================================================================= @@ -2421,7 +2560,6 @@ void XclExpChLabelRange::Convert( const ScaleData& rScaleData, bool bMirrorOrien void XclExpChLabelRange::ConvertAxisPosition( const ScfPropertySet& rPropSet ) { - namespace cssc = ::com::sun::star::chart; cssc::ChartAxisPosition eAxisPos = cssc::ChartAxisPosition_VALUE; rPropSet.GetProperty( eAxisPos, EXC_CHPROP_CROSSOVERPOSITION ); double fCrossingPos = 1.0; @@ -2479,13 +2617,11 @@ void XclExpChValueRange::Convert( const ScaleData& rScaleData ) ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMINOR, bAutoMinor ); // reverse order - namespace cssc = ::com::sun::star::chart2; - ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_REVERSE, rScaleData.Orientation == cssc::AxisOrientation_REVERSE ); + ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_REVERSE, rScaleData.Orientation == cssc2::AxisOrientation_REVERSE ); } void XclExpChValueRange::ConvertAxisPosition( const ScfPropertySet& rPropSet ) { - namespace cssc = ::com::sun::star::chart; cssc::ChartAxisPosition eAxisPos = cssc::ChartAxisPosition_VALUE; double fCrossingPos = 0.0; if( rPropSet.GetProperty( eAxisPos, EXC_CHPROP_CROSSOVERPOSITION ) && rPropSet.GetProperty( fCrossingPos, EXC_CHPROP_CROSSOVERVALUE ) ) @@ -2569,7 +2705,6 @@ void XclExpChTick::Convert( const ScfPropertySet& rPropSet, const XclChExtTypeIn } else { - namespace cssc = ::com::sun::star::chart; cssc::ChartAxisLabelPosition eApiLabelPos = cssc::ChartAxisLabelPosition_NEAR_AXIS; rPropSet.GetProperty( eApiLabelPos, EXC_CHPROP_LABELPOSITION ); switch( eApiLabelPos ) @@ -2602,9 +2737,9 @@ void XclExpChTick::WriteBody( XclExpStream& rStrm ) rStrm << maData.mnMajor << maData.mnMinor << maData.mnLabelPos - << maData.mnBackMode - << maData.maRect - << maData.maTextColor + << maData.mnBackMode; + rStrm.WriteZeroBytes( 16 ); + rStrm << maData.maTextColor << maData.mnFlags; if( GetBiff() == EXC_BIFF8 ) rStrm << GetPalette().GetColorIndex( mnTextColorId ) << maData.mnRotation; @@ -2758,7 +2893,8 @@ void XclExpChAxis::WriteSubRecords( XclExpStream& rStrm ) void XclExpChAxis::WriteBody( XclExpStream& rStrm ) { - rStrm << maData.mnType << maData.maRect; + rStrm << maData.mnType; + rStrm.WriteZeroBytes( 16 ); } // ---------------------------------------------------------------------------- @@ -2903,6 +3039,28 @@ sal_uInt16 XclExpChAxesSet::Convert( Reference< XDiagram > xDiagram, sal_uInt16 } } + // inner and outer plot area position and size + try + { + Reference< ::com::sun::star::chart::XChartDocument > xChart1Doc( GetChartDocument(), UNO_QUERY_THROW ); + Reference< ::com::sun::star::chart::XDiagramPositioning > xPositioning( xChart1Doc->getDiagram(), UNO_QUERY_THROW ); + // set manual flag in chart data + if( !xPositioning->isAutomaticDiagramPositioning() ) + GetChartData().SetManualPlotArea(); + // the CHAXESSET record contains the inner plot area + maData.maRect = CalcChartRectFromHmm( xPositioning->calculateDiagramPositionExcludingAxes() ); + // the embedded CHFRAMEPOS record contains the outer plot area + mxFramePos.reset( new XclExpChFramePos( EXC_CHFRAMEPOS_PARENT, EXC_CHFRAMEPOS_PARENT ) ); + // for pie charts, always use inner plot area size to exclude the data labels as Excel does + const XclExpChTypeGroup* pFirstTypeGroup = GetFirstTypeGroup().get(); + bool bPieChart = pFirstTypeGroup && (pFirstTypeGroup->GetTypeInfo().meTypeCateg == EXC_CHTYPECATEG_PIE); + mxFramePos->GetFramePosData().maRect = bPieChart ? maData.maRect : + CalcChartRectFromHmm( xPositioning->calculateDiagramPositionIncludingAxes() ); + } + catch( Exception& ) + { + } + // return first unused chart type group index for next axes set return nGroupIdx; } @@ -2915,14 +3073,7 @@ bool XclExpChAxesSet::Is3dChart() const void XclExpChAxesSet::WriteSubRecords( XclExpStream& rStrm ) { - /* Need to set a reasonable size for the plot area, otherwise Excel will - move away embedded shapes while auto-sizing the plot area. This is just - a wild guess, but will be fixed with implementing manual positioning of - chart elements. */ - rStrm.StartRecord( EXC_ID_CHFRAMEPOS, 20 ); - rStrm << sal_uInt16(2) << sal_uInt16(2) << sal_uInt32(66) << sal_uInt32(626) << sal_uInt32(3384) << sal_uInt32(3231); - rStrm.EndRecord(); - + lclSaveRecord( rStrm, mxFramePos ); lclSaveRecord( rStrm, mxXAxis ); lclSaveRecord( rStrm, mxYAxis ); lclSaveRecord( rStrm, mxZAxis ); @@ -2974,10 +3125,10 @@ void XclExpChAxesSet::WriteBody( XclExpStream& rStrm ) // The chart object =========================================================== XclExpChChart::XclExpChChart( const XclExpRoot& rRoot, - Reference< XChartDocument > xChartDoc, const Size& rSize ) : - XclExpChGroupBase( XclExpChRoot( rRoot, this ), EXC_CHFRBLOCK_TYPE_CHART, EXC_ID_CHCHART, 16 ) + Reference< XChartDocument > xChartDoc, const Rectangle& rChartRect ) : + XclExpChGroupBase( XclExpChRoot( rRoot, *this ), EXC_CHFRBLOCK_TYPE_CHART, EXC_ID_CHCHART, 16 ) { - Size aPtSize = OutputDevice::LogicToLogic( rSize, MapMode( MAP_100TH_MM ), MapMode( MAP_POINT ) ); + Size aPtSize = OutputDevice::LogicToLogic( rChartRect.GetSize(), MapMode( MAP_100TH_MM ), MapMode( MAP_POINT ) ); // rectangle is stored in 16.16 fixed-point format maRect.mnX = maRect.mnY = 0; maRect.mnWidth = static_cast< sal_Int32 >( aPtSize.Width() << 16 ); @@ -3001,8 +3152,8 @@ XclExpChChart::XclExpChChart( const XclExpRoot& rRoot, bool bIncludeHidden = aDiagramProp.GetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS ); ::set_flag( maProps.mnFlags, EXC_CHPROPS_SHOWVISIBLEONLY, !bIncludeHidden ); - // initialize API conversion (remembers xChartDoc internally) - InitConversion( xChartDoc ); + // initialize API conversion (remembers xChartDoc and rChartRect internally) + InitConversion( xChartDoc, rChartRect ); // chart frame ScfPropertySet aFrameProp( xChartDoc->getPageBackground() ); @@ -3060,6 +3211,13 @@ void XclExpChChart::SetDataLabel( XclExpChTextRef xText ) maLabels.AppendRecord( xText ); } +void XclExpChChart::SetManualPlotArea() +{ + // this flag does not exist in BIFF5 + if( GetBiff() == EXC_BIFF8 ) + ::set_flag( maProps.mnFlags, EXC_CHPROPS_USEMANPLOTAREA ); +} + void XclExpChChart::WriteSubRecords( XclExpStream& rStrm ) { // background format @@ -3105,7 +3263,7 @@ XclExpChartDrawing::XclExpChartDrawing( const XclExpRoot& rRoot, /* Create a new independent object manager with own DFF stream for the DGCONTAINER, pass global manager as parent for shared usage of global DFF data (picture container etc.). */ - mxObjMgr.reset( new XclExpEmbeddedObjectManager( GetObjectManager(), rChartSize, EXC_CHART_UNIT, EXC_CHART_UNIT ) ); + mxObjMgr.reset( new XclExpEmbeddedObjectManager( GetObjectManager(), rChartSize, EXC_CHART_TOTALUNITS, EXC_CHART_TOTALUNITS ) ); // initialize the drawing object list mxObjMgr->StartSheet(); // process the draw page (convert all shapes) @@ -3128,17 +3286,17 @@ void XclExpChartDrawing::Save( XclExpStream& rStrm ) // ---------------------------------------------------------------------------- -XclExpChart::XclExpChart( const XclExpRoot& rRoot, Reference< XModel > xModel, const Size& rSize ) : +XclExpChart::XclExpChart( const XclExpRoot& rRoot, Reference< XModel > xModel, const Rectangle& rChartRect ) : XclExpSubStream( EXC_BOF_CHART ), XclExpRoot( rRoot ) { AppendNewRecord( new XclExpChartPageSettings( rRoot ) ); AppendNewRecord( new XclExpBoolRecord( EXC_ID_PROTECT, false ) ); - AppendNewRecord( new XclExpChartDrawing( rRoot, xModel, rSize ) ); + AppendNewRecord( new XclExpChartDrawing( rRoot, xModel, rChartRect.GetSize() ) ); AppendNewRecord( new XclExpUInt16Record( EXC_ID_CHUNITS, EXC_CHUNITS_TWIPS ) ); Reference< XChartDocument > xChartDoc( xModel, UNO_QUERY ); - AppendNewRecord( new XclExpChChart( rRoot, xChartDoc, rSize ) ); + AppendNewRecord( new XclExpChChart( rRoot, xChartDoc, rChartRect ) ); } // ============================================================================ diff --git a/sc/source/filter/excel/xeescher.cxx b/sc/source/filter/excel/xeescher.cxx index 2df531a9b932..a4b5864668b4 100644 --- a/sc/source/filter/excel/xeescher.cxx +++ b/sc/source/filter/excel/xeescher.cxx @@ -956,8 +956,8 @@ XclExpChartObj::XclExpChartObj( XclExpObjectManager& rObjMgr, Reference< XShape aShapeProp.GetProperty( xModel, CREATE_OUSTRING( "Model" ) ); ::com::sun::star::awt::Rectangle aBoundRect; aShapeProp.GetProperty( aBoundRect, CREATE_OUSTRING( "BoundRect" ) ); - Size aSize( aBoundRect.Width, aBoundRect.Height ); - mxChart.reset( new XclExpChart( GetRoot(), xModel, aSize ) ); + Rectangle aChartRect( Point( aBoundRect.X, aBoundRect.Y ), Size( aBoundRect.Width, aBoundRect.Height ) ); + mxChart.reset( new XclExpChart( GetRoot(), xModel, aChartRect ) ); } XclExpChartObj::~XclExpChartObj() diff --git a/sc/source/filter/excel/xichart.cxx b/sc/source/filter/excel/xichart.cxx index 1e386510b580..1eba311beab5 100644..100755 --- a/sc/source/filter/excel/xichart.cxx +++ b/sc/source/filter/excel/xichart.cxx @@ -37,12 +37,14 @@ #include <com/sun/star/drawing/Direction3D.hpp> #include <com/sun/star/drawing/ProjectionMode.hpp> #include <com/sun/star/drawing/ShadeMode.hpp> +#include <com/sun/star/drawing/XShape.hpp> #include <com/sun/star/drawing/XDrawPageSupplier.hpp> #include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp> #include <com/sun/star/chart/ChartAxisLabelPosition.hpp> #include <com/sun/star/chart/ChartAxisMarkPosition.hpp> #include <com/sun/star/chart/ChartAxisPosition.hpp> #include <com/sun/star/chart/XChartDocument.hpp> +#include <com/sun/star/chart/XDiagramPositioning.hpp> #include <com/sun/star/chart2/XChartDocument.hpp> #include <com/sun/star/chart2/XDiagram.hpp> #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> @@ -57,8 +59,11 @@ #include <com/sun/star/chart2/CurveStyle.hpp> #include <com/sun/star/chart2/DataPointGeometry3D.hpp> #include <com/sun/star/chart2/DataPointLabel.hpp> +#include <com/sun/star/chart2/LegendExpansion.hpp> +#include <com/sun/star/chart2/LegendPosition.hpp> #include <com/sun/star/chart2/StackingDirection.hpp> #include <com/sun/star/chart2/TickmarkStyle.hpp> +#include <com/sun/star/chart2/RelativePosition.hpp> #include <com/sun/star/chart/DataLabelPlacement.hpp> #include <com/sun/star/chart/ErrorBarStyle.hpp> #include <com/sun/star/chart/MissingValueTreatment.hpp> @@ -98,36 +103,41 @@ using ::com::sun::star::frame::XModel; using ::com::sun::star::util::XNumberFormatsSupplier; using ::com::sun::star::drawing::XDrawPage; using ::com::sun::star::drawing::XDrawPageSupplier; +using ::com::sun::star::drawing::XShape; +using ::com::sun::star::chart2::IncrementData; +using ::com::sun::star::chart2::RelativePosition; +using ::com::sun::star::chart2::ScaleData; +using ::com::sun::star::chart2::SubIncrement; +using ::com::sun::star::chart2::XAxis; using ::com::sun::star::chart2::XChartDocument; -using ::com::sun::star::chart2::XDiagram; -using ::com::sun::star::chart2::XCoordinateSystemContainer; -using ::com::sun::star::chart2::XCoordinateSystem; -using ::com::sun::star::chart2::XChartTypeContainer; using ::com::sun::star::chart2::XChartType; -using ::com::sun::star::chart2::XDataSeriesContainer; +using ::com::sun::star::chart2::XChartTypeContainer; +using ::com::sun::star::chart2::XCoordinateSystem; +using ::com::sun::star::chart2::XCoordinateSystemContainer; using ::com::sun::star::chart2::XDataSeries; +using ::com::sun::star::chart2::XDataSeriesContainer; +using ::com::sun::star::chart2::XDiagram; +using ::com::sun::star::chart2::XFormattedString; +using ::com::sun::star::chart2::XLegend; using ::com::sun::star::chart2::XRegressionCurve; using ::com::sun::star::chart2::XRegressionCurveContainer; -using ::com::sun::star::chart2::XAxis; using ::com::sun::star::chart2::XScaling; -using ::com::sun::star::chart2::ScaleData; -using ::com::sun::star::chart2::IncrementData; -using ::com::sun::star::chart2::SubIncrement; -using ::com::sun::star::chart2::XLegend; -using ::com::sun::star::chart2::XTitled; using ::com::sun::star::chart2::XTitle; -using ::com::sun::star::chart2::XFormattedString; +using ::com::sun::star::chart2::XTitled; using ::com::sun::star::chart2::data::XDataProvider; using ::com::sun::star::chart2::data::XDataReceiver; +using ::com::sun::star::chart2::data::XDataSequence; using ::com::sun::star::chart2::data::XDataSink; using ::com::sun::star::chart2::data::XLabeledDataSequence; -using ::com::sun::star::chart2::data::XDataSequence; using ::formula::FormulaToken; using ::formula::StackVar; +namespace cssc = ::com::sun::star::chart; +namespace cssc2 = ::com::sun::star::chart2; + // Helpers ==================================================================== namespace { @@ -158,28 +168,18 @@ void lclSetExpValueOrClearAny( Any& rAny, double fValue, bool bLogScale, bool bC // Common ===================================================================== /** Stores global data needed in various classes of the Chart import filter. */ -class XclImpChRootData : public XclChRootData +struct XclImpChRootData : public XclChRootData { -public: - explicit XclImpChRootData( XclImpChChart* pChartData ); + XclImpChChart& mrChartData; /// The chart data object. - /** Returns a reference to the parent chart data object. */ - inline XclImpChChart& GetChartData() const { return *mpChartData; } - -private: - XclImpChChart* mpChartData; /// Pointer to the chart data object. + inline explicit XclImpChRootData( XclImpChChart& rChartData ) : mrChartData( rChartData ) {} }; -XclImpChRootData::XclImpChRootData( XclImpChChart* pChartData ) : - mpChartData( pChartData ) -{ -} - // ---------------------------------------------------------------------------- -XclImpChRoot::XclImpChRoot( const XclImpRoot& rRoot, XclImpChChart* pChartData ) : +XclImpChRoot::XclImpChRoot( const XclImpRoot& rRoot, XclImpChChart& rChartData ) : XclImpRoot( rRoot ), - mxChData( new XclImpChRootData( pChartData ) ) + mxChData( new XclImpChRootData( rChartData ) ) { } @@ -189,22 +189,22 @@ XclImpChRoot::~XclImpChRoot() XclImpChChart& XclImpChRoot::GetChartData() const { - return mxChData->GetChartData(); + return mxChData->mrChartData; } const XclChTypeInfo& XclImpChRoot::GetChartTypeInfo( XclChTypeId eType ) const { - return mxChData->GetTypeInfoProvider().GetTypeInfo( eType ); + return mxChData->mxTypeInfoProv->GetTypeInfo( eType ); } const XclChTypeInfo& XclImpChRoot::GetChartTypeInfo( sal_uInt16 nRecId ) const { - return mxChData->GetTypeInfoProvider().GetTypeInfoFromRecId( nRecId ); + return mxChData->mxTypeInfoProv->GetTypeInfoFromRecId( nRecId ); } const XclChFormatInfo& XclImpChRoot::GetFormatInfo( XclChObjectType eObjType ) const { - return mxChData->GetFormatInfoProvider().GetFormatInfo( eObjType ); + return mxChData->mxFmtInfoProv->GetFormatInfo( eObjType ); } Color XclImpChRoot::GetFontAutoColor() const @@ -225,10 +225,10 @@ Color XclImpChRoot::GetSeriesFillAutoColor( sal_uInt16 nFormatIdx ) const return ScfTools::GetMixedColor( aColor, rPal.GetColor( EXC_COLOR_CHWINDOWBACK ), nTrans ); } -void XclImpChRoot::InitConversion( Reference< XChartDocument > xChartDoc ) const +void XclImpChRoot::InitConversion( Reference< XChartDocument > xChartDoc, const Rectangle& rChartRect ) const { // create formatting object tables - mxChData->InitConversion( xChartDoc ); + mxChData->InitConversion( GetRoot(), xChartDoc, rChartRect ); // lock the model to suppress any internal updates Reference< XModel > xModel( xChartDoc, UNO_QUERY ); @@ -255,7 +255,7 @@ void XclImpChRoot::FinishConversion( XclImpDffConverter& rDffConv ) const { rDffConv.Progress( EXC_CHART_PROGRESS_SIZE ); // unlock the model - Reference< XModel > xModel( mxChData->GetChartDoc(), UNO_QUERY ); + Reference< XModel > xModel( mxChData->mxChartDoc, UNO_QUERY ); if( xModel.is() ) xModel->unlockControllers(); rDffConv.Progress( EXC_CHART_PROGRESS_SIZE ); @@ -265,14 +265,48 @@ void XclImpChRoot::FinishConversion( XclImpDffConverter& rDffConv ) const Reference< XDataProvider > XclImpChRoot::GetDataProvider() const { - return mxChData->GetChartDoc()->getDataProvider(); + return mxChData->mxChartDoc->getDataProvider(); +} + +Reference< XShape > XclImpChRoot::GetTitleShape( const XclChTextKey& rTitleKey ) const +{ + return mxChData->GetTitleShape( rTitleKey ); +} + +sal_Int32 XclImpChRoot::CalcHmmFromChartX( sal_Int32 nPosX ) const +{ + return static_cast< sal_Int32 >( mxChData->mfUnitSizeX * nPosX + mxChData->mnBorderGapX + 0.5 ); +} + +sal_Int32 XclImpChRoot::CalcHmmFromChartY( sal_Int32 nPosY ) const +{ + return static_cast< sal_Int32 >( mxChData->mfUnitSizeY * nPosY + mxChData->mnBorderGapY + 0.5 ); +} + +::com::sun::star::awt::Rectangle XclImpChRoot::CalcHmmFromChartRect( const XclChRectangle& rRect ) const +{ + return ::com::sun::star::awt::Rectangle( + CalcHmmFromChartX( rRect.mnX ), + CalcHmmFromChartY( rRect.mnY ), + CalcHmmFromChartX( rRect.mnWidth ), + CalcHmmFromChartY( rRect.mnHeight ) ); +} + +double XclImpChRoot::CalcRelativeFromChartX( sal_Int32 nPosX ) const +{ + return static_cast< double >( CalcHmmFromChartX( nPosX ) ) / mxChData->maChartRect.GetWidth(); +} + +double XclImpChRoot::CalcRelativeFromChartY( sal_Int32 nPosY ) const +{ + return static_cast< double >( CalcHmmFromChartY( nPosY ) ) / mxChData->maChartRect.GetHeight(); } void XclImpChRoot::ConvertLineFormat( ScfPropertySet& rPropSet, const XclChLineFormat& rLineFmt, XclChPropertyMode ePropMode ) const { GetChartPropSetHelper().WriteLineProperties( - rPropSet, mxChData->GetLineDashTable(), rLineFmt, ePropMode ); + rPropSet, *mxChData->mxLineDashTable, rLineFmt, ePropMode ); } void XclImpChRoot::ConvertAreaFormat( ScfPropertySet& rPropSet, @@ -286,7 +320,7 @@ void XclImpChRoot::ConvertEscherFormat( ScfPropertySet& rPropSet, XclChPropertyMode ePropMode ) const { GetChartPropSetHelper().WriteEscherProperties( rPropSet, - mxChData->GetGradientTable(), mxChData->GetHatchTable(), mxChData->GetBitmapTable(), + *mxChData->mxGradientTable, *mxChData->mxHatchTable, *mxChData->mxBitmapTable, rEscherFmt, rPicFmt, ePropMode ); } @@ -357,7 +391,13 @@ void XclImpChGroupBase::SkipBlock( XclImpStream& rStrm ) void XclImpChFramePos::ReadChFramePos( XclImpStream& rStrm ) { - rStrm >> maData.mnObjType >> maData.mnSizeMode >> maData.maRect; + rStrm >> maData.mnTLMode >> maData.mnBRMode; + /* According to the spec, the upper 16 bits of all members in the + rectangle are unused and may contain garbage. */ + maData.maRect.mnX = rStrm.ReadInt16(); rStrm.Ignore( 2 ); + maData.maRect.mnY = rStrm.ReadInt16(); rStrm.Ignore( 2 ); + maData.maRect.mnWidth = rStrm.ReadInt16(); rStrm.Ignore( 2 ); + maData.maRect.mnHeight = rStrm.ReadInt16(); rStrm.Ignore( 2 ); } // ---------------------------------------------------------------------------- @@ -862,9 +902,7 @@ void XclImpChText::ReadHeaderRecord( XclImpStream& rStrm ) // #116397# BIFF8: index into palette used instead of RGB data maData.maTextColor = GetPalette().GetColor( rStrm.ReaduInt16() ); // placement and rotation - rStrm >> maData.mnPlacement >> maData.mnRotation; - // lower 4 bits used for placement, other bits contain garbage - maData.mnPlacement &= 0x000F; + rStrm >> maData.mnFlags2 >> maData.mnRotation; } else { @@ -878,6 +916,10 @@ void XclImpChText::ReadSubRecord( XclImpStream& rStrm ) { switch( rStrm.GetRecId() ) { + case EXC_ID_CHFRAMEPOS: + mxFramePos.reset( new XclImpChFramePos ); + mxFramePos->ReadChFramePos( rStrm ); + break; case EXC_ID_CHFONT: mxFont.reset( new XclImpChFont ); mxFont->ReadChFont( rStrm ); @@ -1002,8 +1044,7 @@ void XclImpChText::ConvertDataLabel( ScfPropertySet& rPropSet, const XclChTypeIn bool bShowSymbol = bShowAny && ::get_flag( maData.mnFlags, EXC_CHTEXT_SHOWSYMBOL ); // create API struct for label values, set API label separator - namespace cssc = ::com::sun::star::chart2; - cssc::DataPointLabel aPointLabel( bShowValue, bShowPercent, bShowCateg, bShowSymbol ); + cssc2::DataPointLabel aPointLabel( bShowValue, bShowPercent, bShowCateg, bShowSymbol ); rPropSet.SetProperty( EXC_CHPROP_LABEL, aPointLabel ); String aSep = mxLabelProps.is() ? mxLabelProps->maSeparator : String( sal_Unicode( '\n' ) ); if( aSep.Len() == 0 ) @@ -1016,9 +1057,9 @@ void XclImpChText::ConvertDataLabel( ScfPropertySet& rPropSet, const XclChTypeIn ConvertFont( rPropSet ); ConvertRotation( rPropSet, false ); // label placement - using namespace ::com::sun::star::chart::DataLabelPlacement; + using namespace cssc::DataLabelPlacement; sal_Int32 nPlacement = rTypeInfo.mnDefaultLabelPos; - switch( maData.mnPlacement ) + switch( ::extract_value< sal_uInt16 >( maData.mnFlags2, 0, 4 ) ) { case EXC_CHTEXT_POS_DEFAULT: nPlacement = rTypeInfo.mnDefaultLabelPos; break; case EXC_CHTEXT_POS_OUTSIDE: nPlacement = OUTSIDE; break; @@ -1064,6 +1105,62 @@ Reference< XTitle > XclImpChText::CreateTitle() const return xTitle; } +void XclImpChText::ConvertTitlePosition( const XclChTextKey& rTitleKey ) const +{ + if( !mxFramePos ) return; + + const XclChFramePos& rPosData = mxFramePos->GetFramePosData(); + OSL_ENSURE( (rPosData.mnTLMode == EXC_CHFRAMEPOS_PARENT) && (rPosData.mnBRMode == EXC_CHFRAMEPOS_PARENT), + "XclImpChText::ConvertTitlePosition - unexpected frame position mode" ); + + /* Check if title is moved manually. To get the actual position of the + title, we do some kind of hack and use the values from the CHTEXT + record, effectively ignoring the contents of the CHFRAMEPOS record + which contains the position relative to the default title position + (according to the spec, the CHFRAMEPOS supersedes the CHTEXT record). + Especially when it comes to axis titles, things would become very + complicated here, because the relative title position is stored in a + measurement unit that is dependent on the size of the inner plot area, + the interpretation of the X and Y coordinate is dependent on the + direction of the axis, and in 3D charts, and the title default + positions are dependent on the 3D view settings (rotation, elevation, + and perspective). Thus, it is easier to assume that the creator has + written out the correct absolute position and size of the title in the + CHTEXT record. This is assured by checking that the shape size stored + in the CHTEXT record is non-zero. */ + if( (rPosData.mnTLMode == EXC_CHFRAMEPOS_PARENT) && + ((rPosData.maRect.mnX != 0) || (rPosData.maRect.mnY != 0)) && + (maData.maRect.mnWidth > 0) && (maData.maRect.mnHeight > 0) ) try + { + Reference< XShape > xTitleShape( GetTitleShape( rTitleKey ), UNO_SET_THROW ); + // the call to XShape.getSize() may recalc the chart view + ::com::sun::star::awt::Size aTitleSize = xTitleShape->getSize(); + // rotated titles need special handling... + sal_Int32 nScRot = XclTools::GetScRotation( GetRotation(), 0 ); + double fRad = nScRot * F_PI18000; + double fSin = fabs( sin( fRad ) ); + double fCos = fabs( cos( fRad ) ); + ::com::sun::star::awt::Size aBoundSize( + static_cast< sal_Int32 >( fCos * aTitleSize.Width + fSin * aTitleSize.Height + 0.5 ), + static_cast< sal_Int32 >( fSin * aTitleSize.Width + fCos * aTitleSize.Height + 0.5 ) ); + // calculate the title position from the values in the CHTEXT record + ::com::sun::star::awt::Point aTitlePos( + CalcHmmFromChartX( maData.maRect.mnX ), + CalcHmmFromChartY( maData.maRect.mnY ) ); + // add part of height to X direction, if title is rotated down (clockwise) + if( nScRot > 18000 ) + aTitlePos.X += static_cast< sal_Int32 >( fSin * aTitleSize.Height + 0.5 ); + // add part of width to Y direction, if title is rotated up (counterclockwise) + else if( nScRot > 0 ) + aTitlePos.Y += static_cast< sal_Int32 >( fSin * aTitleSize.Width + 0.5 ); + // set the resulting position at the title shape + xTitleShape->setPosition( aTitlePos ); + } + catch( Exception& ) + { + } +} + void XclImpChText::ReadChFrLabelProps( XclImpStream& rStrm ) { if( GetBiff() == EXC_BIFF8 ) @@ -1087,12 +1184,14 @@ void lclUpdateText( XclImpChTextRef& rxText, XclImpChTextRef xDefText ) rxText = xDefText; } -void lclFinalizeTitle( XclImpChTextRef& rxTitle, XclImpChTextRef xDefText ) +void lclFinalizeTitle( XclImpChTextRef& rxTitle, XclImpChTextRef xDefText, const String& rAutoTitle ) { /* Do not update a title, if it is not visible (if rxTitle is null). Existing reference indicates enabled title. */ if( rxTitle.is() ) { + if( !rxTitle->HasString() ) + rxTitle->SetString( rAutoTitle ); if( rxTitle->HasString() ) rxTitle->UpdateText( xDefText.get() ); else @@ -1544,7 +1643,6 @@ Reference< XPropertySet > XclImpChSerErrorBar::CreateErrorBar( const XclImpChSer aBarProp.SetBoolProperty( EXC_CHPROP_SHOWNEGATIVEERROR, pNegBar != 0 ); // type of displayed error - namespace cssc = ::com::sun::star::chart; switch( pPrimaryBar->maData.mnSourceType ) { case EXC_CHSERERR_PERCENT: @@ -2281,6 +2379,10 @@ void XclImpChLegend::ReadSubRecord( XclImpStream& rStrm ) { switch( rStrm.GetRecId() ) { + case EXC_ID_CHFRAMEPOS: + mxFramePos.reset( new XclImpChFramePos ); + mxFramePos->ReadChFramePos( rStrm ); + break; case EXC_ID_CHTEXT: mxText.reset( new XclImpChText( GetChRoot() ) ); mxText->ReadRecordGroup( rStrm ); @@ -2307,6 +2409,7 @@ Reference< XLegend > XclImpChLegend::CreateLegend() const if( xLegend.is() ) { ScfPropertySet aLegendProp( xLegend ); + aLegendProp.SetBoolProperty( EXC_CHPROP_SHOW, true ); // frame properties if( mxFrame.is() ) @@ -2314,8 +2417,69 @@ Reference< XLegend > XclImpChLegend::CreateLegend() const // text properties if( mxText.is() ) mxText->ConvertFont( aLegendProp ); - // special legend properties - GetChartPropSetHelper().WriteLegendProperties( aLegendProp, maData ); + + /* Legend position and size. Default positions are used only if the + plot area is positioned automatically (Excel sets the plot area to + manual mode, if the legend is moved or resized). With manual plot + areas, Excel ignores the value in maData.mnDockMode completely. */ + cssc2::LegendPosition eApiPos = cssc2::LegendPosition_CUSTOM; + cssc2::LegendExpansion eApiExpand = cssc2::LegendExpansion_BALANCED; + if( !GetChartData().IsManualPlotArea() ) switch( maData.mnDockMode ) + { + case EXC_CHLEGEND_LEFT: eApiPos = cssc2::LegendPosition_LINE_START; eApiExpand = cssc2::LegendExpansion_HIGH; break; + case EXC_CHLEGEND_RIGHT: eApiPos = cssc2::LegendPosition_LINE_END; eApiExpand = cssc2::LegendExpansion_HIGH; break; + case EXC_CHLEGEND_TOP: eApiPos = cssc2::LegendPosition_PAGE_START; eApiExpand = cssc2::LegendExpansion_WIDE; break; + case EXC_CHLEGEND_BOTTOM: eApiPos = cssc2::LegendPosition_PAGE_END; eApiExpand = cssc2::LegendExpansion_WIDE; break; + // top-right not supported + case EXC_CHLEGEND_CORNER: eApiPos = cssc2::LegendPosition_LINE_END; eApiExpand = cssc2::LegendExpansion_HIGH; break; + } + + // no automatic position: try to find the correct position and size + if( eApiPos == cssc2::LegendPosition_CUSTOM ) + { + const XclChFramePos* pFramePos = mxFramePos.is() ? &mxFramePos->GetFramePosData() : 0; + + /* Legend position. Only the settings from the CHFRAMEPOS record + are used by Excel, the position in the CHLEGEND record will be + ignored. */ + if( pFramePos ) + { + RelativePosition aRelPos; + aRelPos.Primary = CalcRelativeFromChartX( pFramePos->maRect.mnX ); + aRelPos.Secondary = CalcRelativeFromChartY( pFramePos->maRect.mnY ); + aRelPos.Anchor = ::com::sun::star::drawing::Alignment_TOP_LEFT; + aLegendProp.SetProperty( EXC_CHPROP_RELATIVEPOSITION, aRelPos ); + } + else + { + // no manual position found, just go for the default + eApiPos = cssc2::LegendPosition_LINE_END; + } + + + /* Legend size. #i71697# It is not possible to set the legend size + directly in the Chart, do some magic here. */ + if( !pFramePos || (pFramePos->mnBRMode != EXC_CHFRAMEPOS_ABSSIZE_POINTS) || + (pFramePos->maRect.mnWidth == 0) || (pFramePos->maRect.mnHeight == 0) ) + { + // automatic size: determine entry direction from flags + eApiExpand = ::get_flagvalue( maData.mnFlags, EXC_CHLEGEND_STACKED, + cssc2::LegendExpansion_HIGH, cssc2::LegendExpansion_WIDE ); + } + else + { + // legend size is given in points, not in chart units + double fRatio = static_cast< double >( pFramePos->maRect.mnWidth ) / pFramePos->maRect.mnHeight; + if( fRatio > 1.5 ) + eApiExpand = cssc2::LegendExpansion_WIDE; + else if( fRatio < 0.75 ) + eApiExpand = cssc2::LegendExpansion_HIGH; + else + eApiExpand = cssc2::LegendExpansion_BALANCED; + } + } + aLegendProp.SetProperty( EXC_CHPROP_ANCHORPOSITION, eApiPos ); + aLegendProp.SetProperty( EXC_CHPROP_EXPANSION, eApiExpand ); } return xLegend; } @@ -2358,7 +2522,8 @@ XclImpChTypeGroup::XclImpChTypeGroup( const XclImpChRoot& rRoot ) : void XclImpChTypeGroup::ReadHeaderRecord( XclImpStream& rStrm ) { - rStrm >> maData.maRect >> maData.mnFlags >> maData.mnGroupIdx; + rStrm.Ignore( 16 ); + rStrm >> maData.mnFlags >> maData.mnGroupIdx; } void XclImpChTypeGroup::ReadSubRecord( XclImpStream& rStrm ) @@ -2548,13 +2713,12 @@ void XclImpChTypeGroup::InsertDataSeries( Reference< XChartType > xChartType, if( xSeriesCont.is() && xSeries.is() ) { // series stacking mode - namespace cssc = ::com::sun::star::chart2; - cssc::StackingDirection eStacking = cssc::StackingDirection_NO_STACKING; + cssc2::StackingDirection eStacking = cssc2::StackingDirection_NO_STACKING; // stacked overrides deep-3d if( maType.IsStacked() || maType.IsPercent() ) - eStacking = cssc::StackingDirection_Y_STACKING; + eStacking = cssc2::StackingDirection_Y_STACKING; else if( Is3dDeepChart() ) - eStacking = cssc::StackingDirection_Z_STACKING; + eStacking = cssc2::StackingDirection_Z_STACKING; // additional series properties ScfPropertySet aSeriesProp( xSeries ); @@ -2674,11 +2838,9 @@ void XclImpChLabelRange::Convert( ScfPropertySet& rPropSet, ScaleData& rScaleDat // do not break text into several lines unless all labels are visible rPropSet.SetBoolProperty( EXC_CHPROP_TEXTBREAK, maData.mnLabelFreq == 1 ); // do not stagger labels in two lines - namespace cssc = ::com::sun::star::chart; rPropSet.SetProperty( EXC_CHPROP_ARRANGEORDER, cssc::ChartAxisArrangeOrderType_SIDE_BY_SIDE ); // reverse order - namespace cssc2 = ::com::sun::star::chart2; bool bReverse = ::get_flag( maData.mnFlags, EXC_CHLABELRANGE_REVERSE ) != bMirrorOrient; rScaleData.Orientation = bReverse ? cssc2::AxisOrientation_REVERSE : cssc2::AxisOrientation_MATHEMATICAL; @@ -2692,7 +2854,6 @@ void XclImpChLabelRange::ConvertAxisPosition( ScfPropertySet& rPropSet, bool b3d But: the Y axis has to be moved to "end", if the X axis is mirrored, to keep it at the left end of the chart. */ bool bMaxCross = ::get_flag( maData.mnFlags, b3dChart ? EXC_CHLABELRANGE_REVERSE : EXC_CHLABELRANGE_MAXCROSS ); - namespace cssc = ::com::sun::star::chart; cssc::ChartAxisPosition eAxisPos = bMaxCross ? cssc::ChartAxisPosition_END : cssc::ChartAxisPosition_VALUE; rPropSet.SetProperty( EXC_CHPROP_CROSSOVERPOSITION, eAxisPos ); @@ -2756,7 +2917,6 @@ void XclImpChValueRange::Convert( ScaleData& rScaleData, bool bMirrorOrient ) co } // reverse order - namespace cssc2 = ::com::sun::star::chart2; bool bReverse = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_REVERSE ) != bMirrorOrient; rScaleData.Orientation = bReverse ? cssc2::AxisOrientation_REVERSE : cssc2::AxisOrientation_MATHEMATICAL; } @@ -2768,7 +2928,6 @@ void XclImpChValueRange::ConvertAxisPosition( ScfPropertySet& rPropSet ) const bool bLogScale = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_LOGSCALE ); // crossing mode (max-cross flag overrides other crossing settings) - namespace cssc = ::com::sun::star::chart; cssc::ChartAxisPosition eAxisPos = bMaxCross ? cssc::ChartAxisPosition_END : cssc::ChartAxisPosition_VALUE; rPropSet.SetProperty( EXC_CHPROP_CROSSOVERPOSITION, eAxisPos ); @@ -2791,7 +2950,7 @@ sal_Int32 lclGetApiTickmarks( sal_uInt8 nXclTickPos ) return nApiTickmarks; } -::com::sun::star::chart::ChartAxisLabelPosition lclGetApiLabelPosition( sal_Int8 nXclLabelPos ) +cssc::ChartAxisLabelPosition lclGetApiLabelPosition( sal_Int8 nXclLabelPos ) { using namespace ::com::sun::star::chart; switch( nXclLabelPos ) @@ -2815,9 +2974,9 @@ void XclImpChTick::ReadChTick( XclImpStream& rStrm ) rStrm >> maData.mnMajor >> maData.mnMinor >> maData.mnLabelPos - >> maData.mnBackMode - >> maData.maRect - >> maData.maTextColor + >> maData.mnBackMode; + rStrm.Ignore( 16 ); + rStrm >> maData.maTextColor >> maData.mnFlags; if( GetBiff() == EXC_BIFF8 ) @@ -2850,7 +3009,7 @@ void XclImpChTick::Convert( ScfPropertySet& rPropSet ) const rPropSet.SetProperty( EXC_CHPROP_MAJORTICKS, lclGetApiTickmarks( maData.mnMajor ) ); rPropSet.SetProperty( EXC_CHPROP_MINORTICKS, lclGetApiTickmarks( maData.mnMinor ) ); rPropSet.SetProperty( EXC_CHPROP_LABELPOSITION, lclGetApiLabelPosition( maData.mnLabelPos ) ); - rPropSet.SetProperty( EXC_CHPROP_MARKPOSITION, ::com::sun::star::chart::ChartAxisMarkPosition_AT_AXIS ); + rPropSet.SetProperty( EXC_CHPROP_MARKPOSITION, cssc::ChartAxisMarkPosition_AT_AXIS ); } // ---------------------------------------------------------------------------- @@ -2864,7 +3023,7 @@ XclImpChAxis::XclImpChAxis( const XclImpChRoot& rRoot, sal_uInt16 nAxisType ) : void XclImpChAxis::ReadHeaderRecord( XclImpStream& rStrm ) { - rStrm >> maData.mnType >> maData.maRect; + rStrm >> maData.mnType; } void XclImpChAxis::ReadSubRecord( XclImpStream& rStrm ) @@ -2941,8 +3100,6 @@ sal_uInt16 XclImpChAxis::GetRotation() const Reference< XAxis > XclImpChAxis::CreateAxis( const XclImpChTypeGroup& rTypeGroup, const XclImpChAxis* pCrossingAxis ) const { - namespace cssc2 = ::com::sun::star::chart2; - // create the axis object (always) Reference< XAxis > xAxis( ScfApiHelper::CreateInstance( SERVICE_CHART2_AXIS ), UNO_QUERY ); if( xAxis.is() ) @@ -3136,8 +3293,8 @@ void XclImpChAxesSet::ReadSubRecord( XclImpStream& rStrm ) switch( rStrm.GetRecId() ) { case EXC_ID_CHFRAMEPOS: - mxPos.reset( new XclImpChFramePos ); - mxPos->ReadChFramePos( rStrm ); + mxFramePos.reset( new XclImpChFramePos ); + mxFramePos->ReadChFramePos( rStrm ); break; case EXC_ID_CHAXIS: ReadChAxis( rStrm ); @@ -3188,9 +3345,10 @@ void XclImpChAxesSet::Finalize() // finalize axis titles XclImpChTextRef xDefText = GetChartData().GetDefaultText( EXC_CHTEXTTYPE_AXISTITLE ); - lclFinalizeTitle( mxXAxisTitle, xDefText ); - lclFinalizeTitle( mxYAxisTitle, xDefText ); - lclFinalizeTitle( mxZAxisTitle, xDefText ); + String aAutoTitle = CREATE_STRING( "Axis Title" ); + lclFinalizeTitle( mxXAxisTitle, xDefText, aAutoTitle ); + lclFinalizeTitle( mxYAxisTitle, xDefText, aAutoTitle ); + lclFinalizeTitle( mxZAxisTitle, xDefText, aAutoTitle ); // #i47745# missing plot frame -> invisible border and area if( !mxPlotFrame ) @@ -3252,6 +3410,16 @@ void XclImpChAxesSet::Convert( Reference< XDiagram > xDiagram ) const } } +void XclImpChAxesSet::ConvertTitlePositions() const +{ + if( mxXAxisTitle.is() ) + mxXAxisTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, maData.mnAxesSetId, EXC_CHAXIS_X ) ); + if( mxYAxisTitle.is() ) + mxYAxisTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, maData.mnAxesSetId, EXC_CHAXIS_Y ) ); + if( mxZAxisTitle.is() ) + mxZAxisTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, maData.mnAxesSetId, EXC_CHAXIS_Z ) ); +} + void XclImpChAxesSet::ReadChAxis( XclImpStream& rStrm ) { XclImpChAxisRef xAxis( new XclImpChAxis( GetChRoot() ) ); @@ -3358,11 +3526,15 @@ void XclImpChAxesSet::ConvertAxis( if( xAxis.is() ) { // create and attach the axis title - if( xChAxisTitle.is() ) + if( xChAxisTitle.is() ) try { - Reference< XTitled > xTitled( xAxis, UNO_QUERY ); - if( xTitled.is() ) - xTitled->setTitleObject( xChAxisTitle->CreateTitle() ); + Reference< XTitled > xTitled( xAxis, UNO_QUERY_THROW ); + Reference< XTitle > xTitle( xChAxisTitle->CreateTitle(), UNO_SET_THROW ); + xTitled->setTitleObject( xTitle ); + } + catch( Exception& ) + { + DBG_ERRORFILE( "XclImpChAxesSet::ConvertAxis - cannot set axis title" ); } // insert axis into coordinate system @@ -3416,7 +3588,7 @@ void XclImpChAxesSet::ConvertBackground( Reference< XDiagram > xDiagram ) const // The chart object =========================================================== XclImpChChart::XclImpChChart( const XclImpRoot& rRoot ) : - XclImpChRoot( rRoot, this ) + XclImpChRoot( rRoot, *this ) { mxPrimAxesSet.reset( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_PRIMARY ) ); mxSecnAxesSet.reset( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_SECONDARY ) ); @@ -3516,23 +3688,34 @@ XclImpChTextRef XclImpChChart::GetDefaultText( XclChTextType eTextType ) const return maDefTexts.get( nDefTextId ); } -void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc, XclImpDffConverter& rDffConv, const OUString& rObjName ) const +bool XclImpChChart::IsManualPlotArea() const +{ + // there is no real automatic mode in BIFF5 charts + return (GetBiff() <= EXC_BIFF5) || ::get_flag( maProps.mnFlags, EXC_CHPROPS_USEMANPLOTAREA ); +} + +void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc, + XclImpDffConverter& rDffConv, const OUString& rObjName, const Rectangle& rChartRect ) const { // initialize conversion (locks the model to suppress any internal updates) - InitConversion( xChartDoc ); + InitConversion( xChartDoc, rChartRect ); - // chart frame and title + // chart frame formatting if( mxFrame.is() ) { ScfPropertySet aFrameProp( xChartDoc->getPageBackground() ); mxFrame->Convert( aFrameProp ); } - if( mxTitle.is() ) + + // chart title + if( mxTitle.is() ) try + { + Reference< XTitled > xTitled( xChartDoc, UNO_QUERY_THROW ); + Reference< XTitle > xTitle( mxTitle->CreateTitle(), UNO_SET_THROW ); + xTitled->setTitleObject( xTitle ); + } + catch( Exception& ) { - Reference< XTitled > xTitled( xChartDoc, UNO_QUERY ); - Reference< XTitle > xTitle = mxTitle->CreateTitle(); - if( xTitled.is() && xTitle.is() ) - xTitled->setTitleObject( xTitle ); } /* Create the diagram object and attach it to the chart document. Currently, @@ -3548,13 +3731,48 @@ void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc, XclImpDffCon if( xDiagram.is() && mxLegend.is() ) xDiagram->setLegend( mxLegend->CreateLegend() ); - // set the IncludeHiddenCells property via the old API as only this ensures that the data provider and al created sequences get this flag correctly - Reference< com::sun::star::chart::XChartDocument > xStandardApiChartDoc( xChartDoc, UNO_QUERY ); - if( xStandardApiChartDoc.is() ) + /* Following all conversions needing the old Chart1 API that involves full + initialization of the chart view. */ + Reference< cssc::XChartDocument > xChart1Doc( xChartDoc, UNO_QUERY ); + if( xChart1Doc.is() ) { - ScfPropertySet aDiagramProp( xStandardApiChartDoc->getDiagram() ); - bool bShowVisCells = (maProps.mnFlags & EXC_CHPROPS_SHOWVISIBLEONLY); - aDiagramProp.SetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS, !bShowVisCells ); + Reference< cssc::XDiagram > xDiagram1 = xChart1Doc->getDiagram(); + + /* Set the 'IncludeHiddenCells' property via the old API as only this + ensures that the data provider and all created sequences get this + flag correctly. */ + ScfPropertySet aDiaProp( xDiagram1 ); + bool bShowVisCells = ::get_flag( maProps.mnFlags, EXC_CHPROPS_SHOWVISIBLEONLY ); + aDiaProp.SetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS, !bShowVisCells ); + + // plot area position and size (there is no real automatic mode in BIFF5 charts) + XclImpChFramePosRef xPlotAreaPos = mxPrimAxesSet->GetPlotAreaFramePos(); + if( IsManualPlotArea() && xPlotAreaPos.is() ) try + { + const XclChFramePos& rFramePos = xPlotAreaPos->GetFramePosData(); + if( (rFramePos.mnTLMode == EXC_CHFRAMEPOS_PARENT) && (rFramePos.mnBRMode == EXC_CHFRAMEPOS_PARENT) ) + { + Reference< cssc::XDiagramPositioning > xPositioning( xDiagram1, UNO_QUERY_THROW ); + ::com::sun::star::awt::Rectangle aDiagramRect = CalcHmmFromChartRect( rFramePos.maRect ); + // for pie charts, always set inner plot area size to exclude the data labels as Excel does + const XclImpChTypeGroup* pFirstTypeGroup = mxPrimAxesSet->GetFirstTypeGroup().get(); + if( pFirstTypeGroup && (pFirstTypeGroup->GetTypeInfo().meTypeCateg == EXC_CHTYPECATEG_PIE) ) + xPositioning->setDiagramPositionExcludingAxes( aDiagramRect ); + else if( pFirstTypeGroup && pFirstTypeGroup->Is3dChart() ) + xPositioning->setDiagramPositionIncludingAxesAndAxisTitles( aDiagramRect ); + else + xPositioning->setDiagramPositionIncludingAxes( aDiagramRect ); + } + } + catch( Exception& ) + { + } + + // positions of all title objects + if( mxTitle.is() ) + mxTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_TITLE ) ); + mxPrimAxesSet->ConvertTitlePositions(); + mxSecnAxesSet->ConvertTitlePositions(); } // unlock the model @@ -3689,21 +3907,24 @@ void XclImpChChart::FinalizeDataFormats() void XclImpChChart::FinalizeTitle() { - if( (!mxTitle || (!mxTitle->IsDeleted() && !mxTitle->HasString())) && !mxSecnAxesSet->IsValidAxesSet() ) + // special handling for auto-generated title + String aAutoTitle; + if( !mxTitle || (!mxTitle->IsDeleted() && !mxTitle->HasString()) ) { - /* Chart title is auto-generated from series title, if there is only - one series with title in the chart. */ - const String& rSerTitle = mxPrimAxesSet->GetSingleSeriesTitle(); - if( rSerTitle.Len() > 0 ) + // automatic title from first series name (if there are no series on secondary axes set) + if( !mxSecnAxesSet->IsValidAxesSet() ) + aAutoTitle = mxPrimAxesSet->GetSingleSeriesTitle(); + if( mxTitle.is() || (aAutoTitle.Len() > 0) ) { if( !mxTitle ) mxTitle.reset( new XclImpChText( GetChRoot() ) ); - mxTitle->SetString( rSerTitle ); + if( aAutoTitle.Len() == 0 ) + aAutoTitle = CREATE_STRING( "Chart Title" ); } } - // will reset mxTitle, if it does not contain a string - lclFinalizeTitle( mxTitle, GetDefaultText( EXC_CHTEXTTYPE_TITLE ) ); + // will reset mxTitle, if it does not contain a string and no auto title exists + lclFinalizeTitle( mxTitle, GetDefaultText( EXC_CHTEXTTYPE_TITLE ), aAutoTitle ); } Reference< XDiagram > XclImpChChart::CreateDiagram() const @@ -3715,7 +3936,7 @@ Reference< XDiagram > XclImpChChart::CreateDiagram() const ScfPropertySet aDiaProp( xDiagram ); // treatment of missing values - using namespace ::com::sun::star::chart::MissingValueTreatment; + using namespace cssc::MissingValueTreatment; sal_Int32 nMissingValues = LEAVE_GAP; switch( maProps.mnEmptyMode ) { @@ -3775,10 +3996,10 @@ Rectangle XclImpChartDrawing::CalcAnchorRect( const XclObjAnchor& rAnchor, bool in the cell address components of the client anchor. In old BIFF3-BIFF5 objects, the position is stored in the offset components of the anchor. */ Rectangle aRect( - static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maFirst.mnCol : rAnchor.mnLX ) / EXC_CHART_UNIT * maChartRect.GetWidth() + 0.5 ), - static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maFirst.mnRow : rAnchor.mnTY ) / EXC_CHART_UNIT * maChartRect.GetHeight() + 0.5 ), - static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maLast.mnCol : rAnchor.mnRX ) / EXC_CHART_UNIT * maChartRect.GetWidth() + 0.5 ), - static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maLast.mnRow : rAnchor.mnBY ) / EXC_CHART_UNIT * maChartRect.GetHeight() + 0.5 ) ); + static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maFirst.mnCol : rAnchor.mnLX ) / EXC_CHART_TOTALUNITS * maChartRect.GetWidth() + 0.5 ), + static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maFirst.mnRow : rAnchor.mnTY ) / EXC_CHART_TOTALUNITS * maChartRect.GetHeight() + 0.5 ), + static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maLast.mnCol : rAnchor.mnRX ) / EXC_CHART_TOTALUNITS * maChartRect.GetWidth() + 0.5 ), + static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maLast.mnRow : rAnchor.mnBY ) / EXC_CHART_TOTALUNITS * maChartRect.GetHeight() + 0.5 ) ); aRect.Justify(); // move shapes into chart area for sheet charts if( mbOwnTab ) @@ -3898,7 +4119,7 @@ void XclImpChart::Convert( Reference< XModel > xModel, XclImpDffConverter& rDffC if( xChartDoc.is() ) { if( mxChartData.is() ) - mxChartData->Convert( xChartDoc, rDffConv, rObjName ); + mxChartData->Convert( xChartDoc, rDffConv, rObjName, rChartRect ); if( mxChartDrawing.is() ) mxChartDrawing->ConvertObjects( rDffConv, xModel, rChartRect ); } diff --git a/sc/source/filter/excel/xiescher.cxx b/sc/source/filter/excel/xiescher.cxx index 64ed79e3d3b2..3d055d94a498 100644 --- a/sc/source/filter/excel/xiescher.cxx +++ b/sc/source/filter/excel/xiescher.cxx @@ -478,14 +478,14 @@ void XclImpDrawObjBase::PreProcessSdrObject( XclImpDffConverter& rDffConv, SdrOb { if( ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( &rSdrObj, TRUE ) ) { - pInfo->SetMacro( XclControlHelper::GetScMacroName( maMacroName ) ); + pInfo->SetMacro( XclControlHelper::GetScMacroName( maMacroName, GetDocShell() ) ); pInfo->SetHlink( maHyperlink ); } } #else if( mbSimpleMacro && (maMacroName.Len() > 0) ) if( ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( &rSdrObj, TRUE ) ) - pInfo->SetMacro( XclControlHelper::GetScMacroName( maMacroName ) ); + pInfo->SetMacro( XclControlHelper::GetScMacroName( maMacroName, GetDocShell() ) ); #endif // call virtual function for object type specific processing @@ -1947,7 +1947,7 @@ void XclImpTbxObjBase::SetDffProperties( const DffPropSet& rDffPropSet ) bool XclImpTbxObjBase::FillMacroDescriptor( ScriptEventDescriptor& rDescriptor ) const { - return XclControlHelper::FillMacroDescriptor( rDescriptor, DoGetEventType(), GetMacroName() ); + return XclControlHelper::FillMacroDescriptor( rDescriptor, DoGetEventType(), GetMacroName(), GetDocShell() ); } void XclImpTbxObjBase::ConvertFont( ScfPropertySet& rPropSet ) const diff --git a/sc/source/filter/excel/xilink.cxx b/sc/source/filter/excel/xilink.cxx index 45eed0fd98a9..dc2234570ea6 100644 --- a/sc/source/filter/excel/xilink.cxx +++ b/sc/source/filter/excel/xilink.cxx @@ -575,6 +575,7 @@ void XclImpSupbook::LoadCachedValues() const String& rTabName = pTab->GetTabName(); ScExternalRefCache::TableTypeRef pCacheTable = pRefMgr->getCacheTable(nFileId, rTabName, true); pTab->LoadCachedValues(pCacheTable); + pCacheTable->setWholeTableCached(); } } diff --git a/sc/source/filter/excel/xlchart.cxx b/sc/source/filter/excel/xlchart.cxx index 41e682f85808..10a0657c7899 100644..100755 --- a/sc/source/filter/excel/xlchart.cxx +++ b/sc/source/filter/excel/xlchart.cxx @@ -38,11 +38,13 @@ #include <com/sun/star/drawing/LineStyle.hpp> #include <com/sun/star/drawing/FillStyle.hpp> #include <com/sun/star/drawing/BitmapMode.hpp> -#include <com/sun/star/chart2/RelativePosition.hpp> -#include <com/sun/star/chart2/LegendPosition.hpp> -#include <com/sun/star/chart2/LegendExpansion.hpp> -#include <com/sun/star/chart2/Symbol.hpp> #include <com/sun/star/chart/DataLabelPlacement.hpp> +#include <com/sun/star/chart/XAxisXSupplier.hpp> +#include <com/sun/star/chart/XAxisYSupplier.hpp> +#include <com/sun/star/chart/XAxisZSupplier.hpp> +#include <com/sun/star/chart/XChartDocument.hpp> +#include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp> +#include <com/sun/star/chart2/Symbol.hpp> #include <rtl/math.hxx> #include <svl/itemset.hxx> @@ -55,9 +57,8 @@ #include <filter/msfilter/escherex.hxx> #include <editeng/memberids.hrc> #include "global.hxx" -#include "xlconst.hxx" +#include "xlroot.hxx" #include "xlstyle.hxx" -#include "xltools.hxx" using ::rtl::OUString; using ::com::sun::star::uno::Any; @@ -66,6 +67,9 @@ using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::uno::Exception; using ::com::sun::star::lang::XMultiServiceFactory; using ::com::sun::star::chart2::XChartDocument; +using ::com::sun::star::drawing::XShape; + +namespace cssc = ::com::sun::star::chart; // Common ===================================================================== @@ -104,8 +108,8 @@ XclChFrBlock::XclChFrBlock( sal_uInt16 nType ) : // Frame formatting =========================================================== XclChFramePos::XclChFramePos() : - mnObjType( EXC_CHFRAMEPOS_ANY ), - mnSizeMode( EXC_CHFRAMEPOS_AUTOSIZE ) + mnTLMode( EXC_CHFRAMEPOS_PARENT ), + mnBRMode( EXC_CHFRAMEPOS_PARENT ) { } @@ -189,7 +193,7 @@ XclChText::XclChText() : mnVAlign( EXC_CHTEXT_ALIGN_CENTER ), mnBackMode( EXC_CHTEXT_TRANSPARENT ), mnFlags( EXC_CHTEXT_AUTOCOLOR | EXC_CHTEXT_AUTOFILL ), - mnPlacement( EXC_CHTEXT_POS_DEFAULT ), + mnFlags2( EXC_CHTEXT_POS_DEFAULT ), mnRotation( EXC_ROT_NONE ) { } @@ -512,7 +516,7 @@ const sal_Char SERVICE_CHART2_SCATTER[] = "com.sun.star.chart2.ScatterChartTyp const sal_Char SERVICE_CHART2_BUBBLE[] = "com.sun.star.chart2.BubbleChartType"; const sal_Char SERVICE_CHART2_SURFACE[] = "com.sun.star.chart2.ColumnChartType"; // Todo -namespace csscd = ::com::sun::star::chart::DataLabelPlacement; +namespace csscd = cssc::DataLabelPlacement; static const XclChTypeInfo spTypeInfos[] = { @@ -680,10 +684,6 @@ const sal_Char* const sppcHatchNamesFilled[] = { "FillStyle", "HatchName", "Colo /** Property names for bitmap area style. */ const sal_Char* const sppcBitmapNames[] = { "FillStyle", "FillBitmapName", "FillBitmapMode", 0 }; -/** Property names for legend properties. */ -const sal_Char* const sppcLegendNames[] = - { "Show", "AnchorPosition", "Expansion", "RelativePosition", 0 }; - } // namespace // ---------------------------------------------------------------------------- @@ -698,8 +698,7 @@ XclChPropSetHelper::XclChPropSetHelper() : maGradHlpFilled( sppcGradNamesFilled ), maHatchHlpCommon( sppcHatchNamesCommon ), maHatchHlpFilled( sppcHatchNamesFilled ), - maBitmapHlp( sppcBitmapNames ), - maLegendHlp( sppcLegendNames ) + maBitmapHlp( sppcBitmapNames ) { } @@ -957,46 +956,6 @@ sal_uInt16 XclChPropSetHelper::ReadRotationProperties( const ScfPropertySet& rPr XclTools::GetXclRotation( static_cast< sal_Int32 >( fAngle * 100.0 + 0.5 ) ); } -void XclChPropSetHelper::ReadLegendProperties( XclChLegend& rLegend, const ScfPropertySet& rPropSet ) -{ - namespace cssc = ::com::sun::star::chart2; - namespace cssd = ::com::sun::star::drawing; - - // read the properties - bool bShow; - cssc::LegendPosition eApiPos; - cssc::LegendExpansion eApiExpand; - Any aRelPosAny; - maLegendHlp.ReadFromPropertySet( rPropSet ); - maLegendHlp >> bShow >> eApiPos >> eApiExpand >> aRelPosAny; - DBG_ASSERT( bShow, "XclChPropSetHelper::ReadLegendProperties - legend must be visible" ); - - // legend position - switch( eApiPos ) - { - case cssc::LegendPosition_LINE_START: rLegend.mnDockMode = EXC_CHLEGEND_LEFT; break; - case cssc::LegendPosition_LINE_END: rLegend.mnDockMode = EXC_CHLEGEND_RIGHT; break; - case cssc::LegendPosition_PAGE_START: rLegend.mnDockMode = EXC_CHLEGEND_TOP; break; - case cssc::LegendPosition_PAGE_END: rLegend.mnDockMode = EXC_CHLEGEND_BOTTOM; break; - default: rLegend.mnDockMode = EXC_CHLEGEND_NOTDOCKED; - } - // legend expansion - ::set_flag( rLegend.mnFlags, EXC_CHLEGEND_STACKED, eApiExpand != cssc::LegendExpansion_WIDE ); - // legend position - if( rLegend.mnDockMode == EXC_CHLEGEND_NOTDOCKED ) - { - cssc::RelativePosition aRelPos; - if( aRelPosAny >>= aRelPos ) - { - rLegend.maRect.mnX = limit_cast< sal_Int32 >( aRelPos.Primary * EXC_CHART_UNIT, 0, EXC_CHART_UNIT ); - rLegend.maRect.mnY = limit_cast< sal_Int32 >( aRelPos.Secondary * EXC_CHART_UNIT, 0, EXC_CHART_UNIT ); - } - else - rLegend.mnDockMode = EXC_CHLEGEND_LEFT; - } - ::set_flag( rLegend.mnFlags, EXC_CHLEGEND_DOCKED, rLegend.mnDockMode != EXC_CHLEGEND_NOTDOCKED ); -} - // write properties ----------------------------------------------------------- void XclChPropSetHelper::WriteLineProperties( @@ -1207,51 +1166,6 @@ void XclChPropSetHelper::WriteRotationProperties( } } -void XclChPropSetHelper::WriteLegendProperties( - ScfPropertySet& rPropSet, const XclChLegend& rLegend ) -{ - namespace cssc = ::com::sun::star::chart2; - namespace cssd = ::com::sun::star::drawing; - - // legend position - cssc::LegendPosition eApiPos = cssc::LegendPosition_CUSTOM; - switch( rLegend.mnDockMode ) - { - case EXC_CHLEGEND_LEFT: eApiPos = cssc::LegendPosition_LINE_START; break; - case EXC_CHLEGEND_RIGHT: eApiPos = cssc::LegendPosition_LINE_END; break; - case EXC_CHLEGEND_TOP: eApiPos = cssc::LegendPosition_PAGE_START; break; - case EXC_CHLEGEND_BOTTOM: eApiPos = cssc::LegendPosition_PAGE_END; break; - } - // legend expansion - cssc::LegendExpansion eApiExpand = ::get_flagvalue( - rLegend.mnFlags, EXC_CHLEGEND_STACKED, cssc::LegendExpansion_HIGH, cssc::LegendExpansion_WIDE ); - // legend position - Any aRelPosAny; - if( eApiPos == cssc::LegendPosition_CUSTOM ) - { - // #i71697# it is not possible to set the size directly, do some magic here - double fRatio = ((rLegend.maRect.mnWidth > 0) && (rLegend.maRect.mnHeight > 0)) ? - (static_cast< double >( rLegend.maRect.mnWidth ) / rLegend.maRect.mnHeight) : 1.0; - if( fRatio > 1.5 ) - eApiExpand = cssc::LegendExpansion_WIDE; - else if( fRatio < 0.75 ) - eApiExpand = cssc::LegendExpansion_HIGH; - else - eApiExpand = cssc::LegendExpansion_BALANCED; - // set position - cssc::RelativePosition aRelPos; - aRelPos.Primary = static_cast< double >( rLegend.maRect.mnX ) / EXC_CHART_UNIT; - aRelPos.Secondary = static_cast< double >( rLegend.maRect.mnY ) / EXC_CHART_UNIT; - aRelPos.Anchor = cssd::Alignment_TOP_LEFT; - aRelPosAny <<= aRelPos; - } - - // write the properties - maLegendHlp.InitializeWrite(); - maLegendHlp << true << eApiPos << eApiExpand << aRelPosAny; - maLegendHlp.WriteToPropertySet( rPropSet ); -} - // private -------------------------------------------------------------------- ScfPropSetHelper& XclChPropSetHelper::GetLineHelper( XclChPropertyMode ePropMode ) @@ -1301,27 +1215,81 @@ ScfPropSetHelper& XclChPropSetHelper::GetHatchHelper( XclChPropertyMode ePropMod // ============================================================================ +namespace { + +/* The following local functions implement getting the XShape interface of all + supported title objects (chart and axes). This needs some effort due to the + design of the old Chart1 API used to access these objects. */ + +/** A code fragment that returns a shape object from the passed shape supplier + using the specified interface function. Checks a boolean property first. */ +#define EXC_FRAGMENT_GETTITLESHAPE( shape_supplier, supplier_func, property_name ) \ + ScfPropertySet aPropSet( shape_supplier ); \ + if( shape_supplier.is() && aPropSet.GetBoolProperty( CREATE_OUSTRING( #property_name ) ) ) \ + return shape_supplier->supplier_func(); \ + return Reference< XShape >(); \ + +/** Implements a function returning the drawing shape of an axis title, if + existing, using the specified API interface and its function. */ +#define EXC_DEFINEFUNC_GETAXISTITLESHAPE( func_name, interface_type, supplier_func, property_name ) \ +Reference< XShape > func_name( const Reference< cssc::XChartDocument >& rxChart1Doc ) \ +{ \ + Reference< cssc::interface_type > xAxisSupp( rxChart1Doc->getDiagram(), UNO_QUERY ); \ + EXC_FRAGMENT_GETTITLESHAPE( xAxisSupp, supplier_func, property_name ) \ +} + +/** Returns the drawing shape of the main title, if existing. */ +Reference< XShape > lclGetMainTitleShape( const Reference< cssc::XChartDocument >& rxChart1Doc ) +{ + EXC_FRAGMENT_GETTITLESHAPE( rxChart1Doc, getTitle, HasMainTitle ) +} + +EXC_DEFINEFUNC_GETAXISTITLESHAPE( lclGetXAxisTitleShape, XAxisXSupplier, getXAxisTitle, HasXAxisTitle ) +EXC_DEFINEFUNC_GETAXISTITLESHAPE( lclGetYAxisTitleShape, XAxisYSupplier, getYAxisTitle, HasYAxisTitle ) +EXC_DEFINEFUNC_GETAXISTITLESHAPE( lclGetZAxisTitleShape, XAxisZSupplier, getZAxisTitle, HasZAxisTitle ) +EXC_DEFINEFUNC_GETAXISTITLESHAPE( lclGetSecXAxisTitleShape, XSecondAxisTitleSupplier, getSecondXAxisTitle, HasSecondaryXAxisTitle ) +EXC_DEFINEFUNC_GETAXISTITLESHAPE( lclGetSecYAxisTitleShape, XSecondAxisTitleSupplier, getSecondYAxisTitle, HasSecondaryYAxisTitle ) + +#undef EXC_DEFINEFUNC_GETAXISTITLESHAPE +#undef EXC_IMPLEMENT_GETTITLESHAPE + +} // namespace + +// ---------------------------------------------------------------------------- + XclChRootData::XclChRootData() : mxTypeInfoProv( new XclChTypeInfoProvider ), - mxFmtInfoProv( new XclChFormatInfoProvider ) + mxFmtInfoProv( new XclChFormatInfoProvider ), + mnBorderGapX( 0 ), + mnBorderGapY( 0 ) { + // remember some title shape getter functions + maGetShapeFuncs[ XclChTextKey( EXC_CHTEXTTYPE_TITLE ) ] = lclGetMainTitleShape; + maGetShapeFuncs[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, EXC_CHAXESSET_PRIMARY, EXC_CHAXIS_X ) ] = lclGetXAxisTitleShape; + maGetShapeFuncs[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, EXC_CHAXESSET_PRIMARY, EXC_CHAXIS_Y ) ] = lclGetYAxisTitleShape; + maGetShapeFuncs[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, EXC_CHAXESSET_PRIMARY, EXC_CHAXIS_Z ) ] = lclGetZAxisTitleShape; + maGetShapeFuncs[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, EXC_CHAXESSET_SECONDARY, EXC_CHAXIS_X ) ] = lclGetSecXAxisTitleShape; + maGetShapeFuncs[ XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, EXC_CHAXESSET_SECONDARY, EXC_CHAXIS_Y ) ] = lclGetSecYAxisTitleShape; } XclChRootData::~XclChRootData() { } -Reference< XChartDocument > XclChRootData::GetChartDoc() const +void XclChRootData::InitConversion( const XclRoot& rRoot, const Reference< XChartDocument >& rxChartDoc, const Rectangle& rChartRect ) { - DBG_ASSERT( mxChartDoc.is(), "XclChRootData::GetChartDoc - missing chart document" ); - return mxChartDoc; -} + // remember chart document reference and chart shape position/size + DBG_ASSERT( rxChartDoc.is(), "XclChRootData::InitConversion - missing chart document" ); + mxChartDoc = rxChartDoc; + maChartRect = rChartRect; -void XclChRootData::InitConversion( XChartDocRef xChartDoc ) -{ - // remember chart document reference - DBG_ASSERT( xChartDoc.is(), "XclChRootData::InitConversion - missing chart document" ); - mxChartDoc = xChartDoc; + // Excel excludes a border of 5 pixels in each direction from chart area + mnBorderGapX = rRoot.GetHmmFromPixelX( 5.0 ); + mnBorderGapY = rRoot.GetHmmFromPixelY( 5.0 ); + + // size of a chart unit in 1/100 mm + mfUnitSizeX = ::std::max< double >( maChartRect.GetWidth() - 2 * mnBorderGapX, mnBorderGapX ) / EXC_CHART_TOTALUNITS; + mfUnitSizeY = ::std::max< double >( maChartRect.GetHeight() - 2 * mnBorderGapY, mnBorderGapY ) / EXC_CHART_TOTALUNITS; // create object tables Reference< XMultiServiceFactory > xFactory( mxChartDoc, UNO_QUERY ); @@ -1346,5 +1314,15 @@ void XclChRootData::FinishConversion() mxChartDoc.clear(); } -// ============================================================================ +Reference< XShape > XclChRootData::GetTitleShape( const XclChTextKey& rTitleKey ) const +{ + XclChGetShapeFuncMap::const_iterator aIt = maGetShapeFuncs.find( rTitleKey ); + OSL_ENSURE( aIt != maGetShapeFuncs.end(), "XclChRootData::GetTitleShape - invalid title key" ); + Reference< cssc::XChartDocument > xChart1Doc( mxChartDoc, UNO_QUERY ); + Reference< XShape > xTitleShape; + if( xChart1Doc.is() && (aIt != maGetShapeFuncs.end()) ) + xTitleShape = (aIt->second)( xChart1Doc ); + return xTitleShape; +} +// ============================================================================ diff --git a/sc/source/filter/excel/xlescher.cxx b/sc/source/filter/excel/xlescher.cxx index 538fd7fd7242..e1132c1b5606 100644 --- a/sc/source/filter/excel/xlescher.cxx +++ b/sc/source/filter/excel/xlescher.cxx @@ -35,6 +35,7 @@ #include "document.hxx" #include "xistream.hxx" #include "xlescher.hxx" +#include <filter/msfilter/msvbahelper.hxx> using ::rtl::OUString; using ::com::sun::star::uno::Reference; @@ -328,10 +329,16 @@ Reference< XControlModel > XclControlHelper::GetControlModel( Reference< XShape #define EXC_MACRONAME_PRE "vnd.sun.star.script:Standard." #define EXC_MACRONAME_SUF "?language=Basic&location=document" -OUString XclControlHelper::GetScMacroName( const String& rXclMacroName ) +OUString XclControlHelper::GetScMacroName( const String& rXclMacroName, SfxObjectShell* pDocShell ) { + String sTmp( rXclMacroName ); if( rXclMacroName.Len() > 0 ) - return CREATE_OUSTRING( EXC_MACRONAME_PRE ) + rXclMacroName + CREATE_OUSTRING( EXC_MACRONAME_SUF ); + { + ooo::vba::VBAMacroResolvedInfo aMacro = ooo::vba::resolveVBAMacro( pDocShell, rXclMacroName, false ); + if ( aMacro.IsResolved() ) + return ooo::vba::makeMacroURL( aMacro.ResolvedMacro() ); + + } return OUString(); } @@ -365,14 +372,14 @@ spTbxListenerData[] = #define EXC_MACROSCRIPT "Script" bool XclControlHelper::FillMacroDescriptor( ScriptEventDescriptor& rDescriptor, - XclTbxEventType eEventType, const String& rXclMacroName ) + XclTbxEventType eEventType, const String& rXclMacroName, SfxObjectShell* pShell ) { if( rXclMacroName.Len() > 0 ) { rDescriptor.ListenerType = OUString::createFromAscii( spTbxListenerData[ eEventType ].mpcListenerType ); rDescriptor.EventMethod = OUString::createFromAscii( spTbxListenerData[ eEventType ].mpcEventMethod ); rDescriptor.ScriptType = CREATE_OUSTRING( EXC_MACROSCRIPT ); - rDescriptor.ScriptCode = GetScMacroName( rXclMacroName ); + rDescriptor.ScriptCode = GetScMacroName( rXclMacroName, pShell ); return true; } return false; diff --git a/sc/source/filter/excel/xlroot.cxx b/sc/source/filter/excel/xlroot.cxx index 8a22b05828b9..2b2180db5e6a 100644 --- a/sc/source/filter/excel/xlroot.cxx +++ b/sc/source/filter/excel/xlroot.cxx @@ -28,7 +28,11 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sc.hxx" #include "xlroot.hxx" +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XFramesSupplier.hpp> #include <com/sun/star/i18n/ScriptType.hpp> +#include <comphelper/processfactory.hxx> #include <vcl/svapp.hxx> #include <svl/stritem.hxx> #include <svl/languageoptions.hxx> @@ -57,6 +61,15 @@ namespace ApiScriptType = ::com::sun::star::i18n::ScriptType; using ::rtl::OUString; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::uno::UNO_SET_THROW; +using ::com::sun::star::awt::XDevice; +using ::com::sun::star::awt::DeviceInfo; +using ::com::sun::star::frame::XFrame; +using ::com::sun::star::frame::XFramesSupplier; +using ::com::sun::star::lang::XMultiServiceFactory; // Global data ================================================================ @@ -88,6 +101,8 @@ XclRootData::XclRootData( XclBiff eBiff, SfxMedium& rMedium, mxFontPropSetHlp( new XclFontPropSetHelper ), mxChPropSetHlp( new XclChPropSetHelper ), mxRD( new RootData ),//! + mfScreenPixelX( 50.0 ), + mfScreenPixelY( 50.0 ), mnCharWidth( 110 ), mnScTab( 0 ), mbExport( bExport ) @@ -129,6 +144,22 @@ XclRootData::XclRootData( XclBiff eBiff, SfxMedium& rMedium, mxExtDocOpt.reset( new ScExtDocOptions( *pOldDocOpt ) ); else mxExtDocOpt.reset( new ScExtDocOptions ); + + // screen pixel size + try + { + Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), UNO_SET_THROW ); + Reference< XFramesSupplier > xFramesSupp( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.frame.Desktop" ) ), UNO_QUERY_THROW ); + Reference< XFrame > xFrame( xFramesSupp->getActiveFrame(), UNO_SET_THROW ); + Reference< XDevice > xDevice( xFrame->getContainerWindow(), UNO_QUERY_THROW ); + DeviceInfo aDeviceInfo = xDevice->getInfo(); + mfScreenPixelX = (aDeviceInfo.PixelPerMeterX > 0) ? (100000.0 / aDeviceInfo.PixelPerMeterX) : 50.0; + mfScreenPixelY = (aDeviceInfo.PixelPerMeterY > 0) ? (100000.0 / aDeviceInfo.PixelPerMeterY) : 50.0; + } + catch( Exception& ) + { + OSL_ENSURE( false, "XclRootData::XclRootData - cannot get output device info" ); + } } XclRootData::~XclRootData() @@ -199,6 +230,16 @@ void XclRoot::SetCharWidth( const XclFontData& rFontData ) } } +sal_Int32 XclRoot::GetHmmFromPixelX( double fPixelX ) const +{ + return static_cast< sal_Int32 >( fPixelX * mrData.mfScreenPixelX + 0.5 ); +} + +sal_Int32 XclRoot::GetHmmFromPixelY( double fPixelY ) const +{ + return static_cast< sal_Int32 >( fPixelY * mrData.mfScreenPixelY + 0.5 ); +} + String XclRoot::RequestPassword( ::comphelper::IDocPasswordVerifier& rVerifier ) const { ::std::vector< OUString > aDefaultPasswords; diff --git a/sc/source/filter/html/htmlexp.cxx b/sc/source/filter/html/htmlexp.cxx index e8c71d20af11..0ab97170621e 100644 --- a/sc/source/filter/html/htmlexp.cxx +++ b/sc/source/filter/html/htmlexp.cxx @@ -148,8 +148,6 @@ const sal_Char __FAR_DATA ScHTMLExport::sIndentSource[nIndentMax+1] = #define OUT_SP_CSTR_ASS( s ) rStrm << ' ' << s << '=' #define APPEND_SPACE( s ) s.AppendAscii(" ") -extern BOOL bOderSo; - #define GLOBSTR(id) ScGlobal::GetRscString( id ) @@ -234,30 +232,6 @@ void lcl_AppendHTMLColorTripel( ByteString& rStr, const Color& rColor ) } */ -bool SC_DLLPUBLIC ScGetWriteTeamInfo(); - -void lcl_WriteTeamInfo( SvStream& rStrm, rtl_TextEncoding eDestEnc ) -{ - if ( !ScGetWriteTeamInfo() ) return; - lcl_OUT_LF(); - lcl_OUT_COMMENT( CREATE_STRING( "Sascha Ballach " ) ); - lcl_OUT_COMMENT( CREATE_STRING( "Michael Daeumling (aka Bitsau) " ) ); - lcl_OUT_COMMENT( CREATE_STRING( "Michael Hagen " ) ); - lcl_OUT_COMMENT( CREATE_STRING( "Roland Jakobs " ) ); - lcl_OUT_COMMENT( CREATE_STRING( "Andreas Krebs " ) ); - lcl_OUT_COMMENT( CREATE_STRING( "John Marmion " ) ); - lcl_OUT_COMMENT( CREATE_STRING( "Niklas Nebel " ) ); - lcl_OUT_COMMENT( CREATE_STRING( "Jacques Nietsch " ) ); - lcl_OUT_COMMENT( CREATE_STRING( "Marcus Olk " ) ); - lcl_OUT_COMMENT( CREATE_STRING( "Eike Rathke " ) ); - lcl_OUT_COMMENT( CREATE_STRING( "Daniel Rentz " ) ); - lcl_OUT_COMMENT( CREATE_STRING( "Stephan Templin " ) ); - lcl_OUT_COMMENT( CREATE_STRING( "Gunnar Timm " ) ); - lcl_OUT_COMMENT( CREATE_STRING( "*** Man kann nicht ALLES haben! ***" ) ); - lcl_OUT_LF(); -} - - ////////////////////////////////////////////////////////////////////////////// ScHTMLExport::ScHTMLExport( SvStream& rStrmP, const String& rBaseURL, ScDocument* pDocP, @@ -416,8 +390,6 @@ void ScHTMLExport::WriteHeader() OUT_COMMENT( aStrOut ); } //---------------------------------------------------------- - - lcl_WriteTeamInfo( rStrm, eDestEnc ); } OUT_LF(); diff --git a/sc/source/filter/html/htmlpars.cxx b/sc/source/filter/html/htmlpars.cxx index 2716dc216ed1..85e77fc3124b 100644 --- a/sc/source/filter/html/htmlpars.cxx +++ b/sc/source/filter/html/htmlpars.cxx @@ -2424,12 +2424,15 @@ void ScHTMLTable::InsertNewCell( const ScHTMLSize& rSpanSize ) { ScRange* pRange; - // find an unused cell - while( (pRange = maVMergedCells.Find( maCurrCell.MakeAddr() )) != 0 ) + /* Find an unused cell by skipping all merged ranges that cover the + current cell position stored in maCurrCell. */ + while( ((pRange = maVMergedCells.Find( maCurrCell.MakeAddr() )) != 0) || ((pRange = maHMergedCells.Find( maCurrCell.MakeAddr() )) != 0) ) maCurrCell.mnCol = pRange->aEnd.Col() + 1; mpCurrEntryList = &maEntryMap[ maCurrCell ]; - // try to find collisions, shrink existing ranges + /* If the new cell is merged horizontally, try to find collisions with + other vertically merged ranges. In this case, shrink existing + vertically merged ranges (do not shrink the new cell). */ SCCOL nColEnd = maCurrCell.mnCol + rSpanSize.mnCols; for( ScAddress aAddr( maCurrCell.MakeAddr() ); aAddr.Col() < nColEnd; aAddr.IncCol() ) if( (pRange = maVMergedCells.Find( aAddr )) != 0 ) @@ -2438,14 +2441,19 @@ void ScHTMLTable::InsertNewCell( const ScHTMLSize& rSpanSize ) // insert the new range into the cell lists ScRange aNewRange( maCurrCell.MakeAddr() ); aNewRange.aEnd.Move( rSpanSize.mnCols - 1, rSpanSize.mnRows - 1, 0 ); - if( rSpanSize.mnCols > 1 ) + if( rSpanSize.mnRows > 1 ) { maVMergedCells.Append( aNewRange ); + /* Do not insert vertically merged ranges into maUsedCells yet, + because they may be shrunken (see above). The final vertically + merged ranges are inserted in FillEmptyCells(). */ } else { - if( rSpanSize.mnRows > 1 ) + if( rSpanSize.mnCols > 1 ) maHMergedCells.Append( aNewRange ); + /* Insert horizontally merged ranges and single cells into + maUsedCells, they will not be changed anymore. */ maUsedCells.Join( aNewRange ); } @@ -2562,8 +2570,9 @@ void ScHTMLTable::SetDocSize( ScHTMLOrient eOrient, SCCOLROW nCellPos, SCCOLROW while( nIndex >= rSizes.size() ) rSizes.push_back( rSizes.empty() ? 1 : (rSizes.back() + 1) ); // update size of passed position and all following + // #i109987# only grow, don't shrink - use the largest needed size SCsCOLROW nDiff = nSize - ((nIndex == 0) ? rSizes.front() : (rSizes[ nIndex ] - rSizes[ nIndex - 1 ])); - if( nDiff != 0 ) + if( nDiff > 0 ) for( ScSizeVec::iterator aIt = rSizes.begin() + nIndex, aEnd = rSizes.end(); aIt != aEnd; ++aIt ) *aIt += nDiff; } @@ -2591,6 +2600,7 @@ void ScHTMLTable::FillEmptyCells() for( ScHTMLTableIterator aIter( mxNestedTables.get() ); aIter.is(); ++aIter ) aIter->FillEmptyCells(); + // insert the final vertically merged ranges into maUsedCells for( const ScRange* pRange = maVMergedCells.First(); pRange; pRange = maVMergedCells.Next() ) maUsedCells.Join( *pRange ); diff --git a/sc/source/filter/inc/xechart.hxx b/sc/source/filter/inc/xechart.hxx index 2cf976b11efe..5bb75e029210 100644 --- a/sc/source/filter/inc/xechart.hxx +++ b/sc/source/filter/inc/xechart.hxx @@ -39,6 +39,10 @@ class Size; namespace com { namespace sun { namespace star { + namespace awt + { + struct Rectangle; + } namespace frame { class XModel; @@ -65,7 +69,7 @@ namespace com { namespace sun { namespace star { // Common ===================================================================== -class XclExpChRootData; +struct XclExpChRootData; class XclExpChChart; /** Base class for complex chart classes, provides access to other components @@ -80,11 +84,13 @@ public: typedef ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument > XChartDocRef; public: - explicit XclExpChRoot( const XclExpRoot& rRoot, XclExpChChart* pChartData ); + explicit XclExpChRoot( const XclExpRoot& rRoot, XclExpChChart& rChartData ); virtual ~XclExpChRoot(); /** Returns this root instance - for code readability in derived classes. */ inline const XclExpChRoot& GetChRoot() const { return *this; } + /** Returns the API Chart document model. */ + XChartDocRef GetChartDocument() const; /** Returns a reference to the parent chart data object. */ XclExpChChart& GetChartData() const; /** Returns chart type info for a unique chart type identifier. */ @@ -96,7 +102,7 @@ public: const XclChFormatInfo& GetFormatInfo( XclChObjectType eObjType ) const; /** Starts the API chart document conversion. Must be called once before all API conversion. */ - void InitConversion( XChartDocRef xChartDoc ) const; + void InitConversion( XChartDocRef xChartDoc, const Rectangle& rChartRect ) const; /** Finishes the API chart document conversion. Must be called once after all API conversion. */ void FinishConversion() const; @@ -105,6 +111,18 @@ public: /** Sets a system color and the respective color identifier. */ void SetSystemColor( Color& rColor, sal_uInt32& rnColorId, sal_uInt16 nSysColorIdx ) const; + /** Converts the passed horizontal coordinate from 1/100 mm to Excel chart units. */ + sal_Int32 CalcChartXFromHmm( sal_Int32 nPosX ) const; + /** Converts the passed vertical coordinate from 1/100 mm to Excel chart units. */ + sal_Int32 CalcChartYFromHmm( sal_Int32 nPosY ) const; + /** Converts the passed rectangle from 1/100 mm to Excel chart units. */ + XclChRectangle CalcChartRectFromHmm( const ::com::sun::star::awt::Rectangle& rRect ) const; + + /** Converts the passed horizontal coordinate from a relative position to Excel chart units. */ + sal_Int32 CalcChartXFromRelative( double fPosX ) const; + /** Converts the passed vertical coordinate from a relative position to Excel chart units. */ + sal_Int32 CalcChartYFromRelative( double fPosY ) const; + /** Reads all line properties from the passed property set. */ void ConvertLineFormat( XclChLineFormat& rLineFmt, @@ -191,6 +209,25 @@ public: // Frame formatting =========================================================== +class XclExpChFramePos : public XclExpRecord +{ +public: + explicit XclExpChFramePos( sal_uInt16 nTLMode, sal_uInt16 nBRMode ); + + /** Returns read/write access to the frame position data. */ + inline XclChFramePos& GetFramePosData() { return maData; } + +private: + virtual void WriteBody( XclExpStream& rStrm ); + +private: + XclChFramePos maData; /// Position of the frame. +}; + +typedef ScfRef< XclExpChFramePos > XclExpChFramePosRef; + +// ---------------------------------------------------------------------------- + class XclExpChLineFormat : public XclExpRecord { public: @@ -514,6 +551,7 @@ private: private: XclChText maData; /// Contents of the CHTEXT record. + XclExpChFramePosRef mxFramePos; /// Relative text frame position (CHFRAMEPOS record). XclExpChSourceLinkRef mxSrcLink; /// Linked data (CHSOURCELINK with CHSTRING record). XclExpChFrameRef mxFrame; /// Text object frame properties (CHFRAME group). XclExpChFontRef mxFont; /// Index into font buffer (CHFONT record). @@ -830,8 +868,8 @@ typedef ScfRef< XclExpChChart3d > XclExpChChart3dRef; /** Represents the CHLEGEND record group describing the chart legend. - The CHLEGEND group consists of: CHLEGEND, CHBEGIN, CHFRAME group, - CHTEXT group, CHEND. + The CHLEGEND group consists of: CHLEGEND, CHBEGIN, CHFRAMEPOS, CHFRAME + group, CHTEXT group, CHEND. */ class XclExpChLegend : public XclExpChGroupBase { @@ -849,6 +887,7 @@ private: private: XclChLegend maData; /// Contents of the CHLEGEND record. + XclExpChFramePosRef mxFramePos; /// Legend frame position (CHFRAMEPOS record). XclExpChTextRef mxText; /// Legend text format (CHTEXT group). XclExpChFrameRef mxFrame; /// Legend frame format (CHFRAME group). }; @@ -1137,6 +1176,7 @@ private: typedef XclExpRecordList< XclExpChTypeGroup > XclExpChTypeGroupList; XclChAxesSet maData; /// Contents of the CHAXESSET record. + XclExpChFramePosRef mxFramePos; /// Outer plot area position (CHFRAMEPOS record). XclExpChAxisRef mxXAxis; /// The X axis (CHAXIS group). XclExpChAxisRef mxYAxis; /// The Y axis (CHAXIS group). XclExpChAxisRef mxZAxis; /// The Z axis (CHAXIS group). @@ -1164,7 +1204,7 @@ public: public: explicit XclExpChChart( const XclExpRoot& rRoot, - XChartDocRef xChartDoc, const Size& rSize ); + XChartDocRef xChartDoc, const Rectangle& rChartRect ); /** Creates, registers and returns a new data series object. */ XclExpChSeriesRef CreateSeries(); @@ -1172,6 +1212,8 @@ public: void RemoveLastSeries(); /** Stores a CHTEXT group that describes a data point label. */ void SetDataLabel( XclExpChTextRef xText ); + /** Sets the plot area position and size to manual mode. */ + void SetManualPlotArea(); /** Writes all embedded records. */ virtual void WriteSubRecords( XclExpStream& rStrm ); @@ -1224,7 +1266,7 @@ public: public: explicit XclExpChart( const XclExpRoot& rRoot, - XModelRef xModel, const Size& rSize ); + XModelRef xModel, const Rectangle& rChartRect ); }; // ============================================================================ diff --git a/sc/source/filter/inc/xichart.hxx b/sc/source/filter/inc/xichart.hxx index 5d03c99b124a..d8289b3b671b 100644 --- a/sc/source/filter/inc/xichart.hxx +++ b/sc/source/filter/inc/xichart.hxx @@ -43,10 +43,18 @@ #include "xistring.hxx" namespace com { namespace sun { namespace star { + namespace awt + { + struct Rectangle; + } namespace frame { class XModel; } + namespace drawing + { + class XShape; + } namespace chart2 { struct ScaleData; @@ -75,7 +83,7 @@ struct XclObjFillData; // Common ===================================================================== class ScfProgressBar; -class XclImpChRootData; +struct XclImpChRootData; class XclImpChChart; class ScTokenArray; @@ -83,11 +91,10 @@ class ScTokenArray; class XclImpChRoot : public XclImpRoot { public: - typedef ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument > XChartDocRef; - typedef ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataProvider > XDataProviderRef; + typedef ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument > XChartDocRef; public: - explicit XclImpChRoot( const XclImpRoot& rRoot, XclImpChChart* pChartData ); + explicit XclImpChRoot( const XclImpRoot& rRoot, XclImpChChart& rChartData ); virtual ~XclImpChRoot(); /** Returns this root instance - for code readability in derived classes. */ @@ -109,12 +116,28 @@ public: Color GetSeriesFillAutoColor( sal_uInt16 nFormatIdx ) const; /** Starts the API chart document conversion. Must be called once before all API conversion. */ - void InitConversion( XChartDocRef xChartDoc ) const; + void InitConversion( XChartDocRef xChartDoc, const Rectangle& rChartRect ) const; /** Finishes the API chart document conversion. Must be called once after all API conversion. */ void FinishConversion( XclImpDffConverter& rDffConv ) const; /** Returns the data provider for the chart document. */ - XDataProviderRef GetDataProvider() const; + ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataProvider > + GetDataProvider() const; + /** Returns the drawing shape interface of the specified title object. */ + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > + GetTitleShape( const XclChTextKey& rTitleKey ) const; + + /** Converts the passed horizontal coordinate from Excel chart units into 1/100 mm. */ + sal_Int32 CalcHmmFromChartX( sal_Int32 nPosX ) const; + /** Converts the passed vertical coordinate from Excel chart units into 1/100 mm. */ + sal_Int32 CalcHmmFromChartY( sal_Int32 nPosY ) const; + /** Converts the passed rectangle from Excel chart units into 1/100 mm. */ + ::com::sun::star::awt::Rectangle CalcHmmFromChartRect( const XclChRectangle& rRect ) const; + + /** Converts the passed horizontal coordinate from Excel chart units into a relative position. */ + double CalcRelativeFromChartX( sal_Int32 nPosX ) const; + /** Converts the passed vertical coordinate from Excel chart units into a relative position. */ + double CalcRelativeFromChartY( sal_Int32 nPosY ) const; /** Writes all line properties to the passed property set. */ void ConvertLineFormat( @@ -184,6 +207,9 @@ public: /** Reads the CHFRAMEPOS record (frame position and size). */ void ReadChFramePos( XclImpStream& rStrm ); + /** Returns read-only access to the imported frame position data. */ + inline const XclChFramePos& GetFramePosData() const { return maData; } + private: XclChFramePos maData; /// Position of the frame. }; @@ -506,6 +532,8 @@ public: void ConvertDataLabel( ScfPropertySet& rPropSet, const XclChTypeInfo& rTypeInfo ) const; /** Creates a title text object. */ XTitleRef CreateTitle() const; + /** Converts the manual position of the specified title */ + void ConvertTitlePosition( const XclChTextKey& rTitleKey ) const; private: using XclImpChRoot::ConvertFont; @@ -519,6 +547,7 @@ private: XclChText maData; /// Contents of the CHTEXT record. XclChObjectLink maObjLink; /// Link target for this text object. XclFormatRunVec maFormats; /// Formatting runs (CHFORMATRUNS record). + XclImpChFramePosRef mxFramePos; /// Relative text frame position (CHFRAMEPOS record). XclImpChSourceLinkRef mxSrcLink; /// Linked data (CHSOURCELINK with CHSTRING record). XclImpChFrameRef mxFrame; /// Text object frame properties (CHFRAME group). XclImpChFontRef mxFont; /// Index into font buffer (CHFONT record). @@ -922,8 +951,8 @@ typedef ScfRef< XclImpChChart3d > XclImpChChart3dRef; /** Represents the CHLEGEND record group describing the chart legend. - The CHLEGEND group consists of: CHLEGEND, CHBEGIN, CHFRAME group, - CHTEXT group, CHEND. + The CHLEGEND group consists of: CHLEGEND, CHBEGIN, CHFRAMEPOS, CHFRAME + group, CHTEXT group, CHEND. */ class XclImpChLegend : public XclImpChGroupBase, protected XclImpChRoot { @@ -945,6 +974,7 @@ public: private: XclChLegend maData; /// Contents of the CHLEGEND record. + XclImpChFramePosRef mxFramePos; /// Legend frame position (CHFRAMEPOS record). XclImpChTextRef mxText; /// Legend text format (CHTEXT group). XclImpChFrameRef mxFrame; /// Legend frame format (CHFRAME group). }; @@ -1265,6 +1295,8 @@ public: /** Returns the axes set index used by the chart API. */ inline sal_Int32 GetApiAxesSetIndex() const { return maData.GetApiAxesSetIndex(); } + /** Returns the outer plot area position, if existing. */ + inline XclImpChFramePosRef GetPlotAreaFramePos() const { return mxFramePos; } /** Returns the specified chart type group. */ inline XclImpChTypeGroupRef GetTypeGroup( sal_uInt16 nGroupIdx ) const { return maTypeGroups.get( nGroupIdx ); } /** Returns the first chart type group. */ @@ -1276,6 +1308,8 @@ public: /** Creates a coordinate system and converts all series and axis settings. */ void Convert( XDiagramRef xDiagram ) const; + /** Converts the manual positions of all axis titles. */ + void ConvertTitlePositions() const; private: /** Reads a CHAXIS record group containing a single axis. */ @@ -1304,7 +1338,7 @@ private: typedef ScfRefMap< sal_uInt16, XclImpChTypeGroup > XclImpChTypeGroupMap; XclChAxesSet maData; /// Contents of the CHAXESSET record. - XclImpChFramePosRef mxPos; /// Position of the axes set (CHFRAMEPOS record). + XclImpChFramePosRef mxFramePos; /// Outer plot area position (CHFRAMEPOS record). XclImpChAxisRef mxXAxis; /// The X axis (CHAXIS group). XclImpChAxisRef mxYAxis; /// The Y axis (CHAXIS group). XclImpChAxisRef mxZAxis; /// The Z axis (CHAXIS group). @@ -1351,13 +1385,16 @@ public: XclImpChTypeGroupRef GetTypeGroup( sal_uInt16 nGroupIdx ) const; /** Returns the specified default text. */ XclImpChTextRef GetDefaultText( XclChTextType eTextType ) const; + /** Returns true, if the plot area has benn moved and/or resized manually. */ + bool IsManualPlotArea() const; /** Returns the number of units on the progress bar needed for the chart. */ inline sal_Size GetProgressSize() const { return 2 * EXC_CHART_PROGRESS_SIZE; } /** Converts and writes all properties to the passed chart. */ void Convert( XChartDocRef xChartDoc, XclImpDffConverter& rDffConv, - const ::rtl::OUString& rObjName ) const; + const ::rtl::OUString& rObjName, + const Rectangle& rChartRect ) const; private: /** Reads a CHSERIES group (data series source and formatting). */ diff --git a/sc/source/filter/inc/xlchart.hxx b/sc/source/filter/inc/xlchart.hxx index f6711211bc13..13eda8619cc0 100644..100755 --- a/sc/source/filter/inc/xlchart.hxx +++ b/sc/source/filter/inc/xlchart.hxx @@ -34,14 +34,19 @@ #define EXC_CHART2_3DBAR_HAIRLINES_ONLY 1 #include <map> +#include <tools/gen.hxx> #include "fapihelper.hxx" namespace com { namespace sun { namespace star { namespace container { class XNameContainer; } namespace lang { class XMultiServiceFactory; } + namespace chart { class XChartDocument; } namespace chart2 { class XChartDocument; } + namespace drawing { class XShape; } } } } +class XclRoot; + // Property names ============================================================= // service names @@ -72,6 +77,7 @@ namespace com { namespace sun { namespace star { // property names #define EXC_CHPROP_ADDITIONALSHAPES CREATE_OUSTRING( "AdditionalShapes" ) +#define EXC_CHPROP_ANCHORPOSITION CREATE_OUSTRING( "AnchorPosition" ) #define EXC_CHPROP_ARRANGEORDER CREATE_OUSTRING( "ArrangeOrder" ) #define EXC_CHPROP_ATTAXISINDEX CREATE_OUSTRING( "AttachedAxisIndex" ) #define EXC_CHPROP_ATTRIBDATAPOINTS CREATE_OUSTRING( "AttributedDataPoints" ) @@ -94,10 +100,12 @@ namespace com { namespace sun { namespace star { #define EXC_CHPROP_ERRORBARSTYLE CREATE_OUSTRING( "ErrorBarStyle" ) #define EXC_CHPROP_ERRORBARX CREATE_OUSTRING( "ErrorBarX" ) #define EXC_CHPROP_ERRORBARY CREATE_OUSTRING( "ErrorBarY" ) +#define EXC_CHPROP_EXPANSION CREATE_OUSTRING( "Expansion" ) #define EXC_CHPROP_FILLBITMAPMODE CREATE_OUSTRING( "FillBitmapMode" ) #define EXC_CHPROP_FILLSTYLE CREATE_OUSTRING( "FillStyle" ) #define EXC_CHPROP_GAPWIDTHSEQ CREATE_OUSTRING( "GapwidthSequence" ) #define EXC_CHPROP_GEOMETRY3D CREATE_OUSTRING( "Geometry3D" ) +#define EXC_CHPROP_HASMAINTITLE CREATE_OUSTRING( "HasMainTitle" ) #define EXC_CHPROP_INCLUDEHIDDENCELLS CREATE_OUSTRING( "IncludeHiddenCells" ) #define EXC_CHPROP_JAPANESE CREATE_OUSTRING( "Japanese" ) #define EXC_CHPROP_LABEL CREATE_OUSTRING( "Label" ) @@ -116,6 +124,7 @@ namespace com { namespace sun { namespace star { #define EXC_CHPROP_PERCENTDIAGONAL CREATE_OUSTRING( "PercentDiagonal" ) #define EXC_CHPROP_PERSPECTIVE CREATE_OUSTRING( "Perspective" ) #define EXC_CHPROP_POSITIVEERROR CREATE_OUSTRING( "PositiveError" ) +#define EXC_CHPROP_RELATIVEPOSITION CREATE_OUSTRING( "RelativePosition" ) #define EXC_CHPROP_RIGHTANGLEDAXES CREATE_OUSTRING( "RightAngledAxes" ) #define EXC_CHPROP_ROLE CREATE_OUSTRING( "Role" ) #define EXC_CHPROP_ROTATIONHORIZONTAL CREATE_OUSTRING( "RotationHorizontal" ) @@ -169,7 +178,8 @@ const sal_Int32 EXC_CHART_AXESSET_NONE = -1; /// For internal use const sal_Int32 EXC_CHART_AXESSET_PRIMARY = 0; /// API primary axes set index. const sal_Int32 EXC_CHART_AXESSET_SECONDARY = 1; /// API secondary axes set index. -const sal_Int32 EXC_CHART_UNIT = 4000; /// Chart objects are positioned in 1/4000 of chart area. +const sal_Int32 EXC_CHART_TOTALUNITS = 4000; /// Most chart objects are positioned in 1/4000 of chart area. +const sal_Int32 EXC_CHART_PLOTAREAUNITS = 1000; /// For objects that are positioned in 1/1000 of plot area. // (0x0850) CHFRINFO ---------------------------------------------------------- @@ -604,7 +614,8 @@ const sal_uInt16 EXC_ID_CHPROPERTIES = 0x1044; const sal_uInt16 EXC_CHPROPS_MANSERIES = 0x0001; /// Manual series allocation. const sal_uInt16 EXC_CHPROPS_SHOWVISIBLEONLY = 0x0002; /// Show visible cells only. const sal_uInt16 EXC_CHPROPS_NORESIZE = 0x0004; /// Do not resize chart with window. -const sal_uInt16 EXC_CHPROPS_MANPLOTAREA = 0x0008; /// Plot area with CHFRAMEPOS records. +const sal_uInt16 EXC_CHPROPS_MANPLOTAREA = 0x0008; /// Manual plot area mode. +const sal_uInt16 EXC_CHPROPS_USEMANPLOTAREA = 0x0010; /// Manual plot area layout in CHFRAMEPOS record. const sal_uInt8 EXC_CHPROPS_EMPTY_SKIP = 0; /// Skip empty values. const sal_uInt8 EXC_CHPROPS_EMPTY_ZERO = 1; /// Plot empty values as zero. @@ -643,11 +654,11 @@ const sal_uInt16 EXC_ID_CHFORMAT = 0x104E; const sal_uInt16 EXC_ID_CHFRAMEPOS = 0x104F; -const sal_uInt16 EXC_CHFRAMEPOS_ANY = 2; -const sal_uInt16 EXC_CHFRAMEPOS_LEGEND = 5; - -const sal_uInt16 EXC_CHFRAMEPOS_MANUALSIZE = 1; -const sal_uInt16 EXC_CHFRAMEPOS_AUTOSIZE = 2; +const sal_uInt16 EXC_CHFRAMEPOS_POINTS = 0; +const sal_uInt16 EXC_CHFRAMEPOS_ABSSIZE_POINTS = 1; +const sal_uInt16 EXC_CHFRAMEPOS_PARENT = 2; +const sal_uInt16 EXC_CHFRAMEPOS_DEFOFFSET_PLOT = 3; +const sal_uInt16 EXC_CHFRAMEPOS_CHARTSIZE = 5; // (0x1050) CHFORMATRUNS ------------------------------------------------------ @@ -774,8 +785,8 @@ struct XclChFrBlock struct XclChFramePos { XclChRectangle maRect; /// Object dependent position data. - sal_uInt16 mnObjType; /// Object type. - sal_uInt16 mnSizeMode; /// Size mode (manual, automatic). + sal_uInt16 mnTLMode; /// Top-left position mode. + sal_uInt16 mnBRMode; /// Bottom-right position mode. explicit XclChFramePos(); }; @@ -885,7 +896,7 @@ struct XclChText sal_uInt8 mnVAlign; /// Vertical alignment. sal_uInt16 mnBackMode; /// Background mode: transparent, opaque. sal_uInt16 mnFlags; /// Additional flags. - sal_uInt16 mnPlacement; /// Text object placement (BIFF8+). + sal_uInt16 mnFlags2; /// Text object placement and text direction (BIFF8+). sal_uInt16 mnRotation; /// Text object rotation (BIFF8+). explicit XclChText(); @@ -1013,7 +1024,6 @@ struct XclChLegend struct XclChTypeGroup { - XclChRectangle maRect; /// Position (not used). sal_uInt16 mnFlags; /// Additional flags. sal_uInt16 mnGroupIdx; /// Chart type group index. @@ -1060,7 +1070,6 @@ struct XclChValueRange struct XclChTick { - XclChRectangle maRect; /// Position (not used). Color maTextColor; /// Tick labels color. sal_uInt8 mnMajor; /// Type of tick marks of major grid. sal_uInt8 mnMinor; /// Type of tick marks of minor grid. @@ -1076,7 +1085,6 @@ struct XclChTick struct XclChAxis { - XclChRectangle maRect; /// Position (not used). sal_uInt16 mnType; /// Axis type. explicit XclChAxis(); @@ -1089,7 +1097,7 @@ struct XclChAxis struct XclChAxesSet { - XclChRectangle maRect; /// Position of the axes set. + XclChRectangle maRect; /// Position of the axes set (inner plot area). sal_uInt16 mnAxesSetId; /// Primary/secondary axes set. explicit XclChAxesSet(); @@ -1158,16 +1166,6 @@ enum XclChFrameType EXC_CHFRAMETYPE_INVISIBLE /// Missing frame represents invisible formatting. }; -/** Enumerates different text box types for default text formatting. */ -enum XclChTextType -{ - EXC_CHTEXTTYPE_TITLE, /// Chart title. - EXC_CHTEXTTYPE_LEGEND, /// Chart legend. - EXC_CHTEXTTYPE_AXISTITLE, /// Chart axis titles. - EXC_CHTEXTTYPE_AXISLABEL, /// Chart axis labels. - EXC_CHTEXTTYPE_DATALABEL /// Data point labels. -}; - /** Contains information about auto formatting of a specific chart object type. */ struct XclChFormatInfo { @@ -1298,6 +1296,30 @@ private: XclChTypeInfoMap maInfoMap; /// Maps chart types to type info data. }; +// Chart text and title object helpers ======================================== + +/** Enumerates different text box types for default text formatting and title + positioning. */ +enum XclChTextType +{ + EXC_CHTEXTTYPE_TITLE, /// Chart title. + EXC_CHTEXTTYPE_LEGEND, /// Chart legend. + EXC_CHTEXTTYPE_AXISTITLE, /// Chart axis titles. + EXC_CHTEXTTYPE_AXISLABEL, /// Chart axis labels. + EXC_CHTEXTTYPE_DATALABEL /// Data point labels. +}; + +/** A map key for text and title objects. */ +struct XclChTextKey : public ::std::pair< XclChTextType, ::std::pair< sal_uInt16, sal_uInt16 > > +{ + inline explicit XclChTextKey( XclChTextType eTextType, sal_uInt16 nMainIdx = 0, sal_uInt16 nSubIdx = 0 ) + { first = eTextType; second.first = nMainIdx; second.second = nSubIdx; } +}; + +/** Function prototype receiving a chart document and returning a title shape. */ +typedef ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > + (*XclChGetShapeFunc)( const ::com::sun::star::uno::Reference< ::com::sun::star::chart::XChartDocument >& ); + // Property helpers =========================================================== class XclChObjectTable @@ -1363,10 +1385,6 @@ public: sal_uInt16 ReadRotationProperties( const ScfPropertySet& rPropSet, bool bSupportsStacked ); - /** Reads all legend properties from the passed property set. */ - void ReadLegendProperties( - XclChLegend& rLegend, - const ScfPropertySet& rPropSet ); /** Writes all line properties to the passed property set. */ void WriteLineProperties( @@ -1397,10 +1415,6 @@ public: ScfPropertySet& rPropSet, sal_uInt16 nRotation, bool bSupportsStacked ); - /** Writes all legend properties to the passed property set. */ - void WriteLegendProperties( - ScfPropertySet& rPropSet, - const XclChLegend& rLegend ); private: /** Returns a line property set helper according to the passed property mode. */ @@ -1423,51 +1437,47 @@ private: ScfPropSetHelper maHatchHlpCommon; /// Properties for hatches in common objects. ScfPropSetHelper maHatchHlpFilled; /// Properties for hatches in filled series. ScfPropSetHelper maBitmapHlp; /// Properties for bitmaps. - ScfPropSetHelper maLegendHlp; /// Properties for legend. }; // ============================================================================ /** Base struct for internal root data structs for import and export. */ -class XclChRootData +struct XclChRootData { -public: - typedef ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument > XChartDocRef; + typedef ScfRef< XclChTypeInfoProvider > XclChTypeProvRef; + typedef ScfRef< XclChFormatInfoProvider > XclChFmtInfoProvRef; + typedef ScfRef< XclChObjectTable > XclChObjectTableRef; + typedef ::std::map< XclChTextKey, XclChGetShapeFunc > XclChGetShapeFuncMap; + + ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument > + mxChartDoc; /// The chart document. + Rectangle maChartRect; /// Position and size of the chart shape. + XclChTypeProvRef mxTypeInfoProv; /// Provides info about chart types. + XclChFmtInfoProvRef mxFmtInfoProv; /// Provides info about auto formatting. + XclChObjectTableRef mxLineDashTable; /// Container for line dash styles. + XclChObjectTableRef mxGradientTable; /// Container for gradient fill styles. + XclChObjectTableRef mxHatchTable; /// Container for hatch fill styles. + XclChObjectTableRef mxBitmapTable; /// Container for bitmap fill styles. + XclChGetShapeFuncMap maGetShapeFuncs; /// Maps title shape getter functions. + sal_Int32 mnBorderGapX; /// Border gap to chart space in 1/100mm. + sal_Int32 mnBorderGapY; /// Border gap to chart space in 1/100mm. + double mfUnitSizeX; /// Size of a chart X unit (1/4000 of chart width) in 1/100 mm. + double mfUnitSizeY; /// Size of a chart Y unit (1/4000 of chart height) in 1/100 mm. -public: explicit XclChRootData(); virtual ~XclChRootData(); - /** Returns the API reference of the chart document. */ - XChartDocRef GetChartDoc() const; - - /** Returns the chart type info provider, that contains data about all chart types. */ - inline XclChTypeInfoProvider& GetTypeInfoProvider() const { return *mxTypeInfoProv; } - /** Returns the chart type info provider, that contains data about all chart types. */ - inline XclChFormatInfoProvider& GetFormatInfoProvider() const { return *mxFmtInfoProv; } - - inline XclChObjectTable& GetLineDashTable() const { return *mxLineDashTable; } - inline XclChObjectTable& GetGradientTable() const { return *mxGradientTable; } - inline XclChObjectTable& GetHatchTable() const { return *mxHatchTable; } - inline XclChObjectTable& GetBitmapTable() const { return *mxBitmapTable; } - /** Starts the API chart document conversion. Must be called once before any API access. */ - void InitConversion( XChartDocRef xChartDoc ); + void InitConversion( + const XclRoot& rRoot, + const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument >& rxChartDoc, + const Rectangle& rChartRect ); /** Finishes the API chart document conversion. Must be called once before any API access. */ void FinishConversion(); -private: - typedef ScfRef< XclChTypeInfoProvider > XclChTypeProvRef; - typedef ScfRef< XclChFormatInfoProvider > XclChFmtInfoProvRef; - typedef ScfRef< XclChObjectTable > XclChObjectTableRef; - - XChartDocRef mxChartDoc; /// The chart document. - XclChTypeProvRef mxTypeInfoProv; /// Provides info about chart types. - XclChFmtInfoProvRef mxFmtInfoProv; /// Provides info about auto formatting. - XclChObjectTableRef mxLineDashTable; /// Container for line dash styles. - XclChObjectTableRef mxGradientTable; /// Container for gradient fill styles. - XclChObjectTableRef mxHatchTable; /// Container for hatch fill styles. - XclChObjectTableRef mxBitmapTable; /// Container for bitmap fill styles. + /** Returns the drawing shape interface of the specified title object. */ + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > + GetTitleShape( const XclChTextKey& rTitleKey ) const; }; // ============================================================================ diff --git a/sc/source/filter/inc/xlescher.hxx b/sc/source/filter/inc/xlescher.hxx index 33b75af8cd2c..95a87b51de12 100644 --- a/sc/source/filter/inc/xlescher.hxx +++ b/sc/source/filter/inc/xlescher.hxx @@ -432,7 +432,7 @@ public: GetControlModel( ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape ); /** Returns the Calc macro name from an Excel macro name. */ - static ::rtl::OUString GetScMacroName( const String& rXclMacroName ); + static ::rtl::OUString GetScMacroName( const String& rXclMacroName, SfxObjectShell* pShell = NULL ); /** Returns the Excel macro name from a Calc macro name. */ static String GetXclMacroName( const ::rtl::OUString& rScMacroName ); @@ -440,7 +440,7 @@ public: static bool FillMacroDescriptor( ::com::sun::star::script::ScriptEventDescriptor& rDescriptor, XclTbxEventType eEventType, - const String& rXclMacroName ); + const String& rXclMacroName, SfxObjectShell* pShell = NULL ); /** Tries to extract an Excel macro name from the passed macro descriptor. */ static String ExtractFromMacroDescriptor( const ::com::sun::star::script::ScriptEventDescriptor& rDescriptor, diff --git a/sc/source/filter/inc/xlroot.hxx b/sc/source/filter/inc/xlroot.hxx index f3b0f78a948c..2f029c74baa9 100644 --- a/sc/source/filter/inc/xlroot.hxx +++ b/sc/source/filter/inc/xlroot.hxx @@ -113,6 +113,8 @@ struct XclRootData XclTracerRef mxTracer; /// Filter tracer. RootDataRef mxRD; /// Old RootData struct. Will be removed. + double mfScreenPixelX; /// Width of a screen pixel (1/100 mm). + double mfScreenPixelY; /// Height of a screen pixel (1/100 mm). long mnCharWidth; /// Width of '0' in default font (twips). SCTAB mnScTab; /// Current Calc sheet index. const bool mbExport; /// false = Import, true = Export. @@ -177,6 +179,11 @@ public: /** Returns the current Calc sheet index. */ inline SCTAB GetCurrScTab() const { return mrData.mnScTab; } + /** Calculates the width of the passed number of pixels in 1/100 mm. */ + sal_Int32 GetHmmFromPixelX( double fPixelX ) const; + /** Calculates the height of the passed number of pixels in 1/100 mm. */ + sal_Int32 GetHmmFromPixelY( double fPixelY ) const; + /** Returns the medium to import from. */ inline SfxMedium& GetMedium() const { return mrData.mrMedium; } /** Returns the document URL of the imported/exported file. */ diff --git a/sc/source/filter/xml/sheetdata.cxx b/sc/source/filter/xml/sheetdata.cxx index 66b1c2579dd4..947c1370fa4b 100644 --- a/sc/source/filter/xml/sheetdata.cxx +++ b/sc/source/filter/xml/sheetdata.cxx @@ -43,7 +43,8 @@ ScSheetSaveData::ScSheetSaveData() : mnStartTab( -1 ), mnStartOffset( -1 ), - maPreviousNote( rtl::OUString(), rtl::OUString(), ScAddress(ScAddress::INITIALIZE_INVALID) ) + maPreviousNote( rtl::OUString(), rtl::OUString(), ScAddress(ScAddress::INITIALIZE_INVALID) ), + mbInSupportedSave( false ) { } @@ -270,3 +271,13 @@ bool ScSheetSaveData::AddLoadedNamespaces( SvXMLNamespaceMap& rNamespaces ) cons return true; // success } +bool ScSheetSaveData::IsInSupportedSave() const +{ + return mbInSupportedSave; +} + +void ScSheetSaveData::SetInSupportedSave( bool bSet ) +{ + mbInSupportedSave = bSet; +} + diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx index b3f08f7e554d..a620bc01ffb4 100644 --- a/sc/source/filter/xml/xmlexprt.cxx +++ b/sc/source/filter/xml/xmlexprt.cxx @@ -2605,6 +2605,180 @@ void ScXMLExport::_ExportAutoStyles() GetProgressBarHelper()->SetReference(GetProgressBarHelper()->GetReference() + nCount2 - nCount); } } + + // collect other auto-styles only for non-copied sheets + if (xTable.is() && !bUseStream) + { + uno::Reference<sheet::XUniqueCellFormatRangesSupplier> xCellFormatRanges ( xTable, uno::UNO_QUERY ); + if ( xCellFormatRanges.is() ) + { + uno::Reference<container::XIndexAccess> xFormatRangesIndex(xCellFormatRanges->getUniqueCellFormatRanges()); + if (xFormatRangesIndex.is()) + { + sal_Int32 nFormatRangesCount(xFormatRangesIndex->getCount()); + GetProgressBarHelper()->ChangeReference(GetProgressBarHelper()->GetReference() + nFormatRangesCount); + for (sal_Int32 nFormatRange = 0; nFormatRange < nFormatRangesCount; ++nFormatRange) + { + uno::Reference< sheet::XSheetCellRanges> xCellRanges(xFormatRangesIndex->getByIndex(nFormatRange), uno::UNO_QUERY); + if (xCellRanges.is()) + { + uno::Reference <beans::XPropertySet> xProperties (xCellRanges, uno::UNO_QUERY); + if (xProperties.is()) + { + AddStyleFromCells(xProperties, xTable, nTable, NULL); + IncrementProgressBar(sal_False); + } + } + } + } + } + uno::Reference<table::XColumnRowRange> xColumnRowRange (xTable, uno::UNO_QUERY); + if (xColumnRowRange.is()) + { + if (pDoc) + { + uno::Reference<table::XTableColumns> xTableColumns(xColumnRowRange->getColumns()); + if (xTableColumns.is()) + { + sal_Int32 nColumns(pDoc->GetLastChangedCol(sal::static_int_cast<SCTAB>(nTable))); + pSharedData->SetLastColumn(nTable, nColumns); + table::CellRangeAddress aCellAddress(GetEndAddress(xTable, nTable)); + if (aCellAddress.EndColumn > nColumns) + { + ++nColumns; + pColumnStyles->AddNewTable(nTable, aCellAddress.EndColumn); + } + // else if (nColumns < MAXCOL) + // pColumnStyles->AddNewTable(nTable, ++nColumns); + else + pColumnStyles->AddNewTable(nTable, nColumns); + sal_Int32 nColumn = 0; + while (/*nColumn <= nColumns && */nColumn <= MAXCOL) + { + sal_Int32 nIndex(-1); + sal_Bool bIsVisible(sal_True); + uno::Reference <beans::XPropertySet> xColumnProperties(xTableColumns->getByIndex(nColumn), uno::UNO_QUERY); + if (xColumnProperties.is()) + { + AddStyleFromColumn( xColumnProperties, NULL, nIndex, bIsVisible ); + //if(xPropStates.size()) + pColumnStyles->AddFieldStyleName(nTable, nColumn, nIndex, bIsVisible); + } + sal_Int32 nOld(nColumn); + nColumn = pDoc->GetNextDifferentChangedCol(sal::static_int_cast<SCTAB>(nTable), static_cast<USHORT>(nColumn)); + for (sal_Int32 i = nOld + 1; i < nColumn; ++i) + pColumnStyles->AddFieldStyleName(nTable, i, nIndex, bIsVisible); + } + if (aCellAddress.EndColumn > nColumns) + { + sal_Bool bIsVisible(sal_True); + sal_Int32 nIndex(pColumnStyles->GetStyleNameIndex(nTable, nColumns, bIsVisible)); + for (sal_Int32 i = nColumns + 1; i <= aCellAddress.EndColumn; ++i) + pColumnStyles->AddFieldStyleName(nTable, i, nIndex, bIsVisible); + } + } + uno::Reference<table::XTableRows> xTableRows(xColumnRowRange->getRows()); + if (xTableRows.is()) + { + sal_Int32 nRows(pDoc->GetLastChangedRow(sal::static_int_cast<SCTAB>(nTable))); + pSharedData->SetLastRow(nTable, nRows); + table::CellRangeAddress aCellAddress(GetEndAddress(xTable, nTable)); + if (aCellAddress.EndRow > nRows) + { + ++nRows; + pRowStyles->AddNewTable(nTable, aCellAddress.EndRow); + } + // else if (nRows < MAXROW) + // pRowStyles->AddNewTable(nTable, ++nRows); + else + pRowStyles->AddNewTable(nTable, nRows); + sal_Int32 nRow = 0; + while ( /*nRow <= nRows && */nRow <= MAXROW) + { + sal_Int32 nIndex = 0; + uno::Reference <beans::XPropertySet> xRowProperties(xTableRows->getByIndex(nRow), uno::UNO_QUERY); + if(xRowProperties.is()) + { + AddStyleFromRow( xRowProperties, NULL, nIndex ); + //if(xPropStates.size()) + pRowStyles->AddFieldStyleName(nTable, nRow, nIndex); + } + sal_Int32 nOld(nRow); + nRow = pDoc->GetNextDifferentChangedRow(sal::static_int_cast<SCTAB>(nTable), static_cast<USHORT>(nRow), false); + for (sal_Int32 i = nOld + 1; i < nRow; ++i) + pRowStyles->AddFieldStyleName(nTable, i, nIndex); + } + if (aCellAddress.EndRow > nRows) + { + sal_Int32 nIndex(pRowStyles->GetStyleNameIndex(nTable, nRows)); + for (sal_Int32 i = nRows + 1; i <= aCellAddress.EndRow; ++i) + pRowStyles->AddFieldStyleName(nTable, i, nIndex); + } + } + } + } + uno::Reference<sheet::XCellRangesQuery> xCellRangesQuery (xTable, uno::UNO_QUERY); + if (xCellRangesQuery.is()) + { + uno::Reference<sheet::XSheetCellRanges> xSheetCellRanges(xCellRangesQuery->queryContentCells(sheet::CellFlags::FORMATTED)); + uno::Reference<sheet::XSheetOperation> xSheetOperation(xSheetCellRanges, uno::UNO_QUERY); + if (xSheetCellRanges.is() && xSheetOperation.is()) + { + sal_uInt32 nCount(sal_uInt32(xSheetOperation->computeFunction(sheet::GeneralFunction_COUNT))); + uno::Reference<container::XEnumerationAccess> xCellsAccess(xSheetCellRanges->getCells()); + if (xCellsAccess.is()) + { + GetProgressBarHelper()->ChangeReference(GetProgressBarHelper()->GetReference() + nCount); + uno::Reference<container::XEnumeration> xCells(xCellsAccess->createEnumeration()); + if (xCells.is()) + { + sal_uInt32 nCount2(0); + while (xCells->hasMoreElements()) + { + uno::Reference<text::XText> xText(xCells->nextElement(), uno::UNO_QUERY); + if (xText.is()) + GetTextParagraphExport()->collectTextAutoStyles(xText, sal_False, sal_False); + ++nCount2; + IncrementProgressBar(sal_False); + } + if(nCount2 > nCount) + GetProgressBarHelper()->SetReference(GetProgressBarHelper()->GetReference() + nCount2 - nCount); + } + } + } + } + } + IncrementProgressBar(sal_False); + } + pChangeTrackingExportHelper->CollectAutoStyles(); + + GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_COLUMN, + GetDocHandler(), GetMM100UnitConverter(), GetNamespaceMap()); + GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_ROW, + GetDocHandler(), GetMM100UnitConverter(), GetNamespaceMap()); + GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_TABLE, + GetDocHandler(), GetMM100UnitConverter(), GetNamespaceMap()); + exportAutoDataStyles(); + GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_CELL, + GetDocHandler(), GetMM100UnitConverter(), GetNamespaceMap()); + + GetShapeExport()->exportAutoStyles(); + GetFormExport()->exportAutoStyles( ); + + if (pDoc) + { + ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager(); + // #i100879# write the table style for cached tables only if there are cached tables + // (same logic as in ExportExternalRefCacheStyles) + if (pRefMgr->hasExternalData()) + { + // Special table style for the external ref cache tables. + AddAttribute(XML_NAMESPACE_STYLE, XML_NAME, sExternalRefTabStyleName); + AddAttribute(XML_NAMESPACE_STYLE, XML_FAMILY, XML_TABLE); + SvXMLElementExport aElemStyle(*this, XML_NAMESPACE_STYLE, XML_STYLE, sal_True, sal_True); + AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY, XML_FALSE); + SvXMLElementExport aElemStyleTabProps(*this, XML_NAMESPACE_STYLE, XML_TABLE_PROPERTIES, sal_True, sal_True); + } } } } @@ -3242,6 +3416,7 @@ void ScXMLExport::WriteAreaLink( const ScMyCell& rMyCell ) { const ScMyAreaLink& rAreaLink = rMyCell.aAreaLink; AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, rAreaLink.sSourceStr ); + AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE ); AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, GetRelativeReference(rAreaLink.sURL) ); AddAttribute( XML_NAMESPACE_TABLE, XML_FILTER_NAME, rAreaLink.sFilter ); if( rAreaLink.sFilterOptions.getLength() ) @@ -3725,6 +3900,7 @@ void ScXMLExport::WriteTableSource() xLinkProps->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_REFDELAY))) >>= nRefresh; if (sLink.getLength()) { + AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE); AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, GetRelativeReference(sLink)); if (sTableName.getLength()) AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_NAME, sTableName); @@ -3963,6 +4139,7 @@ void ScXMLExport::WriteExternalRefCaches() aRelUrl = pExtFileData->maRelativeName; else aRelUrl = GetRelativeReference(pExtFileData->maRelativeName); + AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE); AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, aRelUrl); AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_NAME, *itr); if (pExtFileData->maFilterName.Len()) @@ -3992,6 +4169,14 @@ void ScXMLExport::WriteExternalRefCaches() } } + // Column definitions have to be present to make a valid file + { + if (nMaxColsUsed > 1) + AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, + OUString::valueOf(static_cast<sal_Int32>(nMaxColsUsed))); + SvXMLElementExport aElemColumn(*this, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True); + } + // Write cache content for this table. SCROW nLastRow = 0; bool bFirstRow = true; diff --git a/sc/source/filter/xml/xmlexternaltabi.cxx b/sc/source/filter/xml/xmlexternaltabi.cxx index ce1f58f5d912..083a73d81872 100644 --- a/sc/source/filter/xml/xmlexternaltabi.cxx +++ b/sc/source/filter/xml/xmlexternaltabi.cxx @@ -370,7 +370,7 @@ SvXMLImportContext* ScXMLExternalRefCellContext::CreateChildContext( const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowCellElemTokenMap(); sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName); if (nToken == XML_TOK_TABLE_ROW_CELL_P) - return new ScXMLExternalRefCellTextContext(mrScImport, nPrefix, rLocalName, xAttrList, maCellString); + return new ScXMLExternalRefCellTextContext(mrScImport, nPrefix, rLocalName, xAttrList, *this); return new SvXMLImportContext(GetImport(), nPrefix, rLocalName); } @@ -399,14 +399,20 @@ void ScXMLExternalRefCellContext::EndElement() } } +void ScXMLExternalRefCellContext::SetCellString(const OUString& rStr) +{ + maCellString = rStr; +} + // ============================================================================ ScXMLExternalRefCellTextContext::ScXMLExternalRefCellTextContext( ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName, - const Reference<XAttributeList>& /*xAttrList*/, OUString& rCellString ) : + const Reference<XAttributeList>& /*xAttrList*/, + ScXMLExternalRefCellContext& rParent ) : SvXMLImportContext( rImport, nPrefix, rLName ), mrScImport(rImport), - mrCellString(rCellString) + mrParent(rParent) { } @@ -422,9 +428,10 @@ SvXMLImportContext* ScXMLExternalRefCellTextContext::CreateChildContext( void ScXMLExternalRefCellTextContext::Characters(const OUString& rChar) { - mrCellString = rChar; + maCellStrBuf.append(rChar); } void ScXMLExternalRefCellTextContext::EndElement() { + mrParent.SetCellString(maCellStrBuf.makeStringAndClear()); } diff --git a/sc/source/filter/xml/xmlexternaltabi.hxx b/sc/source/filter/xml/xmlexternaltabi.hxx index 0007a8b29702..6aaff181315e 100644 --- a/sc/source/filter/xml/xmlexternaltabi.hxx +++ b/sc/source/filter/xml/xmlexternaltabi.hxx @@ -29,6 +29,7 @@ #define SC_XMLEXTERNALTABI_HXX #include <xmloff/xmlictxt.hxx> +#include "rtl/ustrbuf.hxx" class ScXMLImport; struct ScXMLExternalTabData; @@ -129,6 +130,8 @@ public: virtual void EndElement(); + void SetCellString(const ::rtl::OUString& rStr); + private: ScXMLImport& mrScImport; ScXMLExternalTabData& mrExternalRefInfo; @@ -150,7 +153,7 @@ public: const ::rtl::OUString& rLName, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList>& xAttrList, - ::rtl::OUString& rCellString ); + ScXMLExternalRefCellContext& rParent ); virtual ~ScXMLExternalRefCellTextContext(); @@ -165,7 +168,9 @@ public: private: ScXMLImport& mrScImport; - ::rtl::OUString& mrCellString; + ScXMLExternalRefCellContext& mrParent; + + ::rtl::OUStringBuffer maCellStrBuf; }; #endif diff --git a/sc/source/filter/xml/xmltabi.cxx b/sc/source/filter/xml/xmltabi.cxx index 9afc08308feb..095b6ee6d450 100644 --- a/sc/source/filter/xml/xmltabi.cxx +++ b/sc/source/filter/xml/xmltabi.cxx @@ -98,21 +98,27 @@ static bool lcl_isExternalRefCache(const rtl::OUString& rName, rtl::OUString& rU const sal_Unicode c = p[i]; if (i <= 7) { + // Checking the prefix 'file://'. if (c != aPrefix[i]) return false; } - else if (c == '#') + else if (bInUrl) { - if (cPrev != '\'') - return false; + // parsing file URL + if (c == '#') + { + if (cPrev != '\'') + return false; - rUrl = aUrlBuf.makeStringAndClear(); - rUrl = rUrl.copy(0, rUrl.getLength()-1); // remove the trailing single-quote. - bInUrl = false; + rUrl = aUrlBuf.makeStringAndClear(); + rUrl = rUrl.copy(0, rUrl.getLength()-1); // remove the trailing single-quote. + bInUrl = false; + } + else + aUrlBuf.append(c); } - else if (bInUrl) - aUrlBuf.append(c); else + // parsing sheet name. aTabNameBuf.append(c); cPrev = c; @@ -206,6 +212,7 @@ ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport, ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager(); pExternalRefInfo->mnFileId = pRefMgr->getExternalFileId(aExtUrl); pExternalRefInfo->mpCacheTable = pRefMgr->getCacheTable(pExternalRefInfo->mnFileId, aExtTabName, true); + pExternalRefInfo->mpCacheTable->setWholeTableCached(); } } else diff --git a/sc/source/filter/xml/xmlwrap.cxx b/sc/source/filter/xml/xmlwrap.cxx index fde7f00bb05a..f21ed7d55ac2 100644 --- a/sc/source/filter/xml/xmlwrap.cxx +++ b/sc/source/filter/xml/xmlwrap.cxx @@ -78,6 +78,8 @@ #include "globstr.hrc" #include "scerrors.hxx" #include "XMLExportSharedData.hxx" +#include "docuno.hxx" +#include "sheetdata.hxx" #define MAP_LEN(x) x, sizeof(x) - 1 @@ -738,16 +740,23 @@ sal_Bool ScXMLImportWrapper::ExportToComponent(uno::Reference<lang::XMultiServic uno::Reference<embed::XStorage> xTmpStorage = rDoc.GetDocumentShell()->GetStorage(); uno::Reference<io::XStream> xSrcStream; uno::Reference<io::XInputStream> xSrcInput; - try - { - if (xTmpStorage.is()) - xSrcStream = xTmpStorage->openStreamElement( sName, embed::ElementModes::READ ); - if (xSrcStream.is()) - xSrcInput = xSrcStream->getInputStream(); - } - catch (uno::Exception&) + + // #i108978# If an embedded object is saved and no events are notified, don't use the stream + // because without the ...DONE events, stream positions aren't updated. + ScSheetSaveData* pSheetData = ScModelObj::getImplementation(xModel)->GetSheetSaveData(); + if (pSheetData && pSheetData->IsInSupportedSave()) { - // stream not available (for example, password protected) - save normally (xSrcInput is null) + try + { + if (xTmpStorage.is()) + xSrcStream = xTmpStorage->openStreamElement( sName, embed::ElementModes::READ ); + if (xSrcStream.is()) + xSrcInput = xSrcStream->getInputStream(); + } + catch (uno::Exception&) + { + // stream not available (for example, password protected) - save normally (xSrcInput is null) + } } pExport->SetSourceStream( xSrcInput ); @@ -755,7 +764,10 @@ sal_Bool ScXMLImportWrapper::ExportToComponent(uno::Reference<lang::XMultiServic pExport->SetSourceStream( uno::Reference<io::XInputStream>() ); // If there was an error, reset all stream flags, so the next save attempt will use normal saving. - if (!bRet) + // #i110692# For embedded objects, the stream may be unavailable for one save operation (m_pAntiImpl) + // and become available again later. But after saving normally once, the stream positions aren't + // valid anymore, so the flags also have to be reset if the stream wasn't available. + if ( !bRet || !xSrcInput.is() ) { SCTAB nTabCount = rDoc.GetTableCount(); for (SCTAB nTab=0; nTab<nTabCount; nTab++) diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx index 485ea4b88589..28f178565da0 100644 --- a/sc/source/ui/app/inputhdl.cxx +++ b/sc/source/ui/app/inputhdl.cxx @@ -189,6 +189,14 @@ handle_r1c1: if ( (nFlags & SCA_TAB2_3D) == 0 ) aRange.aEnd.SetTab( aRange.aStart.Tab() ); + if ( ( nFlags & ( SCA_VALID_COL2 | SCA_VALID_ROW2 | SCA_VALID_TAB2 ) ) == 0 ) + { + // #i73766# if a single ref was parsed, set the same "abs" flags for ref2, + // so Format doesn't output a double ref because of different flags. + USHORT nAbsFlags = nFlags & ( SCA_COL_ABSOLUTE | SCA_ROW_ABSOLUTE | SCA_TAB_ABSOLUTE ); + nFlags |= nAbsFlags << 4; + } + if (!nCount) { pEngine->SetUpdateMode( FALSE ); @@ -421,7 +429,9 @@ ScInputHandler::ScInputHandler() pColumnData( NULL ), pFormulaData( NULL ), pFormulaDataPara( NULL ), + pTipVisibleParent( NULL ), nTipVisible( 0 ), + pTipVisibleSecParent( NULL ), nTipVisibleSec( 0 ), nAutoPos( SCPOS_INVALID ), bUseTab( FALSE ), @@ -683,12 +693,29 @@ void ScInputHandler::GetFormulaData() } } +IMPL_LINK( ScInputHandler, ShowHideTipVisibleParentListener, VclWindowEvent*, pEvent ) +{ + if( pEvent->GetId() == VCLEVENT_OBJECT_DYING || pEvent->GetId() == VCLEVENT_WINDOW_HIDE ) + HideTip(); + return 0; +} + +IMPL_LINK( ScInputHandler, ShowHideTipVisibleSecParentListener, VclWindowEvent*, pEvent ) +{ + if( pEvent->GetId() == VCLEVENT_OBJECT_DYING || pEvent->GetId() == VCLEVENT_WINDOW_HIDE ) + HideTipBelow(); + return 0; +} + void ScInputHandler::HideTip() { if ( nTipVisible ) { + if (pTipVisibleParent) + pTipVisibleParent->RemoveEventListener( LINK( this, ScInputHandler, ShowHideTipVisibleParentListener ) ); Help::HideTip( nTipVisible ); nTipVisible = 0; + pTipVisibleParent = NULL; } aManualTip.Erase(); } @@ -696,8 +723,11 @@ void ScInputHandler::HideTipBelow() { if ( nTipVisibleSec ) { + if (pTipVisibleSecParent) + pTipVisibleSecParent->RemoveEventListener( LINK( this, ScInputHandler, ShowHideTipVisibleSecParentListener ) ); Help::HideTip( nTipVisibleSec ); nTipVisibleSec = 0; + pTipVisibleSecParent = NULL; } aManualTip.Erase(); } @@ -889,15 +919,16 @@ void ScInputHandler::ShowTip( const String& rText ) if (pActiveView) { Point aPos; - Window* pWin = pActiveView->GetWindow(); + pTipVisibleParent = pActiveView->GetWindow(); Cursor* pCur = pActiveView->GetCursor(); if (pCur) - aPos = pWin->LogicToPixel( pCur->GetPos() ); - aPos = pWin->OutputToScreenPixel( aPos ); + aPos = pTipVisibleParent->LogicToPixel( pCur->GetPos() ); + aPos = pTipVisibleParent->OutputToScreenPixel( aPos ); Rectangle aRect( aPos, aPos ); USHORT nAlign = QUICKHELP_LEFT|QUICKHELP_BOTTOM; - nTipVisible = Help::ShowTip(pWin, aRect, rText, nAlign); + nTipVisible = Help::ShowTip(pTipVisibleParent, aRect, rText, nAlign); + pTipVisibleParent->AddEventListener( LINK( this, ScInputHandler, ShowHideTipVisibleParentListener ) ); } } @@ -909,18 +940,19 @@ void ScInputHandler::ShowTipBelow( const String& rText ) if ( pActiveView ) { Point aPos; - Window* pWin = pActiveView->GetWindow(); + pTipVisibleSecParent = pActiveView->GetWindow(); Cursor* pCur = pActiveView->GetCursor(); if ( pCur ) { Point aLogicPos = pCur->GetPos(); aLogicPos.Y() += pCur->GetHeight(); - aPos = pWin->LogicToPixel( aLogicPos ); + aPos = pTipVisibleSecParent->LogicToPixel( aLogicPos ); } - aPos = pWin->OutputToScreenPixel( aPos ); + aPos = pTipVisibleSecParent->OutputToScreenPixel( aPos ); Rectangle aRect( aPos, aPos ); USHORT nAlign = QUICKHELP_LEFT | QUICKHELP_TOP; - nTipVisibleSec = Help::ShowTip(pWin, aRect, rText, nAlign); + nTipVisibleSec = Help::ShowTip(pTipVisibleSecParent, aRect, rText, nAlign); + pTipVisibleSecParent->AddEventListener( LINK( this, ScInputHandler, ShowHideTipVisibleSecParentListener ) ); } } @@ -2682,6 +2714,7 @@ void ScInputHandler::EnterHandler( BYTE nBlockMode ) delete pObject; HideTip(); + HideTipBelow(); nFormSelStart = nFormSelEnd = 0; aFormText.Erase(); diff --git a/sc/source/ui/app/scdll.cxx b/sc/source/ui/app/scdll.cxx index 11e33a8892e8..a1b8f05d2918 100644 --- a/sc/source/ui/app/scdll.cxx +++ b/sc/source/ui/app/scdll.cxx @@ -40,6 +40,7 @@ #include <svx/tbxcolor.hxx> #include <sot/clsids.hxx> +#include <sfx2/taskpane.hxx> #include <sfx2/docfilt.hxx> #include <sfx2/fcontnr.hxx> #include <sfx2/docfile.hxx> @@ -47,7 +48,7 @@ #include <avmedia/mediaplayer.hxx> #include <avmedia/mediatoolbox.hxx> #include <comphelper/types.hxx> -#include <svx/extrusioncontrols.hxx> +#include <svx/extrusioncolorcontrol.hxx> #include <svx/fontworkgallery.hxx> #include <svx/tbxcustomshapes.hxx> @@ -263,6 +264,9 @@ void ScDLL::Init() //Media Controller ::avmedia::MediaToolBoxControl::RegisterControl( SID_AVMEDIA_TOOLBOX, pMod ); + // common SFX controller + ::sfx2::TaskPaneWrapper::RegisterChildWindow( FALSE, pMod ); + // Svx-StatusBar-Controller SvxInsertStatusBarControl ::RegisterControl(SID_ATTR_INSERT, pMod); SvxSelectionModeControl ::RegisterControl(SID_STATUS_SELMODE, pMod); @@ -278,15 +282,8 @@ void ScDLL::Init() SvxFontSizeMenuControl ::RegisterControl(SID_ATTR_CHAR_FONTHEIGHT, pMod); // CustomShape extrusion controller - svx::ExtrusionDepthControl::RegisterControl( SID_EXTRUSION_DEPTH_FLOATER, pMod ); - svx::ExtrusionDirectionControl::RegisterControl( SID_EXTRUSION_DIRECTION_FLOATER, pMod ); - svx::ExtrusionLightingControl::RegisterControl( SID_EXTRUSION_LIGHTING_FLOATER, pMod ); - svx::ExtrusionSurfaceControl::RegisterControl( SID_EXTRUSION_SURFACE_FLOATER, pMod ); svx::ExtrusionColorControl::RegisterControl( SID_EXTRUSION_3D_COLOR, pMod ); - svx::FontWorkShapeTypeControl::RegisterControl( SID_FONTWORK_SHAPE_TYPE, pMod ); - svx::FontWorkAlignmentControl::RegisterControl( SID_FONTWORK_ALIGNMENT_FLOATER, pMod ); - svx::FontWorkCharacterSpacingControl::RegisterControl( SID_FONTWORK_CHARACTER_SPACING_FLOATER, pMod ); // Child-Windows diff --git a/sc/source/ui/app/scmod.cxx b/sc/source/ui/app/scmod.cxx index 5220563be966..8f46b11236ae 100644 --- a/sc/source/ui/app/scmod.cxx +++ b/sc/source/ui/app/scmod.cxx @@ -98,7 +98,6 @@ #include "msgpool.hxx" #include "scresid.hxx" #include "anyrefdg.hxx" -#include "teamdlg.hxx" #include "dwfunctr.hxx" #include "formdata.hxx" //CHINA001 #include "tpview.hxx" @@ -142,7 +141,6 @@ ScModule::ScModule( SfxObjectFactory* pFact ) : pSelTransfer( NULL ), pMessagePool( NULL ), pRefInputHandler( NULL ), - pTeamDlg( NULL ), pViewCfg( NULL ), pDocCfg( NULL ), pAppCfg( NULL ), @@ -1507,11 +1505,6 @@ void ScModule::ViewShellGone( ScTabViewShell* pViewSh ) ScInputHandler* pHdl = GetInputHdl(); if (pHdl) pHdl->ViewShellGone( pViewSh ); - - // Team dialog is opened with the window from a view as parent - // -> close it if any view is closed - if (pTeamDlg) - pTeamDlg->Close(); // resets variable pTeamDlg } void ScModule::SetRefInputHdl( ScInputHandler* pNew ) @@ -1635,21 +1628,6 @@ void ScModule::SetRefDialog( USHORT nId, BOOL bVis, SfxViewFrame* pViewFrm ) } } -void ScModule::OpenTeamDlg() -{ - if ( !pTeamDlg ) - { - // team dialog needs an existing parent window - // -> use window from active view (dialog is closed in ViewShellGone) - - ScTabViewShell* pShell = ScTabViewShell::GetActiveViewShell(); - if (pShell) - pTeamDlg = new ScTeamDlg( pShell->GetActiveWin() ); - } - else - pTeamDlg->Center(); -} - SfxChildWindow* lcl_GetChildWinFromAnyView( USHORT nId ) { // first try the current view diff --git a/sc/source/ui/dbgui/filtdlg.cxx b/sc/source/ui/dbgui/filtdlg.cxx index 56878f623828..b5dd2f3242c2 100644 --- a/sc/source/ui/dbgui/filtdlg.cxx +++ b/sc/source/ui/dbgui/filtdlg.cxx @@ -448,24 +448,27 @@ void ScFilterDlg::UpdateValueList( USHORT nList ) SCCOL nColumn = theQueryData.nCol1 + static_cast<SCCOL>(nFieldSelPos) - 1; if (!pEntryLists[nColumn]) { + USHORT nOffset = GetSliderPos(); SCTAB nTab = nSrcTab; SCROW nFirstRow = theQueryData.nRow1; SCROW nLastRow = theQueryData.nRow2; + mbHasDates[nOffset+nList-1] = false; // erstmal ohne die erste Zeile pEntryLists[nColumn] = new TypedScStrCollection( 128, 128 ); pEntryLists[nColumn]->SetCaseSensitive( aBtnCase.IsChecked() ); pDoc->GetFilterEntriesArea( nColumn, nFirstRow+1, nLastRow, - nTab, *pEntryLists[nColumn] ); + nTab, *pEntryLists[nColumn], mbHasDates[nOffset+nList-1] ); // Eintrag fuer die erste Zeile //! Eintrag (pHdrEntry) ohne Collection erzeugen? nHeaderPos[nColumn] = USHRT_MAX; TypedScStrCollection aHdrColl( 1, 1 ); + bool bDummy = false; pDoc->GetFilterEntriesArea( nColumn, nFirstRow, nFirstRow, - nTab, aHdrColl ); + nTab, aHdrColl, bDummy ); TypedStrData* pHdrEntry = aHdrColl[0]; if ( pHdrEntry ) { @@ -1061,7 +1064,8 @@ IMPL_LINK( ScFilterDlg, ValModifyHdl, ComboBox*, pEd ) static_cast<SCCOL>(nField) - 1) : static_cast<SCCOL>(0); ScQueryOp eOp = (ScQueryOp)pLbCond->GetSelectEntryPos(); - rEntry.eOp = eOp; + rEntry.eOp = eOp; + rEntry.bQueryByDate = mbHasDates[nQE]; } } diff --git a/sc/source/ui/dbgui/makefile.mk b/sc/source/ui/dbgui/makefile.mk index 2d4fa71f690e..1e7000d0cb07 100644 --- a/sc/source/ui/dbgui/makefile.mk +++ b/sc/source/ui/dbgui/makefile.mk @@ -106,7 +106,6 @@ LIB1OBJFILES = \ $(SLO)$/expftext.obj \ $(SLO)$/fieldwnd.obj \ $(SLO)$/pvlaydlg.obj \ - $(SLO)$/pvfundlg.obj \ $(SLO)$/consdlg.obj \ $(SLO)$/imoptdlg.obj \ $(SLO)$/csvsplits.obj \ diff --git a/sc/source/ui/dbgui/pfiltdlg.cxx b/sc/source/ui/dbgui/pfiltdlg.cxx index cde18fcc3b52..d590ffb83457 100644 --- a/sc/source/ui/dbgui/pfiltdlg.cxx +++ b/sc/source/ui/dbgui/pfiltdlg.cxx @@ -349,11 +349,12 @@ void ScPivotFilterDlg::UpdateValueList( USHORT nList ) SCROW nFirstRow = theQueryData.nRow1; SCROW nLastRow = theQueryData.nRow2; nFirstRow++; + bool bHasDates = false; pEntryLists[nColumn] = new TypedScStrCollection( 128, 128 ); pEntryLists[nColumn]->SetCaseSensitive( aBtnCase.IsChecked() ); pDoc->GetFilterEntriesArea( nColumn, nFirstRow, nLastRow, - nTab, *pEntryLists[nColumn] ); + nTab, *pEntryLists[nColumn], bHasDates ); } TypedScStrCollection* pColl = pEntryLists[nColumn]; diff --git a/sc/source/ui/dbgui/pvfundlg.cxx b/sc/source/ui/dbgui/pvfundlg.cxx index 03de0b8914a3..6b04993ba0bc 100644 --- a/sc/source/ui/dbgui/pvfundlg.cxx +++ b/sc/source/ui/dbgui/pvfundlg.cxx @@ -28,6 +28,8 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sc.hxx" +#undef SC_DLLIMPLEMENTATION + #include "pvfundlg.hxx" #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp> diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx index da6ff27990a0..5ca2a01f05c9 100644 --- a/sc/source/ui/docshell/docfunc.cxx +++ b/sc/source/ui/docshell/docfunc.cxx @@ -48,6 +48,12 @@ #include <svl/zforlist.hxx> #include <svl/PasswordHelper.hxx> +#include <basic/sbstar.hxx> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/script/XLibraryContainer.hpp> +#include <com/sun/star/script/XVBAModuleInfo.hpp> +#include <com/sun/star/script/ModuleType.hpp> + #include <list> #include "docfunc.hxx" @@ -92,8 +98,11 @@ #include "scui_def.hxx" //CHINA001 #include "tabprotection.hxx" #include "clipparam.hxx" +#include "externalrefmgr.hxx" #include <memory> +#include <basic/basmgr.hxx> +#include <boost/scoped_ptr.hpp> using namespace com::sun::star; using ::com::sun::star::uno::Sequence; @@ -1035,6 +1044,10 @@ BOOL ScDocFunc::SetCellText( const ScAddress& rPos, const String& rText, { if ( bEnglish ) { + ::boost::scoped_ptr<ScExternalRefManager::ApiGuard> pExtRefGuard; + if (bApi) + pExtRefGuard.reset(new ScExternalRefManager::ApiGuard(pDoc)); + // code moved to own method InterpretEnglishString because it is also used in // ScCellRangeObj::setFormulaArray @@ -2576,6 +2589,106 @@ BOOL ScDocFunc::MoveBlock( const ScRange& rSource, const ScAddress& rDestPos, } //------------------------------------------------------------------------ +uno::Reference< uno::XInterface > GetDocModuleObject( SfxObjectShell& rDocSh, String& sCodeName ) +{ + uno::Reference< lang::XMultiServiceFactory> xSF(rDocSh.GetModel(), uno::UNO_QUERY); + uno::Reference< container::XNameAccess > xVBACodeNamedObjectAccess; + uno::Reference< uno::XInterface > xDocModuleApiObject; + if ( xSF.is() ) + { + xVBACodeNamedObjectAccess.set( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAObjectModuleObjectProvider"))), uno::UNO_QUERY ); + xDocModuleApiObject.set( xVBACodeNamedObjectAccess->getByName( sCodeName ), uno::UNO_QUERY ); + } + return xDocModuleApiObject; + +} + +script::ModuleInfo lcl_InitModuleInfo( SfxObjectShell& rDocSh, String& sModule ) +{ + ::rtl::OUString sVbaOption( RTL_CONSTASCII_USTRINGPARAM( "Rem Attribute VBA_ModuleType=VBADocumentModule\nOption VBASupport 1\n" )); + script::ModuleInfo sModuleInfo; + sModuleInfo.ModuleType = script::ModuleType::DOCUMENT; + sModuleInfo.ModuleObject = GetDocModuleObject( rDocSh, sModule ); + return sModuleInfo; +} + +void VBA_InsertModule( ScDocument& rDoc, SCTAB nTab, String& sModuleName, String& sSource ) +{ + SFX_APP()->EnterBasicCall(); + SfxObjectShell& rDocSh = *rDoc.GetDocumentShell(); + uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer(); + DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" ); + + uno::Reference< container::XNameContainer > xLib; + if( xLibContainer.is() ) + { + String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); + if ( rDocSh.GetBasicManager() && rDocSh.GetBasicManager()->GetName().Len() ) + aLibName = rDocSh.GetBasicManager()->GetName(); + uno::Any aLibAny = xLibContainer->getByName( aLibName ); + aLibAny >>= xLib; + } + if( xLib.is() ) + { + // if the Module with codename exists then find a new name + sal_Int32 nNum = 0; + String genModuleName; + if ( sModuleName.Len() ) + sModuleName = sModuleName; + else + { + genModuleName = String::CreateFromAscii( "Sheet1" ); + nNum = 1; + } + while( xLib->hasByName( genModuleName ) ) + genModuleName = rtl::OUString::createFromAscii( "Sheet" ) + rtl::OUString::valueOf( ++nNum ); + + uno::Any aSourceAny; + rtl::OUString sTmpSource = sSource; + if ( sTmpSource.getLength() == 0 ) + sTmpSource = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Rem Attribute VBA_ModuleType=VBADocumentModule\nOption VBASupport 1\n" )); + aSourceAny <<= sTmpSource; + uno::Reference< script::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY ); + if ( xVBAModuleInfo.is() ) + { + String sCodeName( genModuleName ); + rDoc.SetCodeName( nTab, sCodeName ); + script::ModuleInfo sModuleInfo = lcl_InitModuleInfo( rDocSh, genModuleName ); + xVBAModuleInfo->insertModuleInfo( genModuleName, sModuleInfo ); + xLib->insertByName( genModuleName, aSourceAny ); + } + + } + SFX_APP()->LeaveBasicCall(); +} + +void VBA_DeleteModule( ScDocShell& rDocSh, String& sModuleName ) +{ + SFX_APP()->EnterBasicCall(); + uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer(); + DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" ); + + uno::Reference< container::XNameContainer > xLib; + if( xLibContainer.is() ) + { + String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); + if ( rDocSh.GetBasicManager() && rDocSh.GetBasicManager()->GetName().Len() ) + aLibName = rDocSh.GetBasicManager()->GetName(); + uno::Any aLibAny = xLibContainer->getByName( aLibName ); + aLibAny >>= xLib; + } + if( xLib.is() ) + { + uno::Reference< script::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY ); + if( xLib->hasByName( sModuleName ) ) + xLib->removeByName( sModuleName ); + if ( xVBAModuleInfo.is() ) + xVBAModuleInfo->removeModuleInfo( sModuleName ); + + } + SFX_APP()->LeaveBasicCall(); +} + BOOL ScDocFunc::InsertTable( SCTAB nTab, const String& rName, BOOL bRecord, BOOL bApi ) { @@ -2585,8 +2698,19 @@ BOOL ScDocFunc::InsertTable( SCTAB nTab, const String& rName, BOOL bRecord, BOOL ScDocShellModificator aModificator( rDocShell ); ScDocument* pDoc = rDocShell.GetDocument(); - if (bRecord && !pDoc->IsUndoEnabled()) + + + // Strange loop, also basic is loaded too early ( InsertTable ) + // is called via the xml import for sheets in described in odf + BOOL bInsertDocModule = false; + + if( !rDocShell.GetDocument()->IsImportingXML() ) + { + bInsertDocModule = pDoc ? pDoc->IsInVBAMode() : false; + } + if ( bInsertDocModule || ( bRecord && !pDoc->IsUndoEnabled() ) ) bRecord = FALSE; + if (bRecord) pDoc->BeginDrawUndo(); // InsertTab erzeugt ein SdrUndoNewPage @@ -2597,10 +2721,17 @@ BOOL ScDocFunc::InsertTable( SCTAB nTab, const String& rName, BOOL bRecord, BOOL if (pDoc->InsertTab( nTab, rName )) { + String sCodeName; if (bRecord) rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertTab( &rDocShell, nTab, bAppend, rName)); // Views updaten: + // Only insert vba modules if vba mode ( and not currently importing XML ) + if( bInsertDocModule ) + { + String sSource; + VBA_InsertModule( *pDoc, nTab, sCodeName, sSource ); + } rDocShell.Broadcast( ScTablesHint( SC_TAB_INSERTED, nTab ) ); rDocShell.PostPaintExtras(); @@ -2622,8 +2753,11 @@ BOOL ScDocFunc::DeleteTable( SCTAB nTab, BOOL bRecord, BOOL /* bApi */ ) BOOL bSuccess = FALSE; ScDocument* pDoc = rDocShell.GetDocument(); + BOOL bVbaEnabled = pDoc ? pDoc->IsInVBAMode() : false; if (bRecord && !pDoc->IsUndoEnabled()) bRecord = FALSE; + if ( bVbaEnabled ) + bRecord = FALSE; BOOL bWasLinked = pDoc->IsLinked(nTab); ScDocument* pUndoDoc = NULL; ScRefUndoData* pUndoData = NULL; @@ -2665,6 +2799,8 @@ BOOL ScDocFunc::DeleteTable( SCTAB nTab, BOOL bRecord, BOOL /* bApi */ ) pUndoData = new ScRefUndoData( pDoc ); } + String sCodeName; + BOOL bHasCodeName = pDoc->GetCodeName( nTab, sCodeName ); if (pDoc->DeleteTab( nTab, pUndoDoc )) { if (bRecord) @@ -2675,6 +2811,13 @@ BOOL ScDocFunc::DeleteTable( SCTAB nTab, BOOL bRecord, BOOL /* bApi */ ) new ScUndoDeleteTab( &rDocShell, theTabs, pUndoDoc, pUndoData )); } // Views updaten: + if( bVbaEnabled ) + { + if( bHasCodeName ) + { + VBA_DeleteModule( rDocShell, sCodeName ); + } + } rDocShell.Broadcast( ScTablesHint( SC_TAB_DELETED, nTab ) ); if (bWasLinked) diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx index 821b2a6ad880..135bbcdace49 100644 --- a/sc/source/ui/docshell/docsh.cxx +++ b/sc/source/ui/docshell/docsh.cxx @@ -356,6 +356,7 @@ void ScDocShell::AfterXMLLoading(sal_Bool bRet) } else aDocument.SetInsertingFromOtherDoc( FALSE ); +#if 0 // disable load of vba related libraries // add vba globals ( if they are availabl ) uno::Any aGlobs; uno::Sequence< uno::Any > aArgs(1); @@ -376,7 +377,7 @@ void ScDocShell::AfterXMLLoading(sal_Bool bRet) BasicManager* pAppMgr = SFX_APP()->GetBasicManager(); if ( pAppMgr ) pAppMgr->SetGlobalUNOConstant( "ThisExcelDoc", aArgs[ 0 ] ); - +#endif aDocument.SetImportingXML( FALSE ); aDocument.EnableExecuteLink( true ); aDocument.EnableUndo( TRUE ); @@ -767,19 +768,38 @@ void __EXPORT ScDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint ) if ( !bSuccess ) SetError( ERRCODE_IO_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); // this error code will produce no error message, but will break the further saving process } + if (pSheetSaveData) + pSheetSaveData->SetInSupportedSave(true); } break; + case SFX_EVENT_SAVEASDOC: + case SFX_EVENT_SAVETODOC: + // #i108978# If no event is sent before saving, there will also be no "...DONE" event, + // and SAVE/SAVEAS can't be distinguished from SAVETO. So stream copying is only enabled + // if there is a SAVE/SAVEAS/SAVETO event first. + if (pSheetSaveData) + pSheetSaveData->SetInSupportedSave(true); + break; case SFX_EVENT_SAVEDOCDONE: { if ( IsDocShared() && !SC_MOD()->IsInSharedDocSaving() ) { } UseSheetSaveEntries(); // use positions from saved file for next saving + if (pSheetSaveData) + pSheetSaveData->SetInSupportedSave(false); } break; case SFX_EVENT_SAVEASDOCDONE: // new positions are used after "save" and "save as", but not "save to" UseSheetSaveEntries(); // use positions from saved file for next saving + if (pSheetSaveData) + pSheetSaveData->SetInSupportedSave(false); + break; + case SFX_EVENT_SAVETODOCDONE: + // only reset the flag, don't use the new positions + if (pSheetSaveData) + pSheetSaveData->SetInSupportedSave(false); break; default: { diff --git a/sc/source/ui/docshell/docsh2.cxx b/sc/source/ui/docshell/docsh2.cxx index 4b76c18edbe6..9e3ed217382f 100644 --- a/sc/source/ui/docshell/docsh2.cxx +++ b/sc/source/ui/docshell/docsh2.cxx @@ -102,6 +102,7 @@ BOOL __EXPORT ScDocShell::InitNew( const uno::Reference < embed::XStorage >& xSt InitItems(); CalcOutputFactor(); +#if 0 uno::Any aGlobs; uno::Sequence< uno::Any > aArgs(1); aArgs[ 0 ] <<= GetModel(); @@ -121,6 +122,7 @@ BOOL __EXPORT ScDocShell::InitNew( const uno::Reference < embed::XStorage >& xSt BasicManager* pAppMgr = SFX_APP()->GetBasicManager(); if ( pAppMgr ) pAppMgr->SetGlobalUNOConstant( "ThisExcelDoc", aArgs[ 0 ] ); +#endif return bRet; } diff --git a/sc/source/ui/docshell/docsh5.cxx b/sc/source/ui/docshell/docsh5.cxx index 1bbf9437bc1c..84979e3dbcdf 100644 --- a/sc/source/ui/docshell/docsh5.cxx +++ b/sc/source/ui/docshell/docsh5.cxx @@ -65,6 +65,11 @@ #include "sc.hrc" #include "waitoff.hxx" #include "sizedev.hxx" +#include <basic/sbstar.hxx> +#include <basic/basmgr.hxx> + +// defined in docfunc.cxx +void VBA_InsertModule( ScDocument& rDoc, SCTAB nTab, String& sModuleName, String& sModuleSource ); // --------------------------------------------------------------------------- @@ -97,8 +102,9 @@ void ScDocShell::ErrorMessage( USHORT nGlobStrId ) BOOL ScDocShell::IsEditable() const { // import into read-only document is possible - must be extended if other filters use api + // #i108547# MSOOXML filter uses "IsChangeReadOnlyEnabled" property - return !IsReadOnly() || aDocument.IsImportingXML(); + return !IsReadOnly() || aDocument.IsImportingXML() || aDocument.IsChangeReadOnlyEnabled(); } void ScDocShell::DBAreaDeleted( SCTAB nTab, SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW /* nY2 */ ) @@ -865,6 +871,8 @@ BOOL ScDocShell::MoveTable( SCTAB nSrcTab, SCTAB nDestTab, BOOL bCopy, BOOL bRec if (bRecord) aDocument.BeginDrawUndo(); // drawing layer must do its own undo actions + String sSrcCodeName; + aDocument.GetCodeName( nSrcTab, sSrcCodeName ); if (!aDocument.CopyTab( nSrcTab, nDestTab )) { //! EndDrawUndo? @@ -888,8 +896,38 @@ BOOL ScDocShell::MoveTable( SCTAB nSrcTab, SCTAB nDestTab, BOOL bCopy, BOOL bRec GetUndoManager()->AddUndoAction( new ScUndoCopyTab( this, aSrcList, aDestList ) ); } - } + BOOL bVbaEnabled = aDocument.IsInVBAMode(); + if ( bVbaEnabled ) + { + StarBASIC* pStarBASIC = GetBasic(); + String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); + if ( GetBasicManager()->GetName().Len() > 0 ) + { + aLibName = GetBasicManager()->GetName(); + pStarBASIC = GetBasicManager()->GetLib( aLibName ); + } + SCTAB nTabToUse = nDestTab; + if ( nDestTab == SC_TAB_APPEND ) + nTabToUse = aDocument.GetMaxTableNumber() - 1; + String sCodeName; + String sSource; + com::sun::star::uno::Reference< com::sun::star::script::XLibraryContainer > xLibContainer = GetBasicContainer(); + com::sun::star::uno::Reference< com::sun::star::container::XNameContainer > xLib; + if( xLibContainer.is() ) + { + com::sun::star::uno::Any aLibAny = xLibContainer->getByName( aLibName ); + aLibAny >>= xLib; + } + if( xLib.is() ) + { + rtl::OUString sRTLSource; + xLib->getByName( sSrcCodeName ) >>= sRTLSource; + sSource = sRTLSource; + } + VBA_InsertModule( aDocument, nTabToUse, sCodeName, sSource ); + } + } Broadcast( ScTablesHint( SC_TAB_COPIED, nSrcTab, nDestTab ) ); } else diff --git a/sc/source/ui/docshell/docsh8.cxx b/sc/source/ui/docshell/docsh8.cxx index b761dd75d9df..cb9d625da70c 100644 --- a/sc/source/ui/docshell/docsh8.cxx +++ b/sc/source/ui/docshell/docsh8.cxx @@ -597,7 +597,7 @@ void lcl_GetColumnTypes( ScDocShell& rDocShell, else if ( nDbType == sdbc::DataType::DECIMAL ) { // maximale Feldbreite und Nachkommastellen bestimmen xub_StrLen nLen; - USHORT nPrec; + sal_uInt16 nPrec; nLen = pDoc->GetMaxNumberStringLen( nPrec, nTab, nCol, nFirstDataRow, nLastRow ); // dBaseIII Limit Nachkommastellen: 15 diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx index e7b04afa9c4f..0569e95605b1 100644 --- a/sc/source/ui/docshell/externalrefmgr.cxx +++ b/sc/source/ui/docshell/externalrefmgr.cxx @@ -65,6 +65,8 @@ #include <memory> #include <algorithm> +#include <boost/scoped_ptr.hpp> + using ::std::auto_ptr; using ::com::sun::star::uno::Any; using ::rtl::OUString; @@ -135,6 +137,69 @@ private: ScExternalRefManager::LinkUpdateType meType; }; +struct UpdateFormulaCell : public unary_function<ScFormulaCell*, void> +{ + void operator() (ScFormulaCell* pCell) const + { + // Check to make sure the cell really contains ocExternalRef. + // External names, external cell and range references all have a + // ocExternalRef token. + const ScTokenArray* pCode = pCell->GetCode(); + if (!pCode->HasOpCode( ocExternalRef)) + return; + + ScTokenArray* pArray = pCell->GetCode(); + if (pArray) + // Clear the error code, or a cell with error won't get re-compiled. + pArray->SetCodeError(0); + + pCell->SetCompile(true); + pCell->CompileTokenArray(); + pCell->SetDirty(); + } +}; + +class RemoveFormulaCell : public unary_function<pair<const sal_uInt16, ScExternalRefManager::RefCellSet>, void> +{ +public: + explicit RemoveFormulaCell(ScFormulaCell* p) : mpCell(p) {} + void operator() (pair<const sal_uInt16, ScExternalRefManager::RefCellSet>& r) const + { + r.second.erase(mpCell); + } +private: + ScFormulaCell* mpCell; +}; + +class ConvertFormulaToStatic : public unary_function<ScFormulaCell*, void> +{ +public: + explicit ConvertFormulaToStatic(ScDocument* pDoc) : mpDoc(pDoc) {} + void operator() (ScFormulaCell* pCell) const + { + ScAddress aPos = pCell->aPos; + + // We don't check for empty cells because empty external cells are + // treated as having a value of 0. + + if (pCell->IsValue()) + { + // Turn this into value cell. + double fVal = pCell->GetValue(); + mpDoc->PutCell(aPos, new ScValueCell(fVal)); + } + else + { + // string cell otherwise. + String aVal; + pCell->GetString(aVal); + mpDoc->PutCell(aPos, new ScStringCell(aVal)); + } + } +private: + ScDocument* mpDoc; +}; + } // ============================================================================ @@ -170,7 +235,7 @@ bool ScExternalRefCache::Table::isReferenced() const return meReferenced != UNREFERENCED; } -void ScExternalRefCache::Table::setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex) +void ScExternalRefCache::Table::setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex, bool bSetCacheRange) { using ::std::pair; RowsDataType::iterator itrRow = maRows.find(nRow); @@ -193,6 +258,8 @@ void ScExternalRefCache::Table::setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, aCell.mxToken = pToken; aCell.mnFmtIndex = nFmtIndex; rRow.insert(RowDataType::value_type(nCol, aCell)); + if (bSetCacheRange) + setCachedCell(nCol, nRow); } ScExternalRefCache::TokenRef ScExternalRefCache::Table::getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex) const @@ -201,7 +268,7 @@ ScExternalRefCache::TokenRef ScExternalRefCache::Table::getCell(SCCOL nCol, SCRO if (itrTable == maRows.end()) { // this table doesn't have the specified row. - return TokenRef(); + return getEmptyOrNullToken(nCol, nRow); } const RowDataType& rRowData = itrTable->second; @@ -209,7 +276,7 @@ ScExternalRefCache::TokenRef ScExternalRefCache::Table::getCell(SCCOL nCol, SCRO if (itrRow == rRowData.end()) { // this row doesn't have the specified column. - return TokenRef(); + return getEmptyOrNullToken(nCol, nRow); } const Cell& rCell = itrRow->second; @@ -225,13 +292,14 @@ bool ScExternalRefCache::Table::hasRow( SCROW nRow ) const return itrRow != maRows.end(); } -void ScExternalRefCache::Table::getAllRows(vector<SCROW>& rRows) const +void ScExternalRefCache::Table::getAllRows(vector<SCROW>& rRows, SCROW nLow, SCROW nHigh) const { vector<SCROW> aRows; aRows.reserve(maRows.size()); RowsDataType::const_iterator itr = maRows.begin(), itrEnd = maRows.end(); for (; itr != itrEnd; ++itr) - aRows.push_back(itr->first); + if (nLow <= itr->first && itr->first <= nHigh) + aRows.push_back(itr->first); // hash map is not ordered, so we need to explicitly sort it. ::std::sort(aRows.begin(), aRows.end()); @@ -258,7 +326,7 @@ void ScExternalRefCache::Table::getAllRows(vector<SCROW>& rRows) const return aRange; } -void ScExternalRefCache::Table::getAllCols(SCROW nRow, vector<SCCOL>& rCols) const +void ScExternalRefCache::Table::getAllCols(SCROW nRow, vector<SCCOL>& rCols, SCCOL nLow, SCCOL nHigh) const { RowsDataType::const_iterator itrRow = maRows.find(nRow); if (itrRow == maRows.end()) @@ -270,7 +338,8 @@ void ScExternalRefCache::Table::getAllCols(SCROW nRow, vector<SCCOL>& rCols) con aCols.reserve(rRowData.size()); RowDataType::const_iterator itrCol = rRowData.begin(), itrColEnd = rRowData.end(); for (; itrCol != itrColEnd; ++itrCol) - aCols.push_back(itrCol->first); + if (nLow <= itrCol->first && itrCol->first <= nHigh) + aCols.push_back(itrCol->first); // hash map is not ordered, so we need to explicitly sort it. ::std::sort(aCols.begin(), aCols.end()); @@ -319,6 +388,54 @@ void ScExternalRefCache::Table::getAllNumberFormats(vector<sal_uInt32>& rNumFmts } } +const ScRangeList& ScExternalRefCache::Table::getCachedRanges() const +{ + return maCachedRanges; +} + +bool ScExternalRefCache::Table::isRangeCached(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const +{ + return maCachedRanges.In(ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0)); +} + +void ScExternalRefCache::Table::setCachedCell(SCCOL nCol, SCROW nRow) +{ + setCachedCellRange(nCol, nRow, nCol, nRow); +} + +void ScExternalRefCache::Table::setCachedCellRange(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) +{ + ScRange aRange(nCol1, nRow1, 0, nCol2, nRow2, 0); + if (!maCachedRanges.Count()) + maCachedRanges.Append(aRange); + else + maCachedRanges.Join(aRange); + + String aStr; + maCachedRanges.Format(aStr, SCA_VALID); +} + +void ScExternalRefCache::Table::setWholeTableCached() +{ + setCachedCellRange(0, 0, MAXCOL, MAXROW); +} + +bool ScExternalRefCache::Table::isInCachedRanges(SCCOL nCol, SCROW nRow) const +{ + return maCachedRanges.In(ScRange(nCol, nRow, 0, nCol, nRow, 0)); +} + +ScExternalRefCache::TokenRef ScExternalRefCache::Table::getEmptyOrNullToken( + SCCOL nCol, SCROW nRow) const +{ + if (isInCachedRanges(nCol, nRow)) + { + TokenRef p(new ScEmptyCellToken(false, false)); + return p; + } + return TokenRef(); +} + // ---------------------------------------------------------------------------- ScExternalRefCache::TableName::TableName(const String& rUpper, const String& rReal) : @@ -383,8 +500,7 @@ const String* ScExternalRefCache::getRealRangeName(sal_uInt16 nFileId, const Str } ScExternalRefCache::TokenRef ScExternalRefCache::getCellData( - sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow, - bool bEmptyCellOnNull, bool bWriteEmpty, sal_uInt32* pnFmtIndex) + sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex) { DocDataType::const_iterator itrDoc = maDocs.find(nFileId); if (itrDoc == maDocs.end()) @@ -409,18 +525,11 @@ ScExternalRefCache::TokenRef ScExternalRefCache::getCellData( return TokenRef(); } - TokenRef pToken = pTableData->getCell(nCol, nRow, pnFmtIndex); - if (!pToken && bEmptyCellOnNull) - { - pToken.reset(new ScEmptyCellToken(false, false)); - if (bWriteEmpty) - pTableData->setCell(nCol, nRow, pToken); - } - return pToken; + return pTableData->getCell(nCol, nRow, pnFmtIndex); } ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData( - sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, bool bEmptyCellOnNull, bool bWriteEmpty) + sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange) { DocDataType::iterator itrDoc = maDocs.find(nFileId); if (itrDoc == maDocs.end()) @@ -450,13 +559,14 @@ ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData( return TokenArrayRef(); ScRange aCacheRange( nCol1, nRow1, static_cast<SCTAB>(nTabFirstId), nCol2, nRow2, static_cast<SCTAB>(nTabLastId)); + RangeArrayMap::const_iterator itrRange = rDoc.maRangeArrays.find( aCacheRange); if (itrRange != rDoc.maRangeArrays.end()) - { + // Cache hit! return itrRange->second; - } - TokenArrayRef pArray(new ScTokenArray); + ::boost::scoped_ptr<ScRange> pNewRange; + TokenArrayRef pArray; bool bFirstTab = true; for (size_t nTab = nTabFirstId; nTab <= nTabLastId; ++nTab) { @@ -464,27 +574,72 @@ ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData( if (!pTab.get()) return TokenArrayRef(); + SCCOL nDataCol1 = nCol1, nDataCol2 = nCol2; + SCROW nDataRow1 = nRow1, nDataRow2 = nRow2; + + if (!pTab->isRangeCached(nDataCol1, nDataRow1, nDataCol2, nDataRow2)) + { + // specified range is not entirely within cached ranges. + return TokenArrayRef(); + } + ScMatrixRef xMat = new ScMatrix( - static_cast<SCSIZE>(nCol2-nCol1+1), static_cast<SCSIZE>(nRow2-nRow1+1)); + static_cast<SCSIZE>(nDataCol2-nDataCol1+1), static_cast<SCSIZE>(nDataRow2-nDataRow1+1)); - for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow) +#if 0 + // TODO: Switch to this code block once we have support for sparsely-filled + // matrices in ScMatrix. + + // Only fill non-empty cells, for better performance. + vector<SCROW> aRows; + pTab->getAllRows(aRows, nDataRow1, nDataRow2); + for (vector<SCROW>::const_iterator itr = aRows.begin(), itrEnd = aRows.end(); itr != itrEnd; ++itr) { - for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) + SCROW nRow = *itr; + vector<SCCOL> aCols; + pTab->getAllCols(nRow, aCols, nDataCol1, nDataCol2); + for (vector<SCCOL>::const_iterator itrCol = aCols.begin(), itrColEnd = aCols.end(); itrCol != itrColEnd; ++itrCol) { + SCCOL nCol = *itrCol; TokenRef pToken = pTab->getCell(nCol, nRow); if (!pToken) + // This should never happen! + return TokenArrayRef(); + + SCSIZE nC = nCol - nDataCol1, nR = nRow - nDataRow1; + switch (pToken->GetType()) { - if (bEmptyCellOnNull) - { - pToken.reset(new ScEmptyCellToken(false, false)); - if (bWriteEmpty) - pTab->setCell(nCol, nRow, pToken); - } - else - return TokenArrayRef(); + case svDouble: + xMat->PutDouble(pToken->GetDouble(), nC, nR); + break; + case svString: + xMat->PutString(pToken->GetString(), nC, nR); + break; + default: + ; } + } + } +#else + vector<SCROW> aRows; + pTab->getAllRows(aRows, nDataRow1, nDataRow2); + if (aRows.empty()) + // Cache is empty. + return TokenArrayRef(); + else + // Trim the column below the last non-empty row. + nDataRow2 = aRows.back(); + // Empty all matrix elements first, and fill only non-empty elements. + for (SCROW nRow = nDataRow1; nRow <= nDataRow2; ++nRow) + { + for (SCCOL nCol = nDataCol1; nCol <= nDataCol2; ++nCol) + { + TokenRef pToken = pTab->getCell(nCol, nRow); SCSIZE nC = nCol - nCol1, nR = nRow - nRow1; + if (!pToken) + return TokenArrayRef(); + switch (pToken->GetType()) { case svDouble: @@ -498,17 +653,27 @@ ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData( } } } +#endif if (!bFirstTab) pArray->AddOpCode(ocSep); ScMatrix* pMat2 = xMat; ScMatrixToken aToken(pMat2); + if (!pArray) + pArray.reset(new ScTokenArray); pArray->AddToken(aToken); bFirstTab = false; + + if (!pNewRange) + pNewRange.reset(new ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0)); + else + pNewRange->ExtendTo(ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0)); } - rDoc.maRangeArrays.insert( RangeArrayMap::value_type( aCacheRange, pArray)); + + if (pNewRange) + rDoc.maRangeArrays.insert( RangeArrayMap::value_type(*pNewRange, pArray)); return pArray; } @@ -539,7 +704,7 @@ void ScExternalRefCache::setRangeNameTokens(sal_uInt16 nFileId, const String& rN pDoc->maRealRangeNameMap.insert(NamePairMap::value_type(aUpperName, rName)); } -void ScExternalRefCache::setCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol, +void ScExternalRefCache::setCellData(sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex) { if (!isDocInitialized(nFileId)) @@ -564,6 +729,7 @@ void ScExternalRefCache::setCellData(sal_uInt16 nFileId, const String& rTabName, pTableData.reset(new Table); pTableData->setCell(nCol, nRow, pToken, nFmtIndex); + pTableData->setCachedCell(nCol, nRow); } void ScExternalRefCache::setCellRangeData(sal_uInt16 nFileId, const ScRange& rRange, const vector<SingleRangeData>& rData, @@ -609,20 +775,27 @@ void ScExternalRefCache::setCellRangeData(sal_uInt16 nFileId, const ScRange& rRa SCSIZE nC = nCol - nCol1, nR = nRow - nRow1; TokenRef pToken; const ScMatrixRef& pMat = itrData->mpRangeData; + if (pMat->IsEmpty(nC, nR)) + // Don't cache empty cells. + continue; + if (pMat->IsValue(nC, nR)) pToken.reset(new formula::FormulaDoubleToken(pMat->GetDouble(nC, nR))); else if (pMat->IsString(nC, nR)) pToken.reset(new formula::FormulaStringToken(pMat->GetString(nC, nR))); - else - pToken.reset(new ScEmptyCellToken(false, false)); - pTabData->setCell(nCol, nRow, pToken); + if (pToken) + // Don't mark this cell 'cached' here, for better performance. + pTabData->setCell(nCol, nRow, pToken, 0, false); } } + // Mark the whole range 'cached'. + pTabData->setCachedCellRange(nCol1, nRow1, nCol2, nRow2); } size_t nTabLastId = nTabFirstId + rRange.aEnd.Tab() - rRange.aStart.Tab(); ScRange aCacheRange( nCol1, nRow1, static_cast<SCTAB>(nTabFirstId), nCol2, nRow2, static_cast<SCTAB>(nTabLastId)); + rDoc.maRangeArrays.insert( RangeArrayMap::value_type( aCacheRange, pArray)); } @@ -1019,6 +1192,9 @@ ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nF { // specified table found. if( pnIndex ) *pnIndex = nIndex; + if (bCreateNew && !rDoc.maTables[nIndex]) + rDoc.maTables[nIndex].reset(new Table); + return rDoc.maTables[nIndex]; } @@ -1186,11 +1362,11 @@ static FormulaToken* lcl_convertToToken(ScBaseCell* pCell) return NULL; } -static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, const ScRange& rRange, +static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, ScRange& rRange, vector<ScExternalRefCache::SingleRangeData>& rCacheData) { - const ScAddress& s = rRange.aStart; - const ScAddress& e = rRange.aEnd; + ScAddress& s = rRange.aStart; + ScAddress& e = rRange.aEnd; SCTAB nTab1 = s.Tab(), nTab2 = e.Tab(); SCCOL nCol1 = s.Col(), nCol2 = e.Col(); @@ -1204,19 +1380,35 @@ static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, const ScRange& // range to it. return NULL; + ::boost::scoped_ptr<ScRange> pUsedRange; + auto_ptr<ScTokenArray> pArray(new ScTokenArray); bool bFirstTab = true; vector<ScExternalRefCache::SingleRangeData>::iterator itrCache = rCacheData.begin(), itrCacheEnd = rCacheData.end(); + for (SCTAB nTab = nTab1; nTab <= nTab2 && itrCache != itrCacheEnd; ++nTab, ++itrCache) { + // Only loop within the data area. + SCCOL nDataCol1 = nCol1, nDataCol2 = nCol2; + SCROW nDataRow1 = nRow1, nDataRow2 = nRow2; + if (!pSrcDoc->ShrinkToDataArea(nTab, nDataCol1, nDataRow1, nDataCol2, nDataRow2)) + // no data within specified range. + continue; + + if (pUsedRange.get()) + // Make sure the used area only grows, not shrinks. + pUsedRange->ExtendTo(ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0)); + else + pUsedRange.reset(new ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0)); + ScMatrixRef xMat = new ScMatrix( - static_cast<SCSIZE>(nCol2-nCol1+1), - static_cast<SCSIZE>(nRow2-nRow1+1)); + static_cast<SCSIZE>(nDataCol2-nDataCol1+1), + static_cast<SCSIZE>(nDataRow2-nDataRow1+1)); - for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) + for (SCCOL nCol = nDataCol1; nCol <= nDataCol2; ++nCol) { - for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow) + for (SCROW nRow = nDataRow1; nRow <= nDataRow2; ++nRow) { SCSIZE nC = nCol - nCol1, nR = nRow - nRow1; ScBaseCell* pCell; @@ -1283,12 +1475,38 @@ static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, const ScRange& bFirstTab = false; } + + if (!pUsedRange.get()) + return NULL; + + s.SetCol(pUsedRange->aStart.Col()); + s.SetRow(pUsedRange->aStart.Row()); + e.SetCol(pUsedRange->aEnd.Col()); + e.SetRow(pUsedRange->aEnd.Row()); + + return pArray.release(); +} + +static ScTokenArray* lcl_fillEmptyMatrix(const ScRange& rRange) +{ + SCSIZE nC = static_cast<SCSIZE>(rRange.aEnd.Col()-rRange.aStart.Col()+1); + SCSIZE nR = static_cast<SCSIZE>(rRange.aEnd.Row()-rRange.aStart.Row()+1); + ScMatrixRef xMat = new ScMatrix(nC, nR); + for (SCSIZE i = 0; i < nC; ++i) + for (SCSIZE j = 0; j < nR; ++j) + xMat->PutEmpty(i, j); + + ScMatrix* pMat2 = xMat; + ScMatrixToken aToken(pMat2); + auto_ptr<ScTokenArray> pArray(new ScTokenArray); + pArray->AddToken(aToken); return pArray.release(); } ScExternalRefManager::ScExternalRefManager(ScDocument* pDoc) : mpDoc(pDoc), - bInReferenceMarking(false) + mbInReferenceMarking(false), + mbUserInteractionEnabled(true) { maSrcDocTimer.SetTimeoutHdl( LINK(this, ScExternalRefManager, TimeOutHdl) ); maSrcDocTimer.SetTimeout(SRCDOC_SCAN_INTERVAL); @@ -1316,236 +1534,28 @@ ScExternalRefCache::TableTypeRef ScExternalRefManager::getCacheTable(sal_uInt16 // ============================================================================ -ScExternalRefManager::RefCells::TabItem::TabItem(SCTAB nIndex) : - mnIndex(nIndex) -{ -} - -ScExternalRefManager::RefCells::TabItem::TabItem(const TabItem& r) : - mnIndex(r.mnIndex), - maCols(r.maCols) -{ -} - -ScExternalRefManager::RefCells::RefCells() -{ -} - -ScExternalRefManager::RefCells::~RefCells() -{ -} - -list<ScExternalRefManager::RefCells::TabItemRef>::iterator ScExternalRefManager::RefCells::getTabPos(SCTAB nTab) -{ - list<TabItemRef>::iterator itr = maTables.begin(), itrEnd = maTables.end(); - for (; itr != itrEnd; ++itr) - if ((*itr)->mnIndex >= nTab) - return itr; - // Not found. return the end position. - return itrEnd; -} - -void ScExternalRefManager::RefCells::insertCell(const ScAddress& rAddr) -{ - SCTAB nTab = rAddr.Tab(); - SCCOL nCol = rAddr.Col(); - SCROW nRow = rAddr.Row(); - - // Search by table index. - list<TabItemRef>::iterator itrTab = getTabPos(nTab); - TabItemRef xTabRef; - if (itrTab == maTables.end()) - { - // All previous tables come before the specificed table. - xTabRef.reset(new TabItem(nTab)); - maTables.push_back(xTabRef); - } - else if ((*itrTab)->mnIndex > nTab) - { - // Insert at the current iterator position. - xTabRef.reset(new TabItem(nTab)); - maTables.insert(itrTab, xTabRef); - } - else if ((*itrTab)->mnIndex == nTab) - { - // The table found. - xTabRef = *itrTab; - } - ColSet& rCols = xTabRef->maCols; - - // Then by column index. - ColSet::iterator itrCol = rCols.find(nCol); - if (itrCol == rCols.end()) - { - RowSet aRows; - pair<ColSet::iterator, bool> r = rCols.insert(ColSet::value_type(nCol, aRows)); - if (!r.second) - // column insertion failed. - return; - itrCol = r.first; - } - RowSet& rRows = itrCol->second; - - // Finally, insert the row index. - rRows.insert(nRow); -} - -void ScExternalRefManager::RefCells::removeCell(const ScAddress& rAddr) -{ - SCTAB nTab = rAddr.Tab(); - SCCOL nCol = rAddr.Col(); - SCROW nRow = rAddr.Row(); - - // Search by table index. - list<TabItemRef>::iterator itrTab = getTabPos(nTab); - if (itrTab == maTables.end() || (*itrTab)->mnIndex != nTab) - // No such table. - return; - - ColSet& rCols = (*itrTab)->maCols; - - // Then by column index. - ColSet::iterator itrCol = rCols.find(nCol); - if (itrCol == rCols.end()) - // No such column - return; - - RowSet& rRows = itrCol->second; - rRows.erase(nRow); -} - -void ScExternalRefManager::RefCells::moveTable(SCTAB nOldTab, SCTAB nNewTab, bool bCopy) -{ - if (nOldTab == nNewTab) - // Nothing to do here. - return; - - list<TabItemRef>::iterator itrOld = getTabPos(nOldTab); - if (itrOld == maTables.end() || (*itrOld)->mnIndex != nOldTab) - // No table to move or copy. - return; - - list<TabItemRef>::iterator itrNew = getTabPos(nNewTab); - if (bCopy) - { - // Simply make a duplicate of the original table, insert it at the - // new tab position, and increment the table index for all tables - // that come after that inserted table. - - TabItemRef xNewTab(new TabItem(*(*itrOld))); - xNewTab->mnIndex = nNewTab; - maTables.insert(itrNew, xNewTab); - list<TabItemRef>::iterator itr = itrNew, itrEnd = maTables.end(); - if (itr != itrEnd) // #i99807# check that itr is not at end already - for (++itr; itr != itrEnd; ++itr) - (*itr)->mnIndex += 1; - } - else - { - if (itrOld == itrNew) - { - // No need to move the table. Just update the table index. - (*itrOld)->mnIndex = nNewTab; - return; - } - - if (nOldTab < nNewTab) - { - // Iterate from the old tab position to the new tab position (not - // inclusive of the old tab itself), and decrement their tab - // index by one. - list<TabItemRef>::iterator itr = itrOld; - for (++itr; itr != itrNew; ++itr) - (*itr)->mnIndex -= 1; - - // Insert a duplicate of the original table. This does not - // invalidate the iterators. - (*itrOld)->mnIndex = nNewTab - 1; - if (itrNew == maTables.end()) - maTables.push_back(*itrOld); - else - maTables.insert(itrNew, *itrOld); - - // Remove the original table. - maTables.erase(itrOld); - } - else - { - // nNewTab < nOldTab - - // Iterate from the new tab position to the one before the old tab - // position, and increment their tab index by one. - list<TabItemRef>::iterator itr = itrNew; - for (++itr; itr != itrOld; ++itr) - (*itr)->mnIndex += 1; - - (*itrOld)->mnIndex = nNewTab; - maTables.insert(itrNew, *itrOld); - - // Remove the original table. - maTables.erase(itrOld); - } - } -} - -void ScExternalRefManager::RefCells::insertTable(SCTAB nPos) -{ - TabItemRef xNewTab(new TabItem(nPos)); - list<TabItemRef>::iterator itr = getTabPos(nPos); - if (itr == maTables.end()) - maTables.push_back(xNewTab); - else - maTables.insert(itr, xNewTab); -} - -void ScExternalRefManager::RefCells::removeTable(SCTAB nPos) +ScExternalRefManager::LinkListener::LinkListener() { - list<TabItemRef>::iterator itr = getTabPos(nPos); - if (itr == maTables.end()) - // nothing to remove. - return; - - maTables.erase(itr); } -void ScExternalRefManager::RefCells::refreshAllCells(ScExternalRefManager& rRefMgr) +ScExternalRefManager::LinkListener::~LinkListener() { - // Get ALL the cell positions for re-compilation. - for (list<TabItemRef>::iterator itrTab = maTables.begin(), itrTabEnd = maTables.end(); - itrTab != itrTabEnd; ++itrTab) - { - SCTAB nTab = (*itrTab)->mnIndex; - ColSet& rCols = (*itrTab)->maCols; - for (ColSet::iterator itrCol = rCols.begin(), itrColEnd = rCols.end(); - itrCol != itrColEnd; ++itrCol) - { - SCCOL nCol = itrCol->first; - RowSet& rRows = itrCol->second; - RowSet aNewRows; - for (RowSet::iterator itrRow = rRows.begin(), itrRowEnd = rRows.end(); - itrRow != itrRowEnd; ++itrRow) - { - SCROW nRow = *itrRow; - ScAddress aCell(nCol, nRow, nTab); - if (rRefMgr.compileTokensByCell(aCell)) - // This cell still contains an external refernce. - aNewRows.insert(nRow); - } - // Update the rows so that cells with no external references are - // no longer tracked. - rRows.swap(aNewRows); - } - } } // ---------------------------------------------------------------------------- -ScExternalRefManager::LinkListener::LinkListener() +ScExternalRefManager::ApiGuard::ApiGuard(ScDocument* pDoc) : + mpMgr(pDoc->GetExternalRefManager()), + mbOldInteractionEnabled(mpMgr->mbUserInteractionEnabled) { + // We don't want user interaction handled in the API. + mpMgr->mbUserInteractionEnabled = false; } -ScExternalRefManager::LinkListener::~LinkListener() +ScExternalRefManager::ApiGuard::~ApiGuard() { + // Restore old value. + mpMgr->mbUserInteractionEnabled = mbOldInteractionEnabled; } // ---------------------------------------------------------------------------- @@ -1595,9 +1605,22 @@ bool ScExternalRefManager::markUsedByLinkListeners() return bAllMarked; } -bool ScExternalRefManager::setCacheDocReferenced( sal_uInt16 nFileId ) +bool ScExternalRefManager::markUsedExternalRefCells() { - return maRefCache.setCacheDocReferenced( nFileId); + RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); + for (; itr != itrEnd; ++itr) + { + RefCellSet::iterator itrCell = itr->second.begin(), itrCellEnd = itr->second.end(); + for (; itrCell != itrCellEnd; ++itrCell) + { + ScFormulaCell* pCell = *itrCell; + bool bUsed = pCell->MarkUsedExternalReferences(); + if (bUsed) + // Return true when at least one cell references external docs. + return true; + } + } + return false; } bool ScExternalRefManager::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets ) @@ -1617,7 +1640,7 @@ void ScExternalRefManager::setCacheTableReferencedPermanently( sal_uInt16 nFileI void ScExternalRefManager::setAllCacheTableReferencedStati( bool bReferenced ) { - bInReferenceMarking = !bReferenced; + mbInReferenceMarking = !bReferenced; maRefCache.setAllCacheTableReferencedStati( bReferenced ); } @@ -1642,20 +1665,13 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken( if (pFmt) pFmt->mbIsSet = false; - bool bLoading = mpDoc->IsImportingXML(); - // Check if the given table name and the cell position is cached. - // #i101304# When loading a file, the saved cache (hidden sheet) - // is assumed to contain all data for the loaded formulas. - // No cache entries are created from empty cells in the saved sheet, - // so they have to be created here (bWriteEmpty parameter). - // Otherwise, later interpretation of the loaded formulas would - // load the source document even if the user didn't want to update. sal_uInt32 nFmtIndex = 0; ScExternalRefCache::TokenRef pToken = maRefCache.getCellData( - nFileId, rTabName, rCell.Col(), rCell.Row(), bLoading, bLoading, &nFmtIndex); + nFileId, rTabName, rCell.Col(), rCell.Row(), &nFmtIndex); if (pToken) { + // Cache hit ! if (pFmt) { short nFmtType = mpDoc->GetFormatTable()->GetType(nFmtIndex); @@ -1673,11 +1689,8 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken( ScDocument* pSrcDoc = getSrcDocument(nFileId); if (!pSrcDoc) { - // Source document is not reachable. Try to get data from the cache - // once again, but this time treat a non-cached cell as an empty cell - // as long as the table itself is cached. - pToken = maRefCache.getCellData( - nFileId, rTabName, rCell.Col(), rCell.Row(), true, false, &nFmtIndex); + // Source document not reachable. Throw a reference error. + pToken.reset(new FormulaErrorToken(errNoRef)); return pToken; } @@ -1686,12 +1699,30 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken( if (!pSrcDoc->GetTable(rTabName, nTab)) { // specified table name doesn't exist in the source document. - return ScExternalRefCache::TokenRef(); + pToken.reset(new FormulaErrorToken(errNoRef)); + return pToken; } if (pTab) *pTab = nTab; + SCCOL nDataCol1 = 0, nDataCol2 = MAXCOL; + SCROW nDataRow1 = 0, nDataRow2 = MAXROW; + pSrcDoc->ShrinkToDataArea(nTab, nDataCol1, nDataRow1, nDataCol2, nDataRow2); + if (rCell.Col() < nDataCol1 || nDataCol2 < rCell.Col() || rCell.Row() < nDataRow1 || nDataRow2 < rCell.Row()) + { + // requested cell is outside the data area. Don't even bother caching + // this data, but add it to the cached range to prevent accessing the + // source document time and time again. + ScExternalRefCache::TableTypeRef pCacheTab = + maRefCache.getCacheTable(nFileId, rTabName, true, NULL); + if (pCacheTab) + pCacheTab->setCachedCell(rCell.Col(), rCell.Row()); + + pToken.reset(new ScEmptyCellToken(false, false)); + return pToken; + } + pSrcDoc->GetCell(rCell.Col(), rCell.Row(), nTab, pCell); ScExternalRefCache::TokenRef pTok(lcl_convertToToken(pCell)); @@ -1714,39 +1745,45 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken( pTok.reset( new FormulaErrorToken( errNoValue)); } - // Now, insert the token into cache table. - maRefCache.setCellData(nFileId, rTabName, rCell.Row(), rCell.Col(), pTok, nFmtIndex); + // Now, insert the token into cache table but don't cache empty cells. + if (pTok->GetType() != formula::svEmptyCell) + maRefCache.setCellData(nFileId, rTabName, rCell.Col(), rCell.Row(), pTok, nFmtIndex); + return pTok; } -ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, const ScAddress* pCurPos) +ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens( + sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, const ScAddress* pCurPos) { if (pCurPos) insertRefCell(nFileId, *pCurPos); maybeLinkExternalFile(nFileId); - bool bLoading = mpDoc->IsImportingXML(); - // Check if the given table name and the cell position is cached. - // #i101304# When loading, put empty cells into cache, see getSingleRefToken. - ScExternalRefCache::TokenArrayRef p = maRefCache.getCellRangeData(nFileId, rTabName, rRange, bLoading, bLoading); - if (p.get()) - return p; + ScExternalRefCache::TokenArrayRef pArray = + maRefCache.getCellRangeData(nFileId, rTabName, rRange); + if (pArray) + // Cache hit ! + return pArray; ScDocument* pSrcDoc = getSrcDocument(nFileId); if (!pSrcDoc) { - // Source document is not reachable. Try to get data from the cache - // once again, but this time treat non-cached cells as empty cells as - // long as the table itself is cached. - return maRefCache.getCellRangeData(nFileId, rTabName, rRange, true, false); + // Source document is not reachable. Throw a reference error. + pArray.reset(new ScTokenArray); + pArray->AddToken(FormulaErrorToken(errNoRef)); + return pArray; } SCTAB nTab1; if (!pSrcDoc->GetTable(rTabName, nTab1)) + { // specified table name doesn't exist in the source document. - return ScExternalRefCache::TokenArrayRef(); + pArray.reset(new ScTokenArray); + pArray->AddToken(FormulaErrorToken(errNoRef)); + return pArray; + } ScRange aRange(rRange); SCTAB nTabSpan = aRange.aEnd.Tab() - aRange.aStart.Tab(); @@ -1770,12 +1807,24 @@ ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(sal_u aRange.aStart.SetTab(nTab1); aRange.aEnd.SetTab(nTab1 + nTabSpan); - ScExternalRefCache::TokenArrayRef pArray; pArray.reset(lcl_convertToTokenArray(pSrcDoc, aRange, aCacheData)); if (pArray) // Cache these values. - maRefCache.setCellRangeData(nFileId, rRange, aCacheData, pArray); + maRefCache.setCellRangeData(nFileId, aRange, aCacheData, pArray); + else + { + // Array is empty. Fill it with an empty matrix of the required size. + pArray.reset(lcl_fillEmptyMatrix(rRange)); + + // Make sure to set this range 'cached', to prevent unnecessarily + // accessing the src document time and time again. + ScExternalRefCache::TableTypeRef pCacheTab = + maRefCache.getCacheTable(nFileId, rTabName, true, NULL); + if (pCacheTab) + pCacheTab->setCachedCellRange( + rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row()); + } return pArray; } @@ -1858,8 +1907,8 @@ void ScExternalRefManager::refreshAllRefCells(sal_uInt16 nFileId) if (itrFile == maRefCells.end()) return; - RefCells& rRefCells = itrFile->second; - rRefCells.refreshAllCells(*this); + RefCellSet& rRefCells = itrFile->second; + for_each(rRefCells.begin(), rRefCells.end(), UpdateFormulaCell()); ScViewData* pViewData = ScDocShell::GetViewData(); if (!pViewData) @@ -1880,7 +1929,7 @@ void ScExternalRefManager::insertRefCell(sal_uInt16 nFileId, const ScAddress& rC RefCellMap::iterator itr = maRefCells.find(nFileId); if (itr == maRefCells.end()) { - RefCells aRefCells; + RefCellSet aRefCells; pair<RefCellMap::iterator, bool> r = maRefCells.insert( RefCellMap::value_type(nFileId, aRefCells)); if (!r.second) @@ -1889,7 +1938,10 @@ void ScExternalRefManager::insertRefCell(sal_uInt16 nFileId, const ScAddress& rC itr = r.first; } - itr->second.insertCell(rCell); + + ScBaseCell* pCell = mpDoc->GetCell(rCell); + if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA) + itr->second.insert(static_cast<ScFormulaCell*>(pCell)); } ScDocument* ScExternalRefManager::getSrcDocument(sal_uInt16 nFileId) @@ -1902,6 +1954,12 @@ ScDocument* ScExternalRefManager::getSrcDocument(sal_uInt16 nFileId) if (itr != itrEnd) { + // document already loaded. + + // TODO: Find out a way to access a document that's already open in + // memory and re-use that instance, instead of loading it from the + // disk again. + SfxObjectShell* p = itr->second.maShell; itr->second.maLastAccess = Time(); return static_cast<ScDocShell*>(p)->GetDocument(); @@ -1996,7 +2054,8 @@ SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, Stri if (pMedium->GetError() != ERRCODE_NONE) return NULL; - pMedium->UseInteractionHandler(false); + // To load encrypted documents with password, user interaction needs to be enabled. + pMedium->UseInteractionHandler(mbUserInteractionEnabled); ScDocShell* pNewShell = new ScDocShell(SFX_CREATE_MODE_INTERNAL); SfxObjectShellRef aRef = pNewShell; @@ -2005,6 +2064,10 @@ SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, Stri ScExtDocOptions* pExtOpt = mpDoc->GetExtDocOptions(); sal_uInt32 nLinkCount = pExtOpt ? pExtOpt->GetDocSettings().mnLinkCnt : 0; ScDocument* pSrcDoc = pNewShell->GetDocument(); + pSrcDoc->EnableExecuteLink(false); // to prevent circular access of external references. + pSrcDoc->EnableUndo(false); + pSrcDoc->EnableAdjustHeight(false); + ScExtDocOptions* pExtOptNew = pSrcDoc->GetExtDocOptions(); if (!pExtOptNew) { @@ -2082,35 +2145,6 @@ void ScExternalRefManager::maybeCreateRealFileName(sal_uInt16 nFileId) maSrcFiles[nFileId].maybeCreateRealFileName(getOwnDocumentName()); } -bool ScExternalRefManager::compileTokensByCell(const ScAddress& rCell) -{ - ScBaseCell* pCell; - mpDoc->GetCell(rCell.Col(), rCell.Row(), rCell.Tab(), pCell); - - if (!pCell || pCell->GetCellType() != CELLTYPE_FORMULA) - return false; - - ScFormulaCell* pFC = static_cast<ScFormulaCell*>(pCell); - - // Check to make sure the cell really contains ocExternalRef. - // External names, external cell and range references all have a - // ocExternalRef token. - const ScTokenArray* pCode = pFC->GetCode(); - if (!pCode->HasOpCode( ocExternalRef)) - return false; - - ScTokenArray* pArray = pFC->GetCode(); - if (pArray) - // Clear the error code, or a cell with error won't get re-compiled. - pArray->SetCodeError(0); - - pFC->SetCompile(true); - pFC->CompileTokenArray(); - pFC->SetDirty(); - - return true; -} - const String& ScExternalRefManager::getOwnDocumentName() const { SfxObjectShell* pShell = mpDoc->GetDocumentShell(); @@ -2222,6 +2256,18 @@ void ScExternalRefManager::refreshNames(sal_uInt16 nFileId) void ScExternalRefManager::breakLink(sal_uInt16 nFileId) { + // Turn all formula cells referencing this external document into static + // cells. + RefCellMap::iterator itrRefs = maRefCells.find(nFileId); + if (itrRefs != maRefCells.end()) + { + // Make a copy because removing the formula cells below will modify + // the original container. + RefCellSet aSet = itrRefs->second; + for_each(aSet.begin(), aSet.end(), ConvertFormulaToStatic(mpDoc)); + maRefCells.erase(nFileId); + } + lcl_removeByFileId(nFileId, maDocShells); if (maDocShells.empty()) @@ -2293,32 +2339,9 @@ void ScExternalRefManager::resetSrcFileData(const String& rBaseFileUrl) } } -void ScExternalRefManager::updateRefCell(const ScAddress& rOldPos, const ScAddress& rNewPos, bool bCopy) -{ - for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr) - { - if (!bCopy) - itr->second.removeCell(rOldPos); - itr->second.insertCell(rNewPos); - } -} - -void ScExternalRefManager::updateRefMoveTable(SCTAB nOldTab, SCTAB nNewTab, bool bCopy) -{ - for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr) - itr->second.moveTable(nOldTab, nNewTab, bCopy); -} - -void ScExternalRefManager::updateRefInsertTable(SCTAB nPos) -{ - for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr) - itr->second.insertTable(nPos); -} - -void ScExternalRefManager::updateRefDeleteTable(SCTAB nPos) +void ScExternalRefManager::removeRefCell(ScFormulaCell* pCell) { - for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr) - itr->second.removeTable(nPos); + for_each(maRefCells.begin(), maRefCells.end(), RemoveFormulaCell(pCell)); } void ScExternalRefManager::addLinkListener(sal_uInt16 nFileId, LinkListener* pListener) diff --git a/sc/source/ui/docshell/tablink.cxx b/sc/source/ui/docshell/tablink.cxx index 4d18f9f18c37..697b39052b9f 100644 --- a/sc/source/ui/docshell/tablink.cxx +++ b/sc/source/ui/docshell/tablink.cxx @@ -485,6 +485,11 @@ BOOL ScDocumentLoader::GetFilterName( const String& rFileName, pDocSh = SfxObjectShell::GetNext( *pDocSh, &aScType ); } + INetURLObject aUrl( rFileName ); + INetProtocol eProt = aUrl.GetProtocol(); + if ( eProt == INET_PROT_NOT_VALID ) // invalid URL? + return FALSE; // abort without creating a medium + // Filter-Detection const SfxFilter* pSfxFilter = NULL; diff --git a/sc/source/ui/drawfunc/drformsh.src b/sc/source/ui/drawfunc/drformsh.src index b20ceb9841a5..65e98eea7b2c 100644 --- a/sc/source/ui/drawfunc/drformsh.src +++ b/sc/source/ui/drawfunc/drformsh.src @@ -117,12 +117,14 @@ {\ MenuItem\ {\ + RadioCheck = TRUE ; \ Identifier = SID_ANCHOR_PAGE ; \ HelpId = SID_ANCHOR_PAGE ; \ Text [ en-US ] = "To P~age" ; \ };\ MenuItem\ {\ + RadioCheck = TRUE ; \ Identifier = SID_ANCHOR_CELL ; \ HelpId = SID_ANCHOR_CELL ; \ Text [ en-US ] = "To ~Cell" ; \ diff --git a/sc/source/ui/drawfunc/drtxtob.cxx b/sc/source/ui/drawfunc/drtxtob.cxx index ece7c4ad6c3a..bfbeba2d1302 100644 --- a/sc/source/ui/drawfunc/drtxtob.cxx +++ b/sc/source/ui/drawfunc/drtxtob.cxx @@ -32,6 +32,9 @@ //------------------------------------------------------------------------- +#include <com/sun/star/linguistic2/XThesaurus.hpp> +#include <com/sun/star/lang/Locale.hpp> + #include "scitems.hxx" #include <editeng/adjitem.hxx> @@ -46,6 +49,7 @@ #include <svx/hlnkitem.hxx> #include <editeng/lspcitem.hxx> #include <svx/svdoutl.hxx> +#include <editeng/unolingu.hxx> #include <editeng/outlobj.hxx> #include <editeng/postitem.hxx> #include <editeng/scripttypeitem.hxx> @@ -71,6 +75,7 @@ #include "sc.hrc" #include "globstr.hrc" +#include "scmod.hxx" #include "drtxtob.hxx" #include "fudraw.hxx" #include "viewdata.hxx" @@ -83,6 +88,10 @@ #define ScDrawTextObjectBar #include "scslots.hxx" + +using namespace ::com::sun::star; + + SFX_IMPL_INTERFACE( ScDrawTextObjectBar, SfxShell, ScResId(SCSTR_DRAWTEXTSHELL) ) { SFX_OBJECTBAR_REGISTRATION( SFX_OBJECTBAR_OBJECT|SFX_VISIBILITY_STANDARD|SFX_VISIBILITY_SERVER, @@ -363,6 +372,24 @@ void __EXPORT ScDrawTextObjectBar::Execute( SfxRequest &rReq ) ExecuteGlobal( rReq ); break; #endif + + case SID_THES: + { + String aReplaceText; + SFX_REQUEST_ARG( rReq, pItem2, SfxStringItem, SID_THES, sal_False ); + if (pItem2) + aReplaceText = pItem2->GetValue(); + if (aReplaceText.Len() > 0) + ReplaceTextWithSynonym( pOutView->GetEditView(), aReplaceText ); + } + break; + + case SID_THESAURUS: + { + pOutView->StartThesaurus(); + } + break; + } } @@ -454,6 +481,25 @@ void __EXPORT ScDrawTextObjectBar::GetState( SfxItemSet& rSet ) rSet.Put( SfxBoolItem( SID_ENABLE_HYPHENATION, bValue ) ); } } + + if ( rSet.GetItemState( SID_THES ) != SFX_ITEM_UNKNOWN || + rSet.GetItemState( SID_THESAURUS ) != SFX_ITEM_UNKNOWN ) + { + SdrView * pView = pViewData->GetScDrawView(); + EditView & rEditView = pView->GetTextEditOutlinerView()->GetEditView(); + + String aStatusVal; + LanguageType nLang = LANGUAGE_NONE; + bool bIsLookUpWord = GetStatusValueForThesaurusFromContext( aStatusVal, nLang, rEditView ); + rSet.Put( SfxStringItem( SID_THES, aStatusVal ) ); + + // disable thesaurus main menu and context menu entry if there is nothing to look up + BOOL bCanDoThesaurus = ScModule::HasThesaurusLanguage( nLang ); + if (!bIsLookUpWord || !bCanDoThesaurus) + rSet.DisableItem( SID_THES ); + if (!bCanDoThesaurus) + rSet.DisableItem( SID_THESAURUS ); + } } IMPL_LINK( ScDrawTextObjectBar, ClipboardChanged, TransferableDataHelper*, pDataHelper ) diff --git a/sc/source/ui/drawfunc/objdraw.src b/sc/source/ui/drawfunc/objdraw.src index 0cd8fdd54e4b..82649044b38c 100644 --- a/sc/source/ui/drawfunc/objdraw.src +++ b/sc/source/ui/drawfunc/objdraw.src @@ -339,6 +339,7 @@ {\ MenuItem\ {\ + RadioCheck = TRUE ; \ Identifier = SID_ANCHOR_PAGE ; \ HelpId = SID_ANCHOR_PAGE ; \ Text [ en-US ] = "To P~age" ; \ @@ -346,6 +347,7 @@ };\ MenuItem\ {\ + RadioCheck = TRUE ; \ Identifier = SID_ANCHOR_CELL ; \ HelpId = SID_ANCHOR_CELL ; \ Text [ en-US ] = "To ~Cell" ; \ diff --git a/sc/source/ui/inc/filtdlg.hxx b/sc/source/ui/inc/filtdlg.hxx index 068a48b8d689..31e0e3a5d4b1 100644 --- a/sc/source/ui/inc/filtdlg.hxx +++ b/sc/source/ui/inc/filtdlg.hxx @@ -164,6 +164,7 @@ private: ListBox* aFieldLbArr[4]; ListBox* aCondLbArr[4]; ListBox* aConnLbArr[4]; + bool mbHasDates[MAXQUERY]; BOOL bRefreshExceptQuery[MAXQUERY]; USHORT nFieldCount; BOOL bRefInputMode; diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx index 149498a8314d..4d6ef782aed6 100644 --- a/sc/source/ui/inc/gridwin.hxx +++ b/sc/source/ui/inc/gridwin.hxx @@ -215,7 +215,7 @@ private: BOOL IsAutoFilterActive( SCCOL nCol, SCROW nRow, SCTAB nTab ); void ExecFilter( ULONG nSel, SCCOL nCol, SCROW nRow, - const String& aValue ); + const String& aValue, bool bCheckForDates ); void FilterSelect( ULONG nSel ); void ExecDataSelect( SCCOL nCol, SCROW nRow, const String& rStr ); diff --git a/sc/source/ui/inc/inputhdl.hxx b/sc/source/ui/inc/inputhdl.hxx index bcc5ba0dd396..61974cf7464d 100644 --- a/sc/source/ui/inc/inputhdl.hxx +++ b/sc/source/ui/inc/inputhdl.hxx @@ -68,7 +68,9 @@ private: TypedScStrCollection* pColumnData; TypedScStrCollection* pFormulaData; TypedScStrCollection* pFormulaDataPara; + Window* pTipVisibleParent; ULONG nTipVisible; + Window* pTipVisibleSecParent; ULONG nTipVisibleSec; String aManualTip; String aAutoSearch; @@ -149,6 +151,8 @@ private: BOOL CursorAtClosingPar(); void SkipClosingPar(); DECL_LINK( ModifyHdl, void* ); + DECL_LINK( ShowHideTipVisibleParentListener, VclWindowEvent* ); + DECL_LINK( ShowHideTipVisibleSecParentListener, VclWindowEvent* ); #endif public: diff --git a/sc/source/ui/inc/optdlg.hrc b/sc/source/ui/inc/optdlg.hrc index 00cfdb2c6d5a..27b8976e3541 100644 --- a/sc/source/ui/inc/optdlg.hrc +++ b/sc/source/ui/inc/optdlg.hrc @@ -70,6 +70,7 @@ #define BTN_MATCH 18 #define BTN_LOOKUP 19 #define BTN_REGEX 20 +#define BTN_GENERAL_PREC 21 // TP_VIEW: #define BTN_VSCROLL 1 diff --git a/sc/source/ui/inc/output.hxx b/sc/source/ui/inc/output.hxx index 8d512898afd3..42844513af92 100644 --- a/sc/source/ui/inc/output.hxx +++ b/sc/source/ui/inc/output.hxx @@ -73,6 +73,15 @@ class ScOutputData { friend class ScDrawStringsVars; private: + struct OutputAreaParam + { + Rectangle maAlignRect; + Rectangle maClipRect; + long mnColWidth; + bool mbLeftClip; + bool mbRightClip; + }; + OutputDevice* pDev; // Device OutputDevice* pRefDevice; // printer if used for preview OutputDevice* pFmtDevice; // reference for text formatting @@ -152,19 +161,19 @@ private: void GetVisibleCell( SCCOL nCol, SCROW nRow, SCTAB nTab, ScBaseCell*& rpCell ); BOOL IsAvailable( SCCOL nX, SCROW nY ); + void GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY, - SCCOL nCellX, SCROW nCellY, long nNeeded, - const ScPatternAttr& rPattern, - USHORT nHorJustify, BOOL bCellIsValue, - BOOL bBreak, BOOL bOverwrite, - Rectangle& rAlignRect, Rectangle& rClipRect, - BOOL& rLeftClip, BOOL& rRightClip ); + SCCOL nCellX, SCROW nCellY, long nNeeded, + const ScPatternAttr& rPattern, + USHORT nHorJustify, bool bCellIsValue, + bool bBreak, bool bOverwrite, + OutputAreaParam& rParam ); void ShrinkEditEngine( EditEngine& rEngine, const Rectangle& rAlignRect, long nLeftM, long nTopM, long nRightM, long nBottomM, BOOL bWidth, USHORT nOrient, long nAttrRotate, BOOL bPixelToLogic, long& rEngineWidth, long& rEngineHeight, long& rNeededPixel, - BOOL& rLeftClip, BOOL& rRightClip ); + bool& rLeftClip, bool& rRightClip ); void SetSyntaxColor( Font* pFont, ScBaseCell* pCell ); void SetEditSyntaxColor( EditEngine& rEngine, ScBaseCell* pCell ); diff --git a/sc/source/ui/inc/teamdlg.hxx b/sc/source/ui/inc/teamdlg.hxx deleted file mode 100644 index 9f44f06c4b12..000000000000 --- a/sc/source/ui/inc/teamdlg.hxx +++ /dev/null @@ -1,53 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#ifndef SC_TEAMDLG_HXX -#define SC_TEAMDLG_HXX - - -#include <vcl/floatwin.hxx> -#include <vcl/fixed.hxx> - - -//======================================================================== - -class ScTeamDlg : public FloatingWindow -{ -public: - ScTeamDlg( Window* pParent ); - ~ScTeamDlg(); - - virtual BOOL Close(); - void Center(); - -private: - FixedBitmap aBmpTeam; -}; - - -#endif - diff --git a/sc/source/ui/inc/tpcalc.hxx b/sc/source/ui/inc/tpcalc.hxx index ea9e53a23ee4..31f2c9458c83 100644 --- a/sc/source/ui/inc/tpcalc.hxx +++ b/sc/source/ui/inc/tpcalc.hxx @@ -76,6 +76,7 @@ private: CheckBox aBtnMatch; CheckBox aBtnRegex; CheckBox aBtnLookUp; + CheckBox aBtnGeneralPrec; FixedText aFtPrec; NumericField aEdPrec; diff --git a/sc/source/ui/miscdlgs/autofmt.cxx b/sc/source/ui/miscdlgs/autofmt.cxx index 940856775c07..6ce65ab914be 100644 --- a/sc/source/ui/miscdlgs/autofmt.cxx +++ b/sc/source/ui/miscdlgs/autofmt.cxx @@ -68,8 +68,6 @@ #define FRAME_OFFSET 4 -BOOL bIsOlk = FALSE; - //CHINA001 //======================================================================== //CHINA001 // AutoFormat-Dialog: @@ -508,8 +506,6 @@ ScAutoFmtPreview::ScAutoFmtPreview( Window* pParent, const ResId& rRes, ScDocume pNumFmt ( new SvNumberFormatter( ::comphelper::getProcessServiceFactory(), ScGlobal::eLnge ) ) { Init(); - if( bIsOlk ) - ((String&)aStrMar).AssignAscii(RTL_CONSTASCII_STRINGPARAM( "Olk" )); } //------------------------------------------------------------------------ diff --git a/sc/source/ui/miscdlgs/makefile.mk b/sc/source/ui/miscdlgs/makefile.mk index 0c145f639968..d34994341ade 100644 --- a/sc/source/ui/miscdlgs/makefile.mk +++ b/sc/source/ui/miscdlgs/makefile.mk @@ -61,7 +61,6 @@ SLOFILES = \ $(SLO)$/crdlg.obj \ $(SLO)$/namecrea.obj \ $(SLO)$/namepast.obj \ - $(SLO)$/teamdlg.obj \ $(SLO)$/textdlgs.obj \ $(SLO)$/anyrefdg.obj \ $(SLO)$/crnrdlg.obj \ @@ -110,7 +109,6 @@ LIB1OBJFILES = \ $(SLO)$/solveroptions.obj \ $(SLO)$/solverutil.obj \ $(SLO)$/tabopdlg.obj \ - $(SLO)$/teamdlg.obj \ $(SLO)$/anyrefdg.obj \ $(SLO)$/crnrdlg.obj \ $(SLO)$/acredlin.obj \ diff --git a/sc/source/ui/miscdlgs/teamdlg.cxx b/sc/source/ui/miscdlgs/teamdlg.cxx deleted file mode 100644 index a9f1bf2a17cf..000000000000 --- a/sc/source/ui/miscdlgs/teamdlg.cxx +++ /dev/null @@ -1,116 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_sc.hxx" - - - -//------------------------------------------------------------------ - -#include <tools/shl.hxx> - -#include "teamdlg.hxx" -#include "scmod.hxx" -#include "scresid.hxx" -#include "sc.hrc" - - -//------------------------------------------------------------------ - -void ShowTheTeam() -{ - SC_MOD()->OpenTeamDlg(); -} - -//======================================================================== -// ScTeamDlg -//======================================================================== - -ScTeamDlg::ScTeamDlg( Window* pParent ) - : FloatingWindow( pParent, ScResId( RID_SCDLG_TEAM ) ), - aBmpTeam ( this, ScResId( 1 ) ) -{ - FreeResource(); - SC_MOD()->SetTeamDlg( this ); - - Bitmap aBmp( ScResId( RID_SCTEAMDLGBMP1 ) ); - - Size aSize = aBmp.GetSizePixel(); - USHORT nOff = (USHORT)aBmpTeam.GetPosPixel().X(); - - aBmpTeam.SetSizePixel( aSize ); - aBmpTeam.SetBitmap( aBmp ); - aSize.Width() += (2*nOff); - aSize.Height() += (2*nOff); - SetOutputSizePixel( aSize ); - Center(); - Point aPos = GetPosPixel(); - if (aPos.Y() < 0) - { - // #87164# title bar must be visible - aPos.Y() = 0; - SetPosPixel(aPos); - } - Show(); -} - -//------------------------------------------------------------------------ - -__EXPORT ScTeamDlg::~ScTeamDlg() -{ -} - -//------------------------------------------------------------------------ - -BOOL __EXPORT ScTeamDlg::Close() -{ - BOOL bReturn = FloatingWindow::Close(); - - SC_MOD()->SetTeamDlg( NULL ); - delete this; - - return bReturn; -} - -//------------------------------------------------------------------------ - -void ScTeamDlg::Center() -{ - if ( IsRollUp() ) RollDown(); - - Size aSizeDesktop = GetParent()->GetSizePixel(); - Size aSize = GetSizePixel(); - Point aNewPos; - - aNewPos.X() = (aSizeDesktop.Width() - aSize.Width()) / 2; - aNewPos.Y() = (aSizeDesktop.Height() - aSize.Height()) / 2; - SetPosPixel( aNewPos ); -} - - - diff --git a/sc/source/ui/optdlg/tpcalc.cxx b/sc/source/ui/optdlg/tpcalc.cxx index c6423ea73b23..5b5920e904fc 100644 --- a/sc/source/ui/optdlg/tpcalc.cxx +++ b/sc/source/ui/optdlg/tpcalc.cxx @@ -88,6 +88,7 @@ ScTpCalcOptions::ScTpCalcOptions( Window* pParent, aBtnMatch ( this, ScResId( BTN_MATCH ) ), aBtnRegex ( this, ScResId( BTN_REGEX ) ), aBtnLookUp ( this, ScResId( BTN_LOOKUP ) ), + aBtnGeneralPrec ( this, ScResId( BTN_GENERAL_PREC ) ), aFtPrec ( this, ScResId( FT_PREC ) ), aEdPrec ( this, ScResId( ED_PREC ) ), pOldOptions ( new ScDocOptions( @@ -116,6 +117,7 @@ __EXPORT ScTpCalcOptions::~ScTpCalcOptions() void ScTpCalcOptions::Init() { aBtnIterate .SetClickHdl( LINK( this, ScTpCalcOptions, CheckClickHdl ) ); + aBtnGeneralPrec.SetClickHdl( LINK(this, ScTpCalcOptions, CheckClickHdl) ); aBtnDateStd .SetClickHdl( LINK( this, ScTpCalcOptions, RadioClickHdl ) ); aBtnDateSc10.SetClickHdl( LINK( this, ScTpCalcOptions, RadioClickHdl ) ); aBtnDate1904.SetClickHdl( LINK( this, ScTpCalcOptions, RadioClickHdl ) ); @@ -150,7 +152,6 @@ void __EXPORT ScTpCalcOptions::Reset( const SfxItemSet& /* rCoreAttrs */ ) aBtnLookUp .Check( pLocalOptions->IsLookUpColRowNames() ); aBtnIterate.Check( pLocalOptions->IsIter() ); aEdSteps .SetValue( pLocalOptions->GetIterCount() ); - aEdPrec .SetValue( pLocalOptions->GetStdPrecision() ); aEdEps .SetValue( pLocalOptions->GetIterEps(), 6 ); pLocalOptions->GetDate( d, m, y ); @@ -168,6 +169,21 @@ void __EXPORT ScTpCalcOptions::Reset( const SfxItemSet& /* rCoreAttrs */ ) break; } + sal_uInt16 nPrec = pLocalOptions->GetStdPrecision(); + if (nPrec == SvNumberFormatter::UNLIMITED_PRECISION) + { + aFtPrec.Disable(); + aEdPrec.Disable(); + aBtnGeneralPrec.Check(false); + } + else + { + aBtnGeneralPrec.Check(); + aFtPrec.Enable(); + aEdPrec.Enable(); + aEdPrec.SetValue(nPrec); + } + CheckClickHdl( &aBtnIterate ); } @@ -178,13 +194,18 @@ BOOL __EXPORT ScTpCalcOptions::FillItemSet( SfxItemSet& rCoreAttrs ) { // alle weiteren Optionen werden in den Handlern aktualisiert pLocalOptions->SetIterCount( (USHORT)aEdSteps.GetValue() ); - pLocalOptions->SetStdPrecision( (USHORT)aEdPrec.GetValue() ); pLocalOptions->SetIgnoreCase( !aBtnCase.IsChecked() ); pLocalOptions->SetCalcAsShown( aBtnCalc.IsChecked() ); pLocalOptions->SetMatchWholeCell( aBtnMatch.IsChecked() ); pLocalOptions->SetFormulaRegexEnabled( aBtnRegex.IsChecked() ); pLocalOptions->SetLookUpColRowNames( aBtnLookUp.IsChecked() ); + if (aBtnGeneralPrec.IsChecked()) + pLocalOptions->SetStdPrecision( + static_cast<sal_uInt16>(aEdPrec.GetValue()) ); + else + pLocalOptions->SetStdPrecision( SvNumberFormatter::UNLIMITED_PRECISION ); + if ( *pLocalOptions != *pOldOptions ) { rCoreAttrs.Put( ScTpCalcItem( nWhichCalc, *pLocalOptions ) ); @@ -245,19 +266,35 @@ IMPL_LINK( ScTpCalcOptions, RadioClickHdl, RadioButton*, pBtn ) //----------------------------------------------------------------------- -IMPL_LINK( ScTpCalcOptions, CheckClickHdl, CheckBox*, pBtn ) +IMPL_LINK( ScTpCalcOptions, CheckClickHdl, CheckBox*, pBtn ) { - if ( pBtn->IsChecked() ) + if (pBtn == &aBtnGeneralPrec) { - pLocalOptions->SetIter( TRUE ); - aFtSteps.Enable(); aEdSteps.Enable(); - aFtEps .Enable(); aEdEps .Enable(); + if (pBtn->IsChecked()) + { + aEdPrec.Enable(); + aFtPrec.Enable(); + } + else + { + aEdPrec.Disable(); + aFtPrec.Disable(); + } } - else + else if (pBtn == &aBtnIterate) { - pLocalOptions->SetIter( FALSE ); - aFtSteps.Disable(); aEdSteps.Disable(); - aFtEps .Disable(); aEdEps .Disable(); + if ( pBtn->IsChecked() ) + { + pLocalOptions->SetIter( TRUE ); + aFtSteps.Enable(); aEdSteps.Enable(); + aFtEps .Enable(); aEdEps .Enable(); + } + else + { + pLocalOptions->SetIter( FALSE ); + aFtSteps.Disable(); aEdSteps.Disable(); + aFtEps .Disable(); aEdEps .Disable(); + } } return 0; diff --git a/sc/source/ui/src/globstr.src b/sc/source/ui/src/globstr.src index 96c56706f83c..6c15762bda6a 100644 --- a/sc/source/ui/src/globstr.src +++ b/sc/source/ui/src/globstr.src @@ -927,10 +927,6 @@ Resource RID_GLOBSTR /* END error constants and error strings. */ - String STR_ODER_SO - { - Text [ en-US ] = "%s or similar" ; - }; String STR_GRIDCOLOR { Text [ en-US ] = "Grid color" ; diff --git a/sc/source/ui/src/miscdlgs.src b/sc/source/ui/src/miscdlgs.src index e7d682e845e9..6d4761c8589c 100644 --- a/sc/source/ui/src/miscdlgs.src +++ b/sc/source/ui/src/miscdlgs.src @@ -154,11 +154,6 @@ ModalDialog RID_SCDLG_INSCELL }; }; -Bitmap RID_SCTEAMDLGBMP1 -{ - File = "calcteam.bmp"; -}; - ModalDialog RID_SCDLG_DELCONT { OutputSize = TRUE ; @@ -1421,18 +1416,6 @@ ModalDialog RID_SCDLG_NAMES_PASTE Text [ en-US ] = "Insert Name" ; }; -FloatingWindow RID_SCDLG_TEAM -{ - Hide = TRUE ; - OutputSize = TRUE ; - SVLook = TRUE ; - Moveable = TRUE ; - Closeable = TRUE ; - Zoomable = TRUE ; - FixedBitmap 1 { Pos = MAP_APPFONT ( 1 , 1 ) ; }; - Text [ en-US ] = "The %PRODUCTNAME Calc Team" ; -}; - ModalDialog RID_SCDLG_CHARTCOLROW { OutputSize = TRUE ; diff --git a/sc/source/ui/src/optdlg.src b/sc/source/ui/src/optdlg.src index 856463e27e40..ea7cabf7716d 100644 --- a/sc/source/ui/src/optdlg.src +++ b/sc/source/ui/src/optdlg.src @@ -119,22 +119,6 @@ TabPage RID_SCPAGE_CALC Pos = MAP_APPFONT ( 6 , 64 ) ; Size = MAP_APPFONT ( 248 , 8 ) ; }; - FixedText FT_PREC - { - Pos = MAP_APPFONT ( 150 , 77 ) ; - Size = MAP_APPFONT ( 72 , 8 ) ; - Text [ en-US ] = "~Decimal places" ; - Right = TRUE ; - }; - NumericField ED_PREC - { - Border = TRUE ; - Pos = MAP_APPFONT ( 226 , 75 ) ; - Size = MAP_APPFONT ( 25 , 12 ) ; - Maximum = 20 ; - Spin = TRUE ; - Repeat = TRUE ; - }; CheckBox BTN_CASE { Pos = MAP_APPFONT ( 12 , 77 ) ; @@ -165,6 +149,28 @@ TabPage RID_SCPAGE_CALC Size = MAP_APPFONT ( 239 , 10 ) ; Text [ en-US ] = "~Automatically find column and row labels " ; }; + CheckBox BTN_GENERAL_PREC + { + Pos = MAP_APPFONT ( 12 , 147 ) ; + Size = MAP_APPFONT ( 136 , 10 ) ; + Text [ en-US ] = "Limit decimals for general number format" ; + }; + FixedText FT_PREC + { + Pos = MAP_APPFONT ( 150 , 148 ) ; + Size = MAP_APPFONT ( 72 , 8 ) ; + Text [ en-US ] = "~Decimal places" ; + Right = TRUE ; + }; + NumericField ED_PREC + { + Border = TRUE ; + Pos = MAP_APPFONT ( 226 , 146 ) ; + Size = MAP_APPFONT ( 25 , 12 ) ; + Maximum = 20 ; + Spin = TRUE ; + Repeat = TRUE ; + }; }; /**************************************************************************/ diff --git a/sc/source/ui/src/scfuncs.src b/sc/source/ui/src/scfuncs.src index 18adf9883373..2f5a2d8c88fb 100644 --- a/sc/source/ui/src/scfuncs.src +++ b/sc/source/ui/src/scfuncs.src @@ -1024,7 +1024,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1 }; String 3 // Description of Parameter 1 { - Text [ en-US ] = "An interger between 1583 and 9956, or 0 and 99 (19xx or 20xx depending on the option set)."; + Text [ en-US ] = "An integer between 1583 and 9956, or 0 and 99 (19xx or 20xx depending on the option set)."; }; }; // -=*# Resource for function BW #*=- @@ -1576,7 +1576,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1 { String 1 // Description { - Text [ en-US ] = "Calulates the arithmetically declining value of an asset (depreciation) for a specified period." ; + Text [ en-US ] = "Calculates the arithmetically declining value of an asset (depreciation) for a specified period." ; }; ExtraData = { @@ -4064,7 +4064,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1 { String 1 // Description { - Text [ en-US ] = "Array transposition. Exchanges the rows and columns of an aray." ; + Text [ en-US ] = "Array transposition. Exchanges the rows and columns of an array." ; }; ExtraData = { @@ -4724,7 +4724,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 }; String 3 // Description of Parameter 1 { - Text [ en-US ] = "Value 1; value 2;.. .are 1 to 30 arguments representing a sample taken from a basic total population."; + Text [ en-US ] = "Value 1; value 2; ... are 1 to 30 arguments representing a sample taken from a basic total population."; }; }; // -=*# Resource for function VARIANZEN #*=- @@ -4820,7 +4820,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 }; String 3 // Description of Parameter 1 { - Text [ en-US ] = "Value 1; value 2;.. .are 1 to 30 arguments representing a sample taken from a basic total population."; + Text [ en-US ] = "Value 1; value 2; ... are 1 to 30 arguments representing a sample taken from a basic total population."; }; }; // -=*# Resource for function STABWN #*=- @@ -4916,7 +4916,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 }; String 3 // Description of Parameter 1 { - Text [ en-US ] = "Value 1; value 2;.. .are 1 to 30 arguments representing a sample taken from a basic total population."; + Text [ en-US ] = "Value 1; value 2; ... are 1 to 30 arguments representing a sample taken from a basic total population."; }; }; // -=*# Resource for function SUMQUADABW #*=- @@ -6358,7 +6358,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 }; String 7 // Description of Parameter 3 { - Text [ en-US ] = "Mode = 1calculates the one-tailed test, 2 = two-tailed distribution." ; + Text [ en-US ] = "Mode = 1 calculates the one-tailed test, 2 = two-tailed distribution." ; }; }; // -=*# Resource for function TINV #*=- @@ -7525,7 +7525,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 }; String 9 // Description of Parameter 4 { - Text [ en-US ] = "if the value is TRUE or not given, the search column of the array must be sorted in ascending order." ; + Text [ en-US ] = "If the value is TRUE or not given, the search column of the array must be sorted in ascending order." ; }; }; // -=*# Resource for function INDEX #*=- @@ -8397,7 +8397,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 { String 1 // Description { - Text [ en-US ] = "Converts a value into text." ; + Text [ en-US ] = "Returns a value if it is text, otherwise an empty string." ; }; ExtraData = { @@ -8413,7 +8413,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 }; String 3 // Description of Parameter 1 { - Text [ en-US ] = "The value to be converted." ; + Text [ en-US ] = "The value to be checked and returned if it is text." ; }; }; // -=*# Resource for function ERSETZEN #*=- @@ -8709,7 +8709,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 }; String 9 // Description of Parameter 4 { - Text [ en-US ] = "Which occurence of the old text is to be replaced." ; + Text [ en-US ] = "Which occurrence of the old text is to be replaced." ; }; }; // -=*# Resource for function BASIS #*=- diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx index 67d651087082..3f5612376962 100644 --- a/sc/source/ui/unoobj/cellsuno.cxx +++ b/sc/source/ui/unoobj/cellsuno.cxx @@ -770,6 +770,7 @@ const SfxItemPropertySet* lcl_GetSheetPropertySet() {MAP_CHAR_LEN(SC_UNONAME_CELLVJUS), ATTR_VER_JUSTIFY, &getCppuType((table::CellVertJustify*)0), 0, 0 }, {MAP_CHAR_LEN(SC_UNONAME_WRITING), ATTR_WRITINGDIR, &getCppuType((sal_Int16*)0), 0, 0 }, {MAP_CHAR_LEN(SC_UNONAME_TABCOLOR), SC_WID_UNO_TABCOLOR, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_CODENAME), SC_WID_UNO_CODENAME, &getCppuType(static_cast< const rtl::OUString * >(0)), 0, 0}, {0,0,0,0,0,0} }; static SfxItemPropertySet aSheetPropertySet( aSheetPropertyMap_Impl ); @@ -5265,6 +5266,8 @@ void SAL_CALL ScCellRangeObj::setFormulaArray( ScDocShell* pDocSh = GetDocShell(); if (pDocSh) { + ScExternalRefManager::ApiGuard aExtRefGuard(pDocSh->GetDocument()); + // GRAM_PODF_A1 for API compatibility. bDone = lcl_PutFormulaArray( *pDocSh, aRange, aArray, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 ); } @@ -7913,7 +7916,8 @@ void SAL_CALL ScTableSheetObj::protect( const rtl::OUString& aPassword ) { ScUnoGuard aGuard; ScDocShell* pDocSh = GetDocShell(); - if ( pDocSh ) + // #i108245# if already protected, don't change anything + if ( pDocSh && !pDocSh->GetDocument()->IsTabProtected( GetTab_Impl() ) ) { String aString(aPassword); ScDocFunc aFunc(*pDocSh); @@ -7930,9 +7934,9 @@ void SAL_CALL ScTableSheetObj::unprotect( const rtl::OUString& aPassword ) { String aString(aPassword); ScDocFunc aFunc(*pDocSh); - aFunc.Unprotect( GetTab_Impl(), aString, TRUE ); - - //! Rueckgabewert auswerten, Exception oder so + BOOL bDone = aFunc.Unprotect( GetTab_Impl(), aString, TRUE ); + if (!bDone) + throw lang::IllegalArgumentException(); } } @@ -8469,7 +8473,7 @@ void ScTableSheetObj::SetOnePropertyValue( const SfxItemPropertySimpleEntry* pEn } } else if ( pEntry->nWID == SC_WID_UNO_TABCOLOR ) - { + { sal_Int32 nColor = COL_AUTO; if (aValue >>= nColor) { @@ -8477,6 +8481,16 @@ void ScTableSheetObj::SetOnePropertyValue( const SfxItemPropertySimpleEntry* pEn pDoc->SetTabBgColor(nTab, Color(static_cast<ColorData>(nColor))); } } + else if ( pEntry->nWID == SC_WID_UNO_CODENAME ) + { + rtl::OUString aCodeName; + if ( pDocSh && ( aValue >>= aCodeName ) ) + { + String sNewName( aCodeName ); + pDocSh->GetDocument()->SetCodeName( GetTab_Impl(), sNewName ); + } + } + } else ScCellRangeObj::SetOnePropertyValue(pEntry, aValue); // base class, no Item WID } @@ -8616,9 +8630,17 @@ void ScTableSheetObj::GetOnePropertyValue( const SfxItemPropertySimpleEntry* pEn ScUnoHelpFunctions::SetBoolInAny( rAny, bAutoPrint ); } else if ( pEntry->nWID == SC_WID_UNO_TABCOLOR ) - { + { rAny <<= sal_Int32(pDoc->GetTabBgColor(nTab).GetColor()); - } + } + else if ( pEntry->nWID == SC_WID_UNO_CODENAME ) + { + String aCodeName; + if ( pDocSh ) + pDocSh->GetDocument()->GetCodeName( GetTab_Impl(), aCodeName ); + rAny <<= rtl::OUString( aCodeName ); + } + } else ScCellRangeObj::GetOnePropertyValue(pEntry, rAny); } diff --git a/sc/source/ui/unoobj/dapiuno.cxx b/sc/source/ui/unoobj/dapiuno.cxx index 7e23d6b2f9f5..c7bf89671161 100755 --- a/sc/source/ui/unoobj/dapiuno.cxx +++ b/sc/source/ui/unoobj/dapiuno.cxx @@ -1891,9 +1891,10 @@ void SAL_CALL ScDataPilotFieldObj::setPropertyValue( const OUString& aPropertyNa String aNameString(aPropertyName); if ( aNameString.EqualsAscii( SC_UNONAME_FUNCTION ) ) { - GeneralFunction eFunction = GeneralFunction_NONE; - if( aValue >>= eFunction ) - setFunction( eFunction ); + // #i109350# use GetEnumFromAny because it also allows sal_Int32 + GeneralFunction eFunction = (GeneralFunction) + ScUnoHelpFunctions::GetEnumFromAny( aValue ); + setFunction( eFunction ); } else if ( aNameString.EqualsAscii( SC_UNONAME_SUBTOTALS ) ) { diff --git a/sc/source/ui/unoobj/defltuno.cxx b/sc/source/ui/unoobj/defltuno.cxx index 141a7d0abb73..f3f76685e5cb 100644 --- a/sc/source/ui/unoobj/defltuno.cxx +++ b/sc/source/ui/unoobj/defltuno.cxx @@ -46,6 +46,8 @@ #include "unonames.hxx" #include "docoptio.hxx" +#include <limits> + using namespace ::com::sun::star; //------------------------------------------------------------------------ @@ -157,7 +159,7 @@ void SAL_CALL ScDocDefaultsObj::setPropertyValue( sal_Int16 nValue = 0; if (aValue >>= nValue) { - aDocOpt.SetStdPrecision(static_cast<sal_uInt8> (nValue)); + aDocOpt.SetStdPrecision(static_cast<sal_uInt16> (nValue)); pDoc->SetDocOptions(aDocOpt); } } @@ -250,7 +252,12 @@ uno::Any SAL_CALL ScDocDefaultsObj::getPropertyValue( const rtl::OUString& aProp if (pDoc) { const ScDocOptions& aDocOpt = pDoc->GetDocOptions(); - aRet <<= static_cast<sal_Int16> (aDocOpt.GetStdPrecision()); + sal_uInt16 nPrec = aDocOpt.GetStdPrecision(); + // the max value of unsigned 16-bit integer is used as the flag + // value for unlimited precision, c.f. + // SvNumberFormatter::UNLIMITED_PRECISION. + if (nPrec <= ::std::numeric_limits<sal_Int16>::max()) + aRet <<= static_cast<sal_Int16> (nPrec); } else throw uno::RuntimeException(); diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx index 8e857adca09c..d9fb4d53e634 100644 --- a/sc/source/ui/unoobj/docuno.cxx +++ b/sc/source/ui/unoobj/docuno.cxx @@ -152,6 +152,7 @@ const SfxItemPropertyMapEntry* lcl_GetDocOptPropertyMap() {MAP_CHAR_LEN(SC_UNO_ISCHANGEREADONLYENABLED), 0, &getBooleanCppuType(), 0, 0}, {MAP_CHAR_LEN(SC_UNO_REFERENCEDEVICE), 0, &getCppuType((uno::Reference<awt::XDevice>*)0), beans::PropertyAttribute::READONLY, 0}, {MAP_CHAR_LEN("BuildId"), 0, &::getCppuType(static_cast< const rtl::OUString * >(0)), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_CODENAME), 0, &getCppuType(static_cast< const rtl::OUString * >(0)), 0, 0}, {0,0,0,0,0,0} }; @@ -1039,18 +1040,21 @@ uno::Sequence<beans::PropertyValue> SAL_CALL ScModelObj::getRenderer( sal_Int32 Size aTwips = aFunc.GetPageSize(); awt::Size aPageSize( TwipsToHMM( aTwips.Width() ), TwipsToHMM( aTwips.Height() ) ); - long nPropCount = bWasCellRange ? 2 : 1; + long nPropCount = bWasCellRange ? 3 : 2; uno::Sequence<beans::PropertyValue> aSequence(nPropCount); beans::PropertyValue* pArray = aSequence.getArray(); pArray[0].Name = rtl::OUString::createFromAscii( SC_UNONAME_PAGESIZE ); pArray[0].Value <<= aPageSize; + // #i111158# all positions are relative to the whole page, including non-printable area + pArray[1].Name = rtl::OUString::createFromAscii( SC_UNONAME_INC_NP_AREA ); + pArray[1].Value = uno::makeAny( sal_True ); if ( bWasCellRange ) { table::CellRangeAddress aRangeAddress( nTab, aCellRange.aStart.Col(), aCellRange.aStart.Row(), aCellRange.aEnd.Col(), aCellRange.aEnd.Row() ); - pArray[1].Name = rtl::OUString::createFromAscii( SC_UNONAME_SOURCERANGE ); - pArray[1].Value <<= aRangeAddress; + pArray[2].Name = rtl::OUString::createFromAscii( SC_UNONAME_SOURCERANGE ); + pArray[2].Value <<= aRangeAddress; } #if 0 @@ -1392,7 +1396,8 @@ void SAL_CALL ScModelObj::enableAutomaticCalculation( sal_Bool bEnabled ) void SAL_CALL ScModelObj::protect( const rtl::OUString& aPassword ) throw(uno::RuntimeException) { ScUnoGuard aGuard; - if (pDocShell) + // #i108245# if already protected, don't change anything + if ( pDocShell && !pDocShell->GetDocument()->IsDocProtected() ) { String aString(aPassword); @@ -1410,9 +1415,9 @@ void SAL_CALL ScModelObj::unprotect( const rtl::OUString& aPassword ) String aString(aPassword); ScDocFunc aFunc(*pDocShell); - aFunc.Unprotect( TABLEID_DOC, aString, TRUE ); - - //! Rueckgabewert auswerten, Exception oder so + BOOL bDone = aFunc.Unprotect( TABLEID_DOC, aString, TRUE ); + if (!bDone) + throw lang::IllegalArgumentException(); } } @@ -1651,6 +1656,12 @@ void SAL_CALL ScModelObj::setPropertyValue( pDoc->SetLanguage( eLatin, eCjk, eCtl ); } } + else if ( aString.EqualsAscii( SC_UNO_CODENAME ) ) + { + rtl::OUString sCodeName; + if ( aValue >>= sCodeName ) + pDoc->SetCodeName( sCodeName ); + } else if ( aString.EqualsAscii( SC_UNO_CJK_CLOCAL ) ) { lang::Locale aLocale; @@ -1783,6 +1794,12 @@ uno::Any SAL_CALL ScModelObj::getPropertyValue( const rtl::OUString& aPropertyNa ScUnoConversion::FillLocale( aLocale, eLatin ); aRet <<= aLocale; } + else if ( aString.EqualsAscii( SC_UNO_CODENAME ) ) + { + rtl::OUString sCodeName = pDoc->GetCodeName(); + aRet <<= sCodeName; + } + else if ( aString.EqualsAscii( SC_UNO_CJK_CLOCAL ) ) { LanguageType eLatin, eCjk, eCtl; @@ -2074,6 +2091,13 @@ sal_Int64 SAL_CALL ScModelObj::getSomething( return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); } + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( SfxObjectShell::getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(pDocShell )); + } + // aggregated number formats supplier has XUnoTunnel, too // interface from aggregated object must be obtained via queryAggregation diff --git a/sc/source/ui/unoobj/filtuno.cxx b/sc/source/ui/unoobj/filtuno.cxx index 8591f2fc0801..efe804784a40 100644 --- a/sc/source/ui/unoobj/filtuno.cxx +++ b/sc/source/ui/unoobj/filtuno.cxx @@ -185,7 +185,9 @@ sal_Int16 SAL_CALL ScFilterOptionsObj::execute() throw(uno::RuntimeException) } else if ( aFilterString == ScDocShell::GetWebQueryFilterName() || aFilterString == ScDocShell::GetHtmlFilterName() ) { - if (!bExport) + if (bExport) + nRet = ui::dialogs::ExecutableDialogResults::OK; // export HTML without dialog + else { // HTML import. ::std::auto_ptr<AbstractScTextImportOptionsDlg> pDlg( diff --git a/sc/source/ui/unoobj/linkuno.cxx b/sc/source/ui/unoobj/linkuno.cxx index 6d9fcd1d23e4..a119eda13a32 100644 --- a/sc/source/ui/unoobj/linkuno.cxx +++ b/sc/source/ui/unoobj/linkuno.cxx @@ -1605,12 +1605,16 @@ ScExternalDocLinkObj::~ScExternalDocLinkObj() } Reference< sheet::XExternalSheetCache > SAL_CALL ScExternalDocLinkObj::addSheetCache( - const OUString& aSheetName ) + const OUString& aSheetName, sal_Bool bDynamicCache ) throw (RuntimeException) { ScUnoGuard aGuard; size_t nIndex = 0; ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aSheetName, true, &nIndex); + if (!bDynamicCache) + // Set the whole table cached to prevent access to the source document. + pTable->setWholeTableCached(); + Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex)); return aSheetCache; } diff --git a/sc/source/ui/unoobj/nameuno.cxx b/sc/source/ui/unoobj/nameuno.cxx index 474d07764127..75686df460d6 100644 --- a/sc/source/ui/unoobj/nameuno.cxx +++ b/sc/source/ui/unoobj/nameuno.cxx @@ -340,7 +340,7 @@ uno::Reference<table::XCellRange> SAL_CALL ScNamedRangeObj::getReferredCells() ScUnoGuard aGuard; ScRange aRange; ScRangeData* pData = GetRangeData_Impl(); - if ( pData && pData->IsReference( aRange ) ) + if ( pData && pData->IsValidReference( aRange ) ) { //! static Funktion um ScCellObj/ScCellRangeObj zu erzeugen am ScCellRangeObj ??? diff --git a/sc/source/ui/unoobj/scdetect.cxx b/sc/source/ui/unoobj/scdetect.cxx index cded62efa3a8..80cb88595b11 100644 --- a/sc/source/ui/unoobj/scdetect.cxx +++ b/sc/source/ui/unoobj/scdetect.cxx @@ -256,6 +256,7 @@ static BOOL lcl_IsAnyXMLFilter( const SfxFilter* pFilter ) sal_Int32 nIndexOfReadOnlyFlag = -1; sal_Int32 nIndexOfTemplateFlag = -1; sal_Int32 nIndexOfDocumentTitle = -1; + bool bFakeXLS = false; for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty ) { @@ -436,8 +437,11 @@ static BOOL lcl_IsAnyXMLFilter( const SfxFilter* pFilter ) } else { + bool bIsXLS = false; SvStream* pStream = aMedium.GetInStream(); const SfxFilter* pPreselectedFilter = pFilter; + if ( pPreselectedFilter && pPreselectedFilter->GetName().SearchAscii("Excel") != STRING_NOTFOUND ) + bIsXLS = true; pFilter = 0; if ( pStream ) { @@ -718,7 +722,8 @@ static BOOL lcl_IsAnyXMLFilter( const SfxFilter* pFilter ) // further checks for filters only if they are preselected: ASCII, HTML, RTF, DBase // without the preselection other filters (Writer) take precedence // DBase can't be detected reliably, so it also needs preselection - if ( pPreselectedFilter->GetFilterName().EqualsAscii(pFilterAscii) && lcl_MayBeAscii( rStr ) ) + bool bMaybeText = lcl_MayBeAscii( rStr ); + if ( pPreselectedFilter->GetFilterName().EqualsAscii(pFilterAscii) && bMaybeText ) { // Text filter is accepted if preselected pFilter = pPreselectedFilter; @@ -747,8 +752,15 @@ static BOOL lcl_IsAnyXMLFilter( const SfxFilter* pFilter ) else { pFilter = aMatcher.GetFilter4FilterName( String::CreateFromAscii(pFilterHtmlWeb) ); + if ( bIsXLS ) + bFakeXLS = true; } } + else if ( bIsXLS && bMaybeText ) + { + pFilter = aMatcher.GetFilter4FilterName( String::CreateFromAscii(pFilterAscii) ); + bFakeXLS = true; + } else if ( aHeader.CompareTo( "{\\rtf", 5 ) == COMPARE_EQUAL ) { // test for RTF @@ -834,6 +846,19 @@ static BOOL lcl_IsAnyXMLFilter( const SfxFilter* pFilter ) lDescriptor[nIndexOfDocumentTitle].Value <<= aDocumentTitle; } + if ( bFakeXLS ) + { + if ( nIndexOfFilterName == -1 ) + { + lDescriptor.realloc( nPropertyCount + 1 ); + lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("FilterName"); + lDescriptor[nPropertyCount].Value <<= rtl::OUString(pFilter->GetName()); + nPropertyCount++; + } + else + lDescriptor[nIndexOfFilterName].Value <<= rtl::OUString(pFilter->GetName()); + } + if ( pFilter ) aTypeName = pFilter->GetTypeName(); else diff --git a/sc/source/ui/unoobj/servuno.cxx b/sc/source/ui/unoobj/servuno.cxx index 0c57963a4f12..0b3a6f01f9ea 100644 --- a/sc/source/ui/unoobj/servuno.cxx +++ b/sc/source/ui/unoobj/servuno.cxx @@ -37,6 +37,7 @@ #include <com/sun/star/sheet/XSpreadsheetDocument.hpp> #include "servuno.hxx" +#include "unoguard.hxx" #include "unonames.hxx" #include "cellsuno.hxx" #include "fielduno.hxx" @@ -65,8 +66,127 @@ #include <com/sun/star/form/XFormsSupplier.hpp> #include <svx/unomod.hxx> +#include <comphelper/processfactory.hxx> +#include <basic/basmgr.hxx> +#include <sfx2/app.hxx> + using namespace ::com::sun::star; +#ifndef CWS_NPOWER14MISCFIXES +uno::Reference< uno::XInterface > lcl_createVBAUnoAPIServiceWithArgs( SfxObjectShell* pShell, const sal_Char* _pAsciiName, const uno::Sequence< uno::Any >& aArgs ) throw (uno::RuntimeException) +{ + uno::Any aUnoVar; + if ( !pShell || !pShell->GetBasicManager()->GetGlobalUNOConstant( "VBAGlobals", aUnoVar ) ) + throw lang::IllegalArgumentException(); + uno::Reference< lang::XMultiServiceFactory > xVBAFactory( aUnoVar, uno::UNO_QUERY_THROW ); + ::rtl::OUString sVarName( ::rtl::OUString::createFromAscii( _pAsciiName ) ); + uno::Reference< uno::XInterface > xIf = xVBAFactory->createInstanceWithArguments( sVarName, aArgs ); + return xIf; +} +#endif + +class ScVbaObjectForCodeNameProvider : public ::cppu::WeakImplHelper1< container::XNameAccess > +{ + uno::Any maWorkbook; + uno::Any maCachedObject; + ScDocShell* mpDocShell; +public: + ScVbaObjectForCodeNameProvider( ScDocShell* pDocShell ) : mpDocShell( pDocShell ) + { + ScDocument* pDoc = mpDocShell->GetDocument(); + if ( !pDoc ) + throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("")), uno::Reference< uno::XInterface >() ); + + uno::Sequence< uno::Any > aArgs(2); + aArgs[0] = uno::Any( uno::Reference< uno::XInterface >() ); + aArgs[1] = uno::Any( mpDocShell->GetModel() ); +#ifdef CWS_NPOWER14MISCFIXES + maWorkbook <<= ooo::vba::createVBAUnoAPIServiceWithArgs( mpDocShell, "ooo.vba.excel.Workbook", aArgs ); +#else + maWorkbook <<= lcl_createVBAUnoAPIServiceWithArgs( mpDocShell, "ooo.vba.excel.Workbook", aArgs ); +#endif + } + + virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (::com::sun::star::uno::RuntimeException ) + { + ScUnoGuard aGuard; + maCachedObject = uno::Any(); // clear cached object + String sName = aName; + + ScDocument* pDoc = mpDocShell->GetDocument(); + if ( !pDoc ) + throw uno::RuntimeException(); + if ( sName == pDoc->GetCodeName() ) + maCachedObject = maWorkbook; + else + { + String sCodeName; + SCTAB nCount = pDoc->GetTableCount(); + for( SCTAB i = 0; i < nCount; i++ ) + { + pDoc->GetCodeName( i, sCodeName ); + if( sCodeName == sName ) + { + String sSheetName; + if( pDoc->GetName( i, sSheetName ) ) + { + uno::Reference< frame::XModel > xModel( mpDocShell->GetModel() ); + uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( xModel, uno::UNO_QUERY_THROW ); + uno::Reference<sheet::XSpreadsheets > xSheets( xSpreadDoc->getSheets(), uno::UNO_QUERY_THROW ); + uno::Reference< container::XIndexAccess > xIndexAccess( xSheets, uno::UNO_QUERY_THROW ); + uno::Reference< sheet::XSpreadsheet > xSheet( xIndexAccess->getByIndex( i ), uno::UNO_QUERY_THROW ); + uno::Sequence< uno::Any > aArgs(3); + aArgs[0] = maWorkbook; + aArgs[1] = uno::Any( xModel ); + aArgs[2] = uno::Any( rtl::OUString( sSheetName ) ); +#ifdef CWS_NPOWER14MISCFIXES + // use the convience function + maCachedObject <<= ooo::vba::createVBAUnoAPIServiceWithArgs( mpDocShell, "ooo.vba.excel.Worksheet", aArgs ); +#else + // use the temp function + maCachedObject <<= lcl_createVBAUnoAPIServiceWithArgs( mpDocShell, "ooo.vba.excel.Worksheet", aArgs ); +#endif + break; + } + } + } + } + return maCachedObject.hasValue(); + + } + ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) + { + ScUnoGuard aGuard; + OSL_TRACE("ScVbaObjectForCodeNameProvider::getByName( %s )", + rtl::OUStringToOString( aName, RTL_TEXTENCODING_UTF8 ).getStr() ); + if ( !hasByName( aName ) ) + throw ::com::sun::star::container::NoSuchElementException(); + return maCachedObject; + } + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw (::com::sun::star::uno::RuntimeException) + { + ScUnoGuard aGuard; + ScDocument* pDoc = mpDocShell->GetDocument(); + if ( !pDoc ) + throw uno::RuntimeException(); + SCTAB nCount = pDoc->GetTableCount(); + uno::Sequence< rtl::OUString > aNames( nCount + 1 ); + SCTAB index = 0; + String sCodeName; + for( ; index < nCount; ++index ) + { + pDoc->GetCodeName( index, sCodeName ); + aNames[ index ] = sCodeName; + } + aNames[ index ] = pDoc->GetCodeName(); + return aNames; + } + // XElemenAccess + virtual ::com::sun::star::uno::Type SAL_CALL getElementType( ) throw (::com::sun::star::uno::RuntimeException){ return uno::Type(); } + virtual ::sal_Bool SAL_CALL hasElements( ) throw (::com::sun::star::uno::RuntimeException ) { return sal_True; } + +}; + class ScVbaCodeNameProvider : public ::cppu::WeakImplHelper1< document::XCodeNameQuery > { ScDocShell* mpDocShell; @@ -75,6 +195,7 @@ public: // XCodeNameQuery rtl::OUString SAL_CALL getCodeNameForObject( const uno::Reference< uno::XInterface >& xIf ) throw( uno::RuntimeException ) { + ScUnoGuard aGuard; rtl::OUString sCodeName; if ( mpDocShell ) { @@ -172,7 +293,9 @@ static const ProvNamesId_Type __FAR_DATA aProvNamesId[] = { SC_SERVICENAME_CHDATAPROV, SC_SERVICE_CHDATAPROV }, { SC_SERVICENAME_FORMULAPARS, SC_SERVICE_FORMULAPARS }, { SC_SERVICENAME_OPCODEMAPPER, SC_SERVICE_OPCODEMAPPER }, + { "ooo.vba.VBAObjectModuleObjectProvider", SC_SERVICE_VBAOBJECTPROVIDER }, { "ooo.vba.VBACodeNameProvider", SC_SERVICE_VBACODENAMEPROVIDER }, + { "ooo.vba.VBAGlobals", SC_SERVICE_VBAGLOBALS }, // case-correct versions of the service names (#i102468#) { "com.sun.star.text.textfield.URL", SC_SERVICE_URLFIELD }, @@ -182,7 +305,7 @@ static const ProvNamesId_Type __FAR_DATA aProvNamesId[] = { "com.sun.star.text.textfield.Time", SC_SERVICE_TIMEFIELD }, { "com.sun.star.text.textfield.DocumentTitle", SC_SERVICE_TITLEFIELD }, { "com.sun.star.text.textfield.FileName", SC_SERVICE_FILEFIELD }, - { "com.sun.star.text.textfield.SheetName", SC_SERVICE_SHEETFIELD }, + { "com.sun.star.text.textfield.SheetName", SC_SERVICE_SHEETFIELD } }; // @@ -235,7 +358,9 @@ static const sal_Char* __FAR_DATA aOldNames[SC_SERVICE_COUNT] = "", // SC_SERVICE_CHDATAPROV "", // SC_SERVICE_FORMULAPARS "", // SC_SERVICE_OPCODEMAPPER + "", // SC_SERVICE_VBAOBJECTPROVIDER "", // SC_SERVICE_VBACODENAMEPROVIDER + "", // SC_SERVICE_VBAGLOBALS }; @@ -440,6 +565,13 @@ uno::Reference<uno::XInterface> ScServiceProvider::MakeInstance( xRet.set(static_cast<sheet::XFormulaOpCodeMapper*>(new ScFormulaOpCodeMapperObj(::std::auto_ptr<formula::FormulaCompiler> (pComp)))); break; } + case SC_SERVICE_VBAOBJECTPROVIDER: + if ( pDocShell ) + { + OSL_TRACE("**** creating VBA Object mapper"); + xRet.set(static_cast<container::XNameAccess*>(new ScVbaObjectForCodeNameProvider( pDocShell ))); + } + break; case SC_SERVICE_VBACODENAMEPROVIDER: { // Only create the excel faking service for excel docs @@ -453,6 +585,25 @@ uno::Reference<uno::XInterface> ScServiceProvider::MakeInstance( } break; } + case SC_SERVICE_VBAGLOBALS: + { + uno::Any aGlobs; + ScDocument* pDoc = pDocShell->GetDocument(); + if ( pDoc ) + { + if ( !pDocShell->GetBasicManager()->GetGlobalUNOConstant( "VBAGlobals", aGlobs ) ) + { + uno::Sequence< uno::Any > aArgs(1); + aArgs[ 0 ] <<= pDocShell->GetModel(); + aGlobs <<= ::comphelper::getProcessServiceFactory()->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.excel.Globals" ) ), aArgs ); + pDocShell->GetBasicManager()->SetGlobalUNOConstant( "VBAGlobals", aGlobs ); + BasicManager* pAppMgr = SFX_APP()->GetBasicManager(); + if ( pAppMgr ) + pAppMgr->SetGlobalUNOConstant( "ThisExcelDoc", aArgs[ 0 ] ); + } + aGlobs >>= xRet; + } + } } return xRet; diff --git a/sc/source/ui/unoobj/tokenuno.cxx b/sc/source/ui/unoobj/tokenuno.cxx index fc14b53a6372..5e3b3102e14a 100644 --- a/sc/source/ui/unoobj/tokenuno.cxx +++ b/sc/source/ui/unoobj/tokenuno.cxx @@ -140,9 +140,11 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula( if (mpDocShell) { + ScDocument* pDoc = mpDocShell->GetDocument(); + ScExternalRefManager::ApiGuard aExtRefGuard(pDoc); + ScAddress aRefPos( ScAddress::UNINITIALIZED ); ScUnoConversion::FillScAddress( aRefPos, rReferencePos ); - ScDocument* pDoc = mpDocShell->GetDocument(); ScCompiler aCompiler( pDoc, aRefPos); aCompiler.SetGrammar(pDoc->GetGrammar()); SetCompilerFlags( aCompiler ); diff --git a/sc/source/ui/vba/excelvbahelper.cxx b/sc/source/ui/vba/excelvbahelper.cxx index 4912863a446e..b1c4db637434 100644 --- a/sc/source/ui/vba/excelvbahelper.cxx +++ b/sc/source/ui/vba/excelvbahelper.cxx @@ -208,12 +208,11 @@ getViewFrame( const uno::Reference< frame::XModel >& xModel ) } SfxItemSet* -ScVbaCellRangeAccess::GetDataSet( ScCellRangeObj* pRangeObj ) +ScVbaCellRangeAccess::GetDataSet( ScCellRangesBase* pRangeObj ) { - SfxItemSet* pDataSet = pRangeObj ? pRangeObj->GetCurrentDataSet( true ) : NULL ; - return pDataSet; - + return pRangeObj ? pRangeObj->GetCurrentDataSet( true ) : 0; } + } //excel } //vba } //ooo diff --git a/sc/source/ui/vba/excelvbahelper.hxx b/sc/source/ui/vba/excelvbahelper.hxx index 34b099e6db46..9af804ab169f 100644 --- a/sc/source/ui/vba/excelvbahelper.hxx +++ b/sc/source/ui/vba/excelvbahelper.hxx @@ -30,7 +30,7 @@ #include<vbahelper/vbahelper.hxx> #include <docsh.hxx> -class ScCellRangeObj; +class ScCellRangesBase; namespace ooo { @@ -51,7 +51,7 @@ namespace ooo class ScVbaCellRangeAccess { public: - static SfxItemSet* GetDataSet( ScCellRangeObj* pRangeObj ); + static SfxItemSet* GetDataSet( ScCellRangesBase* pRangeObj ); }; } } diff --git a/sc/source/ui/vba/testvba/runTests.pl b/sc/source/ui/vba/testvba/runTests.pl index f5051516a9c4..e686a1d4cb89 100644..100755 --- a/sc/source/ui/vba/testvba/runTests.pl +++ b/sc/source/ui/vba/testvba/runTests.pl @@ -20,7 +20,7 @@ my $theResult; my $officepath = shift || die "please specify path to office installation program dir"; my $DocName = shift || ""; my $programpath = "$officepath"."3/program:$officepath/program:"; -my $basiclibrarypath = "$officepath/basis3.2/program"; +my $basiclibrarypath = "$officepath/basis3.3/program"; my $urelibpath = "$officepath/ure/lib"; my $binext = ""; my $testDocDir = "$binDir/TestDocuments"; diff --git a/sc/source/ui/vba/testvba/testclient b/sc/source/ui/vba/testvba/testclient Binary files differindex 12e9ca1659f4..c9cde8c5b052 100755 --- a/sc/source/ui/vba/testvba/testclient +++ b/sc/source/ui/vba/testvba/testclient diff --git a/sc/source/ui/vba/vbaapplication.cxx b/sc/source/ui/vba/vbaapplication.cxx index 5d9e513dabeb..3d5af01acef1 100644 --- a/sc/source/ui/vba/vbaapplication.cxx +++ b/sc/source/ui/vba/vbaapplication.cxx @@ -132,10 +132,16 @@ ScVbaApplication::getActiveWorkbook() throw (uno::RuntimeException) { return new ActiveWorkbook( this, mxContext ); } + uno::Reference< excel::XWorkbook > SAL_CALL ScVbaApplication::getThisWorkbook() throw (uno::RuntimeException) { - return getActiveWorkbook(); + uno::Reference< frame::XModel > xModel = getThisExcelDoc(mxContext); + if( !xModel.is() ) + return uno::Reference< excel::XWorkbook >(); + + ScVbaWorkbook *pWb = new ScVbaWorkbook( this, mxContext, xModel ); + return uno::Reference< excel::XWorkbook > (pWb); } uno::Reference< XAssistant > SAL_CALL @@ -769,46 +775,74 @@ bool lcl_canJoin( ScRange& r1, ScRange& r2 ) void lcl_strip_containedRanges( Ranges& vRanges ) { // get rid of ranges that are surrounded by other ranges - for( Ranges::iterator it = vRanges.begin(); it != vRanges.end(); ++it ) + Ranges::iterator it_outer = vRanges.begin(); + while( it_outer != vRanges.end() ) { - for( Ranges::iterator it_inner = vRanges.begin(); it_inner != vRanges.end(); ++it_inner ) + bool it_outer_erased = false; // true = it_outer erased from vRanges + Ranges::iterator it_inner = vRanges.begin(); + /* Exit the inner loop if outer iterator has been erased in its last + iteration (this means it has been joined to last it_inner, or that + the it_inner contains it completely). The inner loop will restart + with next element of the outer loop, and all elements (from the + beginning of the list) will be checked against that new element. */ + while( !it_outer_erased && (it_inner != vRanges.end()) ) { - if ( it != it_inner ) + bool it_inner_erased = false; // true = it_inner erased from vRanges + if ( it_outer != it_inner ) { #ifdef DEBUG - String r1; - String r2; - it->Format( r1, SCA_VALID ) ; - it_inner->Format( r2, SCA_VALID ) ; - OSL_TRACE( "try strip/join address %s with %s ", - rtl::OUStringToOString( r1, RTL_TEXTENCODING_UTF8 ).getStr(), - rtl::OUStringToOString( r2, RTL_TEXTENCODING_UTF8 ).getStr() ); + String r1; + String r2; + it_outer->Format( r1, SCA_VALID ) ; + it_inner->Format( r2, SCA_VALID ) ; + OSL_TRACE( "try strip/join address %s with %s ", + rtl::OUStringToOString( r1, RTL_TEXTENCODING_UTF8 ).getStr(), + rtl::OUStringToOString( r2, RTL_TEXTENCODING_UTF8 ).getStr() ); #endif - if ( it->In( *it_inner ) ) + if ( it_outer->In( *it_inner ) ) + { it_inner = vRanges.erase( it_inner ); - else if ( it_inner->In( *it ) ) - it = vRanges.erase( it ); + it_inner_erased = true; + } + else if ( it_inner->In( *it_outer ) ) + { + it_outer = vRanges.erase( it_outer ); + it_outer_erased = true; + } #ifndef OWN_JOIN - else if ( (*it_inner).aStart.Row() == (*it).aStart.Row() - && (*it_inner).aEnd.Row() == (*it).aEnd.Row() ) + else if ( (*it_inner).aStart.Row() == (*it_outer).aStart.Row() + && (*it_inner).aEnd.Row() == (*it_outer).aEnd.Row() ) { - it->ExtendTo( *it_inner ); + it_outer->ExtendTo( *it_inner ); it_inner = vRanges.erase( it_inner ); + it_inner_erased = true; } #else - else if ( lcl_canJoin( *it, *it_inner ) ) + else if ( lcl_canJoin( *it_outer, *it_inner ) ) { - it->ExtendTo( *it_inner ); + it_outer->ExtendTo( *it_inner ); it_inner = vRanges.erase( it_inner ); + it_inner_erased = true; } - else if ( lcl_canJoin( *it_inner, *it) ) + else if ( lcl_canJoin( *it_inner, *it_outer) ) { - it_inner->ExtendTo( *it ); - it = vRanges.erase( it ); + it_inner->ExtendTo( *it_outer ); + it_outer = vRanges.erase( it_outer ); + it_outer_erased = true; } #endif } + /* If it_inner has not been erased from vRanges, continue inner + loop with next element. Otherwise, it_inner already points to + the next element (return value of list::erase()). */ + if( !it_inner_erased ) + ++it_inner; } + /* If it_outer has not been erased from vRanges, continue outer loop + with next element. Otherwise, it_outer already points to the next + element (return value of list::erase()). */ + if( !it_outer_erased ) + ++it_outer; } } diff --git a/sc/source/ui/vba/vbaformat.cxx b/sc/source/ui/vba/vbaformat.cxx index c98029fb1292..23c2bf96a810 100644 --- a/sc/source/ui/vba/vbaformat.cxx +++ b/sc/source/ui/vba/vbaformat.cxx @@ -45,7 +45,10 @@ #include "vbafont.hxx" #include "vbainterior.hxx" -#include "unonames.hxx" +#include <unonames.hxx> +#include <cellsuno.hxx> +#include <scitems.hxx> +#include <attrib.hxx> using namespace ::ooo::vba; using namespace ::com::sun::star; @@ -571,14 +574,24 @@ ScVbaFormat<Ifc1>::getLocked( ) throw (script::BasicErrorException, uno::Runtim uno::Any aCellProtection = aNULL(); try { - rtl::OUString sCellProt( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_CELLPRO ) ); + if (!isAmbiguous(sCellProt)) { - util::CellProtection cellProtection; - mxPropertySet->getPropertyValue(sCellProt) >>= cellProtection; - - aCellProtection = uno::makeAny( cellProtection.IsLocked ); + SfxItemSet* pDataSet = getCurrentDataSet(); + if ( pDataSet ) + { + const ScProtectionAttr& rProtAttr = (const ScProtectionAttr &) pDataSet->Get(ATTR_PROTECTION, TRUE); + SfxItemState eState = pDataSet->GetItemState(ATTR_PROTECTION, TRUE, NULL); + if(eState != SFX_ITEM_DONTCARE) + aCellProtection = uno::makeAny(rProtAttr.GetProtection()); + } + else // fallback to propertyset + { + util::CellProtection cellProtection; + mxPropertySet->getPropertyValue(sCellProt) >>= aCellProtection; + aCellProtection = uno::makeAny( cellProtection.IsLocked ); + } } } catch (uno::Exception& ) @@ -598,9 +611,20 @@ ScVbaFormat<Ifc1>::getFormulaHidden( ) throw (script::BasicErrorException, uno: rtl::OUString sCellProt( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_CELLPRO ) ); if (!isAmbiguous(sCellProt)) { - util::CellProtection aCellProtection; - mxPropertySet->getPropertyValue(sCellProt) >>= aCellProtection; - aBoolRet = uno::makeAny( aCellProtection.IsFormulaHidden ); + SfxItemSet* pDataSet = getCurrentDataSet(); + if ( pDataSet ) + { + const ScProtectionAttr& rProtAttr = (const ScProtectionAttr &) pDataSet->Get(ATTR_PROTECTION, TRUE); + SfxItemState eState = pDataSet->GetItemState(ATTR_PROTECTION, TRUE, NULL); + if(eState != SFX_ITEM_DONTCARE) + aBoolRet = uno::makeAny(rProtAttr.GetHideFormula()); + } + else + { + util::CellProtection aCellProtection; + mxPropertySet->getPropertyValue(sCellProt) >>= aCellProtection; + aBoolRet = uno::makeAny( aCellProtection.IsFormulaHidden ); + } } } catch (uno::Exception e) @@ -794,6 +818,24 @@ ScVbaFormat<Ifc1>::getServiceNames() return aServiceNames; } +template< typename Ifc1 > +ScCellRangesBase* +ScVbaFormat<Ifc1>::getCellRangesBase() throw ( ::uno::RuntimeException ) +{ + return ScCellRangesBase::getImplementation( mxPropertySet ); +} + +template< typename Ifc1 > +SfxItemSet* +ScVbaFormat<Ifc1>::getCurrentDataSet( ) throw ( uno::RuntimeException ) +{ + SfxItemSet* pDataSet = excel::ScVbaCellRangeAccess::GetDataSet( getCellRangesBase() ); + if ( !pDataSet ) + throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Can't access Itemset for XPropertySet" ) ), uno::Reference< uno::XInterface >() ); + return pDataSet; +} + + template class ScVbaFormat< excel::XStyle >; template class ScVbaFormat< excel::XRange >; diff --git a/sc/source/ui/vba/vbaformat.hxx b/sc/source/ui/vba/vbaformat.hxx index e024cd68b9ad..bfa88d6c7cb8 100644 --- a/sc/source/ui/vba/vbaformat.hxx +++ b/sc/source/ui/vba/vbaformat.hxx @@ -38,6 +38,8 @@ #include <com/sun/star/beans/XPropertyState.hpp> #include <vbahelper/vbahelperinterface.hxx> +class ScCellRangesBase; + template< typename Ifc1 > class ScVbaFormat : public InheritedHelperInterfaceImpl1< Ifc1 > { @@ -60,6 +62,9 @@ protected: css::uno::Reference< css::beans::XPropertyState > getXPropertyState() throw ( css::uno::RuntimeException ); void initializeNumberFormats() throw ( css::script::BasicErrorException ); void setNumberFormat( css::lang::Locale _aLocale, const rtl::OUString& _sFormatString) throw( css::script::BasicErrorException ); + SfxItemSet* getCurrentDataSet( ) throw ( css::uno::RuntimeException ); +protected: + virtual ScCellRangesBase* getCellRangesBase() throw ( css::uno::RuntimeException ); public: ScVbaFormat( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext > & xContext, const css::uno::Reference< css::beans::XPropertySet >& _xPropertySet, const css::uno::Reference< css::frame::XModel >& xModel, bool bCheckAmbiguoity ) throw ( css::script::BasicErrorException ); virtual ~ScVbaFormat() {} diff --git a/sc/source/ui/vba/vbarange.cxx b/sc/source/ui/vba/vbarange.cxx index b3307ffdc55d..1a153b440b15 100644 --- a/sc/source/ui/vba/vbarange.cxx +++ b/sc/source/ui/vba/vbarange.cxx @@ -238,21 +238,28 @@ uno::Reference< excel::XRange > lcl_makeXRangeFromSheetCellRanges( const uno::Re return xRange; } -ScCellRangeObj* ScVbaRange::getCellRangeObj() throw ( uno::RuntimeException ) +ScCellRangesBase* ScVbaRange::getCellRangesBase() throw ( uno::RuntimeException ) { - uno::Reference< uno::XInterface > xIf; - if ( mxRanges.is() ) - xIf.set( mxRanges, uno::UNO_QUERY_THROW ); - else - xIf.set( mxRange, uno::UNO_QUERY_THROW ); - ScCellRangeObj* pUnoCellRange = dynamic_cast< ScCellRangeObj* >( xIf.get() ); - return pUnoCellRange; + if( mxRanges.is() ) + return ScCellRangesBase::getImplementation( mxRanges ); + if( mxRange.is() ) + return ScCellRangesBase::getImplementation( mxRange ); + throw uno::RuntimeException( rtl::OUString::createFromAscii("General Error creating range - Unknown" ), uno::Reference< uno::XInterface >() ); +} + +ScCellRangeObj* ScVbaRange::getCellRangeObj() throw ( uno::RuntimeException ) +{ + return dynamic_cast< ScCellRangeObj* >( getCellRangesBase() ); +} + +ScCellRangesObj* ScVbaRange::getCellRangesObj() throw ( uno::RuntimeException ) +{ + return dynamic_cast< ScCellRangesObj* >( getCellRangesBase() ); } SfxItemSet* ScVbaRange::getCurrentDataSet( ) throw ( uno::RuntimeException ) { - ScCellRangeObj* pUnoCellRange = getCellRangeObj(); - SfxItemSet* pDataSet = excel::ScVbaCellRangeAccess::GetDataSet( pUnoCellRange ); + SfxItemSet* pDataSet = excel::ScVbaCellRangeAccess::GetDataSet( getCellRangesBase() ); if ( !pDataSet ) throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Can't access Itemset for range" ) ), uno::Reference< uno::XInterface >() ); return pDataSet; @@ -3852,25 +3859,6 @@ ScVbaRange::getWorksheet() throw (uno::RuntimeException) return xSheet; } -ScCellRangesBase* -ScVbaRange::getCellRangesBase() throw( uno::RuntimeException ) -{ - ScCellRangesBase* pUnoRangesBase = NULL; - if ( mxRanges.is() ) - { - uno::Reference< uno::XInterface > xIf( mxRanges, uno::UNO_QUERY_THROW ); - pUnoRangesBase = dynamic_cast< ScCellRangesBase* >( xIf.get() ); - } - else if ( mxRange.is() ) - { - uno::Reference< uno::XInterface > xIf( mxRange, uno::UNO_QUERY_THROW ); - pUnoRangesBase = dynamic_cast< ScCellRangesBase* >( xIf.get() ); - } - else - throw uno::RuntimeException( rtl::OUString::createFromAscii("General Error creating range - Unknown" ), uno::Reference< uno::XInterface >() ); - return pUnoRangesBase; -} - // #TODO remove this ugly application processing // Process an application Range request e.g. 'Range("a1,b2,a4:b6") uno::Reference< excel::XRange > @@ -4589,26 +4577,6 @@ ScVbaRange::getValidation() throw (css::uno::RuntimeException) return m_xValidation; } -uno::Any ScVbaRange::getFormulaHidden() throw ( script::BasicErrorException, css::uno::RuntimeException) -{ - SfxItemSet* pDataSet = getCurrentDataSet(); - const ScProtectionAttr& rProtAttr = (const ScProtectionAttr &) - pDataSet->Get(ATTR_PROTECTION, TRUE); - SfxItemState eState = pDataSet->GetItemState(ATTR_PROTECTION, TRUE, NULL); - if(eState == SFX_ITEM_DONTCARE) - return aNULL(); - return uno::makeAny(rProtAttr.GetHideFormula()); - -} -void ScVbaRange::setFormulaHidden(const uno::Any& Hidden) throw ( script::BasicErrorException, css::uno::RuntimeException) -{ - uno::Reference< beans::XPropertySet > xProps(mxRange, ::uno::UNO_QUERY_THROW); - util::CellProtection rCellAttr; - xProps->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CELLPRO))) >>= rCellAttr; - Hidden >>= rCellAttr.IsFormulaHidden; - xProps->setPropertyValue(rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CELLPRO)), uno::makeAny(rCellAttr)); -} - uno::Any ScVbaRange::getShowDetail() throw ( css::uno::RuntimeException) { // #FIXME, If the specified range is in a PivotTable report diff --git a/sc/source/ui/vba/vbarange.hxx b/sc/source/ui/vba/vbarange.hxx index 89ae741c7535..1f161a79d973 100644 --- a/sc/source/ui/vba/vbarange.hxx +++ b/sc/source/ui/vba/vbarange.hxx @@ -57,6 +57,7 @@ class ScTableSheetsObj; class ScCellRangesBase; class ScCellRangeObj; +class ScCellRangesObj; class ScDocShell; class ScDocument; @@ -111,14 +112,16 @@ class ScVbaRange : public ScVbaRange_BASE virtual css::uno::Any getFormulaValue( formula::FormulaGrammar::Grammar ) throw (css::uno::RuntimeException); virtual void setFormulaValue( const css::uno::Any& aValue, formula::FormulaGrammar::Grammar ) throw ( css::uno::RuntimeException); css::uno::Reference< ov::excel::XRange > getArea( sal_Int32 nIndex ) throw( css::uno::RuntimeException ); - ScCellRangesBase* getCellRangesBase() throw ( css::uno::RuntimeException ); ScCellRangeObj* getCellRangeObj( ) throw ( css::uno::RuntimeException ); - SfxItemSet* getCurrentDataSet( ) throw ( css::uno::RuntimeException ); + ScCellRangesObj* getCellRangesObj() throw ( css::uno::RuntimeException ); css::uno::Reference< ov::XCollection >& getBorders(); void groupUnGroup( bool bUnGroup = false ) throw ( css::script::BasicErrorException, css::uno::RuntimeException ); css::uno::Reference< ov::excel::XRange > PreviousNext( bool bIsPrevious ); css::uno::Reference< ov::excel::XRange > SpecialCellsImpl( sal_Int32 nType, const css::uno::Any& _oValue) throw ( css::script::BasicErrorException ); css::awt::Point getPosition() throw ( css::uno::RuntimeException ); +protected: + virtual ScCellRangesBase* getCellRangesBase() throw ( css::uno::RuntimeException ); + virtual SfxItemSet* getCurrentDataSet( ) throw ( css::uno::RuntimeException ); public: ScVbaRange( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::table::XCellRange >& xRange, sal_Bool bIsRows = false, sal_Bool bIsColumns = false ) throw ( css::lang::IllegalArgumentException ); ScVbaRange( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::sheet::XSheetCellRangeContainer >& xRanges, sal_Bool bIsRows = false, sal_Bool bIsColumns = false ) throw ( css::lang::IllegalArgumentException ); @@ -170,10 +173,6 @@ public: virtual css::uno::Any SAL_CALL getPageBreak() throw (css::uno::RuntimeException); virtual void SAL_CALL setPageBreak( const css::uno::Any& _pagebreak ) throw (css::uno::RuntimeException); virtual css::uno::Reference< ov::excel::XValidation > SAL_CALL getValidation() throw (css::uno::RuntimeException); - virtual css::uno::Any SAL_CALL getFormulaHidden() throw (css::script::BasicErrorException, css::uno::RuntimeException); - virtual void SAL_CALL setFormulaHidden(const css::uno::Any& aHidden) throw (css::script::BasicErrorException, css::uno::RuntimeException); - //virtual css::uno::Any SAL_CALL getLocked() throw (css::script::BasicErrorException, css::uno::RuntimeException); - //virtual void SAL_CALL setLocked(const css::uno::Any& aLocked) throw (css::script::BasicErrorException, css::uno::RuntimeException); virtual css::uno::Any SAL_CALL getShowDetail() throw (css::uno::RuntimeException); virtual void SAL_CALL setShowDetail(const css::uno::Any& aShowDetail) throw (css::uno::RuntimeException); // Methods diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx index 406fdab9c824..35befa8f7a36 100755 --- a/sc/source/ui/view/dbfunc3.cxx +++ b/sc/source/ui/view/dbfunc3.cxx @@ -1739,6 +1739,18 @@ void lcl_MoveToEnd( ScDPSaveDimension& rDim, const String& rItemName ) // puts it to the end of the list even if it was in the list before. } +struct ScOUStringCollate +{ + CollatorWrapper* mpCollator; + + ScOUStringCollate(CollatorWrapper* pColl) : mpCollator(pColl) {} + + bool operator()(const rtl::OUString& rStr1, const rtl::OUString& rStr2) const + { + return ( mpCollator->compareString(rStr1, rStr2) < 0 ); + } +}; + bool ScDBFunc::DataPilotSort( const ScAddress& rPos, bool bAscending, sal_uInt16* pUserListId ) { ScDocument* pDoc = GetViewData()->GetDocument(); @@ -1747,7 +1759,8 @@ bool ScDBFunc::DataPilotSort( const ScAddress& rPos, bool bAscending, sal_uInt16 return false; // We need to run this to get all members later. - pDPObj->BuildAllDimensionMembers(); + if ( pUserListId ) + pDPObj->BuildAllDimensionMembers(); USHORT nOrientation; long nDimIndex = pDPObj->GetHeaderDim(rPos, nOrientation); @@ -1766,97 +1779,111 @@ bool ScDBFunc::DataPilotSort( const ScAddress& rPos, bool bAscending, sal_uInt16 if (!pSaveDim) return false; - typedef ScDPSaveDimension::MemberList MemList; - const MemList& rDimMembers = pSaveDim->GetMembers(); - list<OUString> aMembers; - hash_set<OUString, ::rtl::OUStringHash> aMemberSet; - size_t nMemberCount = 0; - for (MemList::const_iterator itr = rDimMembers.begin(), itrEnd = rDimMembers.end(); - itr != itrEnd; ++itr) + // manual evaluation of sort order is only needed if a user list id is given + if ( pUserListId ) { - ScDPSaveMember* pMem = *itr; - aMembers.push_back(pMem->GetName()); - aMemberSet.insert(pMem->GetName()); - ++nMemberCount; - } - - // Sort the member list in ascending order. - aMembers.sort(); + typedef ScDPSaveDimension::MemberList MemList; + const MemList& rDimMembers = pSaveDim->GetMembers(); + list<OUString> aMembers; + hash_set<OUString, ::rtl::OUStringHash> aMemberSet; + size_t nMemberCount = 0; + for (MemList::const_iterator itr = rDimMembers.begin(), itrEnd = rDimMembers.end(); + itr != itrEnd; ++itr) + { + ScDPSaveMember* pMem = *itr; + aMembers.push_back(pMem->GetName()); + aMemberSet.insert(pMem->GetName()); + ++nMemberCount; + } - // Collect and rank those custom sort strings that also exist in the member name list. + // Sort the member list in ascending order. + ScOUStringCollate aCollate( ScGlobal::GetCollator() ); + aMembers.sort(aCollate); - typedef hash_map<OUString, sal_uInt16, OUStringHash> UserSortMap; - UserSortMap aSubStrs; - sal_uInt16 nSubCount = 0; - if (pUserListId) - { - ScUserList* pUserList = ScGlobal::GetUserList(); - if (!pUserList) - return false; + // Collect and rank those custom sort strings that also exist in the member name list. + typedef hash_map<OUString, sal_uInt16, OUStringHash> UserSortMap; + UserSortMap aSubStrs; + sal_uInt16 nSubCount = 0; + if (pUserListId) { - sal_uInt16 n = pUserList->GetCount(); - if (!n || *pUserListId >= n) + ScUserList* pUserList = ScGlobal::GetUserList(); + if (!pUserList) return false; - } - ScUserListData* pData = static_cast<ScUserListData*>((*pUserList)[*pUserListId]); - if (pData) - { - sal_uInt16 n = pData->GetSubCount(); - for (sal_uInt16 i = 0; i < n; ++i) { - OUString aSub = pData->GetSubStr(i); - if (!aMemberSet.count(aSub)) - // This string doesn't exist in the member name set. Don't add this. - continue; + sal_uInt16 n = pUserList->GetCount(); + if (!n || *pUserListId >= n) + return false; + } + + ScUserListData* pData = static_cast<ScUserListData*>((*pUserList)[*pUserListId]); + if (pData) + { + sal_uInt16 n = pData->GetSubCount(); + for (sal_uInt16 i = 0; i < n; ++i) + { + OUString aSub = pData->GetSubStr(i); + if (!aMemberSet.count(aSub)) + // This string doesn't exist in the member name set. Don't add this. + continue; - aSubStrs.insert(UserSortMap::value_type(aSub, nSubCount++)); + aSubStrs.insert(UserSortMap::value_type(aSub, nSubCount++)); + } } } - } - // Rank all members. + // Rank all members. - vector<OUString> aRankedNames(nMemberCount); - sal_uInt16 nCurStrId = 0; - for (list<OUString>::const_iterator itr = aMembers.begin(), itrEnd = aMembers.end(); - itr != itrEnd; ++itr) - { - OUString aName = *itr; - sal_uInt16 nRank = 0; - UserSortMap::const_iterator itrSub = aSubStrs.find(aName); - if (itrSub == aSubStrs.end()) - nRank = nSubCount + nCurStrId++; - else - nRank = itrSub->second; + vector<OUString> aRankedNames(nMemberCount); + sal_uInt16 nCurStrId = 0; + for (list<OUString>::const_iterator itr = aMembers.begin(), itrEnd = aMembers.end(); + itr != itrEnd; ++itr) + { + OUString aName = *itr; + sal_uInt16 nRank = 0; + UserSortMap::const_iterator itrSub = aSubStrs.find(aName); + if (itrSub == aSubStrs.end()) + nRank = nSubCount + nCurStrId++; + else + nRank = itrSub->second; - if (!bAscending) - nRank = static_cast< sal_uInt16 >( nMemberCount - nRank - 1 ); + if (!bAscending) + nRank = static_cast< sal_uInt16 >( nMemberCount - nRank - 1 ); - aRankedNames[nRank] = aName; - } + aRankedNames[nRank] = aName; + } - // Re-order ScDPSaveMember instances with the new ranks. + // Re-order ScDPSaveMember instances with the new ranks. - for (vector<OUString>::const_iterator itr = aRankedNames.begin(), itrEnd = aRankedNames.end(); - itr != itrEnd; ++itr) - { - const ScDPSaveMember* pOldMem = pSaveDim->GetExistingMemberByName(*itr); - if (!pOldMem) - // All members are supposed to be present. - continue; + for (vector<OUString>::const_iterator itr = aRankedNames.begin(), itrEnd = aRankedNames.end(); + itr != itrEnd; ++itr) + { + const ScDPSaveMember* pOldMem = pSaveDim->GetExistingMemberByName(*itr); + if (!pOldMem) + // All members are supposed to be present. + continue; - ScDPSaveMember* pNewMem = new ScDPSaveMember(*pOldMem); - pSaveDim->AddMember(pNewMem); - } + ScDPSaveMember* pNewMem = new ScDPSaveMember(*pOldMem); + pSaveDim->AddMember(pNewMem); + } - // Set the sorting mode to manual for now. We may introduce a new sorting - // mode later on. + // Set the sorting mode to manual for now. We may introduce a new sorting + // mode later on. - sheet::DataPilotFieldSortInfo aSortInfo; - aSortInfo.Mode = sheet::DataPilotFieldSortMode::MANUAL; - pSaveDim->SetSortInfo(&aSortInfo); + sheet::DataPilotFieldSortInfo aSortInfo; + aSortInfo.Mode = sheet::DataPilotFieldSortMode::MANUAL; + pSaveDim->SetSortInfo(&aSortInfo); + } + else + { + // without user list id, just apply sorting mode + + sheet::DataPilotFieldSortInfo aSortInfo; + aSortInfo.Mode = sheet::DataPilotFieldSortMode::NAME; + aSortInfo.IsAscending = bAscending; + pSaveDim->SetSortInfo(&aSortInfo); + } // Update the datapilot with the newly sorted field members. diff --git a/sc/source/ui/view/drawview.cxx b/sc/source/ui/view/drawview.cxx index 311bcf8c24b2..cc09722530ad 100644 --- a/sc/source/ui/view/drawview.cxx +++ b/sc/source/ui/view/drawview.cxx @@ -397,13 +397,13 @@ void ScDrawView::MarkListHasChanged() ScTabViewShell* pViewSh = pViewData->GetViewShell(); - if (!bInConstruct) // nicht wenn die View gerade angelegt wird + // #i110829# remove the cell selection only if drawing objects are selected + if ( !bInConstruct && GetMarkedObjectList().GetMarkCount() ) { - pViewSh->Unmark(); // Selektion auff'm Doc entfernen + pViewSh->Unmark(); // remove cell selection // #65379# end cell edit mode if drawing objects are selected - if ( GetMarkedObjectList().GetMarkCount() ) - SC_MOD()->InputEnterHandler(); + SC_MOD()->InputEnterHandler(); } // IP deaktivieren diff --git a/sc/source/ui/view/editsh.cxx b/sc/source/ui/view/editsh.cxx index d228a205a5a3..848a0a3c7636 100644 --- a/sc/source/ui/view/editsh.cxx +++ b/sc/source/ui/view/editsh.cxx @@ -32,13 +32,16 @@ //------------------------------------------------------------------ +#include <com/sun/star/linguistic2/XThesaurus.hpp> + #include "scitems.hxx" #include <editeng/eeitem.hxx> #include <svx/clipfmtitem.hxx> #include <svx/svxdlg.hxx> #include <editeng/cntritem.hxx> -//CHINA001 #include <svx/chardlg.hxx> +#include <editeng/outliner.hxx> +#include <editeng/unolingu.hxx> #include <editeng/crsditem.hxx> #include <editeng/editeng.hxx> #include <editeng/editview.hxx> @@ -91,6 +94,11 @@ #include "scui_def.hxx" //CHINA001 #include "scabstdlg.hxx" //CHINA001 + + +using namespace ::com::sun::star; + + TYPEINIT1( ScEditShell, SfxShell ); SFX_IMPL_INTERFACE(ScEditShell, SfxShell, ScResId(SCSTR_EDITSHELL)) @@ -213,6 +221,17 @@ void ScEditShell::Execute( SfxRequest& rReq ) } break; + case SID_THES: + { + String aReplaceText; + SFX_REQUEST_ARG( rReq, pItem2, SfxStringItem, SID_THES , sal_False ); + if (pItem2) + aReplaceText = pItem2->GetValue(); + if (aReplaceText.Len() > 0) + ReplaceTextWithSynonym( *pEditView, aReplaceText ); + } + break; + case SID_COPY: pTableView->Copy(); break; @@ -680,6 +699,22 @@ void __EXPORT ScEditShell::GetState( SfxItemSet& rSet ) case SID_INSERT_ZWSP: ScViewUtil::HideDisabledSlot( rSet, pViewData->GetBindings(), nWhich ); break; + + case SID_THES: + { + String aStatusVal; + LanguageType nLang = LANGUAGE_NONE; + bool bIsLookUpWord = GetStatusValueForThesaurusFromContext( aStatusVal, nLang, *pActiveView ); + rSet.Put( SfxStringItem( SID_THES, aStatusVal ) ); + + // disable thesaurus context menu entry if there is nothing to look up + BOOL bCanDoThesaurus = ScModule::HasThesaurusLanguage( nLang ); + if (!bIsLookUpWord || !bCanDoThesaurus) + rSet.DisableItem( SID_THES ); + } + break; + + } nWhich = aIter.NextWhich(); } diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx index b8eeb868809e..87740a88e4df 100644 --- a/sc/source/ui/view/gridwin.cxx +++ b/sc/source/ui/view/gridwin.cxx @@ -165,6 +165,7 @@ private: BOOL bInit; BOOL bCancelled; BOOL bInSelect; + bool mbListHasDates; ULONG nSel; ScFilterBoxMode eMode; @@ -188,6 +189,8 @@ public: BOOL IsInInit() const { return bInit; } void SetCancelled() { bCancelled = TRUE; } BOOL IsInSelect() const { return bInSelect; } + void SetListHasDates(bool b) { mbListHasDates = b; } + bool HasDates() const { return mbListHasDates; } }; //------------------------------------------------------------------- @@ -203,6 +206,7 @@ ScFilterListBox::ScFilterListBox( Window* pParent, ScGridWindow* pGrid, bInit( TRUE ), bCancelled( FALSE ), bInSelect( FALSE ), + mbListHasDates(false), nSel( 0 ), eMode( eNewMode ) { @@ -907,7 +911,9 @@ void ScGridWindow::DoAutoFilterMenue( SCCOL nCol, SCROW nRow, BOOL bDataSelect ) pFilterBox->SetSeparatorPos( nDefCount - 1 ); // get list entries - pDoc->GetFilterEntries( nCol, nRow, nTab, aStrings, true ); + bool bHasDates = false; + pDoc->GetFilterEntries( nCol, nRow, nTab, true, aStrings, bHasDates); + pFilterBox->SetListHasDates(bHasDates); // check widths of numerical entries (string entries are not included) // so all numbers are completely visible @@ -1117,7 +1123,7 @@ void ScGridWindow::FilterSelect( ULONG nSel ) ExecDataSelect( nCol, nRow, aString ); break; case SC_FILTERBOX_FILTER: - ExecFilter( nSel, nCol, nRow, aString ); + ExecFilter( nSel, nCol, nRow, aString, pFilterBox->HasDates() ); break; case SC_FILTERBOX_SCENARIO: pViewData->GetView()->UseScenario( aString ); @@ -1150,7 +1156,7 @@ void ScGridWindow::ExecDataSelect( SCCOL nCol, SCROW nRow, const String& rStr ) void ScGridWindow::ExecFilter( ULONG nSel, SCCOL nCol, SCROW nRow, - const String& aValue ) + const String& aValue, bool bCheckForDates ) { SCTAB nTab = pViewData->GetTabNo(); ScDocument* pDoc = pViewData->GetDocument(); @@ -1222,6 +1228,7 @@ void ScGridWindow::ExecFilter( ULONG nSel, rNewEntry.bDoQuery = TRUE; rNewEntry.bQueryByString = TRUE; rNewEntry.nField = nCol; + rNewEntry.bQueryByDate = bCheckForDates; if ( nSel == SC_AUTOFILTER_TOP10 ) { rNewEntry.eOp = SC_TOPVAL; diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx index 53851f0e3cf0..37bc941c0f16 100644 --- a/sc/source/ui/view/output2.cxx +++ b/sc/source/ui/view/output2.cxx @@ -53,6 +53,7 @@ #include <editeng/udlnitem.hxx> #include <editeng/unolingu.hxx> #include <svl/zforlist.hxx> +#include <svl/zformat.hxx> #include <vcl/svapp.hxx> #include <vcl/metric.hxx> #include <vcl/outdev.hxx> @@ -74,6 +75,8 @@ #include "scmod.hxx" #include "fillinfo.hxx" +#include <boost/ptr_container/ptr_vector.hpp> + #include <math.h> //! Autofilter-Breite mit column.cxx zusammenfassen @@ -108,6 +111,9 @@ class ScDrawStringsVars String aString; // Inhalte Size aTextSize; long nOriginalWidth; + long nMaxDigitWidth; + long nSignWidth; + long nDotWidth; ScBaseCell* pLastCell; ULONG nValueFormat; @@ -132,7 +138,7 @@ public: void SetPatternSimple( const ScPatternAttr* pNew, const SfxItemSet* pSet ); BOOL SetText( ScBaseCell* pCell ); // TRUE -> pOldPattern vergessen - void SetHashText(); + void SetTextToWidthOrHash( ScBaseCell* pCell, long nWidth ); void SetAutoText( const String& rAutoText ); const ScPatternAttr* GetPattern() const { return pPattern; } @@ -161,6 +167,14 @@ public: pCondSet->GetItemState( ATTR_FONT_HEIGHT, TRUE ); } BOOL HasEditCharacters() const; + +private: + void SetHashText(); + long GetMaxDigitWidth(); + long GetSignWidth(); + long GetDotWidth(); + void TextChanged(); + long ConvertWidthLogicToPixel( long nWidth ) const; }; //================================================================== @@ -176,6 +190,9 @@ ScDrawStringsVars::ScDrawStringsVars(ScOutputData* pData, BOOL bPTL) : nIndent ( 0 ), bRotated ( FALSE ), nOriginalWidth( 0 ), + nMaxDigitWidth( 0 ), + nSignWidth( 0 ), + nDotWidth( 0 ), pLastCell ( NULL ), nValueFormat( 0 ), bLineBreak ( FALSE ), @@ -242,6 +259,10 @@ void ScDrawStringsVars::SetShrinkScale( long nScale, BYTE nScript ) void ScDrawStringsVars::SetPattern( const ScPatternAttr* pNew, const SfxItemSet* pSet, ScBaseCell* pCell, BYTE nScript ) { + nMaxDigitWidth = 0; + nSignWidth = 0; + nDotWidth = 0; + pPattern = pNew; pCondSet = pSet; @@ -393,6 +414,9 @@ void ScDrawStringsVars::SetPattern( const ScPatternAttr* pNew, const SfxItemSet* void ScDrawStringsVars::SetPatternSimple( const ScPatternAttr* pNew, const SfxItemSet* pSet ) { + nMaxDigitWidth = 0; + nSignWidth = 0; + nDotWidth = 0; // wird gerufen, wenn sich die Font-Variablen nicht aendern (!StringDiffer) pPattern = pNew; @@ -467,28 +491,7 @@ BOOL ScDrawStringsVars::SetText( ScBaseCell* pCell ) pLastCell = NULL; // naechstes Mal wieder hierherkommen } - OutputDevice* pRefDevice = pOutput->pRefDevice; - OutputDevice* pFmtDevice = pOutput->pFmtDevice; - aTextSize.Width() = pFmtDevice->GetTextWidth( aString ); - aTextSize.Height() = pFmtDevice->GetTextHeight(); - - if ( !pRefDevice->GetConnectMetaFile() || pRefDevice->GetOutDevType() == OUTDEV_PRINTER ) - { - double fMul = pOutput->GetStretch(); - aTextSize.Width() = (long)(aTextSize.Width() / fMul + 0.5); - } - - aTextSize.Height() = aMetric.GetAscent() + aMetric.GetDescent(); - if ( GetOrient() != SVX_ORIENTATION_STANDARD ) - { - long nTemp = aTextSize.Height(); - aTextSize.Height() = aTextSize.Width(); - aTextSize.Width() = nTemp; - } - - nOriginalWidth = aTextSize.Width(); - if ( bPixelToLogic ) - aTextSize = pRefDevice->LogicToPixel( aTextSize ); + TextChanged(); } // sonst String/Groesse behalten } @@ -508,6 +511,82 @@ void ScDrawStringsVars::SetHashText() SetAutoText( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("###")) ); } +void ScDrawStringsVars::SetTextToWidthOrHash( ScBaseCell* pCell, long nWidth ) +{ + if (!pCell) + return; + + CellType eType = pCell->GetCellType(); + if (eType != CELLTYPE_VALUE && eType != CELLTYPE_FORMULA) + // must be a value or formula cell. + return; + + if (eType == CELLTYPE_FORMULA && !static_cast<ScFormulaCell*>(pCell)->IsValue()) + // If it's formula, the result must be a value. + return; + + ULONG nFormat = GetValueFormat(); + if ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) != 0) + { + // Not 'General' number format. Set hash text and bail out. + SetHashText(); + return; + } + + double fVal = (eType == CELLTYPE_VALUE) ? + static_cast<ScValueCell*>(pCell)->GetValue() : static_cast<ScFormulaCell*>(pCell)->GetValue(); + + const SvNumberformat* pNumFormat = pOutput->pDoc->GetFormatTable()->GetEntry(nFormat); + if (!pNumFormat) + return; + + long nMaxDigit = GetMaxDigitWidth(); + sal_uInt16 nNumDigits = static_cast<sal_uInt16>(nWidth / nMaxDigit); + + if (!pNumFormat->GetOutputString(fVal, nNumDigits, aString)) + // Failed to get output string. Bail out. + return; + + sal_uInt8 nSignCount = 0, nDecimalCount = 0; + xub_StrLen nLen = aString.Len(); + sal_Unicode cDecSep = ScGlobal::GetpLocaleData()->getLocaleItem().decimalSeparator.getStr()[0]; + for (xub_StrLen i = 0; i < nLen; ++i) + { + sal_Unicode c = aString.GetChar(i); + if (c == sal_Unicode('-')) + ++nSignCount; + else if (c == cDecSep) + ++nDecimalCount; + } + if (nDecimalCount) + nWidth += (nMaxDigit - GetDotWidth()) * nDecimalCount; + if (nSignCount) + nWidth += (nMaxDigit - GetSignWidth()) * nSignCount; + + if (nDecimalCount || nSignCount) + { + // Re-calculate. + nNumDigits = static_cast<sal_uInt16>(nWidth / nMaxDigit); + if (!pNumFormat->GetOutputString(fVal, nNumDigits, aString)) + // Failed to get output string. Bail out. + return; + } + + long nActualTextWidth = pOutput->pFmtDevice->GetTextWidth(aString); + + if (bPixelToLogic) + nActualTextWidth = ConvertWidthLogicToPixel(nActualTextWidth); + + if (nActualTextWidth > nWidth) + { + // Even after the decimal adjustment the text doesn't fit. Give up. + SetHashText(); + return; + } + + TextChanged(); +} + void ScDrawStringsVars::SetAutoText( const String& rAutoText ) { aString = rAutoText; @@ -538,6 +617,80 @@ void ScDrawStringsVars::SetAutoText( const String& rAutoText ) pLastCell = NULL; // derselbe Text kann in der naechsten Zelle wieder passen } +long ScDrawStringsVars::GetMaxDigitWidth() +{ + if (nMaxDigitWidth > 0) + return nMaxDigitWidth; + + sal_Char cZero = '0'; + for (sal_Char i = 0; i < 10; ++i) + { + sal_Char cDigit = cZero + i; + long n = pOutput->pFmtDevice->GetTextWidth(String(cDigit)); + nMaxDigitWidth = ::std::max(nMaxDigitWidth, n); + } + + if (bPixelToLogic) + nMaxDigitWidth = ConvertWidthLogicToPixel(nMaxDigitWidth); + return nMaxDigitWidth; +} + +long ScDrawStringsVars::GetSignWidth() +{ + if (nSignWidth > 0) + return nSignWidth; + + nSignWidth = pOutput->pFmtDevice->GetTextWidth(String('-')); + if (bPixelToLogic) + nSignWidth = ConvertWidthLogicToPixel(nSignWidth); + return nSignWidth; +} + +long ScDrawStringsVars::GetDotWidth() +{ + if (nDotWidth > 0) + return nDotWidth; + + const ::rtl::OUString& sep = ScGlobal::GetpLocaleData()->getLocaleItem().decimalSeparator; + nDotWidth = pOutput->pFmtDevice->GetTextWidth(sep); + if (bPixelToLogic) + nDotWidth = ConvertWidthLogicToPixel(nDotWidth); + return nDotWidth; +} + +void ScDrawStringsVars::TextChanged() +{ + OutputDevice* pRefDevice = pOutput->pRefDevice; + OutputDevice* pFmtDevice = pOutput->pFmtDevice; + aTextSize.Width() = pFmtDevice->GetTextWidth( aString ); + aTextSize.Height() = pFmtDevice->GetTextHeight(); + + if ( !pRefDevice->GetConnectMetaFile() || pRefDevice->GetOutDevType() == OUTDEV_PRINTER ) + { + double fMul = pOutput->GetStretch(); + aTextSize.Width() = (long)(aTextSize.Width() / fMul + 0.5); + } + + aTextSize.Height() = aMetric.GetAscent() + aMetric.GetDescent(); + if ( GetOrient() != SVX_ORIENTATION_STANDARD ) + { + long nTemp = aTextSize.Height(); + aTextSize.Height() = aTextSize.Width(); + aTextSize.Width() = nTemp; + } + + nOriginalWidth = aTextSize.Width(); + if ( bPixelToLogic ) + aTextSize = pRefDevice->LogicToPixel( aTextSize ); +} + +long ScDrawStringsVars::ConvertWidthLogicToPixel( long nWidth ) const +{ + Size aSize(nWidth, pOutput->pFmtDevice->GetTextHeight()); + aSize = pOutput->pRefDevice->LogicToPixel(aSize); + return aSize.Width(); +} + BOOL ScDrawStringsVars::HasEditCharacters() const { static const sal_Unicode pChars[] = @@ -919,18 +1072,14 @@ BOOL ScOutputData::IsAvailable( SCCOL nX, SCROW nY ) // bCellIsValue: if set, don't extend into empty cells // bBreak: if set, don't extend, and don't set clip marks (but rLeftClip/rRightClip is set) // bOverwrite: if set, also extend into non-empty cells (for rotated text) -// rAlignRect: output: single or merged cell, used for alignment (visual rectangle) -// rClipRect: output: total output area, for clipping (visual) -// rLeftClip: output: need to clip at rClipRect left (visual) edge -// rRightClip: output: same for right +// rParam output: various area parameters. void ScOutputData::GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY, - SCCOL nCellX, SCROW nCellY, long nNeeded, - const ScPatternAttr& rPattern, - USHORT nHorJustify, BOOL bCellIsValue, - BOOL bBreak, BOOL bOverwrite, - Rectangle& rAlignRect, Rectangle& rClipRect, - BOOL& rLeftClip, BOOL& rRightClip ) + SCCOL nCellX, SCROW nCellY, long nNeeded, + const ScPatternAttr& rPattern, + USHORT nHorJustify, bool bCellIsValue, + bool bBreak, bool bOverwrite, + OutputAreaParam& rParam ) { // rThisRowInfo may be for a different row than nCellY, is still used for clip marks RowInfo& rThisRowInfo = pRowInfo[nArrY]; @@ -1009,21 +1158,23 @@ void ScOutputData::GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY --nMergeSizeX; // leave out the grid horizontally, also for alignment (align between grid lines) + rParam.mnColWidth = nMergeSizeX; // store the actual column width. + // // construct the rectangles using logical left/right values (justify is called at the end) // // rAlignRect is the single cell or merged area, used for alignment. - rAlignRect.Left() = nCellPosX; - rAlignRect.Right() = nCellPosX + ( nMergeSizeX - 1 ) * nLayoutSign; - rAlignRect.Top() = nCellPosY; - rAlignRect.Bottom() = nCellPosY + nMergeSizeY - 1; + rParam.maAlignRect.Left() = nCellPosX; + rParam.maAlignRect.Right() = nCellPosX + ( nMergeSizeX - 1 ) * nLayoutSign; + rParam.maAlignRect.Top() = nCellPosY; + rParam.maAlignRect.Bottom() = nCellPosY + nMergeSizeY - 1; // rClipRect is all cells that are used for output. // For merged cells this is the same as rAlignRect, otherwise neighboring cells can also be used. - rClipRect = rAlignRect; + rParam.maClipRect = rParam.maAlignRect; if ( nNeeded > nMergeSizeX ) { SvxCellHorJustify eHorJust = (SvxCellHorJustify)nHorJustify; @@ -1064,7 +1215,7 @@ void ScOutputData::GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY ++nRightX; long nAdd = (long) ( pDoc->GetColWidth( nRightX, nTab ) * nPPTX ); nRightMissing -= nAdd; - rClipRect.Right() += nAdd * nLayoutSign; + rParam.maClipRect.Right() += nAdd * nLayoutSign; if ( rThisRowInfo.nRowNo == nCellY && nRightX >= nX1 && nRightX <= nX2 ) rThisRowInfo.pCellInfo[nRightX].bHideGrid = TRUE; @@ -1078,7 +1229,7 @@ void ScOutputData::GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY --nLeftX; long nAdd = (long) ( pDoc->GetColWidth( nLeftX, nTab ) * nPPTX ); nLeftMissing -= nAdd; - rClipRect.Left() -= nAdd * nLayoutSign; + rParam.maClipRect.Left() -= nAdd * nLayoutSign; } } @@ -1089,22 +1240,22 @@ void ScOutputData::GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY rThisRowInfo.pCellInfo[nRightX+1].nClipMark |= SC_CLIPMARK_RIGHT; bAnyClipped = TRUE; long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX ); - rClipRect.Right() -= nMarkPixel * nLayoutSign; + rParam.maClipRect.Right() -= nMarkPixel * nLayoutSign; } if ( nLeftMissing > 0 && bMarkClipped && nLeftX >= nX1 && nLeftX <= nX2 && !bBreak && !bCellIsValue ) { rThisRowInfo.pCellInfo[nLeftX+1].nClipMark |= SC_CLIPMARK_LEFT; bAnyClipped = TRUE; long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX ); - rClipRect.Left() += nMarkPixel * nLayoutSign; + rParam.maClipRect.Left() += nMarkPixel * nLayoutSign; } - rLeftClip = ( nLeftMissing > 0 ); - rRightClip = ( nRightMissing > 0 ); + rParam.mbLeftClip = ( nLeftMissing > 0 ); + rParam.mbRightClip = ( nRightMissing > 0 ); } else { - rLeftClip = rRightClip = FALSE; + rParam.mbLeftClip = rParam.mbRightClip = FALSE; // leave space for AutoFilter on screen // (for automatic line break: only if not formatting for printer, as in ScColumn::GetNeededSize) @@ -1120,30 +1271,30 @@ void ScOutputData::GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY // content fits even in the remaining area without the filter button // -> align within that remaining area - rAlignRect.Right() -= nFilter * nLayoutSign; - rClipRect.Right() -= nFilter * nLayoutSign; + rParam.maAlignRect.Right() -= nFilter * nLayoutSign; + rParam.maClipRect.Right() -= nFilter * nLayoutSign; // if a number doesn't fit, don't hide part of the number behind the button // -> set clip flags, so "###" replacement is used (but also within the smaller area) if ( !bFit ) - rLeftClip = rRightClip = TRUE; + rParam.mbLeftClip = rParam.mbRightClip = TRUE; } } } // justify both rectangles for alignment calculation, use with DrawText etc. - rAlignRect.Justify(); - rClipRect.Justify(); + rParam.maAlignRect.Justify(); + rParam.maClipRect.Justify(); #if 0 //! Test !!! pDev->Push(); pDev->SetLineColor(); pDev->SetFillColor( COL_LIGHTGREEN ); - pDev->DrawRect( pDev->PixelToLogic(rClipRect) ); - pDev->DrawRect( rClipRect ); // print preview + pDev->DrawRect( pDev->PixelToLogic(rParam.maClipRect) ); + pDev->DrawRect( rParam.maClipRect ); // print preview pDev->Pop(); //! Test !!! #endif @@ -1164,10 +1315,6 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic ) ScDrawStringsVars aVars( this, bPixelToLogic ); - const ScPatternAttr* pOldPattern = NULL; - const SfxItemSet* pOldCondSet = NULL; - BYTE nOldScript = 0; - BOOL bProgress = FALSE; long nInitPosX = nScrX; @@ -1184,15 +1331,19 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic ) --nLoopStartX; // start before nX1 for rest of long text to the left // variables for GetOutputArea + OutputAreaParam aAreaParam; BOOL bCellIsValue = FALSE; - BOOL bLeftClip = FALSE; - BOOL bRightClip = FALSE; long nNeededWidth = 0; - Rectangle aAlignRect; - Rectangle aClipRect; SvxCellHorJustify eOutHorJust = SVX_HOR_JUSTIFY_STANDARD; const ScPatternAttr* pPattern = NULL; const SfxItemSet* pCondSet = NULL; + const ScPatternAttr* pOldPattern = NULL; + const SfxItemSet* pOldCondSet = NULL; + BYTE nOldScript = 0; + + // alternative pattern instances in case we need to modify the pattern + // before processing the cell value. + ::boost::ptr_vector<ScPatternAttr> aAltPatterns; long nPosY = nScrY; for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++) @@ -1330,6 +1481,18 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic ) pCondSet = pDoc->GetCondResult( nCellX, nCellY, nTab ); } + if (pCell->HasValueData() && + static_cast<const SfxBoolItem&>( + pPattern->GetItem(ATTR_LINEBREAK, pCondSet)).GetValue()) + { + // Disable line break when the cell content is numeric. + aAltPatterns.push_back(new ScPatternAttr(*pPattern)); + ScPatternAttr* pAltPattern = &aAltPatterns.back(); + SfxBoolItem aLineBreak(ATTR_LINEBREAK, false); + pAltPattern->GetItemSet().Put(aLineBreak); + pPattern = pAltPattern; + } + BYTE nScript = GetScriptType( pDoc, pCell, pPattern, pCondSet ); if (nScript == 0) nScript = ScGlobal::GetDefaultScriptType(); if ( pPattern != pOldPattern || pCondSet != pOldCondSet || @@ -1360,6 +1523,7 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic ) bNeedEdit = aVars.HasEditCharacters() || (bFormulaCell && ((ScFormulaCell*)pCell)->IsMultilineResult()); } + long nTotalMargin = 0; if (bDoCell && !bNeedEdit) { CellType eCellType = pCell->GetCellType(); @@ -1381,14 +1545,17 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic ) BOOL bRepeat = aVars.IsRepeat() && !bBreak; BOOL bShrink = aVars.IsShrink() && !bBreak && !bRepeat; - long nTotalMargin = (long) ( aVars.GetLeftTotal() * nPPTX ) + - (long) ( aVars.GetMargin()->GetRightMargin() * nPPTX ); + nTotalMargin = + static_cast<long>(aVars.GetLeftTotal() * nPPTX) + + static_cast<long>(aVars.GetMargin()->GetRightMargin() * nPPTX); + nNeededWidth = aVars.GetTextSize().Width() + nTotalMargin; + // GetOutputArea gives justfied rectangles GetOutputArea( nX, nArrY, nPosX, nPosY, nCellX, nCellY, nNeededWidth, - *pPattern, sal::static_int_cast<USHORT>(eOutHorJust), - bCellIsValue || bRepeat || bShrink, bBreak, FALSE, - aAlignRect, aClipRect, bLeftClip, bRightClip ); + *pPattern, sal::static_int_cast<USHORT>(eOutHorJust), + bCellIsValue || bRepeat || bShrink, bBreak, FALSE, + aAreaParam ); if ( bShrink ) { @@ -1398,9 +1565,9 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic ) // DrawEdit is used to vertically scale 90 deg rotated text. bNeedEdit = TRUE; } - else if ( bLeftClip || bRightClip ) // horizontal + else if ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) // horizontal { - long nAvailable = aAlignRect.GetWidth() - nTotalMargin; + long nAvailable = aAreaParam.maAlignRect.GetWidth() - nTotalMargin; long nScaleSize = aVars.GetTextSize().Width(); // without margin if ( nScaleSize > 0 ) // 0 if the text is empty (formulas, number formats) @@ -1424,16 +1591,16 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic ) // If even at half the size the font still isn't rendered smaller, // fall back to normal clipping (showing ### for numbers). if ( nNewSize <= nAvailable ) - bLeftClip = bRightClip = FALSE; + aAreaParam.mbLeftClip = aAreaParam.mbRightClip = FALSE; pOldPattern = NULL; } } } - if ( bRepeat && !bLeftClip && !bRightClip ) + if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip ) { - long nAvailable = aAlignRect.GetWidth() - nTotalMargin; + long nAvailable = aAreaParam.maAlignRect.GetWidth() - nTotalMargin; long nRepeatSize = aVars.GetTextSize().Width(); // without margin // When formatting for the printer, the text sizes don't always add up. // Round down (too few repetitions) rather than exceeding the cell size then: @@ -1457,13 +1624,13 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic ) if ( bBreak ) { if ( aVars.GetOrient() == SVX_ORIENTATION_STANDARD ) - bNeedEdit = ( bLeftClip || bRightClip ); + bNeedEdit = ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ); else { long nHeight = aVars.GetTextSize().Height() + (long)(aVars.GetMargin()->GetTopMargin()*nPPTY) + (long)(aVars.GetMargin()->GetBottomMargin()*nPPTY); - bNeedEdit = ( nHeight > aClipRect.GetHeight() ); + bNeedEdit = ( nHeight > aAreaParam.maClipRect.GetHeight() ); } } } @@ -1479,48 +1646,49 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic ) } if ( bDoCell ) { - if ( bCellIsValue && ( bLeftClip || bRightClip ) ) + if ( bCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) ) { - aVars.SetHashText(); + // Adjust the decimals to fit the available column width. + aVars.SetTextToWidthOrHash(pCell, aAreaParam.mnColWidth - nTotalMargin); nNeededWidth = aVars.GetTextSize().Width() + (long) ( aVars.GetLeftTotal() * nPPTX ) + (long) ( aVars.GetMargin()->GetRightMargin() * nPPTX ); - if ( nNeededWidth <= aClipRect.GetWidth() ) - bLeftClip = bRightClip = FALSE; + if ( nNeededWidth <= aAreaParam.maClipRect.GetWidth() ) + aAreaParam.mbLeftClip = aAreaParam.mbRightClip = FALSE; // If the "###" replacement doesn't fit into the cells, no clip marks // are shown, as the "###" already denotes too little space. // The rectangles from the first GetOutputArea call remain valid. } - long nJustPosX = aAlignRect.Left(); // "justified" - effect of alignment will be added - long nJustPosY = aAlignRect.Top(); - long nAvailWidth = aAlignRect.GetWidth(); - long nOutHeight = aAlignRect.GetHeight(); + long nJustPosX = aAreaParam.maAlignRect.Left(); // "justified" - effect of alignment will be added + long nJustPosY = aAreaParam.maAlignRect.Top(); + long nAvailWidth = aAreaParam.maAlignRect.GetWidth(); + long nOutHeight = aAreaParam.maAlignRect.GetHeight(); - BOOL bOutside = ( aClipRect.Right() < nScrX || aClipRect.Left() >= nScrX + nScrW ); - if ( aClipRect.Left() < nScrX ) + BOOL bOutside = ( aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW ); + if ( aAreaParam.maClipRect.Left() < nScrX ) { - aClipRect.Left() = nScrX; - bLeftClip = TRUE; + aAreaParam.maClipRect.Left() = nScrX; + aAreaParam.mbLeftClip = TRUE; } - if ( aClipRect.Right() > nScrX + nScrW ) + if ( aAreaParam.maClipRect.Right() > nScrX + nScrW ) { - aClipRect.Right() = nScrX + nScrW; //! minus one? - bRightClip = TRUE; + aAreaParam.maClipRect.Right() = nScrX + nScrW; //! minus one? + aAreaParam.mbRightClip = TRUE; } - BOOL bHClip = bLeftClip || bRightClip; + BOOL bHClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip; BOOL bVClip = FALSE; - if ( aClipRect.Top() < nScrY ) + if ( aAreaParam.maClipRect.Top() < nScrY ) { - aClipRect.Top() = nScrY; + aAreaParam.maClipRect.Top() = nScrY; bVClip = TRUE; } - if ( aClipRect.Bottom() > nScrY + nScrH ) + if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH ) { - aClipRect.Bottom() = nScrY + nScrH; //! minus one? + aAreaParam.maClipRect.Bottom() = nScrY + nScrH; //! minus one? bVClip = TRUE; } @@ -1603,27 +1771,27 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic ) if (!bHClip) { - aClipRect.Left() = nScrX; - aClipRect.Right() = nScrX+nScrW; + aAreaParam.maClipRect.Left() = nScrX; + aAreaParam.maClipRect.Right() = nScrX+nScrW; } if (!bVClip) { - aClipRect.Top() = nScrY; - aClipRect.Bottom() = nScrY+nScrH; + aAreaParam.maClipRect.Top() = nScrY; + aAreaParam.maClipRect.Bottom() = nScrY+nScrH; } // aClipRect is not used after SetClipRegion/IntersectClipRegion, // so it can be modified here if (bPixelToLogic) - aClipRect = pRefDevice->PixelToLogic( aClipRect ); + aAreaParam.maClipRect = pRefDevice->PixelToLogic( aAreaParam.maClipRect ); if (bMetaFile) { pDev->Push(); - pDev->IntersectClipRegion( aClipRect ); + pDev->IntersectClipRegion( aAreaParam.maClipRect ); } else - pDev->SetClipRegion( Region( aClipRect ) ); + pDev->SetClipRegion( Region( aAreaParam.maClipRect ) ); } Point aURLStart( nJustPosX, nJustPosY ); // copy before modifying for orientation @@ -1827,7 +1995,7 @@ long lcl_GetEditSize( EditEngine& rEngine, BOOL bWidth, BOOL bSwap, long nAttrRo void ScOutputData::ShrinkEditEngine( EditEngine& rEngine, const Rectangle& rAlignRect, long nLeftM, long nTopM, long nRightM, long nBottomM, BOOL bWidth, USHORT nOrient, long nAttrRotate, BOOL bPixelToLogic, - long& rEngineWidth, long& rEngineHeight, long& rNeededPixel, BOOL& rLeftClip, BOOL& rRightClip ) + long& rEngineWidth, long& rEngineHeight, long& rNeededPixel, bool& rLeftClip, bool& rRightClip ) { if ( !bWidth ) { @@ -2149,10 +2317,7 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic) nPosY = nScrY; } - Rectangle aAlignRect; - Rectangle aClipRect; - BOOL bLeftClip = FALSE; - BOOL bRightClip = FALSE; + OutputAreaParam aAreaParam; // // Initial page size - large for normal text, cell size for automatic line breaks @@ -2167,27 +2332,39 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic) //! handle nArrY == 0 GetOutputArea( nXForPos, nArrYForPos, nPosX, nPosY, nCellX, nCellY, 0, - *pPattern, sal::static_int_cast<USHORT>(eOutHorJust), - bCellIsValue, TRUE, FALSE, - aAlignRect, aClipRect, bLeftClip, bRightClip ); + *pPattern, sal::static_int_cast<USHORT>(eOutHorJust), + bCellIsValue, true, false, aAreaParam ); //! special ScEditUtil handling if formatting for printer if ( eOrient == SVX_ORIENTATION_TOPBOTTOM || eOrient == SVX_ORIENTATION_BOTTOMTOP ) - aPaperSize.Width() = aAlignRect.GetHeight() - nTopM - nBottomM; + aPaperSize.Width() = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM; else - aPaperSize.Width() = aAlignRect.GetWidth() - nLeftM - nRightM; + aPaperSize.Width() = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM; if (bAsianVertical && bBreak) { // add some extra height (default margin value) for safety // as long as GetEditArea isn't used below long nExtraHeight = (long)( 20 * nPPTY ); - aPaperSize.Height() = aAlignRect.GetHeight() - nTopM - nBottomM + nExtraHeight; + aPaperSize.Height() = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM + nExtraHeight; } } if (bPixelToLogic) - pEngine->SetPaperSize(pRefDevice->PixelToLogic(aPaperSize)); + { + Size aLogicSize = pRefDevice->PixelToLogic(aPaperSize); + if ( bBreak && !bAsianVertical && pRefDevice != pFmtDevice ) + { + // #i85342# screen display and formatting for printer, + // use same GetEditArea call as in ScViewData::SetEditEngine + + Fraction aFract(1,1); + Rectangle aUtilRect = ScEditUtil( pDoc, nCellX, nCellY, nTab, Point(0,0), pFmtDevice, + HMM_PER_TWIPS, HMM_PER_TWIPS, aFract, aFract ).GetEditArea( pPattern, FALSE ); + aLogicSize.Width() = aUtilRect.GetWidth(); + } + pEngine->SetPaperSize(aLogicSize); + } else pEngine->SetPaperSize(aPaperSize); @@ -2372,26 +2549,26 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic) { // for break, the first GetOutputArea call is sufficient GetOutputArea( nXForPos, nArrYForPos, nPosX, nPosY, nCellX, nCellY, nNeededPixel, - *pPattern, sal::static_int_cast<USHORT>(eOutHorJust), - bCellIsValue || bRepeat || bShrink, FALSE, FALSE, - aAlignRect, aClipRect, bLeftClip, bRightClip ); + *pPattern, sal::static_int_cast<USHORT>(eOutHorJust), + bCellIsValue || bRepeat || bShrink, false, false, aAreaParam ); if ( bShrink ) { BOOL bWidth = ( eOrient == SVX_ORIENTATION_STANDARD && !bAsianVertical ); - ShrinkEditEngine( *pEngine, aAlignRect, + ShrinkEditEngine( *pEngine, aAreaParam.maAlignRect, nLeftM, nTopM, nRightM, nBottomM, bWidth, sal::static_int_cast<USHORT>(eOrient), 0, bPixelToLogic, - nEngineWidth, nEngineHeight, nNeededPixel, bLeftClip, bRightClip ); + nEngineWidth, nEngineHeight, nNeededPixel, + aAreaParam.mbLeftClip, aAreaParam.mbRightClip ); } - if ( bRepeat && !bLeftClip && !bRightClip && pEngine->GetParagraphCount() == 1 ) + if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip && pEngine->GetParagraphCount() == 1 ) { // First check if twice the space for the formatted text is available // (otherwise just keep it unchanged). long nFormatted = nNeededPixel - nLeftM - nRightM; // without margin - long nAvailable = aAlignRect.GetWidth() - nLeftM - nRightM; + long nAvailable = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM; if ( nAvailable >= 2 * nFormatted ) { // "repeat" is handled with unformatted text (for performance reasons) @@ -2425,7 +2602,7 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic) } } - if ( bCellIsValue && ( bLeftClip || bRightClip ) ) + if ( bCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) ) { pEngine->SetText( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("###")) ); nEngineWidth = (long) pEngine->CalcTextWidth(); @@ -2448,11 +2625,11 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic) } } - long nStartX = aAlignRect.Left(); - long nStartY = aAlignRect.Top(); - long nCellWidth = aAlignRect.GetWidth(); + long nStartX = aAreaParam.maAlignRect.Left(); + long nStartY = aAreaParam.maAlignRect.Top(); + long nCellWidth = aAreaParam.maAlignRect.GetWidth(); long nOutWidth = nCellWidth - 1 - nLeftM - nRightM; - long nOutHeight = aAlignRect.GetHeight() - nTopM - nBottomM; + long nOutHeight = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM; if ( bBreak || eOrient != SVX_ORIENTATION_STANDARD || bAsianVertical ) { @@ -2472,21 +2649,21 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic) nStartX += nLeftM; } - BOOL bOutside = ( aClipRect.Right() < nScrX || aClipRect.Left() >= nScrX + nScrW ); - if ( aClipRect.Left() < nScrX ) + BOOL bOutside = ( aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW ); + if ( aAreaParam.maClipRect.Left() < nScrX ) { - aClipRect.Left() = nScrX; - bLeftClip = TRUE; + aAreaParam.maClipRect.Left() = nScrX; + aAreaParam.mbLeftClip = true; } - if ( aClipRect.Right() > nScrX + nScrW ) + if ( aAreaParam.maClipRect.Right() > nScrX + nScrW ) { - aClipRect.Right() = nScrX + nScrW; //! minus one? - bRightClip = TRUE; + aAreaParam.maClipRect.Right() = nScrX + nScrW; //! minus one? + aAreaParam.mbRightClip = true; } if ( !bHidden && !bOutside ) { - BOOL bClip = bLeftClip || bRightClip; + bool bClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip; BOOL bSimClip = FALSE; if ( bWrapFields ) @@ -2495,14 +2672,14 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic) bClip = TRUE; } - if ( aClipRect.Top() < nScrY ) + if ( aAreaParam.maClipRect.Top() < nScrY ) { - aClipRect.Top() = nScrY; + aAreaParam.maClipRect.Top() = nScrY; bClip = TRUE; } - if ( aClipRect.Bottom() > nScrY + nScrH ) + if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH ) { - aClipRect.Bottom() = nScrY + nScrH; //! minus one? + aAreaParam.maClipRect.Bottom() = nScrY + nScrH; //! minus one? bClip = TRUE; } @@ -2554,8 +2731,8 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic) bAnyClipped = TRUE; long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX ); - if ( aClipRect.Right() - nMarkPixel > aClipRect.Left() ) - aClipRect.Right() -= nMarkPixel; + if ( aAreaParam.maClipRect.Right() - nMarkPixel > aAreaParam.maClipRect.Left() ) + aAreaParam.maClipRect.Right() -= nMarkPixel; } } @@ -2579,9 +2756,9 @@ void ScOutputData::DrawEdit(BOOL bPixelToLogic) // Clip marks are already handled in GetOutputArea if (bPixelToLogic) - aLogicClip = pRefDevice->PixelToLogic( aClipRect ); + aLogicClip = pRefDevice->PixelToLogic( aAreaParam.maClipRect ); else - aLogicClip = aClipRect; + aLogicClip = aAreaParam.maClipRect; if (bClip) // bei bSimClip nur aClipRect initialisieren { @@ -3215,10 +3392,7 @@ void ScOutputData::DrawRotated(BOOL bPixelToLogic) // use GetOutputArea to hide the grid // (clip region is done manually below) - BOOL bLeftClip = FALSE; - BOOL bRightClip = FALSE; - Rectangle aAlignRect; - Rectangle aClipRect; + OutputAreaParam aAreaParam; SCCOL nCellX = nX; SCROW nCellY = nY; @@ -3231,8 +3405,7 @@ void ScOutputData::DrawRotated(BOOL bPixelToLogic) GetOutputArea( nX, nArrY, nCellStartX, nPosY, nCellX, nCellY, nNeededWidth, *pPattern, sal::static_int_cast<USHORT>(eOutHorJust), - FALSE, FALSE, TRUE, - aAlignRect, aClipRect, bLeftClip, bRightClip ); + FALSE, FALSE, TRUE, aAreaParam ); if ( bShrink ) { @@ -3240,19 +3413,19 @@ void ScOutputData::DrawRotated(BOOL bPixelToLogic) pRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width() : nEngineWidth; long nNeededPixel = nPixelWidth + nLeftM + nRightM; - bLeftClip = bRightClip = TRUE; + aAreaParam.mbLeftClip = aAreaParam.mbRightClip = TRUE; // always do height - ShrinkEditEngine( *pEngine, aAlignRect, nLeftM, nTopM, nRightM, nBottomM, + ShrinkEditEngine( *pEngine, aAreaParam.maAlignRect, nLeftM, nTopM, nRightM, nBottomM, FALSE, sal::static_int_cast<USHORT>(eOrient), nAttrRotate, bPixelToLogic, - nEngineWidth, nEngineHeight, nNeededPixel, bLeftClip, bRightClip ); + nEngineWidth, nEngineHeight, nNeededPixel, aAreaParam.mbLeftClip, aAreaParam.mbRightClip ); if ( eRotMode == SVX_ROTATE_MODE_STANDARD ) { // do width only if rotating within the cell (standard mode) - ShrinkEditEngine( *pEngine, aAlignRect, nLeftM, nTopM, nRightM, nBottomM, + ShrinkEditEngine( *pEngine, aAreaParam.maAlignRect, nLeftM, nTopM, nRightM, nBottomM, TRUE, sal::static_int_cast<USHORT>(eOrient), nAttrRotate, bPixelToLogic, - nEngineWidth, nEngineHeight, nNeededPixel, bLeftClip, bRightClip ); + nEngineWidth, nEngineHeight, nNeededPixel, aAreaParam.mbLeftClip, aAreaParam.mbRightClip ); } // nEngineWidth/nEngineHeight is updated in ShrinkEditEngine @@ -3306,19 +3479,19 @@ void ScOutputData::DrawRotated(BOOL bPixelToLogic) } if (bPixelToLogic) - aClipRect = pRefDevice->PixelToLogic( Rectangle( + aAreaParam.maClipRect = pRefDevice->PixelToLogic( Rectangle( Point(nClipStartX,nClipStartY), aClipSize ) ); else - aClipRect = Rectangle(Point(nClipStartX, nClipStartY), + aAreaParam.maClipRect = Rectangle(Point(nClipStartX, nClipStartY), aClipSize ); // Scale = 1 if (bMetaFile) { pDev->Push(); - pDev->IntersectClipRegion( aClipRect ); + pDev->IntersectClipRegion( aAreaParam.maClipRect ); } else - pDev->SetClipRegion( Region( aClipRect ) ); + pDev->SetClipRegion( Region( aAreaParam.maClipRect ) ); } Point aLogicStart; diff --git a/sc/source/ui/view/tabvwsh.cxx b/sc/source/ui/view/tabvwsh.cxx index 06aa294029d9..1733cf2e19b5 100644 --- a/sc/source/ui/view/tabvwsh.cxx +++ b/sc/source/ui/view/tabvwsh.cxx @@ -71,6 +71,7 @@ SFX_IMPL_INTERFACE(ScTabViewShell,SfxViewShell,ScResId(SCSTR_TABVIEWSHELL)) SFX_CHILDWINDOW_REGISTRATION(FID_INPUTLINE_STATUS); SFX_CHILDWINDOW_REGISTRATION(SfxTemplateDialogWrapper::GetChildWindowId()); SFX_CHILDWINDOW_CONTEXT_REGISTRATION(SID_NAVIGATOR); + SFX_CHILDWINDOW_REGISTRATION(SID_TASKPANE); SFX_CHILDWINDOW_REGISTRATION(ScNameDlgWrapper::GetChildWindowId()); SFX_CHILDWINDOW_REGISTRATION(ScSolverDlgWrapper::GetChildWindowId()); SFX_CHILDWINDOW_REGISTRATION(ScOptSolverDlgWrapper::GetChildWindowId()); diff --git a/sc/source/ui/view/viewfun2.cxx b/sc/source/ui/view/viewfun2.cxx index faba1f049695..ea11ee222770 100644 --- a/sc/source/ui/view/viewfun2.cxx +++ b/sc/source/ui/view/viewfun2.cxx @@ -88,6 +88,13 @@ #include "charthelper.hxx" #include "tabbgcolor.hxx" +#include <basic/sbstar.hxx> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/script/XLibraryContainer.hpp> +using namespace com::sun::star; + +// helper func defined in docfunc.cxx +void VBA_DeleteModule( ScDocShell& rDocSh, String& sModuleName ); // STATIC DATA --------------------------------------------------------------- @@ -2142,6 +2149,7 @@ BOOL ScViewFunc::DeleteTables(const SvShorts &TheTabs, BOOL bRecord ) { ScDocShell* pDocSh = GetViewData()->GetDocShell(); ScDocument* pDoc = pDocSh->GetDocument(); + BOOL bVbaEnabled = pDoc ? pDoc->IsInVBAMode() : FALSE; SCTAB nNewTab = TheTabs[0]; int i; WaitObject aWait( GetFrameWin() ); @@ -2214,9 +2222,18 @@ BOOL ScViewFunc::DeleteTables(const SvShorts &TheTabs, BOOL bRecord ) for(i=TheTabs.Count()-1;i>=0;i--) { + String sCodeName; + BOOL bHasCodeName = pDoc->GetCodeName( TheTabs[sal::static_int_cast<USHORT>(i)], sCodeName ); if (pDoc->DeleteTab( TheTabs[sal::static_int_cast<USHORT>(i)], pUndoDoc )) { bDelDone = TRUE; + if( bVbaEnabled ) + { + if( bHasCodeName ) + { + VBA_DeleteModule( *pDocSh, sCodeName ); + } + } pDocSh->Broadcast( ScTablesHint( SC_TAB_DELETED, TheTabs[sal::static_int_cast<USHORT>(i)] ) ); } } diff --git a/sc/source/ui/view/viewutil.cxx b/sc/source/ui/view/viewutil.cxx index f73346398ea1..d887aec8bc5b 100644 --- a/sc/source/ui/view/viewutil.cxx +++ b/sc/source/ui/view/viewutil.cxx @@ -52,6 +52,8 @@ #include <svl/eitem.hxx> #include <com/sun/star/i18n/TransliterationModules.hpp> +#include <com/sun/star/i18n/TransliterationModulesExtra.hpp> + #include "viewutil.hxx" #include "global.hxx" @@ -120,6 +122,15 @@ sal_Int32 ScViewUtil::GetTransliterationType( USHORT nSlotID ) sal_Int32 nType = 0; switch ( nSlotID ) { + case SID_TRANSLITERATE_SENTENCE_CASE: + nType = com::sun::star::i18n::TransliterationModulesExtra::SENTENCE_CASE; + break; + case SID_TRANSLITERATE_TITLE_CASE: + nType = com::sun::star::i18n::TransliterationModulesExtra::TITLE_CASE; + break; + case SID_TRANSLITERATE_TOGGLE_CASE: + nType = com::sun::star::i18n::TransliterationModulesExtra::TOGGLE_CASE; + break; case SID_TRANSLITERATE_UPPER: nType = com::sun::star::i18n::TransliterationModules_LOWERCASE_UPPERCASE; break; |