I trying to make the code I already wrote for an XSSF workbook compatible to both xls and xlsx. Given below a piece of code as an example.
Workbook workbook = WorkbookFactory.create(new File("F:\\JavaEE\\test.xls"));
Sheet sheet = workbook.getSheetAt(0);
short cellBorderColour = IndexedColors.GREY_80_PERCENT.getIndex();
Font font = workbook.createFont();
font.setBoldweight(Font.BOLDWEIGHT_BOLD);
font.setColor(IndexedColors.BLUE_GREY.index);
CellStyle cellStyle = workbook.createCellStyle();
cellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
cellStyle.setFont(font);
cellStyle.setBorderLeft(CellStyle.BORDER_HAIR);
cellStyle.setLeftBorderColor(cellBorderColour);
cellStyle.setBorderTop(CellStyle.BORDER_HAIR);
cellStyle.setTopBorderColor(cellBorderColour);
cellStyle.setBorderRight(CellStyle.BORDER_HAIR);
cellStyle.setRightBorderColor(cellBorderColour);
cellStyle.setBorderBottom(CellStyle.BORDER_MEDIUM);
cellStyle.setBottomBorderColor(cellBorderColour);
Row row = sheet.createRow(1);
Cell cell = row.createCell(1);
sheet.addMergedRegion(new CellRangeAddress(1, 1, 1, 4));
borderRowCells(1, 4, row, cell, cellStyle);
cell.setCellValue("Value");
FileOutputStream fos = new FileOutputStream("F:\\JavaEE\\new_test.xls");
workbook.write(fos);
//Take care of exception handling and closing of the stream.
The utility method as used by the above code to border across merged cells.
private void borderRowCells(int from, int to, Row row, Cell cell, CellStyle cellStyle) {
for (int i = from; i <= to; ++i) {
cell = row.createCell(i);
cell.setCellStyle(cellStyle);
}
}
This code is meant to apply some borders in conjunction with other styles across some merged cells.
The border across merged cells is however, not applied correctly as can be seen in the following picture.
The borders are expected to be applied starting from B2 to E2. The actual border area however, covers only from C2 to E2
The cell value Value is also not aligned center which is specified in the cell style.
How to apply this border correctly across the merged cells along with center alignment?
Also the list of colours provided by IndexedColors.COLOR_NAME.getIndex() is very limited. The list is very unlikely to fulfill the real needs of colours in different cell styles.
Can we use RGB colours in the ss model as we do in the xssf model using XSSFColor as follows?
XSSFColor commonColor = new XSSFColor(new java.awt.Color(240, 240, 240));
Or even something better/different?
PS : I'm using Apache POI 3.10.1.
Related
I need to add different backgrounds colors and borders to the cells of an XLS file
this is my code
Row r = sh.createRow(sh.getPhysicalNumberOfRows());
CellStyle style = wb.createCellStyle();
style = wb.createCellStyle(r.getPhyscal);
//region
style.setFillForegroundColor(IndexedColors.ORANGE.getIndex());
style.setFillPattern(CellStyle.SOLID_FOREGROUND);
org.apache.poi.ss.usermodel.Cell c = r.createCell(1);
c.setCellValue((String) jComboBox1.getSelectedItem());
c.setCellStyle(style);
//sA
style.setFillForegroundColor(IndexedColors.RED.getIndex());
style.setFillPattern(CellStyle.SOLID_FOREGROUND);
c = r.createCell(2);
c.setCellValue((String) jT1.getText() );
c.setCellStyle(style);
this is the result i need
but that is the result i have
You have to create a new CellStyle for each color.
CellStyle orangeStyle = wb.createCellStyle(r.getPhyscal);
orangeStyle.setFillForegroundColor(IndexedColors.ORANGE.getIndex());
orangeStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
CellStyle redStyle = wb.createCellStyle(r.getPhyscal);
redStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
redStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
..
and attach the fitting style to each affected cell
I want to export data to excel using Apache poi. Now the problem that I am facing is that I am unable to merge rows and align them in the center.
Code for export data is:
List<LinkedHashMap<String,Object>> lstReportHeader = null;
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
//Set Header Font
HSSFFont headerFont = wb.createFont();
headerFont.setBoldweight(headerFont.BOLDWEIGHT_BOLD);
headerFont.setFontHeightInPoints((short) 12);
//Set Header Style
CellStyle headerStyle = wb.createCellStyle();
headerStyle.setFillBackgroundColor(IndexedColors.BLACK.getIndex());
headerStyle.setAlignment(headerStyle.ALIGN_CENTER);
headerStyle.setFont(headerFont);
headerStyle.setBorderBottom(HSSFCellStyle.BORDER_MEDIUM);
int rowCount= 0;
Row header;
header = sheet.createRow(0);//its for header
Cell cell ;//= header.createCell(0);
for(int j = 0;j < 4; j++) {
cell = header.createCell(j);
if(j == 0) {
cell.setCellValue("ItemWise List");
}
cell.setCellStyle(headerStyle);
}
sheet.addMergedRegion(new CellRangeAddress(rowCount, rowCount, 0, lstReportFormHeader.size()-1));
header = sheet.createRow(0);
cell = header.createCell(0);
cell.setCellValue("Sr. No");
cell = header.createCell(1);
cell.setCellValue("Item Name");
cell = header.createCell(2);
cell.setCellValue("Qty");
cell = header.createCell(3);
cell.setCellValue("Rate");
Now I want to ItemWise List merge and make it align center.
My solution was to merge the cells by their positions, then created a cell (reference to the first block of the merged cells) to assign a value and then set the alignment throught the CellUtil
// Merges the cells
CellRangeAddress cellRangeAddress = new CellRangeAddress(start, start, j, j + 1);
sheet.addMergedRegion(cellRangeAddress);
// Creates the cell
Cell cell = CellUtil.createCell(row, j, entry.getKey());
// Sets the allignment to the created cell
CellUtil.setAlignment(cell, workbook, CellStyle.ALIGN_CENTER);
Merge like:::
Workbook wb = new HSSFWorkbook();
Sheet sheet = wb.createSheet("new sheet");
Row row = sheet.createRow((short) 1);
Cell cell = row.createCell((short) 1);
cell.setCellValue("This is a test of merging");
sheet.addMergedRegion(new CellRangeAddress(
1, //first row (0-based)
1, //last row (0-based)
1, //first column (0-based)
2 //last column (0-based)
));
// Write the output to a file
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();
For aligning also check the below official link of Apache poi:::
http://poi.apache.org/spreadsheet/quick-guide.html#Alignment
After study I found that after merging 7 cells, merged cell id will be 0 so I applied following style to cell id 0 using following style.
headerStyle.setAlignment(headerStyle.ALIGN_CENTER);
This worked for me and I think it's cleaner:
/**
* Merge and center the cells specified by range
* #param startCell the first cell in the cells to be merged
* #param range the range of the cells to be merged
*/
private static void mergeAndCenter(Cell startCell, CellRangeAddress range) {
startCell.getSheet().addMergedRegion(range);
CellStyle style = startCell.getSheet().getWorkbook().createCellStyle();
style.setAlignment(CellStyle.ALIGN_CENTER);
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
startCell.setCellStyle(style);
}
As per my understanding, you have start and end cells for merging and you want to merge the cell ranges and align the cell content. If I am right, you can use the following method:
/**
* #param startCell: first cell of merging area
* #param endCell: last cell of merging area
*/
public static void mergeAndAlignCenter(HSSFCell startCell, HSSFCell endCell){
//finding reference of start and end cell; will result like $A$1
CellReference startCellRef= new CellReference(startCell.getRowIndex(),startCell.getColumnIndex());
CellReference endCellRef = new CellReference(endCell.getRowIndex(),endCell.getColumnIndex());
// forming string of references; will result like $A$1:$B$5
String cellRefernce = startCellRef.formatAsString()+":"+endCellRef.formatAsString();
//removing $ to make cellRefernce like A1:B5
cellRefernce = cellRefernce.replace("$","");
//passing cellRefernce to make a region
CellRangeAddress region = CellRangeAddress.valueOf(cellRefernce);
//use region to merge; though other method like sheet.addMergedRegion(new CellRangeAddress(1,1,4,1));
// is also available, but facing some problem right now.
startCell.getRow().getSheet().addMergedRegion( region );
//setting alignment to center
CellUtil.setAlignment(startCell, wb, CellStyle.ALIGN_CENTER);
}
Well what worked for me is to set all the merged cells' Cellstyle to CENTER ALIGN. Whether you put the XSSFSheet.addMergedRegion() method before or after setting the cellstyle values to center don't matter.
private void insertXlsHeader(XSSFSheet sheet){
....
//first cell for row1
cell = row1.createCell(colstart);
cell.setCellType(org.apache.poi.ss.usermodel.Cell.CELL_TYPE_STRING);
cell.setCellValue("COURSES");
setHeaderCellStyle(sheet,cell);
//first cell for row2
cell = row2.createCell(colstart);
setHeaderCellStyle(sheet,cell);
//first cell for row3
cell = row3.createCell(colstart);
setHeaderCellStyle(sheet,cell);
//merged the first cells of rows 1 to 3
sheet.addMergedRegion(new CellRangeAddress(ROW1, ROW3, colstart, colstart));
...
}
private void setHeaderCellStyle(XSSFSheet sheet,org.apache.poi.ss.usermodel.Cell cell) {
CellStyle s = null;
s = sheet.getWorkbook().createCellStyle();
cell.setCellStyle(s);
Font f = sheet.getWorkbook().createFont();
f.setBoldweight(Font.BOLDWEIGHT_BOLD);
s.setBorderBottom(CellStyle.BORDER_THIN);
s.setBorderLeft(CellStyle.BORDER_THIN);
s.setBorderRight(CellStyle.BORDER_THIN);
s.setBorderTop(CellStyle.BORDER_THIN);
s.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
s.setAlignment(CellStyle.ALIGN_CENTER);
s.setFont(f);
}
As answered above, merging cells can be achieved using
sheet.addMergedRegion(new CellRangeAddress(frstRow, lastRow, firstColumnIndex, lastColumnIndex));
But for aligning cells vertically,recently I faced similar issue and I tried above answer, but using
CellUtil.setAlignment(dataCell, workbook, CellStyle.VERTICAL_CENTER);
aligned Date formatted cells to Horizontal Left aligned. So I used following method to set only Vertical Alignment of Cell content.
CellUtil.setCellStyleProperty(dataCell, workbook,CellUtil.VERTICAL_ALIGNMENT,CellStyle.VERTICAL_CENTER);
I hope this helps!!
Happy Coding
Use
style.setVerticalAlignment()
to set the vertical alignments instead of
style.setAlignment().
We can merge the column along with we can vertically and horizontally align too.
I had the rows 2 to 10 of column A having the same values.
I used the below code to merge the data where the variable sheet is XSSFSheet. The parameters of CellRangeAddress have the parameters are start row, last row, start column and last column. In my example, the value USA starts from 2nd row (index is 1) and the last value of USA is in 10th row and column is the 1st column.
CellRangeAddress ca = new CellRangeAddress(1,9,0,0);
sheet.addMergedRegion(ca);
When I executed the above code, the cell was merged but the text was not aligned to center.
To overcome this issue, I utilized the class CellStyle and Cell. Get the 2nd row of 1st column text to cell variable. Now set the vertical and horizontal alignment to the cellStyle and set this style to the cell which will align the text to the center.
Cell cell = sheet.getRow(1).getCell(0);
CellStyle cellStyle = workbook.createCellStyle();
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
cellStyle.setAlignment(HorizontalAlignment.CENTER);
cell.setCellStyle(cellStyle);
Below is the final result
Additional references :
Jar files used
Import statements
I am inputting values into a spreadsheet using Apache POI. These values have newlines, and I was able to use this code successfully:
CellStyle style = cell.getCellStyle()
style.setWrapText(true)
cell.setCellStyle(style)
Unfortunately, while the text is wrapping correctly, the rows are not always growing in height enough to show the content. How do I ensure that my rows are always the correct height?
currentRow.setHeight((short)-1)
Works for XSSFCell and Excel 2013
HSSFWorkbook workbook=new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("FirstSheet");
HSSFRow rowhead= sheet.createRow((short)0);
HSSFCellStyle style = workbook.createCellStyle();
style.setWrapText(true);
row.setRowStyle(style);
row.getCell(0).setCellStyle(style);
The above code will generate dynamic height of rows.
The only way I got this to work was write my own implementation to calculate the row height. The code is now released as the Taro project, so you could use that. It has numerous convenience methods to let you write an Excel file in far fewer lines of code.
If you prefer to put the implementation in your own code, you can find it in the SpreadsheetTab class. There is an autoSizeRow(int rowIndex) method half way down. It basically iterates down the row and for each cell finds the number of lines of text, then uses the font size to calculate the optimal cell height. It then sets the row height to the height of the tallest cell.
See all this link, which provides some code to manually calculate the correct height for a row, based on the column width and cell content. I've not personally tested it. Also pasted below for convenience:
// Create Font object with Font attribute (e.g. Font family, Font size, etc) for calculation
java.awt.Font currFont = new java.awt.Font(fontName, 0, fontSize);
AttributedString attrStr = new AttributedString(cellValue);
attrStr.addAttribute(TextAttribute.FONT, currFont);
// Use LineBreakMeasurer to count number of lines needed for the text
FontRenderContext frc = new FontRenderContext(null, true, true);
LineBreakMeasurer measurer = new LineBreakMeasurer(attrStr.getIterator(), frc);
int nextPos = 0;
int lineCnt = 0;
while (measurer.getPosition() < cellValue.length())
{
nextPos = measurer.nextOffset(mergedCellWidth); // mergedCellWidth is the max width of each line
lineCnt++;
measurer.setPosition(nextPos);
}
Row currRow = currSht.getRow(rowNum);
currRow.setHeight((short)(currRow.getHeight() * lineCnt));
// The above solution doesn't handle the newline character, i.e. "\n", and only
// tested under horizontal merged cells.
cell.getRow().setHeight((short) -1);
Worked for HSSFCell in apache poi 3.9 or above
It works in Excel 2010.
I set the limit of cell length of 50 characters
Row row = sheet.createRow(0);
CellStyle style = workbook.createCellStyle();
style.setWrapText(true);
if (data.length() > 50) {
for (int i = 1; i <= Math.abs(data.length() / 50); i++) {
data = data.substring(0, i * 50) + "\n" + data.substring(i * 50);
}
Cell cell = row.createCell(0);
row.setRowStyle(style);
cell.setCellStyle(style);
cell.setCellValue(data);
sheet.autoSizeColumn(0);
}
In my case a robust solution was to calculate the number of lines and set the row height to a multiple of the default row height:
int numberOfLines = cell.getStringCellValue().split("\n").length;
row.setHeightInPoints(numberOfLines*sheet.getDefaultRowHeightInPoints());
You can't adjust cell height directly.
But you can change the row's height
final HSSFSheet fs = wb.createSheet("sheet1");
final HSSFRow row0 = fs.createRow(0);
final HSSFCell cellA1 = row0.createCell(0);
row0.setHeight((short)700);
Row aitosize work for me:
cell.getRow().setHeight((short)0);
Here 0 for calculate autoheight.
Workaround for “LibreOffice Calc“ and “WPS Spreadsheet” with auto height for merged sells.
I add a column out to the right of a main document (In my case it was 32 column)
Set width as all merged cells with same text.
Set style WrapText to true
Set style to Align Top
Copy content which will be displayed in the merged cells
Set that column to be hidden
Set a row height = -1
A sample of code:
private void applyRowHightWorkaroundForMergedCells(HSSFCell cell0) {
HSSFSheet sheet = cell0.getSheet();
HSSFRow row = cell0.getRow();
String value = cell0.getStringCellValue();
HSSFCell cell = row.createCell(32);
sheet.setColumnWidth(32, 32000);
cell.getCellStyle().setWrapText(true);
cell.getCellStyle().setVerticalAlignment(VerticalAlignment.TOP);
cell.setCellValue(value);
sheet.setColumnHidden(32, true);
row.setHeight((short) -1);
}
//we can use column width for sheet
Ex: sheet.setColumnWidth(0, 2000);
I'm using Apache POI to export data to a .xlsx file and I want to style some of the rows and cells contained in the file.
I'm using XSSF since the file is going to be read in Excel 2007+.
Basically, my problem is that I'm trying to set a row style like in the following example, which sets a black foreground color for the entire row at index 0. It works fine, but whenever I create a new cell, the newly created cell has no style, as if it's overriding the row style I specified.
Here's a code snippet to demonstrate what I'm doing:
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sheet = wb.createSheet("mySheet");
XSSFRow row = sheet.createRow(0);
XSSFCellStyle myStyle = wb.createCellStyle();
myStyle.setFillForegroundColor(new XSSFColor(new Color(255, 255, 255)));
myStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
row.setRowStyle(myStyle); //This works, the whole row is now black
row.createCell(0); // This cell doesn't have a style, the rest of the line stays stylized
row.getCell(0).setCellValue("Test");
I also tried *row.createCell(0, Cell.CELL_TYPE_STRING);*, but it didn't change anything.
What is the correct way of accomplishing what I want to do? I wanted to do it this way so I didn't have to set each cell's style after creating it since all cells on the same row have the same style.
Set the style into newly created cell as well e.g. below:
XSSFCell newCell = row.createCell(0);
newCell.setCellStyle(myStyle);
Even you create a row with style, it will not effect to created cell of its. The create cell have their own cell style.
The row style will not override to cell style automatically. If you would like use row style in cell, you have to set again.
Even if you set row style at end, it will not effect to cell.
Example
CreationHelper createHelper = wb.getCreationHelper();
Sheet sheet = wb.createSheet("new sheet");
Row r = sheet.createRow(0);
r.setRowStyle(rowStyle);
Cell c1 = r.createCell(0);
c1.setCellValue("Test 1");
c1.setCellStyle(rowStyle);
I'm agree that "setRowStyle" doesn't work as it should be.
I created my own function to apply a style to a range ( could be a row or multiple row )
public void applyStyleToRange(Sheet sheet, CellStyle style, int rowStart, int colStart, int rowEnd, int colEnd) {
for (int r = rowStart; r <= rowEnd; r++) {
for (int c = colStart; c <= colEnd; c++) {
Row row = sheet.getRow(r);
if (row != null) {
Cell cell = row.getCell(c);
if (cell != null) {
cell.setCellStyle(style);
}
}
}
}
}
I use the following java code to successfully generate cell comments in Apache POI
public static void setComment(String text, Cell cell) {
final Map<Sheet, HSSFPatriarch> drawingPatriarches = new HashMap<Sheet, HSSFPatriarch>();
CreationHelper createHelper = cell.getSheet().getWorkbook().getCreationHelper();
HSSFSheet sheet = (HSSFSheet) cell.getSheet();
HSSFPatriarch drawingPatriarch = drawingPatriarches.get(sheet);
if (drawingPatriarch == null) {
drawingPatriarch = sheet.createDrawingPatriarch();
drawingPatriarches.put(sheet, drawingPatriarch);
}
Comment comment = drawingPatriarch.createComment(new HSSFClientAnchor(100, 100, 100, 100, (short)1, 1, (short) 10, 5));
comment.setString(createHelper.createRichTextString(text));
cell.setCellComment(comment);
}
I copied it from creating cell comments using HSSFClientAnchor in apache poi. Thank you Erik!
How can I change the size of the comment to 300 pixels width and 100 pixels height?
Thanks!
From what I can tell there's not an easy way since comment anchor points are specified by cell (column, row parameters) and offset into cell (dx, dy parameters). So you need to compute the width/height of the cells to figure out the second cell coordinates and then the offsets into that cell to make it exactly the pixel size you want.
Busy Developers' Guide to HSSF and XSSF Features
// When the comment box is visible, have it show in a 1x3 space
ClientAnchor anchor = factory.createClientAnchor();
anchor.setCol1(cell.getColumnIndex());
anchor.setCol2(cell.getColumnIndex()+1);
anchor.setRow1(row.getRowNum());
anchor.setRow2(row.getRowNum()+3);
Just change the values for setCol2 and setRow2.
You can assign a column width for any cell as follows:
sheet.setColumnWidth(0, 1000);