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