본문 바로가기

JAVA (Excel 관련)

엑셀 출력 테스트( naver book api -> 엑셀 출력 )

네이버 developers에서 제공하는 책 상세 검색 결과 조회를 엑셀로 출력해 보고 싶은 생각이 나서 주말에 시간을 내어 만들어보았다.

오랜만에 엑셀 관련 작업을 하니 먼가 쉬운듯 어려운듯.. 
간단하게 구현한 부분만 남겨보겠다.

 

 		String client_id = "{네이버 클라이언트 아이디}";
        String client_secret = "{네이버 클라이언트 비밀번호}";

        try {

            URI uri = UriComponentsBuilder
                    .fromUriString("https://openapi.naver.com")
                    .path("/v1/search/book_adv.json")
                    .queryParam("d_titl", "주식")
                    .queryParam("display", 10)
                    .queryParam("start", 1)
                    .encode()
                    .build()
                    .toUri();

            RequestEntity<Void> requestEntity = RequestEntity.get(uri)
                    .header("X-Naver-Client-Id", client_id)
                    .header("X-Naver-Client-Secret", client_secret)
                    .build();

            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<BookDto> responseEntity = restTemplate.exchange(requestEntity, BookDto.class);
            System.out.println("responseEntity = " + responseEntity);

 

UriCompnent를 사용해서 간편하게 param의 값을 UTF-8 로 인코딩해서 get 요청을 전달했다.

주의점으로는 header에 클라이언트 id, secret을 꼭 추가해 줘야 인증오류가 발생하지 않는다.

 

 if (statusCode.value() == 200) {

                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
                String lastBuildDate = responseEntity.getBody().getLastBuildDate();
                LocalDateTime dateTime = LocalDateTime.parse(lastBuildDate, formatter);

                List<BookResultDto> resultList = new ArrayList<>();
                List<ItemDto> items = responseEntity.getBody().getItems();

                for (ItemDto item : items) {
                    String title = item.getTitle();
                    String author = item.getAuthor();
                    String publisher = item.getPublisher();
                    Long isbn = item.getIsbn();
                    String image = item.getImage();
                    String subImageThumbName = item.getImage().substring(item.getImage().lastIndexOf("/") + 1);

                    BookResultDto resultDto = BookResultDto.builder()
                            .title(title)
                            .author(author)
                            .publisher(publisher)
                            .isbn(isbn)
                            .subImageThumbName(subImageThumbName)
                            .image(image)
                            .build();

                    resultList.add(resultDto);
                }

                XSSFWorkbook workbook = new XSSFWorkbook();
                XSSFSheet firstSheet = workbook.createSheet("book_sheet");

                //타이틀 행 생성
                XSSFRow rowA = firstSheet.createRow(0);
                XSSFCell cellA = rowA.createCell(0);
                cellA.setCellValue(new XSSFRichTextString("책제목"));
                XSSFCell cellB = rowA.createCell(1);
                cellB.setCellValue(new XSSFRichTextString("저자"));
                XSSFCell cellC = rowA.createCell(2);
                cellC.setCellValue(new XSSFRichTextString("출판사"));
                XSSFCell cellD = rowA.createCell(3);
                cellD.setCellValue(new XSSFRichTextString("isbn"));
                XSSFCell cellE = rowA.createCell(4);
                cellE.setCellValue(new XSSFRichTextString("이미지이름"));
                XSSFCell cellF = rowA.createCell(5);
                cellF.setCellValue(new XSSFRichTextString("이미지"));

                for (int i = 1; i < resultList.size(); i++) {

                    XSSFRow row = firstSheet.createRow(i);
                    XSSFCell cellTitle = row.createCell(0);
                    cellTitle.setCellValue(new XSSFRichTextString(resultList.get(i-1).getTitle()));
                    XSSFCell cellAuthor = row.createCell(1);
                    cellAuthor.setCellValue(new XSSFRichTextString(resultList.get(i-1).getAuthor()));
                    XSSFCell cellCompany = row.createCell(2);
                    cellCompany.setCellValue(new XSSFRichTextString(resultList.get(i-1).getPublisher()));
                    XSSFCell cellIsbn = row.createCell(3);
                    cellIsbn.setCellValue(new XSSFRichTextString(String.valueOf(resultList.get(i-1).getIsbn())));
                    XSSFCell cellThumbName = row.createCell(4);
                    cellThumbName.setCellValue(new XSSFRichTextString(String.valueOf(resultList.get(i-1).getSubImageThumbName())));

                    URL url = new URL(resultList.get(i - 1).getImage());
                    InputStream inputStream = url.openStream();
                    BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
                    byte[] bytes = IOUtils.toByteArray(bufferedInputStream);// inputStream -> byte[]
                    int prictureIdx = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG); // 해당 byte[] -> jpg 이미지로 메모리에 올려두고 -> id 반환
                    bufferedInputStream.close();

                    //앵커 클래스(이미지 위치 지정) , drawing(이미지 cell에 출력)을 위해 helper 클래스 생성
                    XSSFCreationHelper helper = workbook.getCreationHelper();
                    //앵커 클래스로 사진 위치 지정
                    XSSFClientAnchor anchor = helper.createClientAnchor();
                    anchor.setCol1(5);
                    anchor.setRow1(i);

                    anchor.setCol2(6);
                    anchor.setRow2(i+1);

                    //메모리에 올라간 jpg 파일을 앵커 위치에 가져오기
                    Drawing<XSSFShape> drawing = firstSheet.createDrawingPatriarch();
                    Picture picture = drawing.createPicture(anchor, prictureIdx);

                    XSSFCell cellImage = row.createCell(5);
                    int w = 20 * 256;
                    firstSheet.setColumnWidth(5,w); //셀 가로길이는 셀 공통이므로
                    short h = 100 * 20;
                    cellImage.getRow().setHeight(h); //셀 높이는 셀마다 다르게 가능
                }

                FileOutputStream fileOutputStream = new FileOutputStream("D:\\study\\file\\result\\isbn.xls");
                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
                workbook.write(fileOutputStream);
                bufferedOutputStream.close();

                System.out.println("성공");
            }

 

받아온 책 응답정보들을 Workbook을 통해서  엑셀로 그려주면 된다.

좀 어려웠던 점은 jpg 이미지 파일을 가져와서 ClientAnchor(앵커 -> 고정 부분) 에 넣어주는 건데
몇번 테스트하다보면 맞는 위치를 찾을 수 있다.
참고바란다.