I try to change background color of a row, or highlight it with a different color with use of following code:
FileInputStream fis = new FileInputStream(src);
HSSFWorkbook wb = new HSSFWorkbook(fis);
HSSFSheet sheet = wb.getSheetAt(0);
r = sheet.getRow(5);
CellStyle style = wb.createCellStyle();
style.setFillForegroundColor(IndexedColors.RED.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
r.setRowStyle(style);
FileOutputStream fileOut = new FileOutputStream(excelFileName);
wb.write(fileOut);
wb.close();
fileOut.flush();
fileOut.close();
I create a style, set it to a row and after that I write it out to same file. File is modified when I execute code, but background color isn't changed.
setRowStyle(CellStyle style) doesn't work as you would expect. Taking a look at the XSSFRow source code you will not find an iteration over the cells in the row or something similar.
/**
* Applies a whole-row cell styling to the row.
* If the value is null then the style information is removed,
* causing the cell to used the default workbook style.
*/
#Override
public void setRowStyle(CellStyle style) {
if(style == null) {
if(_row.isSetS()) {
_row.unsetS();
_row.unsetCustomFormat();
}
} else {
StylesTable styleSource = getSheet().getWorkbook().getStylesSource();
XSSFCellStyle xStyle = (XSSFCellStyle)style;
xStyle.verifyBelongsToStylesSource(styleSource);
long idx = styleSource.putStyle(xStyle);
_row.setS(idx);
_row.setCustomFormat(true);
}
}
To my knowledge it is more like setting a default row style. But even when you set a row style this way afterwards created cells in this row won't get this style. Most probably you will have to do the styling cell by cell.
Related
I am trying following two sets of code to make part of the cell content bold/italic in streaming XSSFWorkbook that is SXSSFWorkbook. But it is not working. Any help in this regard is appreciated.
The cell content should look like following
This is sample content
try (SXSSFWorkbook wb = new SXSSFWorkbook()) {
SXSSFSheet sheet = wb.createSheet("With Rich Text");
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
XSSFFont fontPlain = (XSSFFont) wb.createFont();
XSSFFont fontBoldItalic = (XSSFFont) wb.createFont();
fontBoldItalic.setBold(true);
fontBoldItalic.setItalic(true);
XSSFFont fontItalic = (XSSFFont) wb.createFont();
fontItalic.setItalic(true);
XSSFRichTextString cell1Value= new XSSFRichTextString();
cell1Value.append("This is ");
cell1Value.append("sample ", fontBoldItalic);
cell1Value.append("content", fontItalic);
cell.setCellValue(cell1Value);
wb.write(new FileOutputStream("BoldFile.xlsx"));
} catch (IOException e) {
e.printStackTrace();
}
Also following code does the same. The cell content should look like following
Hello World
try (SXSSFWorkbook wb = new SXSSFWorkbook()) {
SXSSFSheet sheet = wb.createSheet("With Rich Text");
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
Font fontBold = wb.createFont();
fontBold.setBold(true);
String value = "Hello World";
String subValue = "World";
cell.setCellValue(value);
RichTextString rts = cell.getRichStringCellValue();
rts.applyFont(value.indexOf(subValue), value.length(), fontBold);
cell.setCellValue(rts);
wb.write(new FileOutputStream("BoldFile.xlsx"));
} catch (IOException e) {
e.printStackTrace();
}
You should always create the RichTextString using CreationHelper.createRichTextString(java.lang.String text) where CreationHelper comes from Workbook.getCreationHelper(). So you can be sure, that the created RichTextString always is of same type as the workbook. For example HSSFRichTextString from a HSSFCreationHelper, XSSFRichTextString from a XSSFCreationHelper and XSSFRichTextString for streaming SXSSF from a SXSSFCreationHelper. When created using the constructors that is not always guaranteed.
But using SXSSF there is an issue when SXSSFWorkbook uses inline strings instead of a shared strings table. This is the default in SXSSF because inline strings are better usable in the streaming approach. But Apache POI fails to create rich text content in inline strings. It only creates rich text content in the shared strings table, which is the default in Excel.
So using Workbook workbook = new SXSSFWorkbook(); no rich text cell content can be created. One needs using Workbook workbook = new SXSSFWorkbook(new XSSFWorkbook(), 100, false, true); which tells to create a SXSSFWorkbook from a new empty XSSFWorkbook, using the default rowAccessWindowSize of 100, not to use gzip compression for temporary files and to use a shared strings table.
Following code will work for all kinds of Workbook and create rich text cell content.
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
class CreateExcelRichTextString {
public static void main(String[] args) throws Exception {
//Workbook workbook = new XSSFWorkbook(); FileOutputStream out = new FileOutputStream("./Excel.xlsx");
//Workbook workbook = new HSSFWorkbook(); FileOutputStream out = new FileOutputStream("./Excel.xls");
//Workbook workbook = new SXSSFWorkbook(); FileOutputStream out = new FileOutputStream("./Excel.xlsx");
Workbook workbook = new SXSSFWorkbook(new XSSFWorkbook(), 100, false, true); FileOutputStream out = new FileOutputStream("./Excel.xlsx");
CreationHelper creationHelper = workbook.getCreationHelper();
Font font = workbook.createFont(); // default font
Font fontBold = workbook.createFont();
fontBold.setBold(true);
Font fontItalic = workbook.createFont();
fontItalic.setItalic(true);
String text = "This is some sample content.";
RichTextString richTextString = creationHelper.createRichTextString(text);
String word = "some";
int startIndex = text.indexOf(word);
int endIndex = startIndex + word.length();
richTextString.applyFont(startIndex, endIndex, fontBold);
word = "sample";
startIndex = text.indexOf(word);
endIndex = startIndex + word.length();
richTextString.applyFont(startIndex, endIndex, fontItalic);
Sheet sheet = workbook.createSheet();
sheet.createRow(0).createCell(0).setCellValue(richTextString);
workbook.write(out);
out.close();
workbook.close();
if (workbook instanceof SXSSFWorkbook) ((SXSSFWorkbook)workbook).dispose();
}
}
Conclusion: Stop thinking SXSSF is the better XSSF because of using streaming approach to save memory usage. It is not. It has disadvantages of it's own. The structure of spreadsheet application files is nothing what is good to stream bulk data in.
I try to use Apache POI to change background colors of cells in a row. I use following code to handle it in xls file, but there aren't any changes in file after execution.
FileInputStream fis = new FileInputStream(src);
HSSFWorkbook wb = new HSSFWorkbook(fis);
r = sheet.getRow(5);
CellStyle style = wb.createCellStyle();
style.setFillForegroundColor(IndexedColors.RED.getIndex());
r.setRowStyle(style);
Style for cells has to be defined like this.
HSSFCellStyle tCs = wb.createCellStyle();
tCs.setFillPattern(FillPatternType.SOLID_FOREGROUND);
tCs.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
It has to be applied each cells, which needed this style.
for (int k = 0; k < sheet.getRow(5).getLastCellNum(); k++) {
sheet.getRow(i).getCell(k).setCellStyle(tCs);
}
I used POI and tried to arrange one entire column. But only the way I found is arrange individual cell. Although I found sheet.setDefaultColumnStyle() and tried to use this function, it doesn't work at all.
could you let me know the way of using setDefaultColumnStyle() or another way.
below code is my code to arrange individual cell.
xlsxFile = new File("data.xlsx");
wb = new XSSFWorkbook();
cellStyle = wb.createCellStyle();
cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
row = sheet1.createRow(0);
cell = row.createCell(1);
cell.setCellValue("name");
cell.setCellStyle(cellStyle);
My english skill is a little awkward. Thank you for reading. If there is anything weird, please let me know.
This seems to be an bug in Apache POI. There are two issues:
First: After using Sheet.setDefaultColumnStyle with a style which defines alignments, POI does not set applyAlignment="true" in the xf element's tag in styles.xml. But it should, because only that will cause Excel to apply the alignments from that style to new cells.
Second: POI itself does not apply this style to new cells in that column. It should set s="1", where 1 is the style number, in the corresponding c tag of Sheet1.xml.
So we have to workaround:
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import java.io.FileOutputStream;
import java.io.IOException;
class CenteredColumn {
public static void main(String[] args) {
try {
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("Sheet1");
CellStyle cellStyle = wb.createCellStyle();
cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
sheet.setDefaultColumnStyle(1, cellStyle);
//Workaround 1: We set setApplyAlignment(true) into the `xf` element's tag in styles.xml.
//This causes Excel applying alignments from this style to new cells in that column.
for (int i = 0; i < ((XSSFWorkbook)wb).getStylesSource().getNumCellStyles(); i++) {
if (((XSSFWorkbook)wb).getStylesSource().getStyleAt(i).equals(cellStyle)) {
((XSSFWorkbook)wb).getStylesSource().getCellXfAt(i).setApplyAlignment(true);
}
}
Row row = sheet.getRow(0);
if (row == null) row = sheet.createRow(0);
Cell cell = row.getCell(1);
if (cell == null) cell = row.createCell(1);
cell.setCellValue("name");
//Workaround 2: We set the cellStyle to the new cell because POI will not do this itself.
cell.setCellStyle(cellStyle);
FileOutputStream fileOut = new FileOutputStream("workbook.xlsx");
wb.write(fileOut);
} catch (IOException ioex) {
}
}
}
Cell cell = row.createCell(1);
cell.setCellValue(rdf.getEffectiveDate());
cell.getCellStyle().setDataFormat(HSSFDataFormat.getBuiltinFormat("d-mmm-yy"));
cell = row.createCell(2);
cell.setCellValue(rdf.getExpiryDate());
cell.getCellStyle().setDataFormat(HSSFDataFormat.getBuiltinFormat("d-mmm-yy"));
row.createCell(3).setCellValue(rdf.getPremium());
row.createCell(4).setCellValue(rdf.getAccountNumber());
row.createCell(5).setCellValue(rdf.getLedgerName());
I wanted to apply Date Format on two of the above columns. But it is getting applied to all the cells. How can I prevent this.
As the documentation states, Cell.getCellStyle() will never return null.
https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html#getCellStyle()
When no cell style has been explicitly set for a Cell then it will return the default cell style which is initially shared among all cells in the workbook. Changing this then will obviously affect all cells not having an explictly assigned style.
You need to create a new CellStyle and then assign this to the relevant cells.
From the POI developer guide:
https://poi.apache.org/spreadsheet/quick-guide.html#CreateDateCells
Workbook wb = new HSSFWorkbook();
//Workbook wb = new XSSFWorkbook();
CreationHelper createHelper = wb.getCreationHelper();
Sheet sheet = wb.createSheet("new sheet");
// Create a row and put some cells in it. Rows are 0 based.
Row row = sheet.createRow(0);
// Create a cell and put a date value in it. The first cell is not styled
// as a date.
Cell cell = row.createCell(0);
cell.setCellValue(new Date());
// we style the second cell as a date (and time). It is important to
// create a new cell style from the workbook otherwise you can end up
// modifying the built in style and effecting not only this cell but other cells.
CellStyle cellStyle = wb.createCellStyle();
cellStyle.setDataFormat(
createHelper.createDataFormat().getFormat("m/d/yy h:mm"));
cell = row.createCell(1);
cell.setCellValue(new Date());
cell.setCellStyle(cellStyle);
//you can also set date as java.util.Calendar
cell = row.createCell(2);
cell.setCellValue(Calendar.getInstance());
cell.setCellStyle(cellStyle);
// Write the output to a file
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();
Try creating a new cell style. I think you may be changing the default style. So something like this...
CellStyle dateTimeCS = wb.createCellStyle();
dateTimeCS.setDataFormat(HSSFDataFormat.getBuiltinFormat("d-mmm-yy"));
cell.setCellStyle(dateTimeCS);
use RegionUtil to apply borders to a range of cells
https://poi.apache.org/apidocs/org/apache/poi/ss/util/RegionUtil.html
looks like it was added in version 3.15
I want read only excel sheet after creating it using Apache POI HSSF. How can I do that?
A detailed description can be found here:
http://systeminetwork.com/article/locking-cells-hssf
Basically you have to assign your cells a custom CellStyle with CellStyle.setLocked(true)
Edited
Hi Gaurav,
here is the complete and working code:
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("sheet1");
/* password required for locks to become effective */
sheet.protectSheet("secretPassword");
/* cell style for locking */
CellStyle lockedCellStyle = workbook.createCellStyle();
lockedCellStyle.setLocked(true);
/* cell style for editable cells */
CellStyle unlockedCellStyle = workbook.createCellStyle();
unlockedCellStyle.setLocked(false);
/* cell which will be locked */
Cell lockedCell = sheet.createRow(0).createCell(0);
lockedCell.setCellValue("Hi, I'm locked...");
lockedCell.setCellStyle(lockedCellStyle);
/* unlocked cell */
Cell unlockedCell = sheet.createRow(1).createCell(0);
unlockedCell.setCellValue("Just edit me...");
unlockedCell.setCellStyle(unlockedCellStyle);
OutputStream out = new FileOutputStream("sample.xls");
workbook.write(out);
out.flush();
out.close();
Here is some tested code that works in making the specific cell readonly. Based on your comment in #Thomas Weber's answer.
This sets an initial value in a cell, then it uses a data constraint to ensure that fixed value cannot be modified by the user in Excel. Try it out.
HSSFWorkbook workBook = new HSSFWorkbook ();
HSSFSheet sheet1 = workBook.createSheet();
HSSFRow row1 = sheet1.createRow(10);
HSSFCell cell1 = row1.createCell(0);
cell1.setCellValue("text: The new line which should be locked"); // SETTING INITIAL VALUE
HSSFCell displayNameCell = cell1;
String[] displayNameList = new String[]{"text: The new line which should be locked"}; //ADDING SAME VALUE INTO A STRING ARRAY AS THE RESTRICTED VALUE
DVConstraint displayNameConstraint = DVConstraint.createExplicitListConstraint(displayNameList);
CellRangeAddressList displayNameCellRange = new CellRangeAddressList(displayNameCell.getRowIndex(),displayNameCell.getRowIndex(),displayNameCell.getColumnIndex(),displayNameCell.getColumnIndex());
HSSFDataValidation displayNameValidation = new HSSFDataValidation(displayNameCellRange,displayNameConstraint);
displayNameValidation.createErrorBox("Not Applicable","Cannot change the value");
displayNameValidation.setSuppressDropDownArrow(true);
displayNameCell.getSheet().addValidationData(displayNameValidation);
// Write the output to a file
FileOutputStream fileOut1 = new FileOutputStream("D:\\book.xls");
workBook.write(fileOut1);
fileOut1.close();
This code is based on this thread http://osdir.com/ml/user-poi.apache.org/2009-07/msg00056.html
new File("/path/to/file.xls").setReadOnly();