diff --git a/src/main/groovy/org/jggug/kobo/gexcelapi/GExcel.groovy b/src/main/groovy/org/jggug/kobo/gexcelapi/GExcel.groovy index ca14922..c989970 100644 --- a/src/main/groovy/org/jggug/kobo/gexcelapi/GExcel.groovy +++ b/src/main/groovy/org/jggug/kobo/gexcelapi/GExcel.groovy @@ -78,6 +78,23 @@ class GExcel { } return null } + findEmptyRow { label -> + Row targetRow = delegate.find { Row row -> + row.rowNum >= CLU.rowIndex(label) && row.getCell(CLU.columnIndex(label))?.value == null } + if (!targetRow) { + return delegate.createRow(delegate.lastRowNum+1) + } + + return targetRow + } + findByCellValue { label, cellValue -> + def condition = createCondition(label, cellValue) + delegate.find(condition) + } + findAllByCellValue { label, cellValue -> + def condition = createCondition(label, cellValue) + delegate.findAll(condition) + } } } @@ -156,6 +173,50 @@ class GExcel { } } + private static createCondition(String label, String cellValue) { + int cellIndex = CLU.columnIndex(label) + def condition = { Row row -> + if (row.rowNum < CLU.rowIndex(label)) { + return false + } + + Cell cell = row.getCell(cellIndex) + if (cell == null) { + return false + } + if (cell.value == null) { + return false + } + if (!cell.isStringType()) { + return false + } + cell.value.contains(cellValue) + } + return condition + } + + private static createCondition(String label, Integer cellValue) { + int cellIndex = CLU.columnIndex(label) + def condition = { Row row -> + if (row.rowNum < CLU.rowIndex(label)) { + return false + } + + Cell cell = row.getCell(cellIndex) + if (cell == null) { + return false + } + if (cell.value == null) { + return false + } + if (!cell.isNumericType()) { + return false + } + cell.value == cellValue + } + return condition + } + private static getRowFromSheetByLabel(sheet, label) { int rowIndex = CLU.rowIndex(label) def row = sheet.getRow(rowIndex) diff --git a/src/test/groovy/org/jggug/kobo/gexcelapi/GExcelTest.groovy b/src/test/groovy/org/jggug/kobo/gexcelapi/GExcelTest.groovy index a04b2aa..f7ae22f 100644 --- a/src/test/groovy/org/jggug/kobo/gexcelapi/GExcelTest.groovy +++ b/src/test/groovy/org/jggug/kobo/gexcelapi/GExcelTest.groovy @@ -19,12 +19,17 @@ package org.jggug.kobo.gexcelapi class GExcelTest extends GroovyTestCase { def sampleFile = "build/resources/test/sample.xls" + def outputPath = "output.xls" + def outputFile def book def sheet + def sheetForFindRowTest void setUp() { book = GExcel.open(sampleFile) sheet = book[0] + sheetForFindRowTest = book[3] + outputFile = new File(outputPath) // dateCellValue is affected by TimeZone. // So it should be explicitly set as GMT in order to avoid causing a failure dependent on an environment. @@ -34,6 +39,8 @@ class GExcelTest extends GroovyTestCase { void tearDown() { book = null sheet = null + sheetForFindRowTest = null + outputFile.delete() } void testOpen() { @@ -294,5 +301,87 @@ class GExcelTest extends GroovyTestCase { assert sheet.getEnclosingMergedRegion(sheet.A4).isFirstCell(sheet.A5) == false assert sheet.getEnclosingMergedRegion(sheet.A4).isFirstCell(sheet.B5) == false } + + void testFindEmptyRowFormulaValueColumn() { + def emptyRow = sheetForFindRowTest.findEmptyRow('A2'); + assert emptyRow != null + assert emptyRow.rowNum == 10 // rowNum start 0 + assert emptyRow.getCell(0)?.value == null + } + + void testFindEmptyRowValueColumn() { + def emptyRow = sheetForFindRowTest.findEmptyRow('B3'); + assert emptyRow != null + assert emptyRow.rowNum == 8 // rowNum start 0 + assert emptyRow.getCell(1)?.value == null + } + + void testAddRow() { + def emptyRow = sheetForFindRowTest.findEmptyRow('A2'); + emptyRow.createCell(0).value = "100" + emptyRow.createCell(1).value = "test" + + outputFile.withOutputStream { book.write(it) } + def targetBook = GExcel.open(outputFile) + def targetSheet = targetBook[3] + assert targetSheet.A11.value == "100" + assert targetSheet.B11.value == "test" + } + + void testFindByCellValue() { + def resultRow = sheetForFindRowTest.findByCellValue('F4', 'Ken'); + assert resultRow != null + assert resultRow.label == "7" // label equals line number on excel + assert resultRow.F_.value == "Ken" + assert resultRow.getCell(5) == sheetForFindRowTest.F7 + } + + void testFindByCellValuePrefixMatch() { + def resultRow = sheetForFindRowTest.findByCellValue('C4', 'Add'); + assert resultRow != null + assert resultRow.label == "4" // label equals line number on excel + assert resultRow.C_.value == "Add Feature" + assert resultRow.getCell(2) == sheetForFindRowTest.C4 + } + + void testFindByCellValueSuffixMatch() { + def resultRow = sheetForFindRowTest.findByCellValue('H6', 'ed'); + assert resultRow != null + assert resultRow.label == "6" // label equals line number on excel + assert resultRow.H_.value == "Closed" + assert resultRow.getCell(7) == sheetForFindRowTest.H6 + } + + void testFindByCellValueNumberMatch() { + def resultRow = sheetForFindRowTest.findByCellValue('I4', 20); + assert resultRow != null + assert resultRow.label == "5" // label equals line number on excel + assert resultRow.I_.value == 20 + assert resultRow.getCell(8) == sheetForFindRowTest.I5 + } + + void testFindAllByCellValue() { + def resultRows = sheetForFindRowTest.findAllByCellValue('D4', 'B'); + assert resultRows[0].label == "5" + assert resultRows[0].D_.value == "B" + assert resultRows[1].label == "6" + assert resultRows[1].D_.value == "B" + } + + void testFindAllByCellValuePrefixMatch() { + def resultRows = sheetForFindRowTest.findAllByCellValue('C4', 'Spec'); + assert resultRows[0].label == "5" + assert resultRows[0].C_.value == "Spec Change" + assert resultRows[1].label == "7" + assert resultRows[1].C_.value == "Spec Change" + } + + void testFindAllByCellValueNumberMatch() { + def resultRows = sheetForFindRowTest.findAllByCellValue('I4', 10); + assert resultRows[0].label == "7" + assert resultRows[0].I_.value == 10 + assert resultRows[1].label == "8" + assert resultRows[1].I_.value == 10 + } } diff --git a/src/test/resources/sample.xls b/src/test/resources/sample.xls index 80cd780..b136a06 100644 Binary files a/src/test/resources/sample.xls and b/src/test/resources/sample.xls differ