How to set cell background with Apache POI? - java

I try to set the background color of a cell according to a value. Please, find below the corresponding code.
File inputFile = new File(path)
FileInputStream fis = new FileInputStream(inputFile)
XSSFWorkbook inputWorkbook = new XSSFWorkbook(fis)
XSSFWorkbook outputWorkbook = new XSSFWorkbook()
XSSFSheet inputSheet = inputWorkbook.getSheetAt(1)
def inputSheetName = inputWorkbook.getSheetName(1)
XSSFSheet outputSheet = outputWorkbook.createSheet(inputSheetName)
// some code
CellStyle style = outputSheet.getRow(rowIndex).getCell(columnIndex).getCellStyle()
short color = (status.get(listIndex) == 'Passed') ? IndexedColors.GREEN.getIndex() : IndexedColors.RED.getIndex()
style.setFillBackgroundColor(color)
outputSheet.getRow(rowIndex).getCell(columnIndex).setCellStyle(style)
// some code
This code does not make an error, however, the cell background is not set ...
Someone can help me please? Thanks for help!
Update 1
CellStyle style = outputSheet.getRow(rowIndex).getCell(columnIndex).getCellStyle()
short color = (status.get(listIndex) == 'Passed') ? IndexedColors.GREEN.getIndex() : IndexedColors.RED.getIndex()
style.setFillPattern(FillPatternType.SOLID_FOREGROUND)
style.setFillForegroundColor(color)
outputSheet.getRow(rowIndex).getCell(columnIndex).setCellStyle(style)
Update 2
The goal of the following code is to copy and paste content of an excel file to another one. And I want to set the color of the cell according to the status value.
def function(dateTimeOfTestSuite, status, executionDateTime) {
File inputFile = new File(path)
FileInputStream fis = new FileInputStream(inputFile)
XSSFWorkbook inputWorkbook = new XSSFWorkbook(fis)
def inputSheetCount = inputWorkbook.getNumberOfSheets()
def directoryName = 'Data Files\\Reports\\' + name
File directory = new File(directoryName)
if (!directory.exists())
directory.mkdirs()
def excelOutputFileName = directory.path + '\\' + dateTimeOfTestSuite + '.xlsx'
excelOutputFileName = excelOutputFileName.replace(':', '-')
File outputFile = new File(excelOutputFileName)
FileOutputStream fos = new FileOutputStream(outputFile)
XSSFWorkbook outputWorkbook = new XSSFWorkbook()
for(int i = 0; i < inputSheetCount; i++) {
XSSFSheet inputSheet = inputWorkbook.getSheetAt(i)
def inputSheetName = inputWorkbook.getSheetName(i)
XSSFSheet outputSheet = outputWorkbook.createSheet(inputSheetName)
def numberOfRows = inputSheet.getPhysicalNumberOfRows()
def numberOfColumns = inputSheet.getRow(0).getPhysicalNumberOfCells()
def listIndex = 0
def rowIndex = 0
outputSheet.createRow(0)
while (rowIndex < numberOfRows && inputSheet.getRow(rowIndex).getCell(0).getCellType() != Cell.CELL_TYPE_BLANK) {
def columnIndex = 0
while (columnIndex < numberOfColumns && inputSheet.getRow(0).getCell(columnIndex).getCellType() != Cell.CELL_TYPE_BLANK) {
def value = (inputSheet.getRow(rowIndex).getCell(columnIndex).toString() == 'null') ? '' : inputSheet.getRow(rowIndex).getCell(columnIndex).toString()
if (columnIndex == 0)
outputSheet.createRow(rowIndex).createCell(columnIndex).setCellValue(value)
else
outputSheet.getRow(rowIndex).createCell(columnIndex).setCellValue(value)
outputSheet.autoSizeColumn(columnIndex)
columnIndex++
}
if(inputSheetName == "input") {
if(rowIndex == 0) {
outputSheet.getRow(0).createCell(columnIndex).setCellValue('Status')
outputSheet.getRow(0).createCell(columnIndex + 1).setCellValue('ExecutedAt')
}
else if (rowIndex > 1) {
outputSheet.getRow(rowIndex).createCell(columnIndex).setCellValue(status.get(listIndex))
if(status.get(listIndex) != 'No run') {
outputSheet.getRow(rowIndex).createCell(columnIndex + 1).setCellValue(executionDateTime.get(listIndex))
CellStyle style = outputSheet.getRow(rowIndex).getCell(columnIndex).getCellStyle()
def color = (status.get(listIndex) == 'Passed') ? IndexedColors.GREEN.getIndex() : IndexedColors.RED.getIndex()
style.setFillPattern(FillPatternType.SOLID_FOREGROUND)
style.setFillForegroundColor(color)
outputSheet.getRow(rowIndex).getCell(columnIndex).setCellStyle(style)
}
listIndex++
}
outputSheet.autoSizeColumn(columnIndex)
outputSheet.autoSizeColumn(columnIndex + 1)
}
rowIndex++
}
}
outputWorkbook.write(fos)
fos.close()
}
Solution
XSSFCellStyle style = outputWorkbook.createCellStyle()
def color = (status.get(listIndex) == 'Passed') ? IndexedColors.GREEN.getIndex() : IndexedColors.RED.getIndex()
style.setFillPattern(FillPatternType.SOLID_FOREGROUND)
style.setFillForegroundColor(color)
outputSheet.getRow(rowIndex).getCell(columnIndex).setCellStyle(style)

Its actually not about the background. Its the foreground color. Also you need to specify a FillPattern like this:
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setFillForegroundColor(color);
As for the reason, why it is setFillForegroundColor and not setFillBackgroundColor, I couldn't find any information what exactly the difference is, but following code shows how they work:
style.setFillPattern(FillPatternType.LEAST_DOTS);
style.setFillForegroundColor(IndexedColors.BRIGHT_GREEN.getIndex());
style.setFillBackgroundColor(IndexedColors.RED.getIndex());
And the result looks like this:
From this I would guess, that setFillBackgroundColor only works properly in conjuction with setFillForegroundColor to create patterns like this.

Related

I want to write data into excel(.xlsx file) using Apache poi

I want to write data into excel(.xlsx file) using Apache poi. but getting some error while writing a data. I have followed this video " How to read/write data from Excel file using Apache POI API in Selenium || Latest POI Version", I m able to read data but while writing I m getting this error " Cannot invoke "org.apache.poi.xssf.usermodel.XSSFCell.getStringCellValue()" because the return value of "org.apache.poi.xssf.usermodel.XSSFRow.getCell(int)" is null ", basically nullpointerexception.
enter code here
String resourceGroupNameElement = driver.findElement(By.xpath(FrameworkValidator_Constants.Constants.RESOURCE_GROUP_NAME_XPATH)).getText();
String expectedResult = reader.getCellData("RG",6,2);
if( resourceGroupNameElement== expectedResult) {
String status= "pass";
System.out.println(status);
}
else {
String status="fail";
System.out.println(status);
}
//reader.setCellData("RG", "STATUS/PASS/FAIL", 2, status);
System.out.println(status);
reader.setCellData("RG","ACTUAL RESULT" , 2, resourceGroupNameElement);
Assert.assertEquals(resourceGroupNameElement, expectedResult);
#######
It is showing error in this section
public String setCellData(String sheetName, String colName, int rowNum, String data) {
try {
fis = new FileInputStream(path);
workbook = new XSSFWorkbook(fis);
if (rowNum <= 0)
return "";
int index = workbook.getSheetIndex(sheetName);
int colNum = -1;
if (index == -1)
return "";
sheet = workbook.getSheetAt(index);
row = sheet.getRow(0);
for (int i = 0; i < row.getLastCellNum(); i++) {
// System.out.println(row.getCell(i).getStringCellValue().trim());
if (row.getCell(i).getStringCellValue().trim().equals(colName))
colNum = i;
}
if (colNum == -1)
return "";
sheet.autoSizeColumn(colNum);
row = sheet.getRow(rowNum - 1);
if (row == null)
row = sheet.createRow(rowNum - 1);
cell = row.getCell(colNum);
if (cell == null)
cell = row.createCell(colNum);
// cell style
// CellStyle cs = workbook.createCellStyle();
// cs.setWrapText(true);
// cell.setCellStyle(cs);
cell.setCellValue(data);
fileOut = new FileOutputStream(path);
workbook.write(fileOut);
fileOut.close();
} catch (Exception e) {
e.printStackTrace();
return "";
}
return "";
}
so can anybody tell me where I m going wrong.
Have a look at the HOWTO and examples.
You will notice that there are calls for creating a row or creating a cell. Unless you do so, the row/cell does not exist and your getCell() function will return null.
Changing for loop condition part i.e. i < row.getLastCellNum(); to i < row.getLastCellNum()-1; can resolve this issue.
getLastCellNum() returns index plus one and once the counter will reach to end value, getCell(i) can point to the null value as per your code.

How to copy a sheet from an Excel File Cell pop-up docuentation to another using POI Apache?

I am trying to copy a sheet from two different XSSF Workbooks. I have written a code that works really well (see below) but it doesn't take into account the pop-up documentation for cells and doesn't copy it (which is logical because I haven't written that functionnality).
I have searched the Apache POI documentation and it looks like there is no way to do this. Any idea on how I could do to copy-paste that information?
public class CopySheets {
public static void copySheet(String sheetName, XSSFWorkbook wbSrc,XSSFWorkbook wbDest) throws IOException {
XSSFSheet srcSheet = null;
XSSFRow srcRow = null;
XSSFCell srcCell = null;
XSSFSheet destSheet = null;
XSSFRow destRow = null;
XSSFCell destCell = null;
int fCell = 0;
int lCell = 0;
int fRow = 0;
int lRow = 0;
System.out.println(sheetName);
srcSheet = wbSrc.getSheet(sheetName);
System.out.println(srcSheet);
if (srcSheet != null) {
destSheet = wbDest.createSheet(sheetName);
fRow = srcSheet.getFirstRowNum();
lRow = srcSheet.getLastRowNum();
for (int iRow = fRow; iRow <= lRow; iRow++) {
srcRow = srcSheet.getRow(iRow);
destRow = destSheet.createRow(iRow);
if (srcRow != null) {
fCell = srcRow.getFirstCellNum();
lCell = srcRow.getLastCellNum();
for (int iCell = fCell; iCell < lCell; iCell++) {
srcCell = srcRow.getCell(iCell);
destCell = destRow.createCell(iCell);
if (srcCell != null) {
switch (srcCell.getCellTypeEnum()) {
case BLANK:
destCell.setCellValue("");
break;
case BOOLEAN:
destCell.setCellValue(srcCell.getBooleanCellValue());
break;
case ERROR:
destCell.setCellErrorValue(srcCell.getErrorCellValue());
break;
case FORMULA:
destCell.setCellFormula(srcCell.getCellFormula());
break;
case NUMERIC:
destCell.setCellValue(srcCell.getNumericCellValue());
break;
case STRING:
destCell.setCellValue(srcCell.getStringCellValue());
break;
default:
destCell.setCellFormula(srcCell.getCellFormula());
}
CellStyle origStyle = srcCell.getCellStyle(); // Or from a cell
CellStyle newStyle = wbDest.createCellStyle();
newStyle.cloneStyleFrom(origStyle);
destCell.setCellStyle(newStyle);
Comment origComment=srcCell.getCellComment();
destCell.setCellComment(origComment);
}
}
}
}
}
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("workbook.xls", true));
wbDest.write(bos);
bos.close();
}
}
Thanks a lot!
Okay, I found the answer, it turns out POI has something that enables us to get that info on the sheet as a whole so I added this bit to my code and it works like a charm!
List<XSSFDataValidation> validations=srcSheet.getDataValidations();
for (XSSFDataValidation validation:validations){
destSheet.addValidationData(validation);
}
Looking at the documentation-
http://poi.apache.org/apidocs/dev/org/apache/poi/ss/usermodel/Comment.html
Seems like the getAddress() method of the src Comment object will return the reference to the cell it was previously attached to (which is the src cell).
You should try creating a new Comment instead of doing
Comment origComment=srcCell.getCellComment();
destCell.setCellComment(origComment);
You should use RangeCopier.
XSSFWorkbook workbookFrom = new XSSFWorkbook(new File("/path/to/workbookFrom.xlsx"));
XSSFSheet sheetFrom = workbookFrom.getSheetAt(0);
XSSFWorkbook workbookTo = new XSSFWorkbook(new File("/path/to/workbookTo.xlsx"));
XSSFSheet sheetTo = workbookTo.createSheet("sheet1");
workbookTo.setSheetOrder("sheet1", 0);
XSSFRangeCopier xssfRangeCopier = new XSSFRangeCopier(sheetFrom, sheetTo);
//copy the row height and column width, and find the max column num
int lastRow = sheetFrom.getLastRowNum();
int lastCol = 0;
for (int i = 0; i < lastRow; i++) {
Row row = sheetFrom.getRow(i);
if (row != null) {
if (row.getLastCellNum() > lastCol) {
lastCol = row.getLastCellNum();
}
sheetTo.setDefaultRowHeight(sheetFrom.getDefaultRowHeight());
}
}
for (int j = 0; j < lastCol; j++) {
sheetTo.setColumnWidth(j, sheetFrom.getColumnWidth(j));
}
//copy contents from source sheet to destination sheet
CellRangeAddress cellAddresses = new CellRangeAddress(0, lastRow, 0, lastCol);
xssfRangeCopier.copyRange(cellAddresses, cellAddresses, true, true);
workbookTo.write(new FileOutputStream(new File("/path/to/worksheetTo.xlsx")));

how to add check symbol in excel cell SXSSFSheet java

I need to put a check symbol in this cell if the condition met. Here's my sample code:
private SXSSFWorkbook RepWkBook = null;
private SXSSFSheet RepSheet = null;
private int RepRowNum = 0;
private ResultSet RepResult = null;
private Row RepRow = null;
RepSheet = RepWkBook.createSheet(reportType);
RepRowNum = 0;
Row row = RepSheet.createRow(RepRowNum++);
CellStyle cellStyle = RepWkBook.createCellStyle();
Font font = RepWkBook.createFont();
font.setBold(true);
cellStyle.setFont(font);cell = RepRow.createCell(col++);
boolean isMOBhigherThanArea = RepResult.getString("IS_MOB_HIGHER_THAN_AREA").equalsIgnoreCase("1");
char st = '\u2713';
if(isMOBhigherThanArea && (!areaStr.equalsIgnoreCase("No Data") || !mobStr.equalsIgnoreCase("No Data"))) {
cell.setCellValue(st);}
I already used
UTF-16 - feff2713
UTF-16BE - 2713
UTF-16LE - 1327
UTF-8 - e29c93
click here for sample output
SAMPLE EXPECTED OUTPUT
Area | MOB Target | Area Result | MOB > Area
City | 85% | 80% | ✔
There is no method setCellValue which takes a char. Try using a String there.
The following works for me:
import java.io.FileOutputStream;
import org.apache.poi.xssf.streaming.*;
class CreateSXSSFUnicode {
public static void main(String[] args) throws Exception {
char st = '\u2713';
String[] headers = new String[] {"Area", "MOB Target", "Area Result", "MOB > Area"};
try (SXSSFWorkbook workbook = new SXSSFWorkbook();
FileOutputStream fileout = new FileOutputStream("Excel.xlsx") ) {
SXSSFSheet sheet = workbook.createSheet();
SXSSFRow row;
int rowNum = 0;
row = sheet.createRow(rowNum++);
for (int c = 0; c < headers.length; c++) {
row.createCell(c).setCellValue(headers[c]);
}
row = sheet.createRow(rowNum++);
int c = 0;
row.createCell(c++).setCellValue("City");
row.createCell(c++).setCellValue("85%");
row.createCell(c++).setCellValue("80%");
//row.createCell(c++).setCellValue(st); // does not work as st is a char
row.createCell(c++).setCellValue(String.valueOf(st)); // this works
workbook.write(fileout);
workbook.dispose();
}
}
}
Result:
Try using
ChrW(&H2713)
(source: https://www.mrexcel.com/board/threads/how-to-insert-a-checkmark-with-vba.607363/)
The only way that I can think of doing that is formatting your cell with a symbolic font, as Windings, and use the proper character for the check symbol in this font.
So your code would be something like:
Font font = RepWkBook.createFont();
font.setBold(true);
Font wingDingFont = RepWkBook.createFont();
wingDingFont.setBold(true);
wingDingFont.setFontName("Wingdings);
cell = RepRow.createCell(col++);
boolean isMOBhigherThanArea = RepResult.getString("IS_MOB_HIGHER_THAN_AREA").equalsIgnoreCase("1");
if(isMOBhigherThanArea && (!areaStr.equalsIgnoreCase("No Data") || !mobStr.equalsIgnoreCase("No Data"))) {
String st = "ü";
cellStyle.setFont(wingDingFont);
cell.setCellValue(st);
} else {
cellStyle.setFont(font);
}

poi java code to merge cells based on common data

I have data in the above format in an excel file , I want to edit it as follows:
I have used the following code :
public void editExcelTemplate() throws FileNotFoundException, IOException
{
InputStream ExcelFileToRead = new FileInputStream("file.xls");
XSSFWorkbook wb = new XSSFWorkbook(ExcelFileToRead);
XSSFSheet sheet = wb.getSheetAt(0);
int rows = sheet.getPhysicalNumberOfRows();
String cmp = "none";
for(int i=0;i<rows;i++)
{
Row row = sheet.getRow(i);
int col =row.getPhysicalNumberOfCells();
int colIndex = 1;
int v=0;
for(int j=0;j<col;j++)
{
String content = row.getCell(j).getStringCellValue();
if(!(content == cmp) && !(content.equals("none")))
{
if(!(cmp.equals("none")))
{
System.out.println("content: "+content);
System.out.println("cmp: "+cmp);
v= j;
System.out.println("row : "+i+"colst : "+(colIndex)+"colend : "+v);
if(!( v-colIndex == 0) && v>0)
{
System.out.println("row : "+i+"colst : "+(colIndex)+"colend : "+v);
sheet.addMergedRegion(new CellRangeAddress(i,i,colIndex-1,v-1));
System.out.println("merged");
}
}
}
if(!(content == cmp))
{
colIndex = v+1;
}
cmp = content;
}
}
FileOutputStream excelOutputStream = new FileOutputStream(
"file.xls");
wb.write(excelOutputStream);
excelOutputStream.close();
}
I endedup getting the following output :
Can anybody help me get an appropriate output ? The main purpose is to merge the cells with common data in the entire proces.

POI Set foreground color not working in if statement

I am doing some code that compares two sheets and outputs a file with the matching cells in green and the others in red.
Problematic section (see full code at the end)
CellStyle style = cellOutputFile.getCellStyle();
if (isCellContentEqual(cellComparisonFile1, cellComparisonFile2) == true)
{
style.setFillForegroundColor(IndexedColors.GREEN.getIndex());
}
else
{
style.setFillForegroundColor(IndexedColors.RED.getIndex());
}
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
cellOutputFile.setCellStyle(style);
Problem
This code always displays ALL cells as green, even if, when debugging, the else statement is triggered and the style is set to have a red background.
Thanks in advance for any help!
Full Code
for (int i = 0; i < workbookComparisonFile1.getNumberOfSheets(); i++)
{
sheetComparisonFile1 = workbookComparisonFile1.getSheetAt(i);
sheetComparisonFile2 = workbookComparisonFile2.getSheet(sheetComparisonFile1.getSheetName());
sheetOutputFile = workbookOutputFile.getSheet(sheetComparisonFile1.getSheetName());
System.out.println(sheetComparisonFile1.getLastRowNum());
if (sheetComparisonFile2 != null)
{
for (int j = 0; j < sheetComparisonFile1.getLastRowNum(); j++)
{
Row rowComparisonFile1 = sheetComparisonFile1.getRow(j);
Row rowComparisonFile2 = sheetComparisonFile2.getRow(j);
Row rowOutputFile = sheetOutputFile.getRow(j);
if ((rowComparisonFile1 != null && rowComparisonFile2 != null)
&& (rowComparisonFile1.getLastCellNum() == rowComparisonFile2.getLastCellNum()))
{
for (int k = 0; k < rowComparisonFile1.getLastCellNum(); k++)
{
Cell cellComparisonFile1 = rowComparisonFile1.getCell(k);
Cell cellComparisonFile2 = rowComparisonFile2.getCell(k);
Cell cellOutputFile = rowOutputFile.getCell(k);
if (cellComparisonFile1 != null && cellComparisonFile2 != null)
{
CellStyle style = cellOutputFile.getCellStyle();
if (isCellContentEqual(cellComparisonFile1, cellComparisonFile2) == true)
{
style.setFillForegroundColor(IndexedColors.GREEN.getIndex());
}
else
{
style.setFillForegroundColor(IndexedColors.RED.getIndex());
}
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
cellOutputFile.setCellStyle(style);
}
}
}
}
}
}
public boolean isCellContentEqual(Cell cell1, Cell cell2)
{
if (getCellContents(cell1).equals(getCellContents(cell2)) == false)
{
System.out.println("Sheet: " + cell1.getRow().getSheet().getSheetName() +
" Cell1: " + cell1.getRow().getRowNum() + "-" + cell1.getColumnIndex() + " "
+ getCellContents(cell1).equals(getCellContents(cell2)));
}
return getCellContents(cell1).equals(getCellContents(cell2));
}
public String getCellContents(Cell cell)
{
DataFormatter df = new DataFormatter();
return df.formatCellValue(cell);
}
Styles are created at the workbook level, not the cell level. Try the following code but this may fail if the workbook style table is full. Modify the if/else logic of your inner loop as such:
if (isCellContentEqual(cellComparisonFile1, cellComparisonFile2) == true)
{
CellStyle style = workbook.createCellStyle();
style.cloneStyleFrom(cellOutputFile.getCellStyle());
style.setFillForegroundColor(IndexedColors.GREEN.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
cellOutputFile.setCellStyle(style);
}
else
{
CellStyle style = workbook.createCellStyle();
style.cloneStyleFrom(cellOutputFile.getCellStyle());
style.setFillForegroundColor(IndexedColors.RED.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
cellOutputFile.setCellStyle(style);
}
edit code sample updated to copy preexisting style before changing the fill foreground color and fill pattern

Categories