Backend/JAVA

XMLSlideShow 자바로 PPT파일 수정하기

dddzr 2023. 3. 5. 15:05

아래 그림같은 형태의 피피티 화면에서 작성일자를 오늘 날짜로 수정하려고 합니다.

이 글에서는 위치를 이용하여 수정할 거라서 아래 그림처럼 수정하고자 하는 요소의 위치를 알아야합니다.

선택되지 않은 부분에서 표로 보이는 것은 바탕이미지라고 생각해주시고 번호는 설명을위해 붙인걸로 봐주세요!!

이런 형태가 여러개의 슬라이드에 반복적으로 있고 그 중 0부터 카운트해서 3번째위치에 있는 텍스트 박스를 전 슬라이드 일괄 수정합니다.

 

XMLSlideShow

XMLSlideShow는 Apache POI 라이브러리를 사용하여 생성된 PowerPoint 프레젠테이션의 내용을 나타내는 Java 객체입니다.

 

getShapes() 이용

 getShapes() 메서드는 슬라이드의 모든 객체(shape) 목록을 반환합니다. 객체는 텍스트 상자, 이미지, 도형 등의 요소를 포함할 수 있습니다. 이 메서드는 반환된 모든 객체를 순회하면서 각 객체의 속성을 변경하거나 삭제할 수 있습니다.

 

 

1. 객체생성 및 슬라이드 가져오기

우선 DB에 ppt데이터가 바이터리 형태로 저장되어 있던 것을 가져온 것을 targetStream이라는 변수에 가져옵니다.

그런다음 XMLSlideShow객체를 생성하고 슬라이드를 가져옵니다.

XMLSlideShow ppt = new XMLSlideShow(targetStream);
List<XSLFSlide> slides = ppt.getSlides();

 

2. 슬라이드 한 장에서 특정 요소 가져오기

첫번째 슬라이드에서 3번째 요소의 text를 가져오는 방법입니다.

XSLFSlide slide = ppt.getSlides().get(0);
XSLFTextShape textShape = (XSLFTextShape) slide.getShapes().get(3);
String text = textShape.getText();

참고로, 텍스트 상자에 있는 모든 텍스트를 가져오는 외에도, getText() 메서드는 텍스트 상자 내에서 선택한 부분의 텍스트를 가져오는 사용할 있습니다. 예를 들어, getText(0, 5) 텍스트 상자의 처음 다섯 글자를 가져옵니다.

 

3. text 변경

setText함수를 이용하여 해당 요소의 text를 변경합니다.

LocalDate now = LocalDate.now();
textShape.setText(now.toString());

 

4. font 사이즈를 변경

for(XSLFTextParagraph paragraph : textShape.getTextParagraphs()){
	for(XSLFTextRun run : paragraph.getTextRuns()){
		run.setFontSize((double) 10);
	}
}

 

모든 슬라이드에 적용한 전체 코드입니다.

public String downloadPPT(HttpServletRequest request, FileData fileInfo, String fileName) {
  FileData fileSource = fileService.getPptData(fileInfo);
  
  String newFileName = fileName + ".pptx";
  try {
    // 파일 이름 인코딩
    EnumHelper.BrowserType browserType = getBrowser(request);
    switch (browserType) {
      case MSIE:
      case MSIE11:
        newFileName = URLEncoder.encode(newFileName, "UTF-8").replaceAll("\\+", "%20");
        break;

      case FIREFOX:
      case OPERA:
      case CHROME:
        newFileName = new String(newFileName.getBytes("UTF-8"), "ISO-8859-1");
        break;
    }

    InputStream targetStream = new ByteArrayInputStream(fileSource.getPptSource());
    XMLSlideShow ppt = new XMLSlideShow(targetStream);
    List<XSLFSlide> slides = ppt.getSlides();
    for(int i = 0 ; i < slides.size(); i++){
      XSLFSlide slide = slides.get(i);
      XSLFTextShape textShape = (XSLFTextShape) slide.getShapes().get(3);
      LocalDate now = LocalDate.now();
      textShape.setText(now.toString());
      for(XSLFTextParagraph paragraph : textShape.getTextParagraphs()){
        for(XSLFTextRun run : paragraph.getTextRuns()){
           run.setFontSize((double) 10); //폰트 크기 설정
        }
     }
    }
    targetStream.close();

    String fileDestPath = destPath + "/" + newFileName;
    FileOutputStream fos = new FileOutputStream(fileDestPath);
    ppt.write(fos);
    ppt.close();
    fos.close();
  } catch (FileNotFoundException e) {
    e.printStackTrace();
  } catch (UnsupportedEncodingException e) {
    e.printStackTrace();
  } catch (IOException e) {
    e.printStackTrace();
  }

  return newFileName;
}

 

 

getPlaceholder()이용

getPlaceholder()와 getShapes()는 모두 XMLSlideShow 클래스에서 제공하는 메서드입니다.

getShapes() 메서드는 슬라이드의 모든 객체(shape) 목록을 반환하는 반면,

getPlaceholder() 메서드는 지정된 슬라이드에서 특정 placeholder의 텍스트 값을 반환합니다. 예를 들어, 제목이나 부제목 placeholder의 텍스트 값을 가져올 수 있습니다.

 

ppt가 제공하는 레이아웃을 그대로 사용하여 작성할 경우에는 placeholder()을 사용할 수 있습니다

 

XMLSlideShow ppt = new XMLSlideShow(targetStream);
XSLFSlide slide = ppt.getSlides().get(0);
XSLFShape titleShape = slide.getPlaceholder(0);
XSLFTextRun titleRun = titleShape.getTextParagraphs().get(0).getTextRuns().get(0);
titleRun.setText("새로운 제목");

//이미지도 변경할 수 있습니다
XSLFPictureShape pictureShape = slide.getPlaceholder(1);
pictureShape.getPictureData().setData(newImageBytes);

 

만약 이런 에러가 나면

Cannot evaluate because of org.eclipse.debug.core.DebugException: com.sun.jdi.InvocationException: Exception occurred in target VM occurred invoking method..

getPlaceholder() 메서드는 해당 슬라이드에 특정 플레이스홀더가 없는 경우 null 반환하므로, 이러한 예외 상황에 대한 처리가 필요합니다.

아래와 같이 getPlaceholder() 메서드를 호출하기 전에 해당 슬라이드에 플레이스홀더가 있는지 먼저 확인하고, 플레이스홀더가 없는 경우에 대한 처리를 추가할  있습니다.

 

XSLFSlide slide = ppt.getSlides().get(0);
XSLFShape shape = null;
if (slide.getPlaceholder(0) != null) { // 플레이스홀더가 없는 경우 처리 
  shape = slide.getPlaceholder(0); 
} else { // shape을 사용하여 나머지 코드 수행 
   
}