tdf#151000: Add support for CHOOSECOLS function

Change-Id: Id183f79a148080adebe652f63e29716910c638b2
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180992
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
Xisco Fauli 2025-01-31 15:51:15 +01:00
parent b0a4afc58e
commit d595e1aa41
18 changed files with 6555 additions and 21 deletions

View File

@ -281,6 +281,7 @@ const std::pair<const char *, int> RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF[] =
{ "COM.MICROSOFT.FILTER" , SC_OPCODE_FILTER },
{ "COM.MICROSOFT.SORT" , SC_OPCODE_SORT },
{ "COM.MICROSOFT.SORTBY" , SC_OPCODE_SORTBY },
{ "COM.MICROSOFT.CHOOSECOLS" , SC_OPCODE_CHOOSECOLS },
{ "COM.MICROSOFT.CHOOSEROWS" , SC_OPCODE_CHOOSEROWS },
{ "COM.MICROSOFT.DROP" , SC_OPCODE_DROP },
{ "COM.MICROSOFT.EXPAND" , SC_OPCODE_EXPAND },
@ -746,6 +747,7 @@ const std::pair<const char *, int> RID_STRLIST_FUNCTION_NAMES_ENGLISH_OOXML[] =
{ "_xlfn._xlws.FILTER" , SC_OPCODE_FILTER },
{ "_xlfn._xlws.SORT" , SC_OPCODE_SORT },
{ "_xlfn.SORTBY" , SC_OPCODE_SORTBY },
{ "_xlfn.CHOOSECOLS" , SC_OPCODE_CHOOSECOLS },
{ "_xlfn.CHOOSEROWS" , SC_OPCODE_CHOOSEROWS },
{ "_xlfn.DROP" , SC_OPCODE_DROP },
{ "_xlfn.EXPAND" , SC_OPCODE_EXPAND },
@ -1214,6 +1216,7 @@ const std::pair<const char *, int> RID_STRLIST_FUNCTION_NAMES_ENGLISH_PODF[] =
{ "FILTER" , SC_OPCODE_FILTER },
{ "SORT" , SC_OPCODE_SORT },
{ "SORTBY" , SC_OPCODE_SORTBY },
{ "CHOOSECOLS" , SC_OPCODE_CHOOSECOLS },
{ "CHOOSEROWS" , SC_OPCODE_CHOOSEROWS },
{ "DROP" , SC_OPCODE_DROP },
{ "EXPAND" , SC_OPCODE_EXPAND },
@ -1682,6 +1685,7 @@ const std::pair<const char *, int> RID_STRLIST_FUNCTION_NAMES_ENGLISH_API[] =
{ "FILTER" , SC_OPCODE_FILTER },
{ "SORT" , SC_OPCODE_SORT },
{ "SORTBY" , SC_OPCODE_SORTBY },
{ "CHOOSECOLS" , SC_OPCODE_CHOOSECOLS },
{ "CHOOSEROWS" , SC_OPCODE_CHOOSEROWS },
{ "DROP" , SC_OPCODE_DROP },
{ "EXPAND" , SC_OPCODE_EXPAND },
@ -2148,6 +2152,7 @@ const std::pair<const char *, int> RID_STRLIST_FUNCTION_NAMES_ENGLISH[] =
{ "FILTER" , SC_OPCODE_FILTER },
{ "SORT" , SC_OPCODE_SORT },
{ "SORTBY" , SC_OPCODE_SORTBY },
{ "CHOOSECOLS" , SC_OPCODE_CHOOSECOLS },
{ "CHOOSEROWS" , SC_OPCODE_CHOOSEROWS },
{ "DROP" , SC_OPCODE_DROP },
{ "EXPAND" , SC_OPCODE_EXPAND },
@ -2595,6 +2600,7 @@ const std::pair<TranslateId, int> RID_STRLIST_FUNCTION_NAMES[] =
{ NC_("RID_STRLIST_FUNCTION_NAMES", "FILTER") , SC_OPCODE_FILTER },
{ NC_("RID_STRLIST_FUNCTION_NAMES", "SORT") , SC_OPCODE_SORT },
{ NC_("RID_STRLIST_FUNCTION_NAMES", "SORTBY") , SC_OPCODE_SORTBY },
{ NC_("RID_STRLIST_FUNCTION_NAMES", "CHOOSECOLS") , SC_OPCODE_CHOOSECOLS },
{ NC_("RID_STRLIST_FUNCTION_NAMES", "CHOOSEROWS") , SC_OPCODE_CHOOSEROWS },
{ NC_("RID_STRLIST_FUNCTION_NAMES", "DROP") , SC_OPCODE_DROP },
{ NC_("RID_STRLIST_FUNCTION_NAMES", "EXPAND") , SC_OPCODE_EXPAND },

View File

@ -1279,6 +1279,7 @@ bool FormulaCompiler::IsMatrixFunction( OpCode eOpCode )
case ocSort :
case ocSortBy :
case ocRandArray :
case ocChooseCols :
case ocChooseRows :
case ocDrop :
case ocExpand :

View File

@ -517,16 +517,17 @@
#define SC_OPCODE_SORTBY 502
#define SC_OPCODE_MAT_SEQUENCE 503
#define SC_OPCODE_RANDARRAY 504
#define SC_OPCODE_CHOOSEROWS 505
#define SC_OPCODE_DROP 506
#define SC_OPCODE_EXPAND 507
#define SC_OPCODE_TAKE 508
#define SC_OPCODE_TOCOL 509
#define SC_OPCODE_TOROW 510
#define SC_OPCODE_UNIQUE 511
#define SC_OPCODE_WRAPCOLS 512
#define SC_OPCODE_WRAPROWS 513
#define SC_OPCODE_STOP_2_PAR 514 /* last function with two or more parameters' OpCode + 1 */
#define SC_OPCODE_CHOOSECOLS 505
#define SC_OPCODE_CHOOSEROWS 506
#define SC_OPCODE_DROP 507
#define SC_OPCODE_EXPAND 508
#define SC_OPCODE_TAKE 509
#define SC_OPCODE_TOCOL 510
#define SC_OPCODE_TOROW 511
#define SC_OPCODE_UNIQUE 512
#define SC_OPCODE_WRAPCOLS 513
#define SC_OPCODE_WRAPROWS 514
#define SC_OPCODE_STOP_2_PAR 515 /* 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 */

View File

@ -513,6 +513,7 @@ enum OpCode : sal_uInt16
ocSortBy = SC_OPCODE_SORTBY,
ocMatSequence = SC_OPCODE_MAT_SEQUENCE,
ocRandArray = SC_OPCODE_RANDARRAY,
ocChooseCols = SC_OPCODE_CHOOSECOLS,
ocChooseRows = SC_OPCODE_CHOOSEROWS,
ocDrop = SC_OPCODE_DROP,
ocExpand = SC_OPCODE_EXPAND,
@ -1006,6 +1007,7 @@ inline std::string OpCodeEnumToString(OpCode eCode)
case ocFilter: return "Filter";
case ocSort: return "Sort";
case ocSortBy: return "SortBy";
case ocChooseCols: return "ChooseCols";
case ocChooseRows: return "ChooseRows";
case ocDrop: return "Drop";
case ocExpand: return "Expand";

View File

@ -55,6 +55,7 @@ properties, see ODF v1.3 part4 3.4 Host-Defined Behaviors
https://docs.oasis-open.org/office/OpenDocument/v1.3/os/part4-formula/OpenDocument-v1.3-os-part4-formula.html#__RefHeading__1017868_715980110
* Array Functions
* CHOOSECOLS
* CHOOSEROWS
* DROP
* EXPAND

View File

@ -600,6 +600,7 @@ inline constexpr OUString HID_FUNC_XMATCH_MS = u"SC_HID_FUNC_XMATCH_MS"_ustr;
inline constexpr OUString HID_FUNC_FILTER_MS = u"SC_HID_FUNC_FILTER_MS"_ustr;
inline constexpr OUString HID_FUNC_SORT_MS = u"SC_HID_FUNC_SORT_MS"_ustr;
inline constexpr OUString HID_FUNC_SORTBY_MS = u"SC_HID_FUNC_SORTBY_MS"_ustr;
inline constexpr OUString HID_FUNC_CHOOSECOLS_MS = u"SC_HID_FUNC_CHOOSECOLS_MS"_ustr;
inline constexpr OUString HID_FUNC_CHOOSEROWS_MS = u"SC_HID_FUNC_CHOOSEROWS_MS"_ustr;
inline constexpr OUString HID_FUNC_DROP_MS = u"SC_HID_FUNC_DROP_MS"_ustr;
inline constexpr OUString HID_FUNC_EXPAND_MS = u"SC_HID_FUNC_EXPAND_MS"_ustr;

View File

@ -4251,6 +4251,18 @@ const TranslateId SC_OPCODE_RANDARRAY_ARY[] =
NC_("SC_OPCODE_RANDARRAY", "Return integer (TRUE) or decimal (FALSE) values.")
};
// -=*# Resource for function CHOOSECOLS #*=-
const TranslateId SC_OPCODE_CHOOSECOLS_ARY[] =
{
NC_("SC_OPCODE_CHOOSECOLS", "Returns the specified columns from an array."),
NC_("SC_OPCODE_CHOOSECOLS", "Array"),
NC_("SC_OPCODE_CHOOSECOLS", "The array containing the rows to be returned in the new array."),
NC_("SC_OPCODE_CHOOSECOLS", "Column 1"),
NC_("SC_OPCODE_CHOOSECOLS", "The first column number to be returned."),
NC_("SC_OPCODE_CHOOSECOLS", "Column 2"),
NC_("SC_OPCODE_CHOOSECOLS", "Column 2, Column 3,... The list of column numbers to be returned.")
};
// -=*# Resource for function CHOOSEROWS #*=-
const TranslateId SC_OPCODE_CHOOSEROWS_ARY[] =
{

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(412)
, XIndexAccess(413)
, 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

View File

@ -3097,6 +3097,7 @@ CPPUNIT_TEST_FIXTURE(Test, testFunctionLists)
"ADDRESS",
"AREAS",
"CHOOSE",
"CHOOSECOLS",
"CHOOSEROWS",
"COLUMN",
"COLUMNS",

View File

@ -793,6 +793,7 @@ ScFunctionList::ScFunctionList( bool bEnglishFunctionNames )
{ SC_OPCODE_SORTBY, ENTRY(SC_OPCODE_SORTBY_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_SORTBY_MS, PAIRED_VAR_ARGS + 1, { 0, 0, 1 }, 0 },
{ SC_OPCODE_MAT_SEQUENCE, ENTRY(SC_OPCODE_MAT_SEQUENCE_ARY), 0, ID_FUNCTION_GRP_MATRIX, HID_FUNC_MSEQUENCE_MS, 4, { 0, 1, 1, 1 }, 0 },
{ SC_OPCODE_RANDARRAY, ENTRY(SC_OPCODE_RANDARRAY_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_RANDARRAY_MS, 5, { 1, 1, 1, 1, 1 }, 0 },
{ SC_OPCODE_CHOOSECOLS, ENTRY(SC_OPCODE_CHOOSECOLS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_CHOOSECOLS_MS, VAR_ARGS + 2, { 0, 0, 1 }, 0 },
{ SC_OPCODE_CHOOSEROWS, ENTRY(SC_OPCODE_CHOOSEROWS_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_CHOOSEROWS_MS, VAR_ARGS + 2, { 0, 0, 1 }, 0 },
{ SC_OPCODE_DROP, ENTRY(SC_OPCODE_DROP_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_DROP_MS, 3, { 0, 0, 1 }, 0 },
{ SC_OPCODE_EXPAND, ENTRY(SC_OPCODE_EXPAND_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_EXPAND_MS, 4, { 0, 0, 1, 1 }, 0 },

View File

@ -724,6 +724,7 @@ private:
void ScFilter();
void ScSort();
void ScSortBy();
void ScChooseCols();
void ScChooseRows();
void ScDrop();
void ScExpand();
@ -737,6 +738,7 @@ private:
void ScWrapRows();
private:
void ScChooseColsOrRows(bool bCols);
void ScToColOrRow(bool bCol);
void ScWrapColsOrRows(bool bCols);
void ScTakeOrDrop(bool bTake);

View File

@ -8960,7 +8960,17 @@ void ScInterpreter::ScTakeOrDrop(bool bTake)
PushMatrix(pResMat);
}
void ScInterpreter::ScChooseCols()
{
ScChooseColsOrRows(/*bCols*/ true);
}
void ScInterpreter::ScChooseRows()
{
ScChooseColsOrRows(/*bCols*/ false);
}
void ScInterpreter::ScChooseColsOrRows(bool bCols)
{
sal_uInt8 nParamCount = GetByte();
@ -8997,7 +9007,7 @@ void ScInterpreter::ScChooseRows()
return;
}
std::vector<sal_Int32> aRowsVector;
std::vector<sal_Int32> aParamsVector;
while (nGlobalError == FormulaError::NONE && nParamCount-- > 1)
{
if (IsMissing())
@ -9021,17 +9031,18 @@ void ScInterpreter::ScChooseRows()
{
if (!pRefMatrix->IsStringOrEmpty(nC, nR))
{
sal_Int32 nRow = double_to_int32(pRefMatrix->GetDouble(col, row));
if (nRow < 0)
nRow = nsR + nRow + 1;
sal_Int32 nParam = double_to_int32(pRefMatrix->GetDouble(col, row));
sal_Int32 nMax = bCols ? nsC : nsR;
if (nParam < 0)
nParam = nMax + nParam + 1;
if (nRow <= 0 || o3tl::make_unsigned(nRow) > nsR)
if (nParam <= 0 || nParam > nMax)
{
PushIllegalParameter();
return;
}
else
aRowsVector.push_back(nRow);
aParamsVector.push_back(nParam);
}
else
{
@ -9048,18 +9059,23 @@ void ScInterpreter::ScChooseRows()
return;
}
ScMatrixRef pResMat = GetNewMat(nsC, aRowsVector.size(), /*bEmpty*/true);
SCSIZE nColumns = bCols ? aParamsVector.size() : nsC;
SCSIZE nRows = bCols ? nsR : aParamsVector.size();
ScMatrixRef pResMat = GetNewMat(nColumns, nRows, /*bEmpty*/true);
if (!pResMat)
{
PushIllegalArgument();
return;
}
for (SCSIZE col = 0; col < nsC; ++col)
for (SCSIZE col = 0; col < nColumns; ++col)
{
for(SCSIZE row = 0; row < aRowsVector.size(); ++row)
for(SCSIZE row = 0; row < nRows; ++row)
{
lcl_FillCell(pMatSource, pResMat, col, aRowsVector[row] - 1, col, row);
if (bCols)
lcl_FillCell(pMatSource, pResMat, aParamsVector[col] - 1, row, col, row);
else
lcl_FillCell(pMatSource, pResMat, col, aParamsVector[row] - 1, col, row);
}
}

View File

@ -4129,6 +4129,7 @@ StackVar ScInterpreter::Interpret()
case ocIfError : ScIfError( false ); break;
case ocIfNA : ScIfError( true ); break;
case ocChoose : ScChooseJump(); break;
case ocChooseCols : ScChooseCols(); break;
case ocChooseRows : ScChooseRows(); break;
case ocAdd : ScAdd(); break;
case ocSub : ScSub(); break;

View File

@ -57,6 +57,7 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] =
{ ocIfError, {{ Array, Reference }, 0, Value }},
{ ocIfNA, {{ Array, Reference }, 0, Value }},
{ ocChoose, {{ Array, Reference }, 1, Value }},
{ ocChooseCols, {{ ReferenceOrRefArray, ReferenceOrRefArray, ReferenceOrRefArray, }, 2, ForceArrayReturn }},
{ ocChooseRows, {{ ReferenceOrRefArray, ReferenceOrRefArray, ReferenceOrRefArray, }, 2, ForceArrayReturn }},
{ ocLet, {{ Value, ReferenceOrRefArray, ReferenceOrRefArray, }, 2, ForceArrayReturn } },
// Other specials.

View File

@ -1591,6 +1591,7 @@ void ScTokenArray::CheckToken( const FormulaToken& r )
case ocAveDev:
case ocMatSequence:
case ocRandArray:
case ocChooseCols:
case ocChooseRows:
case ocDrop:
case ocExpand:

View File

@ -619,6 +619,7 @@ const XclFunctionInfo saFuncTable_2021[] =
*/
const XclFunctionInfo saFuncTable_2024[] =
{
EXC_FUNCENTRY_V_VR( ocChooseCols, 2, MX, 0, "CHOOSECOLS" ),
EXC_FUNCENTRY_V_VR( ocChooseRows, 2, MX, 0, "CHOOSEROWS" ),
EXC_FUNCENTRY_V_VR( ocDrop, 1, 3, 0, "DROP" ),
EXC_FUNCENTRY_V_VR( ocExpand, 2, 4, 0, "EXPAND" ),

View File

@ -894,6 +894,7 @@ const FunctionData saFuncTable2021[] =
/* FIXME: BIFF?? function identifiers available? Where to obtain? */
const FunctionData saFuncTable2024[] =
{
{ "COM.MICROSOFT.CHOOSECOLS", "CHOOSECOLS", NOID, NOID, 2, MX, A, { VO }, FuncFlags::MACROCALL_NEW },
{ "COM.MICROSOFT.CHOOSEROWS", "CHOOSEROWS", NOID, NOID, 2, MX, A, { VO }, FuncFlags::MACROCALL_NEW },
{ "COM.MICROSOFT.DROP", "DROP", NOID, NOID, 1, 3, A, { VO }, FuncFlags::MACROCALL_NEW },
{ "COM.MICROSOFT.EXPAND", "EXPAND", NOID, NOID, 2, 4, A, { VO }, FuncFlags::MACROCALL_NEW },