I have an Excel spreadsheet that has the first sheet designated for the raw data. There are 3 more sheets that are coded to transform and format the data from the raw sheet. The fifth sheet has the final output.
How can I use Java:
load the data from the CSV file into the first sheet of the excel file?
save the data from the 5th sheet into the new CSV file.
Also, if the original CSV has thousands of rows, I assume the multi-sheet transformations would take some time before the 5th sheet gets all the final data - is there a way to know?
I would follow this approach:
Load the specific .csv file and prepare to read it with Java
Load the .xlsx file and change it according to your requirements and the data that you get from the .csv file. A small example of how an excel file is changed with Apache POI can be seen below:
try
{
HashMap<Integer, ArrayList<String>> fileData; // This for example keeps the data from the csv in this form ( 0 -> [ "Column1", "Column2" ]...)
// Working with the excel file now
FileInputStream file = new FileInputStream("Data.xlsx");
XSSFWorkbook workbook = new XSSFWorkbook(file); // getting the Workbook
XSSFSheet sheet = workbook.getSheetAt(0);
Cell cell = null;
AtomicInteger row = new AtomicInteger(0);
fileData.forEach((key, csvRow) ->
{
//Update the value of the cell
//Retrieve the row and check for null
HSSFRow sheetRow = sheet.getRow(row);
if(sheetRow == null)
{
sheetRow = sheet.createRow(row);
}
for (int i = 0; i < csvRow.size(); i++)
{
//Update the value of cell
cell = sheetRow.getCell(i);
if(cell == null){
cell = sheetRow.createCell(i);
}
cell.setCellValue(csvRow.get(i));
}
});
file.close();
FileOutputStream outFile =new FileOutputStream(new File("Data.xlsx"));
workbook.write(outFile);
outFile.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
After saving the .xlsx file, you can create the .csv file by following this question.
Related
I am trying to write an excel file using java. I'm looking for just simply a column with one username per row right now, and then will build upon this later once I understand what is going a bit better. I get a zip file instead of the expected excel file, and it contains docProps, _rels, xl, and [Content_Types].xml. I don't understand how to open this zip file as though it is an excel file. I have not had luck finding the answer as all the tutorials I see show it to be a straight forward excel file, not a zip file. Is it a configuration I'm missing or is it to do with linux?
Here's my code, and what I end up with:
private void createExcelSheet(Assignment assignment) throws FileNotFoundException {
String excelFilePath = Configuration.DIRECTORY_ROOT+"/tests/"+assignment.getAssn_number()+"/gradebook-"+assignment.getAssn_number();
int rowNum = 0;
int col = 0;
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet spreadsheet = workbook.createSheet(assignment.getAssn_number()+" Grades ");
XSSFRow row = spreadsheet.createRow(rowNum);
Cell cell;
for (User user : userService.getUsers() ) {
row = spreadsheet.createRow(rowNum);
cell = row.createCell(rowNum);
cell.setCellValue(user.getStudent_id());
rowNum++;
}
try (FileOutputStream fos = new FileOutputStream(excelFilePath)) {
workbook.write(fos);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
I am working with a large excel file ( larger than 40 Mb , more than 100k rows and 50 columns ). I am successfully reading it using POI ( 3.10.1 version ) event stream and then doing some calculation and storing result into a List.
Now I have to append this List as a column in the same file. In this part I am facing issue.
I have tried to achieve this by using the below code
FileInputStream excelFile = new FileInputStream(new File(pathToFile));
Workbook workbook = new XSSFWorkbook(excelFile);
Sheet datatypeSheet = workbook.getSheetAt(0); // Get first sheet
Iterator<Row> iterator = datatypeSheet.iterator();
int i=0;
while (iterator.hasNext()) { // Loop over each row
Row currentRow = iterator.next();
Cell cell = currentRow.createCell(currentRow.getLastCellNum());
cell.setCellType(Cell.CELL_TYPE_STRING);
if(currentRow.getRowNum() == 0)
cell.setCellValue("OUTPUT-COLUMN"); // set column header for the new column
else {
cell.setCellValue(list.get(i)); // list contains the output to populate in new column
i++;
}
}
FileOutputStream fos = new FileOutputStream(new File(pathToOutput));
workbook.write(fos);
fos.close();
It is working fine with smaller files But the issue is that I am getting Out of memory for the larger files. Now I tried to modify this and use SXSSF in place of XSFF to get over the memory issue (See below code). But while testing even for smaller files I am getting output file same as the input file.
FileInputStream excelFile = new FileInputStream(new File(pathToFile));
XSSFWorkbook xwb = new XSSFWorkbook(inputStream);
inputStream.close();
SXSSFWorkbook wb = new SXSSFWorkbook(xwb,100);
wb.setCompressTempFiles(true);
SXSSFSheet sh = (SXSSFSheet) wb.getSheetAt(0);
Iterator<Row> iterator = datatypeSheet.iterator();
int i=0;
while (iterator.hasNext()) { // Loop over each row
Row currentRow = iterator.next();
Cell cell = currentRow.createCell(currentRow.getLastCellNum());
cell.setCellType(Cell.CELL_TYPE_STRING);
if(currentRow.getRowNum() == 0)
cell.setCellValue("OUTPUT-COLUMN"); // set column header for the new column
else {
cell.setCellValue(list.get(i)); // list contains the output to populate in new column
i++;
}
}
FileOutputStream fos = new FileOutputStream(new File(pathToOutput));
wb.write(fos);
fos.close();
Using a db is not suitable in my use case and i want to avoid using a temporary data structure to hold data for writing due to memory constraint.
Is there a way to write in output workbook while streaming ? Here is the code that I am using to read using POI Streaming API
private class ExcelData implements SheetContentsHandler {
LinkedHashMap<Strin, String> rowMap;
public void startRow(int rowNum) {
}
public void endRow(int rowNum) {
// Process the row
// Handle write to output workbook ??
}
public void cell(String cellReference, String formattedValue,
XSSFComment comment) {
// Save current row in rowMap ( column name => cell value )
}
public void headerFooter(String text, boolean isHeader, String tagName)
{
}
}
It is not possible to add column to existing workbook using POI SXSSF. It only allows addition of new rows.
The only solution is to read the existing workbook and write to a new workbook with the added column.
To achieve this we can store the rows in a data structure or database in the endrow() method and then use the persisted data to write a new workbook.
I am using Apache POI 3.17 to create xlsx files and filling it with data from the db. The file gets created fine but when I try to open it, I get 'incompatible format' error even though when I inspect the file, I can see that it is a Microsoft spreadsheet file. I looked at here,here and here and tried all these examples but didn't help and I don't know where the problem is. Here is my file creation code:
File excelFile = new File("C:\\myFile.xlsx"); //a new file to be created
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("Sheet1");
Row row = sheet.createRow(rowIndex);
Cell cell;
//some font and style creation
for(String eachHeader : headers) {
cell = row.createCell(cellIndex);
cell.setCellValue(eachHeader);
cell.setCellStyle(headerStyle);
cellIndex++;
}
//some more row and cell creation
try {
//finally try to write all this content into the excel file
OutputStream out = new FileOutputStream(excelFile);
workbook.write(out);
out.close();
logger.debug("Worksheet created: " + excelFile.getAbsolutePath());
}catch(Exception exc) {
logger.error("Error occured while creating or writing to the excel file: " + exc.getMessage());
}
Again, the file is created fine with some data in it as I can see that the size is not 0, but just cannot open it, why??
I have fetched the value from the textbox and stored in a string. Now i want to write this value stored in string into the column named as 'Username' in the excel file.
E.G: Fetched the Username from the textbox as 'Test1' and want to write this in the column 'Username' of the Excel. I am using POI to write excel file using Selenium.
hi please implement the logic like below
public static void writeExcel(String filePath,String fileName,String sheetName,String[] dataToWrite) throws IOException{
//Create a object of File class to open xlsx file
File file = new File(filePath+"\\"+fileName);
//Create an object of FileInputStream class to read excel file
FileInputStream inputStream = new FileInputStream(file);
Workbook Workbook = null;
//Find the file extension by spliting file name in substing and getting only extension name
String fileExtensionName = fileName.substring(fileName.indexOf("."));
//Check condition if the file is xlsx file
if(fileExtensionName.equals(".xlsx")){
//If it is xlsx file then create object of XSSFWorkbook class
Workbook = new XSSFWorkbook(inputStream);
}
//Check condition if the file is xls file
else if(fileExtensionName.equals(".xls")){
//If it is xls file then create object of XSSFWorkbook class
Workbook = new HSSFWorkbook(inputStream);
}
//Read excel sheet by sheet name
Sheet sheet = Workbook.getSheet(sheetName);
//Get the current count of rows in excel file
int rowCount = sheet.getLastRowNum()-sheet.getFirstRowNum();
//Get the first row from the sheet
Row row = sheet.getRow(0);
//Create a new row and append it at last of sheet
Row newRow = sheet.createRow(rowCount+1);
//Create a loop over the cell of newly created Row
for(int j = 0; j < row.getLastCellNum(); j++){
//Fill data in row
Cell cell = newRow.createCell(j);
cell.setCellValue(dataToWrite[j]);
}
//Close input stream
inputStream.close();
//Create an object of FileOutputStream class to create write data in excel file
FileOutputStream outputStream = new FileOutputStream(file);
//write data in the excel file
Workbook.write(outputStream);
//close output stream
outputStream.close();
}
Now call the above in main method like below
public static void main(String[] args) {
// TODO Auto-generated method stub
WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
String valueToWrite = "test 1";
//Create an object of current class
WriteExcelFile objExcelFile = new WriteExcelFile();
//Write the file using file name , sheet name and the data to be filled
objExcelFile.writeExcel(System.getProperty("user.dir")+"\\src\\excelExportAndFileIO","ExportExcel.xlsx","ExcelDemo",valueToWrite);
}
You need to know column number of "Username" column in the excel sheet. Once you know that then it will be easy to write value of String that you captured from webpage. You can take below approach -
File excelFile = new File("C:\\path\\of\\excel\\file\\excel.xlsx");
String cellNo = 3; //column number of "UserName" column
String rowNo = 1; // row number
String userName = "Test1"; // username fetched from textbox
FileInputStream fis = new FileInputStream(excelFile);
XSSFWorkbook workbook = (XSSFWorkbook) WorkbookFactory.create(fis);
XSSFSheet sheet = workbook.getSheetAt(0);
Row row = sheet.getRow(rowNo);
row.createCell(cellNo).setCellValue(userName);
fis.close();
FileOutputStream fos = new FileOutputStream(excelFile);
workbook.write(fos);
fos.close();
This is very simple approach just for this purpose and is not generalized one for any other task.
You can take a look at simple script that reads from a excel sheet and writes back to same excel sheet using Apache POI, here.
Regards,
Punkaaj
I have a java program that prints 1000 integer values each I run it. I want to copy the output to an excel file each time I run the program. I want to output the first run in the first column in excel file and then copy the next runs in the subsequent columns in the same excel file. For example:
Run: 1
value1
value2
.
.
value1000
Run:2
value1
value2
.
.
value1000
I want the first output in the first column of an excel file and the second output in the second column
Here is my code:
int rownum=1;
int cellnum=1;
File file;
HSSFWorkbook workbook;
HSSFSheet sheet;
HSSFRow row;
HSSFCell cell;
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("Sample sheet");
public void writeOutput(double meandispersion) {
String dispersion = Double.toString(meandispersion);
HSSFRow row = sheet.createRow(rownum++);
HSSFCell cell = row.createCell(cellnum);
cell.setCellValue("dispersion");
try {
FileOutputStream out = new FileOutputStream("newFile.xls");
workbook.write(out);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
There are a total of 1000 time steps in the main code and in each time step this method is called and the value of meandispersion is passed to it. It prints the 1000 values in 1000 rows in the first column. The problem is that when I run the program second time I want to copy the 1000 values in the second column, for third run 3rd column and so on. Currently it is not appending the values, it overwrites the entire file. Can anyone point out the problem?
You have to read the existing file, append your new output to the existing data yourself (in correct column and then write it to the file.
Right now you are not reading the file at all, which would overwrite the existing contents.
Hope this helps.
POI's Quick Guide aka the "Busy Developers' Guide to HSSF and XSSF Features" contains lots of code snippets, including one that talks about opening an existing workbook, and reading and writing and saving the modified workbook (example verbatim copied from that page, added some comments):
InputStream inp = new FileInputStream("workbook.xls");
// notice how the Workbook must be constructed from the existing file
Workbook wb = WorkbookFactory.create(inp);
// Navigating in POI always follows the same logic:
// 1. grab a sheet
// 2. grab a row from that sheet
// 3. grab a cell from that row
Sheet sheet = wb.getSheetAt(0);
Row row = sheet.getRow(2);
Cell cell = row.getCell(3);
// a condition like the one that follows will be needed to know in what column
// you have to write your data:
if (cell == null)
cell = row.createCell(3);
cell.setCellType(Cell.CELL_TYPE_STRING);
cell.setCellValue("a test");
// Write the output to a file
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();
That, and the other examples on that page should get you up to speed quickly.