вступление
Все знают POI! Это лучшая библиотека для создания документов Excel на Java. это действительно хорошо и может многое сделать легко. Но недавно я хотел сделать что-то не так просто. Я хотел использовать существующий файл xlsx в качестве шаблона и вставить в него некоторые данные. В этом посте я покажу, почему с версией 4.0.0 было не так просто.
Доступные инструменты
Чтобы вставить некоторое содержимое в середину существующего документа Excel, все строки от точки вставки до последней строки должны быть сдвинуты вниз на n строк, где n — количество вставляемых строк. Также предпочтительно сохранять форматирование перемещаемых строк.
На самом деле POI имеет некоторый API, чтобы помочь с этими проблемами.
Интерфейс листа имеет метод
Sheet.shiftRows (int, int, int), который можно использовать так:
sheet.shiftRows (insertPosition, sheet.getLastRowNum (), n);
Есть более продвинутый метод
Sheet.shiftRows (int, int, int, boolean, boolean), но для XSSF логические параметры не имеют значения, как я мог найти в коде. Для HSSF эти параметры могут быть важны.
Так что этот метод должен сделать свое дело! В чем проблема?
проблема
Когда я попытался использовать этот метод, я столкнулся с ужасной проблемой: «Мы обнаружили проблему с некоторым контентом…»
На самом деле это было очень сложно. Я быстро обнаружил, что каким-то образом строки были перемещены неправильно. LibreOffice смог по крайней мере открыть файл, но форматирование и вставленное содержимое были неверными.
Решение
Это заняло 2-3 часа усердного копания :-). Как оказалось, POI даже в последней версии 4.0.0 (скорее всего, даже в 4.0.1) содержит ошибку и не может правильно перемещать строки. Вот ссылка на ошибку:
https://bz.apache.org/bugzilla/show_bug.cgi?id=57423
Метод обновляет ссылки на строки в листе xml, например
<row r = ” 139 “
но не обновляет ссылки на ячейки
<cr = ” A138 ” s = ”1 ″ /> — неправильно
Ячейка должна указывать на строку верхнего уровня, в этом случае она должна указывать на строку 139 следующим образом:
<cr = ” A139 ” s = ”1 ″ /> — справа
(вы можете взглянуть на лист xml, если распакуете файл xlsx)
Ошибка показывает обходной путь. Я создал метод, который реализует сдвиг и обходной путь в одном методе:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
public static void xssfShiftRows(Sheet sh, int firstRow, int last Row, int shiftN) { int firstShiftedRow = firstRow + shiftN; int lastShiftedRow = lastRow + shiftN; sh.shiftRows(firstRow, lastRow, shiftN, true , true ); /* * This code is a workaround for the bug * In the sheet xml the row references are updated like this: * <row r="139" * but the cell references are incorrect * <c r="A138" s="1"/> * * The number in the row 139 must match the number in the cell A139. * This code manually updates these links. */ for ( int nRow = firstShiftedRow; nRow <= lastShiftedRow; nRow++) { final Row row = sh.getRow(nRow); if (row != null ) { String msg = "Row[rownum=" + row.getRowNum() + "] contains cell(s) included in a multi-cell array formula. " + "You cannot change part of an array." ; for (Cell c : row) { ((XSSFCell) c).updateCellReferencesForShifting(msg); } } } } |
Опубликовано на Java Code Geeks с разрешения Вадима Коркина, партнера нашей программы JCG . Смотрите оригинальную статью здесь: Вставьте контент с помощью Apache POI Мнения, высказанные участниками Java Code Geeks, являются их собственными. |