数据库表字段以表格形式写入Word

news2024/11/25 6:35:56

在项目的开发中,难免会有编写概要设计、详细设计文档的要求,而在这些文档中,不可避免的就是要把数据库表的字段信息以表格的形式体现出来。例如下面这种格式

表数量少点还可以一点点粘贴,多了的话真的会疯,所以自己编写了一套可以自动读取数据表字段来批量写入文档的代码。

maven项目需要先引入依赖

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>27.0-hbase</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.0.0</version> <!-- 请检查是否有更新的版本 -->
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.23</version> <!-- 请检查是否有更新的版本 -->
        </dependency>

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>25.1-jre</version>
        </dependency>

代码如下: 



import avro.shaded.com.google.common.collect.Lists;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.sql.*;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.List;

public class DatabaseToWordExample{
    public static void main(String[] args) throws SQLException, IOException {
        // 创建Word文档
        XWPFDocument doc = new XWPFDocument();
        // 创建1级标题
        setDocTitle(doc,1,"一、数据库表设计");

        // 连接数据库
        Connection conn = DriverManager.getConnection("jdbc:mysql://{IP}:{port}/{数据库名}", 用户名, 密码);
        List<String> dbList = Lists.newArrayList("user");
        // 获取元数据
        DatabaseMetaData metaData = conn.getMetaData();
        int dbNum = 1;
        for (String database : dbList) {
            // 2级数据库标题名
            String databaseTitle = new StringBuilder(String.format("%d.%d",1,dbNum))
                    .append(" ")
                    .append(database)
                    .append("库")
                    .toString();
            // 创建2级标题
            setDocTitle(doc,2,databaseTitle);

            int tableNum = 1;
            // 查询表列表
            ResultSet tables = metaData.getTables(database, null, null, null);
            while (tables.next()){
                String tableName = tables.getString("TABLE_NAME");
                // 查询表注释
                String sql = "SELECT table_comment FROM information_schema.tables WHERE table_schema = ? AND table_name = ?";
                PreparedStatement ps = conn.prepareStatement(sql);
                ps.setString(1, database);
                ps.setString(2, tableName);
                ResultSet rs = ps.executeQuery();
                String tableComment = "";
                if (rs.next()) {
                    tableComment = rs.getString("table_comment");
                }
                // 3级表标题名
                String tableTitle = new StringBuilder(String.format("%d.%d.%d",1,dbNum,tableNum))
                        .append(" ")
                        .append(tableName)
                        .append(" ")
                        .append(tableComment)
                        .toString();
                // 创建3级标题
                setDocTitle(doc,3,tableTitle);

                // 创建表格
                XWPFTable table = createTable(doc);
                ResultSet columns = metaData.getColumns(database, null, tableName, null);

                // 添加数据行
                while (columns.next()) {
                    XWPFTableRow dataRow = table.createRow();
                    setRowHeight(dataRow, "490");

                    dataRow.getCell(0).setText(columns.getString("COLUMN_NAME"));
                    dataRow.getCell(1).setText(columns.getString("TYPE_NAME"));
                    dataRow.getCell(2).setText(Integer.toString(columns.getInt("COLUMN_SIZE")));
                    dataRow.getCell(3).setText(columns.getString("REMARKS"));

                    // 设置数据行单元格边框
                    for (XWPFTableCell cell : dataRow.getTableCells()) {
                        setCellBorders(cell);
                    }
                }

                tableNum++;
            }
            dbNum++;
        }

        // 保存Word文档
        try (FileOutputStream out = new FileOutputStream("output.docx")) {
            doc.write(out);
        }

        // 关闭数据库连接
        conn.close();
    }

    /**
     * 设置标题
     *
     * @param doc
     * @param titleLevel 标题等级
     * @param titleName 标题名称
     */
    private static void setDocTitle(XWPFDocument doc, int titleLevel, String titleName){
        switch (titleLevel) {
            case 1:
                // 创建一级标题
                XWPFParagraph title1 = doc.createParagraph();
                XWPFRun run1 = title1.createRun();
                run1.setText(titleName);
                run1.setBold(true);
                run1.setFontSize(16);
                break;
            case 2:
                // 创建二级标题
                XWPFParagraph title2 = doc.createParagraph();
                XWPFRun run2 = title2.createRun();
                run2.setText(titleName);
                run2.setBold(true);
                run2.setFontSize(14);
                break;
            case 3:
                // 创建三级标题
                XWPFParagraph title3 = doc.createParagraph();
                XWPFRun run3 = title3.createRun();
                run3.setText(titleName);
                run3.setBold(true);
                run3.setFontSize(12);
                break;
            default:
                break;
        }
    }

    /**
     * 创建表格
     *
     * @param doc
     * @return
     */
    private static XWPFTable createTable(XWPFDocument doc){
        // 创建表格
        XWPFTable table = doc.createTable();

        // 设置表格宽度
        table.setWidth("9990");

        // 创建表头
        XWPFTableRow headerRow = table.getRow(0);
        setRowHeight(headerRow, "490");  // 设置行高
        headerRow.getCell(0).setText("字段名");
        headerRow.addNewTableCell().setText("字段类型");
        headerRow.addNewTableCell().setText("字段长度");
        headerRow.addNewTableCell().setText("字段备注");

        // 计算每个单元格的宽度
        int totalWidth = 8222;  // 总宽度,例如14.5厘米
        int numColumns = 4;  // 列数,例如4列
        int cellWidth = totalWidth / numColumns;  // 计算每个单元格的宽度

        // 设置表格的列宽
        CTTblWidth tblWidth = table.getCTTbl().addNewTblPr().addNewTblW();
        tblWidth.setType(STTblWidth.DXA);
        tblWidth.setW(BigInteger.valueOf(totalWidth));


        // 设置单元格的宽度
        for (XWPFTableRow row : table.getRows()) {
            for (XWPFTableCell cell : row.getTableCells()) {
                CTTcPr tcPr = cell.getCTTc().addNewTcPr();
                CTTblWidth cellWidth1 = tcPr.addNewTcW();
                cellWidth1.setW(BigInteger.valueOf(cellWidth));
                cellWidth1.setType(STTblWidth.DXA);
            }
        }

        // 设置表头单元格边框
        for (XWPFTableCell cell : headerRow.getTableCells()) {
            setCellBorders(cell);
            cell.setColor("D3D3D3");  // 浅灰色的十六进制颜色代码
            // 设置文字竖向居中
            cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
        }
        return table;
    }

    private static void setRowHeight(XWPFTableRow row, String height) {
        row.setHeight(Integer.parseInt(height));
    }


    /**
     * 设置单元格边框和竖向居中
     * @param cell
     */
    private static void setCellBorders(XWPFTableCell cell) {

        // 确保单元格的CTTcPr对象已经被初始化
        if (!cell.getCTTc().isSetTcPr()) {
            cell.getCTTc().addNewTcPr();
        }
        // 设置文字竖向居中
        cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);

        // 设置单元格上边框
        CTTcBorders borders = cell.getCTTc().getTcPr().addNewTcBorders();
        CTBorder topBorder = borders.addNewTop();
        topBorder.setVal(STBorder.SINGLE);
        topBorder.setSz(BigInteger.valueOf(4));
        topBorder.setColor("000000");

        // 设置单元格下边框
        CTBorder bottomBorder = borders.addNewBottom();
        bottomBorder.setVal(STBorder.SINGLE);
        bottomBorder.setSz(BigInteger.valueOf(4));
        bottomBorder.setColor("000000");

        // 设置单元格左边框
        CTBorder leftBorder = borders.addNewLeft();
        leftBorder.setVal(STBorder.SINGLE);
        leftBorder.setSz(BigInteger.valueOf(4));
        leftBorder.setColor("000000");

        // 设置单元格右边框
        CTBorder rightBorder = borders.addNewRight();
        rightBorder.setVal(STBorder.SINGLE);
        rightBorder.setSz(BigInteger.valueOf(4));
        rightBorder.setColor("000000");
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1214011.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【计算机网络笔记】DHCP协议

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

35 _ Trie树:如何实现搜索引擎的搜索关键词提示功能?

搜索引擎的搜索关键词提示功能,我想你应该不陌生吧?为了方便快速输入,当你在搜索引擎的搜索框中,输入要搜索的文字的某一部分的时候,搜索引擎就会自动弹出下拉框,里面是各种关键词提示。你可以直接从下拉框中选择你要搜索的东西,而不用把所有内容都输入进去,一定程度上…

C++二分查找算法:132 模式解法二枚举2

题目及解法一&#xff1a; https://blog.csdn.net/he_zhidan/article/details/134362273 分析 第一步&#xff0c;选择各3对应的1&#xff0c;如果有多个符合对应最小的1&#xff0c;记录num[0,j)中的最小值iMin&#xff0c;如果nums[j]大于iMin&#xff0c;则m3To1 [nums[j…

认知升级:模型与范式转换

你好&#xff0c;我是 EarlGrey&#xff0c;一名双语学习者&#xff0c;会一点编程&#xff0c;目前已翻译出版《Python 无师自通》、《Python 并行编程手册》等书籍。 点击上方蓝字关注我&#xff0c;持续获取编程干货、好书推荐和高效工具分享&#xff0c;一起提升认知和思维…

excel中正态分布函数NORM.DIST和NORMDIST,以及它们之间的区别

NORM.DIST和NORMDIST的区别 NORM.DIST和NORMDIST函数都可以返回正态分布的概率密度、或者正态累积分布。 根据微软官网上的说法&#xff0c;NORMDIST函数已经不建议使用了&#xff0c;它已经被一个或者几个新的函数代替&#xff08;例如NORM.DIST&#xff09;&#xff0c;这些…

Rust图形界面编程:egui平直布局

文章目录 平直布局with_layout 平直布局 在前面的示例中&#xff0c;已经用到了ui.horizontal用来布局&#xff0c;其特点是水平摆放控件。相应地&#xff0c;ui.vertical则是垂直摆放控件。根据控件的摆放顺序不同&#xff0c;这两个布局组件衍生出一系列布局函数 horizonta…

深入Rust:探索所有权和借用机制

大家好&#xff01;我是lincyang。 今天&#xff0c;我们将一起深入探索Rust语言中的一个核心概念&#xff1a;所有权和借用机制。 这些特性是Rust区别于其他语言的重要特点&#xff0c;它们在内存管理和并发编程中扮演着关键角色。 一、Rust所有权机制 1. 什么是所有权&#x…

Java --- JVM之StringTable

目录 一、String的基本特性 二、String的内存分配 2.1、String内存分布图 三、字符串拼接操作 3.1、字符串拼接操作底层原理 3.2、拼接操作与append操作效率对比 四、intern()方法 4.1、intern()效率 五、StringTable的垃圾回收 一、String的基本特性 1、String字符…

C++二分查找算法:数组中占绝大多数的元素

题目 设计一个数据结构&#xff0c;有效地找到给定子数组的 多数元素 。 子数组的 多数元素 是在子数组中出现 threshold 次数或次数以上的元素。 实现 MajorityChecker 类: MajorityChecker(int[] arr) 会用给定的数组 arr 对 MajorityChecker 初始化。 int query(int left, …

【算法】区间(差分约束)

题目 给定 n 个区间 [ai,bi] 和 n 个整数 ci。 你需要构造一个整数集合 Z&#xff0c;使得 ∀i∈[1,n]&#xff0c;Z 中满足 ai≤x≤bi 的整数 x 不少于 ci 个。 求这样的整数集合 Z 最少包含多少个数。 输入格式 第一行包含整数 n。 接下来 n 行&#xff0c;每行包含三个…

21 Linux 自带的LED驱动

一、Linux 自带 LED 驱动使能 其实 Linux 内核自带 LED 抢夺那个&#xff0c;但在此之前需要配置 Linux 驱动来使能 LED 驱动。 输入以下命令&#xff1a; cd linux/atk-mpl/linux/my_linux/linux-5.4.31 make menuconfig 根据以下路径找到 LED 驱动&#xff1a; → Device D…

622.设计循环队列(LeetCode)

思路 先确定什么情况为空&#xff0c;什么情况为满。 这里有两种解决方案&#xff0c; 1.留一个空间空置&#xff0c;当rear1 front时 &#xff0c;则队列为满 &#xff08;这里我们选用方案一&#xff09; 2.增加一个size变量记录数据个数&#xff0c;size 0则为空&#xff…

asp.net数字档案管理系统VS开发sqlserver数据库web结构c#编程web网页设计

一、源码特点 asp.net 数字档案管理系统 是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语 言开发。 asp.net数字档案系统1 应用技…

通过右键用WebStorm、Idea打开某个文件夹或者在某一文件夹下右键打开当前文件夹用上述两个应用

通过右键用WebStorm、Idea打开某个文件夹或者在某一文件夹下右键打开当前文件夹用上述两个应用 通过右键点击某个文件夹用Idea打开 首先打开注册表 win R 输入 regedit 然后找到HKEY_CLASSES_ROOT\Directory\shell 然后右键shell 新建一个项名字就叫 Idea 第一步&#xf…

【FPGA】zynq 单端口RAM 双端口RAM 读写冲突 写写冲突

RAMRAM读写分类RAM原理及实现RAM三种读写模式不变模式写优先读优先 单端口 RAM伪双端口 RAM真双端口 RAM读写冲突和写写冲突读写冲突写写冲突总结&#xff1a; RAM RAM 的英文全称是 Random Access Memory&#xff0c;即随机存取存储器&#xff0c;简称随机存储器&#xff0c;…

ProtoBuf的学习和使用(C++)

ProtoBuf的学习和使用---C ⼀、初识ProtoBuf序列化和反序列化的概念ProtoBuf是什么?ProtoBuf工作特点 二、主要学习思路三、快速上手四、proto3语法详解1.字段规则2.消息类型的定义与使⽤实际操练 3.enum枚举类型enum注意事项enum实操 4.Any类型Any类型实操 5.oneof类型oneof类…

滴滴 Redis 异地多活的演进历程

为了更好的做好容灾保障&#xff0c;使业务能够应对机房级别的故障&#xff0c;滴滴的存储服务都在多机房进行部署。本文简要分析了 Redis 实现异地多活的几种思路&#xff0c;以及滴滴 Redis 异地多活架构演进过程中遇到的主要问题和解决方法&#xff0c;抛砖引玉&#xff0c;…

Unity Meta Quest 一体机开发(六):HandGrabInteractor 和 HandGrabInteractable 知识点

文章目录 &#x1f4d5;教程说明&#x1f4d5;HandGrabInteractor⭐HandGrabAPI⭐HandWristPoint⭐GripPoint⭐PinchPoint⭐PinchArea⭐HandGrabVisual⭐HandGrabGlow &#x1f4d5;HandGrabInteractable⭐Support Grab Type⭐Pinch Grab Rules 和 Palm Grab Rules⭐Unselect M…

【SpringBoot3+Vue3】三【实战篇】-后端(优化)

目录 一、登录优化-redis 1、SpringBoot集成redis 1.1 pom 1.2 yml 1.3 测试程序&#xff08;非必须&#xff09; 1.4 启动redis&#xff0c;执行测试程序 2、令牌主动失效&#xff08;代码优化&#xff09; 2.1 UserController设置token到redis 2.2 登录拦截器Log…

下载huggingface预训练模型到本地并调用

写在前面 在大模型横行的时代&#xff0c;无法在服务器上连接外网的研究僧真的是太苦逼了&#xff0c;每次想尝试类似于CLIP&#xff0c;BLIP之类的大模型都会得到“requests.exceptions.ConnectionError: (MaxRetryError("HTTPSConnectionPool(host‘huggingface.co’, …