0

I've designed a program in which:

  • user selects their input directory, the source of the shapefiles
  • user selects their output folder, where their file will end up
  • user names their resulting Excel Workbook
  • the program then runs through the shapefiles in the input directory, and produces an Excel Workbook of calculations

This program works great when run in Eclipse, but I need it to function as an ArcCatalog add-in. (I have access to ArcGIS Desktop, NOT ArcGIS Runtime or ArcGIS Pro)

The first class enables the ArcCatalog button, which works great:

package workbookbuilder;

import java.io.IOException;

import com.esri.arcgis.addins.desktop.Button;
import com.esri.arcgis.framework.IApplication;
import com.esri.arcgis.interop.AutomationException;

public class ArcCatButton extends Button {

    private String[] args;
    static IApplication app;

    public void init(IApplication app) {
        this.app = app;

    }

    public void onClick() throws IOException, AutomationException {

        init(app);
        ArcCatButton.main(args);
    }

    public static void main(String[] args) {

        UserFolderChooser userFolderChooser = new UserFolderChooser(app);
    }
}

This first class works as expected, deployment to ArcCatalog goes well, even chosen image appears as icon, etc.

The NEXT class, UserFolderChooser, is the problem. This Java Swing class completely skips over the call to the next class, and I have no idea why. Everything is 1 thread. I've done debugging and used the ArcCatalog caption & status bar as a pseudo-log to see if my user input is coming through.

What causes my program to NOT call the next class, ExcelSpreadsheetBuilder?

(That line stand out considerable in code below)

package workbookbuilder;

/*
 * This Java Swing class produces 
 * 3 pop-up windows so the user may: 
 * 1. set their root directory, the 
 * location of the files for running this program
 * 2. set the destination of their output, 
 * to find the resulting Excel Workbook
 * 3. Name their Excel file
 */
import java.util.Scanner;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import java.io.File;
import java.io.IOException;

import javax.swing.JFileChooser;
import javax.swing.filechooser.FileSystemView;

import com.esri.arcgis.framework.IApplication;
import com.esri.arcgis.interop.AutomationException;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class UserFolderChooser {
    private String operatingSystem;
    private char Windows = 'W';
    private char Linux = 'L';
    private char OS = 'O';
    private char macOS = 'm';
    private File userInputChoice1;
    private File userInputChoice2;
    private String userInputRootDirectory;
    private String workbookDestinationFolderUserChoice;
    private String userInputWbName;
    private JFrame jframe = new JFrame("AOI Spreadsheet Builder");
    private Box vertBox;
    private JButton jbtn;
    private JButton closingButton;
    private JLabel space1;
    private JLabel space2;
    private JLabel space3;
    private JLabel space4;
    private JLabel jL1;
    private JLabel jL2;
    private JLabel jL3;
    private JLabel jL4;
    private JLabel jL6;
    private JLabel jL7;
    private JLabel jL8;
    private JLabel jL9;

    // constructor
    public UserFolderChooser(IApplication app) {

        chooseRootDir(app);
    }

    // first pop-up window
    private void chooseRootDir(IApplication app) {
        // identify the user's operating system
        operatingSystem = System.getProperty("os.name");
        System.out.println(System.getProperty("os.name"));

        // pop-up window 1: user chooses root directory
        JFileChooser rootDirChooser = new JFileChooser(FileSystemView.getFileSystemView());
        rootDirChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        rootDirChooser
                .setDialogTitle("Welcome to the AOI Spreadsheet Builder. \n In which folder are your files found?");

        // for window 1
        int returnValue = rootDirChooser.showOpenDialog(null);
        // this is the equivalent of button click action for FileChooser
        if (returnValue == JFileChooser.APPROVE_OPTION) {
            userInputChoice1 = rootDirChooser.getSelectedFile();
            userInputRootDirectory = userInputChoice1.getAbsolutePath();
            if (operatingSystem.charAt(0) == Windows) {
                userInputRootDirectory = userInputRootDirectory + "\\";
            } else if (operatingSystem.charAt(0) == Linux) {
                userInputRootDirectory = userInputRootDirectory + "/";
            } else if (operatingSystem.charAt(0) == OS || operatingSystem.charAt(0) == macOS) {
                userInputRootDirectory = userInputRootDirectory + "/";
            }
            System.out.println("user input root directory: " + userInputRootDirectory);
            chooseDestinationFolder(app);

        } else if (returnValue == JFileChooser.CANCEL_OPTION) {
            System.out.println("User canceled the process.");
        }
    }

    // second pop-up window
    public void chooseDestinationFolder(IApplication app) {

        JFileChooser outputFolderChooser = new JFileChooser(FileSystemView.getFileSystemView());
        outputFolderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        outputFolderChooser
                .setDialogTitle("Choose your destination folder - where would you like your spreadsheet to end up?");

        // for window 2
        int returnValue = outputFolderChooser.showOpenDialog(null);
        // this is the equivalent of button click action for FileChooser
        if (returnValue == JFileChooser.APPROVE_OPTION) {
            userInputChoice2 = outputFolderChooser.getSelectedFile();
            workbookDestinationFolderUserChoice = userInputChoice2.getAbsolutePath();
            if (operatingSystem.charAt(0) == Windows) {
                workbookDestinationFolderUserChoice = workbookDestinationFolderUserChoice + "\\";
            } else if (operatingSystem.charAt(0) == Linux) {
                workbookDestinationFolderUserChoice = workbookDestinationFolderUserChoice + "/";
            } else if (operatingSystem.charAt(0) == OS || operatingSystem.charAt(0) == macOS) {
                workbookDestinationFolderUserChoice = workbookDestinationFolderUserChoice + "/";
            }
            System.out.println("Spreadsheet's destination folder: " + workbookDestinationFolderUserChoice);
            nameSpreadsheet(app);

        } else if (returnValue == JFileChooser.CANCEL_OPTION) {

            System.out.println("User canceled the process.");
        }
    }

    public void closeProgram() {
        closingButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
    }

    // third pop-up window
    public void nameSpreadsheet(IApplication app) {
        Scanner scanner = new Scanner(System.in);
        // input
        JTextField textField = new JTextField("", 55);
        textField.setMaximumSize(textField.getPreferredSize());
        // 2 buttons
        jbtn = new JButton("name file");

        // center the JFrame in main display, even with multiiple screens
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        jframe.setLocationRelativeTo(null);
        jframe.setLocation(dim.width / 3 - jframe.getSize().width / 3, dim.height / 4 - jframe.getSize().height / 4);
        vertBox = Box.createVerticalBox();
        jframe.setSize(575, 325);
        jframe.setVisible(true);
        jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jframe.add(vertBox);

        // text display
        JLabel topSpace = new JLabel("                   ");
        jL1 = new JLabel(
                "This program will build an Excel Workbook for the VO End Product from the files found in: ");
        Font notBoldFont1 = new Font(jL1.getFont().getName(), ~Font.BOLD, jL1.getFont().getSize());
        jL1.setFont(notBoldFont1);
        jL2 = new JLabel("     " + userInputRootDirectory);
        Font notBoldFont2 = new Font(jL2.getFont().getName(), ~Font.BOLD, jL2.getFont().getSize());
        jL2.setFont(notBoldFont2);
        space1 = new JLabel("                              ");
        jL3 = new JLabel("Name your Excel file: ");
        jL4 = new JLabel(
                "(Try to avoid using the same name as a file that already exists in your destination folder.)");
        jL4.setForeground(Color.gray);
        space2 = new JLabel("                                  ");
        space4 = new JLabel("                      ");
        vertBox.add(topSpace);
        vertBox.add(jL1);
        vertBox.add(jL2);
        vertBox.add(space1);
        vertBox.add(jL3);
        vertBox.add(textField);
        vertBox.add(jL4);
        vertBox.add(space2);
        vertBox.add(jbtn);
        jframe.setVisible(true);

        jbtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                userInputWbName = textField.getText();
                try {
                    // sanity check to ensure user input is actually captured
                    app.setCaption("change the caption to: " + userInputWbName);
                    app.getStatusBar().setMessage(0, "we put a message here!" + workbookDestinationFolderUserChoice);
                } catch (AutomationException e2) {
                    e2.printStackTrace();
                } catch (IOException e2) {
                    e2.printStackTrace();
                }

                vertBox.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
                try {
                    // UI while user waits & program runs
                    // these UI wait texts do not work without another thread or a timer
                    // threads and timers are not compatible with ArcCatalog
                    space3 = new JLabel("                   ");
                    jL6 = new JLabel("Your workbook is building... :" + userInputWbName);
                    jbtn.setText(userInputWbName);
                    Font jL6ItalFont = new Font(jL6.getFont().getName(), Font.ITALIC, jL6.getFont().getSize());
                    jL6.setFont(jL6ItalFont);
                    vertBox.remove(jbtn);
                    vertBox.add(space3);
                    vertBox.add(jL6);
                    jL1.setText("This program is building the spreadsheet from the files found in: ");
                    jL1.setFont(jL6ItalFont);
                    jL2.setFont(jL6ItalFont);
                    jL1.setForeground(Color.lightGray);
                    jL2.setForeground(Color.lightGray);
                    jL3.setText("name of file: ");
                    jL4.setText("running through all .shp file data ... This may take a bit, not to worry.");
                    jL4.setForeground(Color.gray);
                    space1.setText("        sending result to:  " + workbookDestinationFolderUserChoice);
                    space1.setForeground(Color.lightGray);
                    space2.setText("   ( expect ~ 1-5 minutes ) ");
                    space2.setForeground(Color.lightGray);
                    Font notBoldFontSpace2 = new Font(space2.getFont().getName(), ~Font.BOLD, space2.getFont().getSize());
                    space2.setFont(notBoldFontSpace2);
                    System.out.println("Calling ExcelSpreadsheetBuilder");
                    /**********************************************************/
                    // here is what's missing, this next class (below) continues the program
                    // It's a simple Java class, using some apache jars to create an Excel Workbook
                    // currently, this line is completely skipped and ArcCatalog moves on to finally
                    /*************************************************************/
                    ExcelSpreadsheetBuilder excelSpreadsheetBuilder = new ExcelSpreadsheetBuilder(userInputRootDirectory, workbookDestinationFolderUserChoice, userInputWbName);
                } catch (Exception e1) {
                    e1.printStackTrace();
                    System.out.println("IOException caught in UserFolderChooser" + e1.getMessage());
                    space3.setText("Something's not right. Please check your chosen folders and try again.");
                } finally {
                    vertBox.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                    space2.setText("                                                ");
                    jL1.setText("This program built a spreadsheet from the files found in: ");
                    jL4.setText("Done! ");
                    jL4.setForeground(Color.black);
                    space1.setText("                                             ");
                    System.out.println("User has submitted Excel Workbook file name: " + userInputWbName);
                    jL6 = new JLabel("Please check your destination folder:  ");
                    jL7 = new JLabel("     " + workbookDestinationFolderUserChoice);
                    jL8 = new JLabel("           for your new file:  ");
                    jL9 = new JLabel("                              " + userInputWbName);
                    Font notBoldFont6 = new Font(jL6.getFont().getName(), ~Font.BOLD, jL6.getFont().getSize());
                    jL6.setFont(notBoldFont6);
                    jL7.setForeground(Color.blue);
                    Font notBoldFont8 = new Font(jL8.getFont().getName(), ~Font.BOLD, jL8.getFont().getSize());
                    jL8.setFont(notBoldFont8);
                    jL9.setForeground(Color.blue);
                    vertBox.add(space4);
                    closingButton = new JButton("Got it, Bye!");
                    vertBox.add(closingButton);
                    vertBox.remove(jL6);
                    vertBox.add(jL7);
                    vertBox.add(jL8);
                    vertBox.add(jL9);
                }
                closeProgram();
            }
        });
    }
}

(I know it's ugly, I had it all written in JavaFX, with a callback and progress bar, etc, before I knew that ArcGIS Desktop/ArcObjects do not support JavaFX. So then I had to scramble and re-write in swing, and get rid of callbacks, etc. I just need the program to run all the way through.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.