使用Apache POI更新基于csv工作表的Excel工作表值 [英] Updating Excel sheet values based on a csv sheet with Apache POI

查看:70
本文介绍了使用Apache POI更新基于csv工作表的Excel工作表值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我还是java的新手.我在使用Java语法时遇到了一些问题. 我的程序应执行以下步骤:

I am still new to java. I am having a bit problems with the java syntax. My Program should do the following procedure:

1)它需要一个csv文件作为输入.

1) It takes a csv file as an input.

2)它需要一个excel文件作为输入.

2) It takes an excel file as an input.

3)它应该遍历写入日期的两个文件的第一列.

3) It should iterate over the first columns of the two files where the dates are written.

4)通过添加csv表中的信息来更新excel文件并保存其更改.

4) Update the excel file by adding the information from the csv sheet and save its changes.

我有一个 https://onedrive. live.com/?cid=24b4fceb4f4e4098&id=24B4FCEB4F4E4098%213018&authkey=%21AKKzaZsJ5pkd5NE

这里有两个输入示例,以及excel工作表的外观如何.

where I have the two input examples and how the result excel sheet should look like.

两个输入文件:

export-csv-input.csv

export-csv-input.csv

export-excel-input.xlsx

export-excel-input.xlsx

更新后的excel文件应如下所示:

The updated excel file should look like:

export-excel-output.xlsx

export-excel-output.xlsx

还没有我的Java代码:

My Java Code yet:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class CsvToExcelConverter {

  public static final String SAMPLE_XLSX_FILE_PATH = 
 "C:/Users/blawand/Desktop/CSV_to_Excel/export-excel-test.xlsx";
  public static final String SAMPLE_CSV_FILE_PATH = 
"C:/Users/blawand/Desktop/CSV_to_Excel/export-csv-test.csv";
  public static List<String> dates_csv = new ArrayList<>();
  public static List<String> dates_excel = new ArrayList<>();

  public static void main(String[] args) throws IOException, 
InvalidFormatException {

    try (Reader reader = 
Files.newBufferedReader(Paths.get(SAMPLE_CSV_FILE_PATH));
        CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT);) 
{

      for (CSVRecord csvRecord : csvParser) {
        // Accessing Values by Column Index
         String name = csvRecord.get(0);
        dates_csv.add(name);
      }
      dates_csv.remove(0);
    }

    FileInputStream fsIP = new FileInputStream(new 
File(SAMPLE_XLSX_FILE_PATH));

    /*
     * ================================================================== 
Iterating over all the
     * rows and columns in a Sheet (Multiple ways)
     * ==================================================================
     */

    // Getting the Sheet at index zero
    XSSFWorkbook workbook = new XSSFWorkbook(fsIP);

    XSSFSheet sheet = workbook.getSheetAt(0);

    // Get the Cell at index 2 from the above row
    // Cell cell1 = sheet.getRow(1).getCell(0);
    // for (int i = 0; i < dates_excel.size(); i++) {
    // XSSFRow rowtest = sheet.createRow((short) i + 1);
    // rowtest.createCell(0).setCellValue(dates_csv.get(i));
    //
    // }

    // cell1.setCellValue(dates_csv.get(0));
    // Create a DataFormatter to format and get each cell's value as 
String
    DataFormatter dataFormatter = new DataFormatter();

    for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) 
{
      Row row = sheet.getRow(rowIndex);
      if (row != null) {
        Cell cell = row.getCell(0); // getColumn(0)
        if (cell != null) {
          // Found column and there is value in the cell.
          // String cellValueMaybeNull = cell.getStringCellValue();
          String cellValueMaybeNull = 
dataFormatter.formatCellValue(cell);

      // String to number set
      dates_excel.add(cellValueMaybeNull);

    }
  }
}

System.out.println(dates_csv);
System.out.println(dates_csv.size());
System.out.println(dates_excel);
System.out.println(dates_excel.size());

while (dates_excel == dates_excel) {

  System.out.println("Yes");
  break;
}
fsIP.close();
FileOutputStream output_file = new FileOutputStream(new 
File(SAMPLE_XLSX_FILE_PATH));
workbook.write(output_file);
output_file.close();

  }
}

我已经阅读了两个文件,但是在更新excel文件以及将项目名称添加到正确的日期时遇到了问题.并且如果同一日期已在csv工作表中写入两次或两次以上.

I read already the two files but i am having problems with updating the excel file and adding the project names to the correct dates. And if the same date has been written two or more times in the csv sheet.

您还想知道哪些信息?

感谢您的每一个帮助或建议!

I would be thankful for every help or advice!

推荐答案

我为您提供了一个示例,主要通过代码注释进行了说明.不过,该代码基本上会执行以下操作:

I have an example for you, mostly explained by code comments. Nevertheless, the code basically does the following:

在构造函数中获取xlsx和csv文件的文件路径.

Takes file paths of the xlsx and csv file in the constructor.

更新时,它首先将csv文件的内容读取为Map,其中LocalDate作为键,而List<String>作为值.
然后,它遍历工作簿的行,跳过标题行,并将第一列中的日期与Map<LocalDate, List<String>>的键进行比较.如果映射包含该键,它将开始检查该行中的单元格是否存在当前值,并将它们保留在列表中,以便以后不再写入.
然后,它将开始将这些值写入具有关键日期的行的单元格中.

When updating, it first reads the content of the csv file into a Map with a LocalDate as key and a List<String> as values.
Then it goes through the rows of the workbook skipping the header row and comparing the dates in column one with the keys of the Map<LocalDate, List<String>>. If the map contains that key, it starts checking the cells in that row for present values and keeps them in a list in order to not write them later.
Then it starts writing the values into the cells of the row with the key date.

我希望这会有所帮助.

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class CsvXlsxUpdater {

    private static final DateTimeFormatter DATE_TIME_FORMATTER_CSV = DateTimeFormatter.ofPattern("dd.MM.yyyy");

    private Path csvFilePath;
    private Path xlsxFilePath;
    private XSSFWorkbook workbook;
    private XSSFSheet sheet;
    private Map<LocalDate, List<String>> csvContent = new TreeMap<LocalDate, List<String>>();
    private ZoneId zoneId = ZoneId.systemDefault();

    public CsvXlsxUpdater(String pathToCsvFile, String pathToXlsxFile) {
        csvFilePath = Paths.get(pathToCsvFile);
        xlsxFilePath = Paths.get(pathToXlsxFile);
    }

    /**
     * Reads the content of the csv file into the corresponding class variable,
     * which is a {@link TreeMap} that has a {@link LocalDate} as key and a 
     * {@link List<String>} as values.
     */
    private void readCsvContent() {
        List<String> csvLines;

        try {
            csvLines = Files.readAllLines(csvFilePath);

            for (int i = 1; i < csvLines.size(); i++) {
                String line = csvLines.get(i);
                String[] splitValues = line.split(",");

                if (splitValues.length > 1) {
                    List<String> lineValues = Arrays.asList(splitValues);
                    List<String> projects = getProjectValuesFrom(lineValues);
                    LocalDate localDate = LocalDate.parse(lineValues.get(0), DATE_TIME_FORMATTER_CSV);
                    if (csvContent.containsKey(localDate)) {
                        projects.forEach((String project) -> {
                            List<String> csvProjects = csvContent.get(localDate);
                            if (!csvProjects.contains(project)) {
                                csvProjects.add(project);
                            }
                        });
                    } else {
                        csvContent.put(localDate, projects);
                    }
                } else {
                    LocalDate localDate = LocalDate.parse(splitValues[0], DATE_TIME_FORMATTER_CSV);
                    csvContent.put(localDate, new ArrayList<String>());
                }
            }
        } catch (IOException e) {
            System.err.println("CANNOT FIND OR READ CSV FILE: " + e.getMessage());
            e.printStackTrace();
        } catch (UnsupportedOperationException e) {
            System.err.println("UNSUPPORTED OPERATION: " + e.getMessage());
            e.printStackTrace();
        }

    }

    /**
     * Gets the corresponding {@link LocalDate} from a given (and deprecated)
     * {@link Date}
     * 
     * @param date the deprecated {@link Date} object
     * @return the corresponding {@link LocalDate}
     */
    private LocalDate parseLocalDateFrom(Date date) {
        Instant instantDate = date.toInstant();
        return instantDate.atZone(zoneId).toLocalDate();
    }

    /**
     * Takes a list of read values from the csv file and returns a list containing
     * all the values of the given list <strong>except from the first
     * element</strong>, which is a {@link String} representation of a date and
     * should be treated differently in this context.
     * 
     * @param values the original list of {@link String}s
     * @return another list without the first element of the given list
     */
    private List<String> getProjectValuesFrom(List<String> values) {
        List<String> projectValues = new ArrayList<String>();

        for (int i = 1; i < values.size(); i++) {
            String value = values.get(i);
            if (!value.equals("")) {
                projectValues.add(value);
            }
        }

        return projectValues;
    }

    /**
     * Updates the workbook with the values read from the csv file
     */
    public void updateWorkbook() {
        readCsvContent();
        try {
            FileInputStream fis = new FileInputStream(xlsxFilePath.toAbsolutePath().toString());
            workbook = new XSSFWorkbook(fis);
            sheet = workbook.getSheetAt(0);
            
            // iterate over the rows
            Iterator<Row> rowIterator = sheet.rowIterator();
            
            while (rowIterator.hasNext()) {
                XSSFRow row = (XSSFRow) rowIterator.next();
                
                if (row.getRowNum() == 0) {
                    // skip this or set updated headers
                } else {
                    // check if the csvContent contains the value of cell(0)
                    LocalDate dateKey = parseLocalDateFrom(row.getCell(0).getDateCellValue()); 
                    if (csvContent.containsKey(dateKey)) {
                        // if yes, get list-value of the key
                        List<String> values = csvContent.get(dateKey);
                        
                        // check if there are values
                        if (values != null) {
                            if (values.size() > 0) {
                                // if there are, then go checking the cell values
                                List<String> projectsInXlsx = new ArrayList<String>();
                                Iterator<Cell> cellIterator = row.cellIterator();
                                int lastColumnIndex = 1;
                                
                                // go through all cells with a value except from the first one
                                while (cellIterator.hasNext()) {
                                    Cell cell = cellIterator.next();
                                    
                                    // skip the first column as it contains the date
                                    if (cell.getColumnIndex() != 0) {
                                        lastColumnIndex = cell.getColumnIndex();
                                        System.out.println("Accessing cell in column " + lastColumnIndex);
                                        // if there is a cell with a value
                                        if (cell.getStringCellValue() != null) {
                                            if (!cell.getStringCellValue().equals("")) {
                                                // check if the value in the cell is also in the csv values
                                                if (values.contains(cell.getStringCellValue())) {
                                                    projectsInXlsx.add(cell.getStringCellValue());
                                                    lastColumnIndex++;
                                                }
                                            }
                                        }
                                    }
                                }
                                
                                // now go through the values of the csv file
                                int offset = 0; // cell column offset for more than one entry per date
                                for (String value : values) {
                                    if (!projectsInXlsx.contains(value)) {
                                        // create a cell after the last one with a value
                                        row.createCell(lastColumnIndex + offset).setCellValue(value);
                                        offset++;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            
            fis.close();
        
            FileOutputStream fileOutputStream = new FileOutputStream(xlsxFilePath.toAbsolutePath().toString());
            workbook.write(fileOutputStream);
            fileOutputStream.flush();
            fileOutputStream.close();
            workbook.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

main方法中,您只需要调用构造函数,将文件路径作为String传递,然后调用updateWorkbook()方法,因为它首先在内部读取csv.

In a main method, you would just have to call the constructor, pass the file paths as Strings and then call the updateWorkbook() method, because it internally reads the csv first.

示例:

public class CsvXlsxMain {

    private static final String CSV_FILE_PATH = "S:\\ome\\example\\path\\to\\csv-input.csv";
    private static final String XLSX_FILE_PATH = "S:\\ome\\example\\path\\to\\excel-input.xlsx";
    
    public static void main(String[] args) {
        CsvXlsxUpdater cxu = new CsvXlsxUpdater(CSV_FILE_PATH, XLSX_FILE_PATH);
        cxu.updateWorkbook();
    }
}

请记住,此代码尚未经过完整测试,以后可能会出现备用资源问题 如果需要,可以使用各种符合您要求的xlsx和csv输入进行测试.

Please keep in mind that this CODE IS NOT FULLY TESTED, there may be problems with alternating resources in future If you need, go testing it with various xlsx and csv inputs that fit your requirements.

我还没有使用任何库来解析csv文件!

I haven't used any library to parse the csv file!

我希望这对您有所帮助...

I hope this helps you a little…

这篇关于使用Apache POI更新基于csv工作表的Excel工作表值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆