diff --git a/src/main/java/xyz/wbsite/jmacro/util/TableData.java b/src/main/java/xyz/wbsite/jmacro/util/TableData.java
new file mode 100644
index 0000000..10667c2
--- /dev/null
+++ b/src/main/java/xyz/wbsite/jmacro/util/TableData.java
@@ -0,0 +1,329 @@
+package xyz.wbsite.jmacro.util;
+
+
+import javax.imageio.ImageIO;
+import javax.swing.*;
+import java.awt.*;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 表格工具 - Builder模式实现
+ *
+ * 用法:
+ * TableData.create()
+ * ㅤ.addHead("姓名", "年龄", "职业")
+ * ㅤ.addData("张三", "25", "工程师")
+ * ㅤ.addData("李四", "30", "产品经理")
+ * ㅤ.writeToFile(new File("table.png"));
+ *
+ * @author wangbing
+ * @version 0.0.1
+ * @since 1.8
+ */
+public class TableData {
+ /**
+ * 默认字体
+ */
+ private static final Font DEFAULT_FONT = new Font(null, Font.PLAIN, 14);
+
+ /**
+ * 表格表头
+ */
+ private final List head = new ArrayList<>();
+
+ /**
+ * 表格数据行
+ */
+ private final List> body = new ArrayList<>();
+
+ /**
+ * 私有构造函数
+ */
+ private TableData() {
+
+ }
+
+ /**
+ * 创建TableData构建器实例
+ *
+ * @return TableData.Builder实例
+ */
+ public static TableData create() {
+ return new TableData();
+ }
+
+ /**
+ * 添加表头
+ *
+ * @param headers 表头数组
+ * @return Builder实例
+ */
+ public TableData addHead(String... headers) {
+ this.head.addAll(Arrays.asList(headers));
+ return this;
+ }
+
+ /**
+ * 添加数据行
+ *
+ * @param rowData 行数据数组
+ * @return Builder实例
+ */
+ public TableData addData(String... rowData) {
+ List row = new ArrayList<>(Arrays.asList(rowData));
+ this.body.add(row);
+ return this;
+ }
+
+ private String[][] convertToArrays() {
+ // 验证数据完整性
+ if (head.isEmpty()) {
+ throw new IllegalStateException("必须添加表头");
+ }
+
+ int rows = this.body.size() + 1;
+ int cols = this.head.size();
+
+ String[][] data = new String[rows][cols];
+
+ // 填充表头
+ for (int j = 0; j < cols; j++) {
+ data[0][j] = this.head.get(j);
+ }
+
+ // 填充数据行
+ for (int i = 0; i < this.body.size(); i++) {
+ List row = this.body.get(i);
+ for (int j = 0; j < cols; j++) {
+ data[i + 1][j] = row.get(j);
+ }
+ }
+
+ return data;
+ }
+
+ /**
+ * 计算每列的宽度
+ *
+ * @param data 表格数据
+ * @return 每列的宽度数组
+ */
+ private int[] calculateColumnWidths(String[][] data) {
+ int rows = data.length;
+ int cols = data[0].length;
+
+ // 创建临时Graphics2D对象用于测量文本
+ BufferedImage tempImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
+ Graphics2D tempG2D = tempImage.createGraphics();
+ tempG2D.setFont(DEFAULT_FONT);
+ FontMetrics metrics = tempG2D.getFontMetrics();
+
+ // 计算每列的最大宽度
+ int[] colWidths = new int[cols];
+ for (int j = 0; j < cols; j++) {
+ int maxWidth = 0;
+ for (int i = 0; i < rows; i++) {
+ int textWidth = metrics.stringWidth(data[i][j]);
+ if (textWidth > maxWidth) {
+ maxWidth = textWidth;
+ }
+ }
+ colWidths[j] = maxWidth + 20; // 添加内边距
+ }
+
+ tempG2D.dispose();
+ tempImage.flush();
+
+ return colWidths;
+ }
+
+ /**
+ * 根据表格内容计算合适的图像尺寸
+ *
+ * @return 推荐的图像尺寸
+ */
+ private Dimension calculateTableDimension() {
+ // 将数据转换为二维数组格式
+ String[][] data = convertToArrays();
+
+ int rows = data.length;
+
+ // 计算每列的宽度
+ int[] colWidths = calculateColumnWidths(data);
+
+ // 创建临时Graphics2D对象用于测量文本高度
+ BufferedImage tempImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
+ Graphics2D tempG2D = tempImage.createGraphics();
+ tempG2D.setFont(DEFAULT_FONT);
+ FontMetrics metrics = tempG2D.getFontMetrics();
+
+ // 计算每行的高度(基于字体高度) 添加一些内边距
+ int rowHeight = metrics.getHeight() + 10;
+
+ // 计算总宽度和高度
+ int totalWidth = 0;
+ for (int width : colWidths) {
+ totalWidth += width;
+ }
+ int totalHeight = rowHeight * rows;
+ // 确保最小尺寸
+ totalWidth = Math.max(totalWidth, 100) + 1;
+ totalHeight = Math.max(totalHeight, 100) + 1;
+ tempG2D.dispose();
+ tempImage.flush();
+ return new Dimension(totalWidth, totalHeight);
+ }
+
+ /**
+ * 绘制表格图片
+ *
+ * @return 表格图片
+ */
+ private BufferedImage drawTable() {
+ // 将数据转换为二维数组格式
+ String[][] data = convertToArrays();
+
+ // 计算自适应的图像尺寸
+ Dimension dimension = calculateTableDimension();
+ int width = dimension.width;
+ int height = dimension.height;
+ // 创建图像
+ BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g2d = image.createGraphics();
+ // 设置背景色为白色
+ g2d.setColor(Color.WHITE);
+ g2d.fillRect(0, 0, width, height);
+ // 设置画笔颜色(边框和文字)
+ g2d.setColor(Color.BLACK);
+ g2d.setFont(DEFAULT_FONT);
+ // 计算行列数
+ int rows = data.length;
+ int cols = data[0].length;
+ // 计算单元格宽度(按内容比例分配)
+ int[] colWidths = calculateColumnWidths(data);
+ int totalPreferredWidth = 0;
+
+ for (int widthValue : colWidths) {
+ totalPreferredWidth += widthValue;
+ }
+
+ // 如果总推荐宽度大于实际宽度,则按比例调整
+ if (totalPreferredWidth > width) {
+ for (int j = 0; j < cols; j++) {
+ colWidths[j] = (int) ((double) colWidths[j] / totalPreferredWidth * width);
+ }
+ }
+
+ // 计算单元格高度(平均分配)
+ int cellHeight = height / rows;
+
+ // 绘制表格边框和内容
+ int y = 0;
+ for (int i = 0; i < rows; i++) {
+ int x = 0;
+ for (int j = 0; j < cols; j++) {
+ int cellWidth = colWidths[j];
+
+ // 绘制单元格边框
+ g2d.drawRect(x, y, cellWidth, cellHeight);
+
+ // 绘制单元格内容(居中显示)
+ String text = data[i][j];
+ FontMetrics fm = g2d.getFontMetrics();
+ int textX = x + (cellWidth - fm.stringWidth(text)) / 2;
+ int textY = y + (cellHeight + fm.getAscent()) / 2 - fm.getDescent();
+ g2d.drawString(text, textX, textY);
+
+ x += cellWidth;
+ }
+ y += cellHeight;
+ }
+
+ g2d.dispose();
+ return image;
+ }
+
+ /**
+ * 将图片写入文件
+ *
+ * @param file 目标文件
+ * @throws IOException 文件写入异常
+ */
+ public void writeToFile(File file) throws IOException {
+ BufferedImage tableImage = drawTable();
+ ImageIO.write(tableImage, "png", file);
+ }
+
+ /**
+ * 将图片复制到系统剪贴板
+ *
+ * @throws Exception 复制到剪贴板异常
+ */
+ public void writeToClipboard() throws Exception {
+ BufferedImage tableImage = drawTable();
+ copyImageToClipboard(tableImage);
+ }
+
+ /**
+ * 将图片转换为字节数组
+ *
+ * @return 图片字节数组
+ * @throws IOException 转换异常
+ */
+ public byte[] writeToByteArray() throws IOException {
+ BufferedImage tableImage = drawTable();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ImageIO.write(tableImage, "png", baos);
+ return baos.toByteArray();
+ }
+
+ /**
+ * 将图片复制到系统剪贴板
+ *
+ * @param image 要复制的图片
+ */
+ private static void copyImageToClipboard(BufferedImage image) {
+ try {
+ // 将BufferedImage转为ImageIcon(剪贴板支持的格式)
+ ImageIcon imageIcon = new ImageIcon(image);
+
+ // 创建剪贴板内容
+ Transferable transferable = new Transferable() {
+ @Override
+ public DataFlavor[] getTransferDataFlavors() {
+ return new DataFlavor[]{DataFlavor.imageFlavor};
+ }
+
+ @Override
+ public boolean isDataFlavorSupported(DataFlavor flavor) {
+ return DataFlavor.imageFlavor.equals(flavor);
+ }
+
+ @Override
+ public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
+ if (DataFlavor.imageFlavor.equals(flavor)) {
+ return imageIcon.getImage();
+ }
+ throw new UnsupportedFlavorException(flavor);
+ }
+ };
+
+ // 获取系统剪贴板并设置内容
+ Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+ clipboard.setContents(transferable, null);
+
+ } catch (Exception e) {
+ throw e;
+ }
+ }
+}