Reading https://poi.apache.org/apidocs/org/apache/poi/xssf/streaming/SXSSFSheet.html#groupRow(int,%20int)
it says that groups should be created inside window size, but how to create groups that overpass window size
This minimal example generates a groupRow from row 2 to row 554 in a excel of 1000 rows with a window size of 200
public static final int ROWS=1000;
public static final int WINDOW_SIZE=100;
//public static final int WINDOW_SIZE=1000;
public static void main(String args[]) throws FileNotFoundException, IOException{
File outputFile = new File("testFile-actual.xlsx");
SXSSFWorkbook sworkbook = new SXSSFWorkbook(WINDOW_SIZE);
creatXLSX(outputFile, sworkbook);
File expectedoutputFile = new File("testFile-expected.xlsx");
XSSFWorkbook workbook = new XSSFWorkbook();
creatXLSX(expectedoutputFile, workbook);
}
private static void creatXLSX(File outputFile, Workbook workbook)
throws IOException, FileNotFoundException {
Sheet sheet = workbook.createSheet();
int posFirstRow = 1;
boolean addgroup = true;
for(int i = 0; i < ROWS; i++) {
Row row = sheet.createRow(i);
Cell cell = row.createCell(0);
cell.setCellValue(i);
if (addgroup && i % WINDOW_SIZE == 0) {
sheet.groupRow(posFirstRow, i);
posFirstRow = i+1;
}
if (i == 556) {
sheet.groupRow(posFirstRow, 553);
posFirstRow = 556;
addgroup = false;
}
}
workbook.write(new FileOutputStream(outputFile));
}
Key is that:
groupRow(1,n)
groupRow(n+1, m)
joins two groups and generate same as
groupRow(1,m)
more info here https://bz.apache.org/bugzilla/show_bug.cgi?id=58077
Related
I have written a code to pick data for certain area in the input excel and the transpose and paste it in the output excel. This read and write are 2 separate methods, which i call from main method. However, once the code runs and the file is generated, it only shows the data written for the last write method call. As per my understanding, it has to be because, my code is creating a new workbook object every time. Though i have tried to overcome this by using static keyword in my code. Please see below for the code.
public class DataExtractor {
static FileOutputStream output = null;
static XSSFWorkbook workbook = null;
static XSSFSheet sheet = null;
static XSSFWorkbook outputWorkbook = null;
static XSSFSheet outputSheet = null;
static XSSFRow row = null;
DataFormatter dataFormatter = null;
public DataExtractor(XSSFWorkbook workbook, XSSFSheet sheet, XSSFWorkbook outputWorkbook, XSSFSheet outputSheet) {
DataExtractor.workbook = workbook;
DataExtractor.sheet = sheet;
DataExtractor.outputWorkbook = outputWorkbook;
DataExtractor.outputSheet = outputSheet;
}
private ArrayList<ArrayList<String>> fetchDataFromInputExcel(){
//code for fetching data from excel/reading excel only for some grids.
}
private ArrayList<ArrayList<String>> pasteTransposedDataIntoOutputExcel(){
//code for transposing data and pasting it into output excel/writing to excel.
}
public static void main(String args[]){
File file = new File("path of xlsx file");
workbook = new XSSFWorkbook(new FileInputStream(file));
sheet = workbook.getSheet("SHEETNAME");
outputWorkbook = new XSSFWorkbook();
outputSheet = outputWorkbook.createSheet("OUTPUT");
DataExtractor obj = new DataExtractor(workbook, sheet, outputWorkbook, outputSheet);
ArrayList<ArrayList<String>> header = dataExtractor.fetchDataFromInputExcel(//args for mentioning grid area row and col are passed here);
ArrayList<ArrayList<String>> data = dataExtractor.fetchDataFromInputExcel(//args for mentioning grid area row and col are passed here);
dataExtractor.pasteTransposedDataIntoOutputExcel(dataExtractor, data, 1, 8);
dataExtractor.pasteTransposedDataIntoOutputExcel(dataExtractor, header, 1, 1);
output = new FileOutputStream(new File("path of output.xlsx file"));
outputWorkbook.write(output);
}
}
Only dataExtractor.pasteTransposedDataIntoOutputExcel(dataExtractor, header, 1, 1) operation is performed and i do not see the data for the previous one. Please suggest.
Method for transposeAndPaste:
private boolean transposeAndPasteData(DataExtractor dataExtractor, ArrayList<ArrayList<String>> data, int startRowNum, int startColNum){
XSSFCell cell = null;
XSSFRow row = null;
outputWorkbook = dataExtractor.getOutputWorkbook();
outputSheet = dataExtractor.getOutputSheet();
try {
int startRowIndex = startRowNum - 1;
int startColIndex = startColNum - 1;
//paste data row wise
//for(int rowNum = startColNum-1; rowNum<startColNum+data.size(); rowNum++) {}
Iterator<ArrayList<String>> colItr = data.iterator();
while(colItr.hasNext()) {
row = outputSheet.createRow(startRowIndex++);
ArrayList<String> colData = colItr.next();
Iterator<String> rowItr = colData.iterator();
while(rowItr.hasNext()) {
cell = row.createCell(startColIndex++);
cell.setCellValue(rowItr.next());
}
startColIndex = startColNum - 1;
}
dataExtractor.setOutputSheet(outputSheet);
return true;
}catch(Exception e) {
e.printStackTrace();
return false;
}
Thanks,
Aman
I am trying to read some test data from an Excel file (3 rows and 2 columns with no blank row in between) but in the output I am getting just the first row of the Excel. After that it is giving me a null pointer exception.
public class ReadDataFromExcel {
public void readExcel(String filePath,String fileName,String sheetName) throws IOException {
File file = new File(filePath+"\\"+fileName);
FileInputStream inputStream = new FileInputStream(file);
Workbook myWorkbook = null;
String fileExtensionName = fileName.substring(fileName.indexOf("."));
if(fileExtensionName.equals(".xlsx")) {
myWorkbook = new XSSFWorkbook(inputStream);
}
else if(fileExtensionName.equals(".xls")) {
myWorkbook = new HSSFWorkbook(inputStream);
}
Sheet mySheet = myWorkbook.getSheet(sheetName);
int rowCount = mySheet.getLastRowNum()- guru99Sheet.getFirstRowNum();
System.out.println("Total rows= " +rowCount);
for (int i = 0; i < rowCount+1; i++) {
Row row = mySheet.getRow(i);
int columnCount = row.getLastCellNum() - row.getFirstCellNum();
for(int j=0; j <= columnCount; j++) {
System.out.print(row.getCell(j).getStringCellValue()+"|| ");
}
System.out.println();
}
}
public static void main(String...strings) throws IOException {
ReadDataFromExcel objExcelFile = new ReadDataFromExcel();
String filePath = System.getProperty("user.dir")+"\\src\\testFileInputOutput";
objExcelFile.readExcel(filePath,"testExcel.xlsx","testSheet");
}
}
I am getting the exception on this line:
System.out.print(row.getCell(j).getStringCellValue()+"|| ");
To get past NullPointerException you can check for null by replacing the line that is throwing the exception with this:
Cell cell = row.getCell(j);
if (cell != null) {
System.out.print(cell.getStringCellValue());
}
System.out.print("|| ");
I have the solution to copy .xls workbook in java but not able to copy .xlsx workbook.
Anybody have solution.
I have searched google, stackoverflow and found solution only to copy xls files.
If anyone wants a simpler procedure just use Files.copy:
File originalWb = new File("orginalWb.xlsx");
File clonedWb = new File("clonedWb.xlsx");
Files.copy(originalWb.toPath(), clonedW.toPath());
No need for any bloated code
I didn't test my code. Just wrote it to give you a basic idea of what to do.
public class CopyXSSFWorkbook {
public static void main(String[] args) {
// Read xlsx file
XSSFWorkbook oldWorkbook = null;
try {
oldWorkbook = (XSSFWorkbook) WorkbookFactory.create(new File("old.xlsx"));
} catch (Exception e) {
e.printStackTrace();
return;
}
final XSSFWorkbook newWorkbook = new XSSFWorkbook();
// Copy style source
final StylesTable oldStylesSource = oldWorkbook.getStylesSource();
final StylesTable newStylesSource = newWorkbook.getStylesSource();
oldStylesSource.getFonts().forEach(font -> newStylesSource.putFont(font, true));
oldStylesSource.getFills().forEach(fill -> newStylesSource.putFill(new XSSFCellFill(fill.getCTFill())));
oldStylesSource.getBorders()
.forEach(border -> newStylesSource.putBorder(new XSSFCellBorder(border.getCTBorder())));
// Copy sheets
for (int sheetNumber = 0; sheetNumber < oldWorkbook.getNumberOfSheets(); sheetNumber++) {
final XSSFSheet oldSheet = oldWorkbook.getSheetAt(sheetNumber);
final XSSFSheet newSheet = newWorkbook.createSheet(oldSheet.getSheetName());
newSheet.setDefaultRowHeight(oldSheet.getDefaultRowHeight());
newSheet.setDefaultColumnWidth(oldSheet.getDefaultColumnWidth());
// Copy content
for (int rowNumber = oldSheet.getFirstRowNum(); rowNumber < oldSheet.getLastRowNum(); rowNumber++) {
final XSSFRow oldRow = oldSheet.getRow(rowNumber);
if (oldRow != null) {
final XSSFRow newRow = newSheet.createRow(rowNumber);
newRow.setHeight(oldRow.getHeight());
for (int columnNumber = oldRow.getFirstCellNum(); columnNumber < oldRow
.getLastCellNum(); columnNumber++) {
newSheet.setColumnWidth(columnNumber, oldSheet.getColumnWidth(columnNumber));
final XSSFCell oldCell = oldRow.getCell(columnNumber);
if (oldCell != null) {
final XSSFCell newCell = newRow.createCell(columnNumber);
// Copy value
setCellValue(newCell, getCellValue(oldCell));
// Copy style
XSSFCellStyle newCellStyle = newWorkbook.createCellStyle();
newCellStyle.cloneStyleFrom(oldCell.getCellStyle());
newCell.setCellStyle(newCellStyle);
}
}
}
}
}
try {
oldWorkbook.close();
newWorkbook.write(new FileOutputStream("new.xlsx"));
newWorkbook.close();
} catch (Exception e) {
e.printStackTrace();
return;
}
}
private static void setCellValue(final XSSFCell cell, final Object value) {
if (value instanceof Boolean) {
cell.setCellValue((boolean) value);
} else if (value instanceof Byte) {
cell.setCellValue((byte) value);
} else if (value instanceof Double) {
cell.setCellValue((double) value);
} else if (value instanceof String) {
if (value.startsWith("=")) {
// Formula String
cell.setCellFormula(value.substring(1));
} else {
cell.setCellValue(cstr);
}
} else {
throw new IllegalArgumentException();
}
}
private static Object getCellValue(final XSSFCell cell) {
switch (cell.getCellTypeEnum()) {
case BOOLEAN:
return cell.getBooleanCellValue(); // boolean
case ERROR:
return cell.getErrorCellValue(); // byte
case NUMERIC:
return cell.getNumericCellValue(); // double
case STRING:
case BLANK:
return cell.getStringCellValue(); // String
case FORMULA:
return "=" + cell.getCellFormula(); // String for formula
default:
throw new IllegalArgumentException();
}
}
}
Using Apache POI XSSF library:
public void copyFile(String sourcePath, String destinationPath) throws IOException {
FileInputStream excelFile = new FileInputStream(new File(sourcePath));
Workbook workbook = new XSSFWorkbook(excelFile);
FileOutputStream outputStream = new FileOutputStream(destinationPath);
workbook.write(outputStream);
workbook.close();
}
Clone a workbook in memory (if you can efford it):
public static Workbook cloneWorkbook(final Workbook workbook) {
try {
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(4096);
workbook.write(outputStream);
return WorkbookFactory.create(new ByteArrayInputStream(outputStream.toByteArray()));
} catch (final IOException ex) {
log.warn("Error cloning workbook", ex);
return null; // or throw exception
}
}
Apache POI Busy Developers' Guide to HSSF and XSSF Features
POI performs these steps on XLS/XLSX File. XLS: HSSFWorkbook, XLSX: XSSFWorkbook
Read the File as Stream (FileStream): SystemFile to JavaFileObject
Create a WorkBook form Stream. Stream to XSSFWorkbook-JavaObject
Using POI functions you can perform CURD operations on Java Workbook Object.
Convert Java Workbook Object to file/stream.
NOTE: Index Starts form 0 for Row/Column/Sheet.
Following operations are performed on Sheets:
XLSX File with Sheet1, Sheet2
getSheet_RemoveOthers(Sheet1). XLSX File:Sheet1
public static XSSFSheet getSheet_RemoveOthers(String sourceFileSheetName) {
XSSFSheet srcSheet = workBook.getSheet(sourceFileSheetName);
//Sheet srcSheet = oldWorkbook.getSheetAt(0);
int srcSheetIndex = workBook.getSheetIndex(srcSheet);
System.out.println("srcSheetIndex:"+srcSheetIndex);
int numberOfSheets = workBook.getNumberOfSheets();
for (int indexAt = 0; indexAt < numberOfSheets; indexAt++) {
if (srcSheetIndex == indexAt) {
System.out.println("sourceFileSheetName:"+indexAt);
} else {
String sheetName = workBook.getSheetName(indexAt);
System.out.println("Removing sheetName:"+sheetName);
workBook.removeSheetAt(indexAt);
}
}
System.out.println("getSheetName : "+ srcSheet.getSheetName() );
int totalRows = srcSheet.getPhysicalNumberOfRows();
System.out.println("Total Number of Rows : "+ totalRows );
return srcSheet;
}
XSSFSheet.cloneSheet(Sheet1). XLSX File:Sheet1, Sheet1 (2)
public static XSSFSheet cloneSheet(String sourceFileSheetName) {
Sheet srcSheet = workBook.getSheet(sourceFileSheetName);
int srcSheetIndex = workBook.getSheetIndex(srcSheet);
System.out.println("srcSheetIndex:"+srcSheetIndex);
XSSFSheet cloneSheet = workBook.cloneSheet(srcSheetIndex);
return cloneSheet;
}
Full-Length Example:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
public class POI_XLSX_Report {
static String filePath = "C:/Yash/",
sourceFile = filePath+"POIExcel.xlsx", sourceFileSheetName = "Sheet1",
destinationFile = filePath+"POIExcelCopy.xlsx";
static XSSFWorkbook workBook;
public static void main(String[] args) throws Exception {
File mySrcFile = new File(sourceFile);
FileInputStream stream = new FileInputStream(mySrcFile);
workBook = (XSSFWorkbook) WorkbookFactory.create( stream );
XSSFSheet sheet_RemoveOthers = getSheet_RemoveOthers(sourceFileSheetName);
setSheetValue(sheet_RemoveOthers, 4, 6, "Val2");
// New Sheet with exact copy of Source-Sheet
XSSFSheet cloneSheet = cloneSheet(sourceFileSheetName);
setSheetValue(cloneSheet, 4, 6, "Val2");
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
workBook.write( byteArrayOutputStream );
byteArrayOutputStream.close();
File clonedWb = new File(destinationFile);
//Files.copy(mySrcFile.toPath(), clonedWb.toPath()); If a file is already available then throws exception
// Write the output to a file
FileOutputStream fileOutputStream = new FileOutputStream( clonedWb );
byteArrayOutputStream.writeTo(fileOutputStream);
}
public static XSSFSheet getSheet_RemoveOthers(String sourceFileSheetName) {
// ...
}
public static XSSFSheet cloneSheet(String sourceFileSheetName) {
// ...
}
public static void setSheetValue(Sheet sheet, int colIndex, int rowIndex, String value) {
// Row and Column index starts form 0
rowIndex = rowIndex - 1;
colIndex = colIndex - 1;
Row row = sheet.getRow(rowIndex);
if (row == null) {
System.out.println("createRow:");
Row createRow = sheet.createRow(rowIndex);
row= createRow;
}
short lastCellNum = row.getLastCellNum();
System.out.println("Col:"+lastCellNum);
Cell createCell = row.createCell(colIndex, CellType.STRING);
System.out.println("New cell:"+createCell.getStringCellValue());
createCell.setCellValue(value);
}
}
public class Read {
public static void main(String [] args) throws Exception{
File f = new File ("/users/Me/Documents/Test.xls");
Workbook wb = Workbook.getWorkbook(f);
Sheet s = wb.getSheet(0);
int row = s.getRows();
int col = s.getColumns();
//for(int i = 0; i<row;i++){
//for(int j = 0; j<col;j++){
Cell c = s.getCell(4,1);
Cell e = s.getCell(5,1);
System.out.print(c.getContents()+"\t");
System.out.print(e.getContents()+"\t");
// }
//}
System.out.println("");
}
}
I tried this if statement if(c.getContents()>e.getContents()...but I am getting errors.
The simplest way would be to write
if(Double.parseDouble(c.getContents())>Double.parseDouble(e.getContents())) {...}
This should work if you sure that these cells contain numbers. Otherwise it would be reasonable to theck c.getType()/e.getType() first.
I am reading data from an arraylist and writing this to an excel sheet. The problem is my excel is getting overwritten each time. Here is my code. I can't figure out what is wrong here :( Can someone please help?
public static void main( String[] args ) throws Exception
{
List<String> fileData = new ArrayList<String>();
for(File file:files) {
fileData.add(readFileContents(file.getAbsolutePath()));
}
for(String fileContent:fileData) {
//do some stuff that in turn calls the writeDataToExcel method
}
}
private static void writeDataToExcel(String test,Map<String,String> dataMap,Object object) throws IOException {
File file = new File("input/data.xls");
Map<String,Object[]> data = new LinkedHashMap<String,Object[]>();
XSSFWorkbook workbook = null;
int count = 0;
XSSFSheet sheet = null;
if(file.exists()) {
workbook = new XSSFWorkbook(new FileInputStream(file));
sheet = workbook.getSheet("Data Sheet");
}
else {
workbook = new XSSFWorkbook();
sheet = workbook.createSheet("Data Sheet");
//count = sheet.getLastRowNum();
}
data.put("1", new Object[]{"Id","Name","Field","Description","Value"});
for(Map.Entry<String, String> dataMp:dataMap.entrySet()) {
data.put(Integer.toString(count+2), new Object[]{id,object.getClass().getSimpleName(),dataMp.getKey(),dataMp.getValue(),"null"});
count++;
}
Set<String> keyset = data.keySet();
int rownum = 0;
for (String key : keyset) {
Row row = sheet.createRow(rownum++);
Object [] objArr = data.get(key);
int cellnum = 0;
for (Object obj : objArr) {
Cell cell = row.createCell(cellnum++);
if(obj instanceof String)
cell.setCellValue((String)obj);
}
}
FileOutputStream fis = new FileOutputStream("input/data.xls");
workbook.write(fis);
if(fis!=null)
fis.close();
}
I think problem is at line
int rownum = 0;
this will set rowNUm to zero each time and sheet will be written from zero row
You need to persist this rowNum value if you want to append data in the sheet