I have a excel file with some values like :
**Status Code** **Method Name**
400 createRequest
401 testRequest
402 mdm
403 fileUpload
and the following code to read and print the data[Late on i will put them in HashMap]
package com.poc.excelfun;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
public class ReadExcelData {
public static void main(String[] args) {
try {
FileInputStream file = new FileInputStream(new File("attachment_status.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();
switch(cell.getCellType()) {
case Cell.CELL_TYPE_BOOLEAN:
System.out.print(cell.getBooleanCellValue() + "\t\t");
break;
case Cell.CELL_TYPE_NUMERIC:
System.out.print(cell.getNumericCellValue() + "\t\t");
break;
case Cell.CELL_TYPE_STRING:
System.out.print(cell.getStringCellValue() + "\t\t");
break;
}
}
System.out.println("");
}
file.close();
/*
* The following code to create a new work book with the value fetched from the given work book
* FileOutputStream out =
new FileOutputStream(new File("attachment_status_new.xls"));
workbook.write(out);
out.close();*/
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
but the above code returns the following :
Status Code Method Name
400.0 createRequest
401.0 testRequest
402.0 mdm
403.0 fileUpload
If wee the out put the status code comes with .0 but i want to get only 400 not with .0
How to do this.
I have used poi for excel manipulations.
Best Regards
Anto
cell.getNumericCellValue() returns double vaule cast it into int the decimal point will be ignored.
Excel stores almost all numbers in the file format as floating point values, which is why POI will give you back a double for a numeric cell as that's what was really there.
While you could just cast that to an int, that'd just be specific to the one case, and not general. What I think you probably want (though it's not quite clear from your question) is to get a String in Java that contains the number as it would look in Excel? So your cell containing 400.0 and a format rule of integer would come back as the string "400".
If so, you want to do exactly the same thing as in my answer here. To quote:
What you want to do is use the DataFormatter class. You pass this a cell, and it does its best to return you a string containing what Excel would show you for that cell. If you pass it a string cell, you'll get the string back. If you pass it a numeric cell with formatting rules applied, it will format the number based on them and give you the string back.
For your case, I'd assume that the numeric cells have an integer formatting rule applied to them. If you ask DataFormatter to format those cells, it'll give you back a string with the integer string in it.
Related
I am using Apache poi to extract Mysql data to an Excel file. The code is running correctly but when I am trying to open the excel file it is showing error.
package com.telkomsel.excel;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
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 com.telkomsel.configuirator.Configurator;
import com.telkomsel.dbconnection.DBConnection;
import com.telkomsel.service.TelkomselEntities;
public class TelkomselExcel {
DBConnection db = new DBConnection();
static Configurator configurator = null;
Connection conn = null;
static Statement statement = null;
static ResultSet resultSet = null;
public static HashMap<Integer, TelkomselEntities> getTelkomselData(Statement statement) {
configurator = new Configurator();
String Query = configurator.getProperty("sql_query1");
HashMap<Integer, TelkomselEntities> all = null;
TelkomselEntities smsModel = null;
try {
all = new HashMap<Integer, TelkomselEntities>();
resultSet = statement.executeQuery(Query);
while (resultSet.next()) {
int hour = resultSet.getInt("hour(timestamp)");
String count = resultSet.getString("count(1)");
smsModel = new TelkomselEntities(hour, count, count, count);
all.put(hour, smsModel);
}
smsModel = new TelkomselEntities();
FileInputStream fis = new FileInputStream(new File("Tracker.xlsx"));
XSSFWorkbook workbook = new XSSFWorkbook(fis);
XSSFSheet worksheet = workbook.getSheetAt(0);
XSSFRow row = null;
XSSFCell cell;
int i = 1;
for (Integer l : all.keySet()) {
TelkomselEntities us = all.get(l);
row = worksheet.createRow(i);
cell = row.createCell(2);
cell.setCellValue(us.getHour());
cell = row.createCell(3);
cell.setCellValue(us.getCharge_Count());
i++;
}
fis.close();
FileOutputStream output_file = new FileOutputStream(new File("Tracker.xlsx"),true);
System.out.println("SUCCESS");
workbook.write(output_file);
workbook.close();
output_file.flush();
output_file.close();
} catch (Exception e) {
System.out.println(e);
}
return all;
}
}
I think file output stream is creating problem as it converts data into byte codes. i tried every thing but doesn't work. my excel file is not working
As you supposed, the problem hides inside the line:
FileOutputStream output_file = new FileOutputStream(new File("Tracker.xlsx"),true);
When creating a new XSSFWorkbook Java Object from an existing excel (which you want to update), that XSSFWorkbook is initially created based on your excel file content, then it is totally independent from it.The proof of this is that all changes to the XSSFWorkbook Java Object ARE NOT going to affect the original excel file at all. Apache Poi works that way!
This is the reason why once you're done editing your XSSFWorkbook you have to save it as a new excel file (using a FileOutputStream) overriding the original one (in a sense, you're now updating your excel file with all your changes).
But as the docs says, you're telling FileOutputStream not to override the original excel file with the new and updated one but to append the second to the first one, upsi dupsi! You're creating a single file which contains both all the bytes of the original old file and all the bytes of the new updated one!
To solve the problem, just use instead:
FileOutputStream output_file = new FileOutputStream(new File("Tracker.xlsx"),false);
or
FileOutputStream output_file = new FileOutputStream(new File("Tracker.xlsx"));
and you're done!
Edit: learn Apache Poi before using Apache Poi
It seems that you're using FileOutputStream wrong because you don't know how Apache Poi works and how to use it. You might want to study a little bit about it before using it, the web is full of examples and tutorials! Here they are some examples provided by Apache Poi itself, you might want to have a look at them.
As I said before, the XSSFWorkbook is initialized with all the content of your original excel file. So if you start filling your XSSFSheet from the second line (that's what you're actually doing with your code) you are literally asking to your XSSFWorkbook to override existing data with new one.
You have to improve your code, searching for already existing data in rows and cells and not overriding it if you don't want to.
Rows and cells of each XSSFSheet of your XSSFWorkbook are numbered using 0-based indexes (that's the reason why your code, which starts filling rows from index 1, is filling rows starting from the second one).
With the method XSSFSheet#getRow(int rownum) you can retreive any row from the current XSSFSheet indicating its 0-based index. If this method returns null, then the row you're asking for has never been used and you have to create it using the method XSSFSheet#createRow(int rownum). If it doesn't, then the row you're asking for has already been used and contains some data in some of its cells.
With the method XSSFRow#getCell(int cellnum) you can retrieve any cell from the current XSSFRow indicating its 0-based index. If this method returns null, then the cell you're asking for has never been used and you have to create it using the method XSSFRow#createCell(int cellnum, CellType celltype). If it doesn't, then the cell you're asking for has already been used and contains some data in it.
You can retrieve the CellType of an existing XSSFCell with the method XSSFCell#getCellType().
You can retreive the content of an existing XSSFCell (on the basis of its CellType) using such methods as XSSFCell#getStringCellValue(), XSSFCell#getNumericCellValue() or XSSFCell#getBooleanCellValue().
Other useful methods are XSSFSheet#getLastRowNum() and XSSFRow#getLastCellNum(). The first one returns the index of the last already used row inside your sheet, the second one returns the index of the first not used cell inside your row.
Here it is an example for you (filling 42 rows of your sheet after the last existing one):
public static void main(String[] args) throws EncryptedDocumentException, FileNotFoundException, IOException {
// Step 1: load your excel file as a Workbook
String excelFilePath = "D:\\Desktop\\textExcel.xlsx";
XSSFWorkbook workbook = (XSSFWorkbook) WorkbookFactory.create(new FileInputStream(excelFilePath));
// Step 2: modify your Workbook as you prefer
XSSFSheet sheet = workbook.getSheetAt(0);
int firstUnusedRowIndex = sheet.getLastRowNum() + 1;
for (int rowIndex = firstUnusedRowIndex ; rowIndex < firstUnusedRowIndex + 42 ; rowIndex++) {
sheet.createRow(rowIndex).createCell(0, CellType.STRING).setCellValue("New Row n°" + (rowIndex - firstUnusedRowIndex + 1));
}
// Step 3: update the original excel file
FileOutputStream outputStream = new FileOutputStream(excelFilePath);
workbook.write(outputStream);
workbook.close();
outputStream.close();
}
The problem:
I'm just trying to open it .xls file using the Apache-poi 4.1.0 library and it gives the same error as 4 years ago in a similar question.
I already tried
to put version 3.12-3.16.
3.13 as well
All versions can open blank .xls and filled by myself but not this one.
This document is generated automatically and I need to make a program that accepts it.
I already made a .Net standart library C# which is work, I tried to use xamarin android it's a horror, the app weighs 50 mb vs 3 mb due to various terrible SDK link errors, but that's a different story. So I decided to do it on Kotlin.
Code is from the documentation
You can check file on git
val inputStream = FileInputStream("./test.xls")
val wb = HSSFWorkbook(inputStream)
I expect no errors while opening xls.
Actual output is
Exception in thread "main" java.lang.RuntimeException: Unexpected record type (org.apache.poi.hssf.record.HyperlinkRecord)
at org.apache.poi.hssf.record.aggregates.RowRecordsAggregate.<init>(RowRecordsAggregate.java:97)
at org.apache.poi.hssf.model.InternalSheet.<init>(InternalSheet.java:183)
at org.apache.poi.hssf.model.InternalSheet.createSheet(InternalSheet.java:122)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:354)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:400)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:381)
at ru.plumber71.toolbox.ExcelParcerKt.main(ExcelParcer.kt:19)
at ru.plumber71.toolbox.ExcelParcerKt.main(ExcelParcer.kt)
The document will not be modified in any way. If there any other libraries to just read the dataset or strings from the .xls file will be OK.
After some investigation I found the problem with your test.xls file.
According the file format specifications, all HyperlinkRecords should be together in the Hyperlink Table. It is contained in the Sheet Substream following the cell records. In your case the HyperlinkRecords are between other records (between NumberRecords and LabelSSTRecords in that case). So I suspect it was not Excel what had created that test.xls file.
Excelmight be tolerant enough to open that file nevertheless. But you cannot expect that apache poi also tries to tolerate all possible violations in file format. If you open the file using Excel and then re-save it, apache poi is able creating the Workbookafter that.
Apache poi is not able repairing this as Excel can do. But one could read the POIFSFileSystem a low level way and filtering out the HyperlinkRecords that are between other records. That way one could read the content using apache poi, of course except the hyperlinks.
Example:
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.NameRecord;
import org.apache.poi.hssf.record.NameCommentRecord;
import org.apache.poi.hssf.record.HyperlinkRecord;
import org.apache.poi.hssf.record.RecordFactoryInputStream;
import org.apache.poi.hssf.record.RecordFactory;
import org.apache.poi.hssf.model.RecordStream;
import org.apache.poi.hssf.model.InternalWorkbook;
import org.apache.poi.hssf.model.InternalSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFName;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.util.CellReference;
import java.util.List;
import java.util.ArrayList;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
class ExcelOpenHSSF {
public static void main(String[] args) throws Exception {
String fileName = "test(2).xls";
try (InputStream is = new FileInputStream(fileName);
POIFSFileSystem fileSystem = new POIFSFileSystem(is)) {
//find workbook directory entry
DirectoryNode directory = fileSystem.getRoot();
String workbookName = "";
for(String wbName : InternalWorkbook.WORKBOOK_DIR_ENTRY_NAMES) {
if(directory.hasEntry(wbName)) {
workbookName = wbName;
break;
}
}
InputStream stream = directory.createDocumentInputStream(workbookName);
//loop over all records and manipulate if needed
List<Record> records = new ArrayList<Record>();
RecordFactoryInputStream recStream = new RecordFactoryInputStream(stream, true);
//here we filter out the HyperlinkRecords that are between other records (NumberRecords and LabelSSTRecords in that case)
//System.out.println prints the problematic records
Record record1 = null;
Record record2 = null;
while ((record1 = recStream.nextRecord()) != null) {
record2 = recStream.nextRecord();
if (!(record1 instanceof HyperlinkRecord) && (record2 instanceof HyperlinkRecord)) {
System.out.println(record1);
System.out.println(record2);
records.add(record1);
} else if ((record1 instanceof HyperlinkRecord) && !(record2 instanceof HyperlinkRecord)) {
System.out.println(record1);
System.out.println(record2);
records.add(record2);
} else {
records.add(record1);
if (record2 != null) records.add(record2);
}
}
//now create the HSSFWorkbook
//see https://svn.apache.org/viewvc/poi/tags/REL_4_1_0/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java?view=markup#l322
InternalWorkbook internalWorkbook = InternalWorkbook.createWorkbook(records);
HSSFWorkbook wb = HSSFWorkbook.create(internalWorkbook);
int recOffset = internalWorkbook.getNumRecords();
Method convertLabelRecords = HSSFWorkbook.class.getDeclaredMethod("convertLabelRecords", List.class, int.class);
convertLabelRecords.setAccessible(true);
convertLabelRecords.invoke(wb, records, recOffset);
RecordStream rs = new RecordStream(records, recOffset);
while (rs.hasNext()) {
InternalSheet internelSheet = InternalSheet.createSheet(rs);
Constructor constructor = HSSFSheet.class.getDeclaredConstructor(HSSFWorkbook.class, InternalSheet.class);
constructor.setAccessible(true);
HSSFSheet hssfSheet = (HSSFSheet)constructor.newInstance(wb, internelSheet);
Field _sheets = HSSFWorkbook.class.getDeclaredField("_sheets");
_sheets.setAccessible(true);
#SuppressWarnings("unchecked")
List<HSSFSheet> sheets = (ArrayList<HSSFSheet>)_sheets.get(wb);
sheets.add(hssfSheet);
}
for (int i = 0 ; i < internalWorkbook.getNumNames() ; ++i){
NameRecord nameRecord = internalWorkbook.getNameRecord(i);
Constructor constructor = HSSFName.class.getDeclaredConstructor(HSSFWorkbook.class, NameRecord.class, NameCommentRecord.class);
constructor.setAccessible(true);
HSSFName name = (HSSFName)constructor.newInstance(wb, nameRecord, internalWorkbook.getNameCommentRecord(nameRecord));
Field _names = HSSFWorkbook.class.getDeclaredField("names");
_names.setAccessible(true);
#SuppressWarnings("unchecked")
List<HSSFName> names = (ArrayList<HSSFName>)_names.get(wb);
names.add(name);
}
//now the workbook is created properly
System.out.println(wb);
/*
//getting the data
DataFormatter formatter = new DataFormatter();
Sheet sheet = wb.getSheetAt(0);
for (Row row : sheet) {
for (Cell cell : row) {
CellReference cellRef = new CellReference(row.getRowNum(), cell.getColumnIndex());
System.out.print(cellRef.formatAsString());
System.out.print(" - ");
String text = formatter.formatCellValue(cell);
System.out.println(text);
}
}
*/
}
}
}
I was able to open a file of this "corrupted" type by using JExcel API
But using poi.apache.org also opens the file if manually resave it using excel application. (It may not be suitable for someone)
Sorry that it was asking strange questions. Thank you all and hope that someone may find useful.
val inputStream = FileInputStream("./testCorrupted.xls")
val workbook = Workbook.getWorkbook(inputStream)
val sheet = workbook.getSheet(0)
val cell1 = sheet.getCell(0, 0)
print(cell1.contents + ":")
I have a large xlsx file which has an empty "data source sheet" and other sheets containing lots of formulas that use the data source sheet. My application should generate the data, open the file, fill the empty sheet up with that data and save it. I'm trying to do all that with Apache POI.
The problem is that opening the file takes an unacceptable amount of memory and time. I've read other threads and couldn't find a solution.
This is how I open the file:
pkg = OPCPackage.open(filename);
wb = new XSSFWorkbook(pkg);
Please note that using SXSSFWorkbook does not work as its constructors take a XSSFWorkbook which I'm unable to create in the first place.
What I need is just to fill one empty sheet in the file, I don't need to completely load it in memory. Any Ideas??
Thank you!!
You could try working only with the OPCPackage without creating a Workbook. But then we must work at the lower level org.openxmlformats.schemas.spreadsheetml.x2006.main objects. This means we have not the support from the XSSF objects while storing string values as data (SharedStringsTable) and evaluating formulas.
The example takes a Excel workbook with at least 4 worksheets. The third worksheet is your "data source sheet". It must exist and will be overwritten with new data. The fourth worksheet is the worksheet in which formulas are referencing the "data source sheet". Since we can't use an evaluator, we must set FullCalcOnLoad true. If we would not do that, we had to press [Ctrl]+[Alt]+[Shift]+[F9] to force fully recalculation.
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.xssf.model.SharedStringsTable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetData;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType;
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.XmlException;
import javax.xml.namespace.QName;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.regex.Pattern;
class ReadAndWriteTest5 {
public static void main(String[] args) {
try {
File file = new File("ReGesamt11_3Test.xlsx");
//we only open the OPCPackage, we don't create a Workbook
OPCPackage opcpackage = OPCPackage.open(file);
//if there are strings in the SheetData, we need the SharedStringsTable
PackagePart sharedstringstablepart = opcpackage.getPartsByName(Pattern.compile("/xl/sharedStrings.xml")).get(0);
SharedStringsTable sharedstringstable = new SharedStringsTable();
sharedstringstable.readFrom(sharedstringstablepart.getInputStream());
//create empty WorksheetDocument for the "data source sheet"
WorksheetDocument worksheetdocument = WorksheetDocument.Factory.newInstance();
CTWorksheet worksheet = worksheetdocument.addNewWorksheet();
CTSheetData sheetdata = worksheet.addNewSheetData();
//put some data in for the "data source sheet"
for (int i = 0; i < 10; i++) {
CTCell ctcell= sheetdata.addNewRow().addNewC();
CTRst ctstr = CTRst.Factory.newInstance();
ctstr.setT("DataRow " + i);
int sRef = sharedstringstable.addEntry(ctstr);
ctcell.setT(STCellType.S);
ctcell.setV(Integer.toString(sRef));
ctcell=sheetdata.getRowArray(i).addNewC();
ctcell.setV(""+(i*100+(i+1)*10+(i+2))+"."+((i+3)*10+(i+4)));
}
//write the SharedStringsTable
OutputStream out = sharedstringstablepart.getOutputStream();
sharedstringstable.writeTo(out);
out.close();
//create XmlOptions for saving the worksheet
XmlOptions xmlOptions = new XmlOptions();
xmlOptions.setSaveOuter();
xmlOptions.setUseDefaultNamespace();
xmlOptions.setSaveAggressiveNamespaces();
xmlOptions.setCharacterEncoding("UTF-8");
xmlOptions.setSaveSyntheticDocumentElement(new QName(CTWorksheet.type.getName().getNamespaceURI(), "worksheet"));
Map<String, String> map = new HashMap<String, String>();
map.put(STRelationshipId.type.getName().getNamespaceURI(), "r");
xmlOptions.setSaveSuggestedPrefixes(map);
//get the PackagePart of the third sheet which is the "data source sheet"
//this sheet must exist and will be replaced with the new content
PackagePart sheetpart = opcpackage.getPartsByName(Pattern.compile("/xl/worksheets/sheet3.xml")).get(0);
//save the worksheet as the third sheet which is the "data source sheet"
out = sheetpart.getOutputStream();
worksheet.save(out, xmlOptions);
out.close();
//get the PackagePart of the fourth sheet which is the sheet on which formulas are referencing the "data source sheet"
//since we can't use Evaluator, we must force recalculation on load for this sheet
sheetpart = opcpackage.getPartsByName(Pattern.compile("/xl/worksheets/sheet4.xml")).get(0);
worksheetdocument = WorksheetDocument.Factory.parse(sheetpart.getInputStream());
worksheet = worksheetdocument.getWorksheet();
//setFullCalcOnLoad true
if (worksheet.getSheetCalcPr() == null) {
worksheet.addNewSheetCalcPr().setFullCalcOnLoad(true);
} else {
worksheet.getSheetCalcPr().setFullCalcOnLoad(true);
}
out = sheetpart.getOutputStream();
worksheet.save(out, xmlOptions);
out.close();
opcpackage.close();
} catch (InvalidFormatException ifex) {
ifex.printStackTrace();
} catch (FileNotFoundException fnfex) {
fnfex.printStackTrace();
} catch (IOException ioex) {
ioex.printStackTrace();
} catch (XmlException xmlex) {
xmlex.printStackTrace();
}
}
}
How can I convert/save excel file to pdf? I'm using java play framework to generate some excel files and now the requirement changes to pdf. I don't want to recode everything.
Is there a way to convert to pdf?
The excel files I'm generating are from a template; I read the excel template file, write changes, and save as new excel file. That way, the template is unchanged. It contains border, image, and other formatting.
You would need the following Java libraries and associated JAR files for the program to work.
POI v3.8
iText v5.3.4
Try this Example to convert XLS to PDF
The complete Java code that accepts Excel spreadsheet data as an input and transforms that to a PDF table data is provided below:
import java.io.FileInputStream;
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.usermodel.*;
import java.util.Iterator;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
public class excel2pdf {
public static void main(String[] args) throws Exception{
FileInputStream input_document = new FileInputStream(new File("C:\\excel_to_pdf.xls"));
// Read workbook into HSSFWorkbook
HSSFWorkbook my_xls_workbook = new HSSFWorkbook(input_document);
// Read worksheet into HSSFSheet
HSSFSheet my_worksheet = my_xls_workbook.getSheetAt(0);
// To iterate over the rows
Iterator<Row> rowIterator = my_worksheet.iterator();
//We will create output PDF document objects at this point
Document iText_xls_2_pdf = new Document();
PdfWriter.getInstance(iText_xls_2_pdf, new FileOutputStream("Excel2PDF_Output.pdf"));
iText_xls_2_pdf.open();
//we have two columns in the Excel sheet, so we create a PDF table with two columns
//Note: There are ways to make this dynamic in nature, if you want to.
PdfPTable my_table = new PdfPTable(2);
//We will use the object below to dynamically add new data to the table
PdfPCell table_cell;
//Loop through rows.
while(rowIterator.hasNext()) {
Row row = rowIterator.next();
Iterator<Cell> cellIterator = row.cellIterator();
while(cellIterator.hasNext()) {
Cell cell = cellIterator.next(); //Fetch CELL
switch(cell.getCellType()) { //Identify CELL type
//you need to add more code here based on
//your requirement / transformations
case Cell.CELL_TYPE_STRING:
//Push the data from Excel to PDF Cell
table_cell=new PdfPCell(new Phrase(cell.getStringCellValue()));
//feel free to move the code below to suit to your needs
my_table.addCell(table_cell);
break;
}
//next line
}
}
//Finally add the table to PDF document
iText_xls_2_pdf.add(my_table);
iText_xls_2_pdf.close();
//we created our pdf file..
input_document.close(); //close xls
}
}
i hope this will help you
Add on to assylias's answer
The code from assylias above was very helpful to me in solving this problem. The answer from santhosh could be great if you don't care about the resulting PDF looking exactly like your excel pdf export would look. However, if you are, say, filling out an excel template using Apache POI an then trying to export that while preserving its look and not writing a ton of code in iText just to try to get close to that look, then the VBS option is quite nice.
I'll share a Java version of the kotlin assylias has above in case that helps anyone. All credit to assylias for the general form of the solution.
In Java:
try {
//create a temporary file and grab the path for it
Path tempScript = Files.createTempFile("script", ".vbs");
//read all the lines of the .vbs script into memory as a list
//here we pull from the resources of a Gradle build, where the vbs script is stored
System.out.println("Path for vbs script is: '" + Main.class.getResource("xl2pdf.vbs").toString().substring(6) + "'");
List<String> script = Files.readAllLines(Paths.get(Main.class.getResource("xl2pdf.vbs").toString().substring(6)));
// append test.xlsm for file name. savePath was passed to this function
String templateFile = savePath + "\\test.xlsm";
templateFile = templateFile.replace("\\", "\\\\");
String pdfFile = savePath + "\\test.pdf";
pdfFile = pdfFile.replace("\\", "\\\\");
System.out.println("templateFile is: " + templateFile);
System.out.println("pdfFile is: " + pdfFile);
//replace the placeholders in the vbs script with the chosen file paths
for (int i = 0; i < script.size(); i++) {
script.set(i, script.get(i).replaceAll("XL_FILE", templateFile));
script.set(i, script.get(i).replaceAll("PDF_FILE", pdfFile));
System.out.println("Line " + i + " is: " + script.get(i));
}
//write the modified code to the temporary script
Files.write(tempScript, script);
//create a processBuilder for starting an operating system process
ProcessBuilder pb = new ProcessBuilder("wscript", tempScript.toString());
//start the process on the operating system
Process process = pb.start();
//tell the process how long to wait for timeout
Boolean success = process.waitFor(timeout, minutes);
if(!success) {
System.out.println("Error: Could not print PDF within " + timeout + minutes);
} else {
System.out.println("Process to run visual basic script for pdf conversion succeeded.");
}
} catch (Exception e) {
e.printStackTrace();
Alert saveAsPdfAlert = new Alert(AlertType.ERROR);
saveAsPdfAlert.setTitle("ERROR: Error converting to pdf.");
saveAsPdfAlert.setHeaderText("Exception message is:");
saveAsPdfAlert.setContentText(e.getMessage());
saveAsPdfAlert.showAndWait();
}
VBS:
Option Explicit
Dim objExcel, strExcelPath, objSheet
strExcelPath = "XL_FILE"
Set objExcel = CreateObject("Excel.Application")
objExcel.WorkBooks.Open strExcelPath
Set objSheet = objExcel.ActiveWorkbook.Worksheets(1)
objSheet.ExportAsFixedFormat 0, "PDF_FILE",0, 1, 0, , , 0
objExcel.ActiveWorkbook.Close
objExcel.Application.Quit
An alternative is to use a VB script and call it from Java.
Example:
xl2pdf.vbs
Option Explicit
Dim objExcel, strExcelPath, objSheet
strExcelPath = "$XL_FILE"
Set objExcel = CreateObject("Excel.Application")
objExcel.WorkBooks.Open strExcelPath
Set objSheet = objExcel.ActiveWorkbook.Worksheets(1)
objSheet.ExportAsFixedFormat 0, "$PDF_FILE",0, 1, 0, , , 0
objExcel.ActiveWorkbook.Close
objExcel.Application.Quit
In Java (actually kotlin, but easy to translate)
fun xl2pdf(xlFile: Path, pdfFile: Path, timeout: Long = 1, timeUnit: TimeUnit = TimeUnit.MINUTES) {
val tempScript = Files.createTempFile("script", ".vbs")
val script = Files.readAllLines(Paths.get("xl2pdf.vbs"))
.map { it.replace("\$XL_FILE", "$xlFile") }
.map { it.replace("\$PDF_FILE", "$pdfFile") }
Files.write(tempScript, script)
try {
val pb = ProcessBuilder("wscript", tempScript.toString())
val process = pb.start()
val success = process.waitFor(timeout, timeUnit)
if (!success) LOG.error("Could not print PDF within $timeout $timeUnit")
} catch (e: IOException) {
LOG.error("Error while printing Excel file to PDF", e)
}
}
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>http://repo.e-iceblue.com/nexus/content/groups/public/</url>
</repository>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.xls.free</artifactId>
<version>5.1.0</version>
</dependency>
import com.spire.xls.FileFormat;
import com.spire.xls.Workbook;
import java.io.File;
public class EIceblueConverter {
public static void main(String[] args) {
for (Sources xls : Sources.values()) {
if (isFileExists(xls)) convert(xls);
}
}
private static boolean isFileExists(Sources xls) {
File file = new File(xls.getPath());
return file.exists() && file.isFile();
}
private static void convert(Sources xls) {
Workbook workbook = new Workbook();
workbook.loadFromFile(xls.getPath());
workbook.getConverterSetting().setSheetFitToPage(true);
workbook.saveToFile(Util.getOutputPath(xls.getPath()), FileFormat.PDF);
}
}
Before converting you should edit view area in file.xls*
... and more convertors, including the interesting solution: use libre office as converter .xls* to .pdf.
(do test it in src/main/java/jodconverter/AppStarter.java)
https://github.com/fedor83/xlsToPdfConverter.git
Here is the full fledge working example
Dependencies :
compile 'com.itextpdf:itextpdf:5.5.13.2'
compile 'org.apache.poi:poi-ooxml:5.0.0'
Java code:
import java.io.*;
import org.apache.poi.ss.usermodel.*;
import java.util.Iterator;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
public class Excel2PDF {
public static void main(String[] args) throws Exception {
Workbook my_xls_workbook = WorkbookFactory.create(new File("/Users/harshad/Desktop/excel.xlsx"));
Sheet my_worksheet = my_xls_workbook.getSheetAt(0);
short availableColumns = my_worksheet.getRow(0).getLastCellNum();
System.out.println("Available columns : " + availableColumns);
Iterator<Row> rowIterator = my_worksheet.iterator();
Document iText_xls_2_pdf = new Document();
PdfWriter.getInstance(iText_xls_2_pdf, new FileOutputStream("/Users/harshad/Desktop/excel.pdf"));
iText_xls_2_pdf.open();
PdfPTable my_table = new PdfPTable(availableColumns);
PdfPCell table_cell = null;
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
switch (cell.getCellType()) {
default:
try {
table_cell = new PdfPCell(new Phrase(cell.getStringCellValue()));
} catch (IllegalStateException illegalStateException) {
//TODO: Need to handle exceptions for different type too
if (illegalStateException.getMessage().equals("Cannot get a STRING value from a NUMERIC cell")) {
table_cell = new PdfPCell(new Phrase(String.valueOf(cell.getNumericCellValue())));
}
}
my_table.addCell(table_cell);
break;
}
}
}
iText_xls_2_pdf.add(my_table);
iText_xls_2_pdf.close();
my_xls_workbook.close();
}
}
I'm supposed to realize a Java application that should retrieve data out of an excel spreadsheet and link it to some objects I've already created in order to apply some calculations on them, then display the result .
About the app
==> The excel spreadsheet is a survey to measure a bank's clients satisfaction about the bank's services.
==> The application should parse the data in the spreadsheet, and do some calculations on it.
==> The result should be displayed using an interactive GUI .
What I've done so far
I've analysed to problem and create all the objects I will need in my application.
I Actually did some search here on stackoverflow.com and think that Apache POI would be very useful.
Where I need help
The problem is that I have no idea about what I should begin with .
Any suggestions on how to accomplish this , what tools, languages, API or design pattern I should use is more than welcome.
I disagree with your choice of POI. I think Andy Khan's JExcel is far superior.
I'd wonder why an Excel spreadsheet and not a relational database.
This sounds like a standard layered web application. The best advice is to break the problem into pieces:
Acquire the data
Perform the calculations
Write the UI to display them.
Get each piece working and tested separately, then put it aside. Work your way through the layers, one by one.
you might already be having the apache POI library , this might help you get started on source code basis
import java.io.*;
import java.util.Iterator;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ReadExcelFile {
public static void main(String[] args)
{
try {
FileInputStream file = new FileInputStream(new File("C:/Users/hussain.a/Desktop/mar_25/Tradestation_Q4 Dashboard_Week 5_1029-1104.xlsx"));
XSSFWorkbook workbook = new XSSFWorkbook(file);
XSSFSheet sheet = workbook.getSheetAt(0);
Iterator<Row> rowIterator = sheet.iterator();
rowIterator.next();
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();
switch(cell.getCellType())
{
case Cell.CELL_TYPE_BOOLEAN:
System.out.println("boolean===>>>"+cell.getBooleanCellValue() + "\t");
break;
case Cell.CELL_TYPE_NUMERIC:
System.out.println("numeric===>>>"+cell.getNumericCellValue() + "\t");
break;
case Cell.CELL_TYPE_STRING:
System.out.println("String===>>>"+cell.getStringCellValue() + "\t");
break;
}
}
System.out.println("");
}
file.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}