#java #apache-poi
Вопрос:
Я изо всех сил пытался выяснить, как прочитать тип данных для каждого из столбцов заголовка. Я использую Apache POI 4.1.2 для чтения формата файла XLSX с использованием реализации XSSFWorkbook.
Бизнес-вариант использования: У меня есть excel с 22 ячейками( включает строковое, числовое, поле даты), если пользователь попытается изменить поле даты на строковое или Числовое на строковое или наоборот. Мне нужно выбросить ошибку, даже не читая строки данных. Таким образом, я могу обрабатывать строки данных в случае, если пользователь изменяет тип ( значение даты в varchar, числовое в строку).
Фрагмент кода Sudo:
XSSFRow headerRow = sheet.getRow(rownum:0);
for(int cellNum=0; cellNum<22;cellNum ){
Cell cell = headerRow.getCell(cellNum);
System.out.println(cell.getCellType());
// This always returns the string even though the header row has date and numeric fields)
}
Ни один поиск или рекомендация не помогли мне с какими-либо зацепками или решением, поэтому я ищу рабочее решение.
Ответ №1:
Невозможно определить типы столбцов на основе заголовков. Заголовки обычно представляют собой текст (строку), который мы вводим в первую строку файла. Они не содержат какого-либо определенного типа данных.
С другой стороны, если вам нужно понимать типы столбцов, вам нужно читать со 2-й строки файла (оставляя заголовки).
Вот некоторая реализация, которая довольно хорошо справляется с анализом типов столбцов. Вы можете указать, сколько строк следует рассмотреть для анализа и какой лист следует проанализировать
Код:
import java.io.File;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class Test {
public static void main(String[] args) {
String excelFileName = "C:\Users\test\Downloads\test.xlsx";
int sheet_num = 0;
int maxRows_ToAnalyze = 5;
Map<Integer, String> result = analyzeColumnTypes(excelFileName, sheet_num, maxRows_ToAnalyze);
for(int i : result.keySet()) {
System.out.println("Column " i " is of type ==> " result.get(i));
}
}
static String NUMERIC = "NUMERIC";
static String DATE = "DATE";
static String STRING = "STRING";
static String FORMULA = "FORMULA";
static String BLANK = "BLANK";
static String BOOLEAN = "BOOLEAN";
static String ERROR = "ERROR";
static String NOT_CONSISTENT = "NOT_CONSISTENT";
public static Map<Integer, String> analyzeColumnTypes(String excelFileName, int sheet_num, int maxRows_ToAnalyze){
Workbook workbook = null;
Map<Integer, String> columnTypeMap = new HashMap<Integer, String>();
Map<Integer, Set<String>> tempMap = new HashMap<>();
Pattern p = Pattern.compile("[^0-9\.]", Pattern.CASE_INSENSITIVE);
try {
FileInputStream excelFile = new FileInputStream(new File(excelFileName));
workbook = new XSSFWorkbook(excelFile);
Sheet sheet = workbook.getSheetAt(sheet_num);
int rows_in_sheet = sheet.getPhysicalNumberOfRows();
//if sheet rows are less than number of rows to analyze then analyze all the rows
if(rows_in_sheet<maxRows_ToAnalyze) {
maxRows_ToAnalyze = rows_in_sheet;
}
//i=1 because we dont want to read header rows
//header rows are typically strings
for(int i=1; i<=maxRows_ToAnalyze; i ) {
Row row = sheet.getRow(i);
int column_count = row.getPhysicalNumberOfCells();
for(int j=0; j<column_count; j ) {
tempMap.putIfAbsent(j, new HashSet<>());
Cell cell = row.getCell(j);
if(cell.getCellType().equals(CellType.NUMERIC)) {
Matcher m = p.matcher(cell.toString());
boolean match = m.find();
if(match) {
tempMap.get(j).add(DATE);
} else {
tempMap.get(j).add(NUMERIC);
}
} else if(cell.getCellType().equals(CellType.STRING)) {
tempMap.get(j).add(STRING);
} else if(cell.getCellType().equals(CellType.FORMULA)) {
tempMap.get(j).add(FORMULA);
} else if(cell.getCellType().equals(CellType.BLANK)) {
tempMap.get(j).add(BLANK);
} else if(cell.getCellType().equals(CellType.BOOLEAN)) {
tempMap.get(j).add(BOOLEAN);
} else if(cell.getCellType().equals(CellType.ERROR)) {
tempMap.get(j).add(ERROR);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
for(int colnum: tempMap.keySet()) {
if(tempMap.get(colnum).size()>1) {
columnTypeMap.put(colnum, NOT_CONSISTENT);
} else {
for(String coltype: tempMap.get(colnum)) {
columnTypeMap.put(colnum, coltype);
}
}
}
return columnTypeMap;
}
}
Комментарии:
1. возможно, вам сначала нужно проверить, не является ли ячейка нулевой: if (ячейка == null) { tempMap.get(j).add(ПУСТОЙ); } //или ОШИБКА