sc/inc/cellform.hxx                        |   14 -
 sc/inc/column.hxx                          |    6 
 sc/inc/compiler.hxx                        |   11 -
 sc/inc/document.hxx                        |    4 
 sc/inc/dpcache.hxx                         |    7 
 sc/inc/formulacell.hxx                     |    4 
 sc/inc/global.hxx                          |    5 
 sc/inc/interpretercontext.hxx              |  101 ++++++++---
 sc/inc/patattr.hxx                         |    2 
 sc/inc/queryevaluator.hxx                  |    5 
 sc/inc/queryparam.hxx                      |    4 
 sc/inc/rangeseq.hxx                        |    4 
 sc/inc/scmatrix.hxx                        |    6 
 sc/inc/stringutil.hxx                      |    4 
 sc/inc/table.hxx                           |    2 
 sc/qa/unit/helper/csv_handler.hxx          |    6 
 sc/source/core/data/column2.cxx            |   24 +-
 sc/source/core/data/column3.cxx            |   41 ++--
 sc/source/core/data/column4.cxx            |    8 
 sc/source/core/data/dociter.cxx            |    7 
 sc/source/core/data/documen6.cxx           |    4 
 sc/source/core/data/document.cxx           |    6 
 sc/source/core/data/dpcache.cxx            |   57 ++----
 sc/source/core/data/dpobject.cxx           |   17 -
 sc/source/core/data/formulacell.cxx        |   23 +-
 sc/source/core/data/global.cxx             |    9 
 sc/source/core/data/global2.cxx            |   18 -
 sc/source/core/data/patattr.cxx            |   29 +++
 sc/source/core/data/queryevaluator.cxx     |    6 
 sc/source/core/data/queryiter.cxx          |    9 
 sc/source/core/data/table2.cxx             |    4 
 sc/source/core/data/table5.cxx             |    4 
 sc/source/core/inc/interpre.hxx            |    1 
 sc/source/core/tool/cellform.cxx           |   28 +--
 sc/source/core/tool/compiler.cxx           |   30 +--
 sc/source/core/tool/interpr1.cxx           |   52 ++---
 sc/source/core/tool/interpr2.cxx           |   54 ++---
 sc/source/core/tool/interpr4.cxx           |   17 -
 sc/source/core/tool/interpr5.cxx           |    6 
 sc/source/core/tool/interpr6.cxx           |    2 
 sc/source/core/tool/interpr8.cxx           |   20 +-
 sc/source/core/tool/interpretercontext.cxx |  266 ++++++++++++++++++++++++++---
 sc/source/core/tool/queryparam.cxx         |    9 
 sc/source/core/tool/rangecache.cxx         |    2 
 sc/source/core/tool/rangeseq.cxx           |    7 
 sc/source/core/tool/scmatrix.cxx           |   34 +--
 sc/source/core/tool/stringutil.cxx         |    9 
 sc/source/filter/excel/xicontent.cxx       |    6 
 sc/source/filter/html/htmlexp.cxx          |    2 
 sc/source/filter/rtf/rtfexp.cxx            |    2 
 sc/source/filter/xml/xmlcelli.cxx          |    2 
 sc/source/filter/xml/xmlexprt.cxx          |    4 
 sc/source/ui/app/scmod.cxx                 |    2 
 sc/source/ui/app/transobj.cxx              |    6 
 sc/source/ui/docshell/docfunc.cxx          |    2 
 sc/source/ui/docshell/docsh.cxx            |   18 -
 sc/source/ui/docshell/docsh8.cxx           |   16 -
 sc/source/ui/docshell/impex.cxx            |    8 
 sc/source/ui/unoobj/cellsuno.cxx           |   25 +-
 sc/source/ui/unoobj/textuno.cxx            |    2 
 sc/source/ui/view/output2.cxx              |    6 
 sc/source/ui/view/spelleng.cxx             |    3 
 sc/source/ui/view/tabvwsha.cxx             |   22 +-
 svl/source/numbers/zforlist.cxx            |    2 
 64 files changed, 699 insertions(+), 417 deletions(-)

New commits:
commit b38974391e8d4bf0d450abfaa86bbccbe1022995
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Fri Mar 22 09:47:47 2024 +0000
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Sat Mar 23 01:14:13 2024 +0100

    Related: tdf#160056 do calc NumberFormatting via ScInterpreterContext
    
    and for the duration of Threaded calculation where there will be
    no new formats required we can drive number formatting with the
    unlocked RO policy.
    
    Change-Id: Ic0e449acdcf834bc569d13b4a984f13c55316801
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165160
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sc/inc/cellform.hxx b/sc/inc/cellform.hxx
index 7fb072ee8578..a4a985e2d9cc 100644
--- a/sc/inc/cellform.hxx
+++ b/sc/inc/cellform.hxx
@@ -23,10 +23,10 @@
 #include <rtl/ustring.hxx>
 #include <svl/sharedstring.hxx>
 
-class SvNumberFormatter;
 class Color;
-class ScDocument;
 class ScAddress;
+class ScDocument;
+struct ScInterpreterContext;
 struct ScRefCellValue;
 
 class SC_DLLPUBLIC ScCellFormat
@@ -35,25 +35,25 @@ public:
 
     static OUString GetString(
         const ScRefCellValue& rCell, sal_uInt32 nFormat,
-        const Color** ppColor, SvNumberFormatter& rFormatter, const 
ScDocument& rDoc, bool bNullVals = true,
+        const Color** ppColor, ScInterpreterContext* pContext, const 
ScDocument& rDoc, bool bNullVals = true,
         bool bFormula  = false, bool bUseStarFormat = false );
 
     static OUString GetString(
         ScDocument& rDoc, const ScAddress& rPos, sal_uInt32 nFormat,
-        const Color** ppColor, SvNumberFormatter& rFormatter, bool bNullVals = 
true,
+        const Color** ppColor, ScInterpreterContext* pContext, bool bNullVals 
= true,
         bool bFormula  = false );
 
     // Note that if pShared is set and a value is returned that way, the 
returned OUString is empty.
     static OUString GetInputString(
-        const ScRefCellValue& rCell, sal_uInt32 nFormat, SvNumberFormatter& 
rFormatter,
+        const ScRefCellValue& rCell, sal_uInt32 nFormat, ScInterpreterContext* 
pContext,
         const ScDocument& rDoc, const svl::SharedString** pShared = nullptr, 
bool bFiltering = false,
         bool bForceSystemLocale = false );
 
     static OUString GetInputString(
-        const ScRefCellValue& rCell, sal_uInt32 nFormat, SvNumberFormatter& 
rFormatter,
+        const ScRefCellValue& rCell, sal_uInt32 nFormat, ScInterpreterContext* 
pContext,
         const ScDocument& rDoc, bool bFiltering, bool bForceSystemLocale = 
false )
     {
-        return GetInputString( rCell, nFormat, rFormatter, rDoc, nullptr, 
bFiltering, bForceSystemLocale );
+        return GetInputString( rCell, nFormat, pContext, rDoc, nullptr, 
bFiltering, bForceSystemLocale );
     }
 
     static OUString GetOutputString(
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 0aa812f038a2..bee768873a8e 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -446,10 +446,10 @@ public:
     void SetValue( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, double 
fVal, bool bBroadcast = true );
     void        SetError( SCROW nRow, const FormulaError nError);
 
-    OUString    GetString( SCROW nRow, const ScInterpreterContext* pContext = 
nullptr ) const
+    OUString    GetString( SCROW nRow, ScInterpreterContext* pContext = 
nullptr ) const
         { return GetString( GetCellValue( nRow ), nRow, pContext ); }
     OUString    GetString( sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow,
-                           const ScInterpreterContext* pContext = nullptr ) 
const
+                           ScInterpreterContext* pContext = nullptr ) const
         { return GetString( GetCellValue( rBlockPos, nRow ), nRow, pContext ); 
}
     double* GetValueCell( SCROW nRow );
     // Note that if pShared is set and a value is returned that way, the 
returned OUString is empty.
@@ -831,7 +831,7 @@ private:
         sc::CellStoreType::const_iterator& itPos, SCROW nRow, bool bForward) 
const;
     SCROW FindNextVisibleRow(SCROW nRow, bool bForward) const;
 
-    OUString GetString( const ScRefCellValue& cell, SCROW nRow, const 
ScInterpreterContext* pContext = nullptr ) const;
+    OUString GetString( const ScRefCellValue& cell, SCROW nRow, 
ScInterpreterContext* pContext = nullptr ) const;
     OUString GetInputString( const ScRefCellValue& cell, SCROW nRow, bool 
bForceSystemLocale = false ) const;
 
     /**
diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx
index df2ad5eb71c9..af379104bca7 100644
--- a/sc/inc/compiler.hxx
+++ b/sc/inc/compiler.hxx
@@ -274,8 +274,7 @@ private:
     ScDocument& rDoc;
     ScAddress   aPos;
 
-    SvNumberFormatter* mpFormatter;
-    const ScInterpreterContext* mpInterpreterContext;
+    ScInterpreterContext& mrInterpreterContext;
 
     SCTAB       mnCurrentSheetTab;      // indicates current sheet number 
parsed so far
     sal_Int32   mnCurrentSheetEndPos;   // position after current sheet name 
if parsed
@@ -384,22 +383,22 @@ public:
 
 public:
     ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& rPos,
-            bool bComputeII = false, bool bMatrixFlag = false, const 
ScInterpreterContext* pContext = nullptr );
+            bool bComputeII = false, bool bMatrixFlag = false, 
ScInterpreterContext* pContext = nullptr );
 
     /** If eGrammar == GRAM_UNSPECIFIED then the grammar of rDocument is used,
      */
     SC_DLLPUBLIC ScCompiler( ScDocument& rDocument, const ScAddress&,
             formula::FormulaGrammar::Grammar eGrammar = 
formula::FormulaGrammar::GRAM_UNSPECIFIED,
-            bool bComputeII = false, bool bMatrixFlag = false, const 
ScInterpreterContext* pContext = nullptr );
+            bool bComputeII = false, bool bMatrixFlag = false, 
ScInterpreterContext* pContext = nullptr );
 
     SC_DLLPUBLIC ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& 
rPos, ScTokenArray& rArr,
-            bool bComputeII = false, bool bMatrixFlag = false, const 
ScInterpreterContext* pContext = nullptr );
+            bool bComputeII = false, bool bMatrixFlag = false, 
ScInterpreterContext* pContext = nullptr );
 
     /** If eGrammar == GRAM_UNSPECIFIED then the grammar of rDocument is used,
      */
     SC_DLLPUBLIC ScCompiler( ScDocument& rDocument, const ScAddress&, 
ScTokenArray& rArr,
             formula::FormulaGrammar::Grammar eGrammar = 
formula::FormulaGrammar::GRAM_UNSPECIFIED,
-            bool bComputeII = false, bool bMatrixFlag = false, const 
ScInterpreterContext* pContext = nullptr );
+            bool bComputeII = false, bool bMatrixFlag = false, 
ScInterpreterContext* pContext = nullptr );
 
     SC_DLLPUBLIC virtual ~ScCompiler() override;
 
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index ba507ff54935..593f3f404d42 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -1203,9 +1203,9 @@ public:
                                     SCCOL nCol2, SCROW nRow2, const 
ScMarkData& rMark);
 
     SC_DLLPUBLIC OUString GetString( SCCOL nCol, SCROW nRow, SCTAB nTab,
-                                     const ScInterpreterContext* pContext = 
nullptr ) const;
+                                     ScInterpreterContext* pContext = nullptr 
) const;
     SC_DLLPUBLIC OUString GetString( const ScAddress& rPos,
-                                     const ScInterpreterContext* pContext = 
nullptr ) const;
+                                     ScInterpreterContext* pContext = nullptr 
) const;
 
     /**
      * Return a pointer to the double value stored in value cell.
diff --git a/sc/inc/dpcache.hxx b/sc/inc/dpcache.hxx
index 7db605b85800..ada1d7cddc88 100644
--- a/sc/inc/dpcache.hxx
+++ b/sc/inc/dpcache.hxx
@@ -37,6 +37,7 @@ struct ScQueryParam;
 class ScDPObject;
 class ScDocument;
 class SvNumberFormatter;
+struct ScInterpreterContext;
 
 enum class SvNumFormatType : sal_Int16;
 
@@ -138,11 +139,11 @@ public:
 
     SCROW GetIdByItemData(tools::Long nDim, const ScDPItemData& rItem) const;
 
-    static sal_uInt32 GetLocaleIndependentFormat( SvNumberFormatter& 
rFormatter, sal_uInt32 nNumFormat );
+    static sal_uInt32 GetLocaleIndependentFormat( ScInterpreterContext& 
rContext, sal_uInt32 nNumFormat );
     static OUString GetLocaleIndependentFormattedNumberString( double fValue );
-    static OUString GetLocaleIndependentFormattedString( double fValue, 
SvNumberFormatter& rFormatter, sal_uInt32 nNumFormat );
+    static OUString GetLocaleIndependentFormattedString( double fValue, 
ScInterpreterContext& rContext, sal_uInt32 nNumFormat );
     SC_DLLPUBLIC OUString GetFormattedString(tools::Long nDim, const 
ScDPItemData& rItem, bool bLocaleIndependent) const;
-    SvNumberFormatter* GetNumberFormatter() const;
+    ScInterpreterContext& GetInterpreterContext() const;
 
     tools::Long AppendGroupField();
     void ResetGroupItems(tools::Long nDim, const ScDPNumGroupInfo& rNumInfo, 
sal_Int32 nGroupType);
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 28a3ff981e20..c11fcea7efe5 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -229,8 +229,8 @@ public:
     size_t GetHash() const;
 
     SC_DLLPUBLIC OUString GetFormula( const formula::FormulaGrammar::Grammar = 
formula::FormulaGrammar::GRAM_DEFAULT,
-                         const ScInterpreterContext* pContext = nullptr ) 
const;
-    SC_DLLPUBLIC OUString GetFormula( sc::CompileFormulaContext& rCxt, const 
ScInterpreterContext* pContext = nullptr ) const;
+                         ScInterpreterContext* pContext = nullptr ) const;
+    SC_DLLPUBLIC OUString GetFormula( sc::CompileFormulaContext& rCxt, 
ScInterpreterContext* pContext = nullptr ) const;
 
     SC_DLLPUBLIC void SetDirty( bool bDirtyFlag=true );
     void            SetDirtyVar();
diff --git a/sc/inc/global.hxx b/sc/inc/global.hxx
index 535c919f5fe2..5cb782ac14dc 100644
--- a/sc/inc/global.hxx
+++ b/sc/inc/global.hxx
@@ -482,6 +482,7 @@ class SfxItemPool;
 class EditTextObject;
 class SfxObjectShell;
 class SvNumberFormatter;
+struct ScInterpreterContext;
 class ScUnitConverter;
 class CharClass;
 class LocaleDataWrapper;
@@ -583,7 +584,7 @@ public:
                                                 const SfxObjectShell* pShell );
     SC_DLLPUBLIC static OUString            GetDocTabName( std::u16string_view 
rFileName,
                                                 std::u16string_view rTabName );
-    SC_DLLPUBLIC static sal_uInt32 GetStandardFormat( SvNumberFormatter&, 
sal_uInt32 nFormat, SvNumFormatType nType );
+    SC_DLLPUBLIC static sal_uInt32 GetStandardFormat( ScInterpreterContext&, 
sal_uInt32 nFormat, SvNumFormatType nType );
 
     SC_DLLPUBLIC static sal_uInt16 GetStandardRowHeight();
     /// Horizontal pixel per twips factor.
@@ -823,7 +824,7 @@ public:
      */
     static double ConvertStringToValue( const OUString& rStr, const 
ScCalcConfig& rConfig,
             FormulaError & rError, FormulaError nStringNoValueError,
-            SvNumberFormatter* pFormatter, SvNumFormatType & rCurFmtType );
+            ScInterpreterContext& rContext, SvNumFormatType & rCurFmtType );
 
     /// Calc's threaded group calculation is in progress.
     SC_DLLPUBLIC static bool bThreadedGroupCalcInProgress;
diff --git a/sc/inc/interpretercontext.hxx b/sc/inc/interpretercontext.hxx
index 1fd037a719b5..2f89249a21a6 100644
--- a/sc/inc/interpretercontext.hxx
+++ b/sc/inc/interpretercontext.hxx
@@ -9,11 +9,12 @@
 
 #pragma once
 
+#include <array>
 #include <memory>
 #include <random>
 #include <vector>
-#include <i18nlangtag/lang.h>
-#include <o3tl/sorted_vector.hxx>
+#include <i18nlangtag/mslangid.hxx>
+#include <svl/numformat.hxx>
 #include "types.hxx"
 
 namespace formula
@@ -23,11 +24,10 @@ class FormulaToken;
 
 #define TOKEN_CACHE_SIZE 8
 
+class Color;
 class ScDocument;
-class SvNumberFormatter;
 struct ScLookupCacheMap;
 class ScInterpreter;
-enum class SvNumFormatType : sal_Int16;
 
 // SetNumberFormat() is not thread-safe, so calls to it need to be delayed to 
the main thread.
 struct DelayedSetNumberFormat
@@ -65,9 +65,52 @@ struct ScInterpreterContext
         return mpFormatter;
     }
 
-    SvNumFormatType GetNumberFormatType(sal_uInt32 nFIndex) const;
+    SvNumFormatType NFGetType(sal_uInt32 nFIndex) const;
+    const SvNumberformat* NFGetFormatEntry(sal_uInt32 nKey) const;
+    sal_uInt32 NFGetFormatIndex(NfIndexTableOffset, LanguageType eLnge = 
LANGUAGE_DONTKNOW) const;
+    bool NFIsTextFormat(sal_uInt32 nFIndex) const;
+    sal_uInt32 NFGetTimeFormat(double fNumber, LanguageType eLnge, bool 
bForceDuration) const;
+    const Date& NFGetNullDate() const;
+    OUString NFGetFormatDecimalSep(sal_uInt32 nFormat) const;
+    sal_uInt16 NFGetFormatPrecision(sal_uInt32 nFormat) const;
 
-    sal_uInt32 GetFormatForLanguageIfBuiltIn(sal_uInt32 nFormat, LanguageType 
eLnge) const;
+    sal_uInt32 NFGetFormatForLanguageIfBuiltIn(sal_uInt32 nFormat, 
LanguageType eLnge) const;
+
+    bool NFIsNumberFormat(const OUString& sString, sal_uInt32& F_Index, 
double& fOutNumber,
+                          SvNumInputOptions eInputOptions = 
SvNumInputOptions::NONE);
+
+    void NFGetInputLineString(const double& fOutNumber, sal_uInt32 nFIndex, 
OUString& rOutString,
+                              bool bFiltering = false, bool bForceSystemLocale 
= false) const;
+
+    void NFGetOutputString(const double& fOutNumber, sal_uInt32 nFIndex, 
OUString& sOutString,
+                           const Color** ppColor, bool bUseStarFormat = false) 
const;
+
+    void NFGetOutputString(const OUString& sString, sal_uInt32 nFIndex, 
OUString& sOutString,
+                           const Color** ppColor, bool bUseStarFormat = false) 
const;
+
+    sal_uInt32 NFGetStandardFormat(SvNumFormatType eType, LanguageType eLnge = 
LANGUAGE_DONTKNOW);
+    sal_uInt32 NFGetStandardFormat(sal_uInt32 nFIndex, SvNumFormatType eType, 
LanguageType eLnge);
+    sal_uInt32 NFGetStandardFormat(double fNumber, sal_uInt32 nFIndex, 
SvNumFormatType eType,
+                                   LanguageType eLnge);
+
+    bool NFGetPreviewString(const OUString& sFormatString, double 
fPreviewNumber,
+                            OUString& sOutString, const Color** ppColor, 
LanguageType eLnge);
+    bool NFGetPreviewString(const OUString& sFormatString, const OUString& 
sPreviewString,
+                            OUString& sOutString, const Color** ppColor,
+                            LanguageType eLnge = LANGUAGE_DONTKNOW);
+    bool NFGetPreviewStringGuess(const OUString& sFormatString, double 
fPreviewNumber,
+                                 OUString& sOutString, const Color** ppColor,
+                                 LanguageType eLnge = LANGUAGE_DONTKNOW);
+
+    sal_uInt32 NFGetStandardIndex(LanguageType eLnge = LANGUAGE_DONTKNOW) 
const;
+
+    OUString NFGenerateFormat(sal_uInt32 nIndex, LanguageType eLnge = 
LANGUAGE_DONTKNOW,
+                              bool bThousand = false, bool IsRed = false, 
sal_uInt16 nPrecision = 0,
+                              sal_uInt16 nLeadingCnt = 1);
+
+    sal_uInt16 NFExpandTwoDigitYear(sal_uInt16 nYear) const;
+
+    OUString NFGetCalcCellReturn(sal_uInt32 nFormat) const;
 
 private:
     friend class ScInterpreterContextPool;
@@ -76,28 +119,44 @@ private:
     void Cleanup();
     void ClearLookupCache(const ScDocument* pDoc);
     void initFormatTable();
-    SvNumberFormatter* mpFormatter;
 
-    template <typename T> struct CompareKey
+    // During threaded calculation, where we don't need to add to the number
+    // format data, we can access the numbering data with a RO unlocked view of
+    // the NumberFormat's data and a throw-away object for currently used 
language
+    // This is essentially an exploded view of mpFormatter
+    std::unique_ptr<SvNFLanguageData> mxLanguageData;
+    const SvNFFormatData* mpFormatData;
+    SvNFEngine::Accessor maROPolicy;
+
+    // Some temp caches of the 4 most recent results from NumberFormatting
+    // lookups.
+    struct NFBuiltIn
     {
-        bool operator()(const T& lhs, const T& rhs) const { return lhs.nKey < 
rhs.nKey; }
+        sal_uInt64 nKey;
+        sal_uInt32 nFormat;
+        NFBuiltIn()
+            : nKey(SAL_MAX_UINT64)
+            , nFormat(SAL_MAX_UINT32)
+        {
+        }
     };
-
+    // from format+lang to builtin format
+    mutable std::array<NFBuiltIn, 4> maNFBuiltInCache;
     struct NFType
     {
         sal_uInt32 nKey;
-        mutable SvNumFormatType eType;
+        SvNumFormatType eType;
+        NFType()
+            : nKey(SAL_MAX_UINT32)
+            , eType(SvNumFormatType::ALL)
+        {
+        }
     };
-    // map from format index to type
-    mutable o3tl::sorted_vector<NFType, CompareKey<NFType>> maNFTypeCache;
+    // from format index to type
+    mutable std::array<NFType, 4> maNFTypeCache;
 
-    struct NFBuiltIn
-    {
-        sal_uInt64 nKey;
-        mutable sal_uInt32 nFormat;
-    };
-    // map from format+lang to builtin format
-    mutable o3tl::sorted_vector<NFBuiltIn, CompareKey<NFBuiltIn>> 
maNFBuiltInCache;
+    // Formatter used when non-nthreaded calculation
+    SvNumberFormatter* mpFormatter;
 };
 
 class ScThreadedInterpreterContextGetterGuard;
@@ -148,6 +207,8 @@ class ScInterpreterContextPool
 public:
     // Only to be used to clear lookup cache in all pool elements
     static void ClearLookupCaches(const ScDocument* pDoc);
+    // Called from ScModule dtor, drop all resources
+    static void ModuleExiting();
 };
 
 class ScThreadedInterpreterContextGetterGuard
diff --git a/sc/inc/patattr.hxx b/sc/inc/patattr.hxx
index bbb55b5a309f..7294ff11fdaa 100644
--- a/sc/inc/patattr.hxx
+++ b/sc/inc/patattr.hxx
@@ -241,6 +241,8 @@ public:
     sal_uInt32              GetNumberFormat( const ScInterpreterContext& 
rContext ) const;
     sal_uInt32              GetNumberFormat( SvNumberFormatter* pFormatter,
                                              const SfxItemSet* pCondSet ) 
const;
+    sal_uInt32              GetNumberFormat( const ScInterpreterContext& 
rContext,
+                                             const SfxItemSet* pCondSet ) 
const;
 
     Degree100               GetRotateVal( const SfxItemSet* pCondSet ) const;
     ScRotateDir             GetRotateDir( const SfxItemSet* pCondSet ) const;
diff --git a/sc/inc/queryevaluator.hxx b/sc/inc/queryevaluator.hxx
index f5724083444d..351531b9731c 100644
--- a/sc/inc/queryevaluator.hxx
+++ b/sc/inc/queryevaluator.hxx
@@ -56,7 +56,7 @@ class ScQueryEvaluator
     CollatorWrapper* mpCollator;
     const bool mbMatchWholeCell;
     const bool mbCaseSensitive;
-    const ScInterpreterContext* mpContext;
+    ScInterpreterContext* mpContext;
 
     const SCSIZE mnEntryCount;
     bool* mpPasst;
@@ -108,8 +108,7 @@ class ScQueryEvaluator
 
 public:
     ScQueryEvaluator(ScDocument& rDoc, const ScTable& rTab, const 
ScQueryParam& rParam,
-                     const ScInterpreterContext* pContext = nullptr,
-                     bool* pTestEqualCondition = nullptr);
+                     ScInterpreterContext* pContext = nullptr, bool* 
pTestEqualCondition = nullptr);
 
     bool ValidQuery(SCROW nRow, const ScRefCellValue* pCell = nullptr,
                     sc::TableColumnBlockPositionSet* pBlockPos = nullptr);
diff --git a/sc/inc/queryparam.hxx b/sc/inc/queryparam.hxx
index e80cb864fd48..dc38638075af 100644
--- a/sc/inc/queryparam.hxx
+++ b/sc/inc/queryparam.hxx
@@ -27,7 +27,7 @@
 #include <vector>
 #include <ostream>
 
-class SvNumberFormatter;
+struct ScInterpreterContext;
 
 struct ScDBQueryParamInternal;
 struct ScQueryEntry;
@@ -62,7 +62,7 @@ struct SAL_DLLPUBLIC_RTTI ScQueryParamBase
     SC_DLLPUBLIC void RemoveAllEntriesByField(SCCOLROW nField);
     void Resize(size_t nNew);
     void FillInExcelSyntax( svl::SharedStringPool& rPool, const OUString& 
aCellStr, SCSIZE nIndex,
-                            SvNumberFormatter* pFormatter );
+                            ScInterpreterContext* pContext );
 
 protected:
     typedef std::vector<ScQueryEntry> EntriesType;
diff --git a/sc/inc/rangeseq.hxx b/sc/inc/rangeseq.hxx
index 9f424d0f3812..1657811e2e40 100644
--- a/sc/inc/rangeseq.hxx
+++ b/sc/inc/rangeseq.hxx
@@ -24,7 +24,7 @@
 
 namespace com::sun::star::uno { class Any; }
 
-class SvNumberFormatter;
+struct ScInterpreterContext;
 class ScDocument;
 class ScMatrix;
 class ScRange;
@@ -43,7 +43,7 @@ public:
     static bool FillStringArray( css::uno::Any& rAny,
                                 ScDocument& rDoc, const ScRange& rRange );
     static bool FillStringArray( css::uno::Any& rAny,
-                                const ScMatrix* pMatrix, SvNumberFormatter* 
pFormatter );
+                                const ScMatrix* pMatrix, ScInterpreterContext& 
rContext );
     static bool FillMixedArray( css::uno::Any& rAny,
                                 ScDocument& rDoc, const ScRange& rRange,
                                 bool bAllowNV = false );
diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx
index 1f367793518d..1594ca3bce35 100644
--- a/sc/inc/scmatrix.hxx
+++ b/sc/inc/scmatrix.hxx
@@ -34,7 +34,7 @@
 #define DEBUG_MATRIX 0
 
 class ScInterpreter;
-class SvNumberFormatter;
+struct ScInterpreterContext;
 class ScMatrixImpl;
 enum class FormulaError : sal_uInt16;
 
@@ -314,7 +314,7 @@ public:
         numerical value formatted as string, or in case of an error the error
         string is returned; an empty string for empty, a "FALSE" string for
         empty path. */
-    svl::SharedString GetString( SvNumberFormatter& rFormatter, SCSIZE nC, 
SCSIZE nR) const ;
+    svl::SharedString GetString( ScInterpreterContext& rContext, SCSIZE nC, 
SCSIZE nR) const ;
 
     /// @ATTENTION: If bString the ScMatrixValue->pS may still be NULL to 
indicate
     /// an empty string!
@@ -411,7 +411,7 @@ public:
             EmptyOpFunction aEmptyFunc) const ;
 
     void MatConcat(SCSIZE nMaxCol, SCSIZE nMaxRow, const ScMatrixRef& xMat1, 
const ScMatrixRef& xMat2,
-            SvNumberFormatter& rFormatter, svl::SharedStringPool& rPool) ;
+            ScInterpreterContext& rContext, svl::SharedStringPool& rPool) ;
 
     /** Apply binary operation to values from two input matrices, storing 
result into this matrix. */
     void ExecuteBinaryOp(SCSIZE nMaxCol, SCSIZE nMaxRow, const ScMatrix& 
rInputMat1, const ScMatrix& rInputMat2,
diff --git a/sc/inc/stringutil.hxx b/sc/inc/stringutil.hxx
index 3d930dd359df..98159f0d7e80 100644
--- a/sc/inc/stringutil.hxx
+++ b/sc/inc/stringutil.hxx
@@ -128,6 +128,8 @@ struct ScInputStringType
     SvNumFormatType mnFormatType;
 };
 
+struct ScInterpreterContext;
+
 class ScStringUtil
 {
 public:
@@ -159,7 +161,7 @@ public:
     static bool SC_DLLPUBLIC isMultiline( std::u16string_view rStr );
 
     static ScInputStringType parseInputString(
-        SvNumberFormatter& rFormatter, const OUString& rStr, LanguageType 
eLang );
+        ScInterpreterContext& rContext, const OUString& rStr, LanguageType 
eLang );
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 1761d0cdeed4..846a9234b23d 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -468,7 +468,7 @@ public:
     bool        ReservePatternCount( SCCOL nCol, SCSIZE nReserve );
 
     void        SetRawString( SCCOL nCol, SCROW nRow, const svl::SharedString& 
rStr );
-    OUString    GetString( SCCOL nCol, SCROW nRow, const ScInterpreterContext* 
pContext = nullptr ) const;
+    OUString    GetString( SCCOL nCol, SCROW nRow, ScInterpreterContext* 
pContext = nullptr ) const;
     double*     GetValueCell( SCCOL nCol, SCROW nRow );
     // Note that if pShared is set and a value is returned that way, the 
returned OUString is empty.
     OUString    GetInputString( SCCOL nCol, SCROW nRow, bool 
bForceSystemLocale = false ) const;
diff --git a/sc/qa/unit/helper/csv_handler.hxx 
b/sc/qa/unit/helper/csv_handler.hxx
index 4c59144c3b5e..3cb43bead360 100644
--- a/sc/qa/unit/helper/csv_handler.hxx
+++ b/sc/qa/unit/helper/csv_handler.hxx
@@ -34,9 +34,9 @@ inline OUString getConditionalFormatString(ScDocument* pDoc, 
SCCOL nCol, SCROW n
 
     const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
     const ScPatternAttr* pPattern = pDoc->GetPattern(nCol, nRow, nTab);
-    SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
-    sal_uInt32 nFormat = pPattern->GetNumberFormat( pFormatter, pCondSet );
-    aString = ScCellFormat::GetString(*pDoc, ScAddress(nCol, nRow, nTab), 
nFormat, &pColor, *pFormatter);
+    ScInterpreterContext& rContext = pDoc->GetNonThreadedContext();
+    sal_uInt32 nFormat = pPattern->GetNumberFormat( rContext, pCondSet );
+    aString = ScCellFormat::GetString(*pDoc, ScAddress(nCol, nRow, nTab), 
nFormat, &pColor, &rContext);
     return aString;
 }
 
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index ae1aac3e715d..c4ac17ffe358 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -162,8 +162,8 @@ tools::Long ScColumn::GetNeededSize(
     else
         bBreak = pPattern->GetItem(ATTR_LINEBREAK).GetValue();
 
-    SvNumberFormatter* pFormatter = rDocument.GetFormatTable();
-    sal_uInt32 nFormat = pPattern->GetNumberFormat( pFormatter, pCondSet );
+    ScInterpreterContext& rContext = rDocument.GetNonThreadedContext();
+    sal_uInt32 nFormat = pPattern->GetNumberFormat( rContext, pCondSet );
 
     // get "cell is value" flag
     // Must be synchronized with ScOutputData::LayoutStrings()
@@ -186,7 +186,7 @@ tools::Long ScColumn::GetNeededSize(
     }
 
     // #i111387#, tdf#121040: disable automatic line breaks for all number 
formats
-    if (bBreak && bCellIsValue && (pFormatter->GetType(nFormat) == 
SvNumFormatType::NUMBER))
+    if (bBreak && bCellIsValue && (rContext.NFGetType(nFormat) == 
SvNumFormatType::NUMBER))
     {
         // If a formula cell needs to be interpreted during aCell.hasNumeric()
         // to determine the type, the pattern may get invalidated because the
@@ -207,8 +207,8 @@ tools::Long ScColumn::GetNeededSize(
                 bBreak = false;
             else
             {
-                nFormat = pPattern->GetNumberFormat( pFormatter, pCondSet );
-                if (pFormatter->GetType(nFormat) == SvNumFormatType::NUMBER)
+                nFormat = pPattern->GetNumberFormat( rContext, pCondSet );
+                if (rContext.NFGetType(nFormat) == SvNumFormatType::NUMBER)
                     bBreak = false;
             }
         }
@@ -301,7 +301,7 @@ tools::Long ScColumn::GetNeededSize(
     {
         const Color* pColor;
         OUString aValStr = ScCellFormat::GetString(
-            aCell, nFormat, &pColor, *pFormatter, rDocument, true, 
rOptions.bFormula);
+            aCell, nFormat, &pColor, &rContext, rDocument, true, 
rOptions.bFormula);
 
         if (!aValStr.isEmpty())
         {
@@ -471,7 +471,7 @@ tools::Long ScColumn::GetNeededSize(
         {
             const Color* pColor;
             OUString aString = ScCellFormat::GetString(
-                aCell, nFormat, &pColor, *pFormatter, rDocument, true,
+                aCell, nFormat, &pColor, &rContext, rDocument, true,
                 rOptions.bFormula);
 
             if (!aString.isEmpty())
@@ -652,7 +652,7 @@ class MaxStrLenFinder
     {
         const Color* pColor;
         OUString aValStr = ScCellFormat::GetString(
-            rCell, mnFormat, &pColor, *mrDoc.GetFormatTable(), mrDoc);
+            rCell, mnFormat, &pColor, nullptr, mrDoc);
 
         if (aValStr.getLength() <= mnMaxLen)
             return;
@@ -744,8 +744,8 @@ sal_uInt16 ScColumn::GetOptimalColWidth(
                         static_cast<tools::Long>( pMargin->GetRightMargin() * 
nPPTX );
 
         // Try to find the row that has the longest string, and measure the 
width of that string.
-        SvNumberFormatter* pFormatter = rDocument.GetFormatTable();
-        sal_uInt32 nFormat = pPattern->GetNumberFormat( pFormatter );
+        ScInterpreterContext& rContext = rDocument.GetNonThreadedContext();
+        sal_uInt32 nFormat = pPattern->GetNumberFormat(rContext);
         while ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 && nRow <= 2)
         {
             // This is often used with CSV import or other data having a header
@@ -755,7 +755,7 @@ sal_uInt16 ScColumn::GetOptimalColWidth(
             // rows..
             const ScPatternAttr* pNextPattern = GetPattern( ++nRow );
             if (!ScPatternAttr::areSame(pNextPattern, pPattern))
-                nFormat = pNextPattern->GetNumberFormat( pFormatter );
+                nFormat = pNextPattern->GetNumberFormat(rContext);
         }
         OUString aLongStr;
         const Color* pColor;
@@ -763,7 +763,7 @@ sal_uInt16 ScColumn::GetOptimalColWidth(
         {
             ScRefCellValue aCell = GetCellValue(pParam->mnMaxTextRow);
             aLongStr = ScCellFormat::GetString(
-                aCell, nFormat, &pColor, *pFormatter, rDocument);
+                aCell, nFormat, &pColor, &rContext, rDocument);
         }
         else
         {
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index a03f3f172cd1..76a8f7bef9a9 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -873,7 +873,7 @@ bool ScColumn::UpdateScriptType( sc::CellTextAttr& rAttr, 
SCROW nRow, sc::CellSt
     pPattern = GetPattern(nRow);
     const Color* pColor;
     sal_uInt32 nFormat = pPattern->GetNumberFormat(pFormatter, pCondSet);
-    OUString aStr = ScCellFormat::GetString(aCell, nFormat, &pColor, 
*pFormatter, rDocument);
+    OUString aStr = ScCellFormat::GetString(aCell, nFormat, &pColor, nullptr, 
rDocument);
 
     // Store the real script type to the array.
     rAttr.mnScriptType = rDocument.GetStringScriptType(aStr);
@@ -2569,9 +2569,9 @@ class FilterEntriesHandler
 
     void processCell(const ScColumn& rColumn, SCROW nRow, ScRefCellValue& 
rCell, bool bIsEmptyCell=false)
     {
-        SvNumberFormatter* pFormatter = mrColumn.GetDoc().GetFormatTable();
-        sal_uInt32 nFormat = 
mrColumn.GetNumberFormat(mrColumn.GetDoc().GetNonThreadedContext(), nRow);
-        OUString aStr = ScCellFormat::GetInputString(rCell, nFormat, 
*pFormatter, mrColumn.GetDoc(), mbFiltering);
+        ScInterpreterContext& rContext = 
mrColumn.GetDoc().GetNonThreadedContext();
+        sal_uInt32 nFormat = mrColumn.GetNumberFormat(rContext, nRow);
+        OUString aStr = ScCellFormat::GetInputString(rCell, nFormat, 
&rContext, mrColumn.GetDoc(), mbFiltering);
 
         // Colors
         ScAddress aPos(rColumn.GetCol(), nRow, rColumn.GetTab());
@@ -2638,7 +2638,7 @@ class FilterEntriesHandler
                 ;
         }
 
-        SvNumFormatType nType = pFormatter->GetType(nFormat);
+        SvNumFormatType nType = rContext.NFGetType(nFormat);
         bool bDate = false;
         if ((nType & SvNumFormatType::DATE) && !(nType & 
SvNumFormatType::TIME))
         {
@@ -2649,16 +2649,16 @@ class FilterEntriesHandler
             bDate = true;
             // Convert string representation to ISO 8601 date to eliminate
             // locale dependent behaviour later when filtering for dates.
-            sal_uInt32 nIndex = pFormatter->GetFormatIndex( 
NF_DATE_DIN_YYYYMMDD);
-            pFormatter->GetInputLineString( fVal, nIndex, aStr);
+            sal_uInt32 nIndex = rContext.NFGetFormatIndex( 
NF_DATE_DIN_YYYYMMDD);
+            rContext.NFGetInputLineString( fVal, nIndex, aStr);
         }
         else if (nType == SvNumFormatType::DATETIME)
         {
             // special case for datetime values.
             // Convert string representation to ISO 8601 (with blank instead 
of T) datetime
             // to eliminate locale dependent behaviour later when filtering 
for datetimes.
-            sal_uInt32 nIndex = 
pFormatter->GetFormatIndex(NF_DATETIME_ISO_YYYYMMDD_HHMMSS);
-            pFormatter->GetInputLineString(fVal, nIndex, aStr);
+            sal_uInt32 nIndex = 
rContext.NFGetFormatIndex(NF_DATETIME_ISO_YYYYMMDD_HHMMSS);
+            rContext.NFGetInputLineString(fVal, nIndex, aStr);
         }
         // store the formatted/rounded value for filtering
         if ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) != 0 && !bDate)
@@ -3132,7 +3132,7 @@ void ScColumn::SetValue(
         BroadcastNewCell(nRow);
 }
 
-OUString ScColumn::GetString( const ScRefCellValue& aCell, SCROW nRow, const 
ScInterpreterContext* pContext ) const
+OUString ScColumn::GetString( const ScRefCellValue& aCell, SCROW nRow, 
ScInterpreterContext* pContext ) const
 {
     // ugly hack for ordering problem with GetNumberFormat and missing 
inherited formats
     if (aCell.getType() == CELLTYPE_FORMULA)
@@ -3140,8 +3140,7 @@ OUString ScColumn::GetString( const ScRefCellValue& 
aCell, SCROW nRow, const ScI
 
     sal_uInt32 nFormat = GetNumberFormat( pContext ? *pContext : 
GetDoc().GetNonThreadedContext(), nRow);
     const Color* pColor = nullptr;
-    return ScCellFormat::GetString(aCell, nFormat, &pColor,
-        pContext ? *(pContext->GetFormatTable()) : 
*(GetDoc().GetFormatTable()), GetDoc());
+    return ScCellFormat::GetString(aCell, nFormat, &pColor, pContext, 
GetDoc());
 }
 
 double* ScColumn::GetValueCell( SCROW nRow )
@@ -3160,7 +3159,7 @@ double* ScColumn::GetValueCell( SCROW nRow )
 OUString ScColumn::GetInputString( const ScRefCellValue& aCell, SCROW nRow, 
bool bForceSystemLocale ) const
 {
     sal_uInt32 nFormat = GetNumberFormat(GetDoc().GetNonThreadedContext(), 
nRow);
-    return ScCellFormat::GetInputString(aCell, nFormat, 
*(GetDoc().GetFormatTable()), GetDoc(), nullptr, false, bForceSystemLocale);
+    return ScCellFormat::GetInputString(aCell, nFormat, nullptr, GetDoc(), 
nullptr, false, bForceSystemLocale);
 }
 
 double ScColumn::GetValue( SCROW nRow ) const
@@ -3358,7 +3357,6 @@ class MaxStringLenHandler
 {
     sal_Int32 mnMaxLen;
     const ScColumn& mrColumn;
-    SvNumberFormatter* mpFormatter;
     rtl_TextEncoding meCharSet;
     bool mbOctetEncoding;
 
@@ -3366,7 +3364,7 @@ class MaxStringLenHandler
     {
         const Color* pColor;
         sal_uInt32 nFormat = mrColumn.GetAttr(nRow, 
ATTR_VALUE_FORMAT).GetValue();
-        OUString aString = ScCellFormat::GetString(rCell, nFormat, &pColor, 
*mpFormatter, mrColumn.GetDoc());
+        OUString aString = ScCellFormat::GetString(rCell, nFormat, &pColor, 
nullptr, mrColumn.GetDoc());
         sal_Int32 nLen = 0;
         if (mbOctetEncoding)
         {
@@ -3393,7 +3391,6 @@ public:
     MaxStringLenHandler(const ScColumn& rColumn, rtl_TextEncoding eCharSet) :
         mnMaxLen(0),
         mrColumn(rColumn),
-        mpFormatter(rColumn.GetDoc().GetFormatTable()),
         meCharSet(eCharSet),
         mbOctetEncoding(rtl_isOctetTextEncoding(eCharSet))
     {
@@ -3440,7 +3437,6 @@ namespace {
 class MaxNumStringLenHandler
 {
     const ScColumn& mrColumn;
-    SvNumberFormatter* mpFormatter;
     sal_Int32 mnMaxLen;
     sal_uInt16 mnPrecision;
     sal_uInt16 mnMaxGeneralPrecision;
@@ -3475,9 +3471,10 @@ class MaxNumStringLenHandler
                 mrColumn.GetAttr(nRow, ATTR_VALUE_FORMAT).GetValue();
         if (nFormat % SV_COUNTRY_LANGUAGE_OFFSET)
         {
-            aSep = mpFormatter->GetFormatDecimalSep(nFormat);
-            aString = ScCellFormat::GetInputString(rCell, nFormat, 
*mpFormatter, mrColumn.GetDoc());
-            const SvNumberformat* pEntry = mpFormatter->GetEntry(nFormat);
+            ScInterpreterContext& rContext = 
mrColumn.GetDoc().GetNonThreadedContext();
+            aSep = rContext.NFGetFormatDecimalSep(nFormat);
+            aString = ScCellFormat::GetInputString(rCell, nFormat, &rContext, 
mrColumn.GetDoc());
+            const SvNumberformat* pEntry = rContext.NFGetFormatEntry(nFormat);
             if (pEntry)
             {
                 bool bThousand, bNegRed;
@@ -3485,7 +3482,7 @@ class MaxNumStringLenHandler
                 pEntry->GetFormatSpecialInfo(bThousand, bNegRed, nPrec, 
nLeading);
             }
             else
-                nPrec = mpFormatter->GetFormatPrecision(nFormat);
+                nPrec = rContext.NFGetFormatPrecision(nFormat);
         }
         else
         {
@@ -3560,7 +3557,7 @@ class MaxNumStringLenHandler
 
 public:
     MaxNumStringLenHandler(const ScColumn& rColumn, sal_uInt16 
nMaxGeneralPrecision) :
-        mrColumn(rColumn), mpFormatter(rColumn.GetDoc().GetFormatTable()),
+        mrColumn(rColumn),
         mnMaxLen(0), mnPrecision(0), 
mnMaxGeneralPrecision(nMaxGeneralPrecision),
         mbHaveSigned(false)
     {
diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
index 7b1299d7bae6..2f90021131f4 100644
--- a/sc/source/core/data/column4.cxx
+++ b/sc/source/core/data/column4.cxx
@@ -1128,7 +1128,7 @@ class ScriptTypeUpdater
     sc::CellTextAttrStoreType& mrTextAttrs;
     sc::CellTextAttrStoreType::iterator miPosAttr;
     ScConditionalFormatList* mpCFList;
-    SvNumberFormatter* mpFormatter;
+    ScInterpreterContext& mrContext;
     ScAddress maPos;
     bool mbUpdated;
 
@@ -1161,8 +1161,8 @@ private:
         }
 
         const Color* pColor;
-        sal_uInt32 nFormat = pPat->GetNumberFormat(mpFormatter, pCondSet);
-        OUString aStr = ScCellFormat::GetString(rCell, nFormat, &pColor, 
*mpFormatter, mrCol.GetDoc());
+        sal_uInt32 nFormat = pPat->GetNumberFormat(mrContext, pCondSet);
+        OUString aStr = ScCellFormat::GetString(rCell, nFormat, &pColor, 
&mrContext, mrCol.GetDoc());
 
         rAttr.mnScriptType = mrCol.GetDoc().GetStringScriptType(aStr);
         mbUpdated = true;
@@ -1174,7 +1174,7 @@ public:
         mrTextAttrs(rCol.GetCellAttrStore()),
         miPosAttr(mrTextAttrs.begin()),
         mpCFList(rCol.GetDoc().GetCondFormList(rCol.GetTab())),
-        mpFormatter(rCol.GetDoc().GetFormatTable()),
+        mrContext(rCol.GetDoc().GetNonThreadedContext()),
         maPos(rCol.GetCol(), 0, rCol.GetTab()),
         mbUpdated(false)
     {}
diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx
index bb4e77d27f1d..edecaa1b9fab 100644
--- a/sc/source/core/data/dociter.cxx
+++ b/sc/source/core/data/dociter.cxx
@@ -78,7 +78,10 @@ static void ScAttrArray_IterGetNumberFormat( sal_uInt32& 
nFormat, const ScAttrAr
         nRowEnd = rDoc.MaxRow();
     }
 
-    nFormat = pPattern->GetNumberFormat( pContext ? pContext->GetFormatTable() 
: rDoc.GetFormatTable() );
+    if (pContext)
+        nFormat = pPattern->GetNumberFormat(*pContext);
+    else
+        nFormat = pPattern->GetNumberFormat(rDoc.GetFormatTable());
     rpArr = pNewArr;
     nAttrEndRow = nRowEnd;
 }
@@ -260,7 +263,7 @@ void ScValueIterator::GetCurNumFmtInfo( SvNumFormatType& 
nType, sal_uInt32& nInd
         SCROW nCurRow = GetRow();
         const ScColumn* pCol = &(mrDoc.maTabs[mnTab])->aCol[mnCol];
         nNumFmtIndex = pCol->GetNumberFormat(mrContext, nCurRow);
-        nNumFmtType = mrContext.GetNumberFormatType( nNumFmtIndex );
+        nNumFmtType = mrContext.NFGetType(nNumFmtIndex);
         bNumValid = true;
     }
 
diff --git a/sc/source/core/data/documen6.cxx b/sc/source/core/data/documen6.cxx
index 96c625eaf9af..ef13ecb7aa6a 100644
--- a/sc/source/core/data/documen6.cxx
+++ b/sc/source/core/data/documen6.cxx
@@ -118,9 +118,9 @@ SvtScriptType ScDocument::GetCellScriptType( const 
ScAddress& rPos, sal_uInt32 n
     const Color* pColor;
     OUString aStr;
     if( pCell )
-        aStr = ScCellFormat::GetString(*pCell, nNumberFormat, &pColor, 
*GetFormatTable(), *this);
+        aStr = ScCellFormat::GetString(*pCell, nNumberFormat, &pColor, 
nullptr, *this);
     else
-        aStr = ScCellFormat::GetString(*this, rPos, nNumberFormat, &pColor, 
*GetFormatTable());
+        aStr = ScCellFormat::GetString(*this, rPos, nNumberFormat, &pColor, 
nullptr);
 
     SvtScriptType nRet = GetStringScriptType( aStr );
 
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index b9ef98cf40bb..17a3b72d96b6 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -3547,14 +3547,14 @@ void ScDocument::SetValue( const ScAddress& rPos, 
double fVal )
     pTab->SetValue(rPos.Col(), rPos.Row(), fVal);
 }
 
-OUString ScDocument::GetString( SCCOL nCol, SCROW nRow, SCTAB nTab, const 
ScInterpreterContext* pContext ) const
+OUString ScDocument::GetString( SCCOL nCol, SCROW nRow, SCTAB nTab, 
ScInterpreterContext* pContext ) const
 {
     if (const ScTable* pTable = FetchTable(nTab))
         return pTable->GetString(nCol, nRow, pContext);
     return OUString();
 }
 
-OUString ScDocument::GetString( const ScAddress& rPos, const 
ScInterpreterContext* pContext ) const
+OUString ScDocument::GetString( const ScAddress& rPos, ScInterpreterContext* 
pContext ) const
 {
     if (const ScTable* pTable = FetchTable(rPos.Tab()))
         return pTable->GetString(rPos.Col(), rPos.Row(), pContext);
@@ -3739,7 +3739,7 @@ void ScDocument::GetNumberFormatInfo( const 
ScInterpreterContext& rContext, SvNu
     if (nTab < GetTableCount() && maTabs[nTab])
     {
         nIndex = maTabs[nTab]->GetNumberFormat( rContext, rPos );
-        nType = rContext.GetNumberFormatType( nIndex );
+        nType = rContext.NFGetType(nIndex);
     }
     else
     {
diff --git a/sc/source/core/data/dpcache.cxx b/sc/source/core/data/dpcache.cxx
index 52109c673bd3..efc331ed8bdd 100644
--- a/sc/source/core/data/dpcache.cxx
+++ b/sc/source/core/data/dpcache.cxx
@@ -658,8 +658,8 @@ bool ScDPCache::InitFromDataBase(DBConnector& rDB)
                 if (!aData.IsEmpty())
                 {
                     maEmptyRows.insert_back(nRow, nRow+1, false);
-                    SvNumberFormatter* pFormatter = mrDoc.GetFormatTable();
-                    rField.mnNumFormat = pFormatter ? 
pFormatter->GetStandardFormat(nFormatType) : 0;
+                    ScInterpreterContext& rContext = 
mrDoc.GetNonThreadedContext();
+                    rField.mnNumFormat = 
rContext.NFGetStandardFormat(nFormatType);
                 }
 
                 ++nRow;
@@ -1068,11 +1068,8 @@ bool ScDPCache::IsDateDimension( tools::Long nDim ) const
     if (nDim >= mnColumnCount)
         return false;
 
-    SvNumberFormatter* pFormatter = mrDoc.GetFormatTable();
-    if (!pFormatter)
-        return false;
-
-    SvNumFormatType eType = pFormatter->GetType(maFields[nDim]->mnNumFormat);
+    ScInterpreterContext& rContext = mrDoc.GetNonThreadedContext();
+    SvNumFormatType eType = rContext.NFGetType(maFields[nDim]->mnNumFormat);
     return (eType == SvNumFormatType::DATE) || (eType == 
SvNumFormatType::DATETIME);
 }
 
@@ -1163,22 +1160,22 @@ SCROW ScDPCache::GetIdByItemData(tools::Long nDim, 
const ScDPItemData& rItem) co
 }
 
 // static
-sal_uInt32 ScDPCache::GetLocaleIndependentFormat( SvNumberFormatter& 
rFormatter, sal_uInt32 nNumFormat )
+sal_uInt32 ScDPCache::GetLocaleIndependentFormat(ScInterpreterContext& 
rContext, sal_uInt32 nNumFormat)
 {
     // For a date or date+time format use ISO format so it works across locales
     // and can be matched against string based item queries. For time use 24h
     // format. All others use General format, no currency, percent, ...
     // Use en-US locale for all.
-    switch (rFormatter.GetType( nNumFormat))
+    switch (rContext.NFGetType(nNumFormat))
     {
         case SvNumFormatType::DATE:
-            return rFormatter.GetFormatIndex( NF_DATE_ISO_YYYYMMDD, 
LANGUAGE_ENGLISH_US);
+            return rContext.NFGetFormatIndex( NF_DATE_ISO_YYYYMMDD, 
LANGUAGE_ENGLISH_US);
         case SvNumFormatType::TIME:
-            return rFormatter.GetFormatIndex( NF_TIME_HHMMSS, 
LANGUAGE_ENGLISH_US);
+            return rContext.NFGetFormatIndex( NF_TIME_HHMMSS, 
LANGUAGE_ENGLISH_US);
         case SvNumFormatType::DATETIME:
-            return rFormatter.GetFormatIndex( NF_DATETIME_ISO_YYYYMMDD_HHMMSS, 
LANGUAGE_ENGLISH_US);
+            return rContext.NFGetFormatIndex( NF_DATETIME_ISO_YYYYMMDD_HHMMSS, 
LANGUAGE_ENGLISH_US);
         default:
-            return rFormatter.GetFormatIndex( NF_NUMBER_STANDARD, 
LANGUAGE_ENGLISH_US);
+            return rContext.NFGetFormatIndex( NF_NUMBER_STANDARD, 
LANGUAGE_ENGLISH_US);
     }
 }
 
@@ -1190,15 +1187,15 @@ OUString 
ScDPCache::GetLocaleIndependentFormattedNumberString( double fValue )
 
 // static
 OUString ScDPCache::GetLocaleIndependentFormattedString( double fValue,
-        SvNumberFormatter& rFormatter, sal_uInt32 nNumFormat )
+        ScInterpreterContext& rContext, sal_uInt32 nNumFormat )
 {
-    nNumFormat = GetLocaleIndependentFormat( rFormatter, nNumFormat);
+    nNumFormat = GetLocaleIndependentFormat( rContext, nNumFormat);
     if ((nNumFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0)
         return GetLocaleIndependentFormattedNumberString( fValue);
 
     OUString aStr;
     const Color* pColor = nullptr;
-    rFormatter.GetOutputString( fValue, nNumFormat, aStr, &pColor);
+    rContext.NFGetOutputString( fValue, nNumFormat, aStr, &pColor);
     return aStr;
 }
 
@@ -1211,21 +1208,15 @@ OUString ScDPCache::GetFormattedString(tools::Long 
nDim, const ScDPItemData& rIt
     if (eType == ScDPItemData::Value)
     {
         // Format value using the stored number format.
-        SvNumberFormatter* pFormatter = mrDoc.GetFormatTable();
-        if (pFormatter)
-        {
-            sal_uInt32 nNumFormat = GetNumberFormat(nDim);
-            if (bLocaleIndependent)
-                return GetLocaleIndependentFormattedString( rItem.GetValue(), 
*pFormatter, nNumFormat);
-
-            OUString aStr;
-            const Color* pColor = nullptr;
-            pFormatter->GetOutputString(rItem.GetValue(), nNumFormat, aStr, 
&pColor);
-            return aStr;
-        }
-
-        // Last resort...
-        return GetLocaleIndependentFormattedNumberString( rItem.GetValue());
+        ScInterpreterContext& rContext = mrDoc.GetNonThreadedContext();
+        sal_uInt32 nNumFormat = GetNumberFormat(nDim);
+        if (bLocaleIndependent)
+            return GetLocaleIndependentFormattedString( rItem.GetValue(), 
rContext, nNumFormat);
+
+        OUString aStr;
+        const Color* pColor = nullptr;
+        rContext.NFGetOutputString(rItem.GetValue(), nNumFormat, aStr, 
&pColor);
+        return aStr;
     }
 
     if (eType == ScDPItemData::GroupValue)
@@ -1256,9 +1247,9 @@ OUString ScDPCache::GetFormattedString(tools::Long nDim, 
const ScDPItemData& rIt
     return rItem.GetString();
 }
 
-SvNumberFormatter* ScDPCache::GetNumberFormatter() const
+ScInterpreterContext& ScDPCache::GetInterpreterContext() const
 {
-    return mrDoc.GetFormatTable();
+    return mrDoc.GetNonThreadedContext();
 }
 
 tools::Long ScDPCache::AppendGroupField()
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index 1a9f5959c364..63b7021de95c 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -1888,16 +1888,13 @@ bool ScDPObject::ParseFilters(
             OUString aQueryValue = aQueryValueName;
             if (mpTableData)
             {
-                SvNumberFormatter* pFormatter = 
mpTableData->GetCacheTable().getCache().GetNumberFormatter();
-                if (pFormatter)
-                {
-                    // Parse possible number from aQueryValueName and format
-                    // locale independent as aQueryValue.
-                    sal_uInt32 nNumFormat = 0;
-                    double fValue;
-                    if (pFormatter->IsNumberFormat( aQueryValueName, 
nNumFormat, fValue))
-                        aQueryValue = 
ScDPCache::GetLocaleIndependentFormattedString( fValue, *pFormatter, 
nNumFormat);
-                }
+                ScInterpreterContext& rContext = 
mpTableData->GetCacheTable().getCache().GetInterpreterContext();
+                // Parse possible number from aQueryValueName and format
+                // locale independent as aQueryValue.
+                sal_uInt32 nNumFormat = 0;
+                double fValue;
+                if (rContext.NFIsNumberFormat(aQueryValueName, nNumFormat, 
fValue))
+                    aQueryValue = 
ScDPCache::GetLocaleIndependentFormattedString(fValue, rContext, nNumFormat);
             }
 
             for ( SCSIZE nField=0; nField<nFieldCount; nField++ )
diff --git a/sc/source/core/data/formulacell.cxx 
b/sc/source/core/data/formulacell.cxx
index bcb0a8f97cae..b2283f4aa8a8 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -947,7 +947,7 @@ size_t ScFormulaCell::GetHash() const
     return pCode->GetHash();
 }
 
-OUString ScFormulaCell::GetFormula( const FormulaGrammar::Grammar eGrammar, 
const ScInterpreterContext* pContext ) const
+OUString ScFormulaCell::GetFormula( const FormulaGrammar::Grammar eGrammar, 
ScInterpreterContext* pContext ) const
 {
     if( pCode->GetCodeError() != FormulaError::NONE && !pCode->GetLen() )
     {
@@ -1001,7 +1001,7 @@ OUString ScFormulaCell::GetFormula( const 
FormulaGrammar::Grammar eGrammar, cons
     return buffer.makeStringAndClear();
 }
 
-OUString ScFormulaCell::GetFormula( sc::CompileFormulaContext& rCxt, const 
ScInterpreterContext* pContext ) const
+OUString ScFormulaCell::GetFormula( sc::CompileFormulaContext& rCxt, 
ScInterpreterContext* pContext ) const
 {
     OUStringBuffer aBuf;
     if (pCode->GetCodeError() != FormulaError::NONE && !pCode->GetLen())
@@ -2088,7 +2088,7 @@ void ScFormulaCell::InterpretTail( ScInterpreterContext& 
rContext, ScInterpretTa
                     nFormatType = rContext.GetFormatTable()->GetType( 
nOldFormatIndex);
                 }
                 if (nOldFormatIndex !=
-                        ScGlobal::GetStandardFormat( 
*rContext.GetFormatTable(), nOldFormatIndex, nFormatType))
+                        ScGlobal::GetStandardFormat(rContext, nOldFormatIndex, 
nFormatType))
                     bForceNumberFormat = false;
             }
         }
@@ -2138,8 +2138,7 @@ void ScFormulaCell::InterpretTail( ScInterpreterContext& 
rContext, ScInterpretTa
             }
 
             if (bSetFormat && (bForceNumberFormat || ((nFormatIndex % 
SV_COUNTRY_LANGUAGE_OFFSET) == 0)))
-                nFormatIndex = 
ScGlobal::GetStandardFormat(*rContext.GetFormatTable(),
-                        nFormatIndex, nFormatType);
+                nFormatIndex = ScGlobal::GetStandardFormat(rContext, 
nFormatIndex, nFormatType);
 
             // Do not replace a General format (which was the reason why
             // mbNeedsNumberFormat was set) with a General format.
@@ -2688,19 +2687,19 @@ void ScFormulaCell::GetURLResult( OUString& rURL, 
OUString& rCellText )
     // Cell Text uses the Cell format while the URL uses
     // the default format for the type.
     const sal_uInt32 nCellFormat = rDocument.GetNumberFormat( aPos );
-    SvNumberFormatter* pFormatter = rDocument.GetFormatTable();
+    ScInterpreterContext& rContext = rDocument.GetNonThreadedContext();
 
-    const sal_uInt32 nURLFormat = ScGlobal::GetStandardFormat( *pFormatter, 
nCellFormat, SvNumFormatType::NUMBER);
+    const sal_uInt32 nURLFormat = ScGlobal::GetStandardFormat(rContext, 
nCellFormat, SvNumFormatType::NUMBER);
 
     if ( IsValue() )
     {
         double fValue = GetValue();
-        pFormatter->GetOutputString( fValue, nCellFormat, rCellText, &pColor );
+        rContext.NFGetOutputString( fValue, nCellFormat, rCellText, &pColor );
     }
     else
     {
         aCellString = GetString().getString();
-        pFormatter->GetOutputString( aCellString, nCellFormat, rCellText, 
&pColor );
+        rContext.NFGetOutputString( aCellString, nCellFormat, rCellText, 
&pColor );
     }
     ScConstMatrixRef xMat( aResult.GetMatrix());
     if (xMat)
@@ -2709,16 +2708,16 @@ void ScFormulaCell::GetURLResult( OUString& rURL, 
OUString& rCellText )
         if (!xMat->IsValue(0, 1))
             rURL = xMat->GetString(0, 1).getString();
         else
-            pFormatter->GetOutputString(
+            rContext.NFGetOutputString(
                 xMat->GetDouble(0, 1), nURLFormat, rURL, &pColor);
     }
 
     if(rURL.isEmpty())
     {
         if(IsValue())
-            pFormatter->GetOutputString( GetValue(), nURLFormat, rURL, &pColor 
);
+            rContext.NFGetOutputString( GetValue(), nURLFormat, rURL, &pColor 
);
         else
-            pFormatter->GetOutputString( aCellString, nURLFormat, rURL, 
&pColor );
+            rContext.NFGetOutputString( aCellString, nURLFormat, rURL, &pColor 
);
     }
 }
 
diff --git a/sc/source/core/data/global.cxx b/sc/source/core/data/global.cxx
index 9443d6e0324a..a46f46b3cffb 100644
--- a/sc/source/core/data/global.cxx
+++ b/sc/source/core/data/global.cxx
@@ -157,13 +157,12 @@ bool ScGlobal::HasAttrChanged( const SfxItemSet&  
rNewAttrs,
     return bInvalidate;
 }
 
-sal_uInt32 ScGlobal::GetStandardFormat( SvNumberFormatter& rFormatter,
+sal_uInt32 ScGlobal::GetStandardFormat( ScInterpreterContext& rContext,
         sal_uInt32 nFormat, SvNumFormatType nType )
 {
-    const SvNumberformat* pFormat = rFormatter.GetEntry( nFormat );
-    if ( pFormat )
-        return rFormatter.GetStandardFormat( nFormat, nType, 
pFormat->GetLanguage() );
-    return rFormatter.GetStandardFormat( nType, eLnge );
+    if (const SvNumberformat* pFormat = rContext.NFGetFormatEntry(nFormat))
+        return rContext.NFGetStandardFormat( nFormat, nType, 
pFormat->GetLanguage() );
+    return rContext.NFGetStandardFormat( nType, eLnge );
 }
 
 sal_uInt16 ScGlobal::GetStandardRowHeight()
diff --git a/sc/source/core/data/global2.cxx b/sc/source/core/data/global2.cxx
index 60c0f02dede2..4a9237a38f9f 100644
--- a/sc/source/core/data/global2.cxx
+++ b/sc/source/core/data/global2.cxx
@@ -35,6 +35,7 @@
 #include <compiler.hxx>
 #include <paramisc.hxx>
 #include <calcconfig.hxx>
+#include <interpretercontext.hxx>
 
 // struct ScImportParam:
 
@@ -351,7 +352,7 @@ bool isEmptyString( const OUString& rStr )
 
 double ScGlobal::ConvertStringToValue( const OUString& rStr, const 
ScCalcConfig& rConfig,
         FormulaError & rError, FormulaError nStringNoValueError,
-        SvNumberFormatter* pFormatter, SvNumFormatType & rCurFmtType )
+        ScInterpreterContext& rContext, SvNumFormatType & rCurFmtType )
 {
     // We keep ScCalcConfig::StringConversion::LOCALE default until
     // we provide a friendly way to convert string numbers into numbers in the 
UI.
@@ -385,11 +386,8 @@ double ScGlobal::ConvertStringToValue( const OUString& 
rStr, const ScCalcConfig&
                         return fValue;
                 }
 
-                if (!pFormatter)
-                    goto Label_fallback_to_unambiguous;
-
                 sal_uInt32 nFIndex = 0;
-                if (!pFormatter->IsNumberFormat(rStr, nFIndex, fValue))
+                if (!rContext.NFIsNumberFormat(rStr, nFIndex, fValue))
                 {
                     rError = nStringNoValueError;
                     fValue = 0.0;
@@ -398,7 +396,6 @@ double ScGlobal::ConvertStringToValue( const OUString& 
rStr, const ScCalcConfig&
             }
             break;
         case ScCalcConfig::StringConversion::UNAMBIGUOUS:
-Label_fallback_to_unambiguous:
             {
                 if (!rConfig.mbEmptyStringAsZero)
                 {
@@ -565,14 +562,7 @@ Label_fallback_to_unambiguous:
                                     rError = nStringNoValueError;
                                 else
                                 {
-                                    if (pFormatter)
-                                        fValue = aDate - 
pFormatter->GetNullDate();
-                                    else
-                                    {
-                                        
SAL_WARN("sc.core","ScGlobal::ConvertStringToValue - fixed null date");
-                                        static Date aDefaultNullDate( 30, 12, 
1899);
-                                        fValue = aDate - aDefaultNullDate;
-                                    }
+                                    fValue = aDate - rContext.NFGetNullDate();
                                 }
                             }
                             fValue += ((nUnit[hour] * 3600) + (nUnit[minute] * 
60) + nUnit[second] + fFraction) / 86400.0;
diff --git a/sc/source/core/data/patattr.cxx b/sc/source/core/data/patattr.cxx
index c847d4b35128..79d848f91e3c 100644
--- a/sc/source/core/data/patattr.cxx
+++ b/sc/source/core/data/patattr.cxx
@@ -1659,7 +1659,7 @@ sal_uInt32 ScPatternAttr::GetNumberFormat( const 
ScInterpreterContext& rContext
     if ( nFormat < SV_COUNTRY_LANGUAGE_OFFSET && eLang == LANGUAGE_SYSTEM )
         ;       // it remains as it is
     else
-        nFormat = rContext.GetFormatForLanguageIfBuiltIn( nFormat, eLang );
+        nFormat = rContext.NFGetFormatForLanguageIfBuiltIn( nFormat, eLang );
     return nFormat;
 }
 
@@ -1693,6 +1693,33 @@ sal_uInt32 ScPatternAttr::GetNumberFormat( 
SvNumberFormatter* pFormatter,
     return pFormatter->GetFormatForLanguageIfBuiltIn(nFormat, eLang);
 }
 
+sal_uInt32 ScPatternAttr::GetNumberFormat( const ScInterpreterContext& 
rContext,
+                                           const SfxItemSet* pCondSet ) const
+{
+    if (!pCondSet)
+        return GetNumberFormat(rContext);
+
+    // Conditional format takes precedence over style and even hard format.
+
+    sal_uInt32 nFormat;
+    LanguageType eLang;
+    if (pCondSet->GetItemState(ATTR_VALUE_FORMAT) == SfxItemState::SET )
+    {
+        nFormat = getNumberFormatKey(*pCondSet);
+        if (pCondSet->GetItemState(ATTR_LANGUAGE_FORMAT) == SfxItemState::SET)
+            eLang = getLanguageType(*pCondSet);
+        else
+            eLang = getLanguageType(GetItemSet());
+    }
+    else
+    {
+        nFormat = getNumberFormatKey(GetItemSet());
+        eLang = getLanguageType(GetItemSet());
+    }
+
+    return rContext.NFGetFormatForLanguageIfBuiltIn(nFormat, eLang);
+}
+
 const SfxPoolItem& ScPatternAttr::GetItem( sal_uInt16 nWhich, const 
SfxItemSet& rItemSet, const SfxItemSet* pCondSet )
 {
     const SfxPoolItem* pCondItem;
diff --git a/sc/source/core/data/queryevaluator.cxx 
b/sc/source/core/data/queryevaluator.cxx
index 174e1e0989c7..03d9d19a8dd1 100644
--- a/sc/source/core/data/queryevaluator.cxx
+++ b/sc/source/core/data/queryevaluator.cxx
@@ -100,7 +100,7 @@ void ScQueryEvaluator::setupCollatorIfNeeded()
 }
 
 ScQueryEvaluator::ScQueryEvaluator(ScDocument& rDoc, const ScTable& rTab,
-                                   const ScQueryParam& rParam, const 
ScInterpreterContext* pContext,
+                                   const ScQueryParam& rParam, 
ScInterpreterContext* pContext,
                                    bool* pTestEqualCondition)
     : mrDoc(rDoc)
     , mrStrPool(rDoc.GetSharedStringPool())
@@ -327,9 +327,7 @@ OUString ScQueryEvaluator::getCellString(const 
ScRefCellValue& rCell, SCROW nRow
         sal_uInt32 nFormat
             = mpContext ? mrTab.GetNumberFormat(*mpContext, ScAddress(nCol, 
nRow, mrTab.GetTab()))
                         : mrTab.GetNumberFormat(nCol, nRow);
-        SvNumberFormatter* pFormatter
-            = mpContext ? mpContext->GetFormatTable() : mrDoc.GetFormatTable();
-        return ScCellFormat::GetInputString(rCell, nFormat, *pFormatter, 
mrDoc, sharedString, true);
+        return ScCellFormat::GetInputString(rCell, nFormat, mpContext, mrDoc, 
sharedString, true);
     }
 }
 
diff --git a/sc/source/core/data/queryiter.cxx 
b/sc/source/core/data/queryiter.cxx
index d931b9429925..e3db0aefa39e 100644
--- a/sc/source/core/data/queryiter.cxx
+++ b/sc/source/core/data/queryiter.cxx
@@ -84,7 +84,7 @@ ScQueryCellIteratorBase< accessType, queryType 
>::ScQueryCellIteratorBase(ScDocu
         ScQueryEntry& rEntry = maParam.GetEntry(i);
         ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
         sal_uInt32 nIndex = 0;
-        bool bNumber = mrContext.GetFormatTable()->IsNumberFormat(
+        bool bNumber = mrContext.NFIsNumberFormat(
             rItem.maString.getString(), nIndex, rItem.mfVal);
         rItem.meType = bNumber ? ScQueryEntry::ByValue : 
ScQueryEntry::ByString;
     }
@@ -417,7 +417,6 @@ bool ScQueryCellIteratorBase< accessType, queryType 
>::BinarySearch( SCCOL col,
         return false;
 
     CollatorWrapper& rCollator = ScGlobal::GetCollator(maParam.bCaseSens);
-    SvNumberFormatter& rFormatter = *(mrContext.GetFormatTable());
     const ScQueryEntry& rEntry = maParam.GetEntry(0);
     const ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
     bool bAscending = rEntry.eOp == SC_LESS || rEntry.eOp == SC_LESS_EQUAL || 
rEntry.eOp == SC_EQUAL;
@@ -437,7 +436,7 @@ bool ScQueryCellIteratorBase< accessType, queryType 
>::BinarySearch( SCCOL col,
         {
             ScRefCellValue aCell = sc::toRefCell(aPos.first, aPos.second);
             sal_uInt32 nFormat = pCol->GetNumberFormat(mrContext, nRow);
-            OUString aCellStr = ScCellFormat::GetInputString(aCell, nFormat, 
rFormatter, rDoc);
+            OUString aCellStr = ScCellFormat::GetInputString(aCell, nFormat, 
&mrContext, rDoc);
             sal_Int32 nTmp = rCollator.compareString(aCellStr, 
rEntry.GetQueryItem().maString.getString());
             if ((rEntry.eOp == SC_LESS_EQUAL && nTmp > 0) ||
                     (rEntry.eOp == SC_GREATER_EQUAL && nTmp < 0) ||
@@ -492,7 +491,7 @@ bool ScQueryCellIteratorBase< accessType, queryType 
>::BinarySearch( SCCOL col,
     if (bForceStr || aCell.hasString())
     {
         sal_uInt32 nFormat = pCol->GetNumberFormat(mrContext, 
aCellData.second);
-        aLastInRangeString = ScCellFormat::GetInputString(aCell, nFormat, 
rFormatter, rDoc);
+        aLastInRangeString = ScCellFormat::GetInputString(aCell, nFormat, 
&mrContext, rDoc);
     }
     else
     {
@@ -588,7 +587,7 @@ bool ScQueryCellIteratorBase< accessType, queryType 
>::BinarySearch( SCCOL col,
         else if (bStr && bByString)
         {
             sal_uInt32 nFormat = pCol->GetNumberFormat(mrContext, 
aCellData.second);
-            OUString aCellStr = ScCellFormat::GetInputString(aCell, nFormat, 
rFormatter, rDoc);
+            OUString aCellStr = ScCellFormat::GetInputString(aCell, nFormat, 
&mrContext, rDoc);
 
             nRes = rCollator.compareString(aCellStr, 
rEntry.GetQueryItem().maString.getString());
             if (nRes < 0 && bAscending)
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index b0f2fa1537b5..7d03ef681016 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -575,7 +575,7 @@ void ScTable::CopyStaticToDocument(
         for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
         {
             sal_uInt32 nNumFmt = 
aDefaultColData.GetPattern(nRow)->GetNumberFormat(
-                rDocument.GetNonThreadedContext().GetFormatTable());
+                rDocument.GetNonThreadedContext());
             SvNumberFormatterMergeMap::const_iterator itNum = 
rMap.find(nNumFmt);
             if (itNum != rMap.end())
                 nNumFmt = itNum->second;
@@ -1796,7 +1796,7 @@ void ScTable::SetRawString( SCCOL nCol, SCROW nRow, const 
svl::SharedString& rSt
         CreateColumnIfNotExists(nCol).SetRawString(nRow, rStr);
 }
 
-OUString ScTable::GetString( SCCOL nCol, SCROW nRow, const 
ScInterpreterContext* pContext ) const
+OUString ScTable::GetString( SCCOL nCol, SCROW nRow, ScInterpreterContext* 
pContext ) const
 {
     if (ValidColRow(nCol,nRow) && nCol < GetAllocatedColumnsCount())
         return aCol[nCol].GetString( nRow, pContext );
diff --git a/sc/source/core/data/table5.cxx b/sc/source/core/data/table5.cxx
index 39837464ca71..408ca950b6aa 100644
--- a/sc/source/core/data/table5.cxx
+++ b/sc/source/core/data/table5.cxx
@@ -1064,13 +1064,11 @@ Color ScTable::GetCellTextColor(ScAddress aPos) const
 
         if (pPattern->GetItem(ATTR_VALUE_FORMAT).GetValue())
         {
-            SvNumberFormatter* pNumberFormatter = GetDoc().GetFormatTable();
             const SfxUInt32Item pItem = pPattern->GetItem(ATTR_VALUE_FORMAT);
             auto& rDoc = const_cast<ScDocument&>(GetDoc());
             const Color* pColor;
             ScRefCellValue aCell(rDoc, aPos);
-            ScCellFormat::GetString(rDoc, aPos, pItem.GetValue(), &pColor, 
*pNumberFormatter, false,
-                                    false);
+            ScCellFormat::GetString(rDoc, aPos, pItem.GetValue(), &pColor, 
nullptr, false, false);
             if (pColor)
                 return *pColor;
         }
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index a5b25dad13dc..960390f2b206 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -247,7 +247,6 @@ private:
     ScJumpMatrix*   pJumpMatrix;        // currently active array condition, 
if any
     ScTokenMatrixMap maTokenMatrixMap;  // map FormulaToken* to 
formula::FormulaTokenRef if in array condition
     ScFormulaCell* pMyFormulaCell;      // the cell of this formula expression
-    SvNumberFormatter* pFormatter;
 
     const formula::FormulaToken* pCur;  // current token
     ScTokenStack* pStackObj;            // contains the stacks
diff --git a/sc/source/core/tool/cellform.cxx b/sc/source/core/tool/cellform.cxx
index 9d1a73192923..875e3ac3f396 100644
--- a/sc/source/core/tool/cellform.cxx
+++ b/sc/source/core/tool/cellform.cxx
@@ -29,23 +29,25 @@
 #include <editutil.hxx>
 
 OUString ScCellFormat::GetString( const ScRefCellValue& rCell, sal_uInt32 
nFormat,
-                              const Color** ppColor, SvNumberFormatter& 
rFormatter, const ScDocument& rDoc,
+                              const Color** ppColor, ScInterpreterContext* 
pContext, const ScDocument& rDoc,
                               bool bNullVals, bool bFormula, bool 
bUseStarFormat )
 {
     *ppColor = nullptr;
 
+    ScInterpreterContext& rContext = pContext ? *pContext : 
rDoc.GetNonThreadedContext();
+
     switch (rCell.getType())
     {
         case CELLTYPE_STRING:
         {
             OUString str;
-            rFormatter.GetOutputString(rCell.getSharedString()->getString(), 
nFormat, str, ppColor, bUseStarFormat);
+            rContext.NFGetOutputString(rCell.getSharedString()->getString(), 
nFormat, str, ppColor, bUseStarFormat);
             return str;
         }
         case CELLTYPE_EDIT:
         {
             OUString str;
-            rFormatter.GetOutputString(rCell.getString(&rDoc), nFormat, str, 
ppColor );
+            rContext.NFGetOutputString(rCell.getString(&rDoc), nFormat, str, 
ppColor );
             return str;
         }
         case CELLTYPE_VALUE:
@@ -56,7 +58,7 @@ OUString ScCellFormat::GetString( const ScRefCellValue& 
rCell, sal_uInt32 nForma
             else
             {
                 OUString str;
-                rFormatter.GetOutputString( nValue, nFormat, str, ppColor, 
bUseStarFormat );
+                rContext.NFGetOutputString( nValue, nFormat, str, ppColor, 
bUseStarFormat );
                 return str;
             }
         }
@@ -97,14 +99,14 @@ OUString ScCellFormat::GetString( const ScRefCellValue& 
rCell, sal_uInt32 nForma
                         else
                         {
                             OUString str;
-                            rFormatter.GetOutputString( fValue, nFormat, str, 
ppColor, bUseStarFormat );
+                            rContext.NFGetOutputString( fValue, nFormat, str, 
ppColor, bUseStarFormat );
                             return str;
                         }
                     }
                     else
                     {
                         OUString str;
-                        rFormatter.GetOutputString( 
pFCell->GetString().getString(),
+                        rContext.NFGetOutputString( 
pFCell->GetString().getString(),
                                                     nFormat, str, ppColor, 
bUseStarFormat );
                         return str;
                     }
@@ -118,18 +120,20 @@ OUString ScCellFormat::GetString( const ScRefCellValue& 
rCell, sal_uInt32 nForma
 
 OUString ScCellFormat::GetString(
     ScDocument& rDoc, const ScAddress& rPos, sal_uInt32 nFormat, const Color** 
ppColor,
-    SvNumberFormatter& rFormatter, bool bNullVals, bool bFormula )
+    ScInterpreterContext* pContext, bool bNullVals, bool bFormula )
 {
     *ppColor = nullptr;
 
     ScRefCellValue aCell(rDoc, rPos);
-    return GetString(aCell, nFormat, ppColor, rFormatter, rDoc, bNullVals, 
bFormula);
+    return GetString(aCell, nFormat, ppColor, pContext, rDoc, bNullVals, 
bFormula);
 }
 
 OUString ScCellFormat::GetInputString(
-    const ScRefCellValue& rCell, sal_uInt32 nFormat, SvNumberFormatter& 
rFormatter, const ScDocument& rDoc,
+    const ScRefCellValue& rCell, sal_uInt32 nFormat, ScInterpreterContext* 
pContext, const ScDocument& rDoc,
     const svl::SharedString** pShared, bool bFiltering, bool 
bForceSystemLocale )
 {
+    ScInterpreterContext& rContext = pContext ? *pContext : 
rDoc.GetNonThreadedContext();
+
     if(pShared != nullptr)
         *pShared = nullptr;
     switch (rCell.getType())
@@ -140,7 +144,7 @@ OUString ScCellFormat::GetInputString(
         case CELLTYPE_VALUE:
         {
             OUString str;
-            rFormatter.GetInputLineString(rCell.getDouble(), nFormat, str, 
bFiltering, bForceSystemLocale);
+            rContext.NFGetInputLineString(rCell.getDouble(), nFormat, str, 
bFiltering, bForceSystemLocale);
             return str;
         }
         break;
@@ -153,7 +157,7 @@ OUString ScCellFormat::GetInputString(
             else if (pFC->IsValue())
             {
                 str.emplace();
-                rFormatter.GetInputLineString(pFC->GetValue(), nFormat, *str, 
bFiltering, bForceSystemLocale);
+                rContext.NFGetInputLineString(pFC->GetValue(), nFormat, *str, 
bFiltering, bForceSystemLocale);
             }
             else
             {
@@ -210,7 +214,7 @@ OUString ScCellFormat::GetOutputString( ScDocument& rDoc, 
const ScAddress& rPos,
         //  like in GetString for document (column)
         const Color* pColor;
         sal_uInt32 nNumFmt = rDoc.GetNumberFormat(rPos);
-        return GetString(rCell, nNumFmt, &pColor, *rDoc.GetFormatTable(), 
rDoc);
+        return GetString(rCell, nNumFmt, &pColor, nullptr, rDoc);
     }
 }
 
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 152a75f949b1..7b655d72c944 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -1846,12 +1846,11 @@ struct ConventionXL_R1C1 : public 
ScCompiler::Convention, public ConventionXL
 }
 
 ScCompiler::ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& 
rPos, ScTokenArray& rArr,
-                        bool bComputeII, bool bMatrixFlag, const 
ScInterpreterContext* pContext )
+                        bool bComputeII, bool bMatrixFlag, 
ScInterpreterContext* pContext )
     : FormulaCompiler(rArr, bComputeII, bMatrixFlag),
     rDoc(rCxt.getDoc()),
     aPos(rPos),
-    mpFormatter(pContext ? pContext->GetFormatTable() : rDoc.GetFormatTable()),
-    mpInterpreterContext(pContext),
+    mrInterpreterContext(pContext ? *pContext : rDoc.GetNonThreadedContext()),
     mnCurrentSheetTab(-1),
     mnCurrentSheetEndPos(0),
     pCharClass(&ScGlobal::getCharClass()),
@@ -1870,12 +1869,11 @@ ScCompiler::ScCompiler( sc::CompileFormulaContext& 
rCxt, const ScAddress& rPos,
 
 ScCompiler::ScCompiler( ScDocument& rDocument, const ScAddress& rPos, 
ScTokenArray& rArr,
                         formula::FormulaGrammar::Grammar eGrammar,
-                        bool bComputeII, bool bMatrixFlag, const 
ScInterpreterContext* pContext )
+                        bool bComputeII, bool bMatrixFlag, 
ScInterpreterContext* pContext )
     : FormulaCompiler(rArr, bComputeII, bMatrixFlag),
         rDoc( rDocument ),
         aPos( rPos ),
-        mpFormatter(pContext ? pContext->GetFormatTable() : 
rDoc.GetFormatTable()),
-        mpInterpreterContext(pContext),
+        mrInterpreterContext(pContext ? *pContext : 
rDoc.GetNonThreadedContext()),
         mnCurrentSheetTab(-1),
         mnCurrentSheetEndPos(0),
         nSrcPos(0),
@@ -1895,12 +1893,11 @@ ScCompiler::ScCompiler( ScDocument& rDocument, const 
ScAddress& rPos, ScTokenArr
 }
 
 ScCompiler::ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& rPos,
-                        bool bComputeII, bool bMatrixFlag, const 
ScInterpreterContext* pContext )
+                        bool bComputeII, bool bMatrixFlag, 
ScInterpreterContext* pContext )
     : FormulaCompiler(bComputeII, bMatrixFlag),
     rDoc(rCxt.getDoc()),
     aPos(rPos),
-    mpFormatter(pContext ? pContext->GetFormatTable() : rDoc.GetFormatTable()),
-    mpInterpreterContext(pContext),
+    mrInterpreterContext(pContext ? *pContext : rDoc.GetNonThreadedContext()),
     mnCurrentSheetTab(-1),
     mnCurrentSheetEndPos(0),
     pCharClass(&ScGlobal::getCharClass()),
@@ -1919,12 +1916,11 @@ ScCompiler::ScCompiler( sc::CompileFormulaContext& 
rCxt, const ScAddress& rPos,
 
 ScCompiler::ScCompiler( ScDocument& rDocument, const ScAddress& rPos,
                         formula::FormulaGrammar::Grammar eGrammar,
-                        bool bComputeII, bool bMatrixFlag, const 
ScInterpreterContext* pContext )
+                        bool bComputeII, bool bMatrixFlag, 
ScInterpreterContext* pContext )
         : FormulaCompiler(bComputeII, bMatrixFlag),
         rDoc( rDocument ),
         aPos( rPos ),
-        mpFormatter(pContext ? pContext->GetFormatTable() : 
rDoc.GetFormatTable()),
-        mpInterpreterContext(pContext),
+        mrInterpreterContext(pContext ? *pContext : 
rDoc.GetNonThreadedContext()),
         mnCurrentSheetTab(-1),
         mnCurrentSheetEndPos(0),
         nSrcPos(0),
@@ -3168,12 +3164,12 @@ bool ScCompiler::ParseValue( const OUString& rSym )
     }
 
     double fVal;
-    sal_uInt32 nIndex = mxSymbols->isEnglishLocale() ? 
mpFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US) : 0;
+    sal_uInt32 nIndex = mxSymbols->isEnglishLocale() ? 
mrInterpreterContext.NFGetStandardIndex(LANGUAGE_ENGLISH_US) : 0;
 
-    if (!mpFormatter->IsNumberFormat(rSym, nIndex, fVal))
+    if (!mrInterpreterContext.NFIsNumberFormat(rSym, nIndex, fVal))
         return false;
 
-    SvNumFormatType nType = mpFormatter->GetType(nIndex);
+    SvNumFormatType nType = mrInterpreterContext.NFGetType(nIndex);
 
     // Don't accept 3:3 as time, it is a reference to entire row 3 instead.
     // Dates should never be entered directly and automatically converted
@@ -5358,7 +5354,7 @@ void ScCompiler::CreateStringFromSingleRef( 
OUStringBuffer& rBuffer, const Formu
         ScAddress aAbs = rRef.toAbs(rDoc, aPos);
         if (rDoc.HasStringData(aAbs.Col(), aAbs.Row(), aAbs.Tab()))
         {
-            OUString aStr = rDoc.GetString(aAbs, mpInterpreterContext);
+            OUString aStr = rDoc.GetString(aAbs, &mrInterpreterContext);
             // Enquote to SingleQuoted.
             aStr = aStr.replaceAll(u"'", u"''");
             rBuffer.append('\'');
@@ -5387,7 +5383,7 @@ void ScCompiler::CreateStringFromSingleRef( 
OUStringBuffer& rBuffer, const Formu
             {
                 SAL_WARN("sc.core", "ScCompiler::CreateStringFromSingleRef - 
TableRef falling back to cell: " <<
                         aAbs.Format( ScRefFlags::VALID | ScRefFlags::TAB_3D, 
&rDoc));
-                aStr = rDoc.GetString(aAbs, mpInterpreterContext);
+                aStr = rDoc.GetString(aAbs, &mrInterpreterContext);
             }
             else
             {
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 1c85074f9ac0..34aaba80de96 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -2128,7 +2128,7 @@ void ScInterpreter::ScIsLogical()
                 if (aCell.hasNumeric())
                 {
                     sal_uInt32 nFormat = GetCellNumberFormat(aAdr, aCell);
-                    bRes = (pFormatter->GetType(nFormat) == 
SvNumFormatType::LOGICAL);
+                    bRes = (mrContext.NFGetType(nFormat) == 
SvNumFormatType::LOGICAL);
                 }
             }
         }
@@ -2176,7 +2176,7 @@ void ScInterpreter::ScType()
                     case CELLTYPE_VALUE :
                     {
                         sal_uInt32 nFormat = GetCellNumberFormat(aAdr, aCell);
-                        if (pFormatter->GetType(nFormat) == 
SvNumFormatType::LOGICAL)
+                        if (mrContext.NFGetType(nFormat) == 
SvNumFormatType::LOGICAL)
                             nType = 4;
                         else
                             nType = 1;
@@ -2244,9 +2244,9 @@ static bool lcl_FormatHasOpenPar( const SvNumberformat* 
pFormat )
 
 namespace {
 
-void getFormatString(const SvNumberFormatter* pFormatter, sal_uLong nFormat, 
OUString& rFmtStr)
+void getFormatString(const ScInterpreterContext& rContext, sal_uLong nFormat, 
OUString& rFmtStr)
 {
-    rFmtStr = pFormatter->GetCalcCellReturn( nFormat);
+    rFmtStr = rContext.NFGetCalcCellReturn(nFormat);
 }
 
 }
@@ -2459,17 +2459,17 @@ void ScInterpreter::ScCell()
         {   // specific format code for standard formats
             OUString aFuncResult;
             sal_uInt32 nFormat = mrDoc.GetNumberFormat( aCellPos );
-            getFormatString(pFormatter, nFormat, aFuncResult);
+            getFormatString(mrContext, nFormat, aFuncResult);
             PushString( aFuncResult );
         }
         else if( aInfoType == "COLOR" )
         {   // 1 = negative values are colored, otherwise 0
-            const SvNumberformat* pFormat = pFormatter->GetEntry( 
mrDoc.GetNumberFormat( aCellPos ) );
+            const SvNumberformat* pFormat = mrContext.NFGetFormatEntry( 
mrDoc.GetNumberFormat( aCellPos ) );
             PushInt( lcl_FormatHasNegColor( pFormat ) ? 1 : 0 );
         }
         else if( aInfoType == "PARENTHESES" )
         {   // 1 = format string contains a '(' character, otherwise 0
-            const SvNumberformat* pFormat = pFormatter->GetEntry( 
mrDoc.GetNumberFormat( aCellPos ) );
+            const SvNumberformat* pFormat = mrContext.NFGetFormatEntry( 
mrDoc.GetNumberFormat( aCellPos ) );
             PushInt( lcl_FormatHasOpenPar( pFormat ) ? 1 : 0 );
         }
         else
@@ -2607,7 +2607,7 @@ void ScInterpreter::ScCellExternal()
     {
         OUString aFmtStr;
         sal_uLong nFmt = aFmt.mbIsSet ? aFmt.mnIndex : 0;
-        getFormatString(pFormatter, nFmt, aFmtStr);
+        getFormatString(mrContext, nFmt, aFmtStr);
         PushString(aFmtStr);
     }
     else if ( aInfoType == "COLOR" )
@@ -2616,7 +2616,7 @@ void ScInterpreter::ScCellExternal()
         int nVal = 0;
         if (aFmt.mbIsSet)
         {
-            const SvNumberformat* pFormat = pFormatter->GetEntry(aFmt.mnIndex);
+            const SvNumberformat* pFormat = 
mrContext.NFGetFormatEntry(aFmt.mnIndex);
             nVal = lcl_FormatHasNegColor(pFormat) ? 1 : 0;
         }
         PushInt(nVal);
@@ -2627,7 +2627,7 @@ void ScInterpreter::ScCellExternal()
         int nVal = 0;
         if (aFmt.mbIsSet)
         {
-            const SvNumberformat* pFormat = pFormatter->GetEntry(aFmt.mnIndex);
+            const SvNumberformat* pFormat = 
mrContext.NFGetFormatEntry(aFmt.mnIndex);
             nVal = lcl_FormatHasOpenPar(pFormat) ? 1 : 0;
         }
         PushInt(nVal);
@@ -3410,7 +3410,7 @@ void ScInterpreter::ScValue()
     }
 
     sal_uInt32 nFIndex = 0;     // 0 for default locale
-    if (pFormatter->IsNumberFormat(aInputString, nFIndex, fVal))
+    if (mrContext.NFIsNumberFormat(aInputString, nFIndex, fVal))
         PushDouble(fVal);
     else
         PushIllegalArgument();
@@ -5636,7 +5636,7 @@ void ScInterpreter::IterateParametersIf( ScIterFuncIf 
eFunc )
             }
             else
             {
-                rParam.FillInExcelSyntax(mrDoc.GetSharedStringPool(), 
aString.getString(), 0, pFormatter);
+                rParam.FillInExcelSyntax(mrDoc.GetSharedStringPool(), 
aString.getString(), 0, &mrContext);
                 if (rItem.meType == ScQueryEntry::ByString)
                     rParam.eSearchType = 
DetectSearchType(rItem.maString.getString(), mrDoc);
             }
@@ -5930,7 +5930,7 @@ void ScInterpreter::ScCountIf()
             }
             else
             {
-                rParam.FillInExcelSyntax(mrDoc.GetSharedStringPool(), 
aString.getString(), 0, pFormatter);
+                rParam.FillInExcelSyntax(mrDoc.GetSharedStringPool(), 
aString.getString(), 0, &mrContext);
                 if (rItem.meType == ScQueryEntry::ByString)
                     rParam.eSearchType = 
DetectSearchType(rItem.maString.getString(), mrDoc);
             }
@@ -6242,7 +6242,7 @@ void ScInterpreter::IterateParametersIfs( 
double(*ResultFunc)( const sc::ParamIf
             }
             else
             {
-                rParam.FillInExcelSyntax(mrDoc.GetSharedStringPool(), 
aString.getString(), 0, pFormatter);
+                rParam.FillInExcelSyntax(mrDoc.GetSharedStringPool(), 
aString.getString(), 0, &mrContext);
                 if (rItem.meType == ScQueryEntry::ByString)
                     rParam.eSearchType = 
DetectSearchType(rItem.maString.getString(), mrDoc);
             }
@@ -8571,7 +8571,7 @@ std::unique_ptr<ScDBQueryParamBase> 
ScInterpreter::GetDBParams( bool& rMissingFi
                 ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
                 sal_uInt32 nIndex = 0;
                 OUString aQueryStr = rItem.maString.getString();
-                bool bNumber = pFormatter->IsNumberFormat(
+                bool bNumber = mrContext.NFIsNumberFormat(
                     aQueryStr, nIndex, rItem.mfVal);
                 rItem.meType = bNumber ? ScQueryEntry::ByValue : 
ScQueryEntry::ByString;
 
@@ -9668,18 +9668,18 @@ void ScInterpreter::ScCurrency()
     const Color* pColor = nullptr;
     if ( fDec < 0.0 )
         fDec = 0.0;
-    sal_uLong nIndex = pFormatter->GetStandardFormat(
+    sal_uLong nIndex = mrContext.NFGetStandardFormat(
                                     SvNumFormatType::CURRENCY,
                                     ScGlobal::eLnge);
-    if ( static_cast<sal_uInt16>(fDec) != pFormatter->GetFormatPrecision( 
nIndex ) )
+    if ( static_cast<sal_uInt16>(fDec) != mrContext.NFGetFormatPrecision( 
nIndex ) )
     {
-        OUString sFormatString = pFormatter->GenerateFormat(
+        OUString sFormatString = mrContext.NFGenerateFormat(
                                                nIndex,
                                                ScGlobal::eLnge,
                                                true,        // with thousands 
separator
                                                false,       // not red
-                                              
static_cast<sal_uInt16>(fDec));// decimal places
-        if (!pFormatter->GetPreviewString(sFormatString,
+                                               
static_cast<sal_uInt16>(fDec));// decimal places
+        if (!mrContext.NFGetPreviewString(sFormatString,
                                           fVal,
                                           aStr,
                                           &pColor,
@@ -9688,7 +9688,7 @@ void ScInterpreter::ScCurrency()
     }
     else
     {
-        pFormatter->GetOutputString(fVal, nIndex, aStr, &pColor);
+        mrContext.NFGetOutputString(fVal, nIndex, aStr, &pColor);
     }
     PushString(aStr);
 }
@@ -9767,16 +9767,16 @@ void ScInterpreter::ScFixed()
     const Color* pColor = nullptr;
     if (fDec < 0.0)
         fDec = 0.0;
-    sal_uLong nIndex = pFormatter->GetStandardFormat(
+    sal_uLong nIndex = mrContext.NFGetStandardFormat(
                                         SvNumFormatType::NUMBER,
                                         ScGlobal::eLnge);
-    OUString sFormatString = pFormatter->GenerateFormat(
+    OUString sFormatString = mrContext.NFGenerateFormat(
                                            nIndex,
                                            ScGlobal::eLnge,
                                            bThousand,   // with thousands 
separator
                                            false,       // not red
                                            static_cast<sal_uInt16>(fDec));// 
decimal places
-    if (!pFormatter->GetPreviewString(sFormatString,
+    if (!mrContext.NFGetPreviewString(sFormatString,
                                               fVal,
                                               aStr,
                                               &pColor,
@@ -10503,7 +10503,7 @@ void ScInterpreter::ScText()
             eCellLang = ScGlobal::eLnge;
         if (bString)
         {
-            if (!pFormatter->GetPreviewString( sFormatString, aStr.getString(),
+            if (!mrContext.NFGetPreviewString( sFormatString, aStr.getString(),
                         aResult, &pColor, eCellLang))
                 PushIllegalArgument();
             else
@@ -10511,7 +10511,7 @@ void ScInterpreter::ScText()
         }
         else
         {
-            if (!pFormatter->GetPreviewStringGuess( sFormatString, fVal,
+            if (!mrContext.NFGetPreviewStringGuess( sFormatString, fVal,
                         aResult, &pColor, eCellLang))
                 PushIllegalArgument();
             else
diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx
index 61f88d638a00..2d87abed4789 100644
--- a/sc/source/core/tool/interpr2.cxx
+++ b/sc/source/core/tool/interpr2.cxx
@@ -64,7 +64,7 @@ double ScInterpreter::GetDateSerial( sal_Int16 nYear, 
sal_Int16 nMonth, sal_Int1
         bool bStrict )
 {
     if ( nYear < 100 && !bStrict )
-        nYear = pFormatter->ExpandTwoDigitYear( nYear );
+        nYear = mrContext.NFExpandTwoDigitYear( nYear );
     // Do not use a default Date ctor here because it asks system time with a
     // performance penalty.
     sal_Int16 nY, nM, nD;
@@ -92,7 +92,7 @@ double ScInterpreter::GetDateSerial( sal_Int16 nYear, 
sal_Int16 nMonth, sal_Int1
     if (!bStrict)
         aDate.AddDays( nDay - 1 );
     if (aDate.IsValidAndGregorian())
-        return static_cast<double>(aDate - pFormatter->GetNullDate());
+        return static_cast<double>(aDate - mrContext.NFGetNullDate());
     else
     {
         SetError(FormulaError::NoValue);
@@ -104,7 +104,7 @@ void ScInterpreter::ScGetActDate()
 {
     nFuncFmtType = SvNumFormatType::DATE;
     Date aActDate( Date::SYSTEM );
-    tools::Long nDiff = aActDate - pFormatter->GetNullDate();
+    tools::Long nDiff = aActDate - mrContext.NFGetNullDate();
     PushDouble(static_cast<double>(nDiff));
 }
 
@@ -112,7 +112,7 @@ void ScInterpreter::ScGetActTime()
 {
     nFuncFmtType = SvNumFormatType::DATETIME;
     DateTime aActTime( DateTime::SYSTEM );
-    tools::Long nDiff = aActTime - pFormatter->GetNullDate();
+    tools::Long nDiff = aActTime - mrContext.NFGetNullDate();
     double fTime = aActTime.GetHour()    / 
static_cast<double>(::tools::Time::hourPerDay)   +
                    aActTime.GetMin()     / 
static_cast<double>(::tools::Time::minutePerDay) +
                    aActTime.GetSec()     / 
static_cast<double>(::tools::Time::secondPerDay) +
@@ -122,21 +122,21 @@ void ScInterpreter::ScGetActTime()
 
 void ScInterpreter::ScGetYear()
 {
-    Date aDate = pFormatter->GetNullDate();
+    Date aDate = mrContext.NFGetNullDate();
     aDate.AddDays( GetFloor32());
     PushDouble( static_cast<double>(aDate.GetYear()) );
 }
 
 void ScInterpreter::ScGetMonth()
 {
-    Date aDate = pFormatter->GetNullDate();
+    Date aDate = mrContext.NFGetNullDate();
     aDate.AddDays( GetFloor32());
     PushDouble( static_cast<double>(aDate.GetMonth()) );
 }
 
 void ScInterpreter::ScGetDay()
 {
-    Date aDate = pFormatter->GetNullDate();
+    Date aDate = mrContext.NFGetNullDate();
     aDate.AddDays( GetFloor32());
     PushDouble(static_cast<double>(aDate.GetDay()));
 }
@@ -173,9 +173,9 @@ void ScInterpreter::ScGetDateValue()
     OUString aInputString = GetString().getString();
     sal_uInt32 nFIndex = 0;                 // for a default country/language
     double fVal;
-    if (pFormatter->IsNumberFormat(aInputString, nFIndex, fVal))
+    if (mrContext.NFIsNumberFormat(aInputString, nFIndex, fVal))
     {
-        SvNumFormatType eType = pFormatter->GetType(nFIndex);
+        SvNumFormatType eType = mrContext.NFGetType(nFIndex);
         if (eType == SvNumFormatType::DATE || eType == 
SvNumFormatType::DATETIME)
         {
             nFuncFmtType = SvNumFormatType::DATE;
@@ -200,7 +200,7 @@ void ScInterpreter::ScGetDayOfWeek()
     else
         nFlag = 1;
 
-    Date aDate = pFormatter->GetNullDate();
+    Date aDate = mrContext.NFGetNullDate();
     aDate.AddDays( GetFloor32());
     int nVal = static_cast<int>(aDate.GetDayOfWeek());  // MONDAY = 0
     switch (nFlag)
@@ -241,7 +241,7 @@ void ScInterpreter::ScWeeknumOOo()
     {
         sal_Int16 nFlag = GetInt16();
 
-        Date aDate = pFormatter->GetNullDate();
+        Date aDate = mrContext.NFGetNullDate();
         aDate.AddDays( GetFloor32());
         PushInt( static_cast<int>(aDate.GetWeekOfYear( nFlag == 1 ? SUNDAY : 
MONDAY )));
     }
@@ -255,7 +255,7 @@ void ScInterpreter::ScGetWeekOfYear()
 
     sal_Int16 nFlag = ( nParamCount == 1 ) ? 1 : GetInt16();
 
-    Date aDate = pFormatter->GetNullDate();
+    Date aDate = mrContext.NFGetNullDate();
     aDate.AddDays( GetFloor32());
 
     sal_Int32 nMinimumNumberOfDaysInWeek;
@@ -297,7 +297,7 @@ void ScInterpreter::ScGetIsoWeekOfYear()
 {
     if ( MustHaveParamCount( GetByte(), 1 ) )
     {
-        Date aDate = pFormatter->GetNullDate();
+        Date aDate = mrContext.NFGetNullDate();
         aDate.AddDays( GetFloor32());
         PushInt( static_cast<int>(aDate.GetWeekOfYear()) );
     }
@@ -316,7 +316,7 @@ void ScInterpreter::ScEasterSunday()
         return;
     }
     if ( nYear < 100 )
-        nYear = pFormatter->ExpandTwoDigitYear( nYear );
+        nYear = mrContext.NFExpandTwoDigitYear( nYear );
     if (nYear < 1583 || nYear > 9956)
     {
         // Valid Gregorian and maximum year constraints not met.
@@ -508,7 +508,7 @@ void ScInterpreter::ScNetWorkdays( bool bOOXML_Version )
 
     vector<double> nSortArray;
     bool bWeekendMask[ 7 ];
-    const Date& rNullDate = pFormatter->GetNullDate();
+    const Date& rNullDate = mrContext.NFGetNullDate();
     sal_uInt32 nNullDate = Date::DateToDays( rNullDate.GetDay(), 
rNullDate.GetMonth(), rNullDate.GetYear() );
     FormulaError nErr;
     if ( bOOXML_Version )
@@ -565,7 +565,7 @@ void ScInterpreter::ScWorkday_MS()
     nFuncFmtType = SvNumFormatType::DATE;
     vector<double> nSortArray;
     bool bWeekendMask[ 7 ];
-    const Date& rNullDate = pFormatter->GetNullDate();
+    const Date& rNullDate = mrContext.NFGetNullDate();
     sal_uInt32 nNullDate = Date::DateToDays( rNullDate.GetDay(), 
rNullDate.GetMonth(), rNullDate.GetYear() );
     FormulaError nErr = GetWeekendAndHolidayMasks_MS( nParamCount, nNullDate,
                         nSortArray, bWeekendMask, true );
@@ -721,9 +721,9 @@ void ScInterpreter::ScGetDiffDate360()
         }
         else
             nSign = 1;
-        Date aDate1 = pFormatter->GetNullDate();
+        Date aDate1 = mrContext.NFGetNullDate();
         aDate1.AddDays( nDate1);
-        Date aDate2 = pFormatter->GetNullDate();
+        Date aDate2 = mrContext.NFGetNullDate();
         aDate2.AddDays( nDate2);
         if (aDate1.GetDay() == 31)
             aDate1.AddDays( -1);
@@ -795,12 +795,12 @@ void ScInterpreter::ScGetDateDif()
     // split dates in day, month, year for use with formats other than "d"
     sal_uInt16 d1, m1, d2, m2;
     sal_Int16 y1, y2;
-    Date aDate1( pFormatter->GetNullDate());
+    Date aDate1( mrContext.NFGetNullDate());
     aDate1.AddDays( nDate1);
     y1 = aDate1.GetYear();
     m1 = aDate1.GetMonth();
     d1 = aDate1.GetDay();
-    Date aDate2( pFormatter->GetNullDate());
+    Date aDate2( mrContext.NFGetNullDate());
     aDate2.AddDays( nDate2);
     y2 = aDate2.GetYear();
     m2 = aDate2.GetMonth();
@@ -916,9 +916,9 @@ void ScInterpreter::ScGetTimeValue()
     OUString aInputString = GetString().getString();
     sal_uInt32 nFIndex = 0;                 // damit default Land/Spr.
     double fVal;
-    if (pFormatter->IsNumberFormat(aInputString, nFIndex, fVal, 
SvNumInputOptions::LAX_TIME))
+    if (mrContext.NFIsNumberFormat(aInputString, nFIndex, fVal, 
SvNumInputOptions::LAX_TIME))
     {
-        SvNumFormatType eType = pFormatter->GetType(nFIndex);
+        SvNumFormatType eType = mrContext.NFGetType(nFIndex);
         if (eType == SvNumFormatType::TIME || eType == 
SvNumFormatType::DATETIME)
         {
             nFuncFmtType = SvNumFormatType::TIME;
@@ -3638,12 +3638,12 @@ void ScInterpreter::ScGetPivotData()
                     if (nCurFmtType == SvNumFormatType::UNDEFINED)
                         nNumFormat = 0;
                     else
-                        nNumFormat = pFormatter->GetStandardFormat( 
nCurFmtType, ScGlobal::eLnge);
+                        nNumFormat = mrContext.NFGetStandardFormat( 
nCurFmtType, ScGlobal::eLnge);
                 }
                 const Color* pColor;
-                pFormatter->GetOutputString( fDouble, nNumFormat, 
aFilters[i].MatchValueName, &pColor);
+                mrContext.NFGetOutputString( fDouble, nNumFormat, 
aFilters[i].MatchValueName, &pColor);
                 aFilters[i].MatchValue = 
ScDPCache::GetLocaleIndependentFormattedString(
-                        fDouble, *pFormatter, nNumFormat);
+                        fDouble, mrContext, nNumFormat);
             }
             else
             {
@@ -3653,9 +3653,9 @@ void ScInterpreter::ScGetPivotData()
                 // locale independent as MatchValue.
                 sal_uInt32 nNumFormat = 0;
                 double fValue;
-                if (pFormatter->IsNumberFormat( aFilters[i].MatchValueName, 
nNumFormat, fValue))
+                if (mrContext.NFIsNumberFormat( aFilters[i].MatchValueName, 
nNumFormat, fValue))
                     aFilters[i].MatchValue = 
ScDPCache::GetLocaleIndependentFormattedString(
-                            fValue, *pFormatter, nNumFormat);
+                            fValue, mrContext, nNumFormat);
                 else
                     aFilters[i].MatchValue = aFilters[i].MatchValueName;
             }
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index f31e35269953..492ef24bda22 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -165,7 +165,7 @@ double ScInterpreter::ConvertStringToValue( const OUString& 
rStr )
 {
     FormulaError nError = FormulaError::NONE;
     double fValue = ScGlobal::ConvertStringToValue( rStr, maCalcConfig, 
nError, mnStringNoValueError,
-            pFormatter, nCurFmtType);
+            mrContext, nCurFmtType);
     if (nError != FormulaError::NONE)
         SetError(nError);
     return fValue;
@@ -173,7 +173,7 @@ double ScInterpreter::ConvertStringToValue( const OUString& 
rStr )
 
 double ScInterpreter::ConvertStringToValue( const OUString& rStr, 
FormulaError& rError, SvNumFormatType& rCurFmtType )
 {
-    return ScGlobal::ConvertStringToValue( rStr, maCalcConfig, rError, 
mnStringNoValueError, pFormatter, rCurFmtType);
+    return ScGlobal::ConvertStringToValue( rStr, maCalcConfig, rError, 
mnStringNoValueError, mrContext, rCurFmtType);
 }
 
 double ScInterpreter::GetCellValue( const ScAddress& rPos, ScRefCellValue& 
rCell )
@@ -223,7 +223,7 @@ double ScInterpreter::GetCellValueOrZero( const ScAddress& 
rPos, ScRefCellValue&
         {
             fValue = rCell.getDouble();
             nCurFmtIndex = mrDoc.GetNumberFormat( mrContext, rPos );
-            nCurFmtType = mrContext.GetNumberFormatType( nCurFmtIndex );
+            nCurFmtType = mrContext.NFGetType(nCurFmtIndex);
             if ( bCalcAsShown && fValue != 0.0 )
                 fValue = mrDoc.RoundValueAsShown( fValue, nCurFmtIndex, 
&mrContext );
         }
@@ -2436,7 +2436,7 @@ svl::SharedString 
ScInterpreter::GetStringFromMatrix(const ScMatrixRef& pMat)
         ;   // nothing
     else if ( !pJumpMatrix )
     {
-        return pMat->GetString( *pFormatter, 0, 0);
+        return pMat->GetString( mrContext, 0, 0);
     }
     else
     {
@@ -2445,7 +2445,7 @@ svl::SharedString 
ScInterpreter::GetStringFromMatrix(const ScMatrixRef& pMat)
         pJumpMatrix->GetPos( nC, nR);
         // Use vector replication for single row/column arrays.
         if ( (nC < nCols || nCols == 1) && (nR < nRows || nRows == 1) )
-            return pMat->GetString( *pFormatter, nC, nR);
+            return pMat->GetString( mrContext, nC, nR);
 
         SetError( FormulaError::NoValue);
     }
@@ -2515,11 +2515,11 @@ ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix(
 
 svl::SharedString ScInterpreter::GetStringFromDouble( double fVal )
 {
-    sal_uLong nIndex = pFormatter->GetStandardFormat(
+    sal_uLong nIndex = mrContext.NFGetStandardFormat(
                         SvNumFormatType::NUMBER,
                         ScGlobal::eLnge);
     OUString aStr;
-    pFormatter->GetInputLineString(fVal, nIndex, aStr);
+    mrContext.NFGetInputLineString(fVal, nIndex, aStr);
     return mrStrPool.intern(aStr);
 }
 
@@ -2907,7 +2907,7 @@ void ScInterpreter::ScExternal()
                             }
                             break;
                         case svMatrix:
-                            if (!ScRangeToSequence::FillStringArray( aParam, 
PopMatrix().get(), pFormatter ))
+                            if (!ScRangeToSequence::FillStringArray( aParam, 
PopMatrix().get(), mrContext ))
                                 SetError(FormulaError::IllegalParameter);
                             break;
                         default:
@@ -3831,7 +3831,6 @@ ScInterpreter::ScInterpreter( ScFormulaCell* pCell, 
ScDocument& rDoc, ScInterpre
     , mrStrPool(rDoc.GetSharedStringPool())
     , pJumpMatrix(nullptr)
     , pMyFormulaCell(pCell)
-    , pFormatter(rContext.GetFormatTable())
     , pCur(nullptr)
     , nGlobalError(FormulaError::NONE)
     , sp(0)
diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index f091e7264a2c..1ee3b7258a26 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -1176,7 +1176,7 @@ ScMatrixRef ScInterpreter::MatConcat(const ScMatrixRef& 
pMat1, const ScMatrixRef
     ScMatrixRef xResMat = GetNewMat(nMinC, nMinR, /*bEmpty*/true);
     if (xResMat)
     {
-        xResMat->MatConcat(nMinC, nMinR, pMat1, pMat2, *pFormatter, 
mrDoc.GetSharedStringPool());
+        xResMat->MatConcat(nMinC, nMinR, pMat1, pMat2, mrContext, 
mrDoc.GetSharedStringPool());
     }
     return xResMat;
 }
@@ -1420,7 +1420,7 @@ void ScInterpreter::ScAmpersand()
                             pResMat->PutError( nErr, i, j);
                         else
                         {
-                            OUString aTmp = sStr + 
pMat->GetString(*pFormatter, i, j).getString();
+                            OUString aTmp = sStr + pMat->GetString(mrContext, 
i, j).getString();
                             pResMat->PutString(mrStrPool.intern(aTmp), i, j);
                         }
                     }
@@ -1435,7 +1435,7 @@ void ScInterpreter::ScAmpersand()
                             pResMat->PutError( nErr, i, j);
                         else
                         {
-                            OUString aTmp = pMat->GetString(*pFormatter, i, 
j).getString() + sStr;
+                            OUString aTmp = pMat->GetString(mrContext, i, 
j).getString() + sStr;
                             pResMat->PutString(mrStrPool.intern(aTmp), i, j);
                         }
                     }
diff --git a/sc/source/core/tool/interpr6.cxx b/sc/source/core/tool/interpr6.cxx
index 8c6cfb449bd3..2d6a38a3c6b1 100644
--- a/sc/source/core/tool/interpr6.cxx
+++ b/sc/source/core/tool/interpr6.cxx
@@ -779,7 +779,7 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, 
bool bTextAsZero )
                         nFuncFmtIndex = aAction.getNumberFormat();
                     }
 
-e 
... etc. - the rest is truncated

Reply via email to