I am getting Number stored as text warning for the created excel file using POI. I am trying to display percentage. This question discusses the same, but it's for python. Can some one please suggest me how to avoid this in java using POI?
Below are the lines where I get this warning.
workbook= new XSSFWorkbook();
sh1 = wb.createSheet("Data Sheet");
cell = row.createCell(3);
cell.setCellValue(37 + "%");
Based on Gagravarr answer I did it this way.
XSSFDataFormat df = workbook.createDataFormat();
CellStyle cs = wb.createCellStyle();
cs.setDataFormat(df.getFormat("%"));
cell.setCellValue(0.37);
cell.setCellStyle(cs);
But it just shows up as 0.37 with no warning now, not 37%.
You're getting the warning because, as it says, you're storing a number as text.
What you probably want to do is:
CellStyle cs = wb.createCellStyle();
cs.setDataFormat(df.getFormat("%"));
cell.setCellValue(0.37);
cell.setCellStyle(cs);
That will store the number 37 as a number, and tell excel to apply a percentage format string to it. Oh, and since 37% is 0.37, you need to store 0.37 not 37!
Edit By popular request, here's a standalone program you can use to see it in action, for both .xls and .xlsx files. Tested with POI 3.10 final, and with all the required dependencies and component jars on the classpath.
public class TestPercent {
public static void main(String[] args) throws Exception {
System.out.println("Generating...");
for (Workbook wb : new Workbook[] {new HSSFWorkbook(), new XSSFWorkbook()}) {
Sheet sheet = wb.createSheet("Data Sheet");
Row row = sheet.createRow(0);
Cell cell = row.createCell(3);
DataFormat df = wb.createDataFormat();
CellStyle cs = wb.createCellStyle();
cs.setDataFormat(df.getFormat("%"));
cell.setCellValue(0.37);
cell.setCellStyle(cs);
String output = "/tmp/text.xls";
if (wb instanceof XSSFWorkbook) { output += "x"; }
FileOutputStream out = new FileOutputStream(output);
wb.write(out);
out.close();
}
System.out.println("Done");
}
}
Try also setting the CellType:
cell.setCellType(Cell.CELL_TYPE_NUMERIC);
if(NumberUtils.isDigits(text)){
titleCell.setCellValue(Integer.parseInt(text));
}else{
titleCell.setCellValue(text);
}
XSSFWorkbook xSSFWorkbook = new XSSFWorkbook();
CreationHelper createHelper = xSSFWorkbook.getCreationHelper();
XSSFCellStyle numberStyle = xSSFWorkbook.createCellStyle();
numberStyle.setDataFormat(createHelper.createDataFormat().getFormat("###.00"));
double d = 50.0;
XSSFRow dataRow = sheet.createRow(1);
Cellcel1 = dataRow.createCell(1);
cel1.setCellValue(d);
This may be a bit old but try this:
df.getFormat("0.00%")
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 need to create an XL sheet using Apache POI with some values which are long numeric for ex:1234567891011.
When i use below sample code to generate the excel sheet, the data is stored in form of Scientific format (1.23457E+12). But i want to store this data as a number ex. 1234567891011.00 is fine.
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("format sheet");
String str = "1234567891011";
Row row;
Cell cell;
short rowNum = 0;
short colNum = 0;
row = sheet.createRow(rowNum++);
cell = row.createCell(colNum);
cell.setCellValue(str);
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();
I tried to set the cell format to Numeric as below code but doesnt work.
row = sheet.createRow(rowNum++);
cell = row.createCell(colNum);
cell.setCellValue(str);
dateCell1.setCellType(XSSFCell.CELL_TYPE_NUMERIC);
double converted = new Double(str);
dateCell1.setCellValue(converted);
Please tell if any way possible to do it.
Excel is using number format General per default. This switches to scientific format if needed. That means if cell width is too small or numeric value is too big.
So do using a cell style having a special number format 0.00 or 0.
Example:
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
class CreateExcelBigDecimal {
public static void main(String[] args) throws Exception {
//Workbook workbook = new XSSFWorkbook(); String filePath = "./Excel.xlsx";
Workbook workbook = new HSSFWorkbook(); String filePath = "./Excel.xls";
DataFormat format = workbook.createDataFormat();
CellStyle numberCellStyle = workbook.createCellStyle();
numberCellStyle.setDataFormat((short)8);
numberCellStyle.setDataFormat(format.getFormat("0.00"));
Sheet sheet = workbook.createSheet();
Cell cell = sheet.createRow(0).createCell(0);
double value = 1234567891011d;
cell.setCellValue(value);
cell.setCellStyle(numberCellStyle);
sheet.setColumnWidth(0, 20*256);
FileOutputStream out = new FileOutputStream(filePath);
workbook.write(out);
out.close();
workbook.close();
}
}
That leads to showing 1234567891011.00 in cell A1.
Leave the cell as String type and format your number java side.
long yourLongNumber = 1234567891011;
String strLong = String.format("%d", yourLongNumber);
//out: "1234567891011"
I've looked arround and have'nt found a answer to my problem.
I try to format a Cell with a custom CellType, does anyone know if it's possible.
I try to use the custom Format '[HH]:MM' on my Cells.
As far as I found out is it only possible to use the predefined CellTypes. Does anyone know more and can halp me?
Thanks in advance
Below is an example of some code which will do what you are trying to achieve.
Workbook w = new XSSFWorkbook();
CreationHelper createHelper = w.getCreationHelper();
CellStyle cs = w.createCellStyle();
cs.setDataFormat(createHelper.createDataFormat().getFormat("HH:mm"));
Sheet sheet = w.createSheet(String.valueOf("Format Test"));
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
cell.setCellStyle(cs);
cell.setCellValue(new Date());
File outFile = new File("Test.xlsx");
try {
FileOutputStream fileOut = new FileOutputStream(outFile);
w.write(fileOut);
} catch (IOException ex) {
// do something with exception data
}
I've been using Apache POI for some time to read existing Excel 2003 files programmatically. Now I have a new requirement to create entire .xls files in-memory (still using Apache POI) and then write them to a file at the end. The only problem standing in my way is the handling of cells with dates.
Consider the following code:
Date myDate = new Date();
HSSFCell myCell;
// code that assigns a cell from an HSSFSheet to 'myCell' would go here...
myCell.setCellValue(myDate);
When I write the workbook containing this cell out to a file and open it with Excel, the cell is displayed as a number. Yes, I do realize that Excel stores its 'dates' as the number of days since January 1 1900 and that is what the number in the cell represents.
QUESTION: What API calls can I use in POI to tell it that I want a default date format applied to my date cell?
Ideally I want the spreadsheet cell to be displayed with the same default date format that Excel would have assigned it if a user had manually opened the spreadsheet in Excel and typed in a cell value that Excel recognized as being a date.
http://poi.apache.org/spreadsheet/quick-guide.html#CreateDateCells
CellStyle cellStyle = wb.createCellStyle();
CreationHelper createHelper = wb.getCreationHelper();
cellStyle.setDataFormat(
createHelper.createDataFormat().getFormat("m/d/yy h:mm"));
cell = row.createCell(1);
cell.setCellValue(new Date());
cell.setCellStyle(cellStyle);
To set to default Excel type Date (defaulted to OS level locale /-> i.e. xlsx will look different when opened by a German or British person/ and flagged with an asterisk if you choose it in Excel's cell format chooser) you should:
CellStyle cellStyle = xssfWorkbook.createCellStyle();
cellStyle.setDataFormat((short)14);
cell.setCellStyle(cellStyle);
I did it with xlsx and it worked fine.
This example is for working with .xlsx file types. This example comes from a .jsp page used to create a .xslx spreadsheet.
import org.apache.poi.xssf.usermodel.*; //import needed
XSSFWorkbook wb = new XSSFWorkbook (); // Create workbook
XSSFSheet sheet = wb.createSheet(); // Create spreadsheet in workbook
XSSFRow row = sheet.createRow(rowIndex); // Create the row in the spreadsheet
//1. Create the date cell style
XSSFCreationHelper createHelper = wb.getCreationHelper();
XSSFCellStyle cellStyle = wb.createCellStyle();
cellStyle.setDataFormat(
createHelper.createDataFormat().getFormat("MMMM dd, yyyy"));
//2. Apply the Date cell style to a cell
//This example sets the first cell in the row using the date cell style
cell = row.createCell(0);
cell.setCellValue(new Date());
cell.setCellStyle(cellStyle);
In addition to #BlondeCode answer, here are the list of all available formats that you can get with
creationHelper.createDataFormat().getFormat((short) index)
0 = "General"
1 = "0"
2 = "0.00"
3 = "#,##0"
4 = "#,##0.00"
5 = ""$"#,##0_);("$"#,##0)"
6 = ""$"#,##0_);Red"
7 = ""$"#,##0.00_);("$"#,##0.00)"
8 = ""$"#,##0.00_);Red"
9 = "0%"
10 = "0.00%"
11 = "0.00E+00"
12 = "# ?/?"
13 = "# ??/??"
14 = "m/d/yy"
15 = "d-mmm-yy"
16 = "d-mmm"
17 = "mmm-yy"
18 = "h:mm AM/PM"
19 = "h:mm:ss AM/PM"
20 = "h:mm"
21 = "h:mm:ss"
22 = "m/d/yy h:mm"
23-36 = reserved
37 = "#,##0_);(#,##0)"
38 = "#,##0_);Red"
39 = "#,##0.00_);(#,##0.00)"
40 = "#,##0.00_);Red"
41 = "(* #,##0);(* (#,##0);(* "-");(#)"
42 = "("$"* #,##0_);("$"* (#,##0);("$"* "-");(#)"
43 = "(* #,##0.00_);(* (#,##0.00);(* "-"??);(#)"
44 = "("$"* #,##0.00_);("$"* (#,##0.00);("$"* "-"??);(#_)"
45 = "mm:ss"
46 = "[h]:mm:ss"
47 = "mm:ss.0"
48 = "##0.0E+0"
49 = "#"
And from index 164, there are your custom patterns
To know the format string used by Excel without having to guess it: create an excel file, write a date in cell A1 and format it as you want. Then run the following lines:
FileInputStream fileIn = new FileInputStream("test.xlsx");
Workbook workbook = WorkbookFactory.create(fileIn);
CellStyle cellStyle = workbook.getSheetAt(0).getRow(0).getCell(0).getCellStyle();
String styleString = cellStyle.getDataFormatString();
System.out.println(styleString);
Then copy-paste the resulting string, remove the backslashes (for example d/m/yy\ h\.mm;# becomes d/m/yy h.mm;#) and use it in the http://poi.apache.org/spreadsheet/quick-guide.html#CreateDateCells code:
CellStyle cellStyle = wb.createCellStyle();
CreationHelper createHelper = wb.getCreationHelper();
cellStyle.setDataFormat(createHelper.createDataFormat().getFormat("d/m/yy h.mm;#"));
cell = row.createCell(1);
cell.setCellValue(new Date());
cell.setCellStyle(cellStyle);
I am writing my answer here because it may be helpful to other readers, who might have a slightly different requirement than the questioner here.
I prepare an .xlsx template; all the cells which will be populated with dates, are already formatted as date cells (using Excel).
I open the .xlsx template using Apache POI and then just write the date to the cell, and it works.
In the example below, cell A1 is already formatted from within Excel with the format [$-409]mmm yyyy, and the Java code is used only to populate the cell.
FileInputStream inputStream = new FileInputStream(new File("Path to .xlsx template"));
Workbook wb = new XSSFWorkbook(inputStream);
Date date1=new Date();
Sheet xlsMainTable = (Sheet) wb.getSheetAt(0);
Row myRow= CellUtil.getRow(0, xlsMainTable);
CellUtil.getCell(myRow, 0).setCellValue(date1);
WHen the Excel is opened, the date is formatted correctly.
This code sample can be used to change date format. Here I want to change from yyyy-MM-dd to dd-MM-yyyy. Here pos is position of column.
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
class Test{
public static void main( String[] args )
{
String input="D:\\somefolder\\somefile.xlsx";
String output="D:\\somefolder\\someoutfile.xlsx"
FileInputStream file = new FileInputStream(new File(input));
XSSFWorkbook workbook = new XSSFWorkbook(file);
XSSFSheet sheet = workbook.getSheetAt(0);
Iterator<Row> iterator = sheet.iterator();
Cell cell = null;
Row row=null;
row=iterator.next();
int pos=5; // 5th column is date.
while(iterator.hasNext())
{
row=iterator.next();
cell=row.getCell(pos-1);
//CellStyle cellStyle = wb.createCellStyle();
XSSFCellStyle cellStyle = (XSSFCellStyle)cell.getCellStyle();
CreationHelper createHelper = wb.getCreationHelper();
cellStyle.setDataFormat(
createHelper.createDataFormat().getFormat("dd-MM-yyyy"));
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d=null;
try {
d= sdf.parse(cell.getStringCellValue());
} catch (ParseException e) {
// TODO Auto-generated catch block
d=null;
e.printStackTrace();
continue;
}
cell.setCellValue(d);
cell.setCellStyle(cellStyle);
}
file.close();
FileOutputStream outFile =new FileOutputStream(new File(output));
workbook.write(outFile);
workbook.close();
outFile.close();
}}
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();