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:
@@ -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 },
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -106,5 +106,6 @@ https://docs.oasis-open.org/office/OpenDocument/v1.3/os/part4-formula/OpenDocume
|
||||
* AVERAGEIFS
|
||||
* Text Functions
|
||||
* SEARCH
|
||||
* TEXTAFTER
|
||||
* TEXTBEFORE
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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[] =
|
||||
{
|
||||
|
||||
@@ -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
@@ -3179,6 +3179,7 @@ CPPUNIT_TEST_FIXTURE(Test, testFunctionLists)
|
||||
"SUBSTITUTE",
|
||||
"T",
|
||||
"TEXT",
|
||||
"TEXTAFTER",
|
||||
"TEXTBEFORE",
|
||||
"TEXTJOIN",
|
||||
"TRIM",
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 } },
|
||||
|
||||
@@ -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" ),
|
||||
|
||||
@@ -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 },
|
||||
|
||||
Reference in New Issue
Block a user