HSSF(Apache POI)를 사용하여 기존 Excel에서 두 줄 사이에 행을 삽입하는 방법
어떻게든 기존 엑셀 파일에서 두 줄 사이에 새 행을 만들 수 있습니다.문제는 일부 포맷이 행의 이동에 포함되지 않았다는 것입니다.
그 중 하나는 숨김 행이 교대 중에 상대적으로 이동하지 않는다는 것입니다.즉, (예)20 ~ 30 행은 숨겨져 있지만,A가 새로운 행을 작성하면 그 행은 그대로 형성됩니다.숨김 행은 새 행을 삽입/작성할 때도 이동해야 합니다.이 행은 21~31이어야 합니다.
또 하나는 시트에 있는 세포에 없는 다른 물체입니다.예를 들어 텍스트 상자가 새 행이 생성된 후 이동하지 않습니다.이 물체의 위치가 고정되어 있는 것과 같습니다.단, 새로운 행을 삽입하거나 Excel에 붙여넣는 것과 같은 동작을 하고 싶습니다.새로운 행을 삽입하는 기능이 있으면 알려주세요.
이게 내가 지금 가지고 있는 거야 내 코드의 일부일 뿐이야
HSSFWorkbook wb = new HSSFWorkbook(template); //template is the source of file
HSSFSheet sheet = wb.getSheet("SAMPLE");
HSSFRow newRow;
HSSFCell cellData;
int createNewRowAt = 9; //Add the new row between row 9 and 10
sheet.shiftRows(createNewRowAt, sheet.getLastRowNum(), 1, true, false);
newRow = sheet.createRow(createNewRowAt);
newRow = sheet.getRow(createNewRowAt);
행 복사 및 붙여넣기가 가능하다면 큰 도움이 될 것입니다.하지만 나는 이미 여기에 물어봤지만 해결책을 찾을 수 없다.그래서 임시 해결책으로 행을 만들기로 했습니다.다 썼는데 이런 문제가 있어요.
어떤 도움이라도 주시면 대단히 감사하겠습니다.감사합니다!
여기서 파렴치하게 적응한 행을 복사하는 도우미 기능
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.util.CellRangeAddress;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class RowCopy {
public static void main(String[] args) throws Exception{
HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream("c:/input.xls"));
HSSFSheet sheet = workbook.getSheet("Sheet1");
copyRow(workbook, sheet, 0, 1);
FileOutputStream out = new FileOutputStream("c:/output.xls");
workbook.write(out);
out.close();
}
private static void copyRow(HSSFWorkbook workbook, HSSFSheet worksheet, int sourceRowNum, int destinationRowNum) {
// Get the source / new row
HSSFRow newRow = worksheet.getRow(destinationRowNum);
HSSFRow sourceRow = worksheet.getRow(sourceRowNum);
// If the row exist in destination, push down all rows by 1 else create a new row
if (newRow != null) {
worksheet.shiftRows(destinationRowNum, worksheet.getLastRowNum(), 1);
} else {
newRow = worksheet.createRow(destinationRowNum);
}
// Loop through source columns to add to new row
for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
// Grab a copy of the old/new cell
HSSFCell oldCell = sourceRow.getCell(i);
HSSFCell newCell = newRow.createCell(i);
// If the old cell is null jump to next cell
if (oldCell == null) {
newCell = null;
continue;
}
// Copy style from old cell and apply to new cell
HSSFCellStyle newCellStyle = workbook.createCellStyle();
newCellStyle.cloneStyleFrom(oldCell.getCellStyle());
;
newCell.setCellStyle(newCellStyle);
// If there is a cell comment, copy
if (oldCell.getCellComment() != null) {
newCell.setCellComment(oldCell.getCellComment());
}
// If there is a cell hyperlink, copy
if (oldCell.getHyperlink() != null) {
newCell.setHyperlink(oldCell.getHyperlink());
}
// Set the cell data type
newCell.setCellType(oldCell.getCellType());
// Set the cell data value
switch (oldCell.getCellType()) {
case Cell.CELL_TYPE_BLANK:
newCell.setCellValue(oldCell.getStringCellValue());
break;
case Cell.CELL_TYPE_BOOLEAN:
newCell.setCellValue(oldCell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_ERROR:
newCell.setCellErrorValue(oldCell.getErrorCellValue());
break;
case Cell.CELL_TYPE_FORMULA:
newCell.setCellFormula(oldCell.getCellFormula());
break;
case Cell.CELL_TYPE_NUMERIC:
newCell.setCellValue(oldCell.getNumericCellValue());
break;
case Cell.CELL_TYPE_STRING:
newCell.setCellValue(oldCell.getRichStringCellValue());
break;
}
}
// If there are are any merged regions in the source row, copy to new row
for (int i = 0; i < worksheet.getNumMergedRegions(); i++) {
CellRangeAddress cellRangeAddress = worksheet.getMergedRegion(i);
if (cellRangeAddress.getFirstRow() == sourceRow.getRowNum()) {
CellRangeAddress newCellRangeAddress = new CellRangeAddress(newRow.getRowNum(),
(newRow.getRowNum() +
(cellRangeAddress.getLastRow() - cellRangeAddress.getFirstRow()
)),
cellRangeAddress.getFirstColumn(),
cellRangeAddress.getLastColumn());
worksheet.addMergedRegion(newCellRangeAddress);
}
}
}
}
XSSF(Apache POI)를 사용하여 기존 Excel에서 두 줄 사이에 행을 삽입하려는 사용자를 위해 XSSFSheet에 이미 "copyRows" 메서드가 구현되어 있습니다.
import org.apache.poi.ss.usermodel.CellCopyPolicy;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class App2 throws Exception{
public static void main(String[] args){
XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream("input.xlsx"));
XSSFSheet sheet = workbook.getSheet("Sheet1");
sheet.copyRows(0, 2, 3, new CellCopyPolicy());
FileOutputStream out = new FileOutputStream("output.xlsx");
workbook.write(out);
out.close();
}
}
Qwerty의 답변을 참고하여 XL 사이즈를 부풀리는 것을 피할 수 있습니다.cellStyle
그리고 타입이CELL_TYPE_BLANK
,getStringCellValue
""
null
.
private static void copyRow(Sheet worksheet, int sourceRowNum, int destinationRowNum) {
// Get the source / new row
Row newRow = worksheet.getRow(destinationRowNum);
Row sourceRow = worksheet.getRow(sourceRowNum);
// If the row exist in destination, push down all rows by 1 else create a new row
if (newRow != null) {
worksheet.shiftRows(destinationRowNum, worksheet.getLastRowNum(), 1);
} else {
newRow = worksheet.createRow(destinationRowNum);
}
// Loop through source columns to add to new row
for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
// Grab a copy of the old/new cell
Cell oldCell = sourceRow.getCell(i);
Cell newCell = newRow.createCell(i);
// If the old cell is null jump to next cell
if (oldCell == null) {
newCell = null;
continue;
}
// Use old cell style
newCell.setCellStyle(oldCell.getCellStyle());
// If there is a cell comment, copy
if (newCell.getCellComment() != null) {
newCell.setCellComment(oldCell.getCellComment());
}
// If there is a cell hyperlink, copy
if (oldCell.getHyperlink() != null) {
newCell.setHyperlink(oldCell.getHyperlink());
}
// Set the cell data type
newCell.setCellType(oldCell.getCellType());
// Set the cell data value
switch (oldCell.getCellType()) {
case Cell.CELL_TYPE_BLANK:
break;
case Cell.CELL_TYPE_BOOLEAN:
newCell.setCellValue(oldCell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_ERROR:
newCell.setCellErrorValue(oldCell.getErrorCellValue());
break;
case Cell.CELL_TYPE_FORMULA:
newCell.setCellFormula(oldCell.getCellFormula());
break;
case Cell.CELL_TYPE_NUMERIC:
newCell.setCellValue(oldCell.getNumericCellValue());
break;
case Cell.CELL_TYPE_STRING:
newCell.setCellValue(oldCell.getRichStringCellValue());
break;
}
}
}
Qwerty의 답변을 참조하여 destRow가 null이 아닌 경우 시트를 작성합니다.shiftRows()는 destRow의 참조를 다음 행으로 변경하므로 항상 새 행을 생성해야 합니다.
if (destRow != null) {
sheet.shiftRows(destination, sheet.getLastRowNum(), 1);
}
destRow = sheet.createRow(destination);
Apache POI v3.9에서 테스트한 다음 구현에서 다른 답변과 의견을 병합했습니다.
밖에 rownum
대상 행을 아래로 이동하고 새 빈 행에 복사하기 때문입니다.수식은 예상대로 처리되어 말 그대로 복사되지 않습니다.단, 한 가지 예외는 복사된 행 위에 있는 셀에 대한 참조는 갱신되지 않습니다.이러한 명시적 참조가 있는 경우 이를 사용하여 계산된 참조로 대체하는 것입니다.INDIRECT()
이 투고에서 제시한 바와 같이
protected void copyRow(Sheet worksheet, int rowNum) {
Row sourceRow = worksheet.getRow(rowNum);
//Save the text of any formula before they are altered by row shifting
String[] formulasArray = new String[sourceRow.getLastCellNum()];
for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
if (sourceRow.getCell(i) != null && sourceRow.getCell(i).getCellType() == Cell.CELL_TYPE_FORMULA)
formulasArray[i] = sourceRow.getCell(i).getCellFormula();
}
worksheet.shiftRows(rowNum, worksheet.getLastRowNum(), 1);
Row newRow = sourceRow; //Now sourceRow is the empty line, so let's rename it
sourceRow = worksheet.getRow(rowNum + 1); //Now the source row is at rowNum+1
// Loop through source columns to add to new row
for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
// Grab a copy of the old/new cell
Cell oldCell = sourceRow.getCell(i);
Cell newCell;
// If the old cell is null jump to next cell
if (oldCell == null) {
continue;
} else {
newCell = newRow.createCell(i);
}
// Copy style from old cell and apply to new cell
CellStyle newCellStyle = worksheet.getWorkbook().createCellStyle();
newCellStyle.cloneStyleFrom(oldCell.getCellStyle());
newCell.setCellStyle(newCellStyle);
// If there is a cell comment, copy
if (oldCell.getCellComment() != null) {
newCell.setCellComment(oldCell.getCellComment());
}
// If there is a cell hyperlink, copy
if (oldCell.getHyperlink() != null) {
newCell.setHyperlink(oldCell.getHyperlink());
}
// Set the cell data type
newCell.setCellType(oldCell.getCellType());
// Set the cell data value
switch (oldCell.getCellType()) {
case Cell.CELL_TYPE_BLANK:
break;
case Cell.CELL_TYPE_BOOLEAN:
newCell.setCellValue(oldCell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_ERROR:
newCell.setCellErrorValue(oldCell.getErrorCellValue());
break;
case Cell.CELL_TYPE_FORMULA:
newCell.setCellFormula(formulasArray[i]);
break;
case Cell.CELL_TYPE_NUMERIC:
newCell.setCellValue(oldCell.getNumericCellValue());
break;
case Cell.CELL_TYPE_STRING:
newCell.setCellValue(oldCell.getRichStringCellValue());
break;
default:
break;
}
}
// If there are any merged regions in the source row, copy to new row
for (int i = 0; i < worksheet.getNumMergedRegions(); i++) {
CellRangeAddress cellRangeAddress = worksheet.getMergedRegion(i);
if (cellRangeAddress.getFirstRow() == sourceRow.getRowNum()) {
CellRangeAddress newCellRangeAddress = new CellRangeAddress(newRow.getRowNum(),
(newRow.getRowNum() +
(cellRangeAddress.getLastRow() - cellRangeAddress.getFirstRow()
)),
cellRangeAddress.getFirstColumn(),
cellRangeAddress.getLastColumn());
worksheet.addMergedRegion(newCellRangeAddress);
}
}
}
이 실장을 실가동 코드로 사용하고 있습니다.
Kotlin에는 다음과 같이 구현되어 있습니다.
fun Sheet.buildRow ( rowNum:Int ) : Row {
val templateRow = this.getRow( rowNum )
this.shiftRows( rowNum+1, sheet.lastRowNum, 1 )
val newRow = this.createRow( rowNum+1 )
templateRow.cellIterator().forEach {
newRow.createCell( it.columnIndex ).cellStyle = it.cellStyle
}
return templateRow
}
셀 값이 아니라 형식만 복사됩니다.Java에도 적용할 수 있습니다.
새 행에서 "업데이트"되는 공식에 대해서는 모든 복사가 이동 후에 이루어지기 때문에 이전 행(현재 새 행에서 한 인덱스 위)은 이미 공식이 이동되었으므로 새 행으로 복사하면 이전 행 셀이 참조됩니다.해결책은 시프트 전에 수식을 해석한 다음 이를 적용하는 것입니다(단순한 String 배열이면 됩니다).몇 줄이면 코드화할 수 있을 겁니다).
기능 시작 시:
ArrayList<String> fArray = new ArrayList<String>();
Row origRow = sheet.getRow(sourceRow);
for (int i = 0; i < origRow.getLastCellNum(); i++) {
if (origRow.getCell(i) != null && origRow.getCell(i).getCellType() == Cell.CELL_TYPE_FORMULA)
fArray.add(origRow.getCell(i).getCellFormula());
else fArray.add(null);
}
그런 다음 셀에 공식을 적용할 때 다음을 수행합니다.
newCell.setCellFormula(fArray.get(i));
저도 최근에 같은 문제에 부딪혔어요.숨겨진 행이 있는 문서에 새 행을 삽입해야 했고 당신과 같은 문제에 직면했습니다.Apache poi 목록에서 검색과 이메일을 몇 개 보낸 후 문서에 행이 숨겨져 있을 때 shiftrows() 버그처럼 보입니다.
언급URL : https://stackoverflow.com/questions/5785724/how-to-insert-a-row-between-two-rows-in-an-existing-excel-with-hssf-apache-poi
'programing' 카테고리의 다른 글
Excel의 셀을 보호하지만 VBA 스크립트에 의해 셀을 수정할 수 있습니다. (0) | 2023.04.14 |
---|---|
WPF에서 콤보박스 컨트롤에 열거형을 바인드하려면 어떻게 해야 합니까? (0) | 2023.04.09 |
소수점을 2배로 하는 문자열을 해석하려면 어떻게 해야 하나요? (0) | 2023.04.09 |
-performSelector:withObject:afterDelay:와 같이 지연 후에 블록을 트리거하려면 어떻게 해야 합니까? (0) | 2023.04.09 |
오류: "INSERT EXEC 문을 중첩할 수 없습니다." 및 "INSERT-EXEC 문 내에서 ROLLBLL 문을 사용할 수 없습니다."어떻게 해결할까요? (0) | 2023.04.09 |