From ab2343aec708f130f4ec90f57e093a25f2a6213f Mon Sep 17 00:00:00 2001 From: Selim Soufargi Date: Thu, 30 Jul 2026 19:55:42 +0200 Subject: [PATCH 1/8] feature: csv column filtering support --- .../analysis/csv/CsvExcelReadExecutor.java | 9 ++++-- .../apache/fesod/sheet/FesodSheetTest.java | 29 +++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/csv/CsvExcelReadExecutor.java b/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/csv/CsvExcelReadExecutor.java index b2741a3ff..3ae1b58d8 100644 --- a/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/csv/CsvExcelReadExecutor.java +++ b/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/csv/CsvExcelReadExecutor.java @@ -223,11 +223,16 @@ private void dealRecord(CSVRecord record, int rowIndex) { csvReadContext.csvReadWorkbookHolder().globalConfiguration().getAutoTrim(); Boolean autoStrip = csvReadContext.csvReadWorkbookHolder().globalConfiguration().getAutoStrip(); + List includeColumnIndexes = csvReadContext.readSheetHolder().getColumnIndexes(); while (cellIterator.hasNext()) { String cellString = cellIterator.next(); + int currentColumnIndex = columnIndex++; + if (includeColumnIndexes != null && !includeColumnIndexes.contains(currentColumnIndex)) { + continue; + } ReadCellData readCellData = new ReadCellData<>(); readCellData.setRowIndex(rowIndex); - readCellData.setColumnIndex(columnIndex); + readCellData.setColumnIndex(currentColumnIndex); // csv is an empty string of whether ,, is read or ,"", if (StringUtils.isNotBlank(cellString)) { @@ -242,7 +247,7 @@ private void dealRecord(CSVRecord record, int rowIndex) { } else { readCellData.setType(CellDataTypeEnum.EMPTY); } - cellMap.put(columnIndex++, readCellData); + cellMap.put(currentColumnIndex, readCellData); } RowTypeEnum rowType = MapUtils.isEmpty(cellMap) ? RowTypeEnum.EMPTY : RowTypeEnum.DATA; diff --git a/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java b/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java index 44a8bee94..a3f614d3b 100644 --- a/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java +++ b/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java @@ -23,7 +23,12 @@ import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import org.apache.commons.io.FileUtils; import org.apache.fesod.sheet.read.builder.ExcelReaderBuilder; import org.apache.fesod.sheet.read.builder.ExcelReaderSheetBuilder; import org.apache.fesod.sheet.read.listener.ReadListener; @@ -247,4 +252,28 @@ void testReadSheet_withAllParams_shouldReturnBuilder() { ExcelReaderSheetBuilder builder = FesodSheet.readSheet(0, "DataSheet", 100); Assertions.assertNotNull(builder); } + + @Test + void testReadCsv_withColumnIndexes_shouldFilterColumns() throws Exception { + + String csvContent = "1,Alice,30,Female\n2,Bob,25,Male"; + File csvFile = tempDir.resolve("test_columns.csv").toFile(); + FileUtils.writeStringToFile(csvFile, csvContent, StandardCharsets.UTF_8); + + List targetColumns = Arrays.asList(0, 2); + + List> readResults = FesodSheet.read(csvFile) + .includeColumnIndexes(targetColumns) + .sheet(0) + .doReadSync(); + + Assertions.assertNotNull(readResults); + Assertions.assertEquals(2, readResults.size()); + + Map row1 = readResults.get(0); + Assertions.assertEquals(2, row1.size(), "Should only contain the 2 filtered columns"); + Assertions.assertEquals("1", row1.get(0)); + Assertions.assertEquals("30", row1.get(2)); + Assertions.assertNull(row1.get(1), "Column index 1 (Name) should be omitted"); + } } From 069413c927baa0d6ce532f45ef5c1d605a3150d3 Mon Sep 17 00:00:00 2001 From: Selim Soufargi Date: Mon, 3 Aug 2026 18:38:46 +0200 Subject: [PATCH 2/8] addressing first wave of reviews --- .../apache/fesod/sheet/analysis/csv/CsvExcelReadExecutor.java | 2 +- .../src/test/java/org/apache/fesod/sheet/FesodSheetTest.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/csv/CsvExcelReadExecutor.java b/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/csv/CsvExcelReadExecutor.java index 3ae1b58d8..1c9404d49 100644 --- a/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/csv/CsvExcelReadExecutor.java +++ b/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/csv/CsvExcelReadExecutor.java @@ -223,7 +223,7 @@ private void dealRecord(CSVRecord record, int rowIndex) { csvReadContext.csvReadWorkbookHolder().globalConfiguration().getAutoTrim(); Boolean autoStrip = csvReadContext.csvReadWorkbookHolder().globalConfiguration().getAutoStrip(); - List includeColumnIndexes = csvReadContext.readSheetHolder().getColumnIndexes(); + List includeColumnIndexes = csvReadContext.readSheetHolder().getReadSheet().getColumnIndexes(); while (cellIterator.hasNext()) { String cellString = cellIterator.next(); int currentColumnIndex = columnIndex++; diff --git a/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java b/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java index a3f614d3b..c426f1fe6 100644 --- a/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java +++ b/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java @@ -263,6 +263,7 @@ void testReadCsv_withColumnIndexes_shouldFilterColumns() throws Exception { List targetColumns = Arrays.asList(0, 2); List> readResults = FesodSheet.read(csvFile) + .csv() .includeColumnIndexes(targetColumns) .sheet(0) .doReadSync(); From 9861270d70e2486663be65ca99679d8dad047a60 Mon Sep 17 00:00:00 2001 From: Selim Soufargi Date: Mon, 3 Aug 2026 18:47:00 +0200 Subject: [PATCH 3/8] addressing first wave of reviews 2 --- .../analysis/csv/CsvExcelReadExecutor.java | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/csv/CsvExcelReadExecutor.java b/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/csv/CsvExcelReadExecutor.java index 1c9404d49..0f0187f87 100644 --- a/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/csv/CsvExcelReadExecutor.java +++ b/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/csv/CsvExcelReadExecutor.java @@ -224,17 +224,26 @@ private void dealRecord(CSVRecord record, int rowIndex) { Boolean autoStrip = csvReadContext.csvReadWorkbookHolder().globalConfiguration().getAutoStrip(); List includeColumnIndexes = csvReadContext.readSheetHolder().getReadSheet().getColumnIndexes(); + while (cellIterator.hasNext()) { String cellString = cellIterator.next(); int currentColumnIndex = columnIndex++; - if (includeColumnIndexes != null && !includeColumnIndexes.contains(currentColumnIndex)) { - continue; + int targetColumnIndex; + + if (includeColumnIndexes == null) { + targetColumnIndex = currentColumnIndex; + } else { + targetColumnIndex = includeColumnIndexes.indexOf(currentColumnIndex); + if (targetColumnIndex < 0) { + continue; + } } + ReadCellData readCellData = new ReadCellData<>(); readCellData.setRowIndex(rowIndex); - readCellData.setColumnIndex(currentColumnIndex); - // csv is an empty string of whether ,, is read or ,"", + readCellData.setColumnIndex(targetColumnIndex); + if (StringUtils.isNotBlank(cellString)) { readCellData.setType(CellDataTypeEnum.STRING); if (autoStrip) { @@ -247,7 +256,8 @@ private void dealRecord(CSVRecord record, int rowIndex) { } else { readCellData.setType(CellDataTypeEnum.EMPTY); } - cellMap.put(currentColumnIndex, readCellData); + + cellMap.put(targetColumnIndex, readCellData); } RowTypeEnum rowType = MapUtils.isEmpty(cellMap) ? RowTypeEnum.EMPTY : RowTypeEnum.DATA; From d71205b850a2d1d50bd82cbdd55cb7a84f390395 Mon Sep 17 00:00:00 2001 From: Selim Soufargi Date: Tue, 4 Aug 2026 11:13:07 +0200 Subject: [PATCH 4/8] addressing second wave of reviews --- .../fesod/sheet/analysis/csv/CsvExcelReadExecutor.java | 5 +++-- .../src/test/java/org/apache/fesod/sheet/FesodSheetTest.java | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/csv/CsvExcelReadExecutor.java b/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/csv/CsvExcelReadExecutor.java index 0f0187f87..833aba53b 100644 --- a/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/csv/CsvExcelReadExecutor.java +++ b/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/csv/CsvExcelReadExecutor.java @@ -223,7 +223,8 @@ private void dealRecord(CSVRecord record, int rowIndex) { csvReadContext.csvReadWorkbookHolder().globalConfiguration().getAutoTrim(); Boolean autoStrip = csvReadContext.csvReadWorkbookHolder().globalConfiguration().getAutoStrip(); - List includeColumnIndexes = csvReadContext.readSheetHolder().getReadSheet().getColumnIndexes(); + List includeColumnIndexes = + csvReadContext.readSheetHolder().getReadSheet().getColumnIndexes(); while (cellIterator.hasNext()) { String cellString = cellIterator.next(); @@ -243,7 +244,7 @@ private void dealRecord(CSVRecord record, int rowIndex) { readCellData.setRowIndex(rowIndex); readCellData.setColumnIndex(targetColumnIndex); - + if (StringUtils.isNotBlank(cellString)) { readCellData.setType(CellDataTypeEnum.STRING); if (autoStrip) { diff --git a/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java b/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java index c426f1fe6..c7271f274 100644 --- a/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java +++ b/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java @@ -263,8 +263,8 @@ void testReadCsv_withColumnIndexes_shouldFilterColumns() throws Exception { List targetColumns = Arrays.asList(0, 2); List> readResults = FesodSheet.read(csvFile) - .csv() .includeColumnIndexes(targetColumns) + .csv() .sheet(0) .doReadSync(); From bd15fe6613b1dbd2e5274287fb17e056145d863c Mon Sep 17 00:00:00 2001 From: Selim Soufargi Date: Tue, 4 Aug 2026 14:02:21 +0200 Subject: [PATCH 5/8] fix test method call --- .../src/test/java/org/apache/fesod/sheet/FesodSheetTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java b/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java index e3cee36c2..0ada9827d 100644 --- a/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java +++ b/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java @@ -265,9 +265,9 @@ void testReadCsv_withColumnIndexes_shouldFilterColumns() throws Exception { List targetColumns = Arrays.asList(0, 2); List> readResults = FesodSheet.read(csvFile) - .includeColumnIndexes(targetColumns) .csv() .sheet(0) + .includeColumnIndexes(Set.of(0, 2)) .doReadSync(); Assertions.assertNotNull(readResults); From a189d683cec8bc6bdd1ddad0d7cbbda01d02b52e Mon Sep 17 00:00:00 2001 From: Selim Soufargi Date: Tue, 4 Aug 2026 14:12:36 +0200 Subject: [PATCH 6/8] fix test method call and test behaviour --- .../test/java/org/apache/fesod/sheet/FesodSheetTest.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java b/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java index 0ada9827d..b1505ede9 100644 --- a/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java +++ b/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java @@ -25,8 +25,8 @@ import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; import java.nio.file.Path; -import java.util.Arrays; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import org.apache.commons.io.FileUtils; @@ -276,10 +276,9 @@ void testReadCsv_withColumnIndexes_shouldFilterColumns() throws Exception { Map row1 = readResults.get(0); Assertions.assertEquals(2, row1.size(), "Should only contain the 2 filtered columns"); Assertions.assertEquals("1", row1.get(0)); - Assertions.assertEquals("30", row1.get(2)); - Assertions.assertNull(row1.get(1), "Column index 1 (Name) should be omitted"); + Assertions.assertEquals("30", row1.get(1)); } - + @Test void testReadSheet_withColumnIndexes_shouldConfigureAll() { From 076f3ae955f7a202c9094b9098c3301c3adf67e9 Mon Sep 17 00:00:00 2001 From: Selim Soufargi Date: Tue, 4 Aug 2026 14:14:28 +0200 Subject: [PATCH 7/8] fix test method call and test behaviour --- .../src/test/java/org/apache/fesod/sheet/FesodSheetTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java b/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java index b1505ede9..334ac32e6 100644 --- a/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java +++ b/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java @@ -267,7 +267,7 @@ void testReadCsv_withColumnIndexes_shouldFilterColumns() throws Exception { List> readResults = FesodSheet.read(csvFile) .csv() .sheet(0) - .includeColumnIndexes(Set.of(0, 2)) + .includeColumnIndexes(targetColumns) .doReadSync(); Assertions.assertNotNull(readResults); From 407d0a7fb975220ed8bfc51713a20a7788e7ea4f Mon Sep 17 00:00:00 2001 From: Selim Soufargi Date: Tue, 4 Aug 2026 14:32:18 +0200 Subject: [PATCH 8/8] fix test method call and test behaviour + define the includeColumnIndexes in CSVReaderBuilder --- .../fesod/sheet/read/builder/CsvReaderBuilder.java | 11 +++++++++++ .../java/org/apache/fesod/sheet/FesodSheetTest.java | 12 ++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/fesod-sheet/src/main/java/org/apache/fesod/sheet/read/builder/CsvReaderBuilder.java b/fesod-sheet/src/main/java/org/apache/fesod/sheet/read/builder/CsvReaderBuilder.java index 36a6befe7..84b8cb8e9 100644 --- a/fesod-sheet/src/main/java/org/apache/fesod/sheet/read/builder/CsvReaderBuilder.java +++ b/fesod-sheet/src/main/java/org/apache/fesod/sheet/read/builder/CsvReaderBuilder.java @@ -117,6 +117,17 @@ public CsvReaderBuilder nullString(String nullString) { return this; } + /** + * Specific columns to read + * + * @param columnIndexes + * @return + */ + public CsvReaderBuilder includeColumnIndexes(List columnIndexes) { + readSheet.setColumnIndexes(columnIndexes); + return this; + } + /** * Sets the escape character. * diff --git a/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java b/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java index 334ac32e6..8f267eb7f 100644 --- a/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java +++ b/fesod-sheet/src/test/java/org/apache/fesod/sheet/FesodSheetTest.java @@ -258,7 +258,7 @@ void testReadSheet_withAllParams_shouldReturnBuilder() { @Test void testReadCsv_withColumnIndexes_shouldFilterColumns() throws Exception { - String csvContent = "1,Alice,30,Female\n2,Bob,25,Male"; + String csvContent = "ID,Name,Age,Gender\n2,Bob,25,Male"; File csvFile = tempDir.resolve("test_columns.csv").toFile(); FileUtils.writeStringToFile(csvFile, csvContent, StandardCharsets.UTF_8); @@ -266,17 +266,17 @@ void testReadCsv_withColumnIndexes_shouldFilterColumns() throws Exception { List> readResults = FesodSheet.read(csvFile) .csv() - .sheet(0) .includeColumnIndexes(targetColumns) .doReadSync(); Assertions.assertNotNull(readResults); - Assertions.assertEquals(2, readResults.size()); + Assertions.assertEquals(1, readResults.size()); Map row1 = readResults.get(0); - Assertions.assertEquals(2, row1.size(), "Should only contain the 2 filtered columns"); - Assertions.assertEquals("1", row1.get(0)); - Assertions.assertEquals("30", row1.get(1)); + Assertions.assertEquals( + 2, row1.size(), "Should only contain the 1 filtered columns (excepting the head by default)"); + Assertions.assertEquals("2", row1.get(0)); + Assertions.assertEquals("25", row1.get(1)); } @Test