Hi guys I just want to ask about how to remove the page break in column N in excel using the Apache poi in Java. I've already set up in my code that my print area is until column P. But when I try to print the generated excel it always set that the page break is in column N.
How can I adjust the page break in column using Apache poi on java?
If the goal is that at print all columns (A:P) fit to one page width, then one could solve this using Scale a worksheet.
The following code uses Sheet.setAutobreaks and Sheet.setFitToPage combinated with PrintSetup.setFitWidth and PrintSetup.setFitHeight to set the print setup to scale to fit. The width is set to fit all columns to 1 page width and the height is set automatic, so multiple pages are used when enough rows are present.
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class CreateExcelAllColumnsFitToOnePageWidth {
public static void main(String[] args) throws Exception {
//Workbook workbook = new HSSFWorkbook();
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet();
for (int r = 0; r < 200; r++) {
Row row = sheet.createRow(r);
for (int c = 0; c < 16; c++) {
Cell cell = row.createCell(c);
cell.setCellValue("Lorem ipsum");
if (r==0) sheet.autoSizeColumn(c);
}
}
sheet.setAutobreaks(true);
sheet.setFitToPage(true);
PrintSetup printSetup = sheet.getPrintSetup();
printSetup.setFitHeight((short)0);
printSetup.setFitWidth((short)1);
String fileout = (workbook instanceof HSSFWorkbook)?"Excel.xls":"Excel.xlsx";
FileOutputStream out = new FileOutputStream(fileout);
workbook.write(out);
out.close();
}
}
Related
I'm using apache poi to create excels in my java application.
My use case is when the value in A1 is Change it.
Style in cells A10 to A14 will be changed.
For this I'm following feature of ConditionalFormatting provided by poi.
But the style is only getting applied to cell A10 & not till A14.
What am I missing?
Code:
private void addValidations(Sheet sheet) {
SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("=A1=\"Change it\"");
FontFormatting fontFmt = rule1.createFontFormatting();
fontFmt.setFontStyle(true, false);
fontFmt.setFontColorIndex(IndexedColors.YELLOW.index);
BorderFormatting bordFmt = rule1.createBorderFormatting();
bordFmt.setBorderBottom(BorderStyle.THIN);
bordFmt.setBorderTop(BorderStyle.THICK);
bordFmt.setBorderLeft(BorderStyle.DASHED);
bordFmt.setBorderRight(BorderStyle.DOTTED);
ConditionalFormattingRule [] cfRules =
{
rule1
};
CellRangeAddress[] regions = {
CellRangeAddress.valueOf("A10:A14")
};
sheetCF.addConditionalFormatting(regions, cfRules);
}
The code sheetCF.createConditionalFormattingRule("=A1=\"Change it\""); cannot work at all. In HSSF it throws org.apache.poi.ss.formula.FormulaParseException: The specified formula '=A1="Change it"' starts with an equals sign which is not allowed.. In XSSF it creates a corrupt *.xlsx file. The leading equals sign is not stored in Excel formula cells. t only is shown in Excel's GUI. So it would must be sheetCF.createConditionalFormattingRule("A1=\"Change it\"");.
And the formula =A1="Change it" is relative in column letter as well as in row number. So applied to cell A10 it means =A1="Change it". But applied to cell A11 it means =A2="Change it". And applied to cell A12 it means =A3="Change it" and so on. So if the need is changing all font colors in A10:A14 if content of A1 changes, then the reference in the formula would must be fixed using $. So it would must be sheetCF.createConditionalFormattingRule("A$1=\"Change it\"");.
Complete Example:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;
import java.io.FileOutputStream;
public class ConditionalFormatting {
public static void main(String[] args) throws Exception {
Workbook workbook = new XSSFWorkbook(); String filePath ="./ConditionalFormatting.xlsx";
//Workbook workbook = new HSSFWorkbook(); String filePath ="./ConditionalFormatting.xls";
Sheet sheet = workbook.createSheet();
for (int r = 9; r < 14; r++) {
sheet.createRow(r).createCell(0).setCellValue("Text in Cell A" + (r+1));
}
SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
ConditionalFormattingRule rule = sheetCF.createConditionalFormattingRule("A$1=\"Change it\"");
FontFormatting fontFormatting = rule.createFontFormatting();
fontFormatting.setFontStyle(false, true);
fontFormatting.setFontColorIndex(IndexedColors.YELLOW.index);
ConditionalFormattingRule[] cfRules = new ConditionalFormattingRule[]{rule};
CellRangeAddress[] regions = new CellRangeAddress[]{CellRangeAddress.valueOf("A10:A14")};
sheetCF.addConditionalFormatting(regions, cfRules);
FileOutputStream out = new FileOutputStream(filePath);
workbook.write(out);
out.close();
workbook.close();
}
}
This changes font color in A10:A14 to yellow if cell content in A1 is Change it.
Try this if this works.
CellRangeAddress[] regions = new CellRangeAddress[]{ CellRangeAddress.valueOf("A10:A14") };
I want to fill table a template excel file. I want to insert rows and fill them. I used java Apache POI library to access excel files. At first, I created a new file and filled column A from row 1 to 10 with 1..10 numbers and saved the file. Then I read the file and tried to insert a single empty row with a sheet.shiftRows() method. I tried below code but output file has a problem in the opening (reading) and rows 5,6,7 are empty and move has not occurred.
InputStream inputStream = new FileInputStream("TestIn-1.xlsx");
Workbook workbookIn = new XSSFWorkbook(inputStream);
Sheet sheetIn = workbookIn.getSheet("Sheet1");
sheetIn.shiftRows(4,5,1);
OutputStream outputStream = new FileOutputStream("TestOut.xlsx");
workbookIn.write(outputStream);
outputStream.close();
Your shiftRows tries shifting rows between row 5 (index 4) and row 6 (index 5) one row down. But what about row 7, 8, 9 and 10? You needs shifting rows between row 5 and last row one row down if the need is getting a new empty row 5.
Using apache poi version 3.17 this is as simple as:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
class ExcelReadShiftRowsAndWrite {
public static void main(String[] args) throws Exception {
//String fileIn= "TestIn.xls";
//String fileOut= "TestOut.xls";
String fileIn= "TestIn.xlsx";
String fileOut= "TestOut.xlsx";
try (Workbook workbook = WorkbookFactory.create(new FileInputStream(fileIn));
FileOutputStream out = new FileOutputStream(fileOut)) {
Sheet sheet = workbook.getSheet("Sheet1");
sheet.shiftRows(4, sheet.getLastRowNum(), 1); //shifts rows between row 5 (index 4) and last row one row down
workbook.write(out);
}
}
}
But apache poi versions greater than 3.17, also 4.1.0, have a bug in shiftRows using XSSF. There, after shifting, the references in the cells remain old instead being adjusted to the new rows. For example the references A5, A6, ... remain after shifting down instead of getting adjusted to A6, A7, ...
So this bug must be corrected:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
class ExcelReadShiftRowsAndWrite {
public static void main(String[] args) throws Exception {
//String fileIn= "TestIn.xls";
//String fileOut= "TestOut.xls";
String fileIn= "TestIn.xlsx";
String fileOut= "TestOut.xlsx";
try (Workbook workbook = WorkbookFactory.create(new FileInputStream(fileIn));
FileOutputStream out = new FileOutputStream(fileOut)) {
Sheet sheet = workbook.getSheet("Sheet1");
sheet.shiftRows(4, sheet.getLastRowNum(), 1); //shifts rows between row 5 (index 4) and last row one row down
if (sheet instanceof XSSFSheet) {
XSSFSheet xSSFSheet = (XSSFSheet)sheet;
// correcting bug that shiftRows does not adjusting references of the cells
// if row 3 is shifted down, then reference in the cells remain r="A3", r="B3", ...
// they must be adjusted to the new row thoug: r="A4", r="B4", ...
// apache poi 3.17 has done this properly but had have other bugs in shiftRows.
for (int r = xSSFSheet.getFirstRowNum(); r < sheet.getLastRowNum() + 1; r++) {
XSSFRow row = xSSFSheet.getRow(r);
if (row != null) {
long rRef = row.getCTRow().getR();
for (Cell cell : row) {
String cRef = ((XSSFCell)cell).getCTCell().getR();
((XSSFCell)cell).getCTCell().setR(cRef.replaceAll("[0-9]", "") + rRef);
}
}
}
// end correcting bug
}
workbook.write(out);
}
}
}
I am reading some data from excel and writing it to another sheet in the same file in the form of column and I want the column to be printed in the row. When I am performing iteration createRow().setCellValue() is printing only last element.
package com.editDistance;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ReadColumnsEditDistance {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
File src = new File("C:\\Users\\xyz\\Desktop\\folder\\file.xlsx");
FileInputStream file = new FileInputStream(src);
Workbook workbook = new XSSFWorkbook(file);
Sheet sheet1 = workbook.getSheetAt(0);
int rows = sheet1.getPhysicalNumberOfRows();
workbook.createSheet();
Sheet sheet2 = workbook.getSheetAt(1);
for (int Readingrowindex = 1; Readingrowindex < rows; Readingrowindex++) {
String ah = sheet1.getRow(Readingrowindex).getCell(1).getStringCellValue();
sheet2.createRow(Readingrowindex).createCell(0).setCellValue(ah);
sheet2.createRow(0).createCell(Readingrowindex).setCellValue(ah);
}
FileOutputStream fout = new FileOutputStream(src);
workbook.write(fout);
}
}
Do you want to create sheet with the same cells in first column and first row, like a named table? If yes, you need modify your code, because you always rewrite first row, that's why you get only last item. Do this:
File src = new File("C:\\Users\\xyz\\Desktop\\folder\\file.xlsx");
FileInputStream file = new FileInputStream(src);
Workbook workbook = new XSSFWorkbook(file);
Sheet sheet1 = workbook.getSheetAt(0);
int rows = sheet1.getPhysicalNumberOfRows();
workbook.createSheet();
Sheet sheet2 = workbook.getSheetAt(1);
Row sheet2FirstRow = sheet2.createRow(0);
for (int Readingrowindex = 1; Readingrowindex < rows; Readingrowindex++) {
String ah = sheet1.getRow(Readingrowindex).getCell(1).getStringCellValue();
sheet2.createRow(Readingrowindex).createCell(0).setCellValue(ah);
Cell cell = sheet2FirstRow.createCell(Readingrowindex);
cell.setCellValue((String) ah);
}
FileOutputStream fout = new FileOutputStream(src);
workbook.write(fout);
I think it's because you keep creating row 0 over and over again so it's overwriting what you already created.
You probably want to do something like this:
if(sheet2.getRow() == null){
sheet2.createRow(0).createCell(Readingrowindex).setCellValue(ah);
}else{
sheet2.getRow(0).createCell(Readingrowindex).setCellValue(ah);
}
I faced the similar problem while writing to the code (it was printing the last row only).
Here is the solution for my code:
Failed solution (printing only last cell) i.e. "Hello3"
sheet.createRow(8).createCell(0).setCellValue("Hello1");
sheet.createRow(8).createCell(1).setCellValue("Hello2");
sheet.createRow(8).createCell(2).setCellValue("Hello3");
Working solution (Printing all the data) :
XSSFRow row;
row = sheet.createRow(8);
row.createCell(0).setCellValue("India 123");
row.createCell(1).setCellValue("India 234");
row.createCell(2).setCellValue("India 3453");
row = sheet.createRow(9);
row.createCell(0).setCellValue("Test 123");
row.createCell(1).setCellValue("Test 234");
row.createCell(2).setCellValue("Test 3453");
I'm having a lot of problems with numeric formats in a Cell with POI.
I need to print in the cell 11 decimals for a number and also that the cell has a numeric format to make the sum when you select the data
And I have this code:
private void writeDecimal(HSSFRow row, Double data, int position) {
String pattern = "#.0000000000";
HSSFCell celda = row.createCell(position);
CellStyle styleDecimal = styles.get(ITEM_DECIMAL); // Font and alignment
styleDecimal.setDataFormat(libro.getCreationHelper().createDataFormat().getFormat(pattern));
celda.setCellStyle(styleDecimal);
celda.setCellType(Cell.CELL_TYPE_NUMERIC);
celda.setCellValue(data);
}
But the result always print less decimal because Excel rounds the number:
If I convert the Double to String, prints the 11 decimals but it doesn't make the sum if I select all the numbers.
Any idea how to resolve this?
Thanks
Open the xlsx file select the column , right click on cell -> Format cells...->custom->type = 0.00000000000 click ok.
now whatever you will write on that cell, it will print on that format and if you select also it will show the sum.
by code
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
public class ChangeXlxsDataFormat {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
Workbook wb = new HSSFWorkbook();
Sheet sheet = (Sheet) wb.createSheet("format sheet");
CellStyle style;
DataFormat format = wb.createDataFormat();
Row row;
Cell cell;
short rowNum = 0;
short colNum = 0;
row = sheet.createRow(rowNum);
cell = row.createCell(colNum);
style = wb.createCellStyle();
row = sheet.createRow(rowNum++);
cell = row.createCell(colNum);
style = wb.createCellStyle();
style.setDataFormat(format.getFormat("0.00000000000"));
cell.setCellStyle(style);
cell.setCellValue(5.12345678908);
row = sheet.createRow(rowNum++);
cell = row.createCell(colNum);
cell.setCellValue(2.12345678908);
FileOutputStream fileOut = new FileOutputStream("test.xls");
wb.write(fileOut);
fileOut.close();
}
}
This code snippet doesn't contain celda.setCellStyle( styleDecimal ). Is it missing in the real code too? Add it.
Edit:
Here is a simple example using your function. It works well.
private static HSSFWorkbook workbook;
public static void main( String args[] ) throws IOException {
workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet( "sheet" );
HSSFRow row = sheet.createRow( 0 );
writeDecimal( row, 0.0781013, 0 );
FileOutputStream fos = new FileOutputStream( "workbook.xls", false );
workbook.write( fos );
fos.close();
}
private static void writeDecimal( HSSFRow row, Double data, int position ) {
String pattern = "#.0000000000";
HSSFCell celda = row.createCell(position);
CellStyle styleDecimal = workbook.createCellStyle(); // Font and alignment
styleDecimal.setDataFormat(workbook.createDataFormat().getFormat(pattern));
celda.setCellStyle(styleDecimal);
celda.setCellType(Cell.CELL_TYPE_NUMERIC);
celda.setCellValue(data);
}
What was the problem in your code? I don't know. Your style definitely wasn't applied to the page: zeros shouldn't be rendered with "#".
When working with values that are formulas, I am having difficulty getting the columns to autoresize properly.
I have "solved" this by making a hidden row that has maximum values as constant strings values, but that is far from elegant and often requires evaluating the formulas in each cell to get the largest strings that are generated. While this kind of works for such a small spreadsheet, it becomes very impractical for sheets that are ~16 columns x ~6000 rows.
The following code renders as in OpenOffice.
package com.shagie.poipoc;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import java.io.FileOutputStream;
public class SimpleBug {
public static void main(String[] args) {
try {
Workbook wb = new HSSFWorkbook();
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
Sheet sheet = wb.createSheet("new sheet");
Row row = sheet.createRow(0);
CellStyle style = wb.createCellStyle();
style.setDataFormat(wb.createDataFormat().getFormat("[h]:mm"));
Cell cell = row.createCell(0);
cell.setCellValue(123.12);
cell.setCellStyle(style);
row.createCell(1).setCellFormula("A1");
row.createCell(2)
.setCellFormula("TRUNC(A1) & \"d \" & TRUNC(24 * MOD(A1,1))" +
" & \"h \" & TRUNC(MOD(60 * 24 * MOD(A1,1),60)) & \"m\"");
row.createCell(3).setCellValue("foo");
for(int i = 0; i < 4; i++) {
sheet.autoSizeColumn(i);
}
wb.write(fileOut);
fileOut.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Related and tried:
Apache POI autoSizeColumn Resizes Incorrectly I've tried the font in the style. I got a list of all the fonts Java was aware of with
GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment();
for(String font:e.getAvailableFontFamilyNames()) {
System.out.println(font);
}
I tried several of the fonts listed with that loop, and while OpenOffice changed the font, the columns where still sized incorrectly.
Assuming you're looking to have the correct size of the column based on the formula results, just insert the following line right before you do the autoSizeColumn, in this case before your for loop:
HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
The reason is autoSizeColumn sizes your cell based on the cached formula evaluated results and if the formula was never evaluated, it would not know what size to set for it.
Code:
...
row.createCell(3).setCellValue("foo");
HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
for (int i = 0; i < 4; i++) {
sheet.autoSizeColumn(i);
}
...
Output (in OpenOffice)