Apache POI: content in excel file gets corrupted - java

I am writing a method which writes to an Excel file. Before calling I create a Workbook and a Sheet. The code executes without any errors, but when opening the created Excel file I get the message: We found a problem with some content in...
My method looks like this:
public void writeToCell(int rowNumber, int cellNumber, Double content) {
Row row = sheet.createRow(rowNumber);
Cell cell = row.createCell(cellNumber);
cell.setCellValue(content);
try (FileOutputStream outputStream = new FileOutputStream(month + ".xlsx", true)) {
workbook.write(outputStream);
outputStream.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
This is how I call the method:
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet(month);
writeToCell(25, 4, 0.0);
writeToCell(25, 6, 23.32);

You shouldn't append data to Excel Workbook explicitly, which also point by #Axel in his comment
try (FileOutputStream outputStream = new FileOutputStream(month + ".xlsx", true))
instead
try (FileOutputStream outputStream = new FileOutputStream(month + ".xlsx"))
For side note,
writeToCell(25, 4, 0.0);
writeToCell(25, 6, 23.32);
Last call of writeToCell will overwrite the previous value of same 25th row. As, you are create new Row in each call
Row row = sheet.createRow(rowNumber);

I had also that error, it happened that in some cells the cell content type and the cell value didn't match.

Related

Is there a way to copy/duplicate excel files with java?

I am trying to write a program where I have to either
create an exel file and insert a table (and eventually data) into it, OR
duplicate a template exel file that I have made, and copy that over to a new directory to use.
I have gotten the 'duplicate' part working, but I cannot open the duplicated file (It says the file format/extension is not valid).
This is the code:
try {
var template = new RandomAccessFile(App.NAME+".xlsx", "rw");
var copy = new RandomAccessFile(App.data.getFilePath()+App.NAME+".xlsx", "rw");
var sourceChannel = template.getChannel();
var destinationChannel = copy.getChannel();
destinationChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
System.out.println("Successfully created exel file");
} catch (IOException e) {
System.err.println("Error creating exel file: " + e.getMessage());
}
Does anyone know what I should do to fix this?
Thanks in advance.
The following example creates an Excel File named example.xls. The file has a table with two columns ( name, job ) and one row (bayrem, developer).
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("Persons");
sheet.setColumnWidth(0, 6000); //style
sheet.setColumnWidth(1, 4000);//style
Row header = sheet.createRow(0);
CellStyle headerStyle = workbook.createCellStyle();//style
headerStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex());//style
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);//style
XSSFFont font = ((XSSFWorkbook) workbook).createFont();//style
font.setFontName("Arial");//style
font.setFontHeightInPoints((short) 16);//style
font.setBold(true);//style
headerStyle.setFont(font);//style
Cell headerCell = header.createCell(0);
headerCell.setCellValue("Name");
headerCell.setCellStyle(headerStyle);//style
headerCell = header.createCell(1);
headerCell.setCellValue("Job");
headerCell.setCellStyle(headerStyle);//style
CellStyle style = workbook.createCellStyle();//style
style.setWrapText(true);//style
Row row = sheet.createRow(2);
Cell cell = row.createCell(0);
cell.setCellValue("Bayrem");
cell.setCellStyle(style);//style
cell = row.createCell(1);
cell.setCellValue("Developer");
cell.setCellStyle(style);//style
File currDir = new File(".");
String path = currDir.getAbsolutePath();
String fileLocation = path.substring(0, path.length() - 1) + "example.xlsx";
FileOutputStream outputStream = new FileOutputStream(fileLocation);
workbook.write(outputStream);
workbook.close();
This is all you need for a copy, the language level has to be 7 or higher
import java.io.IOException;
import java.nio.file.*;
public class ExcelCopy {
public static void main(String[] args) {
FileSystem system = FileSystems.getDefault();
Path original = system.getPath("C:\\etc\\etc\\Desktop\\ExcelTestOne.xlsx");
Path target = system.getPath("C:\\etc\\etc\\Desktop\\ExcelCopy.xlsx");
try {
// Throws an exception if the original file is not found.
Files.copy(original, target, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
System.out.println("ERROR");
}
}
}
original post is here,I check that it worked for you.
How to copy excel file?

Unable to write and save XLSM file with Apache POI

I have an existing XLSM file, in which I try to write data with use of Apache POI.
String File = GlobalVariables.XLSM;
try {
Workbook workbook;
workbook = new XSSFWorkbook(OPCPackage.open(GlobalVariables.XLSM));
Sheet sheet = workbook.getSheetAt(0);
Row row = sheet.createRow(recordcount+5);
Cell cell;
cell = row.createCell(GlobalVariables.testID);
cell.setCellValue(recordcount);
FileOutputStream out = new FileOutputStream(new File(File));
workbook.write(out);
out.close();
System.out.println("Data was written in XLSM");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (InvalidFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
I got error message:
org.apache.poi.ooxml.POIXMLException: java.io.EOFException: Unexpected
end of ZLIB input stream
Problem it not related to GZIPinStream and GZIPOutputStream.
UPDATE 2019.06.04.
I modified code, but still getting error:
try {
FileInputStream file = new FileInputStream(GlobalVariables.XLSM);
XSSFWorkbook workbook = new XSSFWorkbook(file);
XSSFSheet sheet = workbook.getSheetAt(0);
XSSFRow row = sheet.createRow(recordcount+4);
Cell cell;
cell = row.createCell(GlobalVariables.testID);
cell.setCellValue(recordcount+1);
file.close();
FileOutputStream out = new FileOutputStream(new File(GlobalVariables.XLSM));
workbook.write(out);
out.flush();
out.close();
workbook.close();
System.out.println("Data was written");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Error message:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<recoveryLog xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<logFileName>error066080_01.xml</logFileName>
<summary>Error in file (C:\_privat\completeReport.xlsm)</summary>
<removedRecords>
<removedRecord>/xl/worksheets/sheet1.xml</removedRecord>
<removedRecord>/xl/calcChain.xml</removedRecord>
</removedRecords>
</recoveryLog>
Nearly every time you stumble upon an error opening a workbook that you created by code, the reason is some not properly closed resource. Unfortunately, I experienced that a lot of times ;-)
In my cases, I could resolve the issue by the following sequence of actions (order matters):
write the workbook: workbook.write(out);
force the FileOutputStream to empty all used buffers: out.flush();
close the FileOutputStream: out.close();
close the workbook: workbook.close();
This is how I would add the missing actions to your code:
try {
Workbook workbook;
workbook = new XSSFWorkbook(OPCPackage.open(GlobalVariables.XLSM));
Sheet sheet = workbook.getSheetAt(0);
Row row = sheet.createRow(recordcount + 5);
Cell cell;
cell = row.createCell(GlobalVariables.testID);
cell.setCellValue(recordcount);
FileOutputStream out = new FileOutputStream(new File(File));
// 1. write the workbook
workbook.write(out);
// 2. force the FileOutputStream to write everything out before closing it
out.flush();
// 3. then close the FileOutputStream
out.close();
// 4. finally close the workbook
workbook.close();
System.out.println("Data was written in XLSM");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (InvalidFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Please note that flushing the FileOutputStream might not always be necessary, but it was mentioned in several best-practice tutorials concerning apache-poi, so I decided to use it my code.
This works for me, I hope it will do so for you as well.
EDIT (OP asked for my example code in a comment below)
This is an independent example for reading and extending an XSSFWorkbook. It is all just in the main method, but at least commented ;-)
You have to change the path to the workbook, which is basically a String in this example and becomes a java.nio.Path afterwards.
public class PoiMain {
public static void main(String[] args) {
/*
* Setup:
* An existing xlsx file with a first sheet containing 6 columns and 1 row.
* The row has 6 filled cells with the values
* cell 1 (index 0): There
* cell 2 (index 1): is
* cell 3 (index 2): a
* cell 4 (index 3): house
* cell 5 (index 4): in
* cell 6 (index 5): New Orleans
*
* Task:
* Write the words "they", "call", "it", "the", "rising", "sun"
* in the cells below.
*/
// define the (correct) path to the workbook
String pathToFile = "Y:\\our\\path\\to\\the\\Test-Workbook.xlsx"; // you can use an xlsm here, too
// create a Path object
Path filePath = Paths.get(pathToFile);
// declare a workbook
XSSFWorkbook workbook;
try {
/*
* READING from the .xlsx file:
*/
FileInputStream in = new FileInputStream(filePath.toFile());
workbook = XSSFWorkbookFactory.createWorkbook(in);
XSSFSheet sheet = workbook.getSheetAt(0);
// read all the cells of the first row and print their content
for (int i = 0; i < sheet.getPhysicalNumberOfRows(); i++) {
XSSFRow row = sheet.getRow(i);
for (int j = 0; j < row.getPhysicalNumberOfCells(); j++) {
XSSFCell cell = row.getCell(j);
System.out.println(cell.getStringCellValue());
}
}
/*
* WRITING to the .xlsx file already read
*/
// create some meaningful words to be added to some cells in the workbook
List<String> wordsToBeWritten = Arrays.asList("they", "call", "it", "the", "rising", "sun");
FileOutputStream out = new FileOutputStream(filePath.toAbsolutePath().toString());
sheet = workbook.getSheetAt(0);
XSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows());
// create new cells and write the words into them
for (int i = 0; i < wordsToBeWritten.size(); i++) {
XSSFCell cell = row.createCell(i);
cell.setCellValue(wordsToBeWritten.get(i));
}
// close the FileInputStream
in.close();
// write the workbook using the FileOutputStream
workbook.write(out);
// force the FileOutputStream to write everything until it is empty
out.flush();
// close the FileOutputStream
out.close();
// close the workbook.
workbook.close();
} catch (FileNotFoundException e) {
System.err.println(
"The file \"" + filePath.toAbsolutePath().toString() + "\" could not be found.");
e.printStackTrace();
} catch (IOException e) {
System.err.println("Error while reading the file \"" + filePath.toAbsolutePath().toString() + "\"");
e.printStackTrace();
} catch (InvalidFormatException e) {
System.out.println(
"The file \"" + filePath.toAbsolutePath().toString() + "\" has an invalid format(ting)");
e.printStackTrace();
} catch (EmptyFileException e) {
System.err.println("The supplied file \"" + filePath.toAbsolutePath().toString() + "\" is empty.");
e.printStackTrace();
}
}

Create .csv file with Apache POI doesn't work

I need to create a file .csv with apache-poi but this file is empty. For this example I want to create only header about this file so I do:
public byte[]...(File save_file) {
Workbook workbook = null;
Sheet sheet = null;
FileOutputStream outputStream=null;
try {
workbook = new HSSFWorkbook();
sheet = workbook.createSheet();
createHeader(0,sheet);
outputStream = new FileOutputStream(save_file);
workbook.write(outputStream);
} catch (Exception exception) {
log.error("ERROR", exception);
} finally {
}
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byteArrayOutputStream.writeTo(outputStream);
log.info("SOTTO BYTE "+byteArrayOutputStream.toByteArray().length);
return byteArrayOutputStream.toByteArray();
}
and after the method "create_header":
private static void createHeader(int rowPosition,Sheet sheet) {
Row row = sheet.createRow(rowPosition);
Cell cell = row.createCell(1);
cell.setCellValue("DATE");
cell = row.createCell(2);
cell.setCellValue("EMAIL");
}
The problem is the file is empty. In the first method I need to return the byte[] that represents the csv file. Anyone can help me?

Excel file is not printed out completely

I am using JACOB to print out the Excel file. This file is created by means of Apache POI. When I save the file or send it to Outlook, everything is OK, the file contains all sheets. But when I send the file to shared printer, it starts to print, but then show the error: Error - Sent to printer. The size of a printing job is about 230 kB, so it should not be too big.
UPDATE: I was able to print out the file when I did not update it before printing. But now by pressing the button "Print out" I has to mark cells, which contains values outside the limits, with red color and only after that call the printing function.
UPDATE2: I converted Excel file into PDF and printed it out using Apache PDFBox - still the same problem. No errors in Java, some sheets from the document are printed and then printer error occurs: Error-Sent to printer.
UPDATE3: I added a function, which I use to fill in the Excel sheets.
Where is a problem? Below you can find a code for printing function:
public class AppExcelPrinter {
private ActiveXComponent excel;
private Dispatch workbooks;
private Variant workbook;
public AppExcelPrinter() { }
public synchronized void print(String filename, String printer) {
try {
ComThread.InitMTA();
excel = new ActiveXComponent("Excel.Application"); //we are going to listen to events on Application
excel.setProperty("Visible", new Variant(false)); //the file will be invisible during printing
workbooks = excel.getProperty("WorkBooks").toDispatch();
workbook = Dispatch.callN(workbooks, "Open", new Object[] { filename });
Variant From =new Variant(1);
Variant To =new Variant(6); //I have 6 sheets in my Excel file
Variant Copies =new Variant(1);
Variant Preview =new Variant(false);
Variant ActivePrinter =new Variant(printer);
Variant PrintToFile = new Variant(false);
Variant Collate = new Variant(false);
Object[] args=new Object[]{From, To, Copies, Preview, ActivePrinter, PrintToFile, Collate};
Dispatch.call(Dispatch.get(workbook.toDispatch(), "Worksheets").toDispatch(), "PrintOut", args);
try {
Thread.sleep(100);}// the sleep is required to let everything clear out after the quit
catch (InterruptedException e) {
e.printStackTrace();}}
finally {
Variant f = new Variant(false);
Dispatch.call(workbook.toDispatch(), "Close", f);
excel.invoke("Quit", new Variant[] {});
ComThread.Release(); }}
}
Function to fill in the sheets:
Path original = Paths.get("");
String original1=original.toAbsolutePath().toString();
String original2=original1+"\\example.xlsx";
Path path1 = Paths.get(original2);
String target = original1+"\\temp\\temp.xlsx";
Path path2 = Paths.get(target);
try { // Copy template, which will be filled in
Files.copy(path1, path2, StandardCopyOption.REPLACE_EXISTING);}
catch (IOException ex) {
JOptionPane.showMessageDialog(null, "Error while working with temporary files", "Error", JOptionPane.ERROR_MESSAGE);}
try {
String VCAMvexp1=jTable16.getModel().getValueAt(2, 0).toString();
... //I have 6 jTables with 15 rows and 10 columns
try {
FileInputStream temp_file = new FileInputStream(new File(target));
XSSFWorkbook wb = new XSSFWorkbook(temp_file);
XSSFSheet worksheet = wb.getSheetAt(0); //separate sheet for each jTable
XSSFSheet worksheet1 = wb.getSheetAt(1);
XSSFSheet worksheet2 = wb.getSheetAt(2);
XSSFSheet worksheet3 = wb.getSheetAt(3);
XSSFSheet worksheet4 = wb.getSheetAt(4);
XSSFSheet worksheet5 = wb.getSheetAt(5);
CellStyle style = wb.createCellStyle();
style.setFillForegroundColor(IndexedColors.RED.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setBorderBottom(BorderStyle.THICK);
style.setBottomBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderLeft(BorderStyle.THICK);
style.setLeftBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderRight(BorderStyle.THICK);
style.setRightBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderTop(BorderStyle.THICK);
style.setTopBorderColor(IndexedColors.BLACK.getIndex());
style.setAlignment(HorizontalAlignment.CENTER);
Font font = wb.createFont();
font.setFontHeightInPoints((short)10);
font.setFontName("Arial");
style.setFont(font);
Cell VCAMvexp1cell = worksheet.getRow(12).getCell(6);
VCAMvexp1cell.setCellValue(VCAMvexp1);
if (Float.parseFloat(VCAMvexp1)<Float.parseFloat(VCAMvexp1_min) || Float.parseFloat(VCAMvexp1)>Float.parseFloat(VCAMvexp1_max)) {
VCAMvexp1cell.setCellStyle(style);}
... //fill in the sheets and mark cells with red color
temp_file.close();
FileOutputStream output_file = new FileOutputStream(new File(target));
wb.write(output_file);
output_file.close();
}
catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(null, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);}
catch (IOException ex){
JOptionPane.showMessageDialog(null, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);}
}
catch (NullPointerException e) {
JOptionPane.showMessageDialog(null, "Cannot save the data. Table is not filled in completely", "Error", JOptionPane.ERROR_MESSAGE);}
The solution is to change the printing protocol from WSD to LPD. After that the file was printed out completely.

Error while creating read only .xlsx file using Apache POI

I am trying to create one read only Excel-sheet using Apache POI 3.10.
private void lockAll(Sheet s, String password) throws Exception{
XSSFSheet sheet = ((XSSFSheet)s);
sheet.protectSheet(password);
sheet.enableLocking();
sheet.lockSelectLockedCells();
sheet.lockSelectUnlockedCells();
}
Now I am calling this method after creating my excel sheet using following.
private String generateExcel(List<Model> DataList) {
Workbook wwbook = null;
File ff = null;
try {
String filePath = // getting this path using ServletContext.
wwbook = new XSSFWorkbook();
Sheet wsheet = wwbook.createSheet("MyReport");
ApachePoiExcelFormat xlsxExcelFormat = new ApachePoiExcelFormat();
CellStyle sheetHeading = xlsxExcelFormat.SheetHeading(wwbook);
//My personal org.apache.poi.ss.usermodel.CellStyle here.
short col = 0, row = 0;
XSSFRow hrow = (XSSFRow) (XSSFRow) wsheet.createRow(row);
XSSFCell cell = hrow.createCell(col);
//My code here to iterate List and add data to cell.
FileOutputStream fileOut = new FileOutputStream(filePath.toString());
wwbook.write(fileOut);
lockAll(wsheet, "password"); //******calling the method to lock my sheet.
fileOut.close();
System.out.println("Excel Created");
} catch (Exception e) {
e.printStackTrace();
} finally {
}
return filePath;
}
Now while I am running this code to download the excel file. Then I am getting error on the webpage but not on my eclipse console.
Next I was trying to run the same code after commenting the following line in lockAll method. And then the excel downloading happens as required, but every cells in the sheet are editable.
sheet.protectSheet(password);

Categories