I m using getLastRowNum() and getPhysicalNumberOfCells() for the number of used rows and columns respectively but its not giving the correct index of the row.
int lastRowNum = sheetAt.getLastRowNum();
int lastColNum = sheetAt.getRow(0).getPhysicalNumberOfCells();
Any other option to find out the same???
Rows and Cells can be missing, and there is no built in function to return the number of cells used in a column. So you have to write the function yourself.
int count = 0;
for (Row row : sheet) {
if (row.getCell(5) != null) {
count += 1;
}
}
This retrieves the number of used cells in column F.
Related
I have table in one of my ppt slide, my requirement is to read the height of table's row, so if the row is going out of that particular slide i can remove it, the height will vary base on the text in it.
I tried reading like these but for some reason not getting the accurate output:
int totalRows = table.getNumberOfRows();
double rowHeight = 0;
for(int t =0; t< totalTableRows; t++)
{
//logic to read height of row
rowHeight += table.getRows().get(t).getCells().get(0).getAnchor().getHeight();
//logic to remove row.
if(rowHeight > slideHeight)
{
for(int remove = t;t< totalRows; t++)
{
table.removeRow(remove);
}
}
}
Note: some rows and column has merged cells as well.
I have this method which adds in an ArrayList named column an entire column from am Excel file. But i have a problem if a column is shorter( it doesn't have as many rows as others)empty String error appears.
public initializingWorkbook( Sheet sheet,ArrayList <Double> column, int index)
{
int rows = sheet.getRows();
for(int row = 1;row < rows;row++)
{
String i = sheet.getCell(index, row).getContents();
column.add(Double.parseDouble(i));
}
}
Here is the sheet. So first 6 columns have the same number of rows and the test column fewer. Cells format are on General.
You have to check first, how much columns the actual row contains:
{
if (index < sheet.getRow(row).length) {
String i = sheet.getCell(index, row).getContents();
column.add(Double.parseDouble(i));
}
}
sheet.getRow(int row) returns all cells of this row; that is an array of cells. So you can check the dimension of the returned array.
I have the following 2D array and I want to compare all the columns with each other.
int [][] myarray={{1,2,3},{1,2,3},{1,2,3}};
So what I want to see is if column 1 (all 1's) is equal to the values in column 2 (all 2's).
Ps. the array size is not just limited to this.
It's not quite clear from your question whether you want to compare all columns to each other, or just a single column to another single column (for example column 1 to column 2). Assuming you meant the latter, you could do this.
public boolean columnsIdentical(int[][] array, int colIndex1, int colIndex2) {
for (int row = 0; row < array.length; row++ ) {
if (array[row][colIndex1] != array[row][colIndex2]) {
return false;
}
}
return true;
}
for (int i=0;i<myarray[0].length;i++) {
int comp=myarray[0][i];
for (int j=1;j<myarray.length;j++) {
if (myarray[j][i] != comp) {
// no match
} else {
// match
}
}
}
To test all pairs of columns you need 3 loops
Innermost compares elements of columns A and B
Middle loops through B, skipping columns already checked
Outermost loops through A for all columns
I use the following code in order to autosize columns in my spreadsheet:
for (int i = 0; i < columns.size(); i++) {
sheet.autoSizeColumn(i, true);
sheet.setColumnWidth(i, sheet.getColumnWidth(i) + 600);
}
The problem is it takes more than 10 minutes to autosize each column in case of large spreadsheets with more than 3000 rows. It goes very fast for small documents though. Is there anything which could help autosizing to work faster?
Solution which worked for me:
It was possible to avoid merged regions, so I could iterate through the other cells and finally autosize to the largest cell like this:
int width = ((int)(maxNumCharacters * 1.14388)) * 256;
sheet.setColumnWidth(i, width);
where 1.14388 is a max character width of the "Serif" font and 256 font units.
Performance of autosizing improved from 10 minutes to 6 seconds.
The autoSizeColumn function itself works not perfect and some columns width not exactly fit the data inside. So, I found some solution that works for me.
To avoid crazy calculations let give that to autoSizeColumn() function:
sheet.autoSizeColumn(<columnIndex>);
Now, our column autosized by library but we wont to add a little bit more to the current column width to make table looks fine:
// get autosized column width
int currentColumnWidth = sheet.getColumnWidth(<columnIndex>);
// add custom value to the current width and apply it to column
sheet.setColumnWidth(<columnIndex>, (currentColumnWidth + 2500));
The full function could looks like:
public void autoSizeColumns(Workbook workbook) {
int numberOfSheets = workbook.getNumberOfSheets();
for (int i = 0; i < numberOfSheets; i++) {
Sheet sheet = workbook.getSheetAt(i);
if (sheet.getPhysicalNumberOfRows() > 0) {
Row row = sheet.getRow(sheet.getFirstRowNum());
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
int columnIndex = cell.getColumnIndex();
sheet.autoSizeColumn(columnIndex);
int currentColumnWidth = sheet.getColumnWidth(columnIndex);
sheet.setColumnWidth(columnIndex, (currentColumnWidth + 2500));
}
}
}
}
P.S. Thanks Ondrej Kvasnovsky for the function https://stackoverflow.com/a/35324693/13087091
The autosizeColumn() function very slow and unneficient. Even authors of apache POI mentioned in docs, that:
This process can be relatively slow on large sheets, ...
Calculating and setting the cell's width manually is way faster - in my case I reduced the time from ~25,000ms to ~1-5ms.
This is how to achieve it (I was basing on Vladimir Shcherbukhin's answer:
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet();
final int[] maxNumCharactersInColumns = new int[headers.length]; // maximum number of characters in columns. Necessary to calculate the cell width in most efficient way. sheet.autoSizeColumn(...) is very slow.
Row headersRow = sheet.createRow(0);
CellStyle headerStyle = createHeadersStyle(workbook); // createHeadersStyle() is my own function. Create headers style if you want
for (int i = 0; i < headers.length; i++) { // create headers
Cell headerCell = headersRow.createCell(i, CELL_TYPE_STRING);
headerCell.setCellValue(headers[i]);
headerCell.setCellStyle(headerStyle);
int length = headers[i].length();
if (maxNumCharactersInColumns[i] < length) { // adjust the columns width
maxNumCharactersInColumns[i] = length + 2; // you can add +2 if you have filtering enabled on your headers
}
}
int rowIndex = 1;
for (List<Object> rowValues : rows) {
Row row = sheet.createRow(rowIndex);
int columnIndex = 0;
for (Object value : rowValues) {
Cell cell = createRowCell(row, value, columnIndex); // createRowCell() is my own function.
int length;
if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
String cellValue = cell.getStringCellValue();
// this is quite important part. In some excel spreadsheet you can have a values with line-breaks. It'll be cool to handle that scenario :)
String[] arr = cellValue.split("\n"); // if cell contains complex value with line breaks, calculate only the longest line
length = Arrays.stream(arr).map(String::length).max(Integer::compareTo).get();
} else {
length = value != null ? value.toString().length() : 0;
}
if (maxNumCharactersInColumns[columnIndex] < length) { // if the current cell value is the longest one, save it to an array
maxNumCharactersInColumns[columnIndex] = length;
}
columnIndex++;
}
rowIndex++;
}
for (int i = 0; i < headers.length; i++) {
int width = (int) (maxNumCharactersInColumns[i] * 1.45f) * 256; // 1.45f <- you can change this value
sheet.setColumnWidth(i, Math.min(width, MAX_CELL_WIDTH)); // <- set calculated cell width
}
sheet.setAutoFilter(new CellRangeAddress(0, 0, 0, headers.length - 1));
ByteArrayOutputStream output = new ByteArrayOutputStream();
workbook.write(output);
workbook.close();
Unfortunately I don't have enough reputations yet to add comments in answers. So here some annotations:
When using Row row = sheet.getRow(sheet.getFirstRowNum()); be shure, this row contains at least a value in the last column. Otherwise the cellIterator will end too early, i.e. if a subsequent row has a value in this column, this column will not be autosized. This problem is bypassed if rowcontains the headers (names of the columns). Or explicit use a known header row, e.g.
int indexOfHeaderRow = ...;
...
Row row = sheet.getRow(indexOfHeaderRow);
Jakub SÅ‚owikowski
sheet.setColumnWidth(i, Math.min(width, MAX_CELL_WIDTH)); // <- set calculated cellwidth
I'm not shure about this line because there is no information about content of MAX_CELL_WIDTH - perhaps overall maximum? So I used instead:
sheet.setColumnWidth(i, Math.max(width, 2048));
2048 seams to be the default width? This value prevents extremely narrow widths for empty columns.
I have a table named tblMainData with several columns with a couple of them with width of 0.
I want to store the all data in the table except those columns with 0 width to a two dimensional array.
How do I check to see if a particular column has 0 width?
Just call TableColumn#getWidth():
for(int col = 0; col < tblMainData.getColumnCount(); col++)
{
if(tblMainData.getColumn(col).getWidth() == 0)
{
// do something
}
}