I have this app. I'm working on. It allows users to view JTable instancess and at the same time have the option to save it in excel format or print it. It asks the user for the file name and location where to place the file then saves it in that location. The app is ran in the local server (tomcat), and it is used by other users in different workstations. I'm using POI API in converting the table into an Excel file and it works well.
The problem now is that FileOutputStream() wont create any file at all for other workstations. It only creates/saves a file in a single workstation, the workstation where I am currently developing the app. I've searched long enough to find a solution, but I haven't found any yet so I'm trying to ask you guys for help. I'll be including the codes.
public class ReportToExcel
{
//file returned comes from the user from antoher function.
public void exportTable(JTable table, File file) throws IOException {
HSSFWorkbook report = new HSSFWorkbook();
HSSFSheet report_sheet = report.createSheet("report_sheet");
HSSFRow rowHead = report_sheet.createRow((int)0);
TableModel model = table.getModel();
FileOutputStream reportOut = new FileOutputStream(file.getAbsolutePath());
System.out.println("table to excel "+table.getName());
for(int x=0; x < model.getColumnCount(); x++) {
rowHead.createCell((int)x).setCellValue(model.getColumnName(x));
report_sheet.autoSizeColumn((int)x);
System.out.println(x+". "+model.getColumnName(x));
}
for(int i=1; i< model.getRowCount(); i++) {
HSSFRow row = report_sheet.createRow((int)i);
for(int j=0; j < model.getColumnCount(); j++) {
row.createCell((int)j).setCellValue(model.getValueAt(i,j).toString());
System.out.println(i+". "+model.getValueAt(i,j).toString());
}
}
report.write(reportOut);
reportOut.close();
System.out.println("write out to: " + file.getAbsolutePath());
}
}
Already found the answer. For NoClassDefFound error, the workstations need to have priveleges in accessing the classpath of the POI api which i definiteley overlooked.
I think a key statement from you is that the code only works on your workstation. Many times the issue is related to file/directory permissions. Normal users do have less permission than a developer.
Also helps if you tell us the output to file.getAbsolutePath() in case the path is suspicious.
The path should be a safe place for your users to create/modify files.
Have you tried saving the output to the server, rather than the local machine for each workstation?
Related
I need to read several xlsx files looking for data specific to an employee and simultaneously create another xlsx file (if I find data in any of the file)with file name as employee Id appended to the name I found the data in. Eg. there is an employee with emp id 1 and there are severaal xlsx files such as A,B, C... so on; I need to look for data relating to emp id 1 in each file and for the files I get a hit I need to create a file named 1_A.xlsx.
Now although I have built the logic and am using Apache POI APIs for reading and writing, my code is throwing Out Of Memory error after creating just the first file with the data. And is unable to read the rest of the files.
I have tried using SXSSF instead of XSSF but same OOM happens.
Increasing the heap space is not an option for me.
Please help here...Thanks in advance.
Here is a piece of code :
//Reader:
Row row = null;
List<Row> listOfRecords = new ArrayList<Row>();
try {
FileInputStream fis = new FileInputStream(metaDataFile);
new InputStreamReader(fis, "ISO-8859-1");
XSSFWorkbook wb = new XSSFWorkbook(fis);
XSSFSheet sheet = wb.getSheetAt(0);
Iterator<Row> rowIterator = sheet.iterator();
while (rowIterator.hasNext()) {
row = rowIterator.next();
if (!isEmptyRow(row)) {
listOfRecords.add(row);
}
}
wb.close();
fis.close();
//Writer
LOGGER.info("in createWorkbook " );
Workbook empWorkbook = new SXSSFWorkbook(200);
Sheet empSheet = empWorkbook.createSheet("Itype Sheet For Emp_"
+ personnelNumber);
int rowNum = listOfRecords.size();
System.out.println("Creating excel");
Cell c = null;
for (int i = 0; i < rowNum; i++) {
Row record = listOfRecords.get(i);
Row empRow = empSheet.createRow(i++);
if (!isEmptyRow(record)) {
int colNum = record.getLastCellNum() + 1;
for (int j = 0; j < colNum; j++) {
Cell newCell = empRow.createCell(j);
System.out.println("cellVal:"
+ String.valueOf(record.getCell(j)));
newCell.setCellValue(String.valueOf(record.getCell(j)));
}
}
}
The writer method is called from within the reader.
Reading of multiple xlsx files is indeed tricky business butI finally solved it.
I had to break down my code several folds to realise that the OOM error was due to the fact that after reading 3 files no more memory was left to process the rest of the files.
xlsx files are compressed xml files. So when we try to read them using XSSF or SXSSF APIs it loads the entire DOM to the memory thereafter choking it.
I found an excellent solution here :
[https://github.com/monitorjbl/excel-streaming-reader]
Hope this will help others who come here facing the same issue.
I want to insert a table at a specific position with poi, the table is generated, but I find this table is not visible.
The generated table in doc is visible when previewing or editing this doc with macOS and its text tool, POI can read the table and content, too. I plan to upload 4 pictures to display the process, but I can only post 2 images, sorry for that.
#Test
public void exportDoc() throws Exception {
FileInputStream readFile = new FileInputStream(new File(readDoc));
FileOutputStream replaceFile = new FileOutputStream(new File(replaceDoc));
HWPFDocument document = new HWPFDocument(readFile);
Table table = WordUtil.insertNewTable(document,"${table}");
insertTableInDoc(table);
document.write(replaceFile);
readFile.close();
replaceFile.close();
}
private Table insertNewTable(HWPFDocument doc, String sourceValue) {
Range range = doc.getRange();
Table table = null;
for (int i = 0; i < range.numSections(); ++i) {
Section s = range.getSection(i);
for (int x = 0; x < s.numParagraphs(); x++) {
Paragraph p = s.getParagraph(x);
if (p.text().contains(sourceValue)) {
//remove target text
range.replaceText(sourceValue, "");
table = p.insertTableBefore((short) 3, 3);
return table;
}
}
}
return table;
}
private void insertTableInDoc(Table table) {
int count = 1;
for (int rowNum = 0; rowNum < table.numRows(); rowNum++) {
TableRow tableRow = table.getRow(rowNum);
for (int colNum = 0; colNum < tableRow.numCells(); colNum++) {
TableCell cell = tableRow.getCell(colNum);
Paragraph paragraph = cell.getParagraph(0);
CharacterRun characterRun = paragraph.getCharacterRun(0);
characterRun.insertBefore("number: " + count++);
}
}
}
PS:
I am sure this is not microsoft for mac 's problem, the generate table in doc at windows platform is not visible, too.
(First time to ask question, if anything wrong or my expression is not clear, please let me know and I will modify it without delay. Thanks)
With the current state of the HWPF project, you likely are out of luck when trying to insert content into a .doc file. Your best bet is to use a different format (docx).
I did not look at HWPF for the past year, so I may be wrong here regarding the current state of HWPF:
Some years ago I was developing a custom HWPF library for a client. The major goal for that custom library was the ability to modify .doc files and that Word can process the modified files correctly. Hence I know in how many levels modifying a .doc file can fail in the end. The public HWPF library is not able to handle many aspects of the .doc file format when it comes to modification (textboxes, two-byte character ranges, shape files, nested tables, ... to name a few).
To handle modification correctly, all the "features" of the specific .doc file must be supported by the library. So when there are shapes in the .doc file, HWPF must adjust the position tables of the shapes even when a simple text snippet is inserted and the shapes are not touched. If shapes are not handled, Word will crash when opening the output file.
So if you can, use docx or rtf. If it is an option, you might try one of the commercial libraries which are able to handle .doc files.
I have a Spring action which should read in an Excel file and access the values contained in the cells. I am using the Java Excel API to process the Excel file. I want it to read from an external folder and not from the root of my project. The problem I am having is Spring MVC cannot recognize my file. I get this error almost every time:
The filename, directory name, or volume label syntax is incorrect
I even tried something like:
Resource banner = resourceLoader.getResource("http://howtodoinjava.com/readme.txt");
as seen here, and still no luck. My controller code:
#RequestMapping(value="migrateexcel", method = RequestMethod.POST)
public String migrateexcel(Model uiModel, HttpServletRequest httpServletRequest) throws BiffException, IOException {
String fileName = httpServletRequest.getParameter("filename");
if (! fileName.isEmpty() && fileName!= null) {//just doing this as the logic kicks in from a form
FileSystemResource resource = new FileSystemResource("file:C:/Users/Administrator/Desktop/myfolder/test.xlsx");
File xlsFile = resource.getFile();
String temp = "";
Workbook workbook = Workbook.getWorkbook(xlsFile);
Sheet sheet = workbook.getSheet(0);
for(int i =0; i<sheet.getRows(); i++){
for(int j =0; j < sheet.getColumns(); j++){
Cell cell = sheet.getCell(j,i);
temp = cell.getContents();
System.out.println(temp);
}
}
uiModel.addAttribute("message", "Excel Data migrated successfully");
return "rates/processexcel";
}else{
uiModel.addAttribute("message", "Please select a file before submiting");
return "rates/processexcel";
}
}
I tested it, and it seems like the only problem is the way you reference the file.
This two ways should work (Unless there is some kind of permission problem):
"C:/Users/Administrator/Desktop/myfolder/test.xlsx"
or
"C:\\Users\\Administrator\\Desktop\\myfolder\\test.xlsx"
Spring and Spring MVC are actually irrelevant for the question, but the constructors of FileSystemResource are expecting the same syntax in a String, or a java.io.File.
I am absolute new to the Eclipse Java coding. I am trying to finish a project for managing the inventory. The part i am having trouble with is that, when I tried to write the items into the excel cell, I got errors saying that the array is out of bounds.
PS: item and item.getPartname etc are all defined under another class file.
Please help. thanks
FileOutputStream os =new FileOutputStream("orderreceipt");
//Create a new workbook for writing data
HSSFWorkbook wb2 = new HSSFWorkbook();
//Create a new sheet:
HSSFSheet newsheet = wb2.createSheet("MyNewSheet");
//Create a new row:
for (int i=0; i<6; i++){
HSSFRow newrow = newsheet.createRow(i);
sentorder item = (sentorder)items.get(i);
for (short j=0; j<5; j++){
HSSFCell cell = newrow.createCell(j);
cell.setCellValue(item.getPartname());
cell.setCellValue(item.getPartnumber());
cell.setCellValue(item.getQuantity());
cell.setCellValue(new Date());
HSSFCellStyle styleOfCell = wb2.createCellStyle();
styleOfCell.setDataFormat(HSSFDataFormat
.getBuiltinFormat("m/d/yy"));
styleOfCell.setFillForegroundColor(HSSFColor.AQUA.index);
styleOfCell.setFillPattern(HSSFCellStyle.BORDER_THIN);
cell.setCellStyle(styleOfCell);
}}
wb2.write(os);
}
I can see quite a few problems with the attached code:
Missing file extension when creating new FileOutputStream - since you're generating the .xls workbook, you'd probably like to store it in the XLS file (the extension is not added automatically), also just make sure you have a proper file path to the directory you have write permissions (local application dir, as in this case should be ok though).
As already mentioned you are re-setting the same cell value 4 times
You are creating the same cell style multiple times (this is not cached behind the scenes and there is largely limited number of cells styles which can be created so if you were generating a couple thousands of rows you might get into troubles
You don't flush() and close() stream after writing your workbook. Streams in Java a precious resources which need to be manually closed.
Without stack trace it's difficult to say 100% where the ArrayOutOfBound issue you're seeing is coming from, however my guess would be that you're trying to access a item (from items collection) with the index that doesn't exist, which is a consequence that you're driving your report data from row indexes instead of the list of items you have.
Also, since you're quite new to Java a couple of guidelines which will allow you to produce hopefully better and less error-prone code in the future:
Use proper Java naming convention - please follow standard Java naming convention http://java.about.com/od/javasyntax/a/nameconventions.htm , your code will be easier to read and reason about (especially when you're looking for help from community) - i.e. sentorder class should be named as SentOrder.
Try to split your code into smaller, more testable modules i.e. you can have a helper createDataRow method called from your main method, in general having more than a couple of inner loops in one method makes them incredibly difficult to test, debug and reason about.
Unless you really need to generate .xls format, consider using XSSF* classes for generating xlsx document - it has many improvements over HSSF* (including much better dataFormat support).
Having those in mind I've rewritten your example:
public void improved(List<SentOrder> items) throws IOException {
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("MyNewSheet");
HSSFCellStyle styleOfCell = workbook.createCellStyle();
styleOfCell.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy"));
styleOfCell.setFillForegroundColor(HSSFColor.AQUA.index);
styleOfCell.setFillPattern(HSSFCellStyle.BORDER_THIN);
int rowIndex = 0;
for(SentOrder item : items) {
HSSFRow row = sheet.createRow(rowIndex++);
HSSFCell nameCell = row.createCell(0);
nameCell.setCellValue(item.getPartName());
HSSFCell numberCell = row.createCell(1);
numberCell.setCellValue(item.getPartNumber());
HSSFCell quantityCell = row.createCell(2);
quantityCell.setCellValue(item.getQuantity());
HSSFCell dateCell = row.createCell(3);
dateCell.setCellValue(new Date());
dateCell.setCellStyle(styleOfCell);
}
FileOutputStream os = new FileOutputStream("order_receipt.xls");
try {
workbook.write(os);
} finally {
os.flush();
os.close();
}
}
I'm a newbie with Java. Please kindly help.
So I'm using jxl for my project. On my laptop, the Excel file did get created with the data I wrote to it.
But when I tried to use it on my client's computer, the excel was not created.
I used JOptionPane.showMessageDialog to indicate in which code the program stopped, and it turns out the program stopped at the:
workbook.write();
My code was like this:
File exlFile = new File("C:/Output/Excel Files/Reports.xls");
WritableWorkbook workbook = Workbook.createWorkbook(exlFile);
WritableSheet exchangeWrite = workbook.createSheet("EXCHANGE_RATE", 0);
try{
String sqlTakeExchange = "select * from R_ExchangeRate";
PreparedStatement psTakeExchange = dbConn.prepareStatement(sqlTakeExchange);
ResultSet rsTakeExchange = psTakeExchange.executeQuery();
Label header = new Label(0, 0, "Ccy", headerFormat());exchangeWrite.addCell(header);
header = new Label(1, 0, "Rate", headerFormat());exchangeWrite.addCell(header);
int currentCol = 1;
while(rsTakeExchange.next()){
for (int row = 0; row < 2; row++){
for (int col = 1; col < 2; col++){
Label content = new Label(row, currentCol, rsTakeExchange.getString(row + 1), numberFormat());
exchangeWrite.addCell(content);
}
}
currentCol++;
}
sheetAutoFitColumns(exchangeWrite);
}catch(Exception ex){
ex.getMessage();
JOptionPane.showMessageDialog(null, ex.getMessage());
ex.printStackTrace();
}
workbook.write();
workbook.close();
On my laptop, the excel file contains data that I want with the right format I want.
but on my client computer, it didn't create the file.
I don't know if this helps, but my client uses:
Intel Core 2 duo
Windows XP Professional
Microsoft Office 2007
Java 6 update 26
Ram 1Gb
It's just a PC for any testing. And because my app doesn't require any high spec (just a mini tool to generate excel file from the database). I'm using Java 7 update 51.
Also I have about 4 clients that are using my app. This jxl problem was only showing up on 1 client only, the other 3 did create the excel file.
Any ideas how to solve this? Many thanks
After some asking to my senior, it turns out that it's facing a problem with:
Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap spa
ce
perhaps i'm gonna tweak the codes.