tdf#150865: Add support for TEXTAFTER function

Change-Id: Iedd79b069c145de4c3b70d50552df8bf7da66a1e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185218
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
Xisco Fauli
2025-05-12 16:13:32 +02:00
parent 047c84f431
commit fd0cc5b2d3
16 changed files with 3790 additions and 13 deletions
+6
View File
@@ -288,6 +288,7 @@ const std::pair<const char *, int> RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF[] =
{ "COM.MICROSOFT.HSTACK" , SC_OPCODE_HSTACK },
{ "COM.MICROSOFT.VSTACK" , SC_OPCODE_VSTACK },
{ "COM.MICROSOFT.TAKE" , SC_OPCODE_TAKE },
{ "COM.MICROSOFT.TEXTAFTER" , SC_OPCODE_TEXTAFTER },
{ "COM.MICROSOFT.TEXTBEFORE" , SC_OPCODE_TEXTBEFORE },
{ "COM.MICROSOFT.TEXTSPLIT" , SC_OPCODE_TEXTSPLIT },
{ "COM.MICROSOFT.TOCOL" , SC_OPCODE_TOCOL },
@@ -758,6 +759,7 @@ const std::pair<const char *, int> RID_STRLIST_FUNCTION_NAMES_ENGLISH_OOXML[] =
{ "_xlfn.HSTACK" , SC_OPCODE_HSTACK },
{ "_xlfn.VSTACK" , SC_OPCODE_VSTACK },
{ "_xlfn.TAKE" , SC_OPCODE_TAKE },
{ "_xlfn.TEXTAFTER" , SC_OPCODE_TEXTAFTER },
{ "_xlfn.TEXTBEFORE" , SC_OPCODE_TEXTBEFORE },
{ "_xlfn.TEXTSPLIT" , SC_OPCODE_TEXTSPLIT },
{ "_xlfn.TOCOL" , SC_OPCODE_TOCOL },
@@ -1231,6 +1233,7 @@ const std::pair<const char *, int> RID_STRLIST_FUNCTION_NAMES_ENGLISH_PODF[] =
{ "HSTACK" , SC_OPCODE_HSTACK },
{ "VSTACK" , SC_OPCODE_VSTACK },
{ "TAKE" , SC_OPCODE_TAKE },
{ "TEXTAFTER" , SC_OPCODE_TEXTAFTER },
{ "TEXTBEFORE" , SC_OPCODE_TEXTBEFORE },
{ "TEXTSPLIT" , SC_OPCODE_TEXTSPLIT },
{ "TOCOL" , SC_OPCODE_TOCOL },
@@ -1704,6 +1707,7 @@ const std::pair<const char *, int> RID_STRLIST_FUNCTION_NAMES_ENGLISH_API[] =
{ "HSTACK" , SC_OPCODE_HSTACK },
{ "VSTACK" , SC_OPCODE_VSTACK },
{ "TAKE" , SC_OPCODE_TAKE },
{ "TEXTAFTER" , SC_OPCODE_TEXTAFTER },
{ "TEXTBEFORE" , SC_OPCODE_TEXTBEFORE },
{ "TEXTSPLIT" , SC_OPCODE_TEXTSPLIT },
{ "TOCOL" , SC_OPCODE_TOCOL },
@@ -2175,6 +2179,7 @@ const std::pair<const char *, int> RID_STRLIST_FUNCTION_NAMES_ENGLISH[] =
{ "HSTACK" , SC_OPCODE_HSTACK },
{ "VSTACK" , SC_OPCODE_VSTACK },
{ "TAKE" , SC_OPCODE_TAKE },
{ "TEXTAFTER" , SC_OPCODE_TEXTAFTER },
{ "TEXTBEFORE" , SC_OPCODE_TEXTBEFORE },
{ "TEXTSPLIT" , SC_OPCODE_TEXTSPLIT },
{ "TOCOL" , SC_OPCODE_TOCOL },
@@ -2627,6 +2632,7 @@ const std::pair<TranslateId, int> RID_STRLIST_FUNCTION_NAMES[] =
{ NC_("RID_STRLIST_FUNCTION_NAMES", "HSTACK") , SC_OPCODE_HSTACK },
{ NC_("RID_STRLIST_FUNCTION_NAMES", "VSTACK") , SC_OPCODE_VSTACK },
{ NC_("RID_STRLIST_FUNCTION_NAMES", "TAKE") , SC_OPCODE_TAKE },
{ NC_("RID_STRLIST_FUNCTION_NAMES", "TEXTAFTER") , SC_OPCODE_TEXTAFTER },
{ NC_("RID_STRLIST_FUNCTION_NAMES", "TEXTBEFORE") , SC_OPCODE_TEXTBEFORE },
{ NC_("RID_STRLIST_FUNCTION_NAMES", "TEXTSPLIT") , SC_OPCODE_TEXTSPLIT },
{ NC_("RID_STRLIST_FUNCTION_NAMES", "TOCOL") , SC_OPCODE_TOCOL },
+9 -8
View File
@@ -524,14 +524,15 @@
#define SC_OPCODE_HSTACK 509
#define SC_OPCODE_VSTACK 510
#define SC_OPCODE_TAKE 511
#define SC_OPCODE_TEXTBEFORE 512
#define SC_OPCODE_TEXTSPLIT 513
#define SC_OPCODE_TOCOL 514
#define SC_OPCODE_TOROW 515
#define SC_OPCODE_UNIQUE 516
#define SC_OPCODE_WRAPCOLS 517
#define SC_OPCODE_WRAPROWS 518
#define SC_OPCODE_STOP_2_PAR 519 /* last function with two or more parameters' OpCode + 1 */
#define SC_OPCODE_TEXTAFTER 512
#define SC_OPCODE_TEXTBEFORE 513
#define SC_OPCODE_TEXTSPLIT 514
#define SC_OPCODE_TOCOL 515
#define SC_OPCODE_TOROW 516
#define SC_OPCODE_UNIQUE 517
#define SC_OPCODE_WRAPCOLS 518
#define SC_OPCODE_WRAPROWS 519
#define SC_OPCODE_STOP_2_PAR 520 /* last function with two or more parameters' OpCode + 1 */
#define SC_OPCODE_STOP_FUNCTION SC_OPCODE_STOP_2_PAR /* last function's OpCode + 1 */
#define SC_OPCODE_LAST_OPCODE_ID (SC_OPCODE_STOP_FUNCTION - 1) /* last OpCode */
+2
View File
@@ -520,6 +520,7 @@ enum OpCode : sal_uInt16
ocHStack = SC_OPCODE_HSTACK,
ocVStack = SC_OPCODE_VSTACK,
ocTake = SC_OPCODE_TAKE,
ocTextAfter = SC_OPCODE_TEXTAFTER,
ocTextBefore = SC_OPCODE_TEXTBEFORE,
ocTextSplit = SC_OPCODE_TEXTSPLIT,
ocToCol = SC_OPCODE_TOCOL,
@@ -1018,6 +1019,7 @@ inline std::string OpCodeEnumToString(OpCode eCode)
case ocHStack: return "HStack";
case ocVStack: return "VStack";
case ocTake: return "Take";
case ocTextAfter: return "TextAfter";
case ocTextBefore: return "TextBefore";
case ocTextSplit: return "TextSplit";
case ocToCol: return "ToCol";
+1
View File
@@ -106,5 +106,6 @@ https://docs.oasis-open.org/office/OpenDocument/v1.3/os/part4-formula/OpenDocume
* AVERAGEIFS
* Text Functions
* SEARCH
* TEXTAFTER
* TEXTBEFORE
+1
View File
@@ -607,6 +607,7 @@ inline constexpr OUString HID_FUNC_EXPAND_MS = u"SC_HID_FUNC_EXPAND_MS"_ustr;
inline constexpr OUString HID_FUNC_HSTACK_MS = u"SC_HID_FUNC_HSTACK_MS"_ustr;
inline constexpr OUString HID_FUNC_VSTACK_MS = u"SC_HID_FUNC_VSTACK_MS"_ustr;
inline constexpr OUString HID_FUNC_TAKE_MS = u"SC_HID_FUNC_TAKE_MS"_ustr;
inline constexpr OUString HID_FUNC_TEXTAFTER_MS = u"SC_HID_FUNC_TEXTAFTER_MS"_ustr;
inline constexpr OUString HID_FUNC_TEXTBEFORE_MS = u"SC_HID_FUNC_TEXTBEFORE_MS"_ustr;
inline constexpr OUString HID_FUNC_TEXTSPLIT_MS = u"SC_HID_FUNC_TEXTSPLIT_MS"_ustr;
inline constexpr OUString HID_FUNC_TOCOL_MS = u"SC_HID_FUNC_TOCOL_MS"_ustr;
+18
View File
@@ -4329,6 +4329,24 @@ const TranslateId SC_OPCODE_TAKE_ARY[] =
NC_("SC_OPCODE_TAKE", "The number of columns to take. A negative value takes from the end of the array.")
};
// -=*# Resource for function TEXTAFTER #*=-
const TranslateId SC_OPCODE_TEXTAFTER_ARY[] =
{
NC_("SC_OPCODE_TEXTAFTER", "Returns the text that occurs after a given substring or delimiter."),
NC_("SC_OPCODE_TEXTAFTER", "Text"),
NC_("SC_OPCODE_TEXTAFTER", "The original text."),
NC_("SC_OPCODE_TEXTAFTER", "Delimiter"),
NC_("SC_OPCODE_TEXTAFTER", "The delimiter. Multiple delimiters can be supplied."),
NC_("SC_OPCODE_TEXTAFTER", "Instance Number"),
NC_("SC_OPCODE_TEXTAFTER", "The instance of the delimiter after which to extract text. The default is 1. A negative number starts searching from the end."),
NC_("SC_OPCODE_TEXTAFTER", "Match Mode"),
NC_("SC_OPCODE_TEXTAFTER", "Set to 1 to perform a case-insensitive match. The default is 0."),
NC_("SC_OPCODE_TEXTAFTER", "Match End"),
NC_("SC_OPCODE_TEXTAFTER", "Set to 1 to treat the end of text as a delimiter. The default is 0."),
NC_("SC_OPCODE_TEXTAFTER", "If Not Found"),
NC_("SC_OPCODE_TEXTAFTER", "The value returned if no match is found. The default is #N/A.")
};
// -=*# Resource for function TEXTBEFORE #*=-
const TranslateId SC_OPCODE_TEXTBEFORE_ARY[] =
{
+1 -1
View File
@@ -77,7 +77,7 @@ public:
ScFunctionListObj::ScFunctionListObj()
: UnoApiTest(u"/sc/qa/extras/testdocuments"_ustr)
, XElementAccess(cppu::UnoType<uno::Sequence<beans::PropertyValue>>::get())
, XIndexAccess(417)
, XIndexAccess(418)
, XNameAccess(u"IF"_ustr)
, XServiceInfo(u"stardiv.StarCalc.ScFunctionListObj"_ustr,
u"com.sun.star.sheet.FunctionDescriptions"_ustr)
File diff suppressed because it is too large Load Diff
+1
View File
@@ -3179,6 +3179,7 @@ CPPUNIT_TEST_FIXTURE(Test, testFunctionLists)
"SUBSTITUTE",
"T",
"TEXT",
"TEXTAFTER",
"TEXTBEFORE",
"TEXTJOIN",
"TRIM",
+1
View File
@@ -800,6 +800,7 @@ ScFunctionList::ScFunctionList( bool bEnglishFunctionNames )
{ SC_OPCODE_HSTACK, ENTRY(SC_OPCODE_HSTACK_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_HSTACK_MS, VAR_ARGS + 1, { 0, 0 }, 0 },
{ SC_OPCODE_VSTACK, ENTRY(SC_OPCODE_VSTACK_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_VSTACK_MS, VAR_ARGS + 1, { 0, 0 }, 0 },
{ SC_OPCODE_TAKE, ENTRY(SC_OPCODE_TAKE_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_TAKE_MS, 3, { 0, 1, 1 }, 0 },
{ SC_OPCODE_TEXTAFTER, ENTRY(SC_OPCODE_TEXTAFTER_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_TEXTAFTER_MS, 6, { 0, 1, 1, 1, 1, 1 }, 0 },
{ SC_OPCODE_TEXTBEFORE, ENTRY(SC_OPCODE_TEXTBEFORE_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_TEXTBEFORE_MS, 6, { 0, 1, 1, 1, 1, 1 }, 0 },
{ SC_OPCODE_TEXTSPLIT, ENTRY(SC_OPCODE_TEXTSPLIT_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_TEXTSPLIT_MS, 6, { 0, 1, 1, 1, 1, 1 }, 0 },
{ SC_OPCODE_TOCOL, ENTRY(SC_OPCODE_TOCOL_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_TOCOL_MS, 3, { 0, 1, 1 }, 0 },
+2
View File
@@ -736,6 +736,7 @@ private:
void ScHStack();
void ScVStack();
void ScTake();
void ScTextAfter();
void ScTextBefore();
void ScTextSplit();
void ScToCol();
@@ -747,6 +748,7 @@ private:
void ScWrapRows();
private:
void ScTextBeforeOrAfter(bool bBefore);
void ScChooseColsOrRows(bool bCols);
void ScToColOrRow(bool bCol);
void ScWrapColsOrRows(bool bCols);
+26 -4
View File
@@ -9295,7 +9295,17 @@ void ScInterpreter::ScTake()
ScTakeOrDrop(/*bTake*/ true);
}
void ScInterpreter::ScTextAfter()
{
ScTextBeforeOrAfter(/*bBefore*/ false);
}
void ScInterpreter::ScTextBefore()
{
ScTextBeforeOrAfter(/*bBefore*/ true);
}
void ScInterpreter::ScTextBeforeOrAfter(bool bBefore)
{
sal_uInt8 nParamCount = GetByte();
if (!MustHaveParamCount(nParamCount, 1, 6))
@@ -9393,10 +9403,13 @@ void ScInterpreter::ScTextBefore()
return;
}
std::vector<sal_Int32> aDelimiterPositions;
if (bMatchEnd && !bBefore)
aDelimiterPositions.push_back(0);
OUString sStr(sText.getString());
const sal_Int32 nLength (sStr.getLength());
sal_Int32 nStart(0);
std::vector<sal_Int32> aDelimiterPositions;
while (nStart < nLength)
{
sal_Int32 nIndex = nLength;
@@ -9428,12 +9441,17 @@ void ScInterpreter::ScTextBefore()
}
if (bFound)
aDelimiterPositions.push_back(nIndex);
{
if (bBefore)
aDelimiterPositions.push_back(nIndex);
else
aDelimiterPositions.push_back(nIndex + nDelLength);
}
nStart = nIndex + nDelLength;
}
if (bMatchEnd)
if (bMatchEnd && bBefore)
aDelimiterPositions.push_back(nLength);
sal_Int32 nSize(aDelimiterPositions.size());
@@ -9449,7 +9467,11 @@ void ScInterpreter::ScTextBefore()
if (nInstanceNum < 0)
nInstanceNum = nSize + nInstanceNum + 1;
PushString(sStr.copy(0, aDelimiterPositions[nInstanceNum - 1]));
sal_Int32 aDelPos(aDelimiterPositions[nInstanceNum - 1]);
if (bBefore)
PushString(sStr.copy(0, aDelPos));
else
PushString(sStr.copy(aDelPos, nLength - aDelPos));
}
}
+1
View File
@@ -4130,6 +4130,7 @@ StackVar ScInterpreter::Interpret()
case ocHStack : ScHStack(); break;
case ocVStack : ScVStack(); break;
case ocTake : ScTake(); break;
case ocTextAfter : ScTextAfter(); break;
case ocTextBefore : ScTextBefore(); break;
case ocTextSplit : ScTextSplit(); break;
case ocToCol : ScToCol(); break;
+1
View File
@@ -263,6 +263,7 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] =
{ ocSumXMY2, {{ ForceArray, ForceArray }, 0, Value }},
{ ocTake, {{ ReferenceOrRefArray, Value, Value, }, 0, ForceArrayReturn } },
{ ocTTest, {{ ForceArray, ForceArray, Value, Value }, 0, Value }},
{ ocTextAfter, {{ ReferenceOrRefArray, ReferenceOrRefArray, ReferenceOrRefArray, Value, Value, Value }, 0, Value } },
{ ocTextBefore, {{ ReferenceOrRefArray, ReferenceOrRefArray, ReferenceOrRefArray, Value, Value, Value }, 0, Value } },
{ ocTextJoin_MS, {{ Reference, Value, Reference }, 1, Value }},
{ ocTextSplit, {{ ReferenceOrRefArray, ReferenceOrRefArray, ReferenceOrRefArray, Value, Value, Value }, 0, ForceArrayReturn } },
+1
View File
@@ -626,6 +626,7 @@ const XclFunctionInfo saFuncTable_2024[] =
EXC_FUNCENTRY_V_VR( ocHStack, 1, MX, 0, "HSTACK" ),
EXC_FUNCENTRY_V_VR( ocVStack, 1, MX, 0, "VSTACK" ),
EXC_FUNCENTRY_V_VR( ocTake, 1, 3, 0, "TAKE" ),
EXC_FUNCENTRY_V_VR( ocTextAfter, 1, 6, 0, "TEXTAFTER" ),
EXC_FUNCENTRY_V_VR( ocTextBefore, 1, 6, 0, "TEXTBEFORE" ),
EXC_FUNCENTRY_V_VR( ocTextSplit, 1, 6, 0, "TEXTSPLIT" ),
EXC_FUNCENTRY_V_VR( ocToCol, 1, 3, 0, "TOCOL" ),
+1
View File
@@ -901,6 +901,7 @@ const FunctionData saFuncTable2024[] =
{ "COM.MICROSOFT.HSTACK", "HSTACK", NOID, NOID, 1, MX, A, { VO }, FuncFlags::MACROCALL_NEW },
{ "COM.MICROSOFT.VSTACK", "VSTACK", NOID, NOID, 1, MX, A, { VO }, FuncFlags::MACROCALL_NEW },
{ "COM.MICROSOFT.TAKE", "TAKE", NOID, NOID, 1, 3, A, { VO }, FuncFlags::MACROCALL_NEW },
{ "COM.MICROSOFT.TEXTAFTER", "TEXTAFTER", NOID, NOID, 1, 6, A, { VO }, FuncFlags::MACROCALL_NEW },
{ "COM.MICROSOFT.TEXTBEFORE", "TEXTBEFORE", NOID, NOID, 1, 6, A, { VO }, FuncFlags::MACROCALL_NEW },
{ "COM.MICROSOFT.TEXTSPLIT", "TEXTSPLIT", NOID, NOID, 1, 6, A, { VO }, FuncFlags::MACROCALL_NEW },
{ "COM.MICROSOFT.TOCOL", "TOCOL", NOID, NOID, 1, 3, A, { VO }, FuncFlags::MACROCALL_NEW },