Просмотр банковских выписок

Java, Swing (Single document interface)

Мой знакомый получает банковские выписки в текстовом формате, где каждое поле задаётся парой ключ-значение. Эти файлы он загружает в информационную систему. Иногда возникают проблемы: то дата платежа в выписке указана в странном формате, то вместо ИНН загружается ОКАТО, а то и вовсе нужного поля в файле нет. При просмотре файла в текстовом редакторе можно найти причину любой проблемы, но это очень неудобно. Было бы гораздо удобнее открыть файл в программе и увидеть банковскую выписку в виде таблицы, где каждая строка представляет собой отдельный платёж. Сразу будет видно, какие там платежи, от кого, кому, какие значения записаны в каждой колонке таблицы.

Именно это и делает эта программа. Но кроме того, она позволяет понять, как из немного Java и немного Swing сделать: меню, инструментальную линейку, строку состояния, контекстное меню, диалог открытия файла, отображение файла в виде таблицы, поиск, Drag & Drop, использование L&F и собрать всё это вместе в виде SDI.

Для разработки использован Eclipse. Проект расположен здесь: https://github.com/weekend-game/bankviewer/ (EN) и здесь: https://gitflic.ru/project/weekend-game/bankviewer/ (RU).

В проекте есть самостоятельная программа TestGenerator. Она находится в пакете game.weekend.bankviewer.util. В тексте программы можно указать имя файла, количество строк банковской выписки, и она сгенерирует тестовый файл. Файл Выписка1.txt сгенерирован именно посредством TestGenerator.

Как запустить программу

Скачайте репозиторий на свой компьютер. Всё необходимое для работы программы расположено в папке app. Зайдите в папку app и запустите программу двойным кликом по BankViewer.jar или, если он не запускается, двойным кликом по BankViewer.bat. Если и последнее не запускает приложение, то скачайте и установите Java 11 или новее и снова попробуйте способы, описанные выше.

Как открыть проект в Eclipse

В Eclipse, в меню выберите File – Import... В появившемся окне выберите Existing Projects into Workspace. Укажите папку скаченного вами репозитория и нажмите кнопку Finish. Проект откроется в Eclipse. В Package Explorer (в левой части экрана) дважды кликните на файле BankViewer.java. Файл откроется для редактирования (в центральной части экрана). Запустите программу на выполнение, нажав Ctrl+F11 или так, как Вам удобно запускать программы в Eclipse.

Как программа написана

Главным классом приложения является класс BankViewer. В его конструкторе создаётся всё необходимое для работы. Прежде всего, это окно приложения - объект класса JFrame. Для реализации SDI использую менеджер расположения BorderLayout(). В центральной части располагаю JEditorPane. Она и будет использоваться для отображения банковской выписки в виде таблицы. В верхней части располагаю инструментальную линейку, в нижней части - строку состояния.

К главному окну приложения подключено меню. К JEditorPane подключено контекстное меню, и, как уже говорилось, отображается инструментальная линейка. Все эти три объекта создаются методами класса Act. Каждый пункт меню или кнопка инструментальной линейки - это объект класса Action. Все необходимые Action создаются методами класса Act. Именно поэтому это, наверное, самый большой по числу строк класс в этой программе. Но, наверное, это и самый простой класс в этой программе, потому что все Action создаются одинаково, а меню и инструментальная линейка - это всего лишь перечисление нужных Action в нужном порядке. Впрочем, есть мелкие нюансы, которые легко понять, просматривая текст класса.

Строка состояния - это объект класса StatusBar. Собственно, строка состояния - это JPanel, в которой последовательно расположены три JTextField. В классе есть три метода для выдачи строкового сообщения в соответствующий JTextField. Крайне правое поле несколько особенное: сообщение, отображаемое в него, будет видно в течение 5 секунд, а затем оно исчезает. Конечно, строку состояния можно бесконечно усложнять и улучшать, но для этой программы такой строки состояния вполне достаточно.

Для отображения информации в виде таблицы Swing предоставляет класс JTable. Но есть ещё один способ: JEditorPane, которому методом setPage(URL u) передали URL HTML-файла, в котором тегами <table> ... </table> сформирована таблица. Использую второй вариант. Итак, главное в программе - это преобразовать исходный текстовый файл «ключ-значение» в HTML-файл. Затем HTML-файл передаётся для отображения той самой JeditorPane, что расположена в центральной части главного окна приложения. Всё остальное - это реализация SDI и обеспечение удобства использования программы.

Программа открывает файлы, чтобы отобразить их в табличном виде. Swing предоставляет готовое окно для указания файла, который надо открыть: это класс javax.swing.JFileChooser. Класс Filer - это только оболочка вокруг него, позволяющая слегка поднастроить внешний вид и поведение.

Для работы Filer необходим объект класса LastFiles. LastFiles при помощи класса Proper (это оболочка для класса java.util.Properties) хранит и умеет читать при запуске программы несколько особенных строк - это пути к последним открытым файлам. Очень удобно увидеть их в меню «Файл» и быстро указать нужный вместо использования окна открытия файла. Filer же при каждом успешном открытии файла сохраняет путь к нему в объекте класса LastFiles. При неудачном открытии он удаляет такой путь из сохранённого списка, если таковой имеется, конечно. Для этих действий LastFiles предоставляет методы put() и remove(). Кроме этого, имеется метод getList(), при помощи которого Act из списка путей формирует фрагмент меню «Файл» со списком из последних открытых файлов.

Если пользователь указал файл, то Filer в методе open() вызовет единственный публичный метод convert() класса Convertor. Этот метод конвертирует исходный файл с данными в виде пар ключ-значение в HTML-файл с теми же данными, представленными в виде таблицы. Затем этот HTML-файл будет передан JEditorPane, которая сама его разберет и отобразит без всякого вмешательства со стороны программиста.

Какая Java-программа не позволяет пользователю установить Look & Fill? Эта программа не является исключением. В меню «Вид» пользователь может выбрать любой доступный в его системе Look & Fill. Работать с этим помогает класс LaF.

Для реализации поиска в отображенном файле был создан класс Finder. FinderFrame - это окно для указания строки поиска, представляющее собой набор компонентов javax.swing. Алгоритм поиска реализован в классе Finder. При создании FinderFrame возникла задача размещения компонентов, и для её решения был создан класс GBL. GBL - это упрощение менеджера расположения GridBagLayout, адаптированное под нужды приложения.

Следует обратить внимание на класс Proper. Это класс, который является оболочкой для класса java.util.Properties. Метод read() читает файл с ранее записанными данными объекта класса java.util.Properties. Метод save() делает обратное: записывает всё, что помещено в объекте, в файл. Класс нужен, чтобы приложение могло сохранять некоторые данные между сеансами работы. Так сохраняется расположение и размер главного окна, пути к нескольким недавно открытым файлам, признак того, надо ли отображать инструментальную линейку, строку состояния, запоминается последняя введённая строка для поиска и некоторые другие данные. Для удобства работы сделана пара методов: setProperty(name, value) и getProperty(name, def), где value может быть строкой или целым числом. Понятно, что первый метод сохраняет некоторое значение value с именем name, а второй читает значение name, а если оно не записывалось, то будет возвращено значение def. Для записи и восстановления расположения и размеров окна приложения используется пара методов saveBounds() и setBounds().

В программе опробована интернационализация (i18n). Для этого используется класс Loc. Все фразы, которые предназначены для отображения, написаны на английском языке с использованием нижнего подчеркивания вместо пробела. Если в файле messages_ru.properties найдётся перевод для такой фразы, то он и будет использоваться для отображения. Иначе, в английской фразе подчёркивания будут заменены на пробел, а первая буква будет сделана прописной. И получившееся будет использовано для отображения. Для целей данной программы этого вполне достаточно.

Итоги

В ходе работы пришлось разобраться со следующим.

Создание Single Document Interface посредством Swing, а именно: создание центральной части для отображения документа, меню, инструментальной линейки, строки состояния, контекстного меню, появляющегося при нажатии правой кнопки мыши.

Реализовать управление пунктом меню, пунктом контекстного меню и кнопкой инструментальной линейки «Копировать». В зависимости от наличия выделенного в документе текста пункт меню и кнопка становятся активными или недоступными, то есть разрешается копировать, если есть что копировать. Реализовать указание файла для отображения посредством:

  • диалогового окна;
  • Drag & Drop;
  • списка недавно открытых файлов.

Программа позволяет использовать установленные на вашем компьютере Look and Fills. Реализован поиск строки в отображённом документе. Для создания окна поиска создано упрощение класса GridBagLayout – класс GBL. Программа сохраняет между сеансами работы различные настройки, такие как: размер экрана, строку поиска, необходимость показывать инструментальную линейку, необходимость показывать статусную строку, используемый L&F, пути к пяти последним открытым файлам. Программа интернационализована (i18n) и локализована (l10n).