JAVA實現(xiàn)Excel和PDF上下標(biāo)的操作代碼
1、簡介
最近項目需要實現(xiàn)26個小寫字母的上下標(biāo)功能,自己去網(wǎng)上找了所有Unicode的上下標(biāo)形式,缺少一些關(guān)鍵字母,顧后面考慮自己創(chuàng)建上下標(biāo)字體樣式,以此來記錄。
2、Excel
Excel本身是支持上下標(biāo),我們可以通過Excel單元格的樣式來設(shè)置當(dāng)前字體上下標(biāo),因使用的是POI的maven包,這邊就以POI的樣例實現(xiàn)。
首先pom.xml引用:
<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>
實現(xiàn)上下標(biāo)代碼:
XSSFWorkbook workbook = new XSSFWorkbook(); XSSFSheet sheet = workbook.createSheet("Sheet1"); XSSFRow row = sheet.createRow(0); XSSFCell cell = row.createCell(0); XSSFFont font = workbook.createFont(); font.setTypeOffset(XSSFFont.SS_SUB); // 上標(biāo) font.setTypeOffset(XSSFFont.SS_SUPER);//下標(biāo) XSSFRichTextString richTextString = new XSSFRichTextString("Hcu"); richTextString.applyFont(1, 2, font); // 設(shè)置第二個字符為上標(biāo) "c" richTextString.applyFont(2, 3, font); // 設(shè)置第三個字符為下標(biāo) "u" cell.setCellValue(richTextString); Path tempFile = Paths.get("E:\\dist\\pdf0.xlsx"); try(OutputStream os = Files.newOutputStream(tempFile)){ workbook.write(os); logger.error("xssfWorkbook-end:" + tempFile.toAbsolutePath()); }
3、造字
因某些字母沒有對應(yīng)的上下標(biāo)字形,所以通過FontCreate軟件來造上下標(biāo),至于軟件可以去網(wǎng)上下載破解版,還有就是Unicode指定的數(shù)量就那么多,所以我們可以通過改變已有Unicode編碼字符來作為我們上下標(biāo)的編碼。
可以通過找到當(dāng)前分支少的Unicode字符做插入:比如選中西里爾字母這個分類點擊 插入->字符:
然后我們對已有的字符做修改和做刪除自己造:
最后形成我們自己所需要的字符:
4、PDF
生成的PDF,采用開源的是開放源碼的站點sourceforge一個項目itextpdf,是用于生成PDF文檔的一個java類庫。通過iText不僅可以生成PDF或rtf的文檔,而且可以將XML、Html文件轉(zhuǎn)化為PDF文件。因項目通過Excel來轉(zhuǎn)PDF,但是因itextpdf無法識別Excel上下標(biāo),并且缺少了關(guān)鍵上下標(biāo)。
首先pom.xml引用:
<dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.10</version> </dependency>
輸出中文,還要引入下面itext-asian.jar包:
<dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> </dependency>
通過以上造好的字母上下標(biāo),直接通過加載指定的Unicode來實現(xiàn)實現(xiàn)加載:
String value = "設(shè)計強度?\u0460\u0461"; File pdfFile = new File("E:\\dist\\pdf1.pdf"); //字符和Unicode組合格式化 value = StringEscapeUtils.unescapeJava(value); Document document = new Document(); PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(pdfFile)); document.open(); // 將 Excel 單元格內(nèi)容寫入 PDF 文檔 PdfPTable table = new PdfPTable(1); BaseFont bf = BaseFont.createFont("E:\\cell\\Merge.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); com.itextpdf.text.Font f = new com.itextpdf.text.Font(bf, 10); Paragraph p = new Paragraph(value, f); table.addCell(p); document.add(table); document.close(); writer.close();
5、字符映射
因設(shè)計可以通過造字來實現(xiàn)上下標(biāo)字母,現(xiàn)在我們可以通過指定字符來實現(xiàn)當(dāng)前上下標(biāo)的標(biāo)簽替換,設(shè)計上下標(biāo)通過標(biāo)簽來包裹,類似:下標(biāo):<sub> </sub> 上標(biāo):<sup><sup>來標(biāo)簽指定上下標(biāo)。
通過解析當(dāng)前字符串上下標(biāo)標(biāo)簽來實現(xiàn)字符替換:
private static final String SUB_START = "<sub>"; //下標(biāo) private static final String SUB_END = "</sub>"; private static final String SUP_START = "<sup>"; //上標(biāo) private static final String SUP_END = "</sup>"; /** * 獲取下一對標(biāo)簽的index,不存在這些標(biāo)簽就返回null * @param s * @param tag SUB_START或者SUP_START * @return int[]中有兩個元素,第一個是開始標(biāo)簽的index,第二個元素是結(jié)束標(biāo)簽的index */ public static int[] getNextTagsIndex(String s, String tag) { int firstStart = s.indexOf(tag); if (firstStart > -1) { int firstEnd = 0; if (tag.equals(SUB_START)) { firstEnd = s.indexOf(SUB_END); String ssString = s.substring(firstStart, firstEnd+SUB_END.length()); if (ssString.contains(SUP_START)) { ssString = ssString.replace(SUP_START, "").replaceAll(SUP_END, ""); firstEnd = firstStart + ssString.indexOf(SUB_END); } }else if (tag.equals(SUP_START)) { firstEnd = s.indexOf(SUP_END); String ssString = s.substring(firstStart, firstEnd+SUP_END.length()); if (ssString.contains(SUB_START)) { ssString = ssString.replace(SUP_START, "").replaceAll(SUP_END, ""); firstEnd = firstStart + ssString.indexOf(SUP_END); } } if (firstEnd > firstStart) { return new int[] { firstStart, firstEnd }; } } return null; } /**移除下一對sub或者sup標(biāo)簽,返回移除后的字符串 * @param s * @param tag SUB_START或者SUP_START * @return */ public static String removeNextTags(String s, String tag) { s = s.replaceFirst(tag, ""); if (tag.equals(SUB_START)) { s = s.replaceFirst(SUB_END, ""); }else if (tag.equals(SUP_START)) { s = s.replaceFirst(SUP_END, ""); } return s; } /** * 判斷是不是包含sub、sup標(biāo)簽 * @param s * @return */ public static boolean containTag(String s) { return (s.contains(SUB_START) && s.contains(SUB_END)) || (s.contains(SUP_START) && s.contains(SUP_END)); } /** * 處理字符串,得到每個sub、sup標(biāo)簽的開始和對應(yīng)的結(jié)束的標(biāo)簽的index * @param s * @param tagIndexList 傳一個新建的空list進來,方法結(jié)束的時候會存儲好標(biāo)簽位置信息。 * <br>tagIndexList.get(0)存放的sub * <br>tagIndexList.get(1)存放的是sup * * @return 返回sub、sup處理完之后的字符串 */ public static String getIndexs(String s, List<List<int[]>> tagIndexList) { List<int[]> subs = Lists.newArrayList(); List<int[]> sups = Lists.newArrayList(); while (true) { int[] sub_pair = getNextTagsIndex(s, SUB_START); if (Objects.nonNull(sub_pair)) { int firstStart = sub_pair[0]; if (firstStart > -1) { int firstEnd = s.indexOf(SUB_END); String startString = s.substring(0, firstStart); String centreString = s.substring(firstStart, firstEnd); String endString = s.substring(firstEnd, s.length()); if (centreString.contains(SUP_START)) { centreString = centreString.replaceAll(SUP_START, "").replaceAll(SUP_END, ""); s = startString + centreString + endString; } } } int[] sup_pair = getNextTagsIndex(s, SUP_START); if (Objects.nonNull(sup_pair)) { int firstStart = sup_pair[0]; if (firstStart > -1) { int firstEnd = s.indexOf(SUP_END); String startString = s.substring(0, firstStart); String centreString = s.substring(firstStart, firstEnd); String endString = s.substring(firstEnd, s.length()); if (centreString.contains(SUB_START)) { centreString = centreString.replaceAll(SUB_START, "").replaceAll(SUB_END, ""); s = startString + centreString + endString; } } } boolean subFirst = false; boolean supFirst = false; List a = new ArrayList(); if (Objects.nonNull(sub_pair)) { a.add(sub_pair[0]); } if (Objects.nonNull(sup_pair)) { a.add(sup_pair[0]); } Collections.sort(a); if (Objects.nonNull(sub_pair)) { if (sub_pair[0] == Integer.parseInt(a.get(0).toString())) { subFirst = true; } } if (Objects.nonNull(sup_pair)) { if (sup_pair[0] == Integer.parseInt(a.get(0).toString())) { supFirst = true; } } if (sub_pair != null && subFirst) { s = removeNextTags(s, SUB_START); //<sub>標(biāo)簽被去掉之后,結(jié)束標(biāo)簽需要相應(yīng)往前移動 sub_pair[1] = sub_pair[1] - SUB_START.length(); subs.add(sub_pair); continue; } if (sup_pair != null && supFirst) { s = removeNextTags(s, SUP_START); //<sup>標(biāo)簽被去掉之后,結(jié)束標(biāo)簽需要相應(yīng)往前移動 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; }
然后我們通過獲取上下標(biāo)標(biāo)簽的下標(biāo),來完成字符的替換,至于要替換的Unicode是存在哪里,這個自己設(shè)計。
首先我們要把指定的字符轉(zhuǎn)成Unicode的:
unicode = StringEscapeUtils.unescapeJava(unicode);
然后通過全局的字符builder來重新構(gòu)造字符串:
StringBuilder sb = new StringBuilder(value); unicode = StringEscapeUtils.unescapeJava(unicode); sb.replace(pair[0], pair[1], unicode);
到此這篇關(guān)于JAVA實現(xiàn)Excel和PDF上下標(biāo)的文章就介紹到這了,更多相關(guān)JAVA Excel和PDF上下標(biāo)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
將Swagger2文檔導(dǎo)出為HTML或markdown等格式離線閱讀解析
這篇文章主要介紹了將Swagger2文檔導(dǎo)出為HTML或markdown等格式離線閱讀,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-11-11Springboot實現(xiàn)Activemq死信隊列詳解
這篇文章主要介紹了Springboot實現(xiàn)Activemq死信隊列詳解,Activemq服務(wù)端配置重新投遞次數(shù)超過?MaximumRedeliveries?,則會進入死信隊列,默認(rèn)情況,有一個死信隊列:AcitveMQ.DLQ,所有的消息都投遞到此隊列,包括過期消息,重投遞失敗消息,需要的朋友可以參考下2023-12-12@WebFilter在SpringBoot無效的原因分析和解決方案
使用Ruoyi的demo部署成功后,發(fā)現(xiàn)js、css等靜態(tài)文件都進入了過濾器,但是發(fā)現(xiàn)靜態(tài)文件沒有使用瀏覽器緩存,新建BrowserCacheFilter.java并增加@WebFilter處理,應(yīng)用自動重啟后發(fā)現(xiàn)@WebFilter無效,所以本文給大家介紹了@WebFilter在SpringBoot無效的原因分析和解決方案2024-03-03基于java查找并打印輸出字符串中字符出現(xiàn)次數(shù)
這篇文章主要介紹了基于java查找并打印輸出字符串中字符出現(xiàn)次數(shù),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-11-11