2017-07-31 6 views
0

J'ai une chaîne de polices X (comme la police Arial) ayant une hauteur Y dans la valeur de définition de la largeur de telle sorte que la chaîne peut être composée de plusieurs lignes. J'ai besoin de calculer la hauteur requise pour que la chaîne requise puisse s'y adapter. La taille automatique de la ligne dans POI Apache ne peut pas être possible car j'ai besoin de la hauteur pour la chaîne de texte riche (toute police et hauteur) présente dans la cellule de fusion de la ligne, dans ce scénario la taille automatique ne fonctionne pas.Comment obtenir la hauteur nécessaire d'un champ de texte enrichi sur plusieurs lignes (n'importe quelle police, n'importe quelle taille de police) ayant une largeur définie en utilisant Java?

+0

double possible de [taille automatique de la hauteur des lignes dans Apache POI] (https://stackoverflow.com/questions/19145628/auto-size-height-for-rows-in-apache-poi) –

+1

@ Tim S: Merci pour la réponse, je suis confronté au problème lorsque nous essayons de redimensionner la ligne de cellules de fusion ayant un texte riche de n'importe quelle police et n'importe quelle hauteur. Dans ce cas, la taille automatique ne fonctionne pas. – FREEVARUN

+0

Le calcul de la hauteur dans [DrawTextShape] (https://svn.apache.org/repos/asf/poi/trunk/src/java/org/apache/poi/sl/draw/DrawTextShape.java) est probablement un peu trop complexe, mais je suppose que cela pourrait être mappé à * textes enrichis SSF aussi ... – kiwiwings

Répondre

0

J'ai trouvé une solution en utilisant un JTextPane pour rendre le texte.

L'exemple de code est d'abord le texte entier dans une police et une taille de police. Mais depuis JTextPane fournit un StyledDocument, le contenu de texte riche devrait également être possible de gérer. (FAIRE).

Le code commente pourquoi des parties de code sont nécessaires.

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(); 
    } 

} 

} 

Le contenu JTextPane est presque exact que le contenu dans la cellule Excel. Donc, la hauteur sera la plupart du temps exacte.

enter image description here

Le résultat d'un test utilisant plusieurs polices et les tailles de police est pas si pauvre.

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(); 

} 

}