Load external Excel file - java

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.

Related

HWPF-POI:The table insert into doc with poi hwpf is not visible

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.

Apache Poi, how to get the linked workbook?

I try to analyze excel files with links to other files and I like to know the file name and path. For that I'm using apache poi 3.14.
I figured it out for Ref3DPtg objects but for Ref3DPxg I don't know how to do it. I only get access to the cell address and the sheet name.
Does anyone know how to do it?
Code:
...
if(ptg instanceof Ref3DPxg){
cellAddress = ptg.format2DRefAsString();
sheetName = ptg.getSheetName();
workbookName = ???;
} else if(ptg instanceof Ref3DPtg) {
// by Ref3DPtg is no problem
}
Because of the way that the XLSX file format stores external references, which isn't actually =[Other.xlsx]Sheet1!A1 but actually =[23]Sheet1!A1, it's a two step process. First, get the external workbook number from the Pxg. Next, from Workbook get the ExternalLinks table for that workbook number, noting the off-by-one. (External Workbook 0 is actually the current workbook, so External Workbook 1 corresponds to External Link 0). Finally, fetch the filename for that link
So, your code should be something like:
if(ptg instanceof Ref3DPxg){
Ref3DPxg pxg = (Ref3DPxg)ptg;
int extWB = pxg.getExternalWorkbookNumber();
int extLink = extWB-1;
ExternalLinksTable links = wb.getExternalLinksTable().get(extLink);
String filename = links.getLinkedFileName();
}

read .pptx causes java.lang.ClassNotFoundException

In this question someone had a similar problem I have: I want to read the content of a .pptx file (only the text), but only got it work with .ppt files. So I tried to solve it with the accepted answer, but I got this exception: java.lang.ClassNotFoundException: org.apache.poi.hslf.model.TextPainter$Key
I used the example from this page (which was suggested in the accepted answer) so I have no idea why it does not work. My code:
public static String readPPTX(String path) throws FileNotFoundException, IOException{
XMLSlideShow ppt = new XMLSlideShow(new FileInputStream(path));
String content = "";
XSLFSlide[] slides = ppt.getSlides();
for (XSLFSlide slide : slides){
XSLFShape[] sh = slide.getShapes();
for (int j = 0; j < sh.length; j++){
if (sh[j] instanceof XSLFTextShape){
XSLFTextShape shape = (XSLFTextShape)sh[j];
content += shape.getText() + "\n";
}
}
}
return content;
}
Solution to this issue is to add the poi-scratchpad-3.9.jar file to the classpath of the project.

POI - Excel remains held by some process and cannot be edited

I am using POI to read,edit and write excel files.
My process flow is like write an excel, read it and again write it.
Then if I try to edit the file using normal desktop excel application while my Java app is still running, the excel cannot be saved, it says some process is holding the excel,
I am properly closing all file handles.
Please help and tell me how to fix this issue.
SXSSFWorkbook wb = new SXSSFWorkbook(WINDOW_SIZE);
Sheet sheet = getCurrentSheet();//stores the current sheet in a instance variable
for (int rowNum = 0; rowNum < data.size(); rowNum++) {
if (rowNum > RECORDS_PER_SHEET) {
if (rowNum % (RECORDS_PER_SHEET * numberOfSheets) == 1) {
numberOfSheets++;
setCurrentSheet(wb.getXSSFWorkbook().createSheet());
sheet = getCurrentSheet();
}
}
final Row row = sheet.createRow(effectiveRowCnt);
for (int columnCount = 0; columnCount < data.get(rowNum).size(); columnCount++) {
final Object value = data.get(rowNum).get(columnCount);
final Cell cell = row.createCell(columnCount);
//This method creates the row and cell at the given loc and adds value
createContent(value, cell, effectiveRowCnt, columnCount, false, false);
}
}
public void closeFile(boolean toOpen) {
FileOutputStream out = null;
try {
out = new FileOutputStream(getFileName());
wb.write(out);
}
finally {
try {
if (out != null) {
out.close();
out = null;
if(toOpen){
// Open the file for user with default program
final Desktop dt = Desktop.getDesktop();
dt.open(new File(getFileName()));
}
}
}
}
}
The code looks correct. After out.close();, there shouldn't be any locks left.
Things that could still happen:
You have another Java process (for example hanging in a debugger). Your new process tries to write the file, fails (because of process 1) and in the finally, it tries to open Excel which sees the same problem. Make sure you log all exceptions that happen in wb.write(out);
Note: The code above looks correct in this respect, since it only starts Excel when out != null and that should only be the case when Java could open the file.
Maybe the file wasn't written completely (i.e. there was an exception during write()). Excel tries to open the corrupt file and gives you the wrong error message.
Use a tool like Process Explorer to find out which process keeps a lock on a file.
I tried all the options. After looking thoroughly, it seems the problem is the Event User model.
I am using the below code for reading the data:
final OPCPackage pkg = OPCPackage.open(getFileName());
final XSSFReader r = new XSSFReader(pkg);
final SharedStringsTable sst = r.getSharedStringsTable();
final XMLReader parser = fetchSheetParser(sst);
final Iterator<InputStream> sheets = r.getSheetsData();
while (sheets.hasNext()) {
final InputStream sheet = sheets.next();
final InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
}
I assume the excel is for some reason held by this process for some time. If I remove this code and use the below code:
final File file = new File(getFileName());
final FileInputStream fis = new FileInputStream(file);
final XSSFWorkbook xWb = new XSSFWorkbook(fis);
The process works fine an the excel does not remain locked.
I figured it out actually.
A very simple line was required but some some reason it was not explained in the New Halloween Document (http://poi.apache.org/spreadsheet/how-to.html#sxssf)
I checked the Busy Developer's Guide and got the solution.
I needed to add
pkg.close(); //To close the OPCPackage
This added my code works fine with any number of reads and writes on the same excel file.

FileOutputStream() not working?

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?

Categories