I'm trying to remove a row in a excel sheet using java.
But my code isn't removing anything.
This is my code for removing the last row.
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.usermodel.Sheet;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
final String filepath = "data-DB.xlsx";
File workbookFile = new File(filepath);
FileInputStream in = new FileInputStream(workbookFile);
Workbook database = WorkbookFactory.create(in);
Sheet sheet = database.getSheet("Users");
int lastRow = sheet.getLastRowNum();
Row row = sheet.getRow(lastRow);
sheet.removeRow(row);
}
}
This line should get the row
Row row = sheet.getRow(lastRow);
This should remove the row.
sheet.removeRow(row);
What am I doing wrong?
The documentation for getLastRowNum says :
Gets the last row on the sheet Note: rows which had content before and
were set to empty later might still be counted as rows by Excel and
Apache POI, so the result of this method will include such rows and
thus the returned value might be higher than expected!
So most probably you'll get getting a row number which is empty already and you are trying to remove that, and you'r seeing that removeRow is not working.
Print or debug the value of lastRow to fix the error
Related
I am using Apache POI to edit an existing file. This file contains multiple formulas that use the numbers that will be inputted through Apache. And this is where I run into problems, when a number is inputted and that cell is being used in a formula, the file gets corrupted and the formula disappears.
Here the formulas for the 0 are C7+D7, C8+D8, etc.
Here the formulas for the 0 became normal 0, the formulas got lost.
Here is the code I used to write to the excel file:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
public class write {
public static void main(String[] args) {
String excelFilePath = "C:\\Users\\jose_\\IdeaProjects\\writeExcel\\src\\JavaBooks.xlsx";
try {
FileInputStream inputStream = new FileInputStream(new File(excelFilePath));
Workbook workbook = WorkbookFactory.create(inputStream);
Sheet sheet = workbook.getSheetAt(0);
/*Cell cell2Update = sheet.getRow(1).getCell(3); // This updates a specific cell: row 0 cell 3
cell2Update.setCellValue(49);*/
Object[][] bookData = {
{2, 17},
{3, 27},
{4, 33},
{5, 44},
};
// int rowCount = sheet.getLastRowNum(); // Gets the last entry
int rowCount = 5;
for (Object[] aBook : bookData) {
Row row = sheet.createRow(++rowCount);
int columnCount = 1;
int lote = 1;
Cell cell = row.createCell(columnCount);
//cell.setCellValue(rowCount); // This sets the index for each entry
cell.setCellValue(lote);
for (Object field : aBook) {
cell = row.createCell(++columnCount);
if (field instanceof String) {
cell.setCellValue((String) field);
} else if (field instanceof Integer) {
cell.setCellValue((Integer) field);
}
}
}
inputStream.close();
FileOutputStream outputStream = new FileOutputStream("C:\\Users\\jose_\\IdeaProjects\\writeExcel\\src\\JavaBooks.xlsx");
workbook.write(outputStream);
workbook.close();
outputStream.close();
} catch (IOException | EncryptedDocumentException ex) {
ex.printStackTrace();
}
}
}
Is there a way to work around this or do I need to set all the formulas again through Apache POI?
You get the error because using code line Row row = sheet.createRow(++rowCount); you always create new empty rows and so you remove all cells in those rows. So you are also removing the cells containing the formulas. Doing so you are damaging the calculation chain. That's what the Excel GUI tells you with the messages.
You should not do this. Instead you always should try to get the rows first using Sheet.getRow. Only if that returns null then you need to create the row.
...
//Row row = sheet.createRow(++rowCount);
Row row = sheet.getRow(rowCount); if (row == null) row = sheet.createRow(rowCount); rowCount++;
...
Additional please read Recalculation of Formulas. So after changing cells referenced in formulas, do always either workbook.getCreationHelper().createFormulaEvaluator().evaluateAll(); or delegate re-calculation to Excel using workbook.setForceFormulaRecalculation(true);.
I am trying to create an Excel sheet that contains an Excel table using Java with the Apache POI library but I couldn't get a result file that is readable by Microsoft Excel 2016 (Office 365). This is my code:
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
class Scratch {
public static void main(String[] args) throws IOException {
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("Table Sheet");
XSSFRow row0 = sheet.createRow(0);
row0.createCell(0).setCellValue("#");
row0.createCell(1).setCellValue("Name");
XSSFRow row1 = sheet.createRow(1);
row1.createCell(0).setCellValue("1");
row1.createCell(1).setCellValue("Foo");
XSSFRow row2 = sheet.createRow(2);
row2.createCell(0).setCellValue("2");
row2.createCell(1).setCellValue("Bar");
AreaReference area = workbook.getCreationHelper().createAreaReference(
new CellReference(row0.getCell(0)),
new CellReference(row2.getCell(1))
);
sheet.createTable(area);
try(FileOutputStream file = new FileOutputStream(new File("workbook.xlsx"))) {
workbook.write(file);
}
}
}
The code runs fine but when I open the output file in Excel I get a message that the file has unreadable content.
I have tried running the official sample and the result is the same. The official sample can be found here: https://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/xssf/usermodel/examples/CreateTable.java
I need to know the minimum code required to get a readable table.
I am using version 4.0.0 of Apache POI with Oracle JavaSE JDK 1.8.0_172 on Windows 10.
Not sure what happens with the "official sample" codes always. They seems not even be tested.
The CreateTable uses XSSFTable table = sheet.createTable(reference); which creates a table having 3 columns as given from the area reference. But all of those have id 1, so we need repairing. And of course the columns should not be created again then.
So repaired sample code would be:
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
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.XSSFTable;
import org.apache.poi.xssf.usermodel.XSSFTableStyleInfo;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
/**
* Demonstrates how to create a simple table using Apache POI.
*/
public class CreateTable {
public static void main(String[] args) throws IOException {
try (Workbook wb = new XSSFWorkbook()) {
XSSFSheet sheet = (XSSFSheet) wb.createSheet();
// Set which area the table should be placed in
AreaReference reference = wb.getCreationHelper().createAreaReference(
new CellReference(0, 0), new CellReference(2, 2));
// Create
XSSFTable table = sheet.createTable(reference); //creates a table having 3 columns as of area reference
// but all of those have id 1, so we need repairing
table.getCTTable().getTableColumns().getTableColumnArray(1).setId(2);
table.getCTTable().getTableColumns().getTableColumnArray(2).setId(3);
table.setName("Test");
table.setDisplayName("Test_Table");
// For now, create the initial style in a low-level way
table.getCTTable().addNewTableStyleInfo();
table.getCTTable().getTableStyleInfo().setName("TableStyleMedium2");
// Style the table
XSSFTableStyleInfo style = (XSSFTableStyleInfo) table.getStyle();
style.setName("TableStyleMedium2");
style.setShowColumnStripes(false);
style.setShowRowStripes(true);
style.setFirstColumn(false);
style.setLastColumn(false);
style.setShowRowStripes(true);
style.setShowColumnStripes(true);
// Set the values for the table
XSSFRow row;
XSSFCell cell;
for (int i = 0; i < 3; i++) {
// Create row
row = sheet.createRow(i);
for (int j = 0; j < 3; j++) {
// Create cell
cell = row.createCell(j);
if (i == 0) {
cell.setCellValue("Column" + (j + 1));
} else {
cell.setCellValue((i + 1.0) * (j + 1.0));
}
}
}
// Save
try (FileOutputStream fileOut = new FileOutputStream("ooxml-table.xlsx")) {
wb.write(fileOut);
}
}
}
}
Btw.: My code from How to insert a table in ms excel using apache java poi works as well using apache poi 4.0.0. The sheet.createTable() is deprecated. So do using XSSFTable table = sheet.createTable(null); instead. Because the area as well as all other things is set using low level classes. Not even more code than the new example though.
I am using apache poi to extract data from excel sheet and trying to save extracted values in an array.
I am getting java.lang.NullPointerException error.
I searched about it, and apparently this exception triggered when you try to assign a value to an object whose value is null.
I tried to look up many example, but most example codes just print out cell value. I want to save them in an array to perform some calculation.
package exceltotext;
import java.io.*;
import java.lang.*;
import java.util.*;
import org.apache.poi.hssf.usermodel.HSSFCell;
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.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class convert {
#SuppressWarnings("null")
public static void main(String[] args) throws IOException {
double [] modify = null ;
FileInputStream fs = new FileInputStream(new File ("Book1.xlsx"));
XSSFWorkbook wb = new XSSFWorkbook(fs);
XSSFSheet sheet = wb.getSheetAt(0);
FormulaEvaluator formulaevaluater = wb.getCreationHelper().createFormulaEvaluator();
for (Row row:sheet)
{
int num = 0;
for(Cell cell : row){
switch (formulaevaluater.evaluate(cell).getCellType())
{
case Cell.CELL_TYPE_NUMERIC:
modify [num] = ( cell.getNumericCellValue());
num += num;
}
System.out.println(modify[num]);
}
}
}
}
Your modify array is null so num += num; will give you NPE. You need to create this array with for an egzample double [] modify = new double[1000]; instead of double [] modify = null ;
I think, first you need to define the rows, from where you are trying to extract the values.
Apache Poi have option for row i.e XSSFRow.
PS i would personally recommend HSSF instead of XSSF , hence HSSF is for new version of excel. You need to change the file extension name to use in HSSF if the same document is being used by XSSF (Cause of Version Incompatibility).
I am trying the this testfile with the Apache POI API (current version 3-10-FINAL). The following test code
import java.io.FileInputStream;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ExcelTest {
public static void main(String[] args) throws Exception {
String filename = "testfile.xlsx";
XSSFWorkbook wb = new XSSFWorkbook(new FileInputStream(filename));
XSSFSheet sheet = wb.getSheetAt(0);
System.out.println(sheet.getFirstRowNum());
}
}
results in the first row number to be -1 (and existing rows come back as null). The test file was created by Excel 2010 (I have no control over that part) and can be read with Excel without warnings or problems. If I open and save the file with my version of Excel (2013) it can be read perfectly as expected.
Any hints into why I can't read the original file or how I can is highly appreciated.
The testfile.xlsx is created with "SpreadsheetGear 7.1.1.120". Open the XLSX file with a software which can deal with ZIP archives and look into /xl/workbook.xml to see that. In the worksheets/sheet?.xml files is to notice that all row elements are without row numbers. If I put a row number in the first row-tag like <row r="1"> then apache POI can read this row.
If it comes to the question, who is to blame for this, then the answer is definitely both Apache Poi and SpreadsheetGear ;-). Apache POI because the attribute r in the row element is optional. But SpreadsheetGear also because there is no reason not to use the r attribute if Excel itself does it ever.
If you cannot get the testfile.xlsx in a format which can Apache POI read directly, then you must work with the underlying objects. The following works with your testfile.xlsx:
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.InputStream;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetData;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow;
import java.util.List;
class Testfile {
public static void main(String[] args) {
try {
InputStream inp = new FileInputStream("testfile.xlsx");
Workbook wb = WorkbookFactory.create(inp);
Sheet sheet = wb.getSheetAt(0);
System.out.println(sheet.getFirstRowNum());
CTWorksheet ctWorksheet = ((XSSFSheet)sheet).getCTWorksheet();
CTSheetData ctSheetData = ctWorksheet.getSheetData();
List<CTRow> ctRowList = ctSheetData.getRowList();
Row row = null;
Cell[] cell = new Cell[2];
for (CTRow ctRow : ctRowList) {
row = new MyRow(ctRow, (XSSFSheet)sheet);
cell[0] = row.getCell(0);
cell[1] = row.getCell(1);
if (cell[0] != null && cell[1] != null && cell[0].toString() != "" && cell[1].toString() != "")
System.out.println(cell[0].toString()+"\t"+cell[1].toString());
}
} catch (InvalidFormatException ifex) {
} catch (FileNotFoundException fnfex) {
} catch (IOException ioex) {
}
}
}
class MyRow extends XSSFRow {
MyRow(org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow row, XSSFSheet sheet) {
super(row, sheet);
}
}
I have used:
org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet
org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetData
org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow
Which are part of the Apache POI Binary Distribution poi-bin-3.10.1-20140818 and there are within poi-ooxml-schemas-3.10.1-20140818.jar
For a documentation see http://grepcode.com/snapshot/repo1.maven.org/maven2/org.apache.poi/ooxml-schemas/1.1/
And I have extend XSSFRow, because we can't use the XSSFRow constructor directly since it has protected access.
I want to write a MySQL Data into Excel file. In that, I need to create table border for my data as well need to merging the few column headers.
I have done the mapping to Load the MySQL data into Excel Sheet. But I don't know the way to create table border as well merging the column headers.
Below code will help me to Merge the cells, But how to incorporate this code in between my two talend components,
tMySQLInput -> tFileOutputExcel
import java.io.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
public class MergeCellsAcrossColumns {
public static void main(String[] args) throws Exception{
/* Create Workbook and Worksheet */
HSSFWorkbook my_workbook = new HSSFWorkbook();
HSSFSheet my_sheet = my_workbook.createSheet("Merge Cells");
Row row = my_sheet.createRow((short) 1);
Cell cell = row.createCell((short) 1);
cell.setCellValue("Merge Data with Apache POI");
my_sheet.addMergedRegion(new CellRangeAddress(
1, // mention first row here
1, //mention last row here, it is 1 as we are doing a column wise merging
1, //mention first column of merging
5 //mention last column to include in merge
));
/* Write changes to the workbook */
FileOutputStream out = new FileOutputStream(new File("C:\\Merge_Across_Columns.xls"));
my_workbook.write(out);
out.close();
}
}
you can use tJavaRow between your components. This component allows you to write java code and transform data. this component has input and output schema where you can specify input this component will take and output this component will give.
section below for import will move to Advance Settings section of tJavaRow.
import java.io.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
You can write your java code in BAsic Settings section
your refer to input data schema column by
input_row.column_name
and output as output_row.column_name
...(try to user GenerateCode option to see how input_row and output_row works)
Ideally for merging/transforming data you can also use tMap which can merge/transform rows and output the data to next level