I want to have a class Employess
from where I create objects with firstName
, lastName
and city
.
I want to iterate through an Employees array, and for each object created to extract the firstName
, lastName
and city
and write it into an Excel file.
My code blocks in the second for block with the following error message:
Exception in thread "main" java.lang.ClassCastException: class http.Employees cannot be cast to class [Ljava.lang.Object; (http.Employees is in unnamed module of loader 'app'; [Ljava.lang.Object; is in module java.base of loader 'bootstrap') at http.App.main(App.java:64).
I am new to Java and I think that the way I use that HashMap is wrong, but I couldn't figure out how to handle it in the correct way.
Any help would be much appreciated. Thank you.
Code below:
class Employees {
String firstName;
String lastName;
String city;
public Employees(String firstName, String lastName, String city) {
this.firstName = firstName;
this.lastName = lastName;
this.city = city;
}
}
public class App {
public static void main(String[] args) throws Exception {
String excelPath = "C:/Work/01_TSM/java/test.xlsx";
FileInputStream inputStream = new FileInputStream(new File(excelPath));
// create workbook object
XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
// create spreadsheet object
XSSFSheet spreadsheet = workbook.getSheetAt(1);
// create row object
XSSFRow row;
// This data needs to be written in (Object[])
HashMap<Integer, Object> employeeData = new HashMap<Integer, Object>();
Employees employee1 = new Employees("John", "Smith", "CT");
Employees employee2 = new Employees("Jane", "Doe", "O");
Employees[] employees = { employee1, employee2 };
// Insert data
for (int i = 0; i < employees.length; i ) {
employeeData.put(i, employees[i]);
}
;
Set<Integer> keyid = employeeData.keySet();
int rowid = 1;
// writing the data into the sheets
for (Integer key : keyid) {
row = spreadsheet.createRow(rowid );
// here the code breaks
Object[] objectArr = (Object[]) employeeData.get(key);
int cellid = 0;
for (Object obj : objectArr) {
Cell cell = row.createCell(cellid );
cell.setCellValue((String) obj);
}
}
// writing the workbook into the file
FileOutputStream out = new FileOutputStream(new File("C:/Work/01_TSM/java/test.xlsx"));
workbook.write(out);
out.close();
}
}
CodePudding user response:
Here is a complete example you can use. Pass the full path to the output file as an argument to the program:
package xlsconv;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFCell;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.io.IOException;
import java.io.OutputStream;
import java.io.BufferedOutputStream;
public class Beans2Sheet {
public static void main(String[] args) {
try {
Beans2Sheet b2s = new Beans2Sheet();
Employee[] emps = new Employee[] {
new Employee("John", "Doe", "Kansas City"),
new Employee("John", "Doe", "New York City")
};
b2s.beans2Sheet(emps, Paths.get(args[0]));
} catch (Exception e) {
e.printStackTrace();
}
}
public void beans2Sheet(Employee[] employees, Path outputPath) throws IOException {
XSSFWorkbook workBook = new XSSFWorkbook();
XSSFSheet sheet = workBook.createSheet();
for (int rowNum = 0; rowNum < employees.length; rowNum ) {
XSSFRow row = sheet.createRow(rowNum);
String[] fields = employees[rowNum].toFields();
for (int i = 0; i < fields.length; i ) {
XSSFCell cell = row.createCell(i);
cell.setCellValue(fields[i]);
}
}
try (OutputStream out = new BufferedOutputStream(Files.newOutputStream(outputPath))) {
workBook.write(out);
}
}
}
This uses a little convenience method in class Employee
that returns the class fields as an array:
public String[] toFields() {
return new String[] { firstName, lastName, city };
}
CodePudding user response:
The problem in your code lies in the way you retrieve an Employees
from the HashMap
. In fact, your employeeData
is defined as a HashMap
with Integer
keys and Object
values (i.e. your Employees
). When you perform a map.get(key)
, the method returns an Object
, specifically an Employees
, not an Object[]
; thus the ClassCastException
.
Besides, HashMap
is a generic class. This means that the type parameters K and V, representing the data types of your keys and values, can be specified with proper type arguments. In your case, it will be a better fit to use Employees
as the data type for your values. In fact, Object
is far too generic, it forces you to resort to casting and losing one of the many benefits of generics.
https://docs.oracle.com/javase/tutorial/java/generics/why.html
Lastly, It doesn't seem like a HashMap
is actually needed for the code you've written. In fact, you could simplify by using an array of Employees
. Here I'll leave both implementations which rely on getter methods in your Employees
class:
HashMap Implementation
String pathFileExcel = "C:/Work/01_TSM/java/test.xlsx";
//Creating a workbook
XSSFWorkbook workbook = new XSSFWorkbook();
//Making sure a spreadSheet exsists before retrieving it
if (workbook.getNumberOfSheets() == 0) {
workbook.createSheet();
}
XSSFSheet spreadsheet = workbook.getSheetAt(0);
//Creating a map
Map<Integer, Employees> employeeMap = new HashMap<>(Map.of(
0, new Employees("John", "Smith", "CT"),
1, new Employees("Jane", "Doe", "O")
));
int rowNum = 0;
//writing the data into the sheets
for (Integer key : employeeMap.keySet()) {
XSSFRow row = spreadsheet.createRow(rowNum );
Employees emp = employeeMap.get(key);
Cell cellFirstName = row.createCell(0);
cellFirstName.setCellValue((emp.getFirstName()));
Cell cellLastName = row.createCell(1);
cellLastName.setCellValue((emp.getLastName()));
Cell cellCity = row.createCell(2);
cellCity.setCellValue((emp.getCity()));
}
//the try-with automatically closes the connection once exited the try block
try (FileOutputStream out = new FileOutputStream(pathFileExcel);) {
workbook.write(out);
}
Array of Employees Implementation
String pathFileExcel = "C:/Work/01_TSM/java/test.xlsx";
//Creating a workbook
XSSFWorkbook workbook = new XSSFWorkbook();
//Making sure a spreadSheet exsists before retrieving it
if (workbook.getNumberOfSheets() == 0) {
workbook.createSheet();
}
XSSFSheet spreadsheet = workbook.getSheetAt(0);
//Creating an array
Employees[] vetEmp = new Employees[]{
new Employees("John", "Smith", "CT"),
new Employees("Jane", "Doe", "O")
};
int rowNum = 0;
//writing the data into the sheets
for (Employees emp : vetEmp) {
XSSFRow row = spreadsheet.createRow(rowNum );
Cell cellFirstName = row.createCell(0);
cellFirstName.setCellValue((emp.getFirstName()));
Cell cellLastName = row.createCell(1);
cellLastName.setCellValue((emp.getLastName()));
Cell cellCity = row.createCell(2);
cellCity.setCellValue((emp.getCity()));
}
//the try-with automatically closes the connection once exited the try block
try (FileOutputStream out = new FileOutputStream(pathFileExcel);) {
workbook.write(out);
}
CodePudding user response:
The value is not an array of objects, but objects of type 'Employees' so you cannot cast it to an array:
Object[] objectArr = (Object[]) employeeData.get(key);
int cellid = 0;
for (Object obj : objectArr) {
Cell cell = row.createCell(cellid );
cell.setCellValue((String) obj);
}
EDIT: i think this may be what you are trying to achieve:
HashMap<Integer, Object> employeeData = new HashMap<Integer, Object>();
Employees employee1 = new Employees("John", "Smith", "CT");
Employees employee2 = new Employees("Jane", "Doe", "O");
Employees[] employees = { employee1, employee2 };
for (int i = 0; i < employees.length; i ) {
employeeData.put(i, employees[i]);
}
Set<Integer> keyid = employeeData.keySet();
int rowid = 1;
for (Integer key : keyid) {
row = spreadsheet.createRow(rowid );
// here the code breaks
Employees employee = (Employees)employeeData.get(key);
for (int cellid = 0; cellid < 3; cellid )
{
Cell cell = row.createCell(cellid ):
if (cellid == 0)
{
cell.setCellValue(employee.firstName);
}
else if(cellid == 1)
{
cell.setCellValue(employee.lastName);
}
else if(cellid == 2)
{
cell.setCellValue(employee.city);
}
}