Рубрики
3. Инструментарий Java

Java + Excel файлы (Apache POI)


С периодичностью раз в два-три года сталкиваюсь с проектами, в которых опять нужно работать с Excel файлами.
Наверно это у меня что-то кармическое...
Сейчас, в очередной раз приходиться реализовать полуавтоматический разбор сотен excel-файлов с прайсами.
В прошлых своих проектах использовал JExcelApi.
Ничего плохого про эту библиотеку сказать не могу, но хочется какого-то разнообразия в жизни поэтому в этот раз с товарищем решили попробовать Apache POI.

Apache POI поддерживает как формат для обычных *.xls файлов (HSSF) так и *.xlsx файлы (XSSF).

Кстати, формат для *.xls файлы в Apache POI они обзывают "HSSF - Horrible SpreadSheet Format", то есть "Вселяющий ужас формат для электронных таблиц".
Для того, чтобы приступить к работе, как обычно прописываем зависимости в pom.xml:

  <dependencies>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <!-- версия 3.7 - стабильная,  3.8 в "beta 2" (на 18 мая 2011г).  -->
            <version>3.7</version>
        </dependency>
    </dependencies>

Для примера, приведу очень простой файл - список ФИО, сумма + Итог:

Если нужно просто вытащить текст, можно использовать "класс-извелкатель": ExcelExtractor

Рубрики
Java

Календари и даты

Постоянно наталкиваюсь на людей, которые утверждают, что "Date - deprecated, нужно использовать Calendar".
Это не верно! Вариаций на тему "почему это не верно" где-только уже не написано, но все-равно появляются люди которые мне доказывают, что правильней использовать Calendar (аргументеруя именно "устареванием" Date).

На самом деле в классе Date просто много deprecated методов. Но если почитать внимательно документацию, то видно, что устарел не сам класс, а просто часть функций этого класса еще во времена выхода Java 1.1 была вынесена в другой класс. Вот и всё!

Целевое назначение объектов класса Date сохранилось. Это простой и легкий класс для обозначения времени (например 2010-01-01T12:00:00). Он сериализуется, и если вам нужно хранить именно дату (и время) в каком-то классе, то в большинстве случаев, разумнее всего использовать именно Date.

Что касается класса Calendar , то это в первую очередь календарик. Он нужен для того, чтобы узнать например какой день недели был на указанную дату, сколько дней прошло с начало года и т.д.. Такой своеобразный аналог обычного настенного календаря с курсором. И гонять его между разными слоями/тирами приложения в составе трансферных объектов или делать его атрибутом какого-то класса для обозначения даты-времени не логично (в большинстве случаев).

Если вам нужно отформатировать или распарсить дату, вы можете использовать например SimpleDateFormat.

Кстати о SimpleDateFormat. Многие его тоже используют не правильно. Постоянно наталкиваюсь в чужих исходниках на конструкции типа:

// так лучше не делать!
private final static SimpleDateFormat DDMMYYYY = new SimpleDateFormat("dd.MM.yyyy");

Конечно дело не в том, что он статик! Просто SimpleDateFormat он в общем-то не потокобезопасен. Как написано в документации:

Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.

То есть по хорошему, если это статик поле будут конкурентно использоваться, то можно нарваться на неприятности. Как правило такие баги (когда игнорируют многопоточное выполнение) не ловятся юнит-тестами, зато в продакшене могут создавать проблемы.

P.S.: Интересно, но использование Calendar вместо Date можно встретить даже в таком матёром API как JCR. Вот не знаю, почему они используют Calendar, а не Date...