20

I would like to use Apache POI to read/create Excel files in an Scala app. Sure, I can use the POI library directly, it's Java after all, but I would like to have the Scala feel. So is there a Scala wrapper bringing the Scala feel (using implicit conversions), i.e. some kind of "Scala-POI-DSL" freely available?

Peter Kofler
  • 9,252
  • 8
  • 51
  • 79

6 Answers6

13

Thanks to Dave Griffith's answer, I've hacked something similar to his DSL.

Workbook {
      Sheet("name") {
        Row(1) {
          Cell(1, "data") :: Cell(2, "data2") :: Nil
        } ::
        Row(2) {
          Cell(1, "data") :: Cell(2, "data2") :: Nil
        } :: Nil
      } ::
      Sheet("name2") {
        Row(2) {
          Cell(1, "data") :: Cell(2, "data2") :: Nil
        } :: Nil
      } :: Nil
    }.save("/home/path/ok.xls")

Code can be found here.

George
  • 8,368
  • 12
  • 65
  • 106
10

Given the lack of advanced, open source spreadsheet wrappers for Scala, I've started the development of Spoiwo: https://github.com/norbert-radyk/spoiwo. It allows the generation of the XSSFWorkbook and supports a significant subset of POI's functionality.

It still requires a bit of documentation, but the below should give a rough idea about its capabilities:

The example of simple spreadsheet using Spoiwo:

object GettingStartedExample {

  val headerStyle =
    CellStyle(fillPattern = CellFill.Solid, fillForegroundColor = Color.AquaMarine, fillBackgroundColor = Color.AquaMarine, font = Font(bold = true))

  val gettingStartedSheet = Sheet(name = "Some serious stuff")
    .withRows(
      Row(style = headerStyle).withCellValues("NAME", "BIRTH DATE", "DIED AGED", "FEMALE"),
      Row().withCellValues("Marie Curie", new LocalDate(1867, 11, 7), 66, true),
      Row().withCellValues("Albert Einstein", new LocalDate(1879, 3, 14), 76, false),
      Row().withCellValues("Erwin Shrodinger", new LocalDate(1887, 8, 12), 73, false)
    )
    .withColumns(
      Column(index = 0, style = CellStyle(font = Font(bold = true)), autoSized = true)
    )

  def main(args: Array[String]) {
    gettingStartedSheet.saveAsXlsx("C:\\Reports\\getting_started.xlsx")
  }
} 
Norbert Radyk
  • 2,608
  • 20
  • 24
  • Thanks for this module! I really love the idea of functional style in report generation. I have a small problem: how it would be possible to use this module in play framework? I'm trying to return a file in controller but I need somehow serialize com.norbitltd.spoiwo.model.Sheet to HTTP response. – Sayat Satybald Feb 25 '15 at 03:43
  • Thanks for your comment and question. The simple answer is: the same way you'd use Apache POI - since you can transform it to the original POI Sheet (just call com.norbitltd.spoiwo.model.Sheet.convertAsXlsx()) and Spoiwo is just a wrapper :) Please let me know how you imagined it working with your application and hopefully I can suggest a better approach. – Norbert Radyk Feb 25 '15 at 08:32
  • As far as I know there's no serializer for XLSX Worbook to HTTP response in Play Framework. I've used a hack to save a file and then return it as a file. Though, I don't like this solution as I need to save a file. Here's a code: http://stackoverflow.com/a/28711403/2586315 – Sayat Satybald Feb 25 '15 at 10:08
  • @NorbertRadyk does SPOIWO support reading xsl / xslx files in a functional style just as it does for creating them? TKS! – juanpavergara Jan 03 '17 at 00:28
  • Unfortunately, it's just a creation-only library as of today. – Norbert Radyk Jan 16 '17 at 23:46
5

Fancy POI - Not much info to be found it seems but I guess it is what you're looking for.

Wivani
  • 2,036
  • 22
  • 28
  • This looks more complete, but there is no documentation, example or unit test. Need to figure out, how this is used... – Peter Kofler Dec 16 '11 at 22:23
4

This is utterly unhelpful, but I hacked up an Scala-ish DSL for POI. It allows code like

Workbook{
  Sheet("Multiplication"){
      for(i<-1 to 10){
         Row{
           for(j<-1 to 10){
             Cell(i*j)
           }
         }
      }
  }
}.writeToFile("multiplication.xls")

Sadly I can't give it out without checking with my boss, but to be honest it wasn't that hard to do. You should be able to reverse-engineer most of it from that example without much trouble.

Dave Griffith
  • 20,435
  • 3
  • 55
  • 76
2

If you're writing Office XML, you could consider avoiding POI and creating the XML directly (plus archiving it together). For simple spreadsheets it's pretty simple to do it, and you're eliminating a lot of variables.

Note that with POI's OOXML support you'll need to use its streaming mode if you intend to create large spreadsheets (greater than 65k rows).

Ross Judson
  • 1,132
  • 5
  • 11
1

I don't know of any Scala library for this kind of encapsulation.

Most questions around using apache POI are about iterators.
And the alexcheng project does import an Excel document, and has a test case.
But that's about it.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250