|
|
|
/* This file is part of the KDE project
|
|
|
|
Copyright (C) 1998-2002 The KSpread Team
|
|
|
|
www.koffice.org/kspread
|
|
|
|
Copyright (C) 2005 Tomas Mecir <mecirt@gmail.com>
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
// built-in text functions
|
|
|
|
// please keep it in alphabetical order
|
|
|
|
|
|
|
|
#include <tqregexp.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#include "functions.h"
|
|
|
|
#include "valuecalc.h"
|
|
|
|
#include "valueconverter.h"
|
|
|
|
|
|
|
|
using namespace KSpread;
|
|
|
|
|
|
|
|
// Functions DOLLAR and FIXED convert data to double, hence they will not
|
|
|
|
// support arbitrary precision, when it will be introduced.
|
|
|
|
|
|
|
|
// prototypes
|
|
|
|
Value func_char (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_clean (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_code (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_compare (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_concatenate (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_dollar (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_exact (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_find (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_fixed (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_left (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_len (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_lower (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_mid (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_proper (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_regexp (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_regexpre (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_replace (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_rept (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_rot (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_right (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_search (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_sleek (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_substitute (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_t (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_text (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_toggle (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_trim (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_upper (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
Value func_value (valVector args, ValueCalc *calc, FuncExtra *);
|
|
|
|
|
|
|
|
// registers all text functions
|
|
|
|
void RegisterTextFunctions()
|
|
|
|
{
|
|
|
|
FunctionRepository* repo = FunctionRepository::self();
|
|
|
|
Function *f;
|
|
|
|
|
|
|
|
// one-parameter functions
|
|
|
|
f = new Function ("CHAR", func_char);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("CLEAN", func_clean);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("CODE", func_code);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("LEN", func_len);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("LOWER", func_lower);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("PROPER", func_proper);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("ROT", func_rot);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("SLEEK", func_sleek);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("T", func_t);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("TOGGLE", func_toggle);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("TRIM", func_trim);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("UPPER", func_upper);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("VALUE", func_value);
|
|
|
|
repo->add (f);
|
|
|
|
|
|
|
|
// other functions
|
|
|
|
f = new Function ("COMPARE", func_compare);
|
|
|
|
f->setParamCount (3);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("CONCATENATE", func_concatenate);
|
|
|
|
f->setParamCount (1, -1);
|
|
|
|
f->setAcceptArray ();
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("DOLLAR", func_dollar);
|
|
|
|
f->setParamCount (1, 2);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("EXACT", func_exact);
|
|
|
|
f->setParamCount (2);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("FIND", func_find);
|
|
|
|
f->setParamCount (2, 3);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("FIXED", func_fixed);
|
|
|
|
f->setParamCount (1, 3);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("LEFT", func_left);
|
|
|
|
f->setParamCount (2);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("MID", func_mid);
|
|
|
|
f->setParamCount (2, 3);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("REGEXP", func_regexp);
|
|
|
|
f->setParamCount (2, 4);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("REGEXPRE", func_regexpre);
|
|
|
|
f->setParamCount (3);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("REPLACE", func_replace);
|
|
|
|
f->setParamCount (4);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("REPT", func_rept);
|
|
|
|
f->setParamCount (2);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("RIGHT", func_right);
|
|
|
|
f->setParamCount (2);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("SEARCH", func_search);
|
|
|
|
f->setParamCount (2, 3);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("SUBSTITUTE", func_substitute);
|
|
|
|
f->setParamCount (3, 4);
|
|
|
|
repo->add (f);
|
|
|
|
f = new Function ("TEXT", func_text);
|
|
|
|
f->setParamCount (1, 2);
|
|
|
|
repo->add (f);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Function: CHAR
|
|
|
|
Value func_char (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
int val = calc->conv()->asInteger (args[0]).asInteger ();
|
|
|
|
return Value (TQString (TQChar (val)));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: CLEAN
|
|
|
|
Value func_clean (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
TQString str (calc->conv()->asString (args[0]).asString());
|
|
|
|
TQString result;
|
|
|
|
TQChar c;
|
|
|
|
int i;
|
|
|
|
int l = str.length();
|
|
|
|
|
|
|
|
for (i = 0; i < l; ++i)
|
|
|
|
{
|
|
|
|
c = str[i];
|
|
|
|
if (c.isPrint())
|
|
|
|
result += c;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Value (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: CODE
|
|
|
|
Value func_code (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
TQString str (calc->conv()->asString (args[0]).asString());
|
|
|
|
if (str.length() <= 0)
|
|
|
|
return Value::errorVALUE();
|
|
|
|
|
|
|
|
return Value (str[0].unicode());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: COMPARE
|
|
|
|
Value func_compare (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
int result = 0;
|
|
|
|
bool exact = calc->conv()->asBoolean (args[2]).asBoolean();
|
|
|
|
|
|
|
|
TQString s1 = calc->conv()->asString (args[0]).asString();
|
|
|
|
TQString s2 = calc->conv()->asString (args[1]).asString();
|
|
|
|
|
|
|
|
if (!exact)
|
|
|
|
result = s1.lower().localeAwareCompare(s2.lower());
|
|
|
|
else
|
|
|
|
result = s1.localeAwareCompare(s2);
|
|
|
|
|
|
|
|
if (result < 0)
|
|
|
|
result = -1;
|
|
|
|
else if (result > 0)
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
return Value (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void func_concatenate_helper (Value val, ValueCalc *calc,
|
|
|
|
TQString& tmp)
|
|
|
|
{
|
|
|
|
if (val.isArray()) {
|
|
|
|
for (unsigned int row = 0; row < val.rows(); ++row)
|
|
|
|
for (unsigned int col = 0; col < val.columns(); ++col)
|
|
|
|
func_concatenate_helper (val.element (col, row), calc, tmp);
|
|
|
|
} else
|
|
|
|
tmp += calc->conv()->asString (val).asString();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: CONCATENATE
|
|
|
|
Value func_concatenate (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
TQString tmp;
|
|
|
|
for (unsigned int i = 0; i < args.count(); ++i)
|
|
|
|
func_concatenate_helper (args[i], calc, tmp);
|
|
|
|
|
|
|
|
return Value (tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: DOLLAR
|
|
|
|
Value func_dollar (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
// ValueConverter doesn't support money directly, hence we need to
|
|
|
|
// use the locale. This code has the same effect as the output
|
|
|
|
// of ValueFormatter for money format.
|
|
|
|
|
|
|
|
// This function converts data to double/int, hence it won't support
|
|
|
|
// larger precision.
|
|
|
|
|
|
|
|
double value = calc->conv()->asFloat (args[0]).asFloat();
|
|
|
|
int precision = 2;
|
|
|
|
if (args.count() == 2)
|
|
|
|
precision = calc->conv()->asInteger (args[1]).asInteger();
|
|
|
|
|
|
|
|
// do round, because formatMoney doesn't
|
|
|
|
value = floor (value * pow (10.0, precision) + 0.5) / pow (10.0, precision);
|
|
|
|
|
|
|
|
TDELocale *locale = calc->conv()->locale();
|
|
|
|
TQString s = locale->formatMoney (value, locale->currencySymbol(), precision);
|
|
|
|
|
|
|
|
return Value (s);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: EXACT
|
|
|
|
Value func_exact (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
TQString s1 = calc->conv()->asString (args[0]).asString();
|
|
|
|
TQString s2 = calc->conv()->asString (args[1]).asString();
|
|
|
|
bool exact = (s1 == s2);
|
|
|
|
return Value (exact);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: FIND
|
|
|
|
Value func_find (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
TQString find_text, within_text;
|
|
|
|
int start_num = 1;
|
|
|
|
|
|
|
|
find_text = calc->conv()->asString (args[0]).asString();
|
|
|
|
within_text = calc->conv()->asString (args[1]).asString();
|
|
|
|
if (args.count() == 3)
|
|
|
|
start_num = calc->conv()->asInteger (args[2]).asInteger();
|
|
|
|
|
|
|
|
// conforms to Excel behaviour
|
|
|
|
if (start_num <= 0) return Value::errorVALUE();
|
|
|
|
if (start_num > (int)within_text.length()) return Value::errorVALUE();
|
|
|
|
|
|
|
|
int pos = within_text.find (find_text, start_num - 1);
|
|
|
|
if( pos < 0 ) return Value::errorNA();
|
|
|
|
|
|
|
|
return Value (pos + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: FIXED
|
|
|
|
Value func_fixed (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
// uses double, hence won't support big precision
|
|
|
|
|
|
|
|
int decimals = 2;
|
|
|
|
bool no_commas = false;
|
|
|
|
|
|
|
|
double number = calc->conv()->asFloat (args[0]).asFloat();
|
|
|
|
if (args.count() > 1)
|
|
|
|
decimals = calc->conv()->asInteger (args[1]).asInteger();
|
|
|
|
if (args.count() == 3)
|
|
|
|
no_commas = calc->conv()->asBoolean (args[2]).asBoolean();
|
|
|
|
|
|
|
|
TQString result;
|
|
|
|
TDELocale *locale = calc->conv()->locale();
|
|
|
|
|
|
|
|
// unfortunately, we can't just use TDELocale::formatNumber because
|
|
|
|
// * if decimals < 0, number is rounded
|
|
|
|
// * if no_commas is true, thousand separators shouldn't show up
|
|
|
|
|
|
|
|
if( decimals < 0 )
|
|
|
|
{
|
|
|
|
decimals = -decimals;
|
|
|
|
number = floor( number/pow(10.0,decimals)+0.5 ) * pow(10.0,decimals);
|
|
|
|
decimals = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool neg = number < 0;
|
|
|
|
result = TQString::number( neg ? -number:number, 'f', decimals );
|
|
|
|
|
|
|
|
int pos = result.find('.');
|
|
|
|
if (pos == -1) pos = result.length();
|
|
|
|
else result.replace(pos, 1, locale->decimalSymbol());
|
|
|
|
if( !no_commas )
|
|
|
|
while (0 < (pos -= 3))
|
|
|
|
result.insert(pos, locale->thousandsSeparator());
|
|
|
|
|
|
|
|
result.prepend( neg ? locale->negativeSign():
|
|
|
|
locale->positiveSign() );
|
|
|
|
|
|
|
|
return Value (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: LEFT
|
|
|
|
Value func_left (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
TQString str = calc->conv()->asString (args[0]).asString();
|
|
|
|
int nb = 1;
|
|
|
|
if (args.count() == 2)
|
|
|
|
nb = calc->conv()->asInteger (args[1]).asInteger();
|
|
|
|
|
|
|
|
return Value (str.left (nb));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: LEN
|
|
|
|
Value func_len (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
int nb = calc->conv()->asString (args[0]).asString().length();
|
|
|
|
return Value (nb);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: LOWER
|
|
|
|
Value func_lower (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
return Value (calc->conv()->asString (args[0]).asString().lower());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: MID
|
|
|
|
Value func_mid (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
TQString str = calc->conv()->asString (args[0]).asString();
|
|
|
|
int pos = calc->conv()->asInteger (args[1]).asInteger();
|
|
|
|
uint len = 0xffffffff;
|
|
|
|
if (args.count() == 3)
|
|
|
|
len = (uint) calc->conv()->asInteger (args[2]).asInteger();
|
|
|
|
|
|
|
|
// Excel compatible
|
|
|
|
pos--;
|
|
|
|
|
|
|
|
return Value (str.mid (pos, len));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: PROPER
|
|
|
|
Value func_proper (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
TQString str = calc->conv()->asString (args[0]).asString().lower();
|
|
|
|
|
|
|
|
TQChar f;
|
|
|
|
bool first = true;
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < str.length(); ++i)
|
|
|
|
{
|
|
|
|
if (first)
|
|
|
|
{
|
|
|
|
f = str[i];
|
|
|
|
if (f.isNumber())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
f = f.upper();
|
|
|
|
|
|
|
|
str[i] = f;
|
|
|
|
first = false;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (str[i] == ' ' || str[i] == '-')
|
|
|
|
first = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Value (str);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: REGEXP
|
|
|
|
Value func_regexp (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
// ensure that we got a valid regular expression
|
|
|
|
TQRegExp exp (calc->conv()->asString (args[1]).asString());
|
|
|
|
if (!exp.isValid ())
|
|
|
|
return Value::errorVALUE();
|
|
|
|
|
|
|
|
TQString s = calc->conv()->asString (args[0]).asString();
|
|
|
|
TQString defText;
|
|
|
|
if (args.count() > 2)
|
|
|
|
defText = calc->conv()->asString (args[2]).asString();
|
|
|
|
int bkref = 0;
|
|
|
|
if (args.count() == 4)
|
|
|
|
bkref = calc->conv()->asInteger (args[3]).asInteger();
|
|
|
|
if (bkref < 0) // strange back-reference
|
|
|
|
return Value::errorVALUE();
|
|
|
|
|
|
|
|
TQString returnValue;
|
|
|
|
|
|
|
|
int pos = exp.search (s);
|
|
|
|
if (pos == -1)
|
|
|
|
returnValue = defText;
|
|
|
|
else
|
|
|
|
returnValue = exp.cap (bkref);
|
|
|
|
|
|
|
|
return Value (returnValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: REGEXPRE
|
|
|
|
Value func_regexpre (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
// ensure that we got a valid regular expression
|
|
|
|
TQRegExp exp (calc->conv()->asString (args[1]).asString());
|
|
|
|
if (!exp.isValid ())
|
|
|
|
return Value::errorVALUE();
|
|
|
|
|
|
|
|
TQString s = calc->conv()->asString (args[0]).asString();
|
|
|
|
TQString str = calc->conv()->asString (args[2]).asString();
|
|
|
|
|
|
|
|
int pos = 0;
|
|
|
|
while ((pos = exp.search (s, pos)) != -1)
|
|
|
|
{
|
|
|
|
int i = exp.matchedLength();
|
|
|
|
s = s.replace (pos, i, str);
|
|
|
|
pos += str.length();
|
|
|
|
}
|
|
|
|
|
|
|
|
return Value (s);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: REPLACE
|
|
|
|
Value func_replace (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
TQString text = calc->conv()->asString (args[0]).asString();
|
|
|
|
int pos = calc->conv()->asInteger (args[1]).asInteger();
|
|
|
|
int len = calc->conv()->asInteger (args[2]).asInteger();
|
|
|
|
TQString new_text = calc->conv()->asString (args[3]).asString();
|
|
|
|
|
|
|
|
if (pos < 0) pos = 0;
|
|
|
|
|
|
|
|
TQString result = text.replace (pos-1, len, new_text);
|
|
|
|
return Value (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: REPT
|
|
|
|
Value func_rept (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
TQString s = calc->conv()->asString (args[0]).asString();
|
|
|
|
int nb = calc->conv()->asInteger (args[1]).asInteger();
|
|
|
|
|
|
|
|
TQString result;
|
|
|
|
for (int i = 0; i < nb; i++) result += s;
|
|
|
|
return Value (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: RIGHT
|
|
|
|
Value func_right (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
TQString str = calc->conv()->asString (args[0]).asString();
|
|
|
|
int nb = 1;
|
|
|
|
if (args.count() == 2)
|
|
|
|
nb = calc->conv()->asInteger (args[1]).asInteger();
|
|
|
|
|
|
|
|
return Value (str.right (nb));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: ROT
|
|
|
|
Value func_rot (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
TQString text = calc->conv()->asString (args[0]).asString();
|
|
|
|
|
|
|
|
for( unsigned i=0; i<text.length(); i++ )
|
|
|
|
{
|
|
|
|
unsigned c = text[i].upper().unicode();
|
|
|
|
if( ( c >= 'A' ) && ( c <= 'M' ) )
|
|
|
|
text[i] = TQChar( text[i].unicode() + 13);
|
|
|
|
if( ( c >= 'N' ) && ( c <= 'Z' ) )
|
|
|
|
text[i] = TQChar( text[i].unicode() - 13);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Value (text);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: SEARCH
|
|
|
|
Value func_search (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
TQString find_text = calc->conv()->asString (args[0]).asString();
|
|
|
|
TQString within_text = calc->conv()->asString (args[1]).asString();
|
|
|
|
int start_num = 1;
|
|
|
|
if (args.count() == 3)
|
|
|
|
start_num = calc->conv()->asInteger (args[2]).asInteger();
|
|
|
|
|
|
|
|
// conforms to Excel behaviour
|
|
|
|
if (start_num <= 0) return Value::errorVALUE();
|
|
|
|
if (start_num > (int)within_text.length()) return Value::errorVALUE();
|
|
|
|
|
|
|
|
// use globbing feature of TQRegExp
|
|
|
|
TQRegExp regex( find_text, false, true );
|
|
|
|
int pos = within_text.find( regex, start_num-1 );
|
|
|
|
if( pos < 0 ) return Value::errorNA();
|
|
|
|
|
|
|
|
return Value (pos + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: SLEEK
|
|
|
|
Value func_sleek (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
TQString str = calc->conv()->asString (args[0]).asString();
|
|
|
|
TQString result;
|
|
|
|
TQChar c;
|
|
|
|
int i;
|
|
|
|
int l = str.length();
|
|
|
|
|
|
|
|
for (i = 0; i < l; ++i)
|
|
|
|
{
|
|
|
|
c = str[i];
|
|
|
|
if (!c.isSpace())
|
|
|
|
result += c;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Value (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: SUBSTITUTE
|
|
|
|
Value func_substitute (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
int num = 1;
|
|
|
|
bool all = true;
|
|
|
|
|
|
|
|
if (args.count() == 4)
|
|
|
|
{
|
|
|
|
num = calc->conv()->asInteger (args[3]).asInteger();
|
|
|
|
all = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString text = calc->conv()->asString (args[0]).asString();
|
|
|
|
TQString old_text = calc->conv()->asString (args[1]).asString();
|
|
|
|
TQString new_text = calc->conv()->asString (args[2]).asString();
|
|
|
|
|
|
|
|
if( num <= 0 ) return Value::errorVALUE();
|
|
|
|
if (old_text.length() == 0) return Value (text);
|
|
|
|
|
|
|
|
TQString result = text;
|
|
|
|
|
|
|
|
int p = result.find (old_text);
|
|
|
|
while ((p != -1) && (num > 0))
|
|
|
|
{
|
|
|
|
result.replace( p, old_text.length(), new_text );
|
|
|
|
// find another location, starting straight after the replaced text
|
|
|
|
p = result.find (old_text, p + new_text.length());
|
|
|
|
if( !all ) num--;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Value (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: T
|
|
|
|
Value func_t (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
return calc->conv()->asString (args[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: TEXT
|
|
|
|
Value func_text (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
//Currently the same as the T function ...
|
|
|
|
//Second parameter is format_text. It is currently ignored.
|
|
|
|
return calc->conv()->asString (args[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: TOGGLE
|
|
|
|
Value func_toggle (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
TQString str = calc->conv()->asString (args[0]).asString();
|
|
|
|
int i;
|
|
|
|
int l = str.length();
|
|
|
|
|
|
|
|
for (i = 0; i < l; ++i)
|
|
|
|
{
|
|
|
|
TQChar c = str[i];
|
|
|
|
TQChar lc = c.lower();
|
|
|
|
TQChar uc = c.upper();
|
|
|
|
|
|
|
|
if (c == lc) // it is in lowercase
|
|
|
|
str[i] = c.upper();
|
|
|
|
else if (c == uc) // it is in uppercase
|
|
|
|
str[i] = c.lower();
|
|
|
|
}
|
|
|
|
|
|
|
|
return Value (str);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: TRIM
|
|
|
|
Value func_trim (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
return Value (
|
|
|
|
calc->conv()->asString (args[0]).asString().simplifyWhiteSpace());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: UPPER
|
|
|
|
Value func_upper (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
return Value (calc->conv()->asString (args[0]).asString().upper());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function: VALUE
|
|
|
|
Value func_value (valVector args, ValueCalc *calc, FuncExtra *)
|
|
|
|
{
|
|
|
|
// same as the N function
|
|
|
|
return calc->conv()->asFloat (args[0]);
|
|
|
|
}
|