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

Судя по документации, в стабильной версии POI (3.6) поддержки фильтров нет в принципе (видимо, этим и объясняется практически полное отсутсвие информации об этом функционале в Сети). Тем не менее, если внимательно изучить API Javadocs, можно обнаружить там загадочный интерфейс org.apache.poi.ss.usermodel.AutoFilter
, а также его не менее загадочные реализации для xls и xlsx - org.apache.poi.hssf.usermodel.HSSFAutoFilter
и org.apache.poi.xssf.usermodel.XSSFAutoFilter
.
Ввиду того, что в использовавшейся нами стабильной версии POI таких классов и интерфейсов не оказалось, а фильтры в xls-документах были нужны очень сильно, было принято решение попробовать тестовую версию POI - сейчас это 3.7beta3. Как это ни странно, тестовая версия зарекомендовала себя так же хорошо, как и стабильная - никаких проблем в решаемых нами задачах не возникло, зато добавились новые возможности, в числе которых и пресловутые фильтры. Заранее оговорюсь, что создавать конфигурируемые фильтры (т.е. всё то, что не autofilter) POI пока, к сожалению не умеет.
Итак, вот как должен выглядеть код метода, генерирующего показанный на скриншоте выше xls-файл (Person - это POJO-класс наподобие приведённого в предыдущей заметке):
//Заголовки столбцов
private static final String LAST_NAME_COLUMN_HEADER = "Фамилия";
private static final String FIRST_NAME_COLUMN_HEADER = "Имя";
private static final String SECOND_NAME_COLUMN_HEADER = "Отчество";
private static final String ADDRESS_COLUMN_HEADER = "Адрес";
private static final String SPHONE_COLUMN_HEADER = "Телефон";
...
/*
* Генерируем xls для заданного списка контактов и отдаём его
* в байтовый поток записи
*/
private void generateXls(ByteArrayOutputStream out, List<Person> contacts) {
try {
HSSFWorkbook wb = new HSSFWorkbook(); //Создаём новый документ
HSSFSheet sheet = wb.createSheet(); //Создаём страницу
//Объявляем переменные для строки и ячейки
HSSFRow row;
HSSFCell cell;
//Создаём "шапку" таблицы
row = sheet.createRow(0);
cell = row.createCell(0, Cell.CELL_TYPE_STRING);
cell.setCellValue(LAST_NAME_COLUMN_HEADER); //Фамилия
cell = row.createCell(1, Cell.CELL_TYPE_STRING);
cell.setCellValue(FIRST_NAME_COLUMN_HEADER); //Имя
cell = row.createCell(2, Cell.CELL_TYPE_STRING);
cell.setCellValue(SECOND_NAME_COLUMN_HEADER); //Отчество
cell = row.createCell(3, Cell.CELL_TYPE_STRING);
cell.setCellValue(ADDRESS_COLUMN_HEADER); //Адрес
cell = row.createCell(4, Cell.CELL_TYPE_STRING);
cell.setCellValue(PHONE_COLUMN_HEADER); //Телефон
if(contacts != null){
//Создаём фильтры на весь диапазон значений таблицы
sheet.setAutoFilter(CellRangeAddress.valueOf("A" +
String.valueOf(1) + ":E" +
String.valueOf(contacts.size())));
//Записываем содержимое в ячейки
if(contacts != null && contacts.size() > 0){
for(int i = 0; i < contacts.size(); i++){
Person person = contacts.get(i);
int rowIndex = i + 1; //Нулевой столбец - "шапка" таблицы
row = sheet.createRow(rowIndex); // Создаём новую строку
cell = row.createCell(0, Cell.CELL_TYPE_STRING);
cell.setCellValue(person.getLastName()); //Фамилия
cell = row.createCell(1, Cell.CELL_TYPE_STRING);
cell.setCellValue(person.getFirstName()); //Имя
cell = row.createCell(2, Cell.CELL_TYPE_STRING);
cell.setCellValue(person.getSecondName()); //Отчество
cell = row.createCell(3, Cell.CELL_TYPE_STRING);
cell.setCellValue(person.getAddress()); //Адрес
cell = row.createCell(4, Cell.CELL_TYPE_STRING);
cell.setCellValue(person.getPhone()); //Телефон
}
}
}
wb.write(out);
out.close();
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
}
Ключевой элемент листинга - строки 35-37, в которых, собственно, и реализовано добавление фильтра. Фильтр добавляется на диапазон ячеек - т.к. наша таблица содержит 5 столбцов, то столбцы мы берём с "A" по "E" включительно, а количество строк зависит от количества контактов в списке.
Собственно, всё! Приведённый выше код генерирует таблицу с фильтрами - можно пользоваться :)