diff options
-rw-r--r-- | oovbaapi/ooo/vba/excel/XName.idl | 2 | ||||
-rw-r--r-- | sc/inc/nameuno.hxx | 3 | ||||
-rw-r--r-- | sc/source/ui/vba/vbaname.cxx | 115 | ||||
-rw-r--r-- | sc/source/ui/vba/vbaname.hxx | 5 | ||||
-rw-r--r-- | sc/source/ui/vba/vbanames.cxx | 100 |
5 files changed, 145 insertions, 80 deletions
diff --git a/oovbaapi/ooo/vba/excel/XName.idl b/oovbaapi/ooo/vba/excel/XName.idl index 379095b0c0c1..dc6ba1c1ee09 100644 --- a/oovbaapi/ooo/vba/excel/XName.idl +++ b/oovbaapi/ooo/vba/excel/XName.idl @@ -36,7 +36,7 @@ interface XName [attribute] string Name; [attribute] string NameLocal; [attribute] boolean Visible; - [attribute, readonly] string Value; + [attribute] string Value; [attribute, readonly] string RefersTo; [attribute, readonly] string RefersToLocal; [attribute, readonly] string RefersToR1C1; diff --git a/sc/inc/nameuno.hxx b/sc/inc/nameuno.hxx index 61be7bb7b0e9..053627130cbf 100644 --- a/sc/inc/nameuno.hxx +++ b/sc/inc/nameuno.hxx @@ -48,7 +48,7 @@ class ScRangeData; class ScTokenArray; class ScNamedRangesObj; -class ScNamedRangeObj : public ::cppu::WeakImplHelper6< +class SC_DLLPUBLIC ScNamedRangeObj : public ::cppu::WeakImplHelper6< ::com::sun::star::sheet::XNamedRange, ::com::sun::star::sheet::XFormulaTokens, ::com::sun::star::sheet::XCellRangeReferrer, @@ -64,6 +64,7 @@ private: com::sun::star::uno::Reference< com::sun::star::container::XNamed > mxSheet; private: +friend class ScVbaName; ScRangeData* GetRangeData_Impl(); void Modify_Impl( const String* pNewName, const ScTokenArray* pNewTokens, const String* pNewContent, diff --git a/sc/source/ui/vba/vbaname.cxx b/sc/source/ui/vba/vbaname.cxx index 815b8b7bb9b9..9721b73ed5d2 100644 --- a/sc/source/ui/vba/vbaname.cxx +++ b/sc/source/ui/vba/vbaname.cxx @@ -30,6 +30,9 @@ #include <vcl/msgbox.hxx> #include "tabvwsh.hxx" #include "viewdata.hxx" +#include "nameuno.hxx" +#include "compiler.hxx" +#include "tokenarray.hxx" using namespace ::ooo::vba; using namespace ::com::sun::star; @@ -92,81 +95,64 @@ ScVbaName::setVisible( sal_Bool /*bVisible*/ ) throw (css::uno::RuntimeException { } -OUString -ScVbaName::getValue() throw (css::uno::RuntimeException) +OUString ScVbaName::getContent( const formula::FormulaGrammar::Grammar eGrammar, bool bPrependEquals ) { - OUString sValue = mxNamedRange->getContent(); - OUString sSheetName = getWorkSheet()->getName(); - OUString sSegmentation = OUString::createFromAscii( ";" ); - OUString sNewSegmentation = OUString::createFromAscii( "," ); - OUString sResult; - sal_Int32 nFrom = 0; - sal_Int32 nTo = 0; - nTo = sValue.indexOf( sSegmentation, nFrom ); - while ( nTo != -1 ) + ScNamedRangeObj* pNamedRange = dynamic_cast< ScNamedRangeObj* >( mxNamedRange.get() ); + OUString aContent; + if ( pNamedRange ) { - OUString sTmpValue = sValue.copy( nFrom, nTo - nFrom ); - if ( sTmpValue.toChar() == '$' ) - { - OUString sTmp = sTmpValue.copy( 1 ); - sTmp = sTmp.replaceAt(0, OUString(sSheetName + OUString::createFromAscii(".")).getLength(), sSheetName + OUString::createFromAscii("!")); - sResult += sTmp; - sResult += sNewSegmentation; - } - nFrom = nTo + 1; - nTo = sValue.indexOf( sSegmentation, nFrom ); + ScRangeData* pData = pNamedRange->GetRangeData_Impl(); + if (pData) + pData->GetSymbol( aContent, eGrammar ); } - OUString sTmpValue = sValue.copy( nFrom ); - if ( sTmpValue.toChar() == '$' ) + if ( bPrependEquals ) { - OUString sTmp = sTmpValue.copy(1); - sTmp = sTmp.replaceAt(0, OUString(sSheetName + OUString::createFromAscii(".")).getLength(), sSheetName + OUString::createFromAscii("!")); - sResult += sTmp; + if (aContent.indexOf('=') != 0) + aContent = OUString::createFromAscii("=") + aContent; } - if (sResult.indexOf('=') != 0) - { - sResult = OUString::createFromAscii("=") + sResult; - } - return sResult; + return aContent; } -void -ScVbaName::setValue( const OUString & rValue ) throw (css::uno::RuntimeException) +void ScVbaName::setContent( const OUString& rContent, const formula::FormulaGrammar::Grammar eGrammar, bool bRemoveEquals ) { - OUString sSheetName = getWorkSheet()->getName(); - OUString sValue = rValue; - OUString sSegmentation = OUString::createFromAscii( "," ); - OUString sNewSegmentation = OUString::createFromAscii( ";" ); - OUString sResult; - sal_Int32 nFrom = 0; - sal_Int32 nTo = 0; - if (sValue.indexOf('=') == 0) + OUString sContent( rContent ); + if ( bRemoveEquals ) { - OUString sTmp = sValue.copy(1); - sValue = sTmp; + if (sContent.indexOf('=') == 0) + sContent = sContent.copy(1); } - nTo = sValue.indexOf( sSegmentation, nFrom ); - while ( nTo != -1 ) + ScNamedRangeObj* pNamedRange = dynamic_cast< ScNamedRangeObj* >( mxNamedRange.get() ); + + // We should be able to do the below by just setting calling SetCode on pNamedRange + // right? + if ( pNamedRange && pNamedRange->pDocShell ) { - OUString sTmpValue = sValue.copy( nFrom, nTo - nFrom ); - sTmpValue = sTmpValue.replaceAt(0, OUString(sSheetName + OUString::createFromAscii("!")).getLength(), sSheetName + OUString::createFromAscii(".")); - if (sTmpValue.copy(0, sSheetName.getLength()).equals(sSheetName)) + + ScDocument* pDoc = pNamedRange->pDocShell->GetDocument(); + ScRangeData* pOldData = pNamedRange->GetRangeData_Impl(); + if (pOldData) { - sTmpValue = OUString::createFromAscii("$") + sTmpValue; + // Shorter way of doing this ? + ScCompiler aComp( pDoc, pOldData->GetPos() ); + aComp.SetGrammar( eGrammar ); + ScTokenArray aArray(*aComp.CompileString( sContent ) ); + pOldData->SetCode( aArray ); } - sTmpValue += sNewSegmentation; - sResult += sTmpValue; - nFrom = nTo + 1; - nTo = sValue.indexOf( sSegmentation, nFrom ); } - OUString sTmpValue = sValue.copy( nFrom ); - sTmpValue = sTmpValue.replaceAt(0, OUString(sSheetName + OUString::createFromAscii("!")).getLength(), sSheetName + OUString::createFromAscii(".")); - if (sTmpValue.copy(0, sSheetName.getLength()).equals(sSheetName)) - { - sTmpValue = OUString::createFromAscii("$") + sTmpValue; - } - sResult += sTmpValue; - mxNamedRange->setContent(sResult); +} + +OUString +ScVbaName::getValue() throw (css::uno::RuntimeException) +{ + rtl::OUString sResult = getContent( formula::FormulaGrammar::GRAM_NATIVE_XL_A1, true ); + + return sResult; +} + +void +ScVbaName::setValue( const OUString & rValue ) throw (css::uno::RuntimeException) +{ + setContent( rValue, formula::FormulaGrammar::GRAM_NATIVE_XL_A1, true ); } OUString @@ -196,19 +182,20 @@ ScVbaName::setRefersToLocal( const OUString & rRefersTo ) throw (css::uno::Runti OUString ScVbaName::getRefersToR1C1() throw (css::uno::RuntimeException) { - return getRefersTo(); + rtl::OUString sResult = getContent( formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1, true ); + return sResult; } void ScVbaName::setRefersToR1C1( const OUString & rRefersTo ) throw (css::uno::RuntimeException) { - setRefersTo( rRefersTo ); + setContent( rRefersTo, formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1, true ); } OUString ScVbaName::getRefersToR1C1Local() throw (css::uno::RuntimeException) { - return getRefersTo(); + return getRefersToR1C1(); } void diff --git a/sc/source/ui/vba/vbaname.hxx b/sc/source/ui/vba/vbaname.hxx index 971c91fb7d7d..505f825f4cb8 100644 --- a/sc/source/ui/vba/vbaname.hxx +++ b/sc/source/ui/vba/vbaname.hxx @@ -24,7 +24,7 @@ #include <com/sun/star/sheet/XNamedRanges.hpp> #include <vbahelper/vbahelperinterface.hxx> - +#include <formula/grammar.hxx> class ScDocument; typedef InheritedHelperInterfaceImpl1< ov::excel::XName > NameImpl_BASE; @@ -34,7 +34,8 @@ class ScVbaName : public NameImpl_BASE css::uno::Reference< css::frame::XModel > mxModel; css::uno::Reference< css::sheet::XNamedRange > mxNamedRange; css::uno::Reference< css::sheet::XNamedRanges > mxNames; - + OUString getContent( const formula::FormulaGrammar::Grammar eGrammar, bool prependEquals = true ); + void setContent( const OUString& sContent, const formula::FormulaGrammar::Grammar eGrammar, bool removeEquals = true ); protected: virtual css::uno::Reference< css::frame::XModel > getModel() { return mxModel; } virtual css::uno::Reference< ov::excel::XWorksheet > getWorkSheet() throw (css::uno::RuntimeException); diff --git a/sc/source/ui/vba/vbanames.cxx b/sc/source/ui/vba/vbanames.cxx index 5c44fbb9fd03..9cf542bbbaab 100644 --- a/sc/source/ui/vba/vbanames.cxx +++ b/sc/source/ui/vba/vbanames.cxx @@ -30,6 +30,9 @@ #include <vcl/msgbox.hxx> #include "tabvwsh.hxx" #include "viewdata.hxx" +#include "compiler.hxx" +#include "tokenarray.hxx" +#include "cellsuno.hxx" using namespace ::ooo::vba; using namespace ::com::sun::star; @@ -117,36 +120,109 @@ ScVbaNames::Add( const css::uno::Any& Name , uno::Reference< uno::XInterface >() ); } } + uno::Reference< table::XCellRange > xUnoRange; if ( RefersTo.hasValue() || RefersToR1C1.hasValue() || RefersToR1C1Local.hasValue() ) { + OUString sFormula; + + formula::FormulaGrammar::Grammar eGram = formula::FormulaGrammar::GRAM_NATIVE_XL_A1; if ( RefersTo.hasValue() ) - RefersTo >>= xRange; + { + if ( RefersTo.getValueTypeClass() == uno::TypeClass_STRING ) + RefersTo >>= sFormula; + else + RefersTo >>= xRange; + } if ( RefersToR1C1.hasValue() ) - RefersToR1C1 >>= xRange; + { + if ( RefersToR1C1.getValueTypeClass() == uno::TypeClass_STRING ) + { + RefersToR1C1 >>= sFormula; + eGram = formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1; + } + else + RefersToR1C1 >>= xRange; + } if ( RefersToR1C1Local.hasValue() ) - RefersToR1C1Local >>= xRange; + { + if ( RefersToR1C1Local.getValueTypeClass() == uno::TypeClass_STRING ) + { + RefersToR1C1Local >>= sFormula; + eGram = formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1; + } + else + RefersToR1C1Local >>= xRange; + } + if ( !xRange.is() && !sFormula.isEmpty() ) + { + ScAddress aBlank; + ScCompiler aComp( getScDocument(), aBlank ); + aComp.SetGrammar( eGram ); + ScTokenArray* pTokens = aComp.CompileString( sFormula ); + if ( pTokens ) + { + ScRange aRange; + ScDocShell* pDocSh = excel::getDocShell(getModel()); + if ( pTokens->IsValidReference( aRange ) ) + xUnoRange = new ScCellRangeObj( pDocSh, aRange ); + else + { + // assume it's an address try strip the '=' if it's there + // and try and create a range ( must be a better way ) + if ( sFormula.startsWith("=") ) + sFormula = sFormula.copy(1); + ScRangeList aCellRanges; + sal_uInt16 nFlags = 0; + + formula::FormulaGrammar::AddressConvention eConv = ( eGram == formula::FormulaGrammar::GRAM_NATIVE_XL_A1 ) ? formula::FormulaGrammar::CONV_XL_A1 : formula::FormulaGrammar::CONV_XL_R1C1; + if ( ScVbaRange::getCellRangesForAddress( nFlags, sFormula, pDocSh, aCellRanges, eConv , ',' ) ) + { + if ( aCellRanges.size() == 1 ) + xUnoRange = new ScCellRangeObj( pDocSh, *aCellRanges.front() ); + else + { + uno::Reference< sheet::XSheetCellRangeContainer > xRanges( new ScCellRangesObj( pDocSh, aCellRanges ) ); + xRange = new ScVbaRange( mxParent, mxContext, xRanges ); + } + } + + } + } + } } - if ( xRange.is() ) + if ( xRange.is() || xUnoRange.is() ) { - ScVbaRange* pRange = dynamic_cast< ScVbaRange* >( xRange.get() ); - uno::Reference< table::XCellRange > thisRange ; - uno::Any xAny = pRange->getCellRange() ; - if ( xAny.hasValue() ) - xAny >>= thisRange; - uno::Reference< sheet::XCellRangeAddressable > thisRangeAdd( thisRange, ::uno::UNO_QUERY_THROW); + if ( !xRange.is() ) + xRange = new ScVbaRange( mxParent, mxContext, xUnoRange ); + + uno::Reference< excel::XRange > xArea( xRange->Areas( uno::makeAny( 1 ) ), uno::UNO_QUERY ); + uno::Any xAny = xArea->getCellRange() ; + + uno::Reference< sheet::XCellRangeAddressable > thisRangeAdd( xAny, ::uno::UNO_QUERY_THROW); + table::CellRangeAddress aAddr = thisRangeAdd->getRangeAddress(); ScAddress aPos( static_cast< SCCOL >( aAddr.StartColumn ) , static_cast< SCROW >( aAddr.StartRow ) , static_cast< SCTAB >(aAddr.Sheet ) ); uno::Any xAny2 ; - String sRangeAdd = xRange->Address( xAny2, xAny2 , xAny2 , xAny2, xAny2 ); if ( mxNames.is() ) { RangeType nType = RT_NAME; table::CellAddress aCellAddr( aAddr.Sheet , aAddr.StartColumn , aAddr.StartRow ); if ( mxNames->hasByName( sName ) ) mxNames->removeByName(sName); - OUString sTmp = "$" + xRange->getWorksheet()->getName() + "." + sRangeAdd; + OUString sTmp = "$"; + uno::Reference< ov::XCollection > xCol( xRange->Areas( uno::Any() ), uno::UNO_QUERY ); + for ( sal_Int32 nArea = 1; nArea <= xCol->getCount(); ++nArea ) + { + xArea.set( xRange->Areas( uno::makeAny( nArea ) ), uno::UNO_QUERY_THROW ); + + String sRangeAdd = xArea->Address( xAny2, xAny2 , xAny2 , xAny2, xAny2 ); + if ( nArea > 1 ) + sTmp += ","; + sTmp = sTmp + "'" + xRange->getWorksheet()->getName() + "'." + sRangeAdd; + } mxNames->addNewByName( sName , sTmp , aCellAddr , (sal_Int32)nType); + return Item( uno::makeAny( sName ), uno::Any() ); } } return css::uno::Any(); |