如何使用Java获得具有已定义宽度的多行富文本字段(任何字体,任何字体大小)所需的高度?

我有一个X字符串(如Arial字体),Y高度定义宽度值,使字符串可以进入多行。 我需要计算所需的高度,以便所需的字符串适合它。 Apache POI中行的自动大小是不可能的,因为我需要行的合并单元格中存在的富文本字符串(任何字体和高度)的高度,在这种情况下,自动大小不起作用。

使用JTextPane找到解决方案来呈现文本。

示例代码首先是一个字体和fontsize的整个文本。 但由于JTextPane提供了StyledDocument ,因此还应该可以处理富文本内容。 (去做)。

代码注释了为什么需要代码部分。

 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单元格中的内容完全相同。 所以高度大部分都是准确的。

在此处输入图像描述

使用多种字体和字体大小的测试结果也不是那么差。

 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); } workbook.write(new FileOutputStream("CreateExcelCellWrapTextRenderedHeightTest.xlsx")); workbook.close(); } }