I am having 2 issues using the apache POI to write data from a csv into an excel file.
The data consists of dates, and numbers
The issues are:
1) The numbers are written as strings.
2) Excel cannot read the date format (this messes the graphs up)
The code (that I received help with previously):
String name = "test";
Sheet sheet = wb.getSheet(name);
if (sheet == null) {
sheet = wb.createSheet(name);
}
int rowCount = 0;
Scanner scanner = new Scanner(new File("/tmp/" + name + ".csv"));
while (scanner.hasNextLine()) {
String[] rowData = scanner.nextLine().split(",");
for (int col = 0; col < rowData.length; col++) {
Row row = sheet.getRow(rowCount);
if (row == null)
row = sheet.createRow(rowCount);
Cell cell = row.getCell(col);
if (cell == null) {
cell = row.createCell(col);
}
cell.setCellValue(rowData[col]);
}
rowCount++;
}
wb.write(new FileOutputStream(excel));
}
1) I tried using Double.parseDouble(rowData[col]) when entering the data into the excel file. but this gives an empty string error. I even set the cell format with style.setDataFormat(format.getFormat("#,##0.0000")); but it still does not work
2) I tried using the date format cellStyle.setDataFormat(createHelper.createDataFormat().getFormat("m/d/yyyy hh:mm:ss")); but still the excel graphs can't read this format. (when I manually copy and paste from the csv file it works).
So basically, when copying data using the apache poi, none of the other data that relies on the copied cells is updated.
for example if a cell has a value of the average of 100 cells, and I manually copy data into those cells, it updates automatically. But when it copies through java, the cells do not update.
The following should do something more.
try {
double value = Double.parseDouble(rowData[col]);
cell.setCellValue(value);
} catch (NumberFormatException | NullPointerException e) {
String value = rowData[col];
cell.setCellValue(value);
}
(However you might not use Apache POI and straight copy the CSV file to a .xls, if
it is just a need for double-click reading by Excel.)
Related
I am looking for a way to export a JTable with data to a .csv file. But I didn't find a good method to do that. It works and generates the csv file. But There is a problem. When there is data in a jTable column like this,
|column 1|column 2|
-------------------
|Java, C#|PHP |
The result is,
column 1,column2,
Java,C#,PHP,
So the problem id there are only 2 columns and 2 data columns but for CSV file, there are 3 data columns. When importing that CSV file to the Excel sheet it is completely wrong. Data went to different locations.
So is there another way to do this in Java or any way to avoid this problem?
Thanks for the help in advance! Best Regards.
I use the following code.
public void ExportToCSVfile(JTable table) throws IOException, ClassNotFoundException
{
Writer writer = null;
DefaultTableModel defaultTableModel = (DefaultTableModel) table.getModel();
int Row = defaultTableModel.getRowCount();
int Col = defaultTableModel.getColumnCount();
try {
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("file.csv"), "utf-8"));
StringBuffer bufferHeader = new StringBuffer();
for (int j = 0; j < Col; j++) {
bufferHeader.append(defaultTableModel.getColumnName(j));
if (j!=Col) bufferHeader.append(", ");
}
writer.write(bufferHeader.toString() + "\r\n");
for (int i = 0 ; i < Row ; i++){
StringBuffer buffer = new StringBuffer();
for (int j = 0 ; j < Col ; j++){
buffer.append(defaultTableModel.getValueAt(i,j));
if (j!=Col) buffer.append(", ");
}
writer.write(buffer.toString() + "\r\n");
}
} finally {
writer.close();
}
}
So is there another way to do this in Java or any way to avoid this problem?
I don't know all the rules of a CSV formatted file but I believe for something this simple where a cell contains a "," you can just delimit the entire text of the cell.
So the ouput of your file should be:
column 1,column2,
"Java,C#",PHP,
This is easy to verify you just create a simple spreadsheet where the cell contains a comma and then you export the spreadsheet to a .csv file and check the format of the file in a text editor.
I think you can delimit all data with "..." even if it doesn't contain a comma but you will need to verify that.
So you need to modify your export code to include the delimiters.
I am trying to update excel file using java.
We have multiple servers whose health i.e. disk space need to be checked every Friday by logging into those servers and check size and also delete some files which are older than month.. and then fill into excel about disk space and then log off.
But now I am trying to automate the tasking using Java.
I successfully checked disk size and deleted files which are older than a month also put that data into excel files.
public class UpdateExcel
{
public static void main(String[]args) throws
EncryptedDocumentException, InvalidFormatException, IOException
{
File f=new File("D:\\TestDeleteFiles");
String list[]=f.list();
Calendar lCal = Calendar.getInstance();
lCal.add(Calendar.DATE, -30);
for(int i=0;i<list.length;i++)
{
System.out.println(list[i]);
File tmpFile=new File("D:\\TestDeleteFiles\\"+list[i]);
Date date=new Date(tmpFile.lastModified());
if(date.before(lCal.getTime()))
{
tmpFile.delete();
System.out.println("Deleted");
}
}
try {
FileSystemView fsv = FileSystemView.getFileSystemView();
File[] drives = File.listRoots();
File cDrive = new File("C:\\");
File dDrive = new File("D:\\");
System.out.println("Drives are : " +cDrive);
System.out.println("Drives are : " +dDrive);
long cTotSpace = cDrive.getTotalSpace();
long cFrSpace = cDrive.getFreeSpace();
long cTotalSpace;
long cFreeSpace;
long dTotSpace = dDrive.getTotalSpace();
long dFrSpace = dDrive.getFreeSpace();
long dTotalSpace;
long dFreeSpace;
cTotalSpace = cTotSpace / (1024*1024*1024);
cFreeSpace = cFrSpace / (1024*1024*1024);
dTotalSpace = dTotSpace / (1024*1024*1024);
dFreeSpace = dFrSpace / (1024*1024*1024);
System.out.println("Total Space in Gb : " + cTotalSpace + " GB");
System.out.println("Free Space in Gb : " + cFreeSpace + " GB");
System.out.println("Total Space in Gb : " + dTotalSpace + " GB");
System.out.println("Free Space in Gb : " + dFreeSpace + " GB");
String excelFilePath = "D:\\CreateXls\\ServerTestDemo.xls";
FileInputStream inputStream = new FileInputStream(new File(excelFilePath));
Workbook workbook = WorkbookFactory.create(inputStream);
Sheet sheet = workbook.getSheetAt(0);
Iterator<Row> iterator = sheet.iterator();
while(iterator.hasNext())
{
Row currentRow = iterator.next();
Cell cell = currentRow.createCell(currentRow.getLastCellNum(), CellType.STRING);
Cell dcell = currentRow.createCell(currentRow.getLastCellNum(), CellType.STRING);
Cell cell1 = currentRow.createCell(currentRow.getLastCellNum(), CellType.STRING);
System.out.println("Hello" + currentRow.getRowNum());
if(currentRow.getRowNum() == 0)
System.out.println("Hello" + currentRow.getRowNum());
cell.setCellValue(cFreeSpace);
dcell.setCellValue(dFreeSpace);
cell1.setCellValue("");
}
inputStream.close();
FileOutputStream outputStream = new
FileOutputStream("D:\\CreateXls\\ServerTestDemo.xls");
workbook.write(outputStream);
workbook.close();
outputStream.close();
} catch (IOException | EncryptedDocumentException
| InvalidFormatException ex) {
ex.printStackTrace();
}
}
}
This code is working well to put disk size in Excel file..This pic will tell you
But now What i want to do is to put Labels like server name on 1st row above IP address as well as Dates on basis of when that code will be executed and C or D drives above that Free space.
Well I tried but cause of Iterator Server name also printed multiple time which i dont want.
NOTE: For information I am not stuck on how to get date and all Its just I am stuck on how to put Labels in First, Second and Third Row without duplication This is demo that's why i took Same IP Address
I'm not clear on what you're asking, perhaps if you showed what you want the excel sheet to look like someone could assist you.
Based on your description I'm presuming you want row 1 to have headers, it also appears you are using Apache POI. If that is the case you may want to read this post: How to add header column in excel using Java Apache POI?
It is not necessary to iterate through the rows for updating values in a row. You can just get the row using its index and update cell values.
Row row = sheet.getRow(0);
In case the row is null, just create a row and update the cell values.
if(row == null)
{
row = sheet.createRow(0);
}
I'm reading xlsx file using SimpleXLSXWorkbook class, below is the code.
public static void testLoadALL( ) {
SimpleXLSXWorkbook workbook =new SimpleXLSXWorkbook(new File("C:/Users/balamurugan.ar/Desktop/eclipse_wrkSce/Base Rates_12_05_2017.xlsx"));
Sheet sheetToRead = workbook.getSheet(0);
List<Cell[]> rows = sheetToRead.getRows();
for (Cell[] row : rows) {
for (Cell cell : row) {
System.out.println(cell.getValue());
}
}
}
In my xlsx file, having few decimal data in cell. While iterating the decimal cell, i'm getting extra numbers.
ie. Original Data in xlsx is 15.2315,
In java while iterating cell, getting extra decimal numbers 15.23149999999999999.
How to get the original decimal data?
I am using Apache POI to create new XSSFWorkbook from an existing one, after updating some values. Suppose I have two worksheets (Lets say: worksheet A & B) in my existing workbook. Worksheet B has some cell reference from Worksheet A. IF i modify those cell values of worksheet A and save them as a new workbook, corresponding cell values of worksheet B should be updated too. But it doesn't. How can i update them programmatically? . Thank you.
My code:
public void createExcel(ClientData cd) throws FileNotFoundException, IOException, InvalidFormatException{
// create a new file
double[] dataHolder1= cd.getFinalData1(), param1 = cd.getRecord1Param();
double[] dataHolder2 = cd.getFinalData2(), param2 = cd.getRecord2Param();
double[] ncv = cd.getNcv();
String[] pname = cd.getName();
Workbook workbook = new XSSFWorkbook(OPCPackage.open(new FileInputStream("template/mncv.xlsx"))); // or sample.xls
//CreationHelper createHelper = workbook.getCreationHelper();
Sheet s=workbook.getSheetAt(0);
int counter = dataHolder1.length + param1.length +param2.length+dataHolder2.length;//+ param1.length + param2.length;
// r = s.getRow(0);
// r.getCell(0).setCellValue("Param1");
// r.getCell(1).setCellValue("Record1");
// r.getCell(2).setCellValue("Param2");
// r.getCell(3).setCellValue("Record2");
int i;
for(i=0;i<counter;i++){
if(i<param1.length){
for(int j=0;j<param1.length;j++){
r = s.getRow(i);
r.getCell(0).setCellValue(param1[j]);
i++;
}
}else if(i<dataHolder1.length+param1.length && i>=param1.length){
for(int j=0;j<dataHolder1.length;j++){
r = s.getRow(i);
r.getCell(0).setCellValue(dataHolder1[j]);
i++;
}
}else if(i<dataHolder1.length+param1.length+param2.length && i>=dataHolder1.length+param1.length){
for(int j=0;j<param2.length;j++){
r = s.getRow(i);
r.getCell(0).setCellValue(param2[j]);
i++;
}
}else{
for(int j=0;j<dataHolder2.length;j++){
r = s.getRow(i);
r.getCell(0).setCellValue(dataHolder2[j]);
i++;
}
}
// if(i<=param1.length){
// r.getCell(0).setCellValue(param1[i-1]);
// r.getCell(2).setCellValue(param2[i-1]);
//
// }
// r.getCell(0).setCellValue(param1[i]);
//r.getCell(3).setCellValue(dataHolder2[i-1]);
i--;
}
for(int k=0;k<ncv.length;k++){
r = s.getRow(i);
r.getCell(0).setCellValue(ncv[k]);
i++;
}
s = workbook.getSheetAt(1);
s.getRow(2).getCell(5).setCellValue(pname[0]+" "+pname[1]+" "+pname[2]);
s.getRow(3).getCell(5).setCellValue(cd.getAge());
s.getRow(4).getCell(5).setCellValue(cd.getGender());
try (FileOutputStream out = new FileOutputStream("workbook.xlsx")) {
//WorkbookEvaluator we = new WorkbookEvaluator(workbook);
workbook.write(out);
out.close();
XSSFFormulaEvaluator.evaluateAllFormulaCells((XSSFWorkbook) workbook);
}catch(Exception e){
System.out.println(e);
}
The Excel file format caches the result of formula evaluation, to make opening the file quicker. This means that when you're done making changes to your file, you'll need to evaluate all of the formula cells to updated their cached value. (Otherwise, when you load the file in Excel, for almost all cases it'll still show the old value until you go into that cell)
Luckily, Apache POI provides code to do that, see the Formula Evaluation documentation for details. (You can choose to only recalculate certain formulas, if you know just those cells have changed, or do everything)
For any cell, say "B5", at runtime,
cell.getReference();
will give you cell reference (like in example... it will return you "B5")
cell.getReference().toString().charAt(0);
will give you the Column Reference (will give you "B" if the current cell is B5). Now
cell.getRowIndex();
OR
cell.getReference().toString().charAt(1);
will give you Row Index. Now you have the reference of the target cell. just replace these character with the references you have already created. This will update the cell references.
The following solution worked for me
wb.setForceFormulaRecalculation(true);
// replace "wb" with your HSSFWorkbook/XSSFWorkbook object
How to delete contents of an Excel sheet in an Excel workbook, using Java SE and Apache POI?
As mentioned in previous comments
Sheet sheet = wb.getSheetAt(0);
for (Row row : sheet) {
sheet.removeRow(row);
}
this code throwing ConcurrentModificationException to me. So, I have modified the code and it's working fine. Here is the code:
Sheet sheet = wb.getSheetAt(0);
Iterator<Row> rowIte = sheet.iterator();
while(rowIte.hasNext()){
rowIte.next();
rowIte.remove();
}
I've found that removeSheetAt/createSheet isn't really an acceptable answer, because you can't put the new sheet into the correct position in the workbook without running into a bug in WorkSheet.setSheetOrder
This code snippet
Sheet sheet = wb.getSheetAt(0);
for (Row row : sheet) {
sheet.removeRow(row);
}
in my world throws a ConcurrentModificationException
I had to resort to
for (int index = crnt.getLastRowNum(); index >= crnt.getFirstRowNum(); index--) {
crnt.removeRow( crnt.getRow(index));
}
Depending on what contents you want to delete you may remove a single cell or row.
Too erase the complete sheet iterate over all rows and delete it.
Sheet sheet = wb.getSheetAt(0);
for (Row row : sheet) {
sheet.removeRow(row);
}
I know this is an old thread but I think I found the best solution
What I did was just create a new workbook of the same type and save it over the file that I wanted to delete.
Heres the code
private void clearOldFile(){
FileOutputStream out = null;
try{
oldFile = new XSSFWorkbook();
Sheet sheet = oldFile.createSheet("temp data");
out = new FileOutputStream(AbsolutePathForTempExcelFile);
oldFile.write(out);
out.close();
} catch(Exception e){
e.printStackTrace();
}
}
You probably want to use HSSFWorkbook.removeSheetAt(index).
I guess it is an old thread but I also get ConcurrentModificationException. Based on VoiceOfUnreason I found this to work:
while (xlsSheet.getPhysicalNumberOfRows() > 0) {
xlsSheet.removeRow(xlsSheet.getRow(xlsSheet.getLastRowNum()));
}
if (xlsSheet.getDrawingPatriarch() != null) {
xlsSheet.getDrawingPatriarch().clear();
}
I also got concurrent modification exception, also using the more "modern" way of doing it :
sheet.forEach(r->sheet.remove(r));
The iterator based solution from #Thirupathi S apparently worked, but for reasons I don't exactly know it was creating xslx files that were not readable by Apple's Numbers and OSX preview (and probably other softwares too).
I suspect this has something to do with the iterator not removing something: the code of the removeRow method is way more complex than the simple iterator remove operation.
Using old plain for-loop with reversed index worked like a charm :
for (int i = sheet.getLastRowNum(); i >= 0; i--) {
sheet.removeRow(sheet.getRow(i));
}
This solution works fine with me. And also consider special cases, e.g. the sheet is blank, or the spaces between the firstRow and lastRow are present.
public void cleanSheet(Sheet sheet) {
int numberOfRows = sheet.getPhysicalNumberOfRows();
if(numberOfRows > 0) {
for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) {
if(sheet.getRow(i) != null) {
sheet.removeRow( sheet.getRow(i));
} else {
System.out.println("Info: clean sheet='" + sheet.getSheetName() + "' ... skip line: " + i);
}
}
} else {
System.out.println("Info: clean sheet='" + sheet.getSheetName() + "' ... is empty");
}
}
My reason for not deleting and recreating sheet: Keep references to sheet-scoped names working.
for(int i = sheet.getLastRowNum(); i >= 0; i--)
{
Row row = sheet.getRow(i);
if(row != null)
{
sheet.removeRow(row);
}
}
The other iterator methods appeared to work but Excel then refused to open the file.
This one worked for me:
int rownum;
while ((rownum=sheet.getLastRowNum()) > 0) sheet.removeRow(sheet.getRow(rownum));