如何使用 Java 获得具有定义宽度的多行富文本字段(任何字体,任何字体大小)的所需高度? [英] How to get the needed height of a multi line rich-text field (any font, any font size) having defined width using Java?

查看:42
本文介绍了如何使用 Java 获得具有定义宽度的多行富文本字段(任何字体,任何字体大小)的所需高度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一串 X 字体(如 Arial 字体),其中 Y 高度定义了宽度值,这样字符串可以分成多行.我需要计算所需的高度,以便所需的字符串可以放入其中.无法在 Apache POI 中自动调整行大小,因为我需要行的合并单元格中存在的富文本字符串(任何字体和高度)的高度,在这种情况下自动调整大小不起作用.

I am having a string of X Font(like Arial font) having Y height in define value of the width in such a way that string can comes into multiple lines. I need to calculate the required height so that required string can be fit into it. Auto size of row in Apache POI can't be possible as I require height for the rich text string(any font and height) present in merge cell of the row, in this scenario auto size doesn't work.

推荐答案

找到了使用 JTextPane 呈现文本的解决方案.

Found a solution using a JTextPane to render the text.

示例代码首先是一种字体和字体大小的整个文本.但是由于JTextPane 提供了一个StyledDocument,所以应该也可以处理富文本内容.(待办事项).

Sample code is at first the whole text in one font and fontsize. But since JTextPane provides a StyledDocument, rich text content should also be possible to handle. (TODO).

代码注释为什么需要代码部分.

The code comments why code parts are needed.

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 CreateExcelCellWrapTextRenderedHeight {

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

  Font font = workbook.createFont();
  font.setFontName("Arial");
  font.setFontHeightInPoints((short)19);

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

  Sheet sheet = workbook.createSheet();

  sheet.setColumnWidth(3, 25*256);

  Row row = sheet.createRow(0);

  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\nGreetings from Axel so long";

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

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

//__________________________calculate text height by rendering the text

  //get the used font 
  Font usedfont = workbook.getFontAt(cell.getCellStyle().getFontIndex());

  //get the used font name
  String fontname = usedfont.getFontName();
System.out.println(fontname);
 
 //get the used font size
  short fontheight = usedfont.getFontHeightInPoints();
System.out.println(fontheight);

  //get the width of the colunms in pixels
  float colwidth = 0;
  for (int c = cellRangeAddress.getFirstColumn(); c <= cellRangeAddress.getLastColumn(); c++) {
   colwidth += sheet.getColumnWidthInPixels(c);
  }
System.out.println(colwidth);

  //get screen resolution
  int ppi = java.awt.Toolkit.getDefaultToolkit().getScreenResolution();
System.out.println(ppi);

  //create a font - correct the size to be appropriate to the screen resolution
  java.awt.Font awtFont = new java.awt.Font(fontname, java.awt.Font.PLAIN, Math.round(fontheight/(72f/ppi)));

  //create a JTextPane to render the text
  javax.swing.JTextPane textpane = new javax.swing.JTextPane();
 
  //set the font
  textpane.setFont(awtFont);

  //set dimension of the JTextPane to colwidth and maximum height
  java.awt.Dimension dimension = new java.awt.Dimension(Math.round(colwidth), Integer.MAX_VALUE);
  textpane.setSize(dimension);

  //Excels cells have different line spacing than default JTextPane
  javax.swing.text.MutableAttributeSet attributeset = new javax.swing.text.SimpleAttributeSet(textpane.getParagraphAttributes());
  javax.swing.text.StyleConstants.setLineSpacing(attributeset, 0.1f);

  javax.swing.text.StyledDocument document = textpane.getStyledDocument();
  document.setParagraphAttributes(0, document.getLength(), attributeset, true);

  //insert the text - TODO: handle rich text
  document.insertString(0, text, null);

  //resize dimension to preferred height
  dimension.setSize(Math.round(colwidth), textpane.getPreferredSize().getHeight());
  textpane.setPreferredSize(dimension);
 
  double textwidthpx = dimension.getWidth();
System.out.println(textwidthpx);
  double textheightpx = dimension.getHeight();
System.out.println(textheightpx);

  //textheightpx is in pixel, but we need points
  float textheight = (float)textheightpx * (72f/ppi);
System.out.println(textheight);

//__________________________
 
  row.setHeightInPoints(textheight);

  workbook.write(new FileOutputStream("CreateExcelCellWrapTextRenderedHeight.xlsx"));
  workbook.close();

  javax.swing.SwingUtilities.invokeLater(new Runnable() {
   public void run() {
    new TextPaneDemo(textpane).setVisible(true);
   }
  });

 }

 static class TextPaneDemo extends javax.swing.JFrame {

  TextPaneDemo(javax.swing.JTextPane textpane) {
   super("TextPaneDemo");
   this.setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE);
   this.getContentPane().add(textpane, java.awt.BorderLayout.CENTER);
   this.pack();
  }
          
 }

}

JTextPane 的内容几乎与 Excel 单元格中的内容完全相同.所以高度将大部分是准确的.

The JTextPane content is nearly exact as the content in the Excel cell. So the height will be mostly accurate.

使用多种字体和字体大小的测试结果也没有那么差.

The result of a test using multiple fonts and font sizes is also not so poor.

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 CreateExcelCellWrapTextRenderedHeightTest {

 static float getPreferredHeight(Cell cell, String text, CellRangeAddress cellrangeaddress) throws Exception {
  //get the used font 
  Font usedfont = cell.getSheet().getWorkbook().getFontAt(cell.getCellStyle().getFontIndex());

  //get the used font name
  String fontname = usedfont.getFontName();

  //get the used font size
  short fontheight = usedfont.getFontHeightInPoints();

  //get the width of the colunms in pixels
  float colwidth = 0;
  for (int c = cellrangeaddress.getFirstColumn(); c <= cellrangeaddress.getLastColumn(); c++) {
   colwidth += cell.getSheet().getColumnWidthInPixels(c);
  }

  //get screen resolution
  int ppi = java.awt.Toolkit.getDefaultToolkit().getScreenResolution();

  //create a font - correct the size to be appropriate to the screen resolution
  java.awt.Font awtFont = new java.awt.Font(fontname, java.awt.Font.PLAIN, Math.round(fontheight/(72f/ppi)));

  //create a JTextPane to render the text
  javax.swing.JTextPane textpane = new javax.swing.JTextPane();

  //set the font
  textpane.setFont(awtFont);

  //set dimension of the JTextPane to colwidth and maximum height
  java.awt.Dimension dimension = new java.awt.Dimension(Math.round(colwidth), Integer.MAX_VALUE);
  textpane.setSize(dimension);

  //Excels cells have different line spacing than default JTextPane
  javax.swing.text.MutableAttributeSet attributeset = new javax.swing.text.SimpleAttributeSet(textpane.getParagraphAttributes());
  javax.swing.text.StyleConstants.setLineSpacing(attributeset, 0.1f);

  javax.swing.text.StyledDocument document = textpane.getStyledDocument();
  document.setParagraphAttributes(0, document.getLength(), attributeset, true);

  //insert the text
  document.insertString(0, text, null);

  //resize dimension to preferred height
  dimension.setSize(Math.round(colwidth), textpane.getPreferredSize().getHeight());
  textpane.setPreferredSize(dimension);

  double textheightpx = dimension.getHeight();

  //textheightpx is in pixel, but we need points
  float textheight = (float)textheightpx * (72f/ppi);

  return textheight;
 }

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

  Sheet sheet = workbook.createSheet();
  sheet.setColumnWidth(3, 30*256);

  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\nGreetings from Axel so long";

  String[] fontnames = new String[]{"Arial", "Times New Roman", "Courier New", "Arial Black"};

  for (int r = 0; r < 16; r++) {

   Font font = workbook.createFont();
   font.setFontName(fontnames[(r % 4)]);

   font.setFontHeightInPoints((short)(r+6));

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

   Row row = sheet.createRow(r);

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

   CellRangeAddress cellrangeaddress = new CellRangeAddress(r, r, 2, 4);
   sheet.addMergedRegion(cellrangeaddress);

   float textheight = getPreferredHeight(cell, text, cellrangeaddress);
   row.setHeightInPoints(textheight);

  }
  
  FileOutputStream out = new FileOutputStream("CreateExcelCellWrapTextRenderedHeightTest.xlsx");
  workbook.write(out);
  out.close();
  workbook.close();

 }

}

这篇关于如何使用 Java 获得具有定义宽度的多行富文本字段(任何字体,任何字体大小)的所需高度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆