用Apache POI把文字信息輸出到Excel的時候续室,遇到如圖的情況摇零。HTML中這些上標下標是用‘<sup></sup>历帚,<sub></sub>’包起來的
那么要導出到excel锋恬,如何讓excel里面也顯示如圖的樣子屯换,而不是直接顯示那些標簽呢?
話不多說与学,先導包:
<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);
//創(chuàng)建單元格(第一行第一格)
HSSFCell cell = row.createCell(0);
//生成富文本文字
HSSFRichTextString text = new HSSFRichTextString(content);
//生成字體
HSSFFont ft = workbook.createFont();
//設(shè)置下標字體趟径,sup的話此處設(shè)置HSSFFont.SS_SUPER
ft.setTypeOffset(HSSFFont.SS_SUB);
//設(shè)置字體生效的位置區(qū)間,content字符串去掉sub標簽之后癣防,第四個字符需要處理成下標,所以參數(shù)是3掌眠,4
//如果是content="aaa<sub>23</sub>ccc",位置參數(shù)就是3蕾盯,5,不同位置可多次調(diào)用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>離子協(xié)同摻雜電解質(zhì),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盔沫,第二個元素是結(jié)束標簽的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標簽的開始和對應的結(jié)束的標簽的index干茉,方便后面根據(jù)這個標簽做字體操作
* @param s
* @param tagIndexList 傳一個新建的空list進來谴忧,方法結(jié)束的時候會存儲好標簽位置信息。
* <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) {
//兩種標簽都存在的時候要考慮到誰在前沾谓,在前的標簽優(yōu)先處理
//因為如果在后的標簽處理完,index就定下來戳鹅,再處理在前的均驶,后面的index就會產(chǎn)生偏移量。從前開始處理不會存在這個問題
if(sub_pair[0] < sup_pair[0]) {
supFirst = false;
} else {
subFirst = false;
}
}
if (sub_pair != null && subFirst) {
s = removeNextSubTags(s, SUB_START);
//<sub>標簽被去掉之后粉楚,結(jié)束標簽需要相應往前移動
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>標簽被去掉之后辣恋,結(jié)束標簽需要相應往前移動
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!DH怼伟骨!