0

I'm new to java so please bear with me. I know java apache poi has the following functions built in but I'm a little lost as to how to use it:

1) code_col = WorksheetFunction.Match("Code", sheet.Range("1:1"), 0)

2) count = WorksheetFunction.CountIf(ref_sheet.Range("A:A"), payee)

3) lr = sheet.Cells(1, 1).CurrentRegion.Rows.count

If you could provide example of how the VBA code converts to its java apache poi equivalent it would be a great help.
So Im basically converting a VBA module to java. And I use the apache poi library. However, those 3 above lines of code I have difficulty converting to its java equivalent

2
  • 1
    Apache poi is made for creating files for Microsoft Office. So apache poi is able creating Excel files having the functions MATCH and COUNTIF stored in formulas in cells. It is also able to evaluate those formulas if it has access to all of the cells which are referenced in those formulas. But it can neither creating nor interpreting VBA. Please make your question more clear about what is the initial state and what is the expected result. Commented Oct 8, 2017 at 14:05
  • This is a good question. To me it makes sense that an Excel macro should basically be able to transpile to Apache POI, at least for basic stuff like "select cell A1, copy value to cell A2". I was hoping I could record a macro and then convert it to Java with a tool. Commented Mar 30, 2019 at 19:25

1 Answer 1

1

As said in my comment already, this question cannot be answered that general.

Apache poi is made for creating files for Microsoft Office. So apache poi is able creating Excel files having the functions MATCH and COUNTIF stored in formulas in cells. It is also able to evaluate those formulas if it has access to all of the cells which are referenced in those formulas.

So for a concrete example, having a MSExcelWithVBA.xlsm like this:

enter image description here

and VBA code like this:

Sub test()
 Set this_sheet = ThisWorkbook.Worksheets("Sheet1")
 code_col = WorksheetFunction.Match("Code", this_sheet.Range("1:1"), 0)
 Debug.Print "code_col: " & code_col
 payee = "b"
 payee_count = WorksheetFunction.CountIf(this_sheet.Range("A:A"), payee)
 Debug.Print "payee_count: " & payee_count
 count_rows_in_region = this_sheet.Cells(1, 1).CurrentRegion.Rows.Count
 Debug.Print "count_rows_in_region: " & count_rows_in_region
End Sub

Then this VBA code prints to the immediate window:

code_col: 4
payee_count: 3
count_rows_in_region: 9

With the same MSExcelWithVBA.xlsm, a Java code like this:

import java.io.FileInputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.formula.WorkbookEvaluator;
import org.apache.poi.ss.formula.eval.*;

public class ExcelEvaluateSomeFunctions{

 public static void main(String[] args) throws Exception {
  Workbook workbook = WorkbookFactory.create(new FileInputStream("MSExcelWithVBA.xlsm"));
  Sheet this_sheet = workbook.getSheet("Sheet1");
  CreationHelper helper = workbook.getCreationHelper();

  XSSFFormulaEvaluator formulaevaluator = (XSSFFormulaEvaluator)helper.createFormulaEvaluator();
  WorkbookEvaluator workbookevaluator = formulaevaluator._getWorkbookEvaluator();
  ValueEval valueeval = null;

  //code_col = WorksheetFunction.Match("Code", this_sheet.Range("1:1"), 0)
  double code_col = Double.NaN;
  valueeval = workbookevaluator.evaluate("MATCH(\"Code\", " + this_sheet.getSheetName() + "!1:1, 0)", null);
  if (valueeval instanceof NumberEval) {
   code_col = ((NumberEval)valueeval).getNumberValue();
  }
  System.out.println("code_col: " + code_col);

  //payee_count = WorksheetFunction.CountIf(this_sheet.Range("A:A"), payee)
  String payee = "b";
  double payee_count = Double.NaN;
  valueeval = workbookevaluator.evaluate("COUNTIF(" + this_sheet.getSheetName() + "!A:A, \"" + payee + "\")", null);
  if (valueeval instanceof NumberEval) {
   payee_count = ((NumberEval)valueeval).getNumberValue();
  }
  System.out.println("payee_count: " + payee_count);

  //count_rows_in_region = this_sheet.Cells(1, 1).CurrentRegion.Rows.Count
  //this is not possible since apache poi does not know the concept of CurrentRegion
  //best you could do:
  int count_rows_in_sheet = this_sheet.getLastRowNum()+1;
  System.out.println("count_rows_in_sheet: " + count_rows_in_sheet);

  workbook.close();
 }  
}

prints to System.out:

code_col: 4.0
payee_count: 3.0
count_rows_in_sheet: 9
Sign up to request clarification or add additional context in comments.

4 Comments

Is there any way to use a user-defined function that is already written in VBA from the excel file? (Since my VBA code is difficult to convert to Java code because it uses Chart object which is not completely implemented with Apache POI.)
@wonsuc: No, apache poi is not able to interpret VBA. And also it does not interact with Excel application.
I found interesting behavior that XSSFFormulaEvaluator.evaluateAllFormulaCells(workbook); this doesn't work for VBA user-defined function, but workbook.setForceFormulaRecalculation(true); this worked. B27 cell already had =setChartAxis("Result","ProbChart") which is user-defined function and I only needed to recalculate it. However I have no idea what's difference between evaluating formular and recalculating formular in Apache POI
@wonsuc: workbook.setForceFormulaRecalculation(true) forces Excel to recalculate all formulas while next time opening that workbook. So the values will be recalculated only if Excel opens the workbook. The apache poi FormulaEvaluator tries evaluating the formulas independent of Excel.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.