基于我的 DocX 版本,这里是 Hssf 的改编版本。与其他版本一样,您必须为各种 css 样式调试和扩展循环。
更新:我昨天忽略了你想要一个流式 XSSF 解决方案,所以我摆弄了一下,如果可以只使用 usermodel 类(不是真的,当涉及到字体颜色),而且我想知道为什么 SXSSF 没有在我发现之前不要使用我的任何字体设置,这是目前的设计(参见错误52484)
import java.awt.Color;
import java.io.FileOutputStream;
import java.lang.reflect.Field;
import java.util.Enumeration;
import javax.swing.text.*;
import javax.swing.text.html.*;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
public class StyledTextXls {
public static void main(String[] args) throws Exception {
HTMLEditorKit kit = new HTMLEditorKit();
HTMLDocument doc = (HTMLDocument)kit.createDefaultDocument();
kit.insertHTML(doc, doc.getLength(), "<p>paragraph <b>1</b></p>", 0, 0, null);
kit.insertHTML(doc, doc.getLength(), "<p>paragraph <span style=\"color:red\">2</span></p>", 0, 0, null);
Workbook wb = new XSSFWorkbook();
// Workbook wb = new HSSFWorkbook();
// Workbook wb = new SXSSFWorkbook(100); // doesn't work yet - see Bug 52484
Sheet sheet = wb.createSheet();
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
StringBuffer sb = new StringBuffer();
for (int lines=0, lastPos=-1; lastPos < doc.getLength(); lines++) {
if (lines > 0) sb.append("\n");
Element line = doc.getParagraphElement(lastPos+1);
lastPos = line.getEndOffset();
for (int elIdx=0; elIdx < line.getElementCount(); elIdx++) {
final Element frag = line.getElement(elIdx);
String subtext = doc.getText(frag.getStartOffset(), frag.getEndOffset()-frag.getStartOffset());
sb.append(subtext);
}
}
CreationHelper ch = wb.getCreationHelper();
RichTextString rt = ch.createRichTextString(sb.toString());
for (int lines=0, lastPos=-1; lastPos < doc.getLength(); lines++) {
Element line = doc.getParagraphElement(lastPos+1);
lastPos = line.getEndOffset();
for (int elIdx=0; elIdx < line.getElementCount(); elIdx++) {
final Element frag = line.getElement(elIdx);
Font font = getFontFromFragment(wb, frag);
rt.applyFont(frag.getStartOffset()+lines, frag.getEndOffset()+lines, font);
}
}
cell.setCellValue(rt);
cell.getCellStyle().setWrapText(true);
row.setHeightInPoints((6*sheet.getDefaultRowHeightInPoints()));
sheet.autoSizeColumn((short)0);
FileOutputStream fos = new FileOutputStream("richtext"+(wb instanceof HSSFWorkbook ? ".xls" : ".xlsx"));
wb.write(fos);
fos.close();
}
static Font getFontFromFragment(Workbook wb, Element frag) {
// creating a font on each is call is not very efficient
// but should be ok for this exercise ...
Font font = wb.createFont();
final AttributeSet as = frag.getAttributes();
final Enumeration<?> ae = as.getAttributeNames();
while (ae.hasMoreElements()) {
final Object attrib = ae.nextElement();
try {
if (CSS.Attribute.COLOR.equals(attrib)) {
// I don't know how to really work with the CSS-swing class ...
Field f = as.getAttribute(attrib).getClass().getDeclaredField("c");
f.setAccessible(true);
Color c = (Color)f.get(as.getAttribute(attrib));
if (font instanceof XSSFFont) {
((XSSFFont)font).setColor(new XSSFColor(c));
} else if (font instanceof HSSFFont && wb instanceof HSSFWorkbook) {
HSSFPalette pal = ((HSSFWorkbook)wb).getCustomPalette();
HSSFColor col = pal.findSimilarColor(c.getRed(), c.getGreen(), c.getBlue());
((HSSFFont)font).setColor(col.getIndex());
}
} else if (CSS.Attribute.FONT_WEIGHT.equals(attrib)) {
if ("bold".equals(as.getAttribute(attrib).toString())) {
font.setBoldweight(Font.BOLDWEIGHT_BOLD);
}
}
} catch (Exception e) {
System.out.println(attrib.getClass().getCanonicalName()+" can't be handled.");
}
}
return font;
}
}