PDDocument doc = new PDDocument();
✅ PDDocument 문서를 만드는 함수
이것은 PDF 문서의 메모리 내 표현입니다. 문서가 더 이상 필요하지 않으면 #close() 메서드를 호출해야 합니다.
-> save(fileName); //저장할 파일명
-> doc.addPage(page); //문서에 페이지 추가
public void save(String fileName)
public void addPage(PDPage page) 으로 사용
✅ PDPage
PDPage page = new PDPage(new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth())); // 가로A4
doc.addPage(page);
✅ PDType0Font
PDType0Font font = PDType0Font.load(doc, new File("C:/Windows/Fonts/malgun.ttf"));
사용자 정의 글꼴등을 매핑할때 사용하는 클래스
TTF 파일을 불러와서 Type 0 글꼴로 문서에 삽입합니다.
public static PDType0Font load(PDDocument doc,File file) throws IOException
doc - 글꼴을 포함할 doc문서
file - 글꼴 위치
✅ PDPageContentStream
PDPageContentStream cs = new PDPageContentStream(doc, page);
페이지에 글쓰는 메소드
-> 페이지 콘텐츠 스트림에 쓸 수 있는 기능을 제공
public void setNonStrokingColor(Color color)
throws IOException
채우기 작업 -> 셀배경
public void addRect(float x, float y,
float width, float height) throws IOException
현재 경로에 사각형 추가
x - The lower left x coordinate.
y - The lower left y coordinate.
width - 직사각형의 너비
height - 직사각형의 높이
public void stroke() throws IOException
길따라 그리기
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class BomPdfGenerator {
// 컬럼 너비 (가로 A4 기준, 포인트 단위)
private static final float[] COL_WIDTHS = {30f, 80f, 130f, 35f, 70f, 437f};
private static final String[] HEADERS = {"순번", "아이템 ID", "아이템 이름", "수량", "BL:대분류", "BL:규격"};
private static final float ROW_HEIGHT = 20f;
private static final float MARGIN = 30f;
private static final float FONT_SIZE = 8f;
private static final float HEADER_SIZE = 10f;
public static void generate(List<BomItem> bomList, String outputPath) throws IOException {
PDDocument doc = new PDDocument();
PDPage page = new PDPage(new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth())); // 가로A4
doc.addPage(page);
// 한글 폰트 (malgun.ttf - 맑은고딕)
PDType0Font font = PDType0Font.load(doc, new File("C:/Windows/Fonts/malgun.ttf"));
PDType0Font fontBold = PDType0Font.load(doc, new File("C:/Windows/Fonts/malgunbd.ttf"));
PDPageContentStream cs = new PDPageContentStream(doc, page);
float pageWidth = page.getMediaBox().getWidth();
float pageHeight = page.getMediaBox().getHeight();
//테이블 시작 Y 위치
float tableTop = pageHeight - MARGIN - 25f;
float startX = MARGIN;
// 헤더 행
drawRow(cs, fontBold, HEADER_SIZE, HEADERS, startX, tableTop,
COL_WIDTHS, ROW_HEIGHT, new Color(44, 62, 80), Color.WHITE, true);
// 데이터 행
for (int i = 0; i < bomList.size(); i++) {
BomItem item = bomList.get(i);
String[] row = {
String.valueOf(item.index),
item.itemId,
item.itemName,
item.quantity,
item.large,
item.spec
};
float y = tableTop - ROW_HEIGHT * (i + 1);
drawRow(cs, font, FONT_SIZE, row, startX, y,
COL_WIDTHS, ROW_HEIGHT, Color.WHITE, Color.BLACK, false);
}
cs.close();
doc.save(outputPath);
doc.close();
System.out.println("PDF 저장 완료: " + outputPath);
}
// 한 행 그리기
private static void drawRow(PDPageContentStream cs,
PDType0Font font, float fontSize,
String[] texts,
float x, float y,
float[] colWidths, float rowHeight,
Color bgColor, Color textColor,
boolean isHeader) throws IOException {
float cx = x;
for (int i = 0; i < colWidths.length; i++) {
// 셀 배경
cs.setNonStrokingColor(bgColor);
cs.addRect(cx, y, colWidths[i], rowHeight);
cs.fill();
// 셀 테두리
cs.setStrokingColor(Color.GRAY);
cs.addRect(cx, y, colWidths[i], rowHeight);
cs.stroke();
// 텍스트
cs.setNonStrokingColor(textColor);
cs.beginText();
cs.setFont(font, fontSize);
cs.newLineAtOffset(cx + 4, y + 6); // 좌측 패딩 4, 하단 패딩 6
String text = texts[i] != null ? texts[i] : "";
cs.showText(text);
cs.endText();
cx += colWidths[i];
}
}
}