CTRun CTLine

如图所示,我们通过NSAttributedString创建一个CTFramesetter,这时候就会自动创建CTTypesetter,

它负责管理字体,下面通过一个或多个frame来渲染文字。然后根据ctframe的大小来创建ctline(每行对应一个ctline)

和ctrun(相同格式的一个或多个相邻字符叫做ctrun)。








@GetMapping public void testGet(HttpServletResponse response) { try (XWPFDocument document = new XWPFDocument()) { // 设置响应头,触发浏览器下载 response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); response.setHeader("Content-Disposition", "attachment; filename=Report.docx"); // 生成柱状图和饼图的字节数组 byte[] barChartBytes = generateBarChart(); byte[] pieChartBytes = generatePieChart(); // 添加标题 XWPFParagraph title = document.createParagraph(); title.setAlignment(org.apache.poi.xwpf.usermodel.ParagraphAlignment.CENTER); XWPFRun titleRun = title.createRun(); titleRun.setBold(true); titleRun.setFontSize(20); titleRun.setText("柱形图与饼图报告"); // 插入柱状图 insertImage(document, barChartBytes, "barChart"); // 插入饼图 insertImage(document, pieChartBytes, "pieChart"); // 写入到响应输出流 document.write(response.getOutputStream()); }catch (Exception e) { e.printStackTrace(); } } // 生成柱状图的字节流 private byte[] generateBarChart() throws IOException { DefaultCategoryDataset dataset = new DefaultCategoryDataset(); dataset.addValue(120, "Sales", "Q1"); dataset.addValue(240, "Sales", "Q2"); dataset.addValue(180, "Sales", "Q3"); dataset.addValue(90, "Sales", "Q4"); JFreeChart barChart = ChartFactory.createBarChart("季度销售统计", "季度", "销售额", dataset); barChart.setBackgroundPaint(Color.WHITE); ByteArrayOutputStream chartOutputStream = new ByteArrayOutputStream(); ChartUtils.writeChartAsPNG(chartOutputStream, barChart, 600, 400); return chartOutputStream.toByteArray(); } // 生成饼图的字节流 private byte[] generatePieChart() throws IOException { DefaultPieDataset dataset = new DefaultPieDataset(); dataset.setValue("Java", 40); dataset.setValue("Python", 30); dataset.setValue("C++", 20); dataset.setValue("Other", 10); JFreeChart pieChart = ChartFactory.createPieChart("编程语言使用比例", dataset, true, true, false); pieChart.setBackgroundPaint(Color.WHITE); ByteArrayOutputStream chartOutputStream = new ByteArrayOutputStream(); ChartUtils.writeChartAsPNG(chartOutputStream, pieChart, 600, 400); return chartOutputStream.toByteArray(); } // 插入图片到Word文档 private void insertImage(XWPFDocument document, byte[] imageBytes, String imgName) throws Exception { XWPFParagraph paragraph = document.createParagraph(); XWPFRun run = paragraph.createRun(); // 使用 ByteArrayInputStream 传入图片流 try (InputStream is = new ByteArrayInputStream(imageBytes)) { int format = XWPFDocument.PICTURE_TYPE_PNG; int width = Units.toEMU(500); // 图片宽度(EMU) int height = Units.toEMU(300); // 图片高度(EMU) // ✅ 正确调用方式 run.addPicture(is, format, imgName + ".png", width, height); } } title乱码了
10-15
你提到 `title` 出现了乱码,这通常是因为 **Word 文档默认编码不支持中文** 或 **未正确设置字体**,尤其是在使用某些版本的 Apache POI 时,对中文字体的支持不友好,默认使用英文字体导致中文显示异常。 --- ### ✅ 解决方法:设置中文字体 你需要在创建 `XWPFRun` 的时候,**显式指定中文字体**,例如 `宋体`、`微软雅黑` 等,以确保中文正常显示。 #### ✅ 修改后的标题添加代码如下: ```java // 添加标题 XWPFParagraph title = document.createParagraph(); title.setAlignment(org.apache.poi.xwpf.usermodel.ParagraphAlignment.CENTER); XWPFRun titleRun = title.createRun(); titleRun.setBold(true); titleRun.setFontSize(20); titleRun.setFontFamily("宋体"); // 设置中文字体 titleRun.setText("柱形图与饼图报告"); ``` --- ### ✅ 如果仍乱码?尝试设置 ANSI 和 EastAsia 字体(更彻底) Apache POI 的 `XWPFRun` 还支持通过底层 XML 设置中英文双字体: ```java XWPFRun titleRun = title.createRun(); titleRun.setBold(true); titleRun.setFontSize(20); CTRun ctRun = titleRun.getCTR(); CTFonts fonts = ctRun.isSetRPr() ? ctRun.getRPr().getRFonts() : ctRun.getRPr().addNewRFonts(); fonts.setAscii("Times New Roman"); fonts.setEastAsia("宋体"); // 设置中文字体 fonts.setHAnsi("Times New Roman"); titleRun.setText("柱形图与饼图报告"); ``` --- ### ✅ 总结:乱码原因与解决方案 | 原因 | 解决方案 | |------|----------| | 默认字体不支持中文 | 使用 `setFontFamily("宋体")` | | Word 文档打开时未识别中文字体 | 显式设置 `CTFonts` 的 `eastAsia` 字体 | | Apache POI 版本问题 | 升级到 5.2.x 系列,增强对中文字体支持 | --- ### ✅ 补充说明:字体选择建议 - 推荐字体:`宋体`、`微软雅黑`、`黑体`、`楷体` - 避免使用特殊字体,如 `华文彩云`,可能在部分系统上不兼容 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值