1

I am creating an big excel using java class. Excel contains a merged cell which store string. Length of the string is very large, i am getting this string dynamically. I need to increase the height of the merged cell so that complete string will fit to that cell. I have tried using "wrap text", it wrap the text but doesn't increase the height of the merged cell due to which complete string is not visible in excel. Java class i am using are:

  1. XSSFWorkbook
  2. XSSFSheet
  3. XSSFRow
  4. XSSFCell
  5. XSSFCellStype

And other required dependent classes. Is there a way how i can increase the height of the merge cell as per the cell value.

Igor Drozdov
  • 14,690
  • 5
  • 37
  • 53
FREEVARUN
  • 13
  • 1
  • 7
  • Calculate the needed height and then use one of the `setHeight` methods of `XSSFRow`. How to calculate the needed height? Well this is the challenge. `Excel` (`Microsoft`) itself has not solved this since there is not a possibility in `Excel` to set "optimal height" for merged cells. – Axel Richter Jul 29 '17 at 08:50

1 Answers1

6

To give you an idea of the challenge how to calculate the needed row height.

We can get the column width in character widths for the columns using Sheet.getColumnWidth(int). But this is not really accurate since it only is for number glyphs: 1,2,3,4,5,6,7,8,9,0. In true type fonts there are glyphs (., |, l, ...) which need much less width. So this result will be as much more inaccurate as such less-width-glyphs are used in the text.

We might correct the column-width-in-chars by a factor. I use 5/4. But this is highly dependent on the language used.

Then we can calculate the needed row count and then get the needed row height by getting the default row height used for one line and multiply that with the needed row count .

import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;

public class CreateExcelCellWrapText {

 public static void main(String[] args) throws Exception {
  XSSFWorkbook workbook = new XSSFWorkbook();

  CellStyle cellstyle = workbook.createCellStyle();
  cellstyle.setWrapText(true);

  Sheet sheet = workbook.createSheet();

//__________________________not merged = height is auto sized

  Row row = sheet.createRow(0);

  Cell cell = row.createCell(2);
  cell.setCellValue("String cell content\nhaving line wrap.");
  cell.setCellStyle(cellstyle);

//__________________________merged = height is not auto sized

  row = sheet.createRow(2);

  cell = row.createCell(2);
  cell.setCellValue("String cell content\nhaving line wrap.");
  cell.setCellStyle(cellstyle);

  CellRangeAddress cellRangeAddress = new CellRangeAddress(2, 2, 2, 3);
  sheet.addMergedRegion(cellRangeAddress);

//__________________________merged with calculated height

  row = sheet.createRow(4);

  String text = "String cell content\nhaving line wrap.\nIt has new line marks and then a long text without new line marks.\nFollowed by short text part.\n\n\nGreetings";

  cell = row.createCell(2);
  cell.setCellValue(text);
  cell.setCellStyle(cellstyle);

  cellRangeAddress = new CellRangeAddress(4, 4, 2, 3);
  sheet.addMergedRegion(cellRangeAddress);

  //get the column width in character widths for the merged columns
  //this is not really accurate since it only is for number glyphs: 1,2,3,4,5,6,7,8,9,0
  //in true type fonts there are glyps (., |, l, ...) which need much less width
  int colwidthinchars = (sheet.getColumnWidth(2) + sheet.getColumnWidth(3)) / 256;
System.out.println(colwidthinchars);
  //correct the colwidthinchars by a factor 5/4 (highly dependent on the language used)
  colwidthinchars = Math.round(colwidthinchars * 5f/4f);
System.out.println(colwidthinchars);

  //calculate the needed rows dependent on the text and the column width in character widths
  String[] chars = text.split("");
  int neededrows = 1;
  int counter = 0;
  for (int i = 0; i < chars.length; i++) {
   counter++;
   if (counter == colwidthinchars) {
System.out.println("new line because of charcter count");
    neededrows++;
    counter = 0;
   } else if ("\n".equals(chars[i])) {
System.out.println("new line because of new line mark");
    neededrows++;
    counter = 0;
   }
  }

System.out.println(neededrows);

  //get default row height
  float defaultrowheight = sheet.getDefaultRowHeightInPoints();
System.out.println(defaultrowheight);

  row.setHeightInPoints(neededrows * defaultrowheight);

  workbook.write(new FileOutputStream("CreateExcelCellWrapText.xlsx"));
  workbook.close();
 }
}

This works because default font and font size is used. The challenge increases up to infinity when different fonts and different font sizes are used ;-).

See How to get the needed height of a multi line rich-text field (any font, any font size) having defined width using Java? for an example rendering the formatted text in a JTextPane to get the preferred height.

Axel Richter
  • 56,077
  • 6
  • 60
  • 87
  • **Not working when we change the font or height from default** This code is only working with default cell properties, when i do little change in the cell like font or height again i am getting the same issue, i can't keep the cell properties as default all the time. – FREEVARUN Jul 30 '17 at 11:58
  • The only way to solve this accurate would be rendering the formatted text in some text box in an graphics environment. But there are not really good working examples for this using Java. [XSLFTextShape.resizeToFitText](https://poi.apache.org/apidocs/org/apache/poi/xslf/usermodel/XSLFTextShape.html#resizeToFitText%28%29) is doing this for example. But it's results also are not very satisfying using fonts and font sizes outside the defaults. So your question could be "How to get the needed height of a multiline rich-text field (any font, any font size) having defined width using Java?" – Axel Richter Jul 31 '17 at 05:29
  • You code snippet solve my 60% of problem. I have tried Graphic classes present in awt also but didn't get any good working example. I will try XSLFTextShape.resizeToFitText and see if it resolve the issue. When i get this issue resolved will update it here with example. Thanks for the help :) – FREEVARUN Jul 31 '17 at 08:26
  • @FREEVARUN: I've tried `XSLFTextShape.resizeToFitText` not with satisfying results as commented above. But try it yourself. If I have time, I will ask "How to get the needed height of a multi line rich-text field (any font, any font size) having defined width using Java?" here as an own question. But you could also do so. [There is a similiar question already.](https://stackoverflow.com/questions/1048224/get-height-of-multi-line-text-with-fixed-width-to-make-dialog-resize-properly) But this is about rendering `HTML`. – Axel Richter Jul 31 '17 at 08:39