Using AbstractCalculationEngine Feature
Introduction
This article provides an understanding of how to use the AbstractCalculationEngine feature to implement custom functions with Aspose.Cells APIs.
The AbstractCalculationEngine interface allows you to add custom formula calculation functions to extend the Aspose.Cells core calculation engine in order to meet certain requirements. This feature is useful to define custom (user defined) functions in a template file or in a code where the custom function can be implemented and evaluated using Aspose.Cells APIs like any other default Microsoft Excel function.
Using AbstractCalculationEngine Feature - 1
The following sample code implements the AbstractCalculationEngine interface which evaluates and returns the values of the two custom functions i.e. MySampleFunc() and YourSampleFunc(). These custom functions are inside the cells A1 and A2 respectively. Then it calls the Workbook.CalculateFormula(const CalculationOptions& options) method to invoke the implementation of AbstractCalculationEngine .Calculate(CalculationData& data) method. Then, it prints the values of A1 and A2 on console. Please see the Console Output of the sample code below for more help.
Sample Code
Aspose::Cells::Startup(); | |
//Implement AbstractCalculationEngine interface | |
class CustomFunction1 : public AbstractCalculationEngine | |
{ | |
public: | |
void Calculate(CalculationData& data) | |
{ | |
Object funcName = data.GetParamValue(0); | |
U16String cellName = data.GetCell().GetName(); | |
Object cellValue = data.GetParamValue(1); | |
if (data.GetFunctionName() == u"MySampleFunc") | |
{ | |
std::cout << funcName.ToString().ToUtf8() << " called successfully." << std::endl; | |
data.GetCell().PutValue(cellValue); | |
} | |
if (data.GetFunctionName() == u"YourSampleFunc") | |
{ | |
std::cout << funcName.ToString().ToUtf8() << " called successfully." << std::endl; | |
data.GetCell().PutValue(cellValue); | |
} | |
} | |
}; | |
//Create workbook | |
Workbook wb; | |
//Access first worksheet in the workbook | |
Worksheet ws = wb.GetWorksheets().Get(0); | |
//Adding custom formulas to Cell A1 and A2 | |
ws.GetCells().Get(u"A1").SetFormula(u"=MySampleFunc(\"MySampleFunc-Test\",1)"); | |
ws.GetCells().Get(u"A2").SetFormula(u"=YourSampleFunc(\"YourSampleFunc-Test\",2)"); | |
// Calcualting Formulas | |
CustomFunction1 custFunc; | |
CalculationOptions options; | |
options.SetCustomEngine(&custFunc); | |
wb.CalculateFormula(options); | |
//Print the value of cell A1 and A2 after the calculation of custom function implemented by us. | |
U16String valA1 = ws.GetCells().Get(u"A1").GetStringValue(); | |
U16String valA2 = ws.GetCells().Get(u"A2").GetStringValue(); | |
std::cout << "Value of A1 is : " << valA1.ToUtf8() << std::endl; | |
std::cout << "Value of A2 is : " << valA2.ToUtf8() << std::endl; | |
Aspose::Cells::Cleanup(); |
Console Output
MySampleFunc-Test called successfully.
YourSampleFunc-Test called successfully.
Value of A1 is : 1
Value of A2 is : 2
Using AbstractCalculationEngine Feature - 2
The following sample code reads a custom function from a sample file and calls the Workbook.CalculateFormula(const CalculationOptions& options) method to call the AbstractCalculationEngine .Calculate(CalculationData& data) method for further processing.
Sample file:sample-file.xlsx
Sample Code
Aspose::Cells::Startup(); | |
//Implement AbstractCalculationEngine interface | |
class CustomFunction2 : public AbstractCalculationEngine | |
{ | |
public: | |
int stage = 0; | |
public: | |
void Calculate(CalculationData& data) | |
{ | |
if (stage == 0) | |
{ | |
data.SetCalculatedValue(0); | |
return; | |
} | |
U16String s = data.GetFunctionName(); | |
if (u"crow" == s) | |
{ | |
data.SetCalculatedValue(data.GetParamValue(0)); | |
} | |
else if (u"crow2" == s) | |
{ | |
data.SetCalculatedValue(data.GetCellRow() + 1); | |
} | |
} | |
}; | |
//Create workbook | |
Workbook wb(u"sample-file.xlsx"); | |
Cells cells = wb.GetWorksheets().Get(0).GetCells(); | |
Cells cells2 = wb.GetWorksheets().Get(1).GetCells(); | |
U16String expectedValue = u"2"; | |
if (expectedValue != cells.Get(u"B2").GetStringValue()) | |
{ | |
std::cout << "Start test: The value of cell B2 is not 2." << std::endl; | |
} | |
cells.Get(u"A2").PutValue(2); | |
cells.Get(u"A3").PutValue(3); | |
// Calcualting Formulas | |
CustomFunction2* resolver1 = new CustomFunction2(); | |
resolver1->stage = 0; | |
CalculationOptions opt1; | |
opt1.SetCustomEngine(resolver1); | |
wb.CalculateFormula(opt1); | |
cells2.InsertRows(1, 9, true); | |
Range range = cells2.CreateRange(1, 0, 9, cells2.GetMaxColumn() + 1); | |
Range source = cells2.CreateRange(0, 0, 1, cells2.GetMaxColumn() + 1); | |
PasteOptions options; | |
options.SetPasteType(PasteType::All); | |
range.Copy(source, options); | |
// Calcualting Formulas | |
CustomFunction2* resolver2 = new CustomFunction2(); | |
resolver2->stage = 1; | |
CalculationOptions opt2; | |
opt2.SetCustomEngine(resolver2); | |
wb.CalculateFormula(opt2); | |
if (expectedValue == cells.Get(u"B2").GetStringValue()) | |
{ | |
std::cout << "End test: The value of cell B2 is 2." << std::endl; | |
} | |
delete resolver1; | |
delete resolver2; | |
Aspose::Cells::Cleanup(); |