Styling HTML documents
Scala QL allows to customize the resulting HTML document with CSS styles.
Start by importing scalaql:
import scalaql._
import scalaql.html.HtmlStyling
import scalatags.Text.styles._
import scalatags.Text.implicits._
// Docs classes
import scalaql.docs.DocUtils._
// Imports for examples
import java.nio.file.Paths
We'll use the following CSV dataset:
import scalaql.docs.CsvData._
val dir = Paths.get("docs/src/main/resources/annual-enterprise-survey-2020/")
// dir: java.nio.file.Path = docs/src/main/resources/annual-enterprise-survey-2020
val csvInput =         
  csv
   .read[EnterpriseSurvey]
   // In this case it's required to provide correct naming.
   .option(Naming.SnakeCase)
   .directory(dir, globPattern = "**/*.csv")
// csvInput: Iterable[EnterpriseSurvey] = Vector(
//   EnterpriseSurvey(
//     year = 2018,
//     industryCodeAnzsic = "O",
//     industryNameAnzsic = "Public Administration and Safety",
//     rmeSizeGrp = "d_10-19",
//     variable = "Sales, government funding, grants and subsidies",
//     value = "78",
//     unit = "DOLLARS(millions)"
//   ),
//   EnterpriseSurvey(
//     year = 2018,
//     industryCodeAnzsic = "O",
//     industryNameAnzsic = "Public Administration and Safety",
//     rmeSizeGrp = "d_10-19",
//     variable = "Total income",
//     value = "78",
//     unit = "DOLLARS(millions)"
//   ),
//   EnterpriseSurvey(
//     year = 2018,
//     industryCodeAnzsic = "O",
//     industryNameAnzsic = "Public Administration and Safety",
//     rmeSizeGrp = "d_10-19",
//     variable = "Total expenditure",
//     value = "72",
//     unit = "DOLLARS(millions)"
//   ),
//   EnterpriseSurvey(
//     year = 2018,
//     industryCodeAnzsic = "O",
//     industryNameAnzsic = "Public Administration and Safety",
//     rmeSizeGrp = "d_10-19",
//     variable = "Operating profit before tax",
//     value = "6",
//     unit = "DOLLARS(millions)"
//   ),
//   EnterpriseSurvey(
//     year = 2018,
//     industryCodeAnzsic = "O",
//     industryNameAnzsic = "Public Administration and Safety",
//     rmeSizeGrp = "d_10-19",
//     variable = "Total assets",
//     value = "39",
//     unit = "DOLLARS(millions)"
//   ),
//   EnterpriseSurvey(
//     year = 2018,
//     industryCodeAnzsic = "O",
// ...
And then generate the following report:
case class ByIndustry(
  industry:              String,
  totalProfitByIndustry: BigDecimal,
  avgProfitByIndustry:   BigDecimal)
case class ByYear(
  year:               Int,
  totalProfitPerYear: BigDecimal,
  avgProfitPerYear:   BigDecimal,
  byIndustry:         List[ByIndustry])
val reportData: Query[From[EnterpriseSurvey], ByYear] =
  select[EnterpriseSurvey]
    .groupBy(_.year)
    .aggregate { (year, data) =>
      val byIndustry = data.report(_.industryNameAnzsic) { (industry, data) =>
         (
          data.sumBy(_.decimalValue) &&
          data.avgBy(_.decimalValue)
        ).map { case (total, avg) => ByIndustry(industry, total, avg) }
      }
       
      (
        data.sumBy(_.decimalValue) &&
        data.avgBy(_.decimalValue) &&
        byIndustry
      ).map { case (total, avg, byIndustry) =>
        ByYear(year, total, avg, byIndustry)
      }
    }
// reportData: Query[From[EnterpriseSurvey], ByYear] = FROM(CsvData::EnterpriseSurvey) -> GROUP BY(Int) -> AGGREGATE(MdocSession::App::ByYear)
To specify CSS styles for your report, use HtmlStyling builder:
val reportStyle = HtmlStyling.builder[ByYear]
  .forAllHeaders(List(backgroundColor := "red", border := "3px solid #000"))
  .forField(
    _.year,
    List(
      backgroundColor := "blue",
      fontWeight.bold,
      verticalAlign.top,
      textAlign.left,
      border := "2px solid #000"
    )
  )
  .forField(
    _.totalProfitPerYear,
    List(
      backgroundColor := "yellow",
      fontWeight.bold,
      verticalAlign.top,
      textAlign.left,
      border := "2px solid #000"
    )
  )
  .forField(
    _.avgProfitPerYear,
    List(
      backgroundColor := "orange",
      fontWeight.bold,
      verticalAlign.top,
      textAlign.left,
      border := "2px solid #000"
    )
  )
  .forField(
    _.byIndustry.each.industry,
    List(
      backgroundColor := "green",
      fontWeight.bold,
      verticalAlign.top,
      textAlign.left,
      border := "2px solid #000"
    )
  )
  .forField(
    _.byIndustry.each.totalProfitByIndustry,
    List(
      backgroundColor := "gray",
      fontWeight.bold,
      verticalAlign.top,
      textAlign.left,
      border := "2px solid #000"
    )
  )
  .forField(
    _.byIndustry.each.avgProfitByIndustry,
    List(
      backgroundColor := "gray",
      fontWeight.bold,
      verticalAlign.top,
      textAlign.left,
      border := "2px solid #000"
    )
  )
  .withDefaultForFields(
    List(verticalAlign.top, textAlign.left, border := "2px solid #000")
  )
  .build
// reportStyle: HtmlStyling[ByYear] = scalaql.html.HtmlStyling$Configured@6d491633
This is how it could be written as HTML file:
reportData
  .foreach(
    html
      .write[ByYear]
      .option(Naming.WithSpacesCapitalize)
      .option(reportStyle)
      .file(Paths.get("docs/target/report-styled.html"))
  )
  .run(
    from(csvInput)
  )
It will produce a more fancy report:
