• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jiangxincode / ApkToolBoxGUI / #1428

21 Apr 2026 03:41PM UTC coverage: 3.42% (-0.03%) from 3.452%
#1428

push

jiangxincode
feat: add export to Excel functionality for result panels

- Add ExcelExporter utility class with XSSFWorkbook-based .xlsx export
- Add right-click context menu 'Export to Excel' in PdfStatPanel
- Add right-click context menu 'Export to Excel' in PdfFinderPanel
- Add right-click context menu 'Export to Excel' in WordStatPanel
- Add right-click context menu 'Export to Excel' in DuplicateSearchPanel

0 of 69 new or added lines in 5 files covered. (0.0%)

4 existing lines in 4 files now uncovered.

250 of 7311 relevant lines covered (3.42%)

0.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main/java/edu/jiangxin/apktoolbox/utils/ExcelExporter.java
1
package edu.jiangxin.apktoolbox.utils;
2

3
import org.apache.logging.log4j.LogManager;
4
import org.apache.logging.log4j.Logger;
5
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
6
import org.apache.poi.ss.usermodel.Row;
7
import org.apache.poi.ss.usermodel.Sheet;
8

9
import javax.swing.*;
10
import javax.swing.filechooser.FileNameExtensionFilter;
11
import javax.swing.table.TableModel;
12
import java.awt.*;
13
import java.io.File;
14
import java.io.FileOutputStream;
15
import java.io.IOException;
16

17
/**
18
 * 工具类:将 JTable 的 TableModel 数据导出为 .xlsx 文件。
19
 */
20
public class ExcelExporter {
21

NEW
22
    private static final Logger logger = LogManager.getLogger(ExcelExporter.class);
×
23

24
    private ExcelExporter() {
25
        // 工具类,禁止实例化
26
    }
27

28
    /**
29
     * 完整导出流程:空数据检查 → 文件选择 → 写文件 → 结果提示。
30
     * 必须在 EDT 中调用。
31
     *
32
     * @param tableModel      数据来源
33
     * @param defaultFileName 文件保存对话框的默认文件名,例如 "pdf_stat_export.xlsx"
34
     * @param parent          父组件,用于对话框定位
35
     */
36
    public static void export(TableModel tableModel, String defaultFileName, Component parent) {
NEW
37
        if (tableModel.getRowCount() == 0) {
×
NEW
38
            SwingUtilities.invokeLater(() ->
×
NEW
39
                JOptionPane.showMessageDialog(parent, "当前没有可导出的数据", "提示", JOptionPane.INFORMATION_MESSAGE));
×
NEW
40
            return;
×
41
        }
42

NEW
43
        JFileChooser fileChooser = new JFileChooser();
×
NEW
44
        fileChooser.setDialogTitle("保存 Excel 文件");
×
NEW
45
        fileChooser.setFileFilter(new FileNameExtensionFilter("Excel 文件 (*.xlsx)", "xlsx"));
×
NEW
46
        fileChooser.setSelectedFile(new File(defaultFileName));
×
47

NEW
48
        int result = fileChooser.showSaveDialog(parent);
×
NEW
49
        if (result != JFileChooser.APPROVE_OPTION) {
×
NEW
50
            return;
×
51
        }
52

NEW
53
        File selectedFile = fileChooser.getSelectedFile();
×
54
        // 自动追加 .xlsx 后缀
NEW
55
        if (!selectedFile.getName().toLowerCase().endsWith(".xlsx")) {
×
NEW
56
            selectedFile = new File(selectedFile.getAbsolutePath() + ".xlsx");
×
57
        }
NEW
58
        final File targetFile = selectedFile;
×
59

60
        // 在后台线程写文件,避免阻塞 EDT
NEW
61
        final TableModel modelSnapshot = tableModel;
×
NEW
62
        new Thread(() -> {
×
63
            try {
NEW
64
                writeToFile(modelSnapshot, targetFile);
×
NEW
65
                final String absolutePath = targetFile.getAbsolutePath();
×
NEW
66
                SwingUtilities.invokeLater(() ->
×
NEW
67
                    JOptionPane.showMessageDialog(parent, "导出成功:" + absolutePath, "成功", JOptionPane.INFORMATION_MESSAGE));
×
NEW
68
            } catch (IOException e) {
×
NEW
69
                logger.error("导出 Excel 失败", e);
×
NEW
70
                final String errorMsg = e.getMessage();
×
NEW
71
                SwingUtilities.invokeLater(() ->
×
NEW
72
                    JOptionPane.showMessageDialog(parent, "导出失败:" + errorMsg, "错误", JOptionPane.ERROR_MESSAGE));
×
NEW
73
            }
×
NEW
74
        }).start();
×
NEW
75
    }
×
76

77
    /**
78
     * 将 TableModel 数据写入指定文件(在后台线程调用)。
79
     */
80
    static void writeToFile(TableModel tableModel, File targetFile) throws IOException {
NEW
81
        try (XSSFWorkbook workbook = new XSSFWorkbook()) {
×
NEW
82
            Sheet sheet = workbook.createSheet("Sheet1");
×
83

84
            // 写表头
NEW
85
            Row headerRow = sheet.createRow(0);
×
NEW
86
            for (int col = 0; col < tableModel.getColumnCount(); col++) {
×
NEW
87
                headerRow.createCell(col).setCellValue(tableModel.getColumnName(col));
×
88
            }
89

90
            // 写数据行
NEW
91
            for (int row = 0; row < tableModel.getRowCount(); row++) {
×
NEW
92
                Row dataRow = sheet.createRow(row + 1);
×
NEW
93
                for (int col = 0; col < tableModel.getColumnCount(); col++) {
×
NEW
94
                    Object value = tableModel.getValueAt(row, col);
×
NEW
95
                    dataRow.createCell(col).setCellValue(value == null ? "" : value.toString());
×
96
                }
97
            }
98

NEW
99
            try (FileOutputStream fos = new FileOutputStream(targetFile)) {
×
NEW
100
                workbook.write(fos);
×
101
            }
102
        }
NEW
103
    }
×
104
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc