Java生成Word文档

本教程将详细介绍如何使用Java从数据库查询图书数据,并生成格式化的Word统计报告。我们将使用Spring Boot框架和Apache POI库来实现这一功能。

一、项目结构

bash 复制代码
src/main/java
├── com/example/libraryreport
│   ├── controller
│   │   └── ReportController.java
│   ├── service
│   │   └── BookReportService.java
│   ├── mapper
│   │   └── BookReportMapper.java
│   └── LibraryReportApplication.java

二、核心代码实现

1. 控制器层

java 复制代码
@RestController
@RequestMapping("/api/reports")
public class ReportController {
    
    @Autowired
    private BookReportService bookReportService;
    
    @GetMapping("/books")
    public ResponseEntity<String> generateBookReport() {
        try {
            String fileName = "图书统计报告_" + System.currentTimeMillis() + ".docx";
            String outputPath = "reports/" + fileName;
            
            bookReportService.generateReport(outputPath);
            
            return ResponseEntity.ok("报告生成成功: " + outputPath);
        } catch (Exception e) {
            return ResponseEntity.status(500)
                    .body("报告生成失败: " + e.getMessage());
        }
    }
}

2. 数据访问层接口

java 复制代码
public interface BookReportMapper {
    // 获取图书总量
    int selectTotalBookCount();
    
    // 按分类统计图书数量
    List<Map<String, Object>> selectBooksByCategory();
    
    // 获取热门图书TOP10
    List<Map<String, Object>> selectPopularBooks();
    
    // 获取借阅统计
    List<Map<String, Object>> selectBorrowStats();
}

3. 服务层实现

java 复制代码
@Service
public class BookReportService {
    
    @Autowired
    private BookReportMapper bookReportMapper;

    public void generateReport(String outputPath) throws Exception {
        // 创建Word文档
        XWPFDocument document = new XWPFDocument();
        
        try {
            // 添加报告标题
            addTitle(document, "图书馆图书统计报告");
            
            // 添加生成日期
            addGenerationDate(document);
            
            // 添加图书总量统计
            addTotalBookCount(document);
            
            // 添加分类统计表格
            addCategoryStatistics(document);
            
            // 添加热门图书列表
            addPopularBooks(document);
            
            // 添加借阅统计
            addBorrowStatistics(document);
            
            // 保存文档
            saveDocument(document, outputPath);
        } finally {
            document.close();
        }
    }
    
    // 创建报告主标题,设置居中、加粗和大号字体
    private void addTitle(XWPFDocument document, String titleText) {
        XWPFParagraph title = document.createParagraph();
        title.setAlignment(ParagraphAlignment.CENTER);
        
        XWPFRun titleRun = title.createRun();
        titleRun.setText(titleText);
        titleRun.setBold(true);
        titleRun.setFontSize(20);
        titleRun.setFontFamily("宋体");
        
        // 添加空行
        document.createParagraph();
    }
    
    // 在右上角添加报告生成日期
    private void addGenerationDate(XWPFDocument document) {
        XWPFParagraph datePara = document.createParagraph();
        datePara.setAlignment(ParagraphAlignment.RIGHT);
        
        XWPFRun dateRun = datePara.createRun();
        dateRun.setText("生成日期: " + LocalDate.now().toString());
        dateRun.setFontSize(12);
        dateRun.setFontFamily("宋体");
        
        // 添加空行
        document.createParagraph();
    }
    
    // 显示图书馆藏书总量
    private void addTotalBookCount(XWPFDocument document) {
        int totalCount = bookReportMapper.selectTotalBookCount();
        
        XWPFParagraph sectionTitle = createSectionTitle(document, "一、图书总量统计");
        
        XWPFParagraph content = document.createParagraph();
        XWPFRun run = content.createRun();
        run.setText(String.format("图书馆目前共有藏书: %s册", formatNumber(totalCount)));
        run.setFontSize(14);
        run.setFontFamily("宋体");
        
        // 添加空行
        document.createParagraph();
    }
    
    // 创建分类统计表格,包括序号、分类名称、数量和占比
    private void addCategoryStatistics(XWPFDocument document) throws Exception {
        // 创建章节标题
        XWPFParagraph sectionTitle = createSectionTitle(document, "二、图书分类统计");
        
        // 获取分类数据
        List<Map<String, Object>> categories = bookReportMapper.selectBooksByCategory();
        int total = bookReportMapper.selectTotalBookCount();
        
        // 创建表格
        XWPFTable table = document.createTable(1, 4);
        table.setWidth("100%");
        
        // 设置表头
        setTableHeader(table, "序号", "图书分类", "数量", "占比");
        
        // 填充数据
        int index = 1;
        for (Map<String, Object> category : categories) {
            XWPFTableRow row = table.createRow();
            row.getCell(0).setText(String.valueOf(index++));
            row.getCell(1).setText(category.get("categoryName").toString());
            
            int count = Integer.parseInt(category.get("count").toString());
            row.getCell(2).setText(formatNumber(count));
            
            double percent = (count * 100.0) / total;
            row.getCell(3).setText(String.format("%.1f%%", percent));
        }
        
        // 添加汇总行
        XWPFTableRow footer = table.createRow();
        footer.getCell(1).setText("总计");
        footer.getCell(2).setText(formatNumber(total));
        footer.getCell(3).setText("100%");
        
        // 添加空行
        document.createParagraph();
    }
    
    // 列出热门图书TOP10,前三名用蓝色加粗显示
    private void addPopularBooks(XWPFDocument document) {
        // 创建章节标题
        XWPFParagraph sectionTitle = createSectionTitle(document, "三、热门图书TOP10");
        
        List<Map<String, Object>> popularBooks = bookReportMapper.selectPopularBooks();
        
        for (int i = 0; i < popularBooks.size(); i++) {
            Map<String, Object> book = popularBooks.get(i);
            
            XWPFParagraph item = document.createParagraph();
            item.setIndentationLeft(200);
            
            XWPFRun run = item.createRun();
            run.setText(String.format("%d. 《%s》 - %s (借阅量: %s次)", 
                i + 1,
                book.get("title"),
                book.get("author"),
                formatNumber(Long.parseLong(book.get("borrowCount").toString()))
            );
            run.setFontSize(12);
            run.setFontFamily("宋体");
            
            // 突出显示前三名
            if (i < 3) {
                run.setBold(true);
                run.setColor("0000FF");
            }
        }
        
        // 添加空行
        document.createParagraph();
    }
    
    // 创建借阅统计表格,显示每月借阅量和同比增长率
    private void addBorrowStatistics(XWPFDocument document) {
        // 创建章节标题
        XWPFParagraph sectionTitle = createSectionTitle(document, "四、借阅统计");
        
        List<Map<String, Object>> borrowStats = bookReportMapper.selectBorrowStats();
        
        // 创建表格
        XWPFTable table = document.createTable(1, 3);
        table.setWidth("100%");
        
        // 设置表头
        setTableHeader(table, "月份", "借阅量", "同比增长");
        
        // 填充数据
        for (Map<String, Object> stat : borrowStats) {
            XWPFTableRow row = table.createRow();
            row.getCell(0).setText(stat.get("month").toString());
            row.getCell(1).setText(formatNumber(Long.parseLong(stat.get("count").toString())));
            
            // 计算同比增长
            if (stat.containsKey("growthRate")) {
                double growth = Double.parseDouble(stat.get("growthRate").toString());
                row.getCell(2).setText(String.format("%.1f%%", growth * 100));
                
                // 设置颜色:增长为红色,下降为绿色
                XWPFRun growthRun = row.getCell(2).getParagraphs().get(0).getRuns().get(0);
                if (growth > 0) {
                    growthRun.setColor("FF0000");
                } else if (growth < 0) {
                    growthRun.setColor("00FF00");
                }
            } else {
                row.getCell(2).setText("N/A");
            }
        }
    }
    
    // 辅助方法,创建统一的章节标题格式
    private XWPFParagraph createSectionTitle(XWPFDocument document, String title) {
        XWPFParagraph paragraph = document.createParagraph();
        XWPFRun run = paragraph.createRun();
        run.setText(title);
        run.setBold(true);
        run.setFontSize(16);
        run.setFontFamily("宋体");
        
        return paragraph;
    }
    
    // 辅助方法,设置表格表头样式
    private void setTableHeader(XWPFTable table, String... headers) {
        XWPFTableRow headerRow = table.getRow(0);
        for (int i = 0; i < headers.length; i++) {
            XWPFRun run = headerRow.getCell(i).getParagraphs().get(0).createRun();
            run.setText(headers[i]);
            run.setBold(true);
            run.setFontSize(12);
            run.setFontFamily("宋体");
            
            // 设置单元格背景色
            headerRow.getCell(i).setColor("D3D3D3");
        }
    }
    
    // 格式化数字显示,添加千位分隔符
    private String formatNumber(long number) {
        return String.format("%,d", number);
    }
    
    // 保存Word文档到指定路径
    private void saveDocument(XWPFDocument document, String outputPath) throws IOException {
        // 确保目录存在
        File outputFile = new File(outputPath);
        outputFile.getParentFile().mkdirs();
        
        try (FileOutputStream out = new FileOutputStream(outputFile)) {
            document.write(out);
        }
    }
}

四、运行效果

文档样式细节

  1. 字体规范

    • 中文默认使用"宋体",数字/英文自动匹配
    • 标题层级分明(20号→16号→14号→12号)
  2. 数字处理

    • 所有数量自动添加千位分隔符(如1,200
    • 百分比保留1位小数(如28.4%
  3. 颜色标记

    • 蓝色:TOP3热门图书
    • 红色/绿色:借阅量增长/下降
    • 灰色:表格标题背景
  4. 布局设计

    • 章节间有适当空行
    • 表格宽度占满页面(100%)
    • 列表项统一缩进
  5. 数据完整性

    • 包含总量统计、分类占比、排行榜和趋势分析
    • 自动计算百分比和增长率
lua 复制代码
+------------------------------------------+
|           图书馆图书统计报告               |
|              (大标题)                   |
|                                          |
| 生成日期:2023-05-20 (右上角小字)        |
|                                          |
| 一、图书总量统计                          |
| 图书馆目前共有藏书:12,345册               |
|                                          |
| 二、图书分类统计                          |
| +----+------------+-------+-------+      |
| |序号| 图书分类   | 数量  | 占比  |        |
| +----+------------+-------+-------+      |
| |1   |计算机科学 | 3,500 | 28.4% |        |
| |2   |文学       | 2,800 | 22.7% |       |
| ...                                      |
| |    |总计       |12,345 | 100%  |       |
| +----+------------+-------+-------+     |
|                                         |
| 三、热门图书TOP10                        |
| 1. 《Java编程思想》...(蓝色加粗)        |
| 2. 《三体》...(蓝色加粗)                |
| ...                                     |
|                                         |
| 四、借阅统计                             |
| +------------+--------+----------+      |
| | 月份       | 借阅量 | 同比增长 |        |
| +------------+--------+----------+      |
| | 2023-01    | 1,200  | +15.2%↑ |       |
| | 2023-02    | 980    | -8.3%↓  |       |
| ...                                     |
+-----------------------------------------+

五、总结

通过本教程,我们实现了:

  1. 使用Spring Boot构建Web服务
  2. 通过MyBatis访问数据库获取统计信息
  3. 使用Apache POI生成格式化的Word文档
  4. 实现表格、列表等复杂格式的输出

这个方案可以轻松扩展为其他类型的统计报告生成工具,只需修改SQL查询和Word格式设置即可。

相关推荐
褚瑱琅1 小时前
T-SQL语言的压力测试
开发语言·后端·golang
东方靖岚4 小时前
R语言的数据库交互
开发语言·后端·golang
uhakadotcom6 小时前
Python 量化计算入门:基础库和实用案例
后端·算法·面试
小萌新上大分6 小时前
SpringCloudGateWay
java·开发语言·后端·springcloud·springgateway·cloudalibaba·gateway网关
uhakadotcom6 小时前
使用Python获取Google Trends数据:2025年详细指南
后端·面试·github
uhakadotcom6 小时前
使用 Python 与 Google Cloud Bigtable 进行交互
后端·面试·github
直视太阳7 小时前
springboot+easyexcel实现下载excels模板下拉选择
java·spring boot·后端
追逐时光者7 小时前
C#/.NET/.NET Core技术前沿周刊 | 第 33 期(2025年4.1-4.6)
后端·.net
灼华十一7 小时前
Golang系列 - 内存对齐
开发语言·后端·golang
兰亭序咖啡8 小时前
学透Spring Boot — 009. Spring Boot的四种 Http 客户端
java·spring boot·后端