I'm trying to get the font size of the header on an excel spreadsheet but I haven't been able to get it. I tried using the following to get the size but I haven't been able to get the size. None of the following worked for me because it doesn't return the correct font size.
headerFont.getFontHeight ();
headerFont.getFontHeightInPoints ();
Any suggestion?
Below is the code that I have:
try {
FileInputStream file = new FileInputStream(new File(fileName));
XSSFWorkbook workbook = new XSSFWorkbook(file);
XSSFSheet sheet = workbook.getSheetAt(1);
int numRows = sheet.getLastRowNum() + 1;
int numCols = sheet.getRow(0).getLastCellNum();
Iterator<Row> rowIterator = sheet.iterator();
for (int i = 0; i < 1; i++) {
Row row = rowIterator.next();
Iterator<Cell> cellIterator = row.cellIterator();
for (int j = 0; j < numCols; j++) {
Cell cell = cellIterator.next();
Font headerFont = workbook.createFont();
headerFontFamily = headerFont.getFontName();
headerFont.getFontHeight();
headerFont.getFontHeightInPoints();
}
}
file.close();
} catch (Exception e) {
}
You need to get the fonts from the cells. Fonts are part of the cell styles. Cell styles can be got via Cell.getCellStyle. Then the index of the used font can be got as a short via CelStyle.getFontIndex or as int via CelStyle.getFontIndexAsInt or as int via CelStyle.getFontIndex dependig of apache poi version used. The latter works using current 5.0.0 version.
Complete example:
import org.apache.poi.ss.usermodel.*;
import java.io.FileInputStream;
class ReadExcel {
public static void main(String[] args) throws Exception {
Workbook workbook = WorkbookFactory.create(new FileInputStream("./ExcelExample.xlsx"));
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
DataFormatter dataFormatter = new DataFormatter();
Sheet sheet = workbook.getSheetAt(0);
for (Row row : sheet) {
for (Cell cell : row) {
String value = dataFormatter.formatCellValue(cell, evaluator);
System.out.println(value);
CellStyle style = cell.getCellStyle();
//short fontIdx = style.getFontIndex(); // depends on apache poi version
//int fontIdx = style.getFontIndexAsInt(); // depends on apache poi version
int fontIdx = style.getFontIndex(); // depends on apache poi version
Font font = workbook.getFontAt(fontIdx);
System.out.println(font.getFontName() + ", " + font.getFontHeightInPoints());
}
}
workbook.close();
}
}
Note: This only works if the cell only has one font. If the cell contains rich text strings, then there are fonts for each formatting text run. Then RichTextString needs to be got and traversed. This is much more complex and needs to be done different for HSSF and XSSF.
Related
This question already has answers here:
How do I resolve ClassNotFoundException?
(28 answers)
Closed 6 months ago.
I am in a learning stage of Java. I want to write a program in Java which reads one Excel file (.xlsx). This file has some columns and many rows. I want to write the data in another Excel file (.xlsx) only the condition is met not all the data from existing file.
My Excel sheet looks like below
I want to filter only those rows with broker Edelweiss and put it in another Excel sheet. I am aware how to copy all the data from one Excel to another Excel using Java. I don't know how to filter a specific row and put it in another Excel.
Here is my code.
FileInputStream file = new FileInputStream(new File("broker.xlsx"));
//Create Workbook instance holding reference to .xlsx file
XSSFWorkbook workbook = new XSSFWorkbook(file);
//Get first/desired sheet from the workbook
XSSFSheet sheet = workbook.getSheetAt(0);
//Iterate through each rows one by one
Iterator<Row> rowIterator = sheet.iterator();
while (rowIterator.hasNext())
{
Row row = rowIterator.next();
//For each row, iterate through all the columns
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext())
{
Cell cell = cellIterator.next();
//Check the cell type and format accordingly
switch (cell.getCellType())
{
case Cell.CELL_TYPE_NUMERIC:
System.out.print(cell.getNumericCellValue() + "t");
break;
case Cell.CELL_TYPE_STRING:
System.out.print(cell.getStringCellValue() + "t");
break;
}
}
System.out.println("");
}
file.close();
}
catch (Exception e)
{
e.printStackTrace();
}
I am getting the below error when I run Axel Richter's code which is shared below
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/io/output/UnsynchronizedByteArrayOutputStream
at org.apache.poi.poifs.filesystem.FileMagic.valueOf(FileMagic.java:209)
at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:222)
at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:185)
at writefile.main(writefile.java:92)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
I have included below jars in my classpath
POI_LIB=$(TOP_DIR)/jar/poi-bin-5.2.2/poi-5.2.2.jar
POI_OOXML_LIB=$(TOP_DIR)/jar/poi-bin-5.2.2/poi-ooxml-full-5.2.2.jar
XML_BEANS_LIB=$(TOP_DIR)/jar/poi-bin-5.2.2/ooxml-lib/xmlbeans-5.0.3.jar
COM_COLL_LIB=$(TOP_DIR)/jar/poi-bin-5.2.2/lib/commons-collections4-4.4.jar
COM_COMPRESS_LIB=$(TOP_DIR)/jar/poi-bin-5.2.2/ooxml-lib/commons-compress-1.21.jar
COM_CODEC_LIB=$(TOP_DIR)/jar/poi-bin-5.2.2/lib/commons-codec-1.15.jar
COM_IO_LIB=$(TOP_DIR)/jar/poi-bin-5.2.2/lib/commons-io-2.11.0.jar
COM_MATH_LIB=$(TOP_DIR)/jar/poi-bin-5.2.2/lib/commons-math3-3.6.1.jar
LOG_J4_LIB=$(TOP_DIR)/jar/poi-bin-5.2.2/lib/log4j-api-2.17.2.jar
SPARSE_LIB=$(TOP_DIR)/jar/poi-bin-5.2.2/lib/SparseBitSet-1.2.jar
COM_LOGG_LIB=$(TOP_DIR)/jar/poi-bin-5.2.2/ooxml-lib/commons-logging-1.2.jar
CURVE_LIB=$(TOP_DIR)/jar/poi-bin-5.2.2/ooxml-lib/curvesapi-1.07.jar
SLF4_LIB=$(TOP_DIR)/jar/poi-bin-5.2.2/ooxml-lib/slf4j-api-1.7.36.jar
I will make my comment an answer.
I would open the source sheet and loop through all rows in it. For each row I would get the content of the column where "Broker" is stored. Then, if that content equals "Edelweiss" I would get that row into a Java collection, a list of rows for example. After that I would write the content of that Java collection into the result sheet.
The following complete example shows this.
It contains methods to get the last filled row in a special column of a sheet and to get the last filled column in a special row of a sheet. That is to determine the used cell range of a sheet.
It also contains a method to get the headings, which maps headings to column indexes. The headings must be in first row of the used cell range of the sheet.
It also shows how to use CellUtil.copyCell to copy cells from one sheet to another.
The code is tested and works using current apache poi 5.2.2.
The first sheet of broker.xlsx looks like:
Code:
import java.io.FileOutputStream;
import java.io.FileInputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellUtil;
import java.util.Locale;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
class ExcelFilterRowsToNewWorkbook {
static int getLastFilledRow(Sheet sheet, int col) {
int lastStoredRowNum = sheet.getLastRowNum();
for (int r = lastStoredRowNum; r >= 0; r--) {
Row row = sheet.getRow(r);
if (row != null) {
Cell cell = row.getCell(col);
if (cell != null && cell.getCellType() != CellType.BLANK) return row.getRowNum();
}
}
return -1; // the sheet is empty in that col
}
static int getLastFilledColumn(Sheet sheet, int rowIdx) {
int lastStoredCellNum = sheet.getRow(rowIdx).getLastCellNum();
Row row = sheet.getRow(rowIdx);
if (row != null) {
for (int c = lastStoredCellNum; c >= 0; c--) {
Cell cell = row.getCell(c);
if (cell != null && cell.getCellType() != CellType.BLANK) return cell.getColumnIndex();
}
}
return -1; // the sheet is empty in that row
}
static Map<Integer, String> getHeadings(Sheet sheet) {
DataFormatter dataFormatter = new DataFormatter(new Locale("en", "US"));
dataFormatter.setUseCachedValuesForFormulaCells(true);
int firstRow = sheet.getFirstRowNum();
int firstCol = sheet.getRow(firstRow).getFirstCellNum();
int lastCol = getLastFilledColumn(sheet, firstRow);
Map<Integer, String> headings = new HashMap<Integer, String>();
Row row = sheet.getRow(firstRow);
if (row != null) {
for (int c = firstCol; c <= lastCol; c++) {
Cell cell = row.getCell(c);
headings.put(c, dataFormatter.formatCellValue(cell));
}
}
return headings;
}
static List<Row> filterRows(Sheet sheet, String filterHeading, String filterValue) {
int filterCol = -1;
Map<Integer, String> headings = getHeadings(sheet);
for (Map.Entry<Integer, String> entry : headings.entrySet()) {
if (entry.getValue().equals(filterHeading)) {
filterCol = entry.getKey();
break;
}
}
List<Row> rows = new ArrayList<Row>();
// add the headings row
int firstRow = sheet.getFirstRowNum();
rows.add(sheet.getRow(firstRow));
// add the fildered rows
if (filterCol > -1) {
DataFormatter dataFormatter = new DataFormatter(new Locale("en", "US"));
dataFormatter.setUseCachedValuesForFormulaCells(true);
int firstCol = sheet.getRow(firstRow).getFirstCellNum();
int lastCol = getLastFilledColumn(sheet, firstRow);
int lastRow = getLastFilledRow(sheet, firstCol);
for (int r = firstRow; r <= lastRow; r++) {
Row row = sheet.getRow(r);
if (row != null && lastCol >= filterCol) {
Cell cell = row.getCell(filterCol);
String cellContent = dataFormatter.formatCellValue(cell);
if (cellContent.equals(filterValue)) {
rows.add(row);
}
}
}
}
return rows;
}
public static void main(String[] args) throws Exception {
try (Workbook workbookSrc = WorkbookFactory.create(new FileInputStream("./broker.xlsx")) ) {
Sheet sheetSrc = workbookSrc.getSheetAt(0);
// get filtered rows
List<Row> rowsSrc = filterRows(sheetSrc, "Broker", "Edelweiss");
// add filtered rows in new workbook
try (Workbook workbookDest = WorkbookFactory.create(true);
FileOutputStream fileout = new FileOutputStream("./brokerFiltered.xlsx") ) {
Sheet sheetDest = workbookDest.createSheet();
int r = 0;
for (Row rowSrc : rowsSrc) {
Row rowDest = sheetDest.createRow(r++);
for (Cell cellSrc : rowSrc) {
Cell cellDest = rowDest.createCell(cellSrc.getColumnIndex());
CellUtil.copyCell(cellSrc,
cellDest,
new CellCopyPolicy(),
new CellCopyContext()
);
}
}
workbookDest.write(fileout);
}
}
}
}
The first sheet of brokerFiltered.xlsx then looks like:
currently im struggling setting a DataFormat to a specific row.
This is how my Excel Sheet looks like. Im having those 4 Columns.
Column 1 should take DataFormat Number
Column 2 & 3 should take DataFormat Date
Column 4 is ok
public static void createTableRow(Sheet sheet, List<String> EDIROWKeys, int col, CellStyle style , int lastRowNum){
if(sheet == null){
return;
}
int lastRow = lastRowNum;
int newRow = lastRow + 1;
Workbook wb = sheet.getWorkbook();
SimpleDateFormat format = new SimpleDateFormat();
CreationHelper helper = wb.getCreationHelper();
org.apache.poi.ss.usermodel.DataFormat date = wb.createDataFormat();
XSSFRow row = (XSSFRow) sheet.createRow(newRow);
if(row == null){
return;
}
int startCol = col;
for(String string : EDIROWKeys){
XSSFCell cell = row.createCell(startCol);
FOe.getFOPSessionContext().getDbContext().out().println(string);
if(style != null){
cell.setCellStyle(style);
}else {
XSSFWorkbook wbx = (XSSFWorkbook) sheet.getWorkbook();
XSSFDataFormat dataformat = wbx.createDataFormat();
XSSFCellStyle cs = wbx.createCellStyle();
if(startCol == 1){
cs.setDataFormat(dataformat.getFormat("#"));
}
cell.setCellStyle(cs);
}
cell.setCellValue(string);
startCol++;
}
return;
}
This is the Method i am using to Create my rows & Columns
https://poi.apache.org/apidocs/dev/org/apache/poi/ss/usermodel/BuiltinFormats.html
This is the resource i was getting my DataFormats from.
I also tried applying those DataFormats with HssfDataformat to my cell - no success either.
I apperciate any helpful input :)
Solved by using setCellValue(Double);...
if(string.matches("\\d+")){
cell.setCellValue(Double.valueOf(string));
startCol++;
continue;
}
I see one possible case. If method argument style is null, new style, XSSFCellStyle cs is not applied to cell. Is cell.setCellStyle(cs) missing?
Please excuse me if I am not clear. English is not my first language.
I'm trying to write a code where I can traverse through the first row of an excel file until I find the column labeled 'Comments'. I want to run some action on the text in that column and then save the result in a new column at the end of the file. Can I traverse the xlsx file in a manner similar to indexes? And if so, how can I jump straight to a cell using that cell's coordinates?
public static void main(String[] args) throws IOException {
File myFile = new File("temp.xlsx");
FileInputStream fis = null;
try {
fis = new FileInputStream(myFile);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
#SuppressWarnings("resource")
XSSFWorkbook myWorkBook = new XSSFWorkbook (fis);
XSSFSheet mySheet = myWorkBook.getSheetAt(0);
Iterator<Row> rowIterator = mySheet.iterator();
Row row = rowIterator.next();
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
String comment = cell.toString();
if (comment.equals("Comments"))
{
System.out.println("Hello");
}
}
}
}
For the question "Wanted to go to the second column's 3rd row I could use coordinates like (3, 2)?":
Yes this is possible using CellUtil. Advantages over the methods in Sheet and Row are that CellUtil methods are able getting the cell if it exists already or creating the cell if it not already exists. So existing cells will be respected instead simply new creating them and so overwriting them.
Example:
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.CellUtil;
import java.util.concurrent.ThreadLocalRandom;
public class CreateExcelCellsByIndex {
public static void main(String[] args) throws Exception {
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet();
//put content in R3C2:
Cell cell = CellUtil.getCell(CellUtil.getRow(3-1, sheet), 2-1); //-1 because apache poi's row and cell indexes are 0 based
cell.setCellValue("R3C2");
//put content in 10 random cells:
for (int i = 1; i < 11; i++) {
int r = ThreadLocalRandom.current().nextInt(4, 11);
int c = ThreadLocalRandom.current().nextInt(1, 6);
cell = CellUtil.getCell(CellUtil.getRow(r-1, sheet), c-1);
String cellcontent = "";
if (cell.getCellTypeEnum() == CellType.STRING) {
cellcontent = cell.getStringCellValue() + " ";
}
cell.setCellValue(cellcontent + i + ":R"+r+"C"+c);
}
workbook.write(new FileOutputStream("CreateExcelCellsByIndex.xlsx"));
workbook.close();
}
}
FileInputStream file = new FileInputStream(new File(fileLocation));
Workbook workbook = new XSSFWorkbook(file);
Sheet sheet = workbook.getSheetAt(0);
Map<Integer, List<String>> data = new HashMap<>();
int i = 0;
for (Row row : sheet) {
data.put(i, new ArrayList<String>());
for (Cell cell : row) {
switch (cell.getCellTypeEnum()) {
case STRING: ... break;
case NUMERIC: ... break;
case BOOLEAN: ... break;
case FORMULA: ... break;
default: data.get(new Integer(i)).add(" ");
}
}
i++;
}
I'm not sure what you mean by 2D index, but a Cell knows which column it belongs to so something like this should work:
...
Cell cell = cellIterator.next();
String comment = cell.toString();
int sourceColumnIndex = -1;
if (comment.equals("Comments")) {
System.out.println("Hello");
sourceColumnIndex = cell.getColumnIndex();
}
....
Similarly, define something like int targetColumnIndex to represent the column which will have the result from processing all the cells from the sourceColumnIndex column.
Actually I tried to store some data in HSSFCell using java but i got an error like
java.lang.IllegalArgumentException: The maximum length of cell contents (text) i
s 32,767 characters
at org.apache.poi.hssf.usermodel.HSSFCell.setCellValue(HSSFCell.java:559
)
at org.apache.poi.hssf.usermodel.HSSFCell.setCellValue(HSSFCell.java:533
)
at application.ExtractUI.datatoexcel(ExtractUI.java:272)
at application.ExtractUI$3.getData(ExtractUI.java:208)
at application.ExtractUI$3.handle(ExtractUI.java:198)
at application.ExtractUI$3.handle(ExtractUI.java:1)
can anyone suggest me a method to increase the cell length ie more than 32767 characters???
I used the following code for which I got the above error
public void datatoexcel(ResultSet rs) {
try {
int iter = 0;
ResultSetMetaData rmeta = rs.getMetaData();
int col = rmeta.getColumnCount();
HSSFWorkbook workbook = new HSSFWorkbook();
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("ddMMyyyy HHmmss");
String pa = pth + "\\" + sdf.format(date) + ".xlsx";
System.out.println(pa);
FileOutputStream out = new FileOutputStream(new File(pa));
HSSFSheet sheet = workbook.createSheet();
HSSFRow myRow = null;
HSSFCell myCell = null;
// Font style for headers
HSSFFont boldFont = workbook.createFont();
boldFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
boldFont.setColor(HSSFFont.COLOR_RED);
HSSFCellStyle cellStyle = workbook.createCellStyle();
cellStyle.setFont(boldFont);
while (rs.next()) {
// limit the data to 1000 anad create a new sheet
if (iter == 1000) {
sheet = workbook.createSheet();
iter = 0;
}
// Adding header to the first row
if (iter == 0) {
myRow = sheet.createRow(iter);
for (int k = 1, j = 0; k <= col && j < col; k++) {
myCell = myRow.createCell( j);
myCell.setCellValue(rmeta.getColumnName(k));
// set style to font
myCell.setCellStyle(cellStyle);
j++;
}
iter++;
}
// Adding data from 2nd Row
myRow = sheet.createRow(iter);
for (int k = 1, j = 0; k <= col && j < col; k++) {
myRow.createCell( j).setCellValue(
rs.getString(rmeta.getColumnName(k)));
j++;
}
iter++;
}
workbook.write(out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
any suggestions??
Your only option is to switch file formats. There's a hard limit in both the .xls and .xlsx file formats of 32,767 characters. Apache POI is simply enforcing the file format + Excel limit. You can see details of those limits in the Microsoft documentation, and also captured nicely in this Apache POI javadoc page
If you really need text that long, you'll need to switch to another file format such as CSV
Or you can truncate your string length to the specified maximum length minus one
private void writeIssueDataForEachRow(Issue issue, Row row, CellStyle style,
List<ColumnIndex> customFieldDefinitions) {
Cell cell = row.createCell(0);
cell.setCellValue(issue.getId()); // 編號
cell.setCellStyle(style);
cell = row.createCell(1);
cell.setCellValue(issue.getSubject()); // 主旨
cell.setCellStyle(style);
// substring 的原因是要避開 The maximum length of cell contents (text) is 32,767 characters
cell = row.createCell(2);
cell.setCellValue(StringUtils.substring(issue.getDescription(), 0, 32767)); // 敘述
cell.setCellStyle(style);
}
I am trying to make an application that can read a .xlsx file and write on the row that does not contain any information. I have tried using something like:
FileInputStream fileIn = new FileInputStream("workbook.xlsx");
Workbook wb = new XSSFWorkbook(fileIn);
Sheet sheet = wb.getSheetAt(0);
Row row1;
Cell cell1;
Cell cell2;
int incrementator=0;
for (int i = 0; i < 1000; i++) {
for (int t = 0; t < 18; t++) {
cell1=sheet.getRow(i).getCell(t);
if(cell1==null){
cell2 = sheet.createRow(incrementator).createCell(0);
cell2.setCellType(Cell.CELL_TYPE_STRING);
cell2.setCellValue("Something");
System.out.println("Succes");
}else{
incrementator++;
System.out.println("Incrementing"+incrementator);
}
I know it's bad, but maybe it can help you understand what i'm trying to do.
Any help would be awesome. Thank you!
Try this:
FileInputStream fileIn = new FileInputStream("workbook.xlsx");
Workbook wb = new XSSFWorkbook(fileIn);
Sheet sheet = wb.getSheetAt(0);
for (int i = 0; i < sheet.getNumberOfRows(); i++) {
if(sheet.getRow(i).getPhysicalNumberOfCells() == 0){
//row is 'empty' : do stuff
}
}
Sheet.getRow(int) can return null, if the row hasn't been used or styled. In such a case, you need to create the row before you can use it. So, your code would want to be something like:
Worbook wb = WorkbookFactory.create(new File("workbook.xlsx"));
Sheet sheet = wb.getSheetAt(0);
Row row1 = sheet.getRow(0);
if (row1 == null) {
// First row hasn't been touched, so create it
row1 = sheet.createRow(1);
}
Cell cell1;
Cell cell2;
// etc
Also, if you have a file, use the file, don't use an inputstream!