首页 > 解决方案 > 如何在 Scala/Spark 中创建包含来自多个 DataFrame 的多个工作表的 excel 文件?

问题描述

Scala/Spark应用程序中,我创建了两个不同的 DataFrame。我的任务是为每个 DataFrame 创建一个带有两张工作表的 excel 文件。

我决定使用spark-excel库,但我有点困惑。据我了解,未来的excel文件是保存在hdfs文件系统中的吧?我需要在.save()方法中设置未来excel文件的路径,对吗?另外我不明白应该dataAddress选择什么格式?

import org.apache.spark.sql.Dataset
import spark.implicits._

val df1 = Seq(
    ("2019-01-01 00:00:00", "7056589658"),
    ("2019-02-02 00:00:00", "7778965896")
).toDF("DATE_TIME", "PHONE_NUMBER")

df1.show()

val df2 = Seq(
    ("2019-01-01 01:00:00", "194.67.45.126"),
    ("2019-02-02 00:00:00", "102.85.62.100"),
    ("2019-03-03 03:00:00", "102.85.62.100")
).toDF("DATE_TIME", "IP")

df2.show()

df1.write
    .format("com.crealytics.spark.excel")
    .option("dataAddress", "'First'!A1:B1000")
    .option("useHeader", "true")
    .mode("append")
    .save("/hdd/home/NNogerbek/data.xlsx")

df2.write
    .format("com.crealytics.spark.excel")
    .option("dataAddress", "'Second'!A1:B1000")
    .option("useHeader", "true")
    .mode("append")
    .save("/hdd/home/NNogerbek/data.xlsx")

标签: excelscaladataframeapache-sparkspark-excel

解决方案


首先这是我使用的Maven 依赖项

<!-- https://mvnrepository.com/artifact/com.crealytics/spark-excel -->
<dependency>
    <groupId>com.crealytics</groupId>
    <artifactId>spark-excel_2.11</artifactId>
    <version>0.12.0</version>
</dependency>

提问:据我了解以后的excel文件是保存在hdfs文件系统中的吧?我需要在 .save() 方法中设置未来 excel 文件的路径,对吧?另外我不明白 dataAddress 选项中应该采用什么格式?


什么是数据地址?来自文档

数据地址:可以使用 dataAddress 选项指定要读取或写入的数据的位置。目前支持以下地址样式:

B3:数据的起始单元格。读取将返回下方的所有行和右侧的所有列。写作将从这里开始,并根据需要使用尽可能多的列和行。B3:F35:数据单元格范围。读取将仅返回指定范围内的行和列。写入将从第一个单元格(本例中为 B3)开始,并且仅使用指定的列和行。如果 DataFrame 中有更多行或列要写入,它们将被截断。确保这是您想要的。'我的工作表'!B3:F35:与上面相同,但具有特定工作表。MyTable[#All]:数据表。读取将返回此表中的所有行和列。写入只会在表的当前范围内写入。不会执行表的增长


所以 "My Sheet1'!B3:C35" 意味着你告诉 api... 我的 Sheet1 和 B3:C35

excel表格中的列位置..

以下是我实现期望的完整清单。


package com.examples

import org.apache.log4j.{Level, Logger}
import org.apache.spark.sql.SparkSession

object ExcelTest {
  def main(args: Array[String]) {
    import org.apache.spark.sql.functions._
    Logger.getLogger("org").setLevel(Level.OFF)

    val spark = SparkSession.builder.
      master("local")
      .appName(this.getClass.getName)
      .getOrCreate()
    import spark.implicits._
    val df1 = Seq(
      ("2019-01-01 00:00:00", "7056589658"),
      ("2019-02-02 00:00:00", "7778965896")
    ).toDF("DATE_TIME", "PHONE_NUMBER")

    df1.show()

    val df2 = Seq(
      ("2019-01-01 01:00:00", "194.67.45.126"),
      ("2019-02-02 00:00:00", "102.85.62.100"),
      ("2019-03-03 03:00:00", "102.85.62.100")
    ).toDF("DATE_TIME", "IP")

    df2.show()

    df1.coalesce(1).write
      .format("com.crealytics.spark.excel")
      .option("dataAddress", "'My Sheet1'!B3:C35")
      .option("useHeader", "true")
      .option("dateFormat", "yy-mmm-d")
      .option("timestampFormat", "mm-dd-yyyy hh:mm:ss")
      .mode("append")
      .save(".\\src\\main\\resources\\testexcel.xlsx")

    df2.coalesce(1).write
      .format("com.crealytics.spark.excel")
      .option("dataAddress", "'My Sheet2'!B3:C35")
      .option("useHeader", "true")
      .option("dateFormat", "yy-mmm-d")
      .option("timestampFormat", "mm-dd-yyyy hh:mm:ss")
      .mode("append")
      .save(".\\src\\main\\resources\\testexcel.xlsx")
  }
}

注意: .coalesce(1) 将创建单个文件而不是多个部分文件...

结果:因为我使用本地结果将保存在本地,如果它的纱线将在 hdfs 中。如果你想使用像s3这样的云存储,也可以用yarn作为master。基本上这是根据您的要求...

在此处输入图像描述

表 1:

![在此处输入图像描述


第 2 页:

在此处输入图像描述

另外,1)请参阅我的文章如何使用 Apache Spark Scala 使用 Excel 表格进行简单报告?
2)在这里查看我的答案
希望有帮助!!


推荐阅读