自動化文檔生成工具(親測可運行)

本文介紹了一個用Java編寫的自動化文檔生成工具,通過讀取開發清單文本自動生成格式規范的Word文檔。該工具的主要特點包括:

  1. 采用Apache POI庫處理Word文檔,支持多級標題和段落自動生成
  2. 實現中文數字轉換功能,將編號轉換為"一、二、三"等樣式
  3. 預設標準的文檔結構(輸入/流程/輸出/財務/異常/源代碼等章節)
  4. 通過Maven打包成可執行JAR,只需將清單文本與JAR同目錄即可運行

使用該工具可將原本繁瑣的手動文檔編寫工作自動化,顯著提高開發文檔的編寫效率。

單位要寫開發文檔,文檔大致結構是上面有一個表格,填入開發內容清單,比如是這樣:

1新增用戶
2刪除用戶
3查詢用戶

下面需要有對應的二級標題和三級標題,我就需要每次都去復制粘貼,改編號,很是麻煩。干脆用java寫個腳本來處理吧。

核心思路是,把開發清單復制到txt文本,然后去讀取,生成一個新的word,帶上這些格式,再拷貝回去即可,省了不少時間。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com</groupId><artifactId>doc-server</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version></dependency></dependencies><build><plugins><!-- 其他插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-assembly-plugin</artifactId><version>3.5.0</version><configuration><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs><archive><manifest><mainClass>main.WordGenerator</mainClass> <!-- 替換為你的主類 --></manifest></archive></configuration><executions><execution><id>make-assembly</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin></plugins></build></project>

WordGenerator.java

package main;import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;import java.io.*;
import java.math.BigInteger;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;public class WordGenerator {/*** 使用BufferedReader按行讀取文件*/public static List<String> readLinesWithBufferedReader(String filePath) {List<String> lines = new ArrayList<>();try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), StandardCharsets.UTF_8))) {String line;while ((line = reader.readLine()) != null) {lines.add(line);}} catch (IOException e) {System.err.println("讀取文件失敗: " + e.getMessage());}return lines;}static class Transaction {private String num;private String content;public Transaction(String num, String content) {this.num = num;this.content = content;}public String getNum() {return num;}public String getContent() {return content;}@Overridepublic String toString() {return "Transaction{" +"num='" + num + '\'' +", content='" + content + '\'' +'}';}}public static String getPath(){String path = WordGenerator.class.getProtectionDomain().getCodeSource().getLocation().getPath();System.out.println("原始路徑:" +  path);if(System.getProperty("os.name").contains("dows")){//path -> file:/D:/Haier/hlmcheckup-admin.jar!/BOOT-INF/lib/hlmcheckup-common-1.0.0.jar!///如果是windows系統,前面有可能有“file:”要替換掉。path = path.replace("file:", "");path = path.substring(1,path.length());System.out.println("原始路徑:" +  path);}if(path.contains("jar")){//這里根據你jar包名稱分割//D:/Haier/hlmcheckup-admin.jar!/BOOT-INF/lib/hlmcheckup-common-1.0.0.jar!/// -> D:/Haier/String[] split = path.split("doc-server-1.0-SNAPSHOT-jar-with-dependencies.jar");System.out.println("jar包路徑:" +  split[0]);return split[0];}//"hlmcheckup-common/target/classes/" 為當前類路徑 linux與macos需要替換掉return path.replace("hlmcheckup-common/target/classes/", "");}public static String getParentDirectory(String jarFilePath) {if (jarFilePath == null || jarFilePath.isEmpty()) {return null;}File jarFile = new File(jarFilePath);File parentDir = jarFile.getParentFile();if (parentDir != null && parentDir.exists() && parentDir.isDirectory()) {return parentDir.getAbsolutePath();}return null;}public static void main(String[] args) throws Exception {File jarFile = new File( getPath() + "\\1.txt" );System.out.println(jarFile.getAbsoluteFile());List<String> lines = readLinesWithBufferedReader(jarFile.getAbsolutePath());List<Transaction> transactionList = new ArrayList<>();System.out.println("讀取的行數: " + lines.size());for (int i = 0; i <  lines.size(); i++) {transactionList.add(new Transaction(lines.get(i).split("\\t")[0],lines.get(i).split("\\t")[2]));}System.out.println(transactionList);// 創建新的Word文檔try (XWPFDocument document = new XWPFDocument()) {ensureHeadingStylesExist(document);for (Transaction transaction: transactionList) {int index = 1;String chinese = NumberToChinese.toChinese(Long.parseLong(transaction.getNum()));// 創建一級標題createHeading(document, " 交易" + chinese + ":" + transaction.getContent(), 2);createHeading(document, " 輸入" , 3 );createParagraph(document, " " + transaction.getContent() + " 輸入參數" );createHeading(document, " 流程" , 3 );createParagraph(document, " 開始 -> " + transaction.getContent() + " -> 結束");createHeading(document, " 輸出" , 3 );createParagraph(document, " " + transaction.getContent() + " 輸出參數");createHeading(document, " 財務" , 3 );createParagraph(document, " 無");createHeading(document, " 異常" , 3 );createParagraph(document, " 無");createHeading(document,  " 源代碼" , 3 );createParagraph(document, " 無");}// 保存文檔try (FileOutputStream out = new FileOutputStream(new File("out.docx"))) {document.write(out);System.out.println("Word文檔生成成功!");}} catch (IOException e) {e.printStackTrace();}}/*** 創建標題段落* @param document Word文檔對象* @param text 標題文本* @param level 標題級別(1-9)*/private static void createHeading(XWPFDocument document, String text, int level) {XWPFParagraph paragraph = document.createParagraph();paragraph.setStyle("Heading" + level); // 設置標題樣式XWPFRun run = paragraph.createRun();run.setText(text);run.setFontSize(16 - (level - 1) * 2); // 標題1:16pt, 標題2:14pt, 依此類推run.setBold(true);}/*** 創建正文段落* @param document Word文檔對象* @param text 段落文本*/private static void createParagraph(XWPFDocument document, String text) {XWPFParagraph paragraph = document.createParagraph();XWPFRun run = paragraph.createRun();run.setText(text);run.setFontSize(12); // 正文默認12pt}// 確保文檔包含必要的標題樣式private static void ensureHeadingStylesExist(XWPFDocument document) {try {XWPFStyles styles = document.getStyles();if (styles == null) {styles = document.createStyles();}// 檢查Heading 1樣式是否存在,不存在則創建if (!hasStyle(styles, "Heading1")) {createHeadingStyle(document, "Heading1", "Heading 1", 1, 24);}if (!hasStyle(styles, "Heading2")) {createHeadingStyle(document, "Heading2", "Heading 2", 2, 18);}if (!hasStyle(styles, "Heading3")) {createHeadingStyle(document, "Heading3", "Heading 3", 3, 14);}} catch (Exception e) {System.err.println("創建標題樣式失敗: " + e.getMessage());}}// 檢查樣式是否存在private static boolean hasStyle(XWPFStyles styles, String styleId) {return styles.getStyle(styleId) != null;}// 創建標題樣式(兼容所有POI版本)private static void createHeadingStyle(XWPFDocument document, String styleId, String styleName, int level, int fontSize) {XWPFStyles styles = document.getStyles();// 創建新樣式CTStyle ctStyle = CTStyle.Factory.newInstance();ctStyle.setStyleId(styleId);// 設置樣式名稱CTString name = CTString.Factory.newInstance();name.setVal(styleName);ctStyle.setName(name);// 設置樣式類型為段落ctStyle.setType(STStyleType.PARAGRAPH);// 設置為標題樣式CTDecimalNumber indentNumber = CTDecimalNumber.Factory.newInstance();indentNumber.setVal(BigInteger.valueOf(level));ctStyle.setUiPriority(indentNumber);// 設置基于Normal樣式ctStyle.setBasedOn(CTString.Factory.newInstance());ctStyle.getBasedOn().setVal("Normal");// 設置段落屬性CTPPr ppr = ctStyle.addNewPPr();ppr.addNewSpacing().setAfter(BigInteger.valueOf(100)); // 段后間距// 設置字體和大小(兼容舊版POI)CTRPr rpr = ctStyle.addNewRPr();CTFonts fonts = rpr.addNewRFonts();fonts.setAscii("宋體");fonts.setEastAsia("宋體");rpr.addNewSz().setVal(BigInteger.valueOf(fontSize * 2)); // 字體大小(Twips單位)rpr.addNewB().setVal(STOnOff.TRUE); // 加粗// 添加樣式到文檔XWPFStyle newStyle = new XWPFStyle(ctStyle);styles.addStyle(newStyle);}
}

NumberToChinese.java 工具類

package main;import java.math.BigDecimal;public class NumberToChinese {// 中文數字字符映射private static final String[] CN_NUMBERS = {"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"};private static final String[] CN_INTEGER_UNITS = {"", "十", "百", "千", "萬", "十", "百", "千", "億", "十", "百", "千", "兆"};private static final String[] CN_DECIMAL_UNITS = {"角", "分", "厘", "毫"};// 中文金額單位映射(用于財務場景)private static final String[] CN_FINANCIAL_UNITS = {"", "拾", "佰", "仟", "萬", "拾", "佰", "仟", "億", "拾", "佰", "仟", "兆"};private static final String CN_ZERO = "零";private static final String CN_INTEGER = "整";private static final String CN_NEGATIVE = "負";/*** 將數字轉換為中文大寫(普通模式)* 例如:1234 → 一千二百三十四*/public static String toChinese(long number) {if (number == 0) {return CN_NUMBERS[0];}StringBuilder result = new StringBuilder();boolean isNegative = number < 0;if (isNegative) {number = -number;result.append(CN_NEGATIVE);}String numStr = String.valueOf(number);int length = numStr.length();for (int i = 0; i < length; i++) {int digit = numStr.charAt(i) - '0';int unitIndex = length - i - 1;// 處理零的情況if (digit == 0) {// 避免多個連續的零if (i > 0 && numStr.charAt(i - 1) != '0') {result.append(CN_NUMBERS[0]);}// 處理萬億等單位if (unitIndex % 4 == 0 && i < length - 1 && numStr.charAt(i + 1) != '0') {result.append(CN_INTEGER_UNITS[unitIndex]);}continue;}result.append(CN_NUMBERS[digit]);result.append(CN_INTEGER_UNITS[unitIndex]);}return result.toString();}/*** 將數字轉換為中文大寫(財務模式)* 例如:1234.56 → 壹仟貳佰叁拾肆元伍角陸分*/public static String toFinancialChinese(double number) {// 使用BigDecimal避免浮點數精度問題BigDecimal bd = new BigDecimal(String.valueOf(number));boolean isNegative = bd.signum() < 0;if (isNegative) {bd = bd.negate();}// 分離整數和小數部分BigDecimal integerPart = bd.setScale(0, BigDecimal.ROUND_DOWN);BigDecimal decimalPart = bd.subtract(integerPart).multiply(new BigDecimal(100)); // 轉換為分StringBuilder result = new StringBuilder();if (isNegative) {result.append(CN_NEGATIVE);}// 處理整數部分String integerStr = integerPart.toPlainString();if (integerStr.equals("0")) {result.append(CN_NUMBERS[0]);} else {int length = integerStr.length();for (int i = 0; i < length; i++) {int digit = integerStr.charAt(i) - '0';int unitIndex = length - i - 1;// 處理零的情況if (digit == 0) {if (i > 0 && integerStr.charAt(i - 1) != '0') {result.append(CN_ZERO);}if (unitIndex % 4 == 0 && i < length - 1 && integerStr.charAt(i + 1) != '0') {result.append(CN_FINANCIAL_UNITS[unitIndex]);}continue;}result.append(CN_NUMBERS[digit]);result.append(CN_FINANCIAL_UNITS[unitIndex]);}}result.append("元");// 處理小數部分int decimalInt = decimalPart.intValue();if (decimalInt == 0) {result.append(CN_INTEGER);} else {int jiao = decimalInt / 10;int fen = decimalInt % 10;if (jiao > 0) {result.append(CN_NUMBERS[jiao]).append(CN_DECIMAL_UNITS[0]);} else if (decimalInt > 9) {result.append(CN_ZERO);}if (fen > 0) {result.append(CN_NUMBERS[fen]).append(CN_DECIMAL_UNITS[1]);}}return result.toString();}// 測試示例public static void main(String[] args) {System.out.println("普通模式:");System.out.println("1234 → " + toChinese(1234));System.out.println("10001 → " + toChinese(10001));System.out.println("10030 → " + toChinese(10030));System.out.println("100000001 → " + toChinese(100000001));System.out.println("-123 → " + toChinese(-123));System.out.println("\n財務模式:");System.out.println("1234.56 → " + toFinancialChinese(1234.56));System.out.println("1000.01 → " + toFinancialChinese(1000.01));System.out.println("0.50 → " + toFinancialChinese(0.50));System.out.println("1000000 → " + toFinancialChinese(1000000));System.out.println("-123.45 → " + toFinancialChinese(-123.45));}
}

用maven打包后,將1.txt和jar放在同一個目錄,雙擊jar,就會生成目標word文件。

1.txt

1?? ?無?? ?新增用戶
2?? ?無?? ?刪除用戶
3?? ?無?? ?查詢用戶

生成out

目錄大綱也是正常的

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/84270.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/84270.shtml
英文地址,請注明出處:http://en.pswp.cn/web/84270.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

湖北理元理律師事務所債務優化模型:法律與生活的平衡之道

在債務重組領域&#xff0c;專業機構需同時解決兩個矛盾&#xff1a;法律合規性與債務人可持續生存能力。湖北理元理律師事務所通過“三維干預模型”&#xff0c;在武漢某餐飲連鎖企業債務危機中驗證了該方案的有效性。 一、法律底層設計&#xff1a;還款方案的合法性審查 以該…

Web3-代幣ERC20/ERC721以及合約安全溢出和下溢的研究

Web3-代幣ERC20/ERC721以及合約安全溢出和下溢的研究 以太坊上的代幣 如果你對以太坊的世界有一些了解&#xff0c;你很可能聽人們聊過代幣— ERC20代幣 一個 代幣 在以太坊基本上就是一個遵循一些共同規則的智能合約——即它實現了所有其他代幣合約共享的一組標準函數&…

論文筆記 <交通燈><多智能體>MetaLight:基于價值的元強化學習用于交通信號控制

今天看的論文是這篇MetaLight:基于價值的元強化學習用于交通信號控制 里面提到的創新點就是MetaLight框架&#xff1a;他目標是讓交通信號控制智能體&#xff08;Agent&#xff09;在新路口&#xff08;即使結構或流量模式不同&#xff09;上能??快速學習??&#xff08;Few…

華為OD-2024年E卷-尋找符合要求的最長子串[200分] -- python

問題描述&#xff1a; 給定一個字符串s&#xff0c;找出這樣一個子串: 1)該子串中的任意一個字符最多出現2次; 2)該子串不包含指定某個字符; 請你找出滿足該條件的最長子串的長度。 輸入描述 第一行為要求不包含的指定字符&#xff0c;為單個字符&#xff0c;取值范圍[0-9a-zA…

CppCon 2016 學習:What C++ Programmers Need to Know about Header <random>

隨機數生成的歷史背景 Middle-Square 方法&#xff08;中位平方法&#xff09;&#xff1a; 已知最早的隨機算法之一或由修道士 Brother Edvin 在 1245 年發明由 John von Neumann 在 1949 年重新發現缺點明顯&#xff0c;但執行速度快 Monte Carlo 方法&#xff1a; 起初是…

Origin:誤差棒點線圖繪制

1.首先將你的數據復制到表格 2.選中B(y)列數據&#xff0c;依次點擊圖示選項 3.選中圖中紅框數據&#xff0c;點擊繪制點線圖即可 4.結果展示

Spring 源碼學習 1:ApplicationContext

Spring 源碼學習 1&#xff1a;ApplicationContext Bean 定義和 Bean 實例 AnnotationConfigApplicationContext 首先&#xff0c;創建一個最簡單的 Spring Boot 應用。 在入口類中接收SpringApplication.run的返回值&#xff1a; SpringBootApplication public class Dem…

CppCon 2017 學習:Design Patterns for Low-Level Real-Time Rendering

這段內容講的是離散顯卡&#xff08;Discrete GPU&#xff09;中的內存管理模型&#xff0c;重點是CPU和GPU各自獨立管理自己的物理內存&#xff0c;以及它們如何通過虛擬內存和DMA引擎實現高效通信。以下是詳細的理解和梳理&#xff1a; 1. 基本概念 CPU 和 GPU 是兩個獨立的…

【單調隊列】-----【原理+模版】

單調隊列 一、什么是單調隊列&#xff1f; 單調隊列是一種在滑動窗口或區間查詢中維護候選元素單調性的數據結構&#xff0c;通常用于解決“滑動窗口最大值/最小值”等問題。 核心思想是&#xff1a;利用雙端隊列&#xff08;deque&#xff09;維護當前窗口內或候選范圍內元素…

CSS語法中的選擇器與屬性詳解

CSS:層疊樣式表&#xff0c;Cascading Style Sheets 層疊樣式表 內容和樣式分離解耦&#xff0c;便于修改樣式。 特殊說明&#xff1a; 最后一條聲明可以沒有分號&#xff0c;但是為了以后修改方便&#xff0c;一般也加上分號為了使用樣式更加容易閱讀&#xff0c;可以將每條代…

模擬設計的軟件工程項目

考核題目 論文論述題&#xff1a;結合你 參與開發、調研或模擬設計的軟件工程項目 &#xff0c;撰寫一篇論文 完成以下任務&#xff0c;論文題目為《面向微服務架構的軟件系統設計與建模分析》&#xff0c;總分&#xff1a; 100 分。 1. 考核內容&#xff1a; 一、系統論述…

個人理解redis中IO多路復用整個網絡處理流

文章目錄 1.redis網絡處理流2.理解通知機制 1.redis網絡處理流 10個客戶端通過TCP與Redis建立socket連接&#xff0c;發送GET name指令到服務器端。服務器端的網卡接收數據&#xff0c;數據進入內核態的網絡協議棧。Redis通過IO多路復用機制中的epoll向內核注冊監聽這些socket的…

【鄭州輕工業大學|數據庫】數據庫課設-酒店管理系統

該數據課設是一個基于酒店管理系統的數據庫設計 建庫語句 create database hotel_room default charset utf8 collate utf8_general_ci;建表語句 use hotel_room;-- 房型表 create table room_type( id bigint primary key auto_increment comment 房型id, name varchar(50)…

TCP 三次握手與四次揮手詳解

前言 在當今互聯網時代&#xff0c;前端開發的工作范疇早已超越了簡單的頁面布局和交互設計。隨著前端應用復雜度的不斷提高&#xff0c;對網絡性能的優化已成為前端工程師不可忽視的重要職責。而要真正理解并優化網絡性能&#xff0c;就需要探究支撐整個互聯網的基礎協議——…

RTD2735TD/RTD2738 (HDMI,DP轉EDP 高分辨率高刷新率顯示器驅動芯片)

一、芯片概述 RTD2738是瑞昱半導體&#xff08;Realtek&#xff09;推出的一款高性能顯示驅動芯片&#xff0c;專為高端顯示器、便攜屏、專業顯示設備及多屏拼接系統設計。其核心優勢在于支持4K分辨率下240Hz高刷新率及8K30Hz顯示&#xff0c;通過集成DisplayPort 1.4a與HDMI …

C++實現手寫strlen函數

要實現求字符串長度的函數&#xff0c;核心思路是通過指針或索引遍歷字符串&#xff0c;直到遇到字符串結束標志 \0 。以下是兩種常見的實現方式&#xff1a; 指針遍歷版本 #include <iostream> using namespace std; // 指針方式實現strlen size_t myStrlen(const cha…

NVPL 函數庫介紹和使用

文章目錄 NVPL 函數庫介紹和使用什么是 NVPLNVPL 的主要組件NVPL 的優勢安裝 NVPL基本使用示例示例1&#xff1a;使用 NVPL RAND 生成隨機數示例2&#xff1a;使用 NVPL FFT 進行快速傅里葉變換 編譯 NVPL 程序性能優化建議總結 NVPL 函數庫介紹和使用 什么是 NVPL NVPL (NVI…

HTTP相關內容補充

目錄 一、URI 和 URL 二、使用 Cookie 的狀態管理 三、返回結果的 HTTP狀態碼 一、URI 和 URL URI &#xff1a;統一資源標識符 URL&#xff1a;統一資源定位符 URI 格式 登錄信息&#xff08;認證&#xff09;指定用戶名和密碼作為從服務器端獲取資源時必要的登錄信息&a…

MySQL: Invalid use of group function

https://stackoverflow.com/questions/2330840/mysql-invalid-use-of-group-function 出錯SQL: 錯誤原因&#xff1a; 1. 不能在 WHERE 子句中使用聚合&#xff08;或分組&#xff09;函數 2. HAVING 只能篩選分組后的聚合結果或分組字段 # Write your MySQL query statem…

C#財政票查驗接口集成-醫療發票查驗-非稅收入票據查驗接口

財政票據是企事業單位、醫療機構、金融機構等組織的重要報銷憑證&#xff0c;其真實性、完整性和合規性日益受到重視。現如今&#xff0c;為有效防范虛假票據報銷、入賬、資金流失等問題的發生&#xff0c;財政票據查驗接口&#xff0c;結合財政票據識別接口&#xff0c;旨在為…