POI Excel 上下标处理(sub,sup的HTML标签转化到excel格式)

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

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

sup
sub

话不多说,先导包:

        
            org.apache.poi
            poi-ooxml
            3.16
        

核心的代码就是:

String content="aaa2ccc"
//生成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="aaa23ccc",位置参数就是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 = "";
    private static final String SUB_END = "";
    private static final String SUP_START = "";
    private static final String SUP_END = "";

    public static void main(String[] args) {
        String title = "一种F-、Zn2+、B3+离子协同掺杂电解质,H2O是水";

        List> tagIndexArr = null;
        if (containSubSup(title)) {
            tagIndexArr = new ArrayList>();
            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 subs = tagIndexArr.get(0);
                List 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进来,方法结束的时候会存储好标签位置信息。
     * 
tagIndexList.get(0)存放的sub *
tagIndexList.get(1)存放的是sup * * @return 返回sub,sup处理完之后的字符串 */ private static String getSubSupIndexs(String s, List> tagIndexList) { List subs = new ArrayList(); List sups = new ArrayList(); 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_pair[1] = sub_pair[1] - SUB_START.length(); subs.add(sub_pair); continue; } if (sup_pair != null && supFirst) { s = removeNextSubTags(s, SUP_START); //标签被去掉之后,结束标签需要相应往前移动 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标签转化到excel格式))