У меня огромный файл Excel, который я пытаюсь проанализировать с помощью SAX-парсера в JAVA. В основном я использую библиотеку Apache POI и работаю с файлами .XLSX. Вот как выглядит содержимое xml внутри zip-папки excel в /xl/worksheets/sheet1.xml
, которую я пытаюсь прочитать:
<row r="1">
<c r="A1" t="inlineStr"><is><t>my value 1</t></is></c>
<c r="B1" t="inlineStr"><is><t>my value 2</t></is></c>
<c r="C1" t="inlineStr"><is><t>my value 3</t></is></c>
</row>
Этот один конкретный файл Excel использует строковые строковые значения, как показано выше.
Это моя функция, которая выполняет программу для чтения файла:
public void executeExcelDataExtraction() throws IOException, OpenXML4JException, SAXException, ParserConfigurationException, XMLStreamException, FactoryConfigurationError {
OPCPackage pkg = OPCPackage.open(XLSX_INPUT_FILE.xlsx);
XSSFReader r = new XSSFReader( pkg );
SharedStringsTable sst = r.getSharedStringsTable();
ImportArticleDataProcessorExcelFileReaderFactory handlerFactory = new
ImportArticleDataProcessorExcelFileReaderFactory(sst);
XMLReader parser = fetchSheetParser(handlerFactory);
Iterator<InputStream> sheets = r.getSheetsData();
if (sheets instanceof XSSFReader.SheetIterator) {
XSSFReader.SheetIterator sheetiterator =
(XSSFReader.SheetIterator)sheets;
while(sheetiterator.hasNext()) {
System.out.println("Processing new sheet:\n");
InputStream sheet = sheets.next();
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
rowCache = handlerFactory.getRowCache();
sheet.close();
pkg.close();
if(!rowCache.isEmpty())
createCategoryMap(rowCache);
}
}
}
и это мой фабричный класс обработчика листов, который используется в вышеуказанной функции.
import java.util.LinkedList;
import java.util.List;
import org.xml.sax.Attributes;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class ImportArticleDataProcessorExcelFileReaderFactory extends DefaultHandler{
private static final String ROW_EVENT = "row";
private static final String CELL_EVENT = "c";
private SharedStringsTable sst;
private String lastContents;
private boolean nextIsString;
private List<String> cellCache = new LinkedList<>();
private List<String[]> rowCache = new LinkedList<>();
ImportArticleDataProcessorExcelFileReaderFactory(SharedStringsTable sst) {
this.sst = sst;
}
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
// c => cell
if (CELL_EVENT.equals(name)) {
String cellType = attributes.getValue("t");
if(cellType != null && cellType.equals("s")) {
nextIsString = true;
} else {
nextIsString = false;
}
} else if (ROW_EVENT.equals(name)) {
if (!cellCache.isEmpty()) {
rowCache.add(cellCache.toArray(new String[cellCache.size()]));
}
cellCache.clear();
}
lastContents = "";
}
public void endElement(String uri, String localName, String name)
throws SAXException {
// Process the last contents as required.
// Do now, as characters() may be called more than once
if(nextIsString) {
int idx = Integer.parseInt(lastContents);
lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
nextIsString = false;
}
// v => contents of a cell
// Output after we've seen the string contents
if(name.equals("v")) {
cellCache.add(lastContents.trim());
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
lastContents += new String(ch, start, length);
}
public List<String[]> getRowCache() {
return rowCache;
}
}
Все остальные файлы Excel, которые не имеют встроенной строки, могут успешно читать, однако, если файлы имеют встроенную строку внутри, алгоритм читает только cellType=inlineStr
, но никогда не получает правильное значение.
Что я хочу:
Все, что мне нужно, это просто напечатать значения, расположенные внутри строковой ячейки, например, в моем случае это «мое значение 1», «мое значение 2» и «мое значение 3»