package application; import java.awt.BorderLayout; import java.awt.Desktop; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.naming.ConfigurationException; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.filechooser.FileNameExtensionFilter; import org.apache.commons.io.FilenameUtils; import de.lcag.common.ExcelWorkbook; import de.lcag.common.LcagProperties; import de.lcag.common.MappingTable; import de.lcag.common.Table; import de.lcag.common.WorkbookComparisonResult; import routines.LcagFileTools; import routines.LcagStringTools; public class FileActions extends JFrame { private static final int FRAME_HEIGHT = 150; private static String MASTER_FILE_LABEL = "Main Excel File"; private static String CONFIG_FILE_LABEL = "Configuration File"; private JLabel masterFileLabel, clientFileLabel, configFileLabel; private JButton selectMasterFile, selectClientFile, selectConfigFile; private Path configFile; private String masterFile, clientFile; private JMenuBar menuBar; private JMenu actionsMenu; private JMenuItem mergeAction; private JPopupMenu contextMenuMasterFile, contextMenuClientFile; private File configFileDirectoryPath = null; private LcagProperties config = null; private File masterDirecory = null; private File clientDirecory = null; private static List SUPPORTED_FILE_TYPES = List.of("xls", "xlsx"); public FileActions() { setTitle("Compare 2 Excel Files"); setSize(800, FRAME_HEIGHT); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel mainPanel = new JPanel(new BorderLayout()); JPanel leftButtonPanel = new JPanel(new GridLayout(3, 1, 5, 5)); JPanel rightTextPanel = new JPanel(new GridLayout(3, 1, 5, 5)); // setLayout(new GridLayout(4, 2)); leftButtonPanel.setPreferredSize(new Dimension(200, FRAME_HEIGHT)); // Fixed width // Add an empty border to create a gap on the right side of leftPanel leftButtonPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10)); // right gap: 10px rightTextPanel.setPreferredSize(new Dimension(1000, FRAME_HEIGHT)); mainPanel.add(leftButtonPanel, BorderLayout.WEST); mainPanel.add(rightTextPanel, BorderLayout.EAST); configFileLabel = new JLabel(String.format(" %s: Not selected", CONFIG_FILE_LABEL)); selectConfigFile = new JButton("Select " + CONFIG_FILE_LABEL); leftButtonPanel.add(selectConfigFile); rightTextPanel.add(configFileLabel); // File Chooser for config file selectConfigFile.setEnabled(true); selectConfigFile.addActionListener(e -> { if (!configFileDirectoryPath.isDirectory()) { System.err.println(String.format("ERROR: Config directory %s does not exist", configFileDirectoryPath.getAbsolutePath())); System.exit(1); } JFileChooser fileChooser = new JFileChooser(configFileDirectoryPath); FileNameExtensionFilter filter = new FileNameExtensionFilter("Config Files", "properties"); fileChooser.setFileFilter(filter); if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { String clientDirString = null; configFile = Path.of(selectFile(fileChooser)); config = new LcagProperties(configFile.toString()); configFileLabel.setText(String.format(" %s: %s", CONFIG_FILE_LABEL, configFile)); masterFile = config.getOptionalProperty("main_file"); if (masterFile != null) { String masterFilePath = LcagFileTools.getPath(masterFile); masterFile = LcagFileTools.getName(masterFile); masterDirecory = new File(masterFilePath); masterFileLabel.setText(String.format("Selected: %s
in: %s", masterFile, masterDirecory.getAbsolutePath())); selectMasterFile.setEnabled(true); } clientFile = config.getOptionalProperty("compare_file"); if (clientFile != null) { String clientFilePath = LcagFileTools.getPath(clientFile); clientFile = LcagFileTools.getName(clientFile); clientDirecory = new File(clientFilePath); if (clientDirecory.isAbsolute()) { clientDirString = clientFilePath; } else { clientDirString = "same directory as 1st file"; } clientFileLabel.setText( String.format("Selected: %s
in: %s ", clientFile, clientDirString)); selectClientFile.setEnabled(true); } // After user selected a config file enable buttons to set files to compare (can // overwrite files listed in config file): } }); // Kontextmenüs erstellen contextMenuMasterFile = new JPopupMenu(); contextMenuClientFile = new JPopupMenu(); JMenuItem renameFile1 = new JMenuItem("Rename File"); JMenuItem renameFile2 = new JMenuItem("Rename File"); contextMenuMasterFile.add(renameFile1); contextMenuClientFile.add(renameFile2); masterFileLabel = new JLabel( String.format(" %s: %s", MASTER_FILE_LABEL, masterFile == null ? "Not selected" : masterFile)); selectMasterFile = new JButton("Select " + MASTER_FILE_LABEL); leftButtonPanel.add(selectMasterFile); rightTextPanel.add(masterFileLabel); clientFileLabel = new JLabel( String.format(" %s: %s", "Excel to compare", clientFile == null ? "Not selected" : clientFile)); selectClientFile = new JButton("Select Excel to Compare"); // MouseListener für Kontextmenü auf den Labels masterFileLabel.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (SwingUtilities.isRightMouseButton(e) && masterFile != null) { contextMenuMasterFile.show(masterFileLabel, e.getX(), e.getY()); } } }); clientFileLabel.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (SwingUtilities.isRightMouseButton(e) && clientFile != null) { contextMenuClientFile.show(clientFileLabel, e.getX(), e.getY()); } } }); leftButtonPanel.add(selectClientFile); rightTextPanel.add(clientFileLabel); renameFile1.addActionListener(e -> renameFile(masterFile, masterFileLabel, "Datei 1")); renameFile2.addActionListener(e -> renameFile(clientFile, clientFileLabel, "Datei 2")); // File Chooser für Datei 1 (nur Excel-Dateien) selectMasterFile.setEnabled(false); selectMasterFile.addActionListener(e -> { JFileChooser fileChooser = new JFileChooser(); FileNameExtensionFilter filter = new FileNameExtensionFilter("Excel-Files", SUPPORTED_FILE_TYPES.toArray(new String[0])); fileChooser.setFileFilter(filter); if (masterFile != null) { Path masterFilePath = Path.of(masterFile); masterDirecory = new File(masterFilePath.getParent().toString()); fileChooser.setCurrentDirectory(masterDirecory); masterDirecory = new File(masterFilePath.getParent().toString()); masterFileLabel.setText(String.format("Selected: %s
in: %s", masterFile, masterFilePath.getParent().toString())); selectClientFile.setEnabled(true); } if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { Path masterFilePath = Path.of(masterFile); masterFile = selectFile(fileChooser); masterDirecory = new File(masterFilePath.getParent().toString()); masterFileLabel.setText(String.format(" %s: %s", MASTER_FILE_LABEL, masterFilePath.getFileName())); selectClientFile.setEnabled(true); } }); // File Chooser für Datei 2 (im selben Verzeichnis wie Datei 1, nur // Excel-Dateien) selectClientFile.setEnabled(false); selectClientFile.addActionListener(e -> { if (masterDirecory != null) { JFileChooser fileChooser = new JFileChooser(masterDirecory); FileNameExtensionFilter filter = new FileNameExtensionFilter("Excel-Dateien", "xls", "xlsx"); fileChooser.setFileFilter(filter); if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { clientFile = selectFile(fileChooser); clientFileLabel.setText("Datei 2: " + clientFile); } } }); // Menü erstellen menuBar = new JMenuBar(); actionsMenu = new JMenu("Actions"); mergeAction = new JMenuItem("Merge 2nd into Main file"); mergeAction.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, ActionEvent.CTRL_MASK)); mergeAction.addActionListener(e -> { System.out.println("Ctrl-C pressed on menu"); }); actionsMenu.add(mergeAction); menuBar.add(actionsMenu); setJMenuBar(menuBar); // Aktion: Erste Datei in Excel öffnen mergeAction.addActionListener(e -> { mergeFiles(config, masterFile, clientFile); }); add(mainPanel); pack(); setVisible(true); } private String selectFile(JFileChooser fileChooser) { File result = fileChooser.getSelectedFile(); return FilenameUtils.separatorsToUnix(result.getAbsolutePath()); } private void mergeFiles(LcagProperties pConfig, String pMasterFilePathPattern, String pClientFilePathPattern) { Pattern masterPattern = Pattern.compile(pMasterFilePathPattern); List masterFiles = new ArrayList<>(); String masterDirectoryPathStr = masterDirecory.getAbsolutePath(); try { Path masterDirectoryPath = Path.of(masterDirectoryPathStr); masterFiles = Files.walk(masterDirectoryPath).filter(p -> { String filePath = FilenameUtils.separatorsToUnix(p.toString()); String fileName = LcagFileTools.getName(p.toString()); Matcher matcher = masterPattern.matcher(fileName); boolean matches = matcher.matches(); return matches; }).toList(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (pConfig == null) { JOptionPane.showMessageDialog(this, "Pls select at least a config file!", "Error", JOptionPane.ERROR_MESSAGE); return; } for (Path aMasterFilePath : masterFiles) { String masterFileName = aMasterFilePath.getFileName().toString(); String fileType = LcagFileTools.getExtension(masterFileName); if (!SUPPORTED_FILE_TYPES.contains(fileType)) { System.err.printf("Comparision of file type %s not supported for %s\n", fileType, masterFileName); continue; } String s = FilenameUtils.separatorsToUnix(aMasterFilePath.normalize().toString()); String clientFilePathStr = clientDirecory.getAbsolutePath() + "/" + masterFileName.replaceFirst(pMasterFilePathPattern, pClientFilePathPattern); Path clientFilePath = Path.of(clientFilePathStr); String clientDirString = null; if (clientFilePath.isAbsolute()) { clientDirString = clientFilePath.getParent().toString(); } else { // client file is relative expect it is same directory as master Path dirPath = aMasterFilePath.getParent(); clientDirString = "same directory as 1st file"; clientFilePath = dirPath.resolve(clientFilePath); } if (clientFilePath != null) { String fileName = clientFilePath.getFileName().toString(); clientFileLabel .setText(String.format("Selected: %s
in: %s", fileName, clientDirString)); selectClientFile.setEnabled(true); } String keyFieldString = pConfig.getProperty("list_of_keys"); List keyFields = LcagStringTools.asList(keyFieldString, ",\\s*"); if (aMasterFilePath != null && clientFilePath != null) { try { Path resultFilePath = LcagFileTools.appendStringToFilePath(aMasterFilePath, "-merged"); String fieldMapping = pConfig.getProperty("column.mapping.main2compare"); Files.copy(aMasterFilePath, resultFilePath, StandardCopyOption.REPLACE_EXISTING); ExcelWorkbook excel1 = new ExcelWorkbook(resultFilePath.toString()); ExcelWorkbook excel2 = new ExcelWorkbook(clientFilePath.toString()); excel1.setKeyColumns(keyFields); excel1.read(); excel2.setKeyColumns(keyFields); excel2.read(); excel1.setOption(keyFieldString, FRAME_HEIGHT); if (fieldMapping != null) { MappingTable mappingTable = new MappingTable(fieldMapping, ";", "->"); excel2.setOption(Table.OPTION_USE_MAPPING, mappingTable); } WorkbookComparisonResult compareResult = excel1.compareTo(excel2); if (compareResult.tablesAreEquals()) { System.out.printf("RESULT: Tables %s and %s are equal.\n", resultFilePath, clientFilePath); } else { ExcelWorkbook integratedTable = (ExcelWorkbook) compareResult.integrateDifferencesIntoMaster(); integratedTable.save(); Desktop.getDesktop().open(resultFilePath.toFile()); } } catch (IOException ex) { JOptionPane.showMessageDialog(this, "Cannot open comparison result file.", "Error", JOptionPane.ERROR_MESSAGE); } catch (ConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } private Path getPath(LcagProperties config, String pProperty, File pMasterFile) { Path result = null; String filePathString = (pMasterFile == null) ? config.getProperty(pProperty) : pMasterFile.getAbsolutePath(); if (!LcagStringTools.isEmpty(filePathString)) { result = Path.of(filePathString); } return result; } private Path renameFile(String pFile, JLabel label, String prefix) { Path newPath = null; if (pFile == null) return newPath; File file = new File(pFile.toString()); String newName = JOptionPane.showInputDialog(this, "Enter new name:", file.getName()); if (!LcagStringTools.isEmpty(newName)) { Path filePath = Path.of(pFile); newPath = filePath.getParent().resolve(newName); File newFile = new File(newPath.toString()); if (file.renameTo(newFile)) { file = newFile; label.setText(prefix + ": " + newFile.getName()); if (prefix.equals("Datei 1")) this.masterFile = newPath.toString(); else this.clientFile = newPath.toString(); } else { JOptionPane.showMessageDialog(this, "Umbenennung fehlgeschlagen!", "Fehler", JOptionPane.ERROR_MESSAGE); } } return newPath; } public static void main(String[] args) { String cfgFileDirectory = args.length < 1 ? System.getenv("_MY_DATA") + "/Tools" : args[0]; SwingUtilities.invokeLater(() -> { FileActions gui = new FileActions(); gui.configFileDirectoryPath = new File(cfgFileDirectory); gui.setVisible(true); }); } }