ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • apache poi 를 사용해 scala 에서 Excel 파일 읽기
    scala/basic 2021. 10. 14. 11:17
      def main(args: Array[String]): Unit = {
        val rows = readSheet[MyModel]("c:/work/input.xlsx", "평가 항목", true)
        println(rows)
      }

    문제

    apache poi 를 사용해 Excel 파일을 읽어보자. apache poi 는 자바 라이브러리지만 스칼라 스타일로 코딩해 보도록 한다.

     

    코드

    일반적으로 사용할 수 있도록 아래처럼 Generic 한 util 을 작성한다.

    import org.apache.poi.openxml4j.opc.OPCPackage
    import org.apache.poi.ss.usermodel.{Row, Workbook}
    import org.apache.poi.xssf.usermodel.XSSFWorkbook
    
    import java.io.File
    import scala.collection.JavaConverters._
    
    trait RowConverter[A] {
      def from(row: Row): A
    }
    
    object ExcelUtil {
      def readSheet[A: RowConverter](path: String, sheetName: String, hasHeader: Boolean): Seq[A] = {
        val rowConverter = implicitly[RowConverter[A]]
    
        val pkg                = OPCPackage.open(new File(path))
        val workbook: Workbook = new XSSFWorkbook(pkg)
    
        val sheet               = workbook.getSheet(sheetName)
        val rows: Iterator[Row] = sheet.iterator().asScala
    
        // header 제거
        val convertedRows: Seq[A] = rows
          .filterNot(hasHeader && _.getRowNum == 0)
          .map(rowConverter.from)
          .toList
    
        workbook.close()
        pkg.close()
        convertedRows
      }
    }

     

    사용 목적에 맞게 모델링 하고, implicit instance 를 구현해 준다.

    import org.apache.poi.ss.usermodel.Row
    
    case class MyModel(
      no: Int,
      keyword: String,
      residence: Option[String]
    )
    
    object MyModel {
      implicit val rowConverterInstance: RowConverter[MyModel] = new RowConverter[MyModel] {
        override def from(row: Row): MyModel = {
          val no         = row.getCell(0).getNumericCellValue.toInt
          val keyword    = row.getCell(1).getStringCellValue
          val residence  = Option(row.getCell(2)).map(_.getStringCellValue)
          MyModel(no, keyword, residence)
        }
      }
    }

     

    마지막으로 아래처럼 사용하면 된다.

      def main(args: Array[String]): Unit = {
        val convertedRows: Seq[MyModel] = readSheet[MyModel]("c:/now/input.xlsx", "평가 항목", true)
        println(convertedRows)
      }

     

    'scala > basic' 카테고리의 다른 글

    scala enumeratum enum 사용하기  (0) 2021.11.13
    Variance 문제  (3) 2021.10.22
    Scala State Monad  (3) 2021.08.03
    Pattern Match 조합 - Email 주소 예제  (0) 2021.07.27
    enum 을 사용한 모델링  (0) 2021.07.23

    댓글

Designed by Tistory.