Direct addressing of cell in apache POI - java

I want to modify an existing xlsm file with apache POI.
As I only have to change single cells I don't want to loop over the whole sheet, but all the examples I have found so far suggest to loop over all the rows and over all cells in a row, checking if the current row/col-index matches the one to be changed.
Is there no "random access" mode to get a single cell by its coordinates directly? Event the promising getCell method of the CellUtil class needs a row object instead of just an integer coordinate.

The Excel file format is a (normally) sparse file format, so unused + unstyled rows and cells are normally skipped from the file. So, you do need to check for null values when fetching rows and cells. But, other than that, you can fetch cells pretty much directly. You can use the CellReference class to turn an Excel-style set of co-ordinates (eg B3) into a POI-style one (eg row=2, column=1), then fetch
CellReference ref = new CellReference("B3");
Workbook workbook = WorkbookFactory.create(new File("input.xls"));
Sheet sheet = workbook.getSheetAt(0);
Row r = sheet.getRow(ref.getRow());
if (r == null) {
// Handle this whole row being empty
} else {
Cell c = r.getCell(ref.getCol(), Row.RETURN_BLANK_AS_NULL);
if (c == null) {
// Handle this cell being empty
} else {
// Do something with the cell
}
}
Depending on how you want to handle missing rows or cells, you can make it shorter, but that'll be specific to your needs

You get first the row from the sheet and then get the cell at x,y from it:
Row myRow = getRow(int x, sheet);
Cell myCell = getCell(myRow, int y);

Related

How to increase the height of the excel row using Apache-POI having merged cell value greater than the cell width?

I am creating an big excel using java class. Excel contains a merged cell which store string. Length of the string is very large, i am getting this string dynamically. I need to increase the height of the merged cell so that complete string will fit to that cell. I have tried using "wrap text", it wrap the text but doesn't increase the height of the merged cell due to which complete string is not visible in excel.
Java class i am using are:
XSSFWorkbook
XSSFSheet
XSSFRow
XSSFCell
XSSFCellStype
And other required dependent classes.
Is there a way how i can increase the height of the merge cell as per the cell value.
To give you an idea of the challenge how to calculate the needed row height.
We can get the column width in character widths for the columns using Sheet.getColumnWidth(int). But this is not really accurate since it only is for number glyphs: 1,2,3,4,5,6,7,8,9,0. In true type fonts there are glyphs (., |, l, ...) which need much less width. So this result will be as much more inaccurate as such less-width-glyphs are used in the text.
We might correct the column-width-in-chars by a factor. I use 5/4. But this is highly dependent on the language used.
Then we can calculate the needed row count and then get the needed row height by getting the default row height used for one line and multiply that with the needed row count .
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;
public class CreateExcelCellWrapText {
public static void main(String[] args) throws Exception {
XSSFWorkbook workbook = new XSSFWorkbook();
CellStyle cellstyle = workbook.createCellStyle();
cellstyle.setWrapText(true);
Sheet sheet = workbook.createSheet();
//__________________________not merged = height is auto sized
Row row = sheet.createRow(0);
Cell cell = row.createCell(2);
cell.setCellValue("String cell content\nhaving line wrap.");
cell.setCellStyle(cellstyle);
//__________________________merged = height is not auto sized
row = sheet.createRow(2);
cell = row.createCell(2);
cell.setCellValue("String cell content\nhaving line wrap.");
cell.setCellStyle(cellstyle);
CellRangeAddress cellRangeAddress = new CellRangeAddress(2, 2, 2, 3);
sheet.addMergedRegion(cellRangeAddress);
//__________________________merged with calculated height
row = sheet.createRow(4);
String text = "String cell content\nhaving line wrap.\nIt has new line marks and then a long text without new line marks.\nFollowed by short text part.\n\n\nGreetings";
cell = row.createCell(2);
cell.setCellValue(text);
cell.setCellStyle(cellstyle);
cellRangeAddress = new CellRangeAddress(4, 4, 2, 3);
sheet.addMergedRegion(cellRangeAddress);
//get the column width in character widths for the merged columns
//this is not really accurate since it only is for number glyphs: 1,2,3,4,5,6,7,8,9,0
//in true type fonts there are glyps (., |, l, ...) which need much less width
int colwidthinchars = (sheet.getColumnWidth(2) + sheet.getColumnWidth(3)) / 256;
System.out.println(colwidthinchars);
//correct the colwidthinchars by a factor 5/4 (highly dependent on the language used)
colwidthinchars = Math.round(colwidthinchars * 5f/4f);
System.out.println(colwidthinchars);
//calculate the needed rows dependent on the text and the column width in character widths
String[] chars = text.split("");
int neededrows = 1;
int counter = 0;
for (int i = 0; i < chars.length; i++) {
counter++;
if (counter == colwidthinchars) {
System.out.println("new line because of charcter count");
neededrows++;
counter = 0;
} else if ("\n".equals(chars[i])) {
System.out.println("new line because of new line mark");
neededrows++;
counter = 0;
}
}
System.out.println(neededrows);
//get default row height
float defaultrowheight = sheet.getDefaultRowHeightInPoints();
System.out.println(defaultrowheight);
row.setHeightInPoints(neededrows * defaultrowheight);
workbook.write(new FileOutputStream("CreateExcelCellWrapText.xlsx"));
workbook.close();
}
}
This works because default font and font size is used. The challenge increases up to infinity when different fonts and different font sizes are used ;-).
See How to get the needed height of a multi line rich-text field (any font, any font size) having defined width using Java? for an example rendering the formatted text in a JTextPane to get the preferred height.

autoSizeColumn() fails for XSSFSheet

I've copied the loop used and working to autosize columns in HSSFSheet, but for XSSFSheet the cell that is using to adjust the column is not the one wider. This results in columns with "0" width.
XSSFSheet xssfSheet = null;
.....
for (short c = 0; c<11; c++){
xssfSheet.autoSizeColumn(c);
}
Thanks in advance!
Edit: this is done at the very end of the method, no data is added. The problem seems to be that it autosizes to the contents of the last cell added in each column
Please make sure to add text in the column before applying autosize column on it.

iText 7 borderless table (no border)

This code below does not work.
Table table = new Table(2);
table.setBorder(Border.NO_BORDER);
I am new to iText 7 and all I wanted is to have my table borderless.
Like how to do it?
The table itself is by default not responsible for borders in iText7, the cells are. You need to set every cell to be borderless if you want a borderless table (or set the outer cells to have no border on the edge if you still want inside borders).
Cell cell = new Cell();
cell.add("contents go here");
cell.setBorder(Border.NO_BORDER);
table.addCell(cell);
You could write a method which runs though all children of a Table and sets NO_BORDER.
private static void RemoveBorder(Table table)
{
for (IElement iElement : table.getChildren()) {
((Cell)iElement).setBorder(Border.NO_BORDER);
}
}
This gives you the advantage that you can still use
table.add("whatever");
table.add("whatever");
RemoveBorder(table);
instead of changing it on all cells manual.

How to get height and width of excel sheet"named index" area from HSSFWorkbook POI API

How to get height and width of excel sheet named range area from HSSFWorkbook POI API.
I got one reference from google but not able to get height and width of named index area of excel sheet.
Thanks in advance.
Yes it's named range, and want height and width of cells aquired by named range. below code having "print_area" named range and want to height and width of cells.
int namedCellIdx = workbook.getNameIndex("Print_Area");
HSSFName aNamedCell = workbook.getNameAt(namedCellIdx);
// retrieve the cell at the named range and test its contents
String a = aNamedCell.getReference();
AreaReference aref = new AreaReference(aNamedCell.getRefersToFormula());
CellReference[] crefs = aref.getAllReferencedCells();
for (int i=0; i<crefs.length; i++) {
Sheet s = workbook.getSheet(crefs[i].getSheetName());
Row r = sheet.getRow(crefs[i].getRow());
System.out.println(r.getHeight());
System.out.println(sheet.getColumnWidth(crefs[i].getCol()));;
//here want height and width of "Print_area" cells
Cell c = r.getCell(crefs[i].getCol());
System.out.println(c.getStringCellValue());
// extract the cell contents based on cell type etc.
}
Read the API docs at http://poi.apache.org/apidocs/index.html
Specifically, look at org.apache.poi.ss.util.AreaReference, from which you can get the first and last cell references and determine the size of the range.
However, you have to cope with a number of special cases, such as areas that are an entire column or entire row, or even non-contiguous.

JAVA+POI API Excel- Need to increase width of the column

I want to increase the width of the column of excel sheet. as the i am writing trough code is long.
and I need to drag the column manually to see the full text.
I did this –
HSSFRow dataRow = sampleDataSheet.createRow(0);
HSSFCellStyle cellStyle = setHeaderStyle(sampleWorkbook);
cellStyle.setWrapText(true);
***sampleDataSheet.autoSizeColumn(1000000);***
But its not changing anything..
This should work. However,
sampleDataSheet.autoSizeColumn(1000000);
auto-expands column 1000000.
If you want to auto-expand column 0(the first column), use:
sampleDataSheet.autoSizeColumn(0);
To auto-expand column 0 to 9(the first 10 columns):
for (int i=0; i<10; i++){
sampleDataSheet.autoSizeColumn(i);
}
Also, you should create all your rows and fill them with content first, before you call autoSizeColumn(so the column gets the width of the value with the broadest width).
(If you want to set the column width to a fixed value, use HSSFSheet.setColumnWidth(int,int) instead.)
// We can set column width for each cell in the sheet
sheet.setColumnWidth(0, 1000);
sheet.setColumnWidth(1, 7500);
sheet.setColumnWidth(2, 7500);
// By applying style for cells we can see the total text in the cell for specified width
HSSFCellStyle cellStyle = workBook.createCellStyle();
cell.setCellStyle(cellStyle );
cellStyle.setWrapText(true);
sheet.autoSizeColumn(columnNumber) works. this will resize the column to the largest cell length.

Categories