Excel Columns into Java Using API - java

I had to create a program that calculates the GPA, using apache poi that reads the xlsx excel file. It coints 220 rows and 4 columns, such as
Course Number Course Name Credit Hours Course Multipler
110 Eng 1 CP 5.0 1.0
There are 220 other courses.
However, I was able to print those data using cell.getStringCellValue and cell.getNumericCellValue, but I can't get these printed data into each array.
I wanted to create an array called courseNumList and put courseNumList[0] the first course Number, and the second course number in courseNumList[1].. on and on..
I want to create 4 arrays, but what is a good way?
private static ArrayList<Object> c = new ArrayList <Object>();
public static void readXLSXFile() throws IOException {
InputStream ExcelFileToRead = new FileInputStream("C:/Users/14KimTa/Desktop/Downloads/Course_List.xlsx");
XSSFWorkbook wb = new XSSFWorkbook(ExcelFileToRead);
XSSFWorkbook test = new XSSFWorkbook();
XSSFSheet sheet = wb.getSheetAt(0);
XSSFRow row;
XSSFCell cell;
Iterator rows = sheet.rowIterator();
while (rows.hasNext())
{
row=(XSSFRow) rows.next();
Iterator cells = row.cellIterator();
while (cells.hasNext())
{
cell=(XSSFCell) cells.next();
if (cell.getCellType() == XSSFCell.CELL_TYPE_STRING)
{
System.out.print(cell.getStringCellValue()+" ");
c.add(getStringCellValue());
}
else if(cell.getCellType() == XSSFCell.CELL_TYPE_NUMERIC)
{
System.out.print(cell.getNumericCellValue()+" ");
}
}
System.out.println();
}
}
this is my code so far.
I tried to create each columns into arrays, but it is not working at all.
Thanks!

I would create a new class to define your data, Course, with one field for each of your columns (4 fields). Then I would create some kind of List (ArrayList<Course> looks good) to hold all Courses. An array of Courses would work too, since you know how many there are from the start. In a loop, I would create one Course object for each row, setting the fields based on the values from cell.getStringCellValue() and cell.getNumericCellValue(), adding the Course to the List (or array) after processing each row.

I don't think creating one array per each column is a good idea. Keeping track of data in the same row by following the same indexes in the 4 arrays may be cumbersome and bad practice.
I would rather create a Java class - Course - with 4 fields -courseNumber, courseName, creditHours and courseMultiplier. Then, I would create a collection of such objects, e.g. Collection<Course> courses = new ArrayList<Course>();, and populate it according to the data read from Excel - one object per row.
EDIT:
I'd suggest you create a custom type instead of using Object for your ArrayList type parameter. You're not gaining much by using Object.
Then, for each row, you'd do the following:
//...obtain your values from cells and populate `courseNumber`, `courseName`,`creditHours` and `courseMultiplier` accordingly
Course course = new Course();
course.setCourseNumber(courseNumber);
course.setCourseName(courseName);
course.setCreditHours(creditHours);
course.setCourseMultiplier(courseMultiplier);
c.add(course);
This snippet of code should be placed inside the loop you use for iterating through rows.

Related

Generic way to parse excel files

I have a requirement to parse the excel file and create the list of objects from that. TO do the same we are using the There are org.apache.poi to read the excel file and we are able to get the required details, currently we are getting the cell value based on the index and set it to the object field. But we believe it is not a good way to get the values based on the index and we should find a generic way to successfully parse the excel file in case some columns are added or removed so that we don't have to do much effort on code. I came across this article which almost fulfills the requirements but used the reflection methods which we are not allowed to use. Is there any possible way to parse the excel file without using the cell index where we don't have to put much effort if the format of the excel file gets changed?
public List<DTO> jsonConverter(Workbook workbook, Sheet sheet, String filename)
throws ParseException {
List<DTO> listOfDTOs = new ArrayList<>();
Row row;
for (int index = 1; index <= sheet.getLastRowNum(); index++) {
row = sheet.getRow(index);
if (row != null) {
DTO dto = new DTO();
dto.setFieldX(
getCellValueAsStringBasedOnCellType(
workbook, row.getCell(0, MissingCellPolicy.CREATE_NULL_AS_BLANK)));
dto.setFieldY(
getCellValueAsStringBasedOnCellType(
workbook, row.getCell(1, MissingCellPolicy.CREATE_NULL_AS_BLANK)));
listOfDTOs.add(dto);
}
}
return listOfDTOs;
}
public String getCellValueAsStringBasedOnCellType(Workbook workbook, Cell cell) {
DataFormatter formatter = new DataFormatter();
if (cell != null && cell.getCellType() == CellType.FORMULA) {
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
return formatter.formatCellValue(cell, evaluator);
}
return formatter.formatCellValue(cell);
}
Sure. It's fairly simple:
The setup
Read the first row in the excel file, treat it as columns, and read every cell as a string.
Store these in an array.
Now you can turn any index into the column name, simply using the expression headers[idx].
Thus, for any given cell, you know the header name. Now you need to translate this knowledge into the right call. Given that you're in column, say, E (i == 4), the header value is header[4] which is, say, Address, then you want to take the string ("Address") and turn that into the right call. You end up needing to invoke:
String cellValue = getCellValueAsStringBasedOnCellType(workbook, row.getCell(1, MissingCellPolicy.CREATE_NULL_AS_BLANK)));
dto.setFieldAddress(cellValue);
Everything in that code snippet is the same for any value of that string, except the setFieldAddress name.
So, we need to turn the string "Address" into the act of invoking setFieldAddress.
The solution
java.util.function and hashmaps to the rescue!
This is a way to store in a variable the concept of taking a dto instance and setting the Address field:
BiConsumer<DTO, String> setAddress = (dto, value) -> dto.setFieldAddress(value);
or even simpler:
BiConsumer<DTO, String> setAddress = DTO::setFieldAddress;
These snippets do the same thing: They don't set an address; they are a recipe for how that is done, and you store the concept of setting an address on a DTO in a variable so you can run it later and as many times as you want. This is generally called a 'closure' a 'lambda'.
We can store these things in a map:
Map<String, BiConsumer<DTO, String>> dtoSetters = new HashMap<>();
dtoSetters.put("Address", DTO::setFieldAddress);
And then we can just figure it out:
int colIdx = ...;
String headerName = header[colIdx];
var setter = dtoSetters.get(headerName);
if (setter == null) throw new IllegalStateException("Unexpected column header in excel sheet: " + headerName);
String cellValue = getCellValueAsStringBasedOnCellType(workbook, row.getCell(1, MissingCellPolicy.CREATE_NULL_AS_BLANK)));
setter.apply(dto, cellValue);
Thus, make that map (once, at system boot, e.g. with static initializers), replace your dto.setFieldX code with the above, and voila.

how to add a new row for jTable in java

i was setting the number of rows of my Table in java using properties of the table but how can i add new row inside the code because i don't know the number of inputs that should be entered?
but how can i add new row inside the code
This will depend on the implementation of the TableModel, for example, the DefaultTableModel provides two addRow methods.
The TableModel itself doesn't provide this functionality directly and is dependent on the physical implementation to provide this functionality if and when required.
See How to Use Tables for more details
first, i set the number of rows equal "0" in the properties of the table
second, write this code in the for loop with your condition
ArrayList arr = new ArrayList();
for (int i = 0; i < shipmain.files.length; i++) {
arr.add(shipmain.files[i]);
arr.add(shipmain.fabricName[i]);
arr.add(shipmain.color[i]);
DefaultTableModel model = (DefaultTableModel)jTable1.getModel();
model.addRow(arr.toArray());
jTable1.setModel(model);
arr.remove(shipmain.files[i]);
arr.remove(shipmain.fabricName[i]);
arr.remove(shipmain.color[i]);
}
AddRow() function must take an object and ArrayList provided that

Group by functionality in Java

I am trying to write a Java program that loads the data (from a tab delimited DAT file) and determines the average amount in Euros (EUR), grouped by Country and Credit Rating.
I have 2 questions,
what is the best way to load the data into data structure after spliting into array?
How do i approach about providing group by functionality in Java
Update: I have given a first try and this is how implementation looks like. Feels like there is a room for improvement.
/**
* #param rows - Each row as a bean
* This method will group objects together based on Country/City and Credit Rating
*/
static void groupObjectsTogether(List<CompanyData> rows) {
Map<String, List<CompanyData>> map = new HashMap<String, List<CompanyData>>();
for(CompanyData companyData : rows){
String key;
if(companyData.getCountry().trim().equalsIgnoreCase("") || companyData.getCountry() == null){
key = companyData.getCity()+":"+companyData.getCreditRating(); //use city+creditRating as key
}else{
key = companyData.getCountry()+":"+companyData.getCreditRating(); //use country+creditRating as key
}
if(map.get(key) == null){
map.put(key, new ArrayList<CompanyData>());
}
map.get(key).add(companyData);
}
processGroupedRowsAndPrint(map);
}
It all depends on the amount of data and performance (CPU vs memory) of the machine. It the amount of data is not significant (less than millions of records or columns) and the number of columns is fixed then you may simply put all data in arrays using
String[] row = String.split(";");
which shall split each row using ; as delimiter. Then you may achieve your grouping functionality using HashMap, i.e.:
ArrayList<String[]> rowAr = new ArrayList<String[]>();
HashMap<String,ArrayList<Integer>> map = new HashMap<String,ArrayList<Integer>>();
int index = 0;
for (String rowStr: rows) {
String[] row = rowStr.split(";");
rowAr.add(row);
String companyCode = row[0];
//please keep in mind that for simplicity of the example I avoided
//creation of new array if it does not exist in HashMap
((ArrayList<Integer>)map.get(companyCode)).add(index);
index++;
}
Sorry for any syntax or other simple errors above (I do not have any tools in hand to verify if there is not any stupid mistake).

how to export dynamic column data to excel

I have to export data to excel having dynamic number of columns
using java apache workbook,
on every execution, column details will be saved in ListObject,
which will be dynamically generated and get saved in
List<Object> expColName = new ArrayList<Object>();
From the List , I have to obtain individual values and export into every column of the excel sheet,
for(int i=0; i<expColName.size(); i++){
data.put("1",new Object[] {
expColName.get(i)
});
}
The above code gives only the last column value in the excel sheet
What type is data and how do you read the values from the map?
It seems like you are putting every object into the same "key" of the Map, thats why you only get the last item from the list.
You could try to give it a test with:
for(int i=0; i<expColName.size(); i++){
data.put(i+"",new Object[] {
expColName.get(i)
});
}

How we get the List objects in backward direction?

Hi i am getting List object that contains pojo class objects of the table. in my case i have to show the table data in reverse order. mean that, for ex
i am adding some rows to particular table in database when i am added recently, the data is storing at last row in table(in database). here i have to show whole content of the table in my jsp page in reverse order, mean that what i inserted recently have to display first row in my jsp page.
here my code was like,
List lst = tabledate.getAllData();//return List<Table> Object
Iterator it = lst.iterator();
MyTable mt = new MyTable();//pojo class
while(it.hasNext())
{
mt=(MyTable)it.next();
//getting data from getters.
System.out.println(mt.getxxx());
System.out.println(mt.getxxx());
System.out.println(mt.getxxx());
System.out.println(mt.getxxx());
}
Use a ListIterator to iterate through the list using hasPrevious() and previous():
ListIterator it = lst.listIterator(lst.size());
while(it.hasPrevious()) {
System.out.println(it.previous());
}
You cannot use an iterator in this case. You will need to use index based access:
int size = lst.size();
for (int i=size - 1; i >= 0; i --)
{
MyTable mt = (MyTable)lst.get(i);
....
}
Btw: there is no need to create a new MyTable() before the loop. This is an instance that will be thrown away immediately and serves no purpose.

Categories