最近需要使用Spark SQL清洗Excel的数据,在网上找到了spark-excel
<dependency>
<groupId>com.crealytics</groupId>
<artifactId>spark-excel_2.12</artifactId>
<version>0.13.7</version>
</dependency>
这个依赖包洗一些简单的Excel数据是没有问题的,但是遇到复杂一点的就不好处理了。这里介绍一下今天踩得坑
如果要读取的Excel文本中含有URLEncoder编码的超链接,会报错,因为这个jar包是没有处理这方面的东西。如果要是遇到这种问题建议直接放弃使用该依赖,直接使用poi依赖自己写
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.1</version>
</dependency>
而且导入poi依赖之后需要删掉spark-Excel的依赖,不然也报错。关于如何使用poi在网上随便搜就有,因为我这里希望生成DataFrame,所以我一般用case class样例类生成一个对象,之后放到Seq集合,再用spark读取,生成DataFrame,像下面这样spark 官方给的例子
* import spark.implicits._
* case class Person(name: String, age: Long)
* val data = Seq(Person("Michael", 29), Person("Andy", 30), Person("Justin", 19))
* val ds = spark.createDataset(data)
*
* ds.show()
* // +-------+---+
* // | name|age|
* // +-------+---+
* // |Michael| 29|
* // | Andy| 30|
* // | Justin| 19|
* // +-------+---+
这个的问题就是处理起来比较繁琐,但是省心,自己想咋调就咋调。
当你使用SparkSql清洗时,得到的会是1/10/21这样格式倒置的数据。我去了spark-excel的仓库看了下,里面也有人提相同的问题,但是估计作者比较忙,还没有优化这一项,据作者回复以后会直接增加一个dateFormat的选项,但是我今天在源码里面看了,在DataFrameWrite里面有dateFormat参数,Reader里面是没有的,所以只能自己解决,我这边就比较简单粗暴,直接按‘/’分割,然后拼接起来。
concat_ws("-", concat(lit("20"),split($"Subscription Date", "/")(2)),
when(length(split($"Subscription Date", "/")(0))===1,concat(lit(0),split($"Subscription Date", "/")(0)))
.otherwise(split($"Subscription Date", "/")(0)),
when(length(split($"Subscription Date", "/")(1))===1,concat(lit(0),split($"Subscription Date", "/")(1)))
.otherwise(split($"Subscription Date", "/")(1))
).as("subscription_date"),
等后续有空我也会尝试参与一下spark-excel的开发工作,毕竟开源社区要大家一起贡献呀。