tdf#151001: Add support for EXPAND function
Change-Id: I4eabd526d656c13da7792d3c195f036ce78bd0d9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180706 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
@@ -282,6 +282,7 @@ const std::pair<const char *, int> RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF[] =
|
||||
{ "COM.MICROSOFT.SORT" , SC_OPCODE_SORT },
|
||||
{ "COM.MICROSOFT.SORTBY" , SC_OPCODE_SORTBY },
|
||||
{ "COM.MICROSOFT.DROP" , SC_OPCODE_DROP },
|
||||
{ "COM.MICROSOFT.EXPAND" , SC_OPCODE_EXPAND },
|
||||
{ "COM.MICROSOFT.TAKE" , SC_OPCODE_TAKE },
|
||||
{ "COM.MICROSOFT.TOCOL" , SC_OPCODE_TOCOL },
|
||||
{ "COM.MICROSOFT.TOROW" , SC_OPCODE_TOROW },
|
||||
@@ -745,6 +746,7 @@ const std::pair<const char *, int> RID_STRLIST_FUNCTION_NAMES_ENGLISH_OOXML[] =
|
||||
{ "_xlfn._xlws.SORT" , SC_OPCODE_SORT },
|
||||
{ "_xlfn.SORTBY" , SC_OPCODE_SORTBY },
|
||||
{ "_xlfn.DROP" , SC_OPCODE_DROP },
|
||||
{ "_xlfn.EXPAND" , SC_OPCODE_EXPAND },
|
||||
{ "_xlfn.TAKE" , SC_OPCODE_TAKE },
|
||||
{ "_xlfn.TOCOL" , SC_OPCODE_TOCOL },
|
||||
{ "_xlfn.TOROW" , SC_OPCODE_TOROW },
|
||||
@@ -1211,6 +1213,7 @@ const std::pair<const char *, int> RID_STRLIST_FUNCTION_NAMES_ENGLISH_PODF[] =
|
||||
{ "SORT" , SC_OPCODE_SORT },
|
||||
{ "SORTBY" , SC_OPCODE_SORTBY },
|
||||
{ "DROP" , SC_OPCODE_DROP },
|
||||
{ "EXPAND" , SC_OPCODE_EXPAND },
|
||||
{ "TAKE" , SC_OPCODE_TAKE },
|
||||
{ "TOCOL" , SC_OPCODE_TOCOL },
|
||||
{ "TOROW" , SC_OPCODE_TOROW },
|
||||
@@ -1677,6 +1680,7 @@ const std::pair<const char *, int> RID_STRLIST_FUNCTION_NAMES_ENGLISH_API[] =
|
||||
{ "SORT" , SC_OPCODE_SORT },
|
||||
{ "SORTBY" , SC_OPCODE_SORTBY },
|
||||
{ "DROP" , SC_OPCODE_DROP },
|
||||
{ "EXPAND" , SC_OPCODE_EXPAND },
|
||||
{ "TAKE" , SC_OPCODE_TAKE },
|
||||
{ "TOCOL" , SC_OPCODE_TOCOL },
|
||||
{ "TOROW" , SC_OPCODE_TOROW },
|
||||
@@ -2141,6 +2145,7 @@ const std::pair<const char *, int> RID_STRLIST_FUNCTION_NAMES_ENGLISH[] =
|
||||
{ "SORT" , SC_OPCODE_SORT },
|
||||
{ "SORTBY" , SC_OPCODE_SORTBY },
|
||||
{ "DROP" , SC_OPCODE_DROP },
|
||||
{ "EXPAND" , SC_OPCODE_EXPAND },
|
||||
{ "TAKE" , SC_OPCODE_TAKE },
|
||||
{ "TOCOL" , SC_OPCODE_TOCOL },
|
||||
{ "TOROW" , SC_OPCODE_TOROW },
|
||||
@@ -2586,6 +2591,7 @@ const std::pair<TranslateId, int> RID_STRLIST_FUNCTION_NAMES[] =
|
||||
{ NC_("RID_STRLIST_FUNCTION_NAMES", "SORT") , SC_OPCODE_SORT },
|
||||
{ NC_("RID_STRLIST_FUNCTION_NAMES", "SORTBY") , SC_OPCODE_SORTBY },
|
||||
{ NC_("RID_STRLIST_FUNCTION_NAMES", "DROP") , SC_OPCODE_DROP },
|
||||
{ NC_("RID_STRLIST_FUNCTION_NAMES", "EXPAND") , SC_OPCODE_EXPAND },
|
||||
{ NC_("RID_STRLIST_FUNCTION_NAMES", "TAKE") , SC_OPCODE_TAKE },
|
||||
{ NC_("RID_STRLIST_FUNCTION_NAMES", "TOCOL") , SC_OPCODE_TOCOL },
|
||||
{ NC_("RID_STRLIST_FUNCTION_NAMES", "TOROW") , SC_OPCODE_TOROW },
|
||||
|
||||
@@ -1280,6 +1280,7 @@ bool FormulaCompiler::IsMatrixFunction( OpCode eOpCode )
|
||||
case ocSortBy :
|
||||
case ocRandArray :
|
||||
case ocDrop :
|
||||
case ocExpand :
|
||||
case ocTake :
|
||||
case ocToCol :
|
||||
case ocToRow :
|
||||
|
||||
@@ -518,13 +518,14 @@
|
||||
#define SC_OPCODE_MAT_SEQUENCE 503
|
||||
#define SC_OPCODE_RANDARRAY 504
|
||||
#define SC_OPCODE_DROP 505
|
||||
#define SC_OPCODE_TAKE 506
|
||||
#define SC_OPCODE_TOCOL 507
|
||||
#define SC_OPCODE_TOROW 508
|
||||
#define SC_OPCODE_UNIQUE 509
|
||||
#define SC_OPCODE_WRAPCOLS 510
|
||||
#define SC_OPCODE_WRAPROWS 511
|
||||
#define SC_OPCODE_STOP_2_PAR 512 /* last function with two or more parameters' OpCode + 1 */
|
||||
#define SC_OPCODE_EXPAND 506
|
||||
#define SC_OPCODE_TAKE 507
|
||||
#define SC_OPCODE_TOCOL 508
|
||||
#define SC_OPCODE_TOROW 509
|
||||
#define SC_OPCODE_UNIQUE 510
|
||||
#define SC_OPCODE_WRAPCOLS 511
|
||||
#define SC_OPCODE_WRAPROWS 512
|
||||
#define SC_OPCODE_STOP_2_PAR 513 /* 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 */
|
||||
|
||||
@@ -514,6 +514,7 @@ enum OpCode : sal_uInt16
|
||||
ocMatSequence = SC_OPCODE_MAT_SEQUENCE,
|
||||
ocRandArray = SC_OPCODE_RANDARRAY,
|
||||
ocDrop = SC_OPCODE_DROP,
|
||||
ocExpand = SC_OPCODE_EXPAND,
|
||||
ocTake = SC_OPCODE_TAKE,
|
||||
ocToCol = SC_OPCODE_TOCOL,
|
||||
ocToRow = SC_OPCODE_TOROW,
|
||||
@@ -1005,6 +1006,7 @@ inline std::string OpCodeEnumToString(OpCode eCode)
|
||||
case ocSort: return "Sort";
|
||||
case ocSortBy: return "SortBy";
|
||||
case ocDrop: return "Drop";
|
||||
case ocExpand: return "Expand";
|
||||
case ocTake: return "Take";
|
||||
case ocToCol: return "ToCol";
|
||||
case ocToRow: return "ToRow";
|
||||
|
||||
@@ -56,6 +56,7 @@ https://docs.oasis-open.org/office/OpenDocument/v1.3/os/part4-formula/OpenDocume
|
||||
|
||||
* Array Functions
|
||||
* DROP
|
||||
* EXPAND
|
||||
* TAKE
|
||||
* TOCOL
|
||||
* TOROW
|
||||
|
||||
@@ -601,6 +601,7 @@ 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_DROP_MS = u"SC_HID_FUNC_DROP_MS"_ustr;
|
||||
inline constexpr OUString HID_FUNC_EXPAND_MS = u"SC_HID_FUNC_EXPAND_MS"_ustr;
|
||||
inline constexpr OUString HID_FUNC_TAKE_MS = u"SC_HID_FUNC_TAKE_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;
|
||||
|
||||
@@ -4263,6 +4263,20 @@ const TranslateId SC_OPCODE_DROP_ARY[] =
|
||||
NC_("SC_OPCODE_DROP", "The number of columns to drop. A negative value drops from the end of the array.")
|
||||
};
|
||||
|
||||
// -=*# Resource for function EXPAND #*=-
|
||||
const TranslateId SC_OPCODE_EXPAND_ARY[] =
|
||||
{
|
||||
NC_("SC_OPCODE_EXPAND", "Expands or pads an array to specified row and column dimensions."),
|
||||
NC_("SC_OPCODE_EXPAND", "Array"),
|
||||
NC_("SC_OPCODE_EXPAND", "The array to expand."),
|
||||
NC_("SC_OPCODE_EXPAND", "Rows"),
|
||||
NC_("SC_OPCODE_EXPAND", "The number of rows in the expanded array. If missing, rows will not be expanded."),
|
||||
NC_("SC_OPCODE_EXPAND", "Column"),
|
||||
NC_("SC_OPCODE_EXPAND", "The number of columns in the expanded array. If missing, columns will not be expanded."),
|
||||
NC_("SC_OPCODE_EXPAND", "Pad with"),
|
||||
NC_("SC_OPCODE_EXPAND", "The value with which to pad. The default is #N/A.")
|
||||
};
|
||||
|
||||
// -=*# Resource for function TAKE #*=-
|
||||
const TranslateId SC_OPCODE_TAKE_ARY[] =
|
||||
{
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
ScFunctionListObj::ScFunctionListObj()
|
||||
: UnoApiTest(u"/sc/qa/extras/testdocuments"_ustr)
|
||||
, XElementAccess(cppu::UnoType<uno::Sequence<beans::PropertyValue>>::get())
|
||||
, XIndexAccess(410)
|
||||
, XIndexAccess(411)
|
||||
, 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
@@ -3103,6 +3103,7 @@ CPPUNIT_TEST_FIXTURE(Test, testFunctionLists)
|
||||
"DROP",
|
||||
"ERROR.TYPE",
|
||||
"ERRORTYPE",
|
||||
"EXPAND",
|
||||
"FILTER",
|
||||
"GETPIVOTDATA",
|
||||
"HLOOKUP",
|
||||
|
||||
@@ -794,6 +794,7 @@ ScFunctionList::ScFunctionList( bool bEnglishFunctionNames )
|
||||
{ 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_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 },
|
||||
{ SC_OPCODE_TAKE, ENTRY(SC_OPCODE_TAKE_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_TAKE_MS, 3, { 0, 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 },
|
||||
|
||||
@@ -725,6 +725,7 @@ private:
|
||||
void ScSort();
|
||||
void ScSortBy();
|
||||
void ScDrop();
|
||||
void ScExpand();
|
||||
void ScTake();
|
||||
void ScToCol();
|
||||
void ScToRow();
|
||||
|
||||
@@ -8936,6 +8936,140 @@ void ScInterpreter::ScDrop()
|
||||
PushMatrix(pResMat);
|
||||
}
|
||||
|
||||
void ScInterpreter::ScExpand()
|
||||
{
|
||||
sal_uInt8 nParamCount = GetByte();
|
||||
if (!MustHaveParamCount(nParamCount, 2, 4))
|
||||
return;
|
||||
|
||||
// 4rd argument optional - pad_with
|
||||
std::optional<bool> bDouble;
|
||||
double fNumber(0.0);
|
||||
svl::SharedString aString;
|
||||
if (nParamCount == 4)
|
||||
bDouble = GetDoubleOrString(fNumber, aString);
|
||||
|
||||
// 3rd argument optional - columns
|
||||
std::optional<sal_Int32> nArgCols;
|
||||
if (nParamCount >= 3)
|
||||
{
|
||||
if (!IsMissing())
|
||||
nArgCols = GetInt32();
|
||||
else
|
||||
Pop();
|
||||
}
|
||||
|
||||
// 2nd argument - rows
|
||||
std::optional<sal_Int32> nArgRows;
|
||||
if (nParamCount >= 2)
|
||||
{
|
||||
if (!IsMissing())
|
||||
nArgRows = GetInt32();
|
||||
else
|
||||
Pop();
|
||||
}
|
||||
|
||||
// 1st argument: take unique search range
|
||||
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);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
PushIllegalParameter();
|
||||
return;
|
||||
}
|
||||
|
||||
if (nGlobalError != FormulaError::NONE || nsC < 1 || nsR < 1)
|
||||
{
|
||||
PushIllegalArgument();
|
||||
return;
|
||||
}
|
||||
|
||||
SCSIZE nColumns = nsC;
|
||||
SCSIZE nRows = nsR;
|
||||
if (nArgCols.has_value())
|
||||
{
|
||||
if (o3tl::make_unsigned(std::abs(nArgCols.value())) < nsC)
|
||||
{
|
||||
PushIllegalArgument();
|
||||
return;
|
||||
}
|
||||
else
|
||||
nColumns = nArgCols.value();
|
||||
}
|
||||
|
||||
if (nArgRows.has_value())
|
||||
{
|
||||
if (o3tl::make_unsigned(std::abs(nArgRows.value())) < nsR)
|
||||
{
|
||||
PushIllegalArgument();
|
||||
return;
|
||||
}
|
||||
else
|
||||
nRows = nArgRows.value();
|
||||
}
|
||||
|
||||
ScMatrixRef pResMat = GetNewMat(nColumns, nRows, /*bEmpty*/true);
|
||||
if (!pResMat)
|
||||
{
|
||||
PushIllegalArgument();
|
||||
return;
|
||||
}
|
||||
|
||||
for (SCSIZE col = 0; col < nColumns; ++col)
|
||||
{
|
||||
for (SCSIZE row = 0; row < nRows; ++row)
|
||||
{
|
||||
if (col < nsC && row < nsR)
|
||||
{
|
||||
if (pMatSource->IsEmptyCell(col, row))
|
||||
{
|
||||
pResMat->PutEmpty(col, row);
|
||||
}
|
||||
else if (!pMatSource->IsStringOrEmpty(col, row))
|
||||
{
|
||||
pResMat->PutDouble(pMatSource->GetDouble(col, row), col, row);
|
||||
}
|
||||
else
|
||||
{
|
||||
pResMat->PutString(pMatSource->GetString(col, row), col, row);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bDouble.has_value())
|
||||
{
|
||||
if (bDouble.value())
|
||||
pResMat->PutDouble(fNumber, col, row);
|
||||
else
|
||||
pResMat->PutString(aString, col, row);
|
||||
}
|
||||
else
|
||||
pResMat->PutError(FormulaError::NotAvailable, col, row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PushMatrix(pResMat);
|
||||
}
|
||||
|
||||
void ScInterpreter::ScTake()
|
||||
{
|
||||
sal_uInt8 nParamCount = GetByte();
|
||||
|
||||
@@ -4160,6 +4160,7 @@ StackVar ScInterpreter::Interpret()
|
||||
case ocSort : ScSort(); break;
|
||||
case ocSortBy : ScSortBy(); break;
|
||||
case ocDrop : ScDrop(); break;
|
||||
case ocExpand : ScExpand(); break;
|
||||
case ocTake : ScTake(); break;
|
||||
case ocToCol : ScToCol(); break;
|
||||
case ocToRow : ScToRow(); break;
|
||||
|
||||
@@ -137,6 +137,7 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] =
|
||||
{ ocDevSq, {{ Reference }, 1, Value }},
|
||||
{ ocDiv, {{ Array, Array }, 0, Value }},
|
||||
{ ocDrop, {{ ReferenceOrRefArray, Value, Value, }, 0, ForceArrayReturn } },
|
||||
{ ocExpand, {{ ReferenceOrRefArray, Value, Value, }, 0, ForceArrayReturn } },
|
||||
{ ocEqual, {{ Array, Array }, 0, Value }},
|
||||
{ ocFTest, {{ ForceArray, ForceArray }, 0, Value }},
|
||||
{ ocFalse, {{ Bounds }, 0, Value }},
|
||||
|
||||
@@ -1592,6 +1592,7 @@ void ScTokenArray::CheckToken( const FormulaToken& r )
|
||||
case ocMatSequence:
|
||||
case ocRandArray:
|
||||
case ocDrop:
|
||||
case ocExpand:
|
||||
case ocTake:
|
||||
case ocToCol:
|
||||
case ocToRow:
|
||||
|
||||
@@ -620,6 +620,7 @@ const XclFunctionInfo saFuncTable_2021[] =
|
||||
const XclFunctionInfo saFuncTable_2024[] =
|
||||
{
|
||||
EXC_FUNCENTRY_V_VR( ocDrop, 1, 3, 0, "DROP" ),
|
||||
EXC_FUNCENTRY_V_VR( ocExpand, 2, 4, 0, "EXPAND" ),
|
||||
EXC_FUNCENTRY_V_VR( ocTake, 1, 3, 0, "TAKE" ),
|
||||
EXC_FUNCENTRY_V_VR( ocToCol, 1, 3, 0, "TOCOL" ),
|
||||
EXC_FUNCENTRY_V_VR( ocToRow, 1, 3, 0, "TOROW" ),
|
||||
|
||||
@@ -895,6 +895,7 @@ const FunctionData saFuncTable2021[] =
|
||||
const FunctionData saFuncTable2024[] =
|
||||
{
|
||||
{ "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 },
|
||||
{ "COM.MICROSOFT.TAKE", "TAKE", NOID, NOID, 1, 3, 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 },
|
||||
|
||||
Reference in New Issue
Block a user