I am creating a test script using RestAssured, java & Selenium. I am trying to create multiple users using POST methods by using the data provided in users.xlsx file. I am getting the exception in my utils file given below:
package utils;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class ExcelUtils {
public static FileInputStream fis;
public static FileOutputStream fos;
public static XSSFWorkbook wb;
public static XSSFSheet ws;
public static XSSFRow row;
public static XSSFCell cell;
public static int getRowCount(String xlFile, String xlSheet) throws IOException {
fis = new FileInputStream(xlFile);
wb = new XSSFWorkbook (fis);
ws = wb.getSheet(xlSheet);
int row_count = ws.getLastRowNum();
wb.close();
fis.close();
return row_count;
}
public static int getCellCount(String xlFile, String xlSheet, int row_num) throws IOException {
fis = new FileInputStream(xlFile);
wb = new XSSFWorkbook(fis);
ws = wb.getSheet(xlSheet);
int cell_count = row.getLastCellNum();
wb.close();
fis.close();
return cell_count;
}
public static String getCellData(String xlFile, String xlSheet, int row_num, int column) throws IOException {
fis = new FileInputStream(xlFile);
wb = new XSSFWorkbook(fis);
ws = wb.getSheet(xlSheet);
row = ws.getRow(row_num);
cell= row.getCell(column);
String data;
try{
DataFormatter formatter = new DataFormatter();
String cellData = formatter.formatCellValue(cell);
return cellData;
}catch (Exception e){
data = "";
}
wb.close();
fis.close();
return data;
}
public static void setCellData(String xlFile, String xlSheet, int row_num, int column, String data) throws IOException {
fis = new FileInputStream(xlFile);
wb = new XSSFWorkbook(fis);
ws = wb.getSheet(xlSheet);
row = ws.getRow(row_num);
cell= row.getCell(column);
cell.setCellValue(data);
fos= new FileOutputStream(xlFile);
wb.write(fos);
wb.close();
fis.close();
fos.close();
}
}
This is my code under #DataProvider
#DataProvider(name = "createBulkUsers")
String[][] getUserData() throws IOException {
//Read data from excel
String path = "./src/test/testdata/users.xlsx";
int row_count = getRowCount(path, "Sheet1");
int col_count = getCellCount(path, "Sheet1", 1);
String userData[][] = new String[row_count][col_count];
for (int i = 1; i <= row_count ; i++) { // for rows
for (int j = 0; j < col_count; j++) { // for columns
userData [i-1][j] = getCellData(path, "Sheet1", i, j);
}
}
return userData ;
}
Please suggest.
Related
i want to get the (valid and invalid) data from excel .xls file and apply that in my application login page.when the error message is display.i want to write failed in excel file.from my code, i can get the value from excel and apply it in my application but cant write the output in excel.i attached my code here.anyone please help me to fix this.
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.hssf.usermodel.HSSFCell;
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.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
public class exceltowrite {
public FileInputStream fis = null;
public FileOutputStream fos = null;
public HSSFWorkbook workbook = null;
public HSSFSheet sheet = null;
public HSSFRow row = null;
public HSSFCell cell = null;
String xlFilePath;
public exceltowrite(String string, String xlFilePath) throws IOException {
this.xlFilePath = xlFilePath;
fis = new FileInputStream(xlFilePath);
workbook = new HSSFWorkbook(fis);
fis.close();
}
public static void main(String[]args) throws EncryptedDocumentException, InvalidFormatException, IOException, InterruptedException {
for(int i=1;i<=29;i++) {
String u1 =exceltowrite.getdata(i,0);
String p1=exceltowrite.getdata(i,1);
WebDriver d1=new FirefoxDriver();
d1.get("http:\\www.google.com");
d1.get("napplication site");
d1.findElement(By.name("AdminLoginForm[email]")).sendKeys(u1);
d1.findElement(By.name("AdminLoginForm[password]")).sendKeys(p1);
d1.findElement(By.name("login-button")).click();
Thread.sleep(2000);
WebElement e1= d1.findElement(By.xpath("email error message path"));
String s1=e1.getText();
WebElement e2=d1.findElement(By.xpath("password error message path"));
String s2=e2.getText();
if(s1.equals("Email cannot be blank.")) {
System.out.println("emailid failed");
d1.quit();
if(s2.equals("Password cannot be blank.")) {
System.out.println("password failed");
d1.quit();
} else {
System.out.println("password pass");
d1.quit();
}
} else {
d1.quit();
}
}
}
public static String getdata(int i, int j) throws EncryptedDocumentException, InvalidFormatException, IOException {
FileInputStream fis=new FileInputStream("file path");
Workbook wb=WorkbookFactory.create(fis);
String s=wb.getSheet("Sheet1").getRow(i).getCell(j).getStringCellValue();
return s;
}
public boolean setCellData(String sheetName, int colNumber, int rowNum, String value)
{
try
{
sheet = workbook.getSheet(sheetName);
row = sheet.getRow(rowNum);
System.out.println(row);
cell = row.getCell(colNumber);
System.out.println(cell);
cell.setCellValue(value);
fos = new FileOutputStream(xlFilePath);
workbook.write(fos);
fos.close();
System.out.println("Finished");
}
catch (Exception ex)
{
ex.printStackTrace();
return false;
}
return true;
}}
}
my another class is this
public class Demo {
public static void main(String args[]) throws Exception
{
// exceltowrite at=new exceltowrite("file path");
for(int j=0;j<=29;j++){
at.setCellData("Sheet1",2,j,"failed");
}}}
public static void write() throws IOException {
String home = System.getProperty("user.home");
String downlpad = home + "\\Downloads";
File file = new File(downlpad + "\\" + "Suhit-File-to-Download.xlsx");
FileOutputStream outputStream = new FileOutputStream(file);
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("Java Books");
ArrayList<Object> bookData = new ArrayList<>();
bookData.add("Name");
bookData.add("Address");
bookData.add("Number");
XSSFRow row = sheet.createRow(0);
for (int i = 0; i < bookData.size(); i++) {
XSSFCell cell3 = row.createCell(i);
cell3.setCellValue((String) bookData.get(i));
}
workbook.write(outputStream);
workbook.close();
}
The project that I'm working on is trying to read a very large Excel file (a couple hundred columns and around 3000 rows) and recognize patterns in a series of letters. It works just fine on smaller files, but when I try to run it using this file I receive a java.lang.OutOfMemoryError: Java heap space error even when I'm only trying to analyze the first few rows. The error appears to be at Workbook wb = WorkbookFactory.create(new File(filepath));
I've tried a few of the solutions on this website, but have not come across any success. My code is as follows:
import java.awt.List;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ExcelReader {
public int Reader(File file) throws IOException, EncryptedDocumentException, InvalidFormatException {
String filepath = file.getPath();
Workbook wb = WorkbookFactory.create(new File(filepath));
XSSFSheet sheet = (XSSFSheet) wb.getSheetAt(0);
XSSFRow row;
XSSFCell cell;
ArrayList<Integer> list = new ArrayList<Integer>();
int rows;
int cols = 0;
int temp = 0;
rows = sheet.getPhysicalNumberOfRows();
for (int i = 0; i <= 1; i++) {
row = sheet.getRow(i);
if (row != null) {
temp = sheet.getRow(i).getPhysicalNumberOfCells();
if (temp > cols)
cols = temp;
}
}
for (int r = 0; r <= 60; r++) {
row = sheet.getRow(r);
if (row != null) {
for (int c = 0; c <= cols; c++) {
int numblanks = 0;
cell = row.getCell((short) c);
if (cell != null) {
//System.out.print(cell + "\t\t");
} else {
//System.out.print("\t\t");
}
if (cell != null && cell.getCellType() == XSSFCell.CELL_TYPE_STRING) {
if ("N".equals(cell.getStringCellValue())) {
for (int k = c; k <= cols; k++) {
if ("-".equals(row.getCell(k).getStringCellValue())) {
numblanks++;
continue;
}
if ("S".equals(row.getCell(c + 2 + numblanks).getStringCellValue())
|| "T".equals(row.getCell(c + 2 + numblanks).getStringCellValue())) {
list.add((int) sheet.getRow(1).getCell(c).getNumericCellValue());
break;
}
}
}
}
}
System.out.println();
}
}
System.out.println();
System.out.println("Rows: " + rows);
System.out.println("Columns: " + cols);
System.out.println(list);
return temp;
}
}
Thank you for any help you can give me!
I solved this issue before. My case was to read a 23M Excel file which contains 230k rows.
Increase maximum heap size is not a good solution. Apache poi does not have a streaming mode to read data. This non-streaming mode costs too much memory.
My solution is to convert the data to xml and then use XMLReader to parse the data.
Please check the following sample code:
protected List<Entity> parseData(InputStream in) throws Exception {
OPCPackage pkg = OPCPackage.open(in);
XSSFReader r = new XSSFReader(pkg);
SharedStringsTable sst = r.getSharedStringsTable();
XMLReader parser = fetchSheetParser(sst);
XSSFReader.SheetIterator sheets = (XSSFReader.SheetIterator) r.getSheetsData();
while (sheets.hasNext()) {
InputStream sheet = sheets.next();
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
break; // if only need to process one sheet.
}
return SheetHandler.getRawData();
}
private XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {
XMLReader parser =
XMLReaderFactory.createXMLReader();
ContentHandler handler = new SheetHandler(sst);
parser.setContentHandler(handler);
return parser;
}
private static class SheetHandler extends DefaultHandler {
private SharedStringsTable sst;
private String lastContents;
private boolean nextIsString;
private boolean nextIsInlineString;
private boolean nextIsNull;
private SheetHandler(SharedStringsTable sst) {
this.sst = sst;
rawData = new ArrayList<Entity>();
}
public static List<Entity> getRawData() {
return rawData;
}
#Override
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
}
#Override
public void endElement(String uri, String localName, String name)
throws SAXException {
}
#Override
public void characters(char[] ch, int start, int length)
throws SAXException {
lastContents += new String(ch, start, length);
}
}
}
I am trying to read few csv files which are present inside a folder and putting the absolute paths inside a list and then looping to the list and inserting data into excel in different sheets but for some reason only last loop is overwriting everything.
package excel;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
public class FileReading {
public static void csvToXLS(String filename, String sheetno) {
try {
String csvFile = filename; //csv file address
String excelFile = "E:\\test.xls"; //xlsx file address
HSSFWorkbook workBook = new HSSFWorkbook();
HSSFSheet sheet = workBook.createSheet(sheetno);
String currentLine = null;
int RowNum = 0;
BufferedReader br = new BufferedReader(new FileReader(csvFile));
while ((currentLine = br.readLine()) != null) {
String str[] = currentLine.split(",");
HSSFRow currentRow = sheet.createRow(RowNum);
RowNum++;
for (int i = 0; i < str.length; i++) {
currentRow.createCell(i).setCellValue(str[i]);
}
}
FileOutputStream fileOutputStream = new FileOutputStream(excelFile);
workBook.write(fileOutputStream);
fileOutputStream.close();
System.out.println("Done");
} catch (Exception ex) {
System.out.println(ex.getMessage() + "Exception in try");
}
}
public static List listOfFiles() {
List<String> results = new ArrayList<String>();
File[] files = new File("f:\\csv").listFiles();
for (File file : files) {
if (file.isFile()) {
results.add(file.getAbsolutePath());
}
}
return results;
}
public static void main(String[] args) {
List list = listOfFiles();
int size = list.size();
for (int i = 0; i < size; i++) {
csvToXLS(list.get(i).toString(), "sheet" + i + 1);
}
}
}
You're re-creating and saving the Workbook every time you call csvToXLS, so only the last call survives, overwriting all others.
Create the Workbook only once, before you start your for loop, passing it into csvToXLS. then that method will create a new Sheet on an existing Workbook. Then after the for loop ends, you can write out and save the Workbook.
I did this thanks for the idea #rgettman
package excel;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
public class CsvToXlx {
public static void csvToXLSX(HSSFWorkbook workBook,String filename, String sheetno) {
try {
String csvFile = filename; //csv file address
String excelFile = "E:\\test.xls"; //xlsx file address
//HSSFWorkbook workBook = new HSSFWorkbook();
HSSFSheet sheet = workBook.createSheet(sheetno);
String currentLine = null;
int RowNum = 0;
BufferedReader br = new BufferedReader(new FileReader(csvFile));
while ((currentLine = br.readLine()) != null) {
String str[] = currentLine.split(",");
HSSFRow currentRow = sheet.createRow(RowNum);
RowNum++;
for (int i = 0; i < str.length; i++) {
currentRow.createCell(i).setCellValue(str[i]);
}
}
FileOutputStream fileOutputStream = new FileOutputStream(excelFile);
workBook.write(fileOutputStream);
fileOutputStream.close();
System.out.println("Done");
} catch (Exception ex) {
System.out.println(ex.getMessage() + "Exception in try");
}
}
public static List listOfFiles() {
List<String> results = new ArrayList<String>();
File[] files = new File("f:\\csv").listFiles();
for (File file : files) {
if (file.isFile()) {
results.add(file.getAbsolutePath());
}
}
return results;
}
public static void main(String[] args) {
List list = listOfFiles();
int size = list.size();
HSSFWorkbook workBook = new HSSFWorkbook();
for (int i = 0; i < size; i++) {
csvToXLSX(workBook,list.get(i).toString(), "sheet" + i + 1);
}
}
}
I am trying to read data from excel sheet to automate my testing(with a number of login credentials). I am using a utility that I found on web. But it is not running successfully.
Here is the utility
package google;
import java.io.File;
import java.io.IOException;
import java.util.Hashtable;
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;
public class class2 {
static Sheet wrksheet;
static Workbook wrkbook =null;
static Hashtable dict= new Hashtable();
//Create a Constructor
public class2(String ExcelSheetPath) throws BiffException, IOException
{
//Initialize
wrkbook = Workbook.getWorkbook(new File(ExcelSheetPath));
//For Demo purpose the excel sheet path is hardcoded, but not recommended :)
wrksheet = wrkbook.getSheet("Sheet1");
}
//Returns the Number of Rows
public static int RowCount()
{
return wrksheet.getRows();
`enter code here` }
//Returns the Cell value by taking row and Column values as argument
public static String ReadCell(int column,int row)
{
return wrksheet.getCell(column,row).getContents();
}
//Create Column Dictionary to hold all the Column Names
public static void ColumnDictionary()
{`enter code here`
//Iterate through all the columns in the Excel sheet and store the value
for(int col=0; col <= wrksheet.getColumns();col++)
{
dict.put(ReadCell(col,0), col);
}
}
//Read Column Names
public static int GetCell(String colName)
{
try {
int value;
value = ((Integer) dict.get(colName)).intValue();
return value;
} catch (NullPointerException e) {
return (0);
}
}
}
And following is the class that calls this utility.
package google;
import java.io.IOException;
import jxl.read.biff.BiffException;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import google.class2;
public class class3 {
//Global initialization of Variables
static class2 xlsUtil;
WebDriver driver = new InternetExplorerDriver();
//Constructor to initialze Excel for Data source
public class3() throws BiffException, IOException
{
//Let's assume we have only one Excel File which holds all Testcases. Demo !!!
xlsUtil = new class2("C:/Users/admin/workspace/login.xls");
//Load the Excel Sheet Col in to Dictionary for Further use in our Test cases.
xlsUtil.ColumnDictionary();
}
#BeforeTest
public void EnvironmentalSetup()
{
System.setProperty("webdriver.chrome.driver",
"C:/Users/admin/Downloads/chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("http://192.168.1.20/dental/userlogin");
}
#Test
public void GmailLoginPage() throws InterruptedException {
//Create a for loop.. for iterate through our Excel sheet for all the test cases.
for(int rowCnt = 1;rowCnt <= xlsUtil.RowCount();rowCnt++)
{
//Enter User Name by reading data from Excel
WebElement userName = driver.findElement(By.name("UserName"));
userName.clear();
userName.sendKeys(xlsUtil.ReadCell(xlsUtil.GetCell("EmailUserName"), rowCnt));
//Enter Password
WebElement password = driver.findElement(By.name("Password"));
password.clear();
password.sendKeys(xlsUtil.ReadCell(xlsUtil.GetCell("Emailpassword"), rowCnt));
//Click on the Sign In Button
// WebElement signin = driver.findElement(By.name("signIn"));
password.submit();
//Sleep for some time,so that we can see things in action # Screen :)
Thread.sleep(2000);
}
}
}
But when I run dis cass it says 'cant instantiate google.class3
I don't get the mistake here.
Please help me run this code successfully.
FileInputStream file = newFileInputStream(newFile("C:/Users/admin/workspace/login.xls"));
//Get the workbook instance for XLS file
HSSFWorkbook workbook = new HSSFWorkbook(file);
//Get first sheet from the workbook
HSSFSheet sheet = workbook.getSheetAt(0);
//Iterate through each rows from first sheet
Iterator<Row> rowIterator = sheet.iterator();
while(rowIterator.hasNext()) {
Row row = rowIterator.next();
//For each row, iterate through each columns
Iterator<Cell> cellIterator = row.cellIterator();
while(cellIterator.hasNext()) {
Cell cell = cellIterator.next();
if(cell.getColumnIndex() == 0){
driver.findElement(By.name("UserName")).sendKeys(cell.getStringCellValue());
}
else
driver.findElement(By.name("Password")).sendKeys(cell.getStringCellValue());
}
public String getExcelData(String sheetName , int rowNum , int colNum) throws InvalidFormatException, IOException{
FileInputStream fis = new FileInputStream(filePath);
Workbook wb = WorkbookFactory.create(fis);
Sheet sh = wb.getSheet(sheetName);
Row row = sh.getRow(rowNum);
String data = row.getCell(colNum).getStringCellValue();
return data;
}
public int getRowCount(String sheetName) throws InvalidFormatException, IOException{
FileInputStream fis = new FileInputStream(filePath);
Workbook wb = WorkbookFactory.create(fis);
Sheet sh = wb.getSheet(sheetName);
int rowCount = sh.getLastRowNum()+1;
return rowCount;
}
public void setExcelData(String sheetName,int rowNum,int colNum,String data) throws InvalidFormatException, IOException{
FileInputStream fis = new FileInputStream(filePath);
Workbook wb = WorkbookFactory.create(fis);
Sheet sh = wb.getSheet(sheetName);
Row row = sh.getRow(rowNum);
Cell cel = row.createCell(colNum);
cel.setCellType(cel.CELL_TYPE_STRING);
cel.setCellValue(data);
FileOutputStream fos = new FileOutputStream(filePath);
wb.write(fos);
}
public int getcellCount(String sheetName,int rowNum) throws InvalidFormatException, IOException{
FileInputStream fis = new FileInputStream(filePath);
Workbook wb = WorkbookFactory.create(fis);
Sheet sh = wb.getSheet(sheetName);
Row row = sh.getRow(rowNum);
return row.getLastCellNum();
}
public class ExcelLIb {
public static String filePath;
public String getExcelData(String sheetName , String testID , String columnHeader) throws InvalidFormatException, IOException{
String userDir = System.getProperty("user.dir");
filePath = userDir+"\\testdata\\Test_Data.xlsx";
String data = null;
FileInputStream fis = new FileInputStream(filePath);
Workbook wb = WorkbookFactory.create(fis);
Sheet sh = wb.getSheet(sheetName);
int rowcount =getRowCount(sheetName);
for(int r=0 ; r<rowcount; r++){
Row row = sh.getRow(r);
if(row.getCell(0).getStringCellValue().toLowerCase().equals(testID.toLowerCase())){
int col = row.getLastCellNum();
for(int c=0; c<col ; c++){
if(row.getCell(c).getStringCellValue().toLowerCase().equals(columnHeader.toLowerCase())){
row = sh.getRow(r+1);
data = row.getCell(c).getStringCellValue();
break;
}
}
}
}
return data;
}
This is sort of inline w/ Writing a large ResultSet to a File but the file in question is an Excel file.
I'm using the Apache POI library to write an Excel file with a large data set retrieved from a ResultSet object. The data could range from a few thousand records to about 1 million; not sure how this translates into file system bytes in Excel format.
The following is a test code I wrote to check out the time taken to write such a large result set and also the performance implication w.r.t CPU & Memory.
protected void writeResultsetToExcelFile(ResultSet rs, int numSheets, String fileNameAndPath) throws Exception {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileNameAndPath));
int numColumns = rs.getMetaData().getColumnCount();
Workbook wb = ExcelFileUtil.createExcelWorkBook(true, numSheets);
Row heading = wb.getSheetAt(0).createRow(1);
ResultSetMetaData rsmd = rs.getMetaData();
for(int x = 0; x < numColumns; x++) {
Cell cell = heading.createCell(x+1);
cell.setCellValue(rsmd.getColumnLabel(x+1));
}
int rowNumber = 2;
int sheetNumber = 0;
while(rs.next()) {
if(rowNumber == 65001) {
log("Sheet " + sheetNumber + "written; moving onto to sheet " + (sheetNumber + 1));
sheetNumber++;
rowNumber = 2;
}
Row row = wb.getSheetAt(sheetNumber).createRow(rowNumber);
for(int y = 0; y < numColumns; y++) {
row.createCell(y+1).setCellValue(rs.getString(y+1));
wb.write(bos);
}
rowNumber++;
}
//wb.write(bos);
bos.close();
}
Not much luck with the above code. The file which is created seems to grow rapidly (~70Mb per sec). So I stopped the execution after about 10 minutes (killed the JVM when the file reaches 7Gb) and tried to open the file in Excel 2007. The moment I open it, the file size becomes 8k(!) and only the header and the first row are created. Not sure what I'm missing here.
Any ideas?
Using SXSSF poi 3.8
package example;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class SXSSFexample {
public static void main(String[] args) throws Throwable {
FileInputStream inputStream = new FileInputStream("mytemplate.xlsx");
XSSFWorkbook wb_template = new XSSFWorkbook(inputStream);
inputStream.close();
SXSSFWorkbook wb = new SXSSFWorkbook(wb_template);
wb.setCompressTempFiles(true);
SXSSFSheet sh = (SXSSFSheet) wb.getSheetAt(0);
sh.setRandomAccessWindowSize(100);// keep 100 rows in memory, exceeding rows will be flushed to disk
for(int rownum = 4; rownum < 100000; rownum++){
Row row = sh.createRow(rownum);
for(int cellnum = 0; cellnum < 10; cellnum++){
Cell cell = row.createCell(cellnum);
String address = new CellReference(cell).formatAsString();
cell.setCellValue(address);
}
}
FileOutputStream out = new FileOutputStream("tempsxssf.xlsx");
wb.write(out);
out.close();
}
}
It requires:
poi-ooxml-3.8.jar,
poi-3.8.jar,
poi-ooxml-schemas-3.8.jar,
stax-api-1.0.1.jar,
xml-apis-1.0.b2.jar,
xmlbeans-2.3.0.jar,
commons-codec-1.5.jar,
dom4j-1.6.1.jar
Useful link
Oh. I think you're writing the workbook out 944,000 times. Your wb.write(bos) call is in the inner loop. I'm not sure this is quite consistent with the semantics of the Workbook class? From what I can tell in the Javadocs of that class, that method writes out the entire workbook to the output stream specified. And it's gonna write out every row you've added so far once for every row as the thing grows.
This explains why you're seeing exactly 1 row, too. The first workbook (with one row) to be written out to the file is all that is being displayed - and then 7GB of junk thereafter.
Unless you have to write formulas or formatting you should consider writing out a .csv file. Infinitely simpler, infinitely faster, and Excel will do the conversion to .xls or .xlsx automatically and correctly by definition.
You can using SXSSFWorkbook implementation of Workbook, if you use style in your excel ,You can caching style by Flyweight Pattern to improve your performance.
You can increase the performance of excel export by following these steps:
1) When you fetch data from database, avoid casting the result set to the list of entity classes. Instead assign it directly to List
List<Object[]> resultList =session.createSQLQuery("SELECT t1.employee_name, t1.employee_id ... from t_employee t1 ").list();
instead of
List<Employee> employeeList =session.createSQLQuery("SELECT t1.employee_name, t1.employee_id ... from t_employee t1 ").list();
2) Create excel workbook object using SXSSFWorkbook instead of XSSFWorkbook and create new row using SXSSFRow when the data is not empty.
3) Use java.util.Iterator to iterate the data list.
Iterator itr = resultList.iterator();
4) Write data into excel using column++.
int rowCount = 0;
int column = 0;
while(itr.hasNext()){
SXSSFRow row = xssfSheet.createRow(rowCount++);
Object[] object = (Object[]) itr.next();
//column 1
row.setCellValue(object[column++]); // write logic to create cell with required style in setCellValue method
//column 2
row.setCellValue(object[column++]);
itr.remove();
}
5) While iterating the list, write the data into excel sheet and remove the row from list using remove method. This is to avoid holding unwanted data from the list and clear the java heap size.
itr.remove();
For now I took #Gian's advice & limited the number of records per Workbook to 500k and rolled over the rest to the next Workbook. Seems to be working decent. For the above configuration, it took me about 10 mins per workbook.
I updated BigGridDemo to support multiple sheets.
BigExcelWriterImpl.java
package com.gdais.common.apache.poi.bigexcelwriter;
import static com.google.common.base.Preconditions.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.io.FilenameUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
public class BigExcelWriterImpl implements BigExcelWriter {
private static final String XML_ENCODING = "UTF-8";
#Nonnull
private final File outputFile;
#Nullable
private final File tempFileOutputDir;
#Nullable
private File templateFile = null;
#Nullable
private XSSFWorkbook workbook = null;
#Nonnull
private LinkedHashMap<String, XSSFSheet> addedSheets = new LinkedHashMap<String, XSSFSheet>();
#Nonnull
private Map<XSSFSheet, File> sheetTempFiles = new HashMap<XSSFSheet, File>();
BigExcelWriterImpl(#Nonnull File outputFile) {
this.outputFile = outputFile;
this.tempFileOutputDir = outputFile.getParentFile();
}
#Override
public BigExcelWriter createWorkbook() {
workbook = new XSSFWorkbook();
return this;
}
#Override
public BigExcelWriter addSheets(String... sheetNames) {
checkState(workbook != null, "workbook must be created before adding sheets");
for (String sheetName : sheetNames) {
XSSFSheet sheet = workbook.createSheet(sheetName);
addedSheets.put(sheetName, sheet);
}
return this;
}
#Override
public BigExcelWriter writeWorkbookTemplate() throws IOException {
checkState(workbook != null, "workbook must be created before writing template");
checkState(templateFile == null, "template file already written");
templateFile = File.createTempFile(FilenameUtils.removeExtension(outputFile.getName())
+ "-template", ".xlsx", tempFileOutputDir);
System.out.println(templateFile);
FileOutputStream os = new FileOutputStream(templateFile);
workbook.write(os);
os.close();
return this;
}
#Override
public SpreadsheetWriter createSpreadsheetWriter(String sheetName) throws IOException {
if (!addedSheets.containsKey(sheetName)) {
addSheets(sheetName);
}
return createSpreadsheetWriter(addedSheets.get(sheetName));
}
#Override
public SpreadsheetWriter createSpreadsheetWriter(XSSFSheet sheet) throws IOException {
checkState(!sheetTempFiles.containsKey(sheet), "writer already created for this sheet");
File tempSheetFile = File.createTempFile(
FilenameUtils.removeExtension(outputFile.getName())
+ "-sheet" + sheet.getSheetName(), ".xml", tempFileOutputDir);
Writer out = null;
try {
out = new OutputStreamWriter(new FileOutputStream(tempSheetFile), XML_ENCODING);
SpreadsheetWriter sw = new SpreadsheetWriterImpl(out);
sheetTempFiles.put(sheet, tempSheetFile);
return sw;
} catch (RuntimeException e) {
if (out != null) {
out.close();
}
throw e;
}
}
private static Function<XSSFSheet, String> getSheetName = new Function<XSSFSheet, String>() {
#Override
public String apply(XSSFSheet sheet) {
return sheet.getPackagePart().getPartName().getName().substring(1);
}
};
#Override
public File completeWorkbook() throws IOException {
FileOutputStream out = null;
try {
out = new FileOutputStream(outputFile);
ZipOutputStream zos = new ZipOutputStream(out);
Iterable<String> sheetEntries = Iterables.transform(sheetTempFiles.keySet(),
getSheetName);
System.out.println("Sheet Entries: " + sheetEntries);
copyTemplateMinusEntries(templateFile, zos, sheetEntries);
for (Map.Entry<XSSFSheet, File> entry : sheetTempFiles.entrySet()) {
XSSFSheet sheet = entry.getKey();
substituteSheet(entry.getValue(), getSheetName.apply(sheet), zos);
}
zos.close();
out.close();
return outputFile;
} finally {
if (out != null) {
out.close();
}
}
}
private static void copyTemplateMinusEntries(File templateFile,
ZipOutputStream zos, Iterable<String> entries) throws IOException {
ZipFile templateZip = new ZipFile(templateFile);
#SuppressWarnings("unchecked")
Enumeration<ZipEntry> en = (Enumeration<ZipEntry>) templateZip.entries();
while (en.hasMoreElements()) {
ZipEntry ze = en.nextElement();
if (!Iterables.contains(entries, ze.getName())) {
System.out.println("Adding template entry: " + ze.getName());
zos.putNextEntry(new ZipEntry(ze.getName()));
InputStream is = templateZip.getInputStream(ze);
copyStream(is, zos);
is.close();
}
}
}
private static void substituteSheet(File tmpfile, String entry,
ZipOutputStream zos)
throws IOException {
System.out.println("Adding sheet entry: " + entry);
zos.putNextEntry(new ZipEntry(entry));
InputStream is = new FileInputStream(tmpfile);
copyStream(is, zos);
is.close();
}
private static void copyStream(InputStream in, OutputStream out) throws IOException {
byte[] chunk = new byte[1024];
int count;
while ((count = in.read(chunk)) >= 0) {
out.write(chunk, 0, count);
}
}
#Override
public Workbook getWorkbook() {
return workbook;
}
#Override
public ImmutableList<XSSFSheet> getSheets() {
return ImmutableList.copyOf(addedSheets.values());
}
}
SpreadsheetWriterImpl.java
package com.gdais.common.apache.poi.bigexcelwriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Calendar;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.util.CellReference;
class SpreadsheetWriterImpl implements SpreadsheetWriter {
private static final String XML_ENCODING = "UTF-8";
private final Writer _out;
private int _rownum;
SpreadsheetWriterImpl(Writer out) {
_out = out;
}
#Override
public SpreadsheetWriter closeFile() throws IOException {
_out.close();
return this;
}
#Override
public SpreadsheetWriter beginSheet() throws IOException {
_out.write("<?xml version=\"1.0\" encoding=\""
+ XML_ENCODING
+ "\"?>"
+
"<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">");
_out.write("<sheetData>\n");
return this;
}
#Override
public SpreadsheetWriter endSheet() throws IOException {
_out.write("</sheetData>");
_out.write("</worksheet>");
closeFile();
return this;
}
/**
* Insert a new row
*
* #param rownum
* 0-based row number
*/
#Override
public SpreadsheetWriter insertRow(int rownum) throws IOException {
_out.write("<row r=\"" + (rownum + 1) + "\">\n");
this._rownum = rownum;
return this;
}
/**
* Insert row end marker
*/
#Override
public SpreadsheetWriter endRow() throws IOException {
_out.write("</row>\n");
return this;
}
#Override
public SpreadsheetWriter createCell(int columnIndex, String value, int styleIndex)
throws IOException {
String ref = new CellReference(_rownum, columnIndex).formatAsString();
_out.write("<c r=\"" + ref + "\" t=\"inlineStr\"");
if (styleIndex != -1) {
_out.write(" s=\"" + styleIndex + "\"");
}
_out.write(">");
_out.write("<is><t>" + value + "</t></is>");
_out.write("</c>");
return this;
}
#Override
public SpreadsheetWriter createCell(int columnIndex, String value) throws IOException {
createCell(columnIndex, value, -1);
return this;
}
#Override
public SpreadsheetWriter createCell(int columnIndex, double value, int styleIndex)
throws IOException {
String ref = new CellReference(_rownum, columnIndex).formatAsString();
_out.write("<c r=\"" + ref + "\" t=\"n\"");
if (styleIndex != -1) {
_out.write(" s=\"" + styleIndex + "\"");
}
_out.write(">");
_out.write("<v>" + value + "</v>");
_out.write("</c>");
return this;
}
#Override
public SpreadsheetWriter createCell(int columnIndex, double value) throws IOException {
createCell(columnIndex, value, -1);
return this;
}
#Override
public SpreadsheetWriter createCell(int columnIndex, Calendar value, int styleIndex)
throws IOException {
createCell(columnIndex, DateUtil.getExcelDate(value, false), styleIndex);
return this;
}
#Override
public SpreadsheetWriter createCell(int columnIndex, Calendar value)
throws IOException {
createCell(columnIndex, value, -1);
return this;
}
}