美文网首页我爱编程
POI Excel 上下标处理(sub,sup的HTML标签转化

POI Excel 上下标处理(sub,sup的HTML标签转化

作者: NormanCao | 来源:发表于2018-05-25 15:56 被阅读0次

    用Apache POI把文字信息输出到Excel的时候,遇到如图的情况。HTML中这些上标下标是用‘<sup></sup>,<sub></sub>’包起来的

    那么要导出到excel,如何让excel里面也显示如图的样子,而不是直接显示那些标签呢?

    sup sub

    话不多说,先导包:

            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>3.16</version>
            </dependency>
    

    核心的代码就是:

    String content="aaa<sub>2</sub>ccc"
    //生成workbook
    HSSFWorkbook workbook = new HSSFWorkbook();
    //生成sheet
    HSSFSheet sheet = workbook.createSheet("sheet1");
    //生成行row(第一行)
    HSSFRow row = sheet.createRow(0);
    //创建单元格(第一行第一格)
    HSSFCell cell = row.createCell(0);
    //生成富文本文字
    HSSFRichTextString text = new HSSFRichTextString(content);
    //生成字体
    HSSFFont  ft = workbook.createFont();
    //设置下标字体,sup的话此处设置HSSFFont.SS_SUPER
    ft.setTypeOffset(HSSFFont.SS_SUB);
    //设置字体生效的位置区间,content字符串去掉sub标签之后,第四个字符需要处理成下标,所以参数是3,4
    //如果是content="aaa<sub>23</sub>ccc",位置参数就是3,5,不同位置可多次调用applyFont方法
    text.applyFont(3,4,ft);
    cell.setCellValue(text);
    //TODO 输出文件
    ......
    

    了解核心代码之后,需要做的就是解析字符串中的标签,然后按照这个方法处理。以下是我写的比较完整的解析例子。

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.apache.poi.hssf.usermodel.HSSFCell;
    import org.apache.poi.hssf.usermodel.HSSFFont;
    import org.apache.poi.hssf.usermodel.HSSFRichTextString;
    import org.apache.poi.hssf.usermodel.HSSFRow;
    import org.apache.poi.hssf.usermodel.HSSFSheet;
    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    
    public class ExcelUtils2 {
        private static final String SUB_START = "<sub>";
        private static final String SUB_END = "</sub>";
        private static final String SUP_START = "<sup>";
        private static final String SUP_END = "</sup>";
    
        public static void main(String[] args) {
            String title = "一种F<sup>-</sup>、Zn<sup>2+</sup>、B<sup>3+</sup>离子协同掺杂电解质,H<sub>2</sub>O是水";
    
            List<List<int[]>> tagIndexArr = null;
            if (containSubSup(title)) {
                tagIndexArr = new ArrayList<List<int[]>>();
                title = getSubSupIndexs(title, tagIndexArr);
            }
            //TODO 文件路径自己改
            File f = new File("C:\\tmp\\test.xls");
            try {
                FileOutputStream fout = new FileOutputStream(f);
                // 声明一个工作薄
                @SuppressWarnings("resource")
                HSSFWorkbook workbook = new HSSFWorkbook();
                // 生成一个表格
                HSSFSheet sheet = workbook.createSheet("sheet1");
                int curRowIndex = 0;
                HSSFRow row = sheet.createRow(curRowIndex);
                HSSFCell cell = row.createCell(0);
    
                if (tagIndexArr != null) {
                    HSSFRichTextString text = new HSSFRichTextString(title);
                    List<int[]> subs = tagIndexArr.get(0);
                    List<int[]> sups = tagIndexArr.get(1);
                    if (subs.size() > 0) {
                        HSSFFont ft = workbook.createFont();
                        ft.setTypeOffset(HSSFFont.SS_SUB);
                        for (int[] pair : subs) {
                            text.applyFont(pair[0], pair[1], ft);
                        }
                    }
                    if (sups.size() > 0) {
                        HSSFFont ft = workbook.createFont();
                        ft.setTypeOffset(HSSFFont.SS_SUPER);
                        for (int[] pair : sups) {
                            text.applyFont(pair[0], pair[1], ft);
                        }
                    }
                    cell.setCellValue(text);
                } else {
                    cell.setCellValue(title);
                }
    
                try {
                    workbook.write(fout);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        /**
         * 获取下一对标签的index,不存在这些标签就返回null
         * @param s
         * @param tag SUB_START 或者SUP_START
         * @return int[]中有两个元素,第一个是开始标签的index,第二个元素是结束标签的index
         */
        private static int[] getNextSubsTagsIndex(String s, String tag) {
    
            int firstSubStart = s.indexOf(tag);
            if (firstSubStart > -1) {
                int firstSubEnd = s.indexOf(tag.equals(SUB_START) ? SUB_END : SUP_END);
                if (firstSubEnd > firstSubStart) {
                    return new int[] { firstSubStart, firstSubEnd };
                }
            }
            return null;
        }
    
        /**移除下一对sub或者sup标签,返回移除后的字符串
         * @param s
         * @param tag SUB_START 或者SUP_START
         * @return
         */
        private static String removeNextSubTags(String s, String tag) {
            s = s.replaceFirst(tag, "");
            s = s.replaceFirst(tag.equals(SUB_START) ? SUB_END : SUP_END, "");
            return s;
        }
    
        /**
         * 判断是不是包含sub,sup标签
         * @param s
         * @return
         */
        private static boolean containSubSup(String s) {
            return (s.contains(SUB_START) && s.contains(SUB_END)) || (s.contains(SUP_START) && s.contains(SUP_END));
        }
    
        /**
         * 处理字符串,得到每个sub,sup标签的开始和对应的结束的标签的index,方便后面根据这个标签做字体操作
         * @param s
         * @param tagIndexList 传一个新建的空list进来,方法结束的时候会存储好标签位置信息。
         * <br>tagIndexList.get(0)存放的sub
         * <br>tagIndexList.get(1)存放的是sup
         * 
         * @return 返回sub,sup处理完之后的字符串
         */
        private static String getSubSupIndexs(String s, List<List<int[]>> tagIndexList) {
            List<int[]> subs = new ArrayList<int[]>();
            List<int[]> sups = new ArrayList<int[]>();
    
            while (true) {
                int[] sub_pair = getNextSubsTagsIndex(s, SUB_START);
                int[] sup_pair = getNextSubsTagsIndex(s, SUP_START);
                boolean subFirst = true;
                boolean supFirst = true;
                if(sub_pair != null && sup_pair != null) {
                    //两种标签都存在的时候要考虑到谁在前,在前的标签优先处理
                    //因为如果在后的标签处理完,index就定下来,再处理在前的,后面的index就会产生偏移量。从前开始处理不会存在这个问题
                    if(sub_pair[0] < sup_pair[0]) {
                        supFirst = false;
                    } else {
                        subFirst = false;
                    }
                }
                if (sub_pair != null && subFirst) {
                    s = removeNextSubTags(s, SUB_START);
                    //<sub>标签被去掉之后,结束标签需要相应往前移动
                    sub_pair[1] = sub_pair[1] - SUB_START.length();
                    subs.add(sub_pair);
                    continue;
                }
                if (sup_pair != null && supFirst) {
                    s = removeNextSubTags(s, SUP_START);
                    //<sup>标签被去掉之后,结束标签需要相应往前移动
                    sup_pair[1] = sup_pair[1] - SUP_START.length();
                    sups.add(sup_pair);
                    continue;
                }
                if (sub_pair == null && sup_pair == null) {
                    break;
                }
            }
    
            tagIndexList.add(subs);
            tagIndexList.add(sups);
            return s;
        }
    
    }
    

    OJBK!!!

    相关文章

      网友评论

        本文标题:POI Excel 上下标处理(sub,sup的HTML标签转化

        本文链接:https://www.haomeiwen.com/subject/gsqujftx.html