From: <ma...@us...> - 2012-08-24 10:41:10
|
Revision: 384 http://objectlabkit.svn.sourceforge.net/objectlabkit/?rev=384&view=rev Author: marchy Date: 2012-08-24 10:41:03 +0000 (Fri, 24 Aug 2012) Log Message: ----------- Excel gets some tests + upgrade to poi 3.8. Upgrading poi library to latest version 3.8. This required some refactors, but it means that it works with xlsx's now too. Adding tests for read* methods... so I think we're ready to release this module. Modified Paths: -------------- trunk/utils-excel/pom.xml trunk/utils-excel/src/main/java/net/objectlab/kit/util/excel/Excel.java Added Paths: ----------- trunk/utils-excel/src/test/ trunk/utils-excel/src/test/java/ trunk/utils-excel/src/test/java/net.objectlab.kit.util.excel/ trunk/utils-excel/src/test/java/net.objectlab.kit.util.excel/ExcelTest.java trunk/utils-excel/src/test/resources/ trunk/utils-excel/src/test/resources/net/ trunk/utils-excel/src/test/resources/net/objectlab/ trunk/utils-excel/src/test/resources/net/objectlab/kit/ trunk/utils-excel/src/test/resources/net/objectlab/kit/util/ trunk/utils-excel/src/test/resources/net/objectlab/kit/util/excel/ trunk/utils-excel/src/test/resources/net/objectlab/kit/util/excel/Test Workbook.xls trunk/utils-excel/src/test/resources/net/objectlab/kit/util/excel/Test Workbook.xlsx Property Changed: ---------------- trunk/utils-excel/ Property changes on: trunk/utils-excel ___________________________________________________________________ Modified: svn:ignore - target + target .idea *.iml Modified: trunk/utils-excel/pom.xml =================================================================== --- trunk/utils-excel/pom.xml 2012-04-25 15:28:20 UTC (rev 383) +++ trunk/utils-excel/pom.xml 2012-08-24 10:41:03 UTC (rev 384) @@ -13,9 +13,15 @@ <dependencies> <dependency> <groupId>org.apache.poi</groupId> - <artifactId>poi</artifactId> - <version>3.2-FINAL</version> + <artifactId>poi-ooxml</artifactId> + <version>3.8</version> </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.10</version> + <scope>test</scope> + </dependency> </dependencies> <build> Modified: trunk/utils-excel/src/main/java/net/objectlab/kit/util/excel/Excel.java =================================================================== --- trunk/utils-excel/src/main/java/net/objectlab/kit/util/excel/Excel.java 2012-04-25 15:28:20 UTC (rev 383) +++ trunk/utils-excel/src/main/java/net/objectlab/kit/util/excel/Excel.java 2012-08-24 10:41:03 UTC (rev 384) @@ -1,114 +1,106 @@ package net.objectlab.kit.util.excel; -import java.io.FileInputStream; -import java.io.FileNotFoundException; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.AreaReference; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.CellReference; + import java.io.InputStream; import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.LinkedList; -import java.util.List; +import java.util.*; -import org.apache.poi.hssf.usermodel.HSSFCell; -import org.apache.poi.hssf.usermodel.HSSFName; -import org.apache.poi.hssf.usermodel.HSSFRow; -import org.apache.poi.hssf.usermodel.HSSFSheet; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.hssf.util.RangeAddress; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; - public class Excel { - private HSSFWorkbook workbook; + private Workbook workbook; - private InputStream inputStream; - - public Excel() { - } - public Excel(InputStream in) { - setInputStream(in); - init(); + init(in); } - public void init() throws RuntimeException { + private void init(InputStream inputStream) throws RuntimeException { - POIFSFileSystem fs; try { - fs = new POIFSFileSystem(inputStream); - workbook = new HSSFWorkbook(fs); + workbook = WorkbookFactory.create(inputStream); } catch (Exception e) { throw new RuntimeException(e); } } - public <E> E readValue(String cellAddress, Class<E> type) { + public <E> E readValueAt(String cellAddress, Class<E> type) { + return readCell(cellAt(cellAddress), type); + } - Object[][] result = readBlock(cellAddress, true, type); - return (E) result[0][0]; + public <E> List<E> readColumn(String rangeOrStartAddress, Class<E> type) { + + Object[][] arr = readBlock(rangeOrStartAddress, type); + + List<E> result = new LinkedList<E>(); + for (int i = 0; i < arr.length; i++) { + result.add((E)arr[i][0]); + } + + return result; } + public String namedRangeToRangeAddress(String namedRange) { + int namedCellIndex = getWorkbook().getNameIndex(namedRange); + Name namedCell = getWorkbook().getNameAt(namedCellIndex); + + return namedCell.getRefersToFormula(); + } + + public Cell cellAt(String cellAddr) { + CellReference cr = new CellReference(cellAddr); + + return workbook + .getSheet(cr.getSheetName()) + .getRow(cr.getRow()) + .getCell((int) cr.getCol()); + } + /** - * - * @param range - * either the range of the entire block to be read, or just the - * top row of the cells, in which case the method will stop when - * the first empty cell is reached in the first column - * @param colTypes - * classes of the result types, per column - * @return 2 dimensional array, containing the data read, cast as per - * colTypes + * @param range either the range of the entire block to be read, or just the + * top row of the cells, in which case the method will stop when + * the first empty cell is reached in the first column + * @param colTypes An array of data types expected at each column. + * If this array is shorter than the number of column, then the last + * data type is used until the end. So if only one value is given, + * then that is used for the entire block. */ public Object[][] readBlock(String range, Class... colTypes) { - return readBlock(range, false, colTypes); - } - - private Object[][] readBlock(String range, boolean oneLiner, Class... colTypes) { + CellRangeAddress cra = CellRangeAddress.valueOf(range); + AreaReference ar = new AreaReference(range); + Sheet sheet = workbook.getSheet(ar.getFirstCell().getSheetName()); - RangeAddress ra = new RangeAddress(range); - HSSFSheet sheet = workbook.getSheet(ra.getSheetName()); + int firstColumn = cra.getFirstColumn(); + int firstRow = cra.getFirstRow(); + int lastRow = cra.getLastRow(); + int height = lastRow - firstRow + 1; + int width = cra.getLastColumn() - firstColumn + 1; - oneLiner = (ra.getHeight() == 1 && oneLiner); - List<Object> result; - if (ra.getHeight() == 1) { + if (height == 1) { result = new LinkedList<Object>(); } else { - result = new ArrayList<Object>(ra.getHeight()); + result = new ArrayList<Object>(height); } - int x = ra.getXPosition(ra.getFromCell()); - int y = ra.getYPosition(ra.getFromCell()); - - Class colType = colTypes[0]; - for (int i = 0; (isMoreToRead(sheet, oneLiner, x, y, i)); i++) { - HSSFRow row = sheet.getRow(y + i - 1); - Object[] resultRow = new Object[ra.getWidth()]; + for (int rowNum = 0; moreDataToRead(sheet, firstColumn, firstRow, lastRow, rowNum); rowNum++) { + Row row = sheet.getRow(firstRow + rowNum); + Object[] resultRow = new Object[width]; result.add(resultRow); - for (int j = 0; j < ra.getWidth(); j++) { - HSSFCell cell = row.getCell((short) (x + j - 1)); + for (int colNum = 0; colNum < width; colNum++) { - if (colTypes.length > j) { - colType = colTypes[j]; + Class colType; + if (colNum < colTypes.length - 1) { + colType = colTypes[colNum]; + } else { + colType = colTypes[colTypes.length - 1]; } - if (colType == Date.class) { - resultRow[j] = cell.getDateCellValue(); - } else if (colType == Calendar.class) { - Calendar cal = Calendar.getInstance(); - cal.setTime(cell.getDateCellValue()); - resultRow[j] = cal; - } else if (colType == Integer.class) { - resultRow[j] = ((Double) cell.getNumericCellValue()).intValue(); - } else if (colType == Double.class) { - resultRow[j] = (Double) cell.getNumericCellValue(); - } else if (colType == BigDecimal.class) { - resultRow[j] = new BigDecimal(String.valueOf(cell.getNumericCellValue())); - } else if (colType == String.class) { - resultRow[j] = cell.getRichStringCellValue().getString(); - } + Cell cell = row.getCell(firstColumn + colNum); + resultRow[colNum] = readCell(cell, colType); } } @@ -116,19 +108,42 @@ return result.toArray(new Object[][] {}); } - private boolean isMoreToRead(HSSFSheet sheet, boolean oneLiner, int x, int y, int i) { + private <E> E readCell(Cell cell, Class<E> colType) { - if (oneLiner) { - return (i < 1); + if (colType == Date.class) { + return (E) cell.getDateCellValue(); + } else if (colType == Calendar.class) { + Calendar cal = Calendar.getInstance(); + cal.setTime(cell.getDateCellValue()); + return (E) cal; + } else if (colType == Integer.class) { + return (E) ((Integer) ((Double) cell.getNumericCellValue()).intValue()); + } else if (colType == Double.class) { + return (E) (Double) cell.getNumericCellValue(); + } else if (colType == BigDecimal.class) { + return (E) new BigDecimal(String.valueOf(cell.getNumericCellValue())); + } else if (colType == String.class) { + return (E) cell.getRichStringCellValue().getString(); + } else { + throw new RuntimeException("Column type not supported: " + colType); } - + + } + + private boolean moreDataToRead(Sheet sheet, int firstColumn, int firstRow, int lastRow, int rowNum) { + + int height = lastRow - firstRow + 1; + if (height > 1 && firstRow + rowNum > lastRow) { + return false; + } + // check if the cell is empty - HSSFRow row = sheet.getRow(y + i - 1); + Row row = sheet.getRow(firstRow + rowNum); if (row == null) { return false; } - - HSSFCell cell = row.getCell((short) (x - 1)); + + Cell cell = row.getCell(firstColumn); if (cell == null) { return false; } @@ -136,49 +151,7 @@ return !(str == null || "".equals(str)); } - public <E> List<E> readColumn(String rangeOrStartAddress, Class<E> type) { - - Object[][] arr = readBlock(rangeOrStartAddress, false, type); - - List<E> result = new LinkedList<E>(); - for (int i = 0; i < arr.length; i++) { - result.add((E)arr[i][0]); - } - - return result; - } - - public String namedRangeToRangeAddress(String namedRange) { - int namedCellIndex = getWorkbook().getNameIndex(namedRange); - HSSFName namedCell = getWorkbook().getNameAt(namedCellIndex); - - return namedCell.getReference(); - } - - public HSSFCell getCell(String cellAddr) { - RangeAddress ra = new RangeAddress(cellAddr); - - return workbook.getSheet(ra.getSheetName()).getRow(ra.getYPosition(ra.getFromCell()) - 1).getCell( - (short) (ra.getXPosition(ra.getFromCell()) - 1)); - } - - public HSSFWorkbook getWorkbook() { + public Workbook getWorkbook() { return workbook; } - - public void setWorkbook(HSSFWorkbook workbook) { - this.workbook = workbook; - } - - public void setInputStream(InputStream inputStream) { - this.inputStream = inputStream; - } - - public void setFilename(String filename) { - try { - inputStream = new FileInputStream(filename); - } catch (FileNotFoundException e) { - throw new RuntimeException(e); - } - } } Added: trunk/utils-excel/src/test/java/net.objectlab.kit.util.excel/ExcelTest.java =================================================================== --- trunk/utils-excel/src/test/java/net.objectlab.kit.util.excel/ExcelTest.java (rev 0) +++ trunk/utils-excel/src/test/java/net.objectlab.kit.util.excel/ExcelTest.java 2012-08-24 10:41:03 UTC (rev 384) @@ -0,0 +1,100 @@ +package net.objectlab.kit.util.excel; + + +import org.junit.Before; +import org.junit.Test; + +import java.math.BigDecimal; +import java.util.List; + +import static junit.framework.Assert.assertEquals; + +/** + * @author Marcin Jekot + * @since 2012/08/17 + */ +public class ExcelTest { + + private Excel xls; + private Excel xlsx; + + @Before + public void setUp() { + xls = new Excel(getClass().getResourceAsStream("Test Workbook.xls")); + xlsx = new Excel(getClass().getResourceAsStream("Test Workbook.xlsx")); + } + + @Test + public void shouldReadSingleCell() { + // When + String result = xlsx.readValueAt("'Test Sheet'!C3", String.class); + + // Then + assertEquals("TestA", result); + } + + @Test + public void shouldReadColumn() { + // When + List<String> result = xlsx.readColumn("'Test Sheet'!C3", String.class); + + // Then + assertEquals(9, result.size()); + assertEquals("TestA", result.get(0)); + assertEquals("TestI", result.get(8)); + } + + @Test + public void shouldReadTwoLinesAndStop() { + // When + Object[][] result = xlsx.readBlock("'Test Sheet'!C3:F4", String.class, Integer.class); + + // Then + assertEquals("Number of rows read should be 2", 2, result.length); + assertEquals("Number of columns read should be 4", 4, result[0].length); + assertEquals("Number of columns read should be 4", 4, result[1].length); + } + + @Test + public void shouldReadWholeBlockGivenTopLine() { + // When + Object[][] result = xlsx.readBlock("'Test Sheet'!C3:F3", String.class, Integer.class); + + // Then + assertEquals("Number of rows read should be 9", 9, result.length); + assertEquals("Number of columns read should be 4", 4, result[0].length); + assertEquals("Number of columns read should be 4", 4, result[8].length); + } + + @Test + public void shouldReadARangeOfCellsInXls() { + shouldReadARangeOfCells(xls); + } + + @Test + public void shouldReadARangeOfCellsInXlx() { + shouldReadARangeOfCells(xlsx); + } + + private void shouldReadARangeOfCells(Excel xl) { + // When + Object[][] result = xl.readBlock("'Test Sheet'!C3:F12", String.class, Integer.class, Double.class, BigDecimal.class); + + // Then + final int numberOfRows = 9; + assertEquals(numberOfRows, result.length); + + for (int i = 1; i <= numberOfRows; i++) { + + Object[] data = result[i - 1]; + assertEquals("Test" + Character.toString((char) ('A' + i - 1)), data[0]); + assertEquals(i, data[1]); + + final int decimal = i % 10; + assertEquals(i + decimal / (double) 10, data[2]); + assertEquals(new BigDecimal("" + i + "." + decimal + decimal), data[3]); + + assertEquals(4, data.length); + } + } +} Added: trunk/utils-excel/src/test/resources/net/objectlab/kit/util/excel/Test Workbook.xls =================================================================== (Binary files differ) Property changes on: trunk/utils-excel/src/test/resources/net/objectlab/kit/util/excel/Test Workbook.xls ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/utils-excel/src/test/resources/net/objectlab/kit/util/excel/Test Workbook.xlsx =================================================================== (Binary files differ) Property changes on: trunk/utils-excel/src/test/resources/net/objectlab/kit/util/excel/Test Workbook.xlsx ___________________________________________________________________ Added: svn:mime-type + application/octet-stream This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |