1

I am reading the data from Excel file, let us say I have 5 rows and 15 columns in Java testNG.

Review the below code

    Class ReadExcel {
    public String[][] getCellData(String path, String sheetName) throws InvalidFormatException, IOException {
              FileInputStream stream = new FileInputStream(path);
              XSSFWorkbook workbook = new XSSFWorkbook(stream);
              Sheet s = workbook.getSheet(sheetName);
              int rowcount = s.getLastRowNum();
              int cellcount = s.getRow(0).getLastCellNum();
              String data[][] = new String[rowcount][cellcount];
              FormulaEvaluator evaluator= workbook.getCreationHelper().createFormulaEvaluator();
              DataFormatter df = new DataFormatter();
              for (int i = 1; i <= rowcount; i++) {
                  Row r = s.getRow(i);
                  for (int j = 0; j < cellcount; j++) { 
                    Cell c = r.getCell(j);
                    try {
                        if(c!=null){
                            if (c.getCellType() == c.CELL_TYPE_STRING) {
                                  data[i - 1][j] = c.getStringCellValue();
                            }else if (c.getCellType() == c.CELL_TYPE_FORMULA) {
                                    data[i - 1][j] = df.formatCellValue(c, evaluator);
                            } 
                            else if (c.getCellType() == c.CELL_TYPE_BOOLEAN) {
                                data[i - 1][j] = df.formatCellValue(c, evaluator);
                            } 
                            else{
                                  data[i - 1][j] = String.valueOf(c.getNumericCellValue());
                            }
                        }
                    
                    } catch (Exception e) {
                         e.printStackTrace();
                    }
                  }
              }
              return data;
        }
}

Another class for processing the data

    public class Sample
{
        ReadExcel read = new ReadExcel();

    @DataProvider (parallel= true)
    public String[][] getFilterValues() throws InvalidFormatException, IOException, InterruptedException{
        
        return read.getCellData("fileLoc","fileName");
    }
    
    @Test(dataProvider = "getFilterValues")
    public void verifyReports(String row, String name, String age, String lastname and so on...) throws Exception
    {
        System.out.println(FileName);
        
    }

So, here I need to reduce the argument count in verifyReports method and should able to retrieve the entire records in the same method.

Note: Argument count may be changed in future.

So I tried with Map concept but I could not find out.

The main goal is to reduce the no. of arguments in verifyReports method. How to achieve this.

I achieved by using the below code. But it would be in 2D array in order to use it in testNG DataProviders

Below is the code, I tried using list of map.

public ArrayList<String> readHeader(String path, String sheetName) throws IOException
{
    FileInputStream stream = new FileInputStream(path);
      XSSFWorkbook workbook = new XSSFWorkbook(stream);
      Sheet s = workbook.getSheet(sheetName);
      int rowcount = s.getLastRowNum();
      int cellcount = s.getRow(0).getLastCellNum();
      ArrayList<String> al = new ArrayList<String>();
      Row r = s.getRow(0);
      for(int i=0;i<cellcount;i++)
      {
          Cell c = r.getCell(i);
          al.add(c.getStringCellValue());
      }
      return al;
}


public ArrayList<HashMap<String,String>> getCellData(String path, String sheetName) throws InvalidFormatException, IOException {
    //ExcelConfig ec = new ExcelConfig();
    FileInputStream stream = new FileInputStream(path);
    ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>(); 
      XSSFWorkbook workbook = new XSSFWorkbook(stream);
      Sheet s = workbook.getSheet(sheetName);
      int rowcount = s.getLastRowNum();
      int cellcount = s.getRow(0).getLastCellNum();
      FormulaEvaluator evaluator= workbook.getCreationHelper().createFormulaEvaluator();
      DataFormatter df = new DataFormatter();
      ArrayList<String> head = ec.readHeader(path, sheetName);
      for (int i = 1; i <= rowcount; i++) {
          HashMap<String,String> map = new HashMap<String,String>();
          Row r = s.getRow(i);
          for (int j = 0; j < cellcount; j++) { 
            Cell c = r.getCell(j);
            try {
                if(c!=null){
                    if (c.getCellType() == c.CELL_TYPE_STRING) {
                        map.put(head.get(j), c.getStringCellValue());
                    }else if (c.getCellType() == c.CELL_TYPE_FORMULA) {
                        map.put(head.get(j), df.formatCellValue(c, evaluator));
                    } 
                    else if (c.getCellType() == c.CELL_TYPE_BOOLEAN) {
                        map.put(head.get(j), df.formatCellValue(c, evaluator));
                    } 
                    else{
                        map.put(head.get(j), String.valueOf(c.getNumericCellValue()));
                    }
                }
            
            } catch (Exception e) {
                 e.printStackTrace();
            }
          }
          list.add(map);
         }
      return list;
}


public void multiRec() throws InvalidFormatException, IOException
{
    ArrayList<HashMap<String, String>> map = read.getCellData(fileLoc,"ComparisonStatus");
    for(HashMap<String, String> ls : map)
    {
        System.out.println(ls.get("Row"));
        System.out.println(ls.get("FileName"));
    }       
}

Here, Row and FileName are Excel file header. So now I reduced the no. of arguments. But how to convert it to 2D array will be the task now.

MoNa
  • 365
  • 4
  • 13
  • 31

1 Answers1

0

The best way would be to create a class containing all the arguments as fields of the class. Let the class name be CellData

class CellData {
    private String row;
    private String name;
    // and all other relevant fields..
}

In the getCellData method, create and initialize an object of CellData with the relevant values of each row and instead of returning String[][] return CellData[]. Then make the below changes:

@DataProvider (parallel= true)
public Object[][] getFilterValues() throws InvalidFormatException, IOException, InterruptedException{        
    CellData[] cellData = read.getCellData("fileLoc","fileName");
    Object[][] data = new Object[cellData.length][];
    for(int i = 0; i < cellData.length; i++) {
        data[i][0] = cellData[i];
    }
    return data;
}

@Test(dataProvider = "getFilterValues")
public void verifyReports(CellData data) throws Exception
{
    // test code.
}

Since you are saying that new arguments could be introduced in the future, using a class would be very much beneficial as it could help the code be maintainable and readable. Any future updates would also require much less code changes as there is no need of updating the DataProvider method or the test method. The only change would be a new field in the CellData class and setting the values for the new fields in getCellData method.

Gautham M
  • 4,816
  • 3
  • 15
  • 37