diff --git a/formula/inc/core_resource.hrc b/formula/inc/core_resource.hrc index 8825cd6dae07..2196be6921cb 100644 --- a/formula/inc/core_resource.hrc +++ b/formula/inc/core_resource.hrc @@ -288,6 +288,7 @@ const std::pair 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.TEXTSPLIT" , SC_OPCODE_TEXTSPLIT }, { "COM.MICROSOFT.TOCOL" , SC_OPCODE_TOCOL }, { "COM.MICROSOFT.TOROW" , SC_OPCODE_TOROW }, { "COM.MICROSOFT.UNIQUE" , SC_OPCODE_UNIQUE }, @@ -756,6 +757,7 @@ const std::pair RID_STRLIST_FUNCTION_NAMES_ENGLISH_OOXML[] = { "_xlfn.HSTACK" , SC_OPCODE_HSTACK }, { "_xlfn.VSTACK" , SC_OPCODE_VSTACK }, { "_xlfn.TAKE" , SC_OPCODE_TAKE }, + { "_xlfn.TEXTSPLIT" , SC_OPCODE_TEXTSPLIT }, { "_xlfn.TOCOL" , SC_OPCODE_TOCOL }, { "_xlfn.TOROW" , SC_OPCODE_TOROW }, { "_xlfn.UNIQUE" , SC_OPCODE_UNIQUE }, @@ -1227,6 +1229,7 @@ const std::pair RID_STRLIST_FUNCTION_NAMES_ENGLISH_PODF[] = { "HSTACK" , SC_OPCODE_HSTACK }, { "VSTACK" , SC_OPCODE_VSTACK }, { "TAKE" , SC_OPCODE_TAKE }, + { "TEXTSPLIT" , SC_OPCODE_TEXTSPLIT }, { "TOCOL" , SC_OPCODE_TOCOL }, { "TOROW" , SC_OPCODE_TOROW }, { "UNIQUE" , SC_OPCODE_UNIQUE }, @@ -1698,6 +1701,7 @@ const std::pair RID_STRLIST_FUNCTION_NAMES_ENGLISH_API[] = { "HSTACK" , SC_OPCODE_HSTACK }, { "VSTACK" , SC_OPCODE_VSTACK }, { "TAKE" , SC_OPCODE_TAKE }, + { "TEXTSPLIT" , SC_OPCODE_TEXTSPLIT }, { "TOCOL" , SC_OPCODE_TOCOL }, { "TOROW" , SC_OPCODE_TOROW }, { "UNIQUE" , SC_OPCODE_UNIQUE }, @@ -2167,6 +2171,7 @@ const std::pair RID_STRLIST_FUNCTION_NAMES_ENGLISH[] = { "HSTACK" , SC_OPCODE_HSTACK }, { "VSTACK" , SC_OPCODE_VSTACK }, { "TAKE" , SC_OPCODE_TAKE }, + { "TEXTSPLIT" , SC_OPCODE_TEXTSPLIT }, { "TOCOL" , SC_OPCODE_TOCOL }, { "TOROW" , SC_OPCODE_TOROW }, { "UNIQUE" , SC_OPCODE_UNIQUE }, @@ -2617,6 +2622,7 @@ const std::pair 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", "TEXTSPLIT") , SC_OPCODE_TEXTSPLIT }, { NC_("RID_STRLIST_FUNCTION_NAMES", "TOCOL") , SC_OPCODE_TOCOL }, { NC_("RID_STRLIST_FUNCTION_NAMES", "TOROW") , SC_OPCODE_TOROW }, { NC_("RID_STRLIST_FUNCTION_NAMES", "UNIQUE") , SC_OPCODE_UNIQUE }, diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx index 1118241350d1..2ced8cfabe5f 100644 --- a/formula/source/core/api/FormulaCompiler.cxx +++ b/formula/source/core/api/FormulaCompiler.cxx @@ -1284,6 +1284,7 @@ bool FormulaCompiler::IsMatrixFunction( OpCode eOpCode ) case ocHStack : case ocVStack : case ocTake : + case ocTextSplit : case ocToCol : case ocToRow : case ocUnique : diff --git a/include/formula/compiler.hxx b/include/formula/compiler.hxx index 867506437f32..6353a37ddad5 100644 --- a/include/formula/compiler.hxx +++ b/include/formula/compiler.hxx @@ -524,12 +524,13 @@ #define SC_OPCODE_HSTACK 509 #define SC_OPCODE_VSTACK 510 #define SC_OPCODE_TAKE 511 -#define SC_OPCODE_TOCOL 512 -#define SC_OPCODE_TOROW 513 -#define SC_OPCODE_UNIQUE 514 -#define SC_OPCODE_WRAPCOLS 515 -#define SC_OPCODE_WRAPROWS 516 -#define SC_OPCODE_STOP_2_PAR 517 /* last function with two or more parameters' OpCode + 1 */ +#define SC_OPCODE_TEXTSPLIT 512 +#define SC_OPCODE_TOCOL 513 +#define SC_OPCODE_TOROW 514 +#define SC_OPCODE_UNIQUE 515 +#define SC_OPCODE_WRAPCOLS 516 +#define SC_OPCODE_WRAPROWS 517 +#define SC_OPCODE_STOP_2_PAR 518 /* 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 */ diff --git a/include/formula/opcode.hxx b/include/formula/opcode.hxx index 835009e77e3f..df0d76e83d67 100644 --- a/include/formula/opcode.hxx +++ b/include/formula/opcode.hxx @@ -520,6 +520,7 @@ enum OpCode : sal_uInt16 ocHStack = SC_OPCODE_HSTACK, ocVStack = SC_OPCODE_VSTACK, ocTake = SC_OPCODE_TAKE, + ocTextSplit = SC_OPCODE_TEXTSPLIT, ocToCol = SC_OPCODE_TOCOL, ocToRow = SC_OPCODE_TOROW, ocUnique = SC_OPCODE_UNIQUE, @@ -1016,6 +1017,7 @@ inline std::string OpCodeEnumToString(OpCode eCode) case ocHStack: return "HStack"; case ocVStack: return "VStack"; case ocTake: return "Take"; + case ocTextSplit: return "TextSplit"; case ocToCol: return "ToCol"; case ocToRow: return "ToRow"; case ocUnique: return "Unique"; diff --git a/sc/README.md b/sc/README.md index 741d7ec5cd02..0bcdf7b2180a 100644 --- a/sc/README.md +++ b/sc/README.md @@ -62,6 +62,7 @@ https://docs.oasis-open.org/office/OpenDocument/v1.3/os/part4-formula/OpenDocume * HSTACK * VSTACK * TAKE + * TEXTSPLIT * TOCOL * TOROW * WRAPCOLS diff --git a/sc/inc/helpids.h b/sc/inc/helpids.h index 48794f18f22e..c00124ba3729 100644 --- a/sc/inc/helpids.h +++ b/sc/inc/helpids.h @@ -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_TEXTSPLIT_MS = u"SC_HID_FUNC_TEXTSPLIT_MS"_ustr; inline constexpr OUString HID_FUNC_TOCOL_MS = u"SC_HID_FUNC_TOCOL_MS"_ustr; inline constexpr OUString HID_FUNC_TOROW_MS = u"SC_HID_FUNC_TOROW_MS"_ustr; inline constexpr OUString HID_FUNC_UNIQUE_MS = u"SC_HID_FUNC_UNIQUE_MS"_ustr; diff --git a/sc/inc/scfuncs.hrc b/sc/inc/scfuncs.hrc index e910534b39af..b81cee703397 100644 --- a/sc/inc/scfuncs.hrc +++ b/sc/inc/scfuncs.hrc @@ -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 TEXTSPLIT #*=- +const TranslateId SC_OPCODE_TEXTSPLIT_ARY[] = +{ + NC_("SC_OPCODE_TEXTSPLIT", "Splits text by a given delimiter to an array of multiple cells."), + NC_("SC_OPCODE_TEXTSPLIT", "Text"), + NC_("SC_OPCODE_TEXTSPLIT", "The text to split."), + NC_("SC_OPCODE_TEXTSPLIT", "Column Delimiter"), + NC_("SC_OPCODE_TEXTSPLIT", "The text to delimit the columns. Multiple delimiters can be supplied."), + NC_("SC_OPCODE_TEXTSPLIT", "Row Delimiter"), + NC_("SC_OPCODE_TEXTSPLIT", "The text to delimit the rows. Multiple delimiters can be supplied."), + NC_("SC_OPCODE_TEXTSPLIT", "Ignore Empty"), + NC_("SC_OPCODE_TEXTSPLIT", "Set to TRUE to ignore consecutive delimiters otherwise creates an empty cell. The default to FALSE."), + NC_("SC_OPCODE_TEXTSPLIT", "Match mode"), + NC_("SC_OPCODE_TEXTSPLIT", "Set to 1 to perform a case-insensitive match otherwise does a case-sensitive match. The default to 0."), + NC_("SC_OPCODE_TEXTSPLIT", "Pad with"), + NC_("SC_OPCODE_TEXTSPLIT", "The value with which to pad. The default is #N/A.") +}; + // -=*# Resource for function TOCOL #*=- const TranslateId SC_OPCODE_TOCOL_ARY[] = { diff --git a/sc/qa/extras/scfunctionlistobj.cxx b/sc/qa/extras/scfunctionlistobj.cxx index 0f7d7cfefe07..0f5acb22db58 100644 --- a/sc/qa/extras/scfunctionlistobj.cxx +++ b/sc/qa/extras/scfunctionlistobj.cxx @@ -77,7 +77,7 @@ public: ScFunctionListObj::ScFunctionListObj() : UnoApiTest(u"/sc/qa/extras/testdocuments"_ustr) , XElementAccess(cppu::UnoType>::get()) - , XIndexAccess(415) + , XIndexAccess(416) , XNameAccess(u"IF"_ustr) , XServiceInfo(u"stardiv.StarCalc.ScFunctionListObj"_ustr, u"com.sun.star.sheet.FunctionDescriptions"_ustr) diff --git a/sc/qa/unit/data/functions/spreadsheet/fods/textsplit.fods b/sc/qa/unit/data/functions/spreadsheet/fods/textsplit.fods new file mode 100644 index 000000000000..9978c1e2fc97 --- /dev/null +++ b/sc/qa/unit/data/functions/spreadsheet/fods/textsplit.fods @@ -0,0 +1,4579 @@ + + + + 2024-01-16T18:30:06.278000000PT12H31M1S158LibreOfficeDev/25.8.0.0.alpha0$Linux_X86_64 LibreOffice_project/dd6ae9d789e56d9f0dfb4370421fd38665a491632025-05-08T20:33:10.636105478 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + - + + + + + + + \ + + + + + \- + + + + + + % + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + £ + + + + + - + £ + + + + + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + + + + . + + . + + + + + + + + + + + + ( + + ) + + + + + + + + + + - + + + + + $ + + + + + ($ + + ) + + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + + + + + + + + + - + + + + + - € + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + - + + - + + + + £ + + + + - + £ + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + + + + + + + + ( + + + + ) + + + + + + + + + + $ + + + + + + + + ( + + ) + + + + + + + + + + - + + + + + + + $ + + + + + - + $ + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + + Yes + + + Yes + + + No + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + + + + - + + + + + + \ + + + + \- + + + + + \ + + + + + + \ + + - + + + + + \ + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + £ + + + + - + £ + + + + + + + + + + + + + EUR + + + + - + + + EUR + + + + + + + + + - + + + + + + + - + + - + + + + $ + + + + + + $ + + ( + + ) + + + $ + + - + + + + + + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + £ + + + + + - + £ + + + + + + On + + + On + + + Off + + + + + $ + + + + + + ($ + + ) + + + + + + + + - + + + + + + + + + $ + + + + + ($ + + ) + + + + $ + + + + + + ($ + + ) + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + - + + + + + + + + + + True + + + True + + + False + + + + + + + + + - + + + + + - + + + + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + / + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + $ + + + + + $( + + ) + + + $- + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + + + WAHR + + + WAHR + + + FALSCH + + + + + + . + + + + + + + + + + - + + + + + + + + + + + + + - + + + + + + + + + + + + + + ( + + ) + + + - + + + + + + + + + + + + + : + + + + + : + + + + £ + + + + + - + £ + + + + + + \ + + + + + \- + + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + : + + : + + + + \ + + + + \- + + + + + + + + + - + + + + + + + + + + / + + / + + + + + + + / + + / + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + - + + + + + + + + + - + + + + + + + + - + + + + + + + + + - + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + - + + + + + + + - Kč + + + + + + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + ¥€ + + + + + + + + + ( + + + + + + ) + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + + + + + - + + + + + + + + + + + + + - + + + + + + + + + + + + + - + + + + + + + + + + + + + - + + + + + + + + + + + + + - + + + + + + + + + + + + + - + + + + + + + + + + + + + - + + + + + + + + + + + + + - + + + + + + + + + + + + + - + + + + + + + + + + + + + - + + + + + + + + + + + + + - + + + + + + + + + + + + + - + + + + + + + + + + + + + - + + + + + + + + + + + + + - + + + + + + + + + + + + + - + + + + + + + + % + + + + % + + + + % + + + + % + + + + % + + + + % + + + + + + $ + + + + + ( + $ + + ) + + + + + % + + + + % + + + + - + + % + + + + + + + + - + + + + + + - + + - + + + + £ + + + + + - + £ + + + + + £ + + + + + - + £ + + + + + + % + + + + - + + % + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + DM + + + - + + DM + + + + + DM + + + + - + + DM + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - DM + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + DM + + + - + + + DM + + + + + - + + DM + + + + + + + + + + + Ouch! - + + - Error detected! + + + + - Result=0 - No Errordetection + + + + / + + / + + + + + . + + . + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + + - + + + + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + $ + + + + $ + + + + + - + $ + + + + + + . + + . + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + $ + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + $ + + + + -$ + + + + + $ + + + + + -$ + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + - + + + + + + + - + + + + - + + + + + -$ + + + + $ + + + + -$ + + + + $- + + + + + + - + + + + + + + - + + + + - + + + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + Ft + + + - + + Ft + + + + + Ft + + + + - + + Ft + + + + + . + + . + + + + + . + + . + + + + + . + + + + + . + + + + + . + + . + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - Ft + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + Ft + + + - + + + Ft + + + + + - + + Ft + + + + + + + + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + + - + + + + + + + + - € + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + + + / + + / + + + + + - + + - + + + + + - + + + + + - + + + + + : + + + + + + + : + + : + + + + + + + : + + + + + : + + : + + + + + / + + / + + + + : + + + + + + + + + ( + + ) + + + + + + + + + ( + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + + ( + + + ) + + + + + + + + + + ( + + + ) + + + + + + + + ( + + ) + + + + + + + + ( + + ) + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + ( + + ) + + + + - + + + + + + + + + + + + + + + + + + + + ( + + ) + + + + + - + + + + + + + + + + + + + + + + + + + - + + + + + : + + : + + + + + : + + + + + + + + % + + + + + + + - + + - + + + + + + + + + - + + + + + + + + + . + + + + + + + . + + + + + + + + + + : + + + + + + + : + + : + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / + + / + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ??? + + + + + Page 1 + + + + + + + + ???(???) + + + 00/00/0000, 00:00:00 + + + + + + Page 1/ 99 + + + + + + + + + + + + + + + TextSplit Function + + + + + + + + + + Result + + + VERDADERO + + + + + + + + + Sheet + + + Result + + + Description + + + + + 2 + + + VERDADERO + + + Simple TEXTSPLIT formulas with local references and values + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Function + + + + Expected + + + + Correct + + + FunctionString + + + Comment + + + Data + + + + + + Data + + + + Data + + + + + + row to array + + + Apples,Lemons,Oranges + + + Mr. + + + + + Apples + + + Lemons + + + Oranges + + + + Apples + + + Lemons + + + Oranges + + + + VERDADERO + + + {=TEXTSPLIT(L2;",")} + + + + Name=Aiden, Score=93, Result=Excellent + + + Ms. + + + + + Apples + + + + Apples + + + + VERDADERO + + + {=TEXTSPLIT(L2; ;",")} + + + + 1111XXX2222XXX3333 + + + , + + + + + Lemons + + + + Lemons + + + + VERDADERO + + + {=TEXTSPLIT(L2; ;",")} + + + + Apples, ,Oranges + + + + + + + + Oranges + + + + Oranges + + + + VERDADERO + + + {=TEXTSPLIT(L2; ;",")} + + + + 16/01/2022 + + + + + + Apples,Lemons,Oranges + + + + Apples,Lemons,Oranges + + + + VERDADERO + + + {=TEXTSPLIT(L2;"x")} + + + + Ms. Mia Brown, 82, Good + + + + + + Apples,Lemons,Oranges + + + + Apples,Lemons,Oranges + + + + VERDADERO + + + {=TEXTSPLIT(L2;;"x")} + + + + ,,,,,,,,One,,,,,Two,,,,Three + + + + + + Name + + + Aiden + + + + Name + + + Aiden + + + + VERDADERO + + + {=TEXTSPLIT(L3; "="; ", ")} + + + + 1111ÇÇÇ2222ÇÇÇ3333 + + + + + + Score + + + 93 + + + + Score + + + 93 + + + + VERDADERO + + + {=TEXTSPLIT(L3; "="; ", ")} + + + + + + + + Result + + + Excellent + + + + Result + + + Excellent + + + + VERDADERO + + + {=TEXTSPLIT(L3; "="; ", ")} + + + + + + + + Name + + + #N/A + + + + Name + + + #N/A + + + + VERDADERO + + + {=TEXTSPLIT(L3; ", "; "=")} + + + + + + + + Aiden + + + Score + + + + Aiden + + + Score + + + + VERDADERO + + + {=TEXTSPLIT(L3; ", "; "=")} + + + + + + + + 93 + + + Result + + + + 93 + + + Result + + + + VERDADERO + + + {=TEXTSPLIT(L3; ", "; "=")} + + + + + + + + Excellent + + + #N/A + + + + Excellent + + + #N/A + + + + VERDADERO + + + {=TEXTSPLIT(L3; ", "; "=")} + + + + + + + + 1111 + + + 2222 + + + 3333 + + + + 1111 + + + 2222 + + + 3333 + + + + VERDADERO + + + {=TEXTSPLIT(L4;"XXX")} + + + + + + + + Apples + + + + + + Oranges + + + + Apples + + + + + + Oranges + + + + VERDADERO + + + {=TEXTSPLIT(L5;",")} + + + + + + Apples + + + + + + Oranges + + + + Apples + + + + + + Oranges + + + + VERDADERO + + + {=TEXTSPLIT(L5;",";;TRUE())} + + + + + + Apples + + + + + + Oranges + + + + Apples + + + + + + Oranges + + + + VERDADERO + + + {=TEXTSPLIT(L5;",";;FALSE())} + + + + + + Apples, ,Oranges + + + + Apples, ,Oranges + + + + VERDADERO + + + {=TEXTSPLIT(L5;"X";;TRUE())} + + + + + + 1111 + + + 2222 + + + 3333 + + + + 1111 + + + 2222 + + + 3333 + + + + VERDADERO + + + {=TEXTSPLIT(L4;"XXX";;;0)} + + + + + + 1111 + + + 2222 + + + 3333 + + + + 1111 + + + 2222 + + + 3333 + + + + VERDADERO + + + {=TEXTSPLIT(L4;"xxx";;;1)} + + + + + + Name + + + + + + + Name + + + + VERDADERO + + + {=TEXTSPLIT(L3; ", "; "=";;;"")} + + + + + + Aiden + + + Score + + + + Aiden + + + Score + + + + VERDADERO + + + {=TEXTSPLIT(L3; ", "; "=";;;"")} + + + + + + 93 + + + Result + + + + 93 + + + Result + + + + VERDADERO + + + {=TEXTSPLIT(L3; ", "; "=";;;"")} + + + + + + Excellent + + + + + + + Excellent + + + + VERDADERO + + + {=TEXTSPLIT(L3; ", "; "=";;;"")} + + + + + + Name + + + Test + + + + Name + + + Test + + + + VERDADERO + + + {=TEXTSPLIT(L3; ", "; "=";;;"Test")} + + + + + + Aiden + + + Score + + + + Aiden + + + Score + + + + VERDADERO + + + {=TEXTSPLIT(L3; ", "; "=";;;"Test")} + + + + + + 93 + + + Result + + + + 93 + + + Result + + + + VERDADERO + + + {=TEXTSPLIT(L3; ", "; "=";;;"Test")} + + + + + + Excellent + + + Test + + + + Excellent + + + Test + + + + VERDADERO + + + {=TEXTSPLIT(L3; ", "; "=";;;"Test")} + + + + + + 1 + + + 16 + + + 2022 + + + + 1 + + 16 + + 2022 + + + + VERDADERO + + + {=TEXTSPLIT(TEXT(L6; "m.d.yyyy"); ".")} + + + + + + Apples + + + Lemons + + + Oranges + + + + Apples + + + Lemons + + + Oranges + + + + VERDADERO + + + {=TEXTSPLIT("Apples,Lemons,Oranges";",")} + + + + + + Mia + + + Brown + + + 82 + + + Good + + + Mia + + + Brown + + 82 + + + Good + + + VERDADERO + + + {=TEXTSPLIT(L7; {" ".", "."Mr. "."Ms. "};;TRUE())} + + + + + + Mia + + + + Mia + + + + VERDADERO + + + {=TEXTSPLIT(L7; ;{" ".", "."Mr. "."Ms. "};TRUE())} + + + + + + Brown + + + + Brown + + + + VERDADERO + + + {=TEXTSPLIT(L7; ;{" ".", "."Mr. "."Ms. "};TRUE())} + + + + + + 82 + + + 82 + + + + VERDADERO + + + {=TEXTSPLIT(L7; ;{" ".", "."Mr. "."Ms. "};TRUE())} + + + + + + Good + + + + Good + + + + VERDADERO + + + {=TEXTSPLIT(L7; ;{" ".", "."Mr. "."Ms. "};TRUE())} + + + + + + + + + + VERDADERO + + + {=TEXTSPLIT(L7; ;{" ".", "."Mr. "."Ms. "})} + + + + + + + + Mia + + + + + Mia + + + + VERDADERO + + + {=TEXTSPLIT(L7; ;{" ".", "."Mr. "."Ms. "})} + + + + + + Brown + + + + Brown + + + + VERDADERO + + + {=TEXTSPLIT(L7; ;{" ".", "."Mr. "."Ms. "})} + + + + + + 82 + + + 82 + + + + VERDADERO + + + {=TEXTSPLIT(L7; ;{" ".", "."Mr. "."Ms. "})} + + + + + + Good + + + + Good + + + + VERDADERO + + + {=TEXTSPLIT(L7; ;{" ".", "."Mr. "."Ms. "})} + + + + + + One + + + Two + + + Three + + + + One + + + Two + + + Three + + + + VERDADERO + + + {=TEXTSPLIT(L8;",";;TRUE())} + + + + + + + + + + VERDADERO + + + {=TEXTSPLIT(L7; ;M2:M5)} + + + + + + Mia + + + + Mia + + + + VERDADERO + + + {=TEXTSPLIT(L7; ;M2:M5)} + + + + + + Brown + + + + Brown + + + + VERDADERO + + + {=TEXTSPLIT(L7; ;M2:M5)} + + + + + + 82 + + + 82 + + + + VERDADERO + + + {=TEXTSPLIT(L7; ;M2:M5)} + + + + + + Good + + + + Good + + + + VERDADERO + + + {=TEXTSPLIT(L7; ;M2:M5)} + + + + + + 1111 + + + 2222 + + + 3333 + + + + 1111 + + + 2222 + + + 3333 + + + + VERDADERO + + + {=TEXTSPLIT(L9;"ÇÇÇ";;;1)} + + + + + + 1111 + + + 2222 + + + 3333 + + + + 1111 + + + 2222 + + + 3333 + + + + VERDADERO + + + {=TEXTSPLIT(L9;"ççç";;;1)} + + + + + + Mia + + + Brown + + + 82 + + + Good + + + Mia + + + Brown + + 82 + + + Good + + + VERDADERO + + + {=TEXTSPLIT(L7; {" ".", "."MR. "."ms. "};;TRUE();1)} + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index 2e1c8fc40341..8ebef294b801 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -3125,6 +3125,7 @@ CPPUNIT_TEST_FIXTURE(Test, testFunctionLists) "SORTBY", "STYLE", "TAKE", + "TEXTSPLIT", "TOCOL", "TOROW", "UNIQUE", diff --git a/sc/source/core/data/funcdesc.cxx b/sc/source/core/data/funcdesc.cxx index a0d371a32258..7a5bc437184e 100644 --- a/sc/source/core/data/funcdesc.cxx +++ b/sc/source/core/data/funcdesc.cxx @@ -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_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 }, { SC_OPCODE_TOROW, ENTRY(SC_OPCODE_TOROW_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_TOROW_MS, 3, { 0, 1, 1 }, 0 }, { SC_OPCODE_UNIQUE, ENTRY(SC_OPCODE_UNIQUE_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_UNIQUE_MS, 3, { 0, 1, 1 }, 0 }, diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx index abeb868c45b2..218826b7ee18 100644 --- a/sc/source/core/inc/interpre.hxx +++ b/sc/source/core/inc/interpre.hxx @@ -736,6 +736,7 @@ private: void ScHStack(); void ScVStack(); void ScTake(); + void ScTextSplit(); void ScToCol(); void ScToRow(); void ScUnique(); diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 63aa0583e4a3..d668c24f5e07 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -9295,6 +9295,207 @@ void ScInterpreter::ScTake() ScTakeOrDrop(/*bTake*/ true); } + +static std::vector lcl_SplitText(const OUString& rText, const std::vector& rDelimiters, + bool bIgnoreEmpty, bool bMatchMode) +{ + std::vector aResStr; + if (!rDelimiters.size() || rText.isEmpty()) + { + aResStr.push_back(rText); + } + else + { + const sal_Int32 nLength (rText.getLength()); + sal_Int32 nStart(0); + while (nStart < nLength) + { + sal_Int32 nIndex = nLength; + sal_Int32 nDelLength(0); + + // Find the first delimiter + for (auto& rDelimiter : rDelimiters) + { + if (rDelimiter.isEmpty()) + continue; + + OUString sDelimiter = rDelimiter.getString(); + sal_Int32 nDelimiterIndex; + if (bMatchMode) + { + nDelimiterIndex = ScGlobal::getCharClass().lowercase(rText).indexOf( + ScGlobal::getCharClass().lowercase(sDelimiter), nStart); + } + else + nDelimiterIndex = rText.indexOf(sDelimiter, nStart); + + if (nDelimiterIndex != -1 && nDelimiterIndex < nIndex) + { + nDelLength = sDelimiter.getLength(); + nIndex = nDelimiterIndex; + } + } + + OUString sRes(rText.copy(nStart, nIndex - nStart)); + if (!bIgnoreEmpty || !sRes.isEmpty()) + { + aResStr.push_back(sRes); + } + nStart = nIndex + nDelLength; + } + } + return aResStr; +} + +void ScInterpreter::ScTextSplit() +{ + sal_uInt8 nParamCount = GetByte(); + if (!MustHaveParamCount(nParamCount, 1, 6)) + return; + + // 6rd argument optional - pad_with + std::optional aPadWith; + if (nParamCount == 6) + aPadWith = GetString(); + + // 5rd argument optional - match_mode + bool bMatchMode = false; + if (nParamCount >= 5) + { + if (!IsMissing()) + { + bMatchMode = GetBool(); + } + else + Pop(); + } + + // 4rd argument optional - ignore_empty + bool bIgnoreEmpty = false; + if (nParamCount >= 4) + { + if (!IsMissing()) + bIgnoreEmpty = GetBool(); + else + Pop(); + } + + // 3rd argument optional - row_delimiter + std::vector aRowDelimiters; + if (nParamCount >= 3) + { + ScMatrixRef pMatSource = nullptr; + SCSIZE nsC = 0, nsR = 0; + switch (GetStackType()) + { + case svSingleRef: + case svDoubleRef: + case svMatrix: + case svExternalSingleRef: + case svExternalDoubleRef: + { + pMatSource = GetMatrix(); + if (!pMatSource) + { + PushIllegalParameter(); + return; + } + + pMatSource->GetDimensions(nsC, nsR); + for (SCSIZE i = 0; i < nsC; i++) + { + for (SCSIZE j = 0; j < nsR; j++) + { + aRowDelimiters.push_back(pMatSource->GetString(i,j)); + } + } + } + break; + + default: + aRowDelimiters.push_back(GetString()); + } + } + + // 2nd argument optional - col_delimiter + std::vector aColDelimiters; + if (nParamCount >= 2) + { + ScMatrixRef pMatSource = nullptr; + SCSIZE nsC = 0, nsR = 0; + switch (GetStackType()) + { + case svSingleRef: + case svDoubleRef: + case svMatrix: + case svExternalSingleRef: + case svExternalDoubleRef: + { + pMatSource = GetMatrix(); + if (!pMatSource) + { + PushIllegalParameter(); + return; + } + + pMatSource->GetDimensions(nsC, nsR); + for (SCSIZE i = 0; i < nsC; i++) + { + for (SCSIZE j = 0; j < nsR; j++) + { + aColDelimiters.push_back(pMatSource->GetString(i,j)); + } + } + } + break; + + default: + aColDelimiters.push_back(GetString()); + } + } + + // 1st argument: text + svl::SharedString sText = GetString(); + if (sText.isEmpty()) + { + PushIllegalParameter(); + return; + } + + std::vector aRowStrs = lcl_SplitText(sText.getString(), aRowDelimiters, bIgnoreEmpty, bMatchMode); + std::vector> aRes; + + SCSIZE nCols = 1; + SCSIZE nRows = aRowStrs.size(); + for (auto& rRow : aRowStrs) + { + std::vector aColStrs = lcl_SplitText(rRow, aColDelimiters, bIgnoreEmpty, bMatchMode); + nCols = std::max(nCols, aColStrs.size()); + aRes.push_back(aColStrs); + } + + ScMatrixRef pResMat = GetNewMat(nCols, nRows, /*bEmpty*/true); + for (SCSIZE col = 0; col < nCols; ++col) + { + for (SCSIZE row = 0; row < nRows; ++row) + { + if (col < aRes[row].size()) + { + pResMat->PutString(mrStrPool.intern(aRes[row][col]), col, row); + } + else + { + if (!aPadWith.has_value()) + pResMat->PutError(FormulaError::NotAvailable, col, row); + else + pResMat->PutString(aPadWith.value(), col, row); + } + } + } + + PushMatrix(pResMat); +} + void ScInterpreter::ScToColOrRow(bool bCol) { sal_uInt8 nParamCount = GetByte(); diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index 3a996bd331f5..af2a60ef7eca 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -4130,6 +4130,7 @@ StackVar ScInterpreter::Interpret() case ocHStack : ScHStack(); break; case ocVStack : ScVStack(); break; case ocTake : ScTake(); break; + case ocTextSplit : ScTextSplit(); break; case ocToCol : ScToCol(); break; case ocToRow : ScToRow(); break; case ocUnique : ScUnique(); break; diff --git a/sc/source/core/tool/parclass.cxx b/sc/source/core/tool/parclass.cxx index 204c9a943f7d..7ea90ff0a23c 100644 --- a/sc/source/core/tool/parclass.cxx +++ b/sc/source/core/tool/parclass.cxx @@ -264,6 +264,7 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] = { ocTake, {{ ReferenceOrRefArray, Value, Value, }, 0, ForceArrayReturn } }, { ocTTest, {{ ForceArray, ForceArray, Value, Value }, 0, Value }}, { ocTextJoin_MS, {{ Reference, Value, Reference }, 1, Value }}, + { ocTextSplit, {{ ReferenceOrRefArray, ReferenceOrRefArray, ReferenceOrRefArray, Value, Value, Value }, 0, ForceArrayReturn } }, { ocToCol, {{ ReferenceOrRefArray, Value, Value, }, 0, ForceArrayReturn } }, { ocToRow, {{ ReferenceOrRefArray, Value, Value, }, 0, ForceArrayReturn } }, { ocTrend, {{ Reference, Reference, Reference, Value }, 0, Value }}, diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index 75b1929f321d..d2d57372a91b 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -1598,6 +1598,7 @@ void ScTokenArray::CheckToken( const FormulaToken& r ) case ocHStack: case ocVStack: case ocTake: + case ocTextSplit: case ocToCol: case ocToRow: case ocUnique: diff --git a/sc/source/filter/excel/xlformula.cxx b/sc/source/filter/excel/xlformula.cxx index cbb211b19cd0..38d4c545ed58 100644 --- a/sc/source/filter/excel/xlformula.cxx +++ b/sc/source/filter/excel/xlformula.cxx @@ -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( ocTextSplit, 1, 6, 0, "TEXTSPLIT" ), EXC_FUNCENTRY_V_VR( ocToCol, 1, 3, 0, "TOCOL" ), EXC_FUNCENTRY_V_VR( ocToRow, 1, 3, 0, "TOROW" ), EXC_FUNCENTRY_V_VR( ocWrapCols, 2, 3, 0, "WRAPCOLS"), diff --git a/sc/source/filter/oox/formulabase.cxx b/sc/source/filter/oox/formulabase.cxx index d722b75a9837..6e37a663fdaa 100644 --- a/sc/source/filter/oox/formulabase.cxx +++ b/sc/source/filter/oox/formulabase.cxx @@ -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.TEXTSPLIT", "TEXTSPLIT", NOID, NOID, 1, 6, A, { VO }, FuncFlags::MACROCALL_NEW }, { "COM.MICROSOFT.TOCOL", "TOCOL", NOID, NOID, 1, 3, A, { VO }, FuncFlags::MACROCALL_NEW }, { "COM.MICROSOFT.TOROW", "TOROW", NOID, NOID, 1, 3, A, { VO }, FuncFlags::MACROCALL_NEW }, { "COM.MICROSOFT.WRAPCOLS", "WRAPCOLS", NOID, NOID, 2, 3, A, { VO }, FuncFlags::MACROCALL_NEW },