Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Concat Function #1341

Merged
merged 2 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions main/SS/Formula/Atp/AnalysisToolPak.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ private static Dictionary<String, FreeRefFunction> CreateFunctionsMap()
r(m, "BIN2OCT", null);
r(m, "COMPLEX", Complex.Instance);
r(m, "CONVERT", null);
r(m, "CONCAT", TextFunction.CONCAT);
r(m, "COUNTIFS", Countifs.instance);
r(m, "COUPDAYBS", null);
r(m, "COUPDAYS", null);
Expand Down
39 changes: 39 additions & 0 deletions main/SS/Formula/Functions/Text/Concat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
namespace NPOI.SS.Formula.Functions
{
using System.Text;
using NPOI.SS.Formula.Eval;

public class Concat : FreeRefFunction
{
public ValueEval Evaluate(ValueEval[] args, OperationEvaluationContext ec)
{
StringBuilder sb = new StringBuilder();
foreach(ValueEval arg in args)
{
try
{
if(arg is AreaEval area)
{
for(int rn = 0; rn<area.Height; rn++)
{
for(int cn = 0; cn<area.Width; cn++)
{
ValueEval ve = area.GetRelativeValue(rn, cn);
sb.Append(TextFunction.EvaluateStringArg(ve, ec.RowIndex, ec.ColumnIndex));
}
}
}
else
{
sb.Append(TextFunction.EvaluateStringArg(arg, ec.RowIndex, ec.ColumnIndex));
}
}
catch (EvaluationException e) {
return e.GetErrorEval();
}
}
return new StringEval(sb.ToString());
}

}
}
1 change: 1 addition & 0 deletions main/SS/Formula/Functions/Text/TextFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ internal static bool IsPrintable(char c)
public static readonly Function RIGHT = new LeftRight(false);

public static readonly Function CONCATENATE = new Concatenate();
public static readonly FreeRefFunction CONCAT = new Concat();

public static readonly Function EXACT = new Exact();

Expand Down
104 changes: 104 additions & 0 deletions testcases/main/SS/Formula/Atp/TestConcat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using NPOI.HSSF.UserModel;
using NPOI.SS.Formula.Eval;
using NPOI.SS.UserModel;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Text;

namespace TestCases.SS.Formula.Atp
{
[TestFixture]
public class TestConcat
{
private IWorkbook wb;
private ISheet sheet;
private IFormulaEvaluator evaluator;
private ICell textCell1;
private ICell textCell2;
private ICell numericCell1;
private ICell numericCell2;
private ICell textCell3;
private ICell formulaCell;

private IWorkbook InitWorkbook1()
{
IWorkbook wb = new HSSFWorkbook();
ISheet sheet = wb.CreateSheet("Sheet1");

sheet.CreateRow(0).CreateCell(0).SetCellValue("Currency");
sheet.CreateRow(1).CreateCell(0).SetCellValue("US Dollar");
sheet.CreateRow(2).CreateCell(0).SetCellValue("Australian Dollar");
sheet.CreateRow(3).CreateCell(0).SetCellValue("Chinese Yuan");
sheet.CreateRow(4).CreateCell(0).SetCellValue("Hong Kong Dollar");
sheet.CreateRow(5).CreateCell(0).SetCellValue("Israeli Shekel");
sheet.CreateRow(6).CreateCell(0).SetCellValue("South Korean Won");
sheet.CreateRow(7).CreateCell(0).SetCellValue("Russian Ruble");
return wb;
}

[SetUp]
public void Setup()
{
wb = new HSSFWorkbook();
evaluator = wb.GetCreationHelper().CreateFormulaEvaluator();

sheet = wb.CreateSheet("CONCAT");
IRow row = sheet.CreateRow(0);

textCell1 = row.CreateCell(0);
textCell1.SetCellValue("One");

textCell2 = row.CreateCell(1);
textCell2.SetCellValue("Two");

textCell3 = row.CreateCell(2);
textCell3.SetCellValue("Three");

numericCell1 = row.CreateCell(3);
numericCell1.SetCellValue(1);

numericCell2 = row.CreateCell(4);
numericCell2.SetCellValue(2);

formulaCell = row.CreateCell(100, CellType.Formula);
}

[Test]
public void TestConcatWithStrings()
{
evaluator.ClearAllCachedResultValues();
formulaCell.SetCellFormula("CONCAT(\"The\",\" \",\"sun\",\" \",\"will\",\" \",\"come\",\" \",\"up\",\" \",\"tomorrow.\")");
evaluator.EvaluateFormulaCell(formulaCell);
Assert.AreEqual("The sun will come up tomorrow.", formulaCell.StringCellValue);
}

[Test]
public void TestConcatWithColumns()
{
evaluator.ClearAllCachedResultValues();
formulaCell.SetCellFormula("CONCAT(B:B, C:C)");
evaluator.EvaluateFormulaCell(formulaCell);
Assert.AreEqual("TwoThree", formulaCell.StringCellValue);
}

[Test]
public void TestConcatWithCellRanges()
{
evaluator.ClearAllCachedResultValues();
formulaCell.SetCellFormula("CONCAT(A1:C1)");
evaluator.EvaluateFormulaCell(formulaCell);
Assert.AreEqual("OneTwoThree", formulaCell.StringCellValue);
}

[Test]
public void TestConcatWithCellRefs()
{
evaluator.ClearAllCachedResultValues();
formulaCell.SetCellFormula("CONCAT(\"ONE\", A1, \"TWO\",B1, \"THREE\",C1, \".\")");
evaluator.EvaluateFormulaCell(formulaCell);
Assert.AreEqual("ONEOneTWOTwoTHREEThree.", formulaCell.StringCellValue);
}

}
}
Loading