基于Apache POI的Java GUI产品编码生成功能实现咨询
解决方案与代码优化
以下是针对你的需求调整后的代码,解决了编码拼接、资源泄漏、输入验证等问题,确保能正确从Excel中读取对应数据并生成符合格式的产品编码:
import java.awt.*; import java.awt.event.*; import java.io.*; import javax.swing.*; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.*; public class ProductCodeGenerator extends JFrame implements ActionListener { private JLabel brandLabel, typeLabel, deliveryLabel, packageLabel, nameLabel, codeLabel; private JTextField brandField, typeField, deliveryField, packageField, nameField; private JButton generateButton; public ProductCodeGenerator() { // 创建GUI组件 brandLabel = new JLabel("品牌:"); typeLabel = new JLabel("类型:"); deliveryLabel = new JLabel("配送方式:"); packageLabel = new JLabel("包装:"); nameLabel = new JLabel("名称:"); codeLabel = new JLabel("产品编码:"); brandField = new JTextField(10); typeField = new JTextField(10); deliveryField = new JTextField(10); packageField = new JTextField(10); nameField = new JTextField(10); generateButton = new JButton("生成编码"); generateButton.addActionListener(this); // 添加组件到面板 JPanel panel = new JPanel(new GridLayout(6, 2)); panel.add(brandLabel); panel.add(brandField); panel.add(typeLabel); panel.add(typeField); panel.add(deliveryLabel); panel.add(deliveryField); panel.add(packageLabel); panel.add(packageField); panel.add(nameLabel); panel.add(nameField); panel.add(generateButton); panel.add(codeLabel); add(panel); // 设置窗口属性 setTitle("产品编码生成器"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(400, 200); setLocationRelativeTo(null); setVisible(true); } public void actionPerformed(ActionEvent e) { // 输入验证 if (brandField.getText().isEmpty() || typeField.getText().isEmpty() || deliveryField.getText().isEmpty() || packageField.getText().isEmpty() || nameField.getText().isEmpty()) { JOptionPane.showMessageDialog(this, "请填写所有输入项", "错误", JOptionPane.ERROR_MESSAGE); return; } try { // 读取用户输入 String brand = brandField.getText().trim(); String type = typeField.getText().trim(); String delivery = deliveryField.getText().trim(); String packageName = packageField.getText().trim(); String name = nameField.getText().trim(); // 读取Excel文件(使用try-with-resources自动关闭资源) try (FileInputStream file = new FileInputStream(new File("DITCO PRODUCT CODE.xlsx")); Workbook workbook = new XSSFWorkbook(file)) { Sheet sheet = workbook.getSheetAt(0); // 获取对应数据的行索引 int brandRowIndex = getRowIndexByColumnValue(sheet, "Marka", brand); int typeRowIndex = getRowIndexByColumnValue(sheet, "Tip", type); int deliveryRowIndex = getRowIndexByColumnValue(sheet, "Gönderim Tipi", delivery); int groupRowIndex = getRowIndexByColumnValue(sheet, "1-40 Bottle", packageName); // 检查索引是否有效 if (brandRowIndex == -1 || typeRowIndex == -1 || deliveryRowIndex == -1 || groupRowIndex == -1) { JOptionPane.showMessageDialog(this, "Excel中未找到匹配的输入项", "错误", JOptionPane.ERROR_MESSAGE); return; } // 提取产品序号(假设名称格式为P3、G8等,取数字部分) int productIndex; try { productIndex = Integer.parseInt(name.replaceAll("[^0-9]", "")); } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(this, "名称格式错误,请输入包含数字的名称", "错误", JOptionPane.ERROR_MESSAGE); return; } // 从Excel读取各部分编码 int brandCode = (int) sheet.getRow(brandRowIndex).getCell(0).getNumericCellValue(); int typeCode = (int) sheet.getRow(typeRowIndex).getCell(1).getNumericCellValue(); int deliveryCode = (int) sheet.getRow(deliveryRowIndex).getCell(2).getNumericCellValue(); // 计算组与产品的组合编码(组号*10 + 产品序号) int groupProductCode = groupRowIndex * 10 + productIndex; // 拼接成目标编码(确保配送码为两位,不足补零) String productCode = String.format("%d%d%02d%d", brandCode, typeCode, deliveryCode, groupProductCode); // 显示编码 codeLabel.setText("产品编码: " + productCode); } } catch (FileNotFoundException ex) { JOptionPane.showMessageDialog(this, "未找到Excel文件", "错误", JOptionPane.ERROR_MESSAGE); } catch (Exception ex) { JOptionPane.showMessageDialog(this, "生成编码失败: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE); ex.printStackTrace(); } } /** * 根据列名和单元格值,返回对应的行索引(从1开始) */ private int getRowIndexByColumnValue(Sheet sheet, String columnName, String value) { // 先找到目标列的索引 int columnIndex = -1; Row headerRow = sheet.getRow(0); if (headerRow == null) { return -1; } for (int i = 0; i < headerRow.getLastCellNum(); i++) { Cell cell = headerRow.getCell(i); if (cell != null && cell.getCellType() == CellType.STRING && cell.getStringCellValue().equals(columnName)) { columnIndex = i; break; } } if (columnIndex == -1) { return -1; } // 在目标列中查找匹配值的行 for (int i = 1; i <= sheet.getLastRowNum(); i++) { Row row = sheet.getRow(i); if (row == null) { continue; } Cell cell = row.getCell(columnIndex); if (cell != null) { String cellValue; if (cell.getCellType() == CellType.STRING) { cellValue = cell.getStringCellValue().trim(); } else if (cell.getCellType() == CellType.NUMERIC) { cellValue = String.valueOf((int) cell.getNumericCellValue()); } else { continue; } if (cellValue.equals(value)) { return i; } } } return -1; } public static void main(String[] args) { // 在EDT中启动GUI SwingUtilities.invokeLater(ProductCodeGenerator::new); } }
关键修改说明
- 编码拼接方式优化:使用
String.format进行字符串拼接,通过%02d确保配送方式编码始终为两位(比如配送码是3时,自动补零为03),完全匹配你需要的编码格式(如示例中的251183)。 - 资源自动管理:使用
try-with-resources语句自动关闭FileInputStream和Workbook,避免资源泄漏。 - 输入验证增强:增加空输入检查、名称格式验证,以及Excel索引有效性检查,通过弹窗提示用户错误,提升用户体验。
- 方法命名优化:将
getIndex重命名为getRowIndexByColumnValue,更清晰表达方法功能;同时优化了单元格值的读取逻辑,支持数值型和字符串型的单元格值匹配。 - GUI线程安全:使用
SwingUtilities.invokeLater启动GUI,符合Swing线程安全规范。
注意事项
- 确保Excel文件路径正确,若文件不在程序运行目录下,需使用绝对路径。
- Excel的结构需与代码逻辑匹配:
- 第一行为列名(如"Marka"对应品牌名称列);
- 品牌编码在品牌名称所在行的第0列;
- 类型编码在类型名称所在行的第1列;
- 配送方式编码在配送名称所在行的第2列;
- 包装对应的组号在包装名称所在行的对应列(代码中为"1-40 Bottle"列)。
内容的提问来源于stack exchange,提问作者AhmetArslan
相关产品推荐
相关产品推荐

