poi3.9 导出 pptx时 通过setFontFamily设置了西文字体,但是没有设置中文字体,我应该怎样设置中文字体呢

王晨宇
  • 14

代码是:
1、pom.xml

 <!-- PPTUtil -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.9</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.9</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
<!-- PPTUtil -->

代码如下:

package com.pptx;

import org.apache.poi.xslf.usermodel.*;

import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

public class TestController {

    public static void main(String[] args) throws IOException {
        //1、创建空的演示文稿
        //要创建空的演示文稿,您必须实例化 org.poi.xslf.usermodel 包的 XMLSlideShow 类:
        XMLSlideShow ppt = new XMLSlideShow();

        //2、设置画布大小
        ppt.setPageSize(new java.awt.Dimension(1920, 1080));

        //3.准备创建幻灯片
        XSLFSlide slide = ppt.createSlide();

        //4.读取该幻灯片中所有元素
        /*创建容器*/
        XSLFTextBox textBox = slide.createTextBox();
        //创建大小
        String x2 = "2.96";  //水平位置
        String y2 = "13.91"; //垂直位置
        String w2 = "10.56"; //宽度
        String h2 = "10.50";  //高度
        textBox.setAnchor(new Rectangle2D.Double(Double.valueOf(x2) / 3.53 * 100, Double.valueOf(y2) / 3.53 * 100, Double.valueOf(w2) / 3.53 * 100, Double.valueOf(h2) / 3.53 * 100));

        //5.创建 XSLFTextParagraph 类 生成一个新的文本段落
        XSLFTextParagraph textParagraph = textBox.addNewTextParagraph();

        //此方法用于设置要设置为段落的对齐方式
        textParagraph.setTextAlign(TextAlign.LEFT);

        /*创建 XSLFTextParagraph.XSLFTextRun 类 添加新的文本运行 */
        XSLFTextRun xslfTextRun = textParagraph.addNewTextRun();


        //写入内容 添加新的文本
        xslfTextRun.setText("我是中文字体");

        //宋体 (正文) 设置字体类型
        String fontName = "zh8hzznct";
        xslfTextRun.setFontFamily(fontName);
        xslfTextRun.setFontSize(40);


        //6.保存文件
        String filename = UUID.randomUUID() + ".pptx";
        String filePath = "D:" + File.separator + filename;

        //使用了File对象打开文件然后读取
        File file = new File(filePath);
        FileOutputStream out = new FileOutputStream(file);

        //保存文件
        ppt.write(out);
        out.close();

    }

}

在office打开(显示字体效果

在wps打开(不显示字体效果)

字体是:
链接:https://pan.baidu.com/s/1a_mk...
提取码:iugs
复制这段内容后打开百度网盘手机App,操作更方便哦

我通过查询百度,发现:
https://blog.csdn.net/weixin_...
有提示:
1、设置ASCII码
2、设置中文字体
但是我在poi官方网站
http://poi.apache.org/apidocs/
查看文档没有找到pptx的相关接口,可以更换poi版本,希望指导一下我解决办法。

回复
阅读 839
1 个回答
✓ 已被采纳

没想到你还会来邀请我继续回答poi的问题,虽然不知道我的方法是否一定正确,但是最后效果倒是出来了,思路大致如下

肯定现在是西文字体修改了,中午字体没有修改,为了方便去对比,我选择反推,于是我是通过poi再读取那个修改的ppt文件(方便区别这个文件叫ppt1.pptx),查看一下现在读出来的getFontFamily()是什么?(因为ppt打开显示字体有中文,西文字体,那读出来的会是哪个呢?)
image.png

读出来还是zh8hzznct,那好,接着我再把ppt中那个中文字体改为zh8hzznct,西文字体改为微软雅黑,另存为文件ppt2.pptx
image.png

再读取查看FontFamily是什么,结果就是微软雅黑
image.png

那说明这个无论怎么改,最终FontFamily无论设置还是读取都会与西文字体相关。所以再从xslfTextRun.setFontFamily就走不通了

索性抛开这条路,因为我们知道poi操作文档,实际是在玩xml,所以想着虽然ppt2.pptxFontFamily读出来是微软雅黑,但是我中文字体是zh8hzznct,那在xml中肯定会体现出来的嘛

于是我再把两个ppt文件读取出来的XSLFSlide直接调用getXmlObject(),把生成的xml打印出来一做对比,这个结果就非常明显了哈
image.png

可以看到

  1. ppt2.pptx中文字体是zh8hzznct,西文字体是微软雅黑,跟我们想要达到的效果很接近了,但是只是我们是通过界面修改。而最终xml效果为latin标签为微软雅黑ea标签为zh8hzznct
  2. 而我们代码修改的ppt1.pptx只设置了FontFamily,最终效果是只有西文字体是zh8hzznct,对应xml只有latin标签zh8hzznct

那我们可以得出一个结论,如果说我们在代码修改ppt时,除了设置FontFamily(这个时候应该会有个latin标签zh8hzznct),再增加一个ea标签为zh8hzznct,这样就可以完成西文中文字体都为zh8hzznct

那怎么修改呢?当然是继续玩xml了啊,所以xslfTextRun直接调用getXmlObject(),开始以为玩xml有点难,结果仔细一对比方法名和xml,也不算难,马上就有了下面的写法

CTRegularTextRun xmlObject = xslfTextRun.getXmlObject();
CTTextCharacterProperties rPr = xmlObject.getRPr();
CTTextFont ctTextFont = rPr.addNewEa();
ctTextFont.setTypeface(fontName);

什么getRPr中的RPr,什么addNewEa中的Ea,结合刚才的xml内容,其实就是个标签名,而这里面的font显然是Typeface属性咯,这样就简单多了
image.png

加了刚上面那行代码,再修改ppt就对味了
image.png
虽然西文字体显示使用中文字体,但是再去读取一次xml就一目了然啦
image.png

大概能解决你的问题吧,如果其他老哥有更合适的api你可以无视我这种,毕竟有点剑走偏锋的感觉,哈哈哈

你知道吗?

宣传栏