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

Java (11), 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).

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

Скачайте репозиторий на свой компьютер. Всё необходимое для работы программы расположено в папке 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.

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

Как работать с программой

Программа реализует Single Document Interface. Это значит, что после запуска мы видим привычное меню, инструментальную панель (тулбар), пустое пространство в центре окна для отображения документа и в самом низу окна - строку состояния.

Открыть банковскую выписку для просмотра можно тремя способами.

Первый способ - в меню выберите "Файл" - "Открыть..." или кнопкой на инструментальной панели. При этом откроется диалоговое окно, посредством которого надо будет указать файл банковской выписки, например, файл Выписка1.txt, который есть в репозитории.

Второй способ - воспользоваться Drag and Drop, а именно перетащить файл с банковской выпиской в центральную часть окна приложения.

Третий способ подходит для файлов, которые уже были открыты ранее. Пути к нескольким последним открытым файлам отображаются в меню "Файл". Достаточно выбрать нужный файл, и он будет отображен.

Для поиска текста в банковской выписке нажмите Ctrl+F, кнопку с изображением «бинокля» на панели инструментов или выберите из меню "Правка" пункт "Поиск...". В появившемся диалоговом окне укажите строку поиска, отметьте, следует ли учитывать регистр, укажите направление поиска и нажмите кнопку "Найти далее". Поиск можно продолжить из открытого окна поиска, с помощью кнопок тулбара или "горячих" клавиш (Ctrl+G или Ctrl+Shift+G).

Некоторые операции можно выполнить, нажав правую кнопку мыши, после чего отобразится контекстное меню.

Внешний вид приложения можно настроить с помощью пунктов меню "Вид".

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

Все настройки, и даже строка для поиска, сохраняются между сеансами работы.

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

Главным классом приложения является класс BankViewer. Именно он содержит статический метод main() для запуска программы. В его конструкторе создаётся всё необходимое для работы.

Главное в программе

В конструкторе BankViewer() я создаю объект pane класса JEditorPane(). JEditorPane — это готовый класс, предоставляемый Swing. Такой объект умеет отображать HTML. Но у меня нет никакого HTML-файла. У меня есть файл банковской выписки в виде списка пар "ключ-значение". Поэтому я должен преобразовать исходный файл в HTML-файл, содержащий таблицу, и передать его pane для отображения.

В классе Filer, который предназначен для работы с файлами, есть метод open(File file). В этом методе я вызываю Convertor.convert(file.getPath(), tempFile), где file.getPath() — это путь к исходному файлу, а tempFile — это имя временного файла, в котором будет сформирована HTML-таблица. Этот метод, руководствуясь правилом, что все пары между ключами "СекцияДокумент" и "КонецДокумента" являются полями платежного поручения, сформирует ArrayList платежных поручений. Так уж получилось, что разные платёжные поручения в выписке содержат разный перечень полей. Но в таблице надо отобразить все поля, которые встречаются в платёжных поручениях. Поэтому приходится определить множество имеющихся полей и только затем записать в tempFile HTML-код HTML-таблицы.

Затем, когда tempFile готов, я вызываю viewer.showFile(tempFile), который делает pane.setPage(имя_сформированного_html_файла), т.е. указывает объекту pane отобразить файл. Что pane и делает. Это всё. Исходный файл, содержащий пары «ключ-значение», отображается на экране в виде таблицы. Всё остальное — это только реализация SDI и сервиса для удобства использования программы.

Да, конечно, класс Convector не так уж прост, он содержит более 350 строк. Но это главное, что решает задачу этой программы. Собственно, поэтому я не поленился написать обширные комментарии в коде этого класса.

Подробнее о Convector

Создание HTML-файла (Convertor.convert(String srcFileName, File dstFile)) состоит из трёх этапов:

  1. Загрузка исходного файла в виде массива документов (loadSource(srcFileName));
  2. Создание массива полей, которые встречаются во всех документах (getFields(documents));
  3. Собственно создание HTML-файла (createHTML(dstFile, documents, fields));

Теперь подробнее.

1. Загрузка исходного файла в виде массива документов (loadSource(srcFileName))

Я читаю из исходного файла пары и создаю объект класса Substance, который содержит все пары ключ-значение документа. Документ — это то, что начинается с ключа "СекцияДокумент" и заканчивается "КонецДокумента". Всё, что между ними, и попадает в Substance. Так как документов в выписке много, я формирую массив из таких документов (ArrayList <Substance> documents).

2. Создание массива полей, которые встречаются во всех документах (getFields(documents))

Объявляю: ArrayList fields = new ArrayList();

Это и будет список полей, которые встречаются во всех документах.

Из списка документов я выбираю документ с самым большим количеством полей. Такой документ становится основой для дальнейшей работы. Все его ключи я копирую в fields. Затем я просматриваю все остальные документы и добавляю в fields все прочие ключи, которых в нем нет.

Итак, на данном этапе я имею список всех документов documents и список всех возможных полей fields.

3. Собственно создание HTML-файла (createHTML(dstFile, documents, fields))

Я записываю в dstFile теги, необходимые для создания таблицы. Просматриваю все документы documents и заполняю HTML-таблицу. Так как пары ключ/значения могут располагаться в разных документах в разных позициях и каких-то пар может не оказаться, я использую fields, чтобы определить, в какой позиции таблицы мне записать очередное значение.

Более подробно о работе программы можно узнать, скачав проект, открыв его в Eclipse, читая тексты классов, внося изменения, запуская программу и наблюдая, что из этого получается.

Итоги

Программа оказалась на удивление простой и полезной.

Хорошо бы…

Хорошо бы сделать изменение размера шрифта отображаемой банковской выписки.

Сделать голоcовое управление.