diff options
author | Eike Rathke <erack@redhat.com> | 2018-10-24 19:42:35 +0200 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2018-10-25 12:13:58 +0200 |
commit | 8dec85a3b3f4cbd46b03f707458347a25cc22c15 (patch) | |
tree | ef417d0d2a8d71e00804e5e531a84e0c5236b052 /sc/source/core/tool | |
parent | ae081cc1137fc0f41612504994d58fe0d9c0a7fc (diff) |
Resolves: tdf#113977 implement REGEX() spreadsheet function
REGEX( Text ; Expression [ ; Replacement ] )
Using ICU regular expressions
http://userguide.icu-project.org/strings/regexp
Change-Id: I4cb9b8ba77cfb5b8faab93037aa0d947609383d7
Reviewed-on: https://gerrit.libreoffice.org/62332
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
Diffstat (limited to 'sc/source/core/tool')
-rw-r--r-- | sc/source/core/tool/interpr1.cxx | 55 | ||||
-rw-r--r-- | sc/source/core/tool/interpr4.cxx | 1 |
2 files changed, 56 insertions, 0 deletions
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index dc23b55a43dc..6708bdce7913 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -9222,6 +9222,61 @@ void ScInterpreter::ScSearch() } } +void ScInterpreter::ScRegex() +{ + sal_uInt8 nParamCount = GetByte(); + if (MustHaveParamCount( nParamCount, 2, 3)) + { + bool bReplacement = false; + OUString aReplacement; + if (nParamCount == 3) + { + // A missing argument is not an empty string to replace the match. + if (IsMissing()) + Pop(); + else + { + aReplacement = GetString().getString(); + bReplacement = true; + } + } + + OUString aExpression = GetString().getString(); + OUString aText = GetString().getString(); + + if (nGlobalError != FormulaError::NONE) + { + PushError( nGlobalError); + return; + } + + sal_Int32 nPos = 0; + sal_Int32 nEndPos = aText.getLength(); + utl::SearchParam aParam( aExpression, utl::SearchParam::SearchType::Regexp); + css::util::SearchResult aResult; + utl::TextSearch aSearch( aParam, *ScGlobal::pCharClass); + const bool bMatch = aSearch.SearchForward( aText, &nPos, &nEndPos, &aResult); + if (!bMatch) + PushNoValue(); + else + { + assert(aResult.subRegExpressions >= 1); + if (!bReplacement) + PushString( aText.copy( aResult.startOffset[0], aResult.endOffset[0] - aResult.startOffset[0])); + else + { + /* TODO: global replacement of multiple occurrences, introduce + * extra parameter with flag 'g'? Loop over positions after + * nEndPos until none left? How to keep the offsets in sync + * after replacement? That should be done by + * ReplaceBackReferences(). */ + aSearch.ReplaceBackReferences( aReplacement, aText, aResult); + PushString( aReplacement); + } + } + } +} + void ScInterpreter::ScMid() { if ( MustHaveParamCount( GetByte(), 3 ) ) diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index f5ca631979e6..d044295ee4d3 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -4215,6 +4215,7 @@ StackVar ScInterpreter::Interpret() case ocMid : ScMid(); break; case ocText : ScText(); break; case ocSubstitute : ScSubstitute(); break; + case ocRegex : ScRegex(); break; case ocRept : ScRept(); break; case ocConcat : ScConcat(); break; case ocConcat_MS : ScConcat_MS(); break; |