简体   繁体   English

遍历对象数组,将数据写入Java中的excel文件

[英]Iterate through an array of objects and write the data into an excel file in Java

I want to have a class Employess from where I create objects with firstName , lastName and city .我想有一个 class Employess ,我从那里创建具有firstNamelastNamecity的对象。

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.我想遍历一个 Employees 数组,并为每个创建的 object 提取firstNamelastNamecity并将其写入 Excel 文件。

My code blocks in the second for block with the following error message:我的代码块在第二个 for 块中出现以下错误消息:

Exception in thread "main" java.lang.ClassCastException: class http.Employees cannot be cast to class [Ljava.lang.Object;线程“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). (http.Employees 在加载程序“app”的未命名模块中;[Ljava.lang.Object;在加载程序“bootstrap”的模块 java.base 中)位于 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.我是 Java 的新手,我认为我使用 HashMap 的方式是错误的,但我不知道如何以正确的方式处理它。

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();
    }
}

The problem in your code lies in the way you retrieve an Employees from the HashMap .您的代码中的问题在于您从HashMap检索Employees的方式。 In fact, your employeeData is defined as a HashMap with Integer keys and Object values (ie your Employees ).事实上,您的employeeData被定义为HashMap ,其中包含Integer键和Object值(即您的Employees )。 When you perform a map.get(key) , the method returns an Object , specifically an Employees , not an Object[] ;当您执行map.get(key)时,该方法返回一个Object ,特别是一个Employees ,而不是一个Object[] thus the ClassCastException .因此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.此外, HashMap是一个通用的 class。这意味着可以使用正确的类型 arguments 指定表示键和值的数据类型的类型参数 K 和 V。在您的情况下,使用Employees更合适您的值的数据类型。 In fact, Object is far too generic, it forces you to resort to casting and losing one of the many benefits of generics.事实上, Object太通用了,它迫使你求助于 cast 并失去 generics 的众多好处之一。

https://docs.oracle.com/javase/tutorial/java/generics/why.html 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.最后,您编写的代码似乎并不需要HashMap In fact, you could simplify it by using an array of Employees .事实上,您可以使用Employees数组来简化它。 Here I'll leave both implementations which rely on getter methods in your Employees class:在这里,我将在您的Employees class 中保留依赖于 getter 方法的两个实现:

HashMap Implementation HashMap 实施

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);
}

The value is not an array of objects, but objects of type 'Employees' so you cannot cast it to an array:该值不是对象数组,而是类型为“Employees”的对象,因此您不能将其转换为数组:

        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);
            }
        }

Here is a complete example you can use.这是您可以使用的完整示例。 Pass the full path to the output file as an argument to the program:将 output 文件的完整路径作为参数传递给程序:

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:这在 class Employee中使用了一个简单的方法,将 class 字段作为数组返回:

public String[] toFields() {
    return new String[] { firstName, lastName, city };
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM