Commits

Anonymous committed d290a8d

mib19: #163664# text values for VBA range Value property must be parsed (always English)

Comments (0)

Files changed (5)

sc/inc/cellsuno.hxx

 	const ScPatternAttr*	GetCurrentAttrsFlat();
 	const ScPatternAttr*	GetCurrentAttrsDeep();
 	SfxItemSet*				GetCurrentDataSet(bool bNoDflt = false);
-	const ScMarkData*		GetMarkData();
     void                    ForgetMarkData();
 	void					ForgetCurrentAttrs();
 
 									const ScAddress* pLastPos);
 
 protected:
+    const ScMarkData*       GetMarkData();
+
 	// GetItemPropertyMap for derived classes must contain all entries, including base class
 	virtual const SfxItemPropertyMap* GetItemPropertyMap();
 	virtual ::com::sun::star::beans::PropertyState GetOnePropertyState(
                                 const ::rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar );
 	const ScAddress&		GetPosition() const { return aCellPos; }
 
+    SC_DLLPUBLIC void       InputEnglishString( const ::rtl::OUString& rText );
+
 							// XText
 	virtual void SAL_CALL	insertTextContent( const ::com::sun::star::uno::Reference<
 									::com::sun::star::text::XTextRange >& xRange,

sc/source/ui/docshell/docfunc.cxx

 
 
 ScBaseCell* ScDocFunc::InterpretEnglishString( const ScAddress& rPos,
-        const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
+        const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar, short* pRetFormatType )
 {
 	ScDocument* pDoc = rDocShell.GetDocument();
 	ScBaseCell* pNewCell = NULL;
 		sal_uInt32 nEnglish = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
 		double fVal;
 		if ( pFormatter->IsNumberFormat( rText, nEnglish, fVal ) )
+        {
 			pNewCell = new ScValueCell( fVal );
+            // return the format type from the English format, so a localized format can be created
+            if ( pRetFormatType )
+                *pRetFormatType = pFormatter->GetType( nEnglish );
+        }
 		else if ( rText.Len() )
 			pNewCell = ScBaseCell::CreateTextCell( rText, pDoc );
 

sc/source/ui/inc/docfunc.hxx

 
 					// creates a new cell for use with PutCell
 	ScBaseCell*		InterpretEnglishString( const ScAddress& rPos, const String& rText,
-                        const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar );
+                        const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar,
+                        short* pRetFormatType = NULL );
 
 	bool			ShowNote( const ScAddress& rPos, bool bShow = true );
 	inline bool		HideNote( const ScAddress& rPos ) { return ShowNote( rPos, false ); }

sc/source/ui/unoobj/cellsuno.cxx

     }
 }
 
+void ScCellObj::InputEnglishString( const ::rtl::OUString& rText )
+{
+    // This is like a mixture of setFormula and property FormulaLocal:
+    // The cell's number format is checked for "text", a new cell format may be set,
+    // but all parsing is in English.
+
+    ScDocShell* pDocSh = GetDocShell();
+    if ( pDocSh )
+    {
+        String aString(rText);
+        ScDocument* pDoc = pDocSh->GetDocument();
+        SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
+        sal_uInt32 nOldFormat = pDoc->GetNumberFormat( aCellPos );
+        if ( pFormatter->GetType( nOldFormat ) == NUMBERFORMAT_TEXT )
+        {
+            SetString_Impl(aString, FALSE, FALSE);      // text cell
+        }
+        else
+        {
+            ScDocFunc aFunc(*pDocSh);
+            short nFormatType = 0;
+            ScBaseCell* pNewCell = aFunc.InterpretEnglishString( aCellPos, aString,
+                                    EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1, &nFormatType );
+            if (pNewCell)
+            {
+                if ( ( nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET ) == 0 && nFormatType != 0 )
+                {
+                    // apply a format for the recognized type and the old format's language
+                    sal_uInt32 nNewFormat = ScGlobal::GetStandardFormat( *pFormatter, nOldFormat, nFormatType );
+                    if ( nNewFormat != nOldFormat )
+                    {
+                        ScPatternAttr aPattern( pDoc->GetPool() );
+                        aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) );
+                        // ATTR_LANGUAGE_FORMAT remains unchanged
+                        aFunc.ApplyAttributes( *GetMarkData(), aPattern, TRUE, TRUE );
+                    }
+                }
+                // put the cell into the document
+                // (after applying the format, so possible formula recalculation already uses the new format)
+                (void)aFunc.PutCell( aCellPos, pNewCell, TRUE );
+            }
+            else
+                SetString_Impl(aString, FALSE, FALSE);      // no cell from InterpretEnglishString, probably empty string
+        }
+    }
+}
+
 //	XText
 
 uno::Reference<text::XTextCursor> SAL_CALL ScCellObj::createTextCursor()

sc/source/ui/vba/vbarange.cxx

 			rtl::OUString aString;
 			if ( aValue >>= aString )
 			{
-				uno::Reference< text::XTextRange > xTextRange( xCell, uno::UNO_QUERY_THROW );
-				xTextRange->setString( aString );
+                // The required behavior for a string value is:
+                // 1. If the first character is a single quote, use the rest as a string cell, regardless of the cell's number format.
+                // 2. Otherwise, if the cell's number format is "text", use the string value as a string cell.
+                // 3. Otherwise, parse the string value in English locale, and apply a corresponding number format with the cell's locale
+                //    if the cell's number format was "General".
+                // Case 1 is handled here, the rest in ScCellObj::InputEnglishString
+
+                if ( aString.toChar() == '\'' )     // case 1 - handle with XTextRange
+                {
+                    rtl::OUString aRemainder( aString.copy(1) );    // strip the quote
+                    uno::Reference< text::XTextRange > xTextRange( xCell, uno::UNO_QUERY_THROW );
+                    xTextRange->setString( aRemainder );
+                }
+                else
+                {
+                    // call implementation method InputEnglishString
+                    ScCellObj* pCellObj = dynamic_cast< ScCellObj* >( xCell.get() );
+                    if ( pCellObj )
+                        pCellObj->InputEnglishString( aString );
+                }
 			}
 			else
 				isExtracted = false;