apache POI merge cells with data resulting in data loss - java

We are displaying a number and a percent like "2 (100%)" in each cell.
I would like to apply different formatting to the Number part and percentage part. It seems not possible to apply different formatting, within a cell.
So I'm trying to write data into 2 consecutive cells, which have different formatting and then merge it.
But after merging , the data in the second cell is lost.
How can I merge, with both cells data merged to single cell ?
HSSFFont percentFont = wb.createFont();
percentFont.setFontName(HSSFFont.FONT_ARIAL);
percentFont.setFontHeightInPoints((short) 10);
percentFont.setBold(true);
percentStyle.setFont(percentFont);
for (int i = 0; i < rows.size(); i++) {
List<String> rowData = rows.get(i);
int rowNumber = 9 + i;
HSSFRow row1 = sheet.createRow(rowNumber);
int colNumber = 0;
for (int j = 0; j < count; j++) {
HSSFCell hssfMainCell = row1.createCell(colNumber);
HSSFCell hssfPercentCell = row1.createCell(colNumber + 1);
hssfPercentCell.setCellStyle(percentStyle);
String val = rowData.get(j);
String percentage = "(" + rowData.get(percentageColumns.get(j)) + "%)";
;
hssfMainCell.setCellValue(val);
hssfMainCell.setCellStyle(rightAligned);
if (percentageColumns.get(j) != null) {
hssfPercentCell.setCellValue(percentage);
percentStyle.setAlignment(CellStyle.ALIGN_RIGHT);
hssfPercentCell.setCellStyle(percentStyle);
sheet.addMergedRegion(new CellRangeAddress(rowNumber, rowNumber, colNumber, colNumber + 1));
colNumber++;
colNumber++;
}
}
}

Related

Inserting new table row with different column number with Apache poi

I have a Word table with 1 row and 2 columns, and I want to insert a new row with 3 columns using Apache poi with Java. What I want to achieve is this:
But what I get is this:
I have searched the Internet for a solution but all I get was about setting column width which does not work for my case. Could anyone help me with this problem?
This is my code which I took from one of the examples in Stack Overflow to work around that yield the output shown in second picture:
File file = new File("C:\\Users\\USER\\Desktop\\testdoc.docx");
XWPFDocument doc = new XWPFDocument(new FileInputStream(file));
FileOutputStream out = new FileOutputStream(file);
XWPFTable table = doc.getTableArray(0);
XWPFTableRow oldRow = table.getRow(0);
table.insertNewTableRow(1);
XWPFTableRow newRow = table.getRow(1);
int indWidth = 0;
for(int i=0; i < oldRow.getTableCells().size(); i++) {
int sum = 0;
BigInteger width = oldRow.getCell(i).getCTTc().getTcPr().getTcW().getW();
sum += width.intValue();
indWidth = sum/oldRow.getTableCells().size();
}
XWPFTableCell cell;
for (int i = 0; i < 3; i++) {
cell = newRow.createCell();
CTTcPr ctTcPr = cell.getCTTc().addNewTcPr();
CTTblWidth cellWidth = ctTcPr.addNewTcW();
cellWidth.setType(oldRow.getCell(0).getCTTc().getTcPr().getTcW().getType()); // sets type of width
BigInteger width = BigInteger.valueOf(indWidth);
cellWidth.setW(width); // sets width
if (oldRow.getCell(0).getCTTc().getTcPr().getGridSpan() != null) {
ctTcPr.setGridSpan(oldRow.getCell(0).getCTTc().getTcPr().getGridSpan()); // sets grid span if any
}
XWPFRun run = cell.getParagraphs().get(0).createRun();
run.setText("NewRow C" + i);
}
doc.write(out);
doc.close();
System.out.println("Done");
}
I can propose a solution, for the java world, but not with poi...
With pxDoc (www.pxdoc.fr, disclaimer: I am one of its authors...), this can be perfectly achieved with the following code :
document {
table {
row {
cell { "Column 1" }
cell { "Column 2" }
}
row {
for (var i = 0; i < 3; i++) {
cell {
"NewRow C" + i
}
}
}
}
}

printing data columnwise in same workbook - java poi

I am using Java and POI to print some data to excel files. I think I am just missing a small logic to solve this question. I have data stored in array lists in following format:
a = [1,2,3] // arraylist
b = [4,5,6] // arraylist
c = [7,8,9] // arraylist
I want to print this data columnwise to excel file in below given format:
1 | 4 | 7
2 | 5 | 8
3 | 6 | 9
The code that I am using is as below:
public final_out = new FileOutputStream(new File(final_output_path));
public XSSFWorkbook workbook = new XSSFWorkbook();
public XSSFSheet sheet = workbook.createSheet("data_vertical_final");
public Row row;
for (int i=0; i < a.size(); i++) {
String value = a.get(i);
row = sheet.createRow(i);
Cell cell = row.createCell(13);
cell.setCellValue(value);
}
for (int i=0; i < b.size(); i++) {
String value = b.get(i);
row = sheet.createRow(i);
Cell cell = row.createCell(15);
cell.setCellValue(value);
}
for (int i=0; i < c.size(); i++) {
String value = a.get(i);
row = sheet.createRow(i);
Cell cell = row.createCell(17);
cell.setCellValue(value);
}
workbook.write(final_out);
workbook.close();
final_out.close();
Error I am getting:
There is no error, but everything is getting overwritten in new excel file and the final output looks broken. Do I need to make new workbooks for every loop? or there is something I am missing.
P.S:
The data that is shown below is just an example. Some of my original files that I am using are between 1000 to 2000 values or maybe more.
I want to dynamically create the rows and extract the values from arraylists and store it in rows that I created.
Create only a.size() rows,
not a.size() squared rows.
Don't overwrite them in your code.
I assume that a.size() == b.size() and b.size() == c.size().
public List<Row> rows = new ArrayList<Row>(a.size());
for (int i=0; i < a.size(); i++) {
rows.add(sheet.createRow(i));
}
for (int i=0; i < a.size(); i++) {
String value = a.get(i);
Cell cell = rows.get(i).createCell(13);
cell.setCellValue(value);
}
for (int i=0; i < b.size(); i++) {
String value = b.get(i);
Cell cell = rows.get(i).createCell(15);
cell.setCellValue(value);
}
for (int i=0; i < c.size(); i++) {
String value = a.get(i);
Cell cell = rows.get(i).createCell(17);
cell.setCellValue(value);
}
If you already solve the problem:
It would be even cleaner to place a, b and c into one collection and use only one loop to iterate through them (in place of 3 separate loops).
I assume that a is the longest list.
Check this out:
public List<Row> rows = new ArrayList<>(a.size());
for (int i=0; i < a.size(); i++) {
rows.add(sheet.createRow(i));
}
List<List<String>> alphabet = new ArrayList<>();
alphabet.add(a);
alphabet.add(b);
alphabet.add(c);
for(int i=0; i < alphabet.size(); i++) {
for (int j=0; j < alphabet.get(i).size(); j++) {
String value = alphabet.get(i).get(j);
Cell cell = rows.get(j).createCell(13 + i*2); //<- 13, 15, 17...
cell.setCellValue(value);
}
}

Apache poi how to get cell coordinates

I try to get a cell's coordinates, right now I write next code:
for (Row row : sheet) {
for(Cell cell : row){
// how to get a cell coordinates?
}
}
How can I get a cell's coordinates (dx1, dx2, dy1, dy2) ?
the shortest way to get cell address is:
cell.getAddress().formatAsString()
to get sheet name do the following
cell.getSheet().getSheetName()
The obvious solution was suggested by user2310289, but that won't work as the iterators skip over blank rows and cells.
So, one option is to iterate manually, taking care of blank cells, and then you'll always know where you cell is, with code something like:
// Decide which rows to process
int rowStart = Math.min(15, sheet.getFirstRowNum());
int rowEnd = Math.max(1400, sheet.getLastRowNum());
for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) {
Row r = sheet.getRow(rowNum);
int lastColumn = Math.max(r.getLastCellNum(), MY_MINIMUM_COLUMN_COUNT);
for (int cn = 0; cn < lastColumn; cn++) {
Cell c = r.getCell(cn, Row.RETURN_BLANK_AS_NULL);
if (c == null) {
// The spreadsheet is empty in this cell
} else {
// Do something useful with the cell's contents
CellReference cr = new CellReference(c);
System.out.println("Cell at " + rowNum + "," + cn + " found, that's " + cr.formatAsString());
}
}
}
Or, if you do want to use the easy iterators, you need to look up the row and cell index from a cell, eg
for (Row r : sheet) {
for (Cell c : r) {
int columnNumber = c.getColumnIndex();
int rowNumber = c.getRow().getRowNum();
CellReference cr = new CellReference(c);
System.out.println("Cell at " + rowNum + "," + columnNumber + " found, that's " + cr.formatAsString());
}
}
I have done following code for getting coordinates of the excel cell. Hope this will help you.
public static void searchSheet(String searchText, XSSFSheet sheet)
{
int flag=0;
for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++)
{
XSSFRow row = sheet.getRow(i);
for (int j = row.getFirstCellNum(); j < row.getLastCellNum(); j++)
{
XSSFCell cell = row.getCell(j);
String CellData=cell.toString();
if(searchText.equals(CellData))
{
flag=1;
CellData=row.getCell(j+1).toString();
System.out.println(CellData);
System.out.println("String Found At Row="+ i +" and At Column="+j);
}
}
break;
}
if(flag==0)
{
System.out.println("String Not Found");
}
}

How to write an excel table starting from the last value?

I am using JXL api. I want to fill an excel table that already have content, like:
123 321 12324
123 321 231
123 321 343
123 321 454
123 321 565
I am trying to write the next value after the fifth line, but I dont know how to do it. I only know how to create and write an excel table if it is empty. And I know how to read it. I was thinking that first I have to read it, and my array which would contain the values of the table would help me to pick the last value of the table then I would write the other values starting from there. I have these methods:
To read:
arquivo = new File("C:\\Users\\maniceto\\Desktop\\arq.xls");
planilha = Workbook.getWorkbook(arquivo);
Sheet[] abas = planilha.getSheets();
aba = planilha.getSheet(0);
matriz = new String[aba.getRows()][aba.getColumns()];
Cell[] cel;
for (int i = 0; i < matriz.length; i++) {
cel = aba.getRow(i);
for (int j = 0; j < matriz[0].length; j++) {
matriz[i][j] = cel[j].getContents();
}
}
System.out.println("Lines " + matriz.length);
System.out.println("Columns " + matriz[0].length);
System.out.println("");
for (int i = 0; i < matriz.length; i++) {
for (int j = 0; j < matriz[0].length; j++) {
System.out.print(matriz[i][j] + "\t");
}
System.out.println("");
}
To write an empty excel table:
WritableWorkbook workbookVazio = Workbook.createWorkbook(file);
WritableSheet sheet1 = workbookVazio.createSheet("First Sheet", 0);
TableModel model = table.getModel();
for (int i = 0; i < model.getColumnCount(); i++) {
Label column = new Label(i, 0, model.getColumnName(i));
sheet1.addCell(column);
}
int j = 0;
for (int i = 0; i < model.getRowCount(); i++) {
for (j = 0; j < model.getColumnCount(); j++) {
Label row = new Label(j, i + 1,
model.getValueAt(i, j).toString());
sheet1.addCell(row);
}
}
workbookVazio.write();
workbookVazio.close();
As stated by rgettman in this question, I would also advise to use Apache POI to handle Excel files with JAVA.
To append values using POI, you just need to get the current number of rows :
int rows = sheet.getPhysicalNumberOfRows();
POI is well documented and you will easily find several code examples on the net.
you could try something like
int lastRowNum = workbookVazio.getSheet("First Sheet").getLastRowNum();
int nextFreeRow = lastRowNum+1;
or you can use Apache POI theres a good tutorial here.

Excel is missing some values while writing

I am new to Apache-poi and using 3.8 version of poi. While writing value in the Excel,i check for the column names if they matched, i will write some value in that column and finish it, and again i will start writing on header. The problem is if write three column values only last column values are add or saved and first two values are not saved in the column. Can anyone tell what went wrong.
(sorry, in case any mistake)
Code:
int i = 0;
Row row = sheet.createRow(i);
CellStyle cellStyle = workbook.createCellStyle();
cellStyle.setFillBackgroundColor(HSSFColor.LIGHT_ORANGE.index);
String validate_header = null;
while (iterator.hasNext()) {
if (eiterator.hasNext()) {
validate_header = eiterator.next();
}
Cell cell = row.createCell(i);
String col_heading = iterator.next();
cell.setCellValue(col_heading);
if(col_heading.equalsIgnoreCase("Assigned Date"))
{
Add_value(i, col_heading, row, sheet);
row=sheet.getRow(0);
cell=row.getCell(i);
}
else if(col_heading.startsWith("Review"))
{
int count=-1;
int n=Col_values.get("Defect Summary").size();
for (int j = 0; j < n; j++) {
row = sheet.createRow(count);
cell = row.createCell(i);
String s="External QC Defect ";
cell.setCellValue(s);
count++;
}
row=sheet.getRow(0);
cell=row.getCell(i);
}
sheet.autoSizeColumn(i);
i++;
}
private static Sheet Add_value(int k,String name,Row row, Sheet sheet) {
System.out.println("Inside the add method");
if(name.equalsIgnoreCase("Assigned Date")||name.equalsIgnoreCase("Reported Date") )
{
vector = Col_values.get("TargetDate");
int count = 1;
System.out.println("IF Size of the vector " + vector.size());
for (int j = 0; j < vector.size(); j++) {
row = sheet.createRow(count);
cell = row.createCell(k);
String s = (String) vector.get(j);
System.out.println(s);
cell.setCellValue(s);
count++;
}
}
else
{
vector = Col_values.get("Defect Summary");
int count = 1;
System.out.println("ELSE Size of the vector " + vector.size());
for (int j = 0; j < vector.size(); j++) {
row = sheet.createRow(count);
cell = row.createCell(k);
String s = (String) vector.get(j);
System.out.println(s);
cell.setCellValue(s);
count++;
}
}
return sheet;
}
'
Can u tell what went Wrong?
It seems that Add_value starts creating rows from top. Therefore on the second call the old rows are removed.
Replace
row = sheet.createRow(count);
with
row = k == 0 ? sheet.createRow(count) : sheet.getRow(count);

Categories