I have a query is that, I have generated an excel sheet containing many columns with Data. Now there is a column named abc_ID and the value coming from back-end is of long type as shown below
//shown below how the value is passed for that column
private Long abc_Id;
abcdeed.abc_Id(13243534540L);
HSSFCellStyle[] cellStyles = new HSSFCellStyle[11];
HSSFCellStyle styleHeader = null;
HSSFCellStyle styleHeaderRBorder = null;
HSSFCellStyle cellStyleReportName = null;
HSSFCellStyle cellStyle00 = null;
HSSFCellStyle style_WhiteBg = null;
and I have set the following cell style of abc_ID column
if(columnHeaders[i].equals("abc_Id") && abcdeed.getabc_Id() != null){
cell.setCellValue(abcdeed.getabc_Id());
cell.setCellStyle(cellStyles[9]);
Now the issue is that finally when the excel sheet is generated and when I open that excel sheet first the value of column abc_Id looks compressed and the value in it initially is exponent type and it is because the column is of compressed type I want the column width should be expanded one and the value should not be of exponent type , I have tried to increase the cellStyles but it does not work. Please suggest the solution.
Use CELL_TYPE_STRING in all the rows for that particular Cell.
rows.getCell(abc_Id_Cell_No).setCellType(Cell.CELL_TYPE_STRING);
and at the end
Sheet.autoSizeColumn(abc_Id_Cell_No);
This will change all the cell values to String and autoSizeColumn will resize that column width.
The reason your cell is showing an exponent is nothing to do with your cell width it is to do with the type of value you are putting in it.
If your number was input as a string then the cell might hide the entire value from view but the full value would still exist in the cell.
Because your value is a number you need to edit the number format parameter for your cell so that it shows the number of digits you wish to display after the decimal point. You can check the valid number format codes as a reference.
Related
I am trying to execute some formula using java apache poi API, however
as a first step I can able to create a new sheet and fill required data.
Now, as step two I want to execute formula on the populated data, formula is able to put in cell but result is not displaying when I open the excel sheet,
Please find inline image for better understanding, here G4 is displaying as #NAME? but what actual cell value is =G3*SQRT(5).
Expected: Using java, If we create a excel and execute formula then upon opening excel sheet should display the formula calculated result without any manual intervention
Actual: After opening the excel, cell data is showing as #NAME? as if the formula is not recognized by excel, however, if I click respective cell to edit then the expected result is displaying
Code:
appendCellValue(sheet, 3, colIndex+3, true, "G3*SQRT(5)", null);
...
...
...
appendCellValue(XSSFSheet sheet, int rowIndex, int colIndex,boolean isFormula, String value, CellStyle cellStyle) {
Row row = sheet.getRow(rowIndex);
Cell cell = row.createCell(colIndex);
if(isFormula) {
cell.setCellFormula(value);
} else {
cell.setCellValue(value);
}
if(cellStyle != null) {
cell.setCellStyle(cellStyle);
}
}
I am trying to migrate the java excel code from JBook to XSSFWorkbook. Am not getting exact methods that are used in JBook. Some of them are:
JBook.setSelection(int row, int col, int row, int col);
JBook.setSelection(JBook.getDefinedName("some String"));
The first method explains moving the active cell to the top left cell in the range.
Is there any way to get the rowindex and column index from XSSFWorkbook object?
You can't set active cell via workbook object.
Possible options:
if you have cell object you can mark it as active: cell.setAsActiveCell();
if you work with XSSFSheet and want to set multiple cell selection: xssfSheet.setActiveCell(reference) (works with xmlbeans 2.6.0, not 2.3.0)
Reference can be set as a string: "A1:A2" or using CellReference class:
String reference = new CellReference(rowNum, colNum).formatAsString()
Is there any way to get the rowindex and column index from XSSFWorkbook object?
You can get index from the cell:
cell.getColumnIndex()
cell.getRowIndex()
I don't know what is JBook.getDefinedName("some String") but if it works with named ranges, check POI user guide: Named Ranges and Named Cells.
Did you try this way
HSSFWorkbook book1 = new HSSFWorkbook();
HSSFSheet sheet = book1.getSheet("sheetName");
int rowIndex=sheet.getLastRowNum()+1;//
int columnIndex = sheet.getRow(sheet.getLastRowNum()).getPhysicalNumberOfCells()
I'm working on a import module from a excel file. I have to read and check this file, if something is wrong I have to color the corrisponding cell of a color. Then I implemented the following method
public void fillCell(Workbook wb, Row row, int errorColumn){
Cell cell = row.getCell(j);
CellStyle cs = wb.createCellStyle();
cs.setFillForegroundColor((short) 10);
cs.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
cell.setCellStyle(cs);
}
but i noted that this method changes the data format of the cell. For example if I'm coloring a cell with data value 29/03/2014 i get the colored cell but its value now is 39536, the same thing happen with the numeric value 1534000001629, also in this case i get the colored cell but if i try to change the value from 1534000001629 to 1534000001630 i get 1,534+E12.
How can I fix it?
The problem is that cell styles don't only control the colour of a cell, they also control the formatting applied to it. So, what's happening is that you're replacing a cell style that eg formats as #.#%, and instead applying one that's eg red but has no number/date formatting rules applied to it.
Cell styles are workbook scoped, so you shouldn't create one per cell, thus you should make your logic somewhat like:
// Lookup from number format to the coloured version
Map<String,CellStyle> styles = new Hashmap<String,CellStyle>();
// Method to make the cell a different colour
public void fillCell(Workbook wb, Row row, int errorColumn){
Cell cell = row.getCell(j);
// Try to find a coloured one for this data formatting
String formatStr = cell.getCellStyle().getDataFormatString();
CellStyle cs = styles.get(formatStr);
if (cs == null) {
// Need to create a new coloured one
cs = wb.createCellStyle();
cs.setFillForegroundColor((short) 10);
cs.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
cs.setDataFormat(
wb.getCreationHelper().createDataFormat().getFormat(formatStr));
// Save this for later
styles.put(formatStr, cs);
}
// Apply the coloured form, with the format string
cell.setCellStyle(cs);
}
You could either convert it to a string if you don't need to do any date processing on it later as so:
cell.setCellType(CELL_TYPE_STRING);
therwise you may be able to do it by getting the date value from the cell into Java.Util.Date object and then saving it bacl=k:
Date date=cell.getDateCellValue();
//colour change
cell.setValue(date);
I don't have time to test this right now but let me know if it works and if not I'll look more into it.
You can get more information here
I'm generating a docx file with apache-poi. In the wordfile, I add tables, whose columns have a width I would like to see fixed.
Currently, I use the technique described here: http://apache-poi.1045710.n5.nabble.com/Is-there-a-way-to-set-the-width-of-a-column-in-XWPFTableCell-td5711491.html
Basically, this entails setting
cell.getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(cols[j]));
on each cell of that column.
The problem is that while the file opens perfectly in MS Word, open office interprets the values I set to the columnwidth differently. Whereas MS Word apparantly assumes 20-th of a point as units, open office seems to use points instead and therefore all columns are 20 times wider when I open the generated document in OO.
Usually when I see something weird in the generated output, I unpack the docx file, see what the value should be and change my code. But open office does not seem to be able to save to docx, so I can't change the value in OO save it back and see if Word still interprets the document correctly in order to find a cross-application solution.
Any idea how I set the width of the table column so that both OO and MS Wordt interprets it the same?
Don't touch single cells.
Add a GRID:
XWPFDocument doc = new XWPFDocument();
XWPFTable table = doc.createTable(1,2);
table.getCTTbl().addNewTblGrid().addNewGridCol().setW(BigInteger.valueOf(6000));
table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(2000));
table.getRow(0).getCell(0).setText("1A");
table.getRow(0).getCell(1).setText("1B");
XWPFTableRow newrow = table.createRow();
newrow.getCell(0).setText("2A");
newrow.getCell(1).setText("2B");
The grid sets widths for entire columns. You don't need to do any cycles to set a width for every cell. It works in LibreOffice and GoogleDocs.
To watch the seted width in MS Word too, you may set widths of cells in the first row:
widthCellsAcrossRow(table, 0, 0, 4000);
widthCellsAcrossRow(table, 0, 0, 5000);
private static void widthCellsAcrossRow (XWPFTable table, int rowNum, int colNum, int width) {
XWPFTableCell cell = table.getRow(rowNum).getCell(colNum);
if (cell.getCTTc().getTcPr() == null)
cell.getCTTc().addNewTcPr();
if (cell.getCTTc().getTcPr().getTcW()==null)
cell.getCTTc().getTcPr().addNewTcW();
cell.getCTTc().getTcPr().getTcW().setW(BigInteger.valueOf((long) width));
}
Answer extracted from question:
It was recently pointed out to me that LibreOffice is able to save to docx. By changing the generated file and saving it back and decompiling the result, I have been able to resolve the issue.
Key is to put an explicit width to the table itself first. Word doesn't seem to care about its presence, and OpenOffice/LibreOffice are able to render the table correctly.
So, after creation of the table, I did as follows:
CTTblWidth width = table.getCTTbl().addNewTblPr().addNewTblW();
width.setType(STTblWidth.DXA);
width.setW(BigInteger.valueOf(9072));
Upon creation of the table, the layout is set to "auto" by default hence the width of the cell will always increase to follow the length of the string. As per OpenXML markup, it look's like
w:tblPr
w:tblLayout w:type="auto"
the solution is to set the layout to fixed and set the individual column length
w:tblPr
w:tblLayout w:type="fixed"
Here's the poi code for setting table layout:
XWPFTable table = document.createTable();
CTTblLayoutType type = table.getCTTbl().getTblPr().addNewTblLayout();
type.setType(STTblLayoutType.FIXED);
Here's how to set the individual width:
int[] cols = {
4896,
1872,
4032,
1728,
1440
};
for (int i = 0; i < table.getNumberOfRows(); i++) {
XWPFTableRow row = table.getRow(i);
int numCells = row.getTableCells().size();
for (int j = 0; j < numCells; j++) {
XWPFTableCell cell = row.getCell(j);
CTTblWidth cellWidth = cell.getCTTc().addNewTcPr().addNewTcW();
CTTcPr pr = cell.getCTTc().addNewTcPr();
pr.addNewNoWrap();
cellWidth.setW(BigInteger.valueOf(cols[j]));
}
}
column lengths are in twentieths of a point (dxa) or 1/1440 inch.
This is a major and very tricky element. I solved it using this own generic method of setting the widths of a table cell.
private static void setTableColumnWidths(XWPFTable table) {
table.getCTTbl().addNewTblGrid().addNewGridCol().setW(BigInteger.valueOf(2000));
table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(3200));
table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(1000));
table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(1000));
table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(1105));
table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(1105));
}
Based on other answers...
public static void setTableColumnsWidth(XWPFTable table, long... widths) {
CTTblGrid grid = table.getCTTbl().addNewTblGrid();
for (long w : widths) {
grid.addNewGridCol().setW(BigInteger.valueOf(w));
}
}
Usage:
setTableColumnsWidth(table, 1440, 2700, 3000, 1440);
I am trying to set column width to the length of the column name. My problem is, I am not able to set it. When I use the following code the table is becoming like this,
tableA.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
for(int i = 0; i < tableA.getColumnCount(); i++) {
int columnLength = (modelA.getColumnName(i)).length();
tableA.getColumnModel().getColumn(i).setPreferredWidth(columnLength);
// tableA.getColumnModel().getColumn(i).setMinWidth(columnLength);
// tableA.getColumnModel().getColumn(i).setMaxWidth(columnLength);
}
I am getting the column length correctly from my table model.
When I use the above code the table is getting packed like this,
I am not able to understand where I am doing wrong.
As Dan has pointed out, you need to calculate the actual width of the column name based on the Font that is being used.
Something like:
String name = modelA.getColumnName(i);
Font f = tableA.getFont();
FontMetrics fm = tableA.getFontMetrics(f);
int width = fm.stringWidth(name);
tableA.getColumnModel().getColumn(i).setPreferredWidth(width);
Note that this is an extremely abbreviated example.
If you want to get it completely correct, you will need to query each column's renderer for the Font and the FontMetrics in order to get the correct values.
If all your renderers use the same font as the JTable, then this should be OK.
The setPreferredWidth expects a value in pixels while the length of the column name is the length of a String (number of characters in a String).
If you do not mind using SwingX, you can use the TableColumnExt#setPrototypeValue method which allows you to set a 'prototype' value which will be used to determine the column width.
columnLength == number or columns from ColumnModel,
standard size is 80pixels
minimum columns size is at 10pixels
see How to get/set PreferredSize