1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  */
9 
10 #include <memory>
11 #include <simpleformulacalc.hxx>
12 #include <document.hxx>
13 #include <tokenarray.hxx>
14 #include <interpre.hxx>
15 #include <compiler.hxx>
16 #include <sfx2/linkmgr.hxx>
17 
18 #define DISPLAY_LEN 15
19 
ScSimpleFormulaCalculator(ScDocument & rDoc,const ScAddress & rAddr,const OUString & rFormula,bool bMatrixFormula,formula::FormulaGrammar::Grammar eGram)20 ScSimpleFormulaCalculator::ScSimpleFormulaCalculator( ScDocument& rDoc, const ScAddress& rAddr,
21         const OUString& rFormula, bool bMatrixFormula, formula::FormulaGrammar::Grammar eGram )
22     : mnFormatType(SvNumFormatType::ALL)
23     , mbCalculated(false)
24     , maAddr(rAddr)
25     , mrDoc(rDoc)
26     , maGram(eGram)
27     , mbMatrixResult(false)
28     , mbLimitString(false)
29     , mbMatrixFormula(bMatrixFormula)
30 {
31     // compile already here
32     ScCompiler aComp(mrDoc, maAddr, eGram, true, bMatrixFormula);
33     mpCode = aComp.CompileString(rFormula);
34     if(mpCode->GetCodeError() == FormulaError::NONE && mpCode->GetLen())
35         aComp.CompileTokenArray();
36 }
37 
~ScSimpleFormulaCalculator()38 ScSimpleFormulaCalculator::~ScSimpleFormulaCalculator()
39 {
40 }
41 
Calculate()42 void ScSimpleFormulaCalculator::Calculate()
43 {
44     if(mbCalculated)
45         return;
46 
47     mbCalculated = true;
48 
49     ScInterpreter aInt(mrDoc.GetFormulaCell( maAddr ), mrDoc, mrDoc.GetNonThreadedContext(), maAddr, *mpCode);
50     if (mbMatrixFormula)
51         aInt.AssertFormulaMatrix();
52 
53     sfx2::LinkManager aNewLinkMgr( mrDoc.GetDocumentShell() );
54     aInt.SetLinkManager( &aNewLinkMgr );
55 
56     formula::StackVar aIntType = aInt.Interpret();
57     if ( aIntType == formula::svMatrixCell )
58     {
59         ScCompiler aComp(mrDoc, maAddr, maGram);
60         OUStringBuffer aStr;
61         aComp.CreateStringFromToken(aStr, aInt.GetResultToken().get());
62 
63         mbMatrixResult = true;
64 
65         if (mbLimitString)
66         {
67             size_t n = aStr.getLength();
68             for (size_t i = DISPLAY_LEN; i < n; ++i)
69             {
70                 if (aStr[i] == ',' || aStr[i] == ';')
71                 {
72                     aStr.truncate(i);
73                     aStr.append("...");
74                     break;
75                 }
76             }
77         }
78 
79         maMatrixFormulaResult = aStr.makeStringAndClear();
80     }
81     mnFormatType = aInt.GetRetFormatType();
82     maResult.SetToken(aInt.GetResultToken().get());
83 }
84 
IsValue()85 bool ScSimpleFormulaCalculator::IsValue()
86 {
87     Calculate();
88 
89     if (mbMatrixResult)
90         return false;
91 
92     return maResult.IsValue();
93 }
94 
IsMatrix()95 bool ScSimpleFormulaCalculator::IsMatrix()
96 {
97     Calculate();
98 
99     return mbMatrixResult;
100 }
101 
GetErrCode()102 FormulaError ScSimpleFormulaCalculator::GetErrCode()
103 {
104     Calculate();
105 
106     FormulaError nErr = mpCode->GetCodeError();
107     if (nErr != FormulaError::NONE)
108         return nErr;
109     return maResult.GetResultError();
110 }
111 
GetValue()112 double ScSimpleFormulaCalculator::GetValue()
113 {
114     Calculate();
115 
116     if ((mpCode->GetCodeError() == FormulaError::NONE) &&
117             maResult.GetResultError() == FormulaError::NONE)
118         return maResult.GetDouble();
119 
120     return 0.0;
121 }
122 
GetString()123 svl::SharedString ScSimpleFormulaCalculator::GetString()
124 {
125     Calculate();
126 
127     if (mbMatrixResult)
128         return svl::SharedString( maMatrixFormulaResult);   // string not interned
129 
130     if ((mpCode->GetCodeError() == FormulaError::NONE) &&
131             maResult.GetResultError() == FormulaError::NONE)
132         return maResult.GetString();
133 
134     return svl::SharedString::getEmptyString();
135 }
136 
HasColRowName() const137 bool ScSimpleFormulaCalculator::HasColRowName() const
138 {
139     return formula::FormulaTokenArrayPlainIterator(*mpCode).GetNextColRowName() != nullptr;
140 }
141 
GetCode()142 ScTokenArray* ScSimpleFormulaCalculator::GetCode()
143 {
144     return mpCode.get();
145 }
146 
SetLimitString(bool bLimitString)147 void ScSimpleFormulaCalculator::SetLimitString(bool bLimitString)
148 {
149     mbLimitString = bLimitString;
150 }
151 
152 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
153