다음은 Apache POI로 엑셀(.xlsx / .xls) 파일을 만들 때, 셀에서 셀렉트 박스(드롭다운) 를 구현하는 대표적인 방법들입니다. 엑셀에서 일반적으로 말하는 “셀렉트박스”는 데이터 유효성 검사(Data Validation) 의 목록(List) 기능을 사용해 만듭니다.
(폼 컨트롤의 “콤보박스”도 있지만, 자동화/데이터 입력 목적이라면 대부분 목록 유효성 검사가 권장됩니다.)
(폼 컨트롤의 “콤보박스”도 있지만, 자동화/데이터 입력 목적이라면 대부분 목록 유효성 검사가 권장됩니다.)
1) .xlsx (XSSF) — 문자열 배열로 직접 목록 지정
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidation;
import java.io.FileOutputStream;
public class XlsxDropdownDirectList {
public static void main(String[] args) throws Exception {
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sheet = wb.createSheet("입력");
// 드롭다운을 적용할 영역 (행 1~20, 열 0 = A열)
CellRangeAddressList addressList = new CellRangeAddressList(1, 20, 0, 0);
// 문자열 목록을 직접 지정
DataValidationHelper helper = sheet.getDataValidationHelper();
DataValidationConstraint constraint =
helper.createExplicitListConstraint(new String[]{"사과", "바나나", "체리"});
DataValidation validation = helper.createValidation(constraint, addressList);
validation.setSuppressDropDownArrow(false); // 드롭다운 화살표 표시
validation.setShowErrorBox(true);
sheet.addValidationData(validation);
try (FileOutputStream fos = new FileOutputStream("dropdown_direct_list.xlsx")) {
wb.write(fos);
}
wb.close();
}
특징
- 목록이 코드에 직접 박혀 있음.
- 간단하지만 목록 변경 시 재빌드 필요.
2) .xlsx (XSSF) — 숨김 시트 + 범위(테이블/셀 범위) 참조
실무에서는 목록 데이터를 별도 시트에 두고 그 범위를 참조하는 방식이 유지보수, 확장에 가장 좋습니다.
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidation;
import java.io.FileOutputStream;
public class XlsxDropdownHiddenSheet {
public static void main(String[] args) throws Exception {
XSSFWorkbook wb = new XSSFWorkbook();
// 1) 목록 데이터 시트 생성 및 값 입력
XSSFSheet listSheet = wb.createSheet("목록");
String[] fruits = {"사과", "바나나", "체리", "포도", "멜론"};
for (int i = 0; i < fruits.length; i++) {
Row r = listSheet.createRow(i);
r.createCell(0).setCellValue(fruits[i]);
}
// 2) 이름 범위(Defined Name)로 리스트 범위를 지정 (동적 확장 필요시 테이블/함수 사용 가능)
Name namedRange = wb.createName();
namedRange.setNameName("Fruits");
// A1:A5 을 범위로 지정
String refersTo = "목록!$A$1:$A$" + fruits.length;
namedRange.setRefersToFormula(refersTo);
// 3) 입력 시트 생성 및 데이터 유효성 검사(목록) 적용
XSSFSheet inputSheet = wb.createSheet("입력");
CellRangeAddressList addressList = new CellRangeAddressList(1, 50, 0, 0); // A2:A51
DataValidationHelper helper = inputSheet.getDataValidationHelper();
// 목록을 이름 범위로 참조
DataValidationConstraint constraint =
helper.createFormulaListConstraint("Fruits");
DataValidation validation = helper.createValidation(constraint, addressList);
validation.setSuppressDropDownArrow(false);
validation.setShowErrorBox(true);
inputSheet.addValidationData(validation);
// 4) 목록 시트 숨김
int idx = wb.getSheetIndex(listSheet);
wb.setSheetHidden(idx, true); // 혹은 wb.setSheetHidden(idx, Workbook.SHEET_STATE_VERY_HIDDEN);
try (FileOutputStream fos = new FileOutputStream("dropdown_hidden_sheet.xlsx")) {
wb.write(fos);
}
wb.close();
}
장점
- 목록 데이터만 수정하면 드롭다운이 자동 반영.
- 목록 시트를 숨겨 사용자에게는 깔끔하게 보임.
- 여러 열/셀에서 같은 목록을 쉽게 재사용.
팁: 목록이 자주 변하면 Table(엑셀 테이블)을 만들고 =테이블명[열명]을 참조하거나, OFFSET/COUNTA 등으로 동적 이름 범위를 구성하면 유지보수가 수월합니다
3) .xls (HSSF) — 구버전 형식 지원
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import java.io.FileOutputStream;
public class XlsDropdown {
public static void main(String[] args) throws Exception {
HSSFWorkbook wb = new HSSFWorkbook();
Sheet sheet = wb.createSheet("입력");
CellRangeAddressList addressList = new CellRangeAddressList(1, 20, 0, 0);
DataValidationHelper helper = sheet.getDataValidationHelper();
DataValidationConstraint constraint =
helper.createExplicitListConstraint(new String[]{"A", "B", "C"});
DataValidation validation = helper.createValidation(constraint, addressList);
validation.setSuppressDropDownArrow(false);
validation.setShowErrorBox(true);
sheet.addValidationData(validation);
try (FileOutputStream fos = new FileOutputStream("dropdown_xls.xls")) {
wb.write(fos);
}
wb.close();
}