Java excel границы ячеек
ПРЕДПОСЫЛКИ . Я пытаюсь прочитать файл Excel в программу Java. Мой файл Excel предназначен для представления сетки или растровой карты, поэтому я сделал высоту и ширину каждой ячейки одним дюймом. Идея состоит в том, что я могу «нарисовать» карту или изображение, закрасив каждую ячейку цветом. Затем я могу прочитать файл Excel в программу Java, которую я сам создал с помощью объекта «Pixel», и создать более буквальное изображение. Я студент в области компьютерных наук, и на данный момент у меня было только четыре компьютерных класса. Я понимаю ООП и могу программировать на Java. Это не для класса; это побочный проект. Я использую XSSF (Microsoft 2007 и более поздние версии).
ИССЛЕДОВАНИЯ . Я обнаружил, что решение этой проблемы заключается в использовании Apache POI. Я уже скачал необходимые файлы jar Apache POI и настроил BuildPath в Eclipse для их чтения. Я обнаружил, что использование метода Iterator hasNext() пропустит пустые ячейки, поэтому решение состоит в том, чтобы использовать более прямой метод getCell() . Я обнаружил, что есть два getCell() метода - один с только индексом в качестве входных данных, а другой использует как вход индекса, так и MissingCellPolicy. Тем не менее, когда я попытался использовать метод MissingCellPolicy, поместив RETURN_NULL_AND_BLANK в качестве входных данных, ячейка стала пустой, но в процессе цвет стал нулевым. MissingCellPolicy CREATE_NULL_AS_BLANK имеет ту же проблему.
НЕПРАВИЛЬНОЕ РЕШЕНИЕ . Когда я помещаю текст в ячейку, он правильно читает цвет. Даже метод итератора может правильно читать ячейки, в которых есть текст. Это потому, что как только я помещаю текст в них, ячейка инициализируется. Однако сетка, которую я пытаюсь создать, слишком велика, чтобы я мог поместить текст в каждую ячейку. Вероятно, есть способ задать для каждой ячейки на листе одинаковый текст, но я тоже не могу этого сделать, потому что у меня уже есть много ячеек с определенным текстом по всей сетке, и их невозможно удалить. Это также, вероятно, сделало бы все ячейки одного цвета, что я также не могу сделать в данный момент. Кроме того, я бы предпочел, чтобы у меня были клетки без текста.
TL; DR : мне нужно прочитать цвет ячейки в Excel в Java, используя Apache POI без записи текста в ячейку. Насколько я понимаю, метод getCell() с MissingCellPolicy не работает, потому что политика создает новую пустую ячейку, перезаписывая существующий цвет. Я видел много вопросов о чтении пустых ячеек в Apache POI, но я не видел ни одного о доступе к цвету.
RGBColor Код конструктора:
RESULT: Приведенный выше код правильно считывает цвет ячейки, если в ней есть текст, и создает объект RGBColor из цвета. Приведенный выше код также может читать текст из ячейки. Однако, как только он достигает ячейки без текста, он вызывает NullPointerException в строке ExtendedColor (поэтому ячейка пуста). Когда вместо этого используется MissingCellPolicy CREATE_NULL_AS_BLANK, это вызывает NullPointerException в строке byte[] (поэтому цвет равен нулю). Любая помощь приветствуется, даже если это не совсем то, о чем я прошу, потому что я новичок в Apache POI !
Свойства и методы взаимодействия Java приложений с файлами Excel представлены на странице библиотеки Apache POI. Здесь рассматриваются примеры использования Apache POI для создания файлов Excel 2007 или более поздней версии. Если необходимо создать Excel 1997-2003, то следует использовать классы, наименования которых начинаются с символа 'H'. Использование библиотеки Apache POI для чтения файлов Excel с примером рассмотрен здесь.
Создание книги Excel
Создание страницы
Наименование страницы не должно превышать 31 символ. Следующие символы недопустимы в наименовании страницы :
0x0 - нулевое значение;
':' - двоеточие;
'\' - обратный слэш;
'/' - прямой слэш;
'*' - «звездочка»;
'?' - вопросительный знак;
'[' - открывающаяся квадратная скобка;
']' - закрывающаяся квадратная скобка.
Можно использовать утилиту WorkbookUtil для получения наименования страницы книги. Метод createSafeSheetName данной утилиты заменит «неправильные» символы на пробелы (' ').
Определение размера колонки
При определении размера колонки необходимо учитывать максимальное количество символов в колонке, коэффициент размера символа для заданного шрифта (для "Sans Sherif" равен 1.14388) и коэффициент EXCEL_COLUMN_WIDTH_FACTOR, равный 256. Метод autoSizeColumn(idx_column) позволяет автоматически установить размер колонки по максимальному значению.
Метод setColumnWidth(column, width) в качестве параметров принимает номер колонки (отсчет от 0) и размер колонки. Методу autoSizeColumn(column) необходимо передать только номер колонки.
Создание строки
При создании строки в метод createRow в качестве параметра необходимо передать номер строки (отсчет от 0). Для определения размера строки можно использовать методы setHeight (short) и setHeightInPoints (float). При использовании метода setHeight также, как и с определением размера колонки, необходимо учитывать коэффициенты. Поэтому метод setHeightInPoints оказывается более предпочтительным.
Создание ячейки, определение типа значения
В следующем примере создаются ячейки, устанавливается их тип и записываются значения.
Класс CellType включает свойства [_NONE, BLANK, BOOLEAN, ERROR, FORMULA, NUMERIC, STRING], которые можно использовать для определения типа значения ячейки.
Определение формата даты ячейки
В следующем примере создаются две ячейки с записью текущей даты. Вторая ячейка форматируется.
Слияние ячеек
Для слияния ячеек используется метод addMergedRegion.
Определение шрифта
Помните, что максимальное количество создаваемых шрифтов ограничено значением 32767. Необходимо использовать объекты шрифтов/стилей.
Определение цвета фона ячейки
ПРИМЕЧАНИЕ : для выделения цвета значения настраивайте шрифт (см. выше).
Выравнивание значения
В следующем примере создаются ячейки с различным выравниванием значений по горизонтали и вертикали.
Границы ячейки, Border
Многострочные ячейки
Для фиксированного разделения/переноса текста в ячейке необходимо в стиле определить свойство WrapText=true, и в тексте установить разделители '\n'.
Использование формулы
Создадим две ячейки. В первую ячейку cell1 запишем сумму значений колонки, а во второй ячейке cell2 разместим формулу "СУММА()". Для вычисления значения первой ячейки дополнительно используются методы getColsSummary и getCellValue.
На странице описания библиотеки Apache POI представлены свойства и методы взаимодействия Java приложений с файлами Excel. Здесь рассматривается пример использования Apache POI для чтения файлов Excel 2007 или более поздней версии. Если необходимо обрабатывать Excel 1997-2003, то следует использовать классы, наименования которых начинаются с символа 'H' (см. наименование классов на странице описания Apache POI).
Открытие книги Excel
Чтобы «открыть» файл Excel как HSSFWorkbook (.xls), так и XSSFWorkbook (.xlsx) можно использовать либо File, либо InputStream. При использовании InputStream требуется больше памяти для загрузки файла в буффер.
Метод openBook демонстрирует использование WorkbookFactory для открытия Excel файла. Строки использования InputStream закомментированы.
Если нужно обойти использование WorkbookFactory, т.е. использовать XSSFWorkbook (HSSFWorkbook) напрямую, то следует использовать OPCPackage (.xlsx) или NPOIFSFileSystem (.xls).
Открытие страницы
При открытии страницы слеудет использовать метод getSheet с указанием в качестве параметра наименования страницы. Здесь необходимо быть внимательным, поскольку наименования страницы по умолчанию могут быть как «Sheet», так и «Лист», в зависимости от локализации операционной системы и Excel.
Перебор строк и ячеек
Чтобы «пройтись» по всем страницам книги и перебрать все значения в ячейках можно использовать итераторы. Следующий код показывает использование итераторов для перебора всех ячеек страницы.
Итераторы доступны по вызовам workbook.sheetIterator(), sheet.rowIterator() и row.cellIterator(). Но необходимо помнить, что rowIterator и cellIterator перебирают только строки и ячейки, которые созданы, пропуская пустые строки и ячейки.
Если необходимо проверить все строки и все ячейки определенной области, то можно воспользоваться следующим кодом.
В представленном коде для чтения ячейки был использован метод getCell(int). Можно использовать метод getCell(int, MissingCellPolicy), где MissingCellPolicy, определяет условие возвращения пустых и отсутствующих ячеек. Однако IDE Eclipse, где работоспособность кода проверялась, показывает, что MissingCellPolicy упразднена (deprecated), а метод getCell(int) для ячейки типа XSSFCell вернул правильные значения. Определение значений ячеек выполнялось в методе printCell(row, cell).
Чтение содержимого ячейки
Чтобы получить значение ячейки, необходимо знать тип её значения. Полагаю, что Вы не раз сталкивались с числовым представлением значения даты. Если у текстовой ячейки попытаться получить числовое значение, то будет вызвано NumberFormatException. Поэтому, необходимо первоначально определиться с типом, чтобы использовать соответствующий метод.
Следующий код в цикле проходит по ячейкам в строке и выводит в консоль ссылочную информацию на ячейку (например $A$3) и содержимое ячейки. Причем, сначала отображается значение, полученное методом formatCellValue класса DataFormatter, а после символа слеша '/' отображается значение, получаемое методами getRichStringCellValue(), getDateCellValue(), getNumericCellValue(), getBooleanCellValue() и getCellFormula() класса XSSFCell.
Пример чтения файла Excel
Работоспособность представленного на странице кода (методов), была проверена в примере, структура которого изображена на следующем скриншоте. Это проект Eclipse, включающий перечень необходимых библиотек для чтения файла Excel. Основной класс ExcelRead реализует все представленные выше методы.
На следующем скриншоте представлена страница простенького файла Excel, содержащая ячейки со значениями типа Date, String, Numeric и ячейки с формулами.
Результат чтения файла
Значения ячеек книги Excel в примере отображаются в консоли. Обратите внимание на отличия значений до слеша и после него для типов Date и Numeric. При необходимости можно использовать в приложении переменные соответствующего типа (Date, Integer) и должным образом отформатировать значения.
Исходный пример, рассмотренный в тексте страницы, можно скачать здесь (11.7 Мб).
Я пытаюсь скопировать ячейки из одной книги в другую с помощью последней версии Apache POI (4.1.2).
Если обе книги являются файлами .xlsx, все работает нормально. Но если исходная книга представляет собой (старый) файл .xls, а целевая книга - файл .xlsx, следующий код не работает.
java.lang.IllegalArgumentException: можно клонировать только из одного XSSFCellStyle в другой, но не между HSSFCellStyle и XSSFCellStyle
Если мы не можем использовать cloneStyleFrom , когда файлы (или Workbook объекты) относятся к разным типам, как мы можем преобразовать объект HSSFCellStyle в XSSFCellStyle ?
1 ответ
Ответ на ваш вопрос "Как мы можем преобразовать объект HSSFCellStyle в XSSFCellStyle ?" is: Мы не можем сделать это с помощью apache poi 4.1.2 . Это просто не поддерживается, как четко указано в CellStyle.cloneStyleFrom:« Однако оба стиля CellStyle должны быть одного типа (HSSFCellStyle или XSSFCellStyle) ».
Другой вопрос: Должны ли мы вообще преобразовывать один стиль ячеек в другой? Или какие варианты использования существуют для CellStyle.cloneStyleFrom вообще? На мой взгляд, нет. Существуют Excel ограничения на количество уникальных форматов ячеек / стилей ячеек. См. спецификации Excel и лимиты. Поэтому мы не должны создавать стиль отдельной ячейки для каждой отдельной ячейки, потому что тогда эти ограничения будут достигнуты очень быстро. Поэтому вместо клонирования стилей ячеек мы должны получить свойства стиля из исходного стиля style1 , а затем использовать CellUtil.setCellStyleProperties, чтобы установить эти свойства стиля для другой ячейки. обсуждаемый. Этот метод пытается найти существующий CellStyle , который соответствует текущему стилю ячейки и свойствам стилей в properties . Новый стиль создается только в том случае, если книга не содержит подходящего стиля.
Поскольку заголовок вашего вопроса - «Копирование ячеек между книгами Excel с помощью Apache POI», я создал рабочий черновик того, как я это буду делать.
Следующий код сначала получает существующий Workbook.xls как HSSFWorkbook wb1 и создает новый XSSFWorkbook wb2 . Затем он перебирает все ячейки первого листа wb1 и пытается скопировать эти ячейки в первый лист wb2 . Для этого существует метод copyCells(Cell cell1, Cell cell2) , который использует copyStyles(Cell cell1, Cell cell2) . Последний получает свойства стиля из исходного стиля style1 , полученного из cell1 , а затем использует CellUtil.setCellStyleProperties для установки этих свойств стиля на cell2 . Для копирования шрифтов используется copyFont(Font font1, Workbook wb2) . Это пытается создать новые шрифты в wb2 , только если такого шрифта еще нет в этой книге. Это необходимо, потому что также существует ограничение на количество уникальных типов шрифтов для каждой книги в Excel .
Если Workbook.xls выглядит так:
Тогда результирующий Workbook.xlsx будет выглядеть так:
Примечание. Это рабочий проект, который необходимо завершить. См. Комментарии TODO в коде. Необходимо учитывать значения ячеек RichTextString . Необходимо учитывать другие типы клеток.
Метод copyStyles обеспечивает только копирование формата данных, образца заливки и цвета переднего плана заливки (только для индексированных цветов), шрифта и границ. Необходимо учитывать дополнительные свойства стиля ячейки.
Читайте также: