在Github上面看到一个针对SparkSQL加载Excel数据源的开源组件,拿过来测试了一下spark-excel
1.Spark Excel库
用于使用Apache Spark查询Excel文件的库,用于Spark SQL和DataFrames。
此包允许将Excel电子表格作为Spark DataFrames进行查询。
2.Spark版本要求
该库需要Spark 2.0+
3.重新编译
在github上面该项目代码是用scala2.11版本编译的,我本地测试环境是spark2.4 scala 2.12.8 所以下载源码在服务器上重新编译了一下。如果你使用的是scala2.11版本则可以跳过该步骤。
3.1.安装sbt
因为该项目使用sbt编译的,需要安装sbt 下载好sbt上传到服务器上之后配置环境变量即可。
3.2.下载源码
下载spark-excel源码,并上传服务器。
3.3.修改build.sbt配置
修改Spark 版本到2.4.0
修改scala 版本到2.12.8 如下图

3.4.打包

4.添加依赖
在pom.xml中添加依赖 或手动导入刚刚编译的包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <dependency> <groupId>com.norbitltd</groupId> <artifactId>spoiwo_2.12</artifactId> <version>1.4.1</version> </dependency>
<dependency> <groupId>com.monitorjbl</groupId> <artifactId>xlsx-streamer</artifactId> <version>2.1.0</version> </dependency>
|
5.读取Excel文件
5.1 代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
object ExcelData { def main(args: Array[String]): Unit = { val spark = SparkUtils.getSparkSession("ExcelData", 4) val sqlContext = spark.sqlContext val filePath = "D:\\test.xlsx" val schema = StructType(List( StructField("c1", StringType, nullable = false), StructField("c2", StringType, nullable = false), StructField("c3", StringType, nullable = false), StructField("c4", StringType, nullable = false), StructField("c5", StringType, nullable = false))) load(filePath,spark,schema) }
def load(filePath:String,spark:SparkSession,schema:StructType): Unit ={ val df = spark.read .format("com.crealytics.spark.excel") .option("dataAddress", "'Sheet2'!A1:G2") .option("useHeader", "false") .option("treatEmptyValuesAsNulls", "true") .option("inferSchema", "true") .schema(schema) .load(filePath) df.show() } }
|
5.2 表格样式
5.2.1 是否使用表头
|
A |
B |
C |
D |
E |
| 1 |
a1 |
a2 |
a3 |
a4 |
a5 |
| 2 |
xiaol |
xiaom |
xiaoh |
xiaoy |
xiaog |
是否使用表头,不使用的话自己命名表头(_c0), 如果使用则第一行为表头
参数名称: .option(“useHeader”, “false”) //参数为必须
1 2 3
| .option("dataAddress", "'Sheet2'!A1:E2") .option("useHeader", "true") df.show()
|
| _c0 |
_c1 |
_c2 |
_c3 |
_c4 |
| a1 |
a2 |
a3 |
a4 |
a5 |
| xiaol |
xiaom |
xiaoh |
xiaoy |
xiaog |
1 2 3
| .option("dataAddress", "'Sheet2'!A1:E2") .option("useHeader", "false") df.show()
|
| a1 |
a2 |
a3 |
a4 |
a5 |
| xiaol |
xiaom |
xiaoh |
xiaoy |
xiaog |
5.2.2 选择数据区域
1 2 3
| .option("dataAddress", "'Sheet2'!A1:C1") .option("useHeader", "false") df.show()
|
5.2.3 修改空单元格
如果表格中有空数据但不做处理的话会抛出异常
可以使用 .option(“treatEmptyValuesAsNulls”, “true”) // 可选, 默认: true
参数将空的单元格设置为null
|
A |
B |
C |
D |
E |
| 1 |
a1 |
a2 |
a3 |
a4 |
a5 |
| 2 |
xiaol |
xiaom |
xiaoh |
|
xiaog |
如上面表格中D2单元格为空的
设置替换空数值之后表格内容如下:
1 2 3
| .option("useHeader", "true") .option("treatEmptyValuesAsNulls", "true") df.show()
|
| _c0 |
_c1 |
_c2 |
_c3 |
_c4 |
| a1 |
a2 |
a3 |
a4 |
a5 |
| xiaol |
xiaom |
xiaoh |
null |
xiaog |
5.2.4 设置schema
设置schema 时需要注意在表格中String 类型数据的单元格不能有为空否则会报空指针。
如果设置范围的列数多余schame的列数那么多余的数据不会读取出来。
参数名称:**.schema(schema) **// 可选
|
A |
B |
C |
D |
E |
| 1 |
a1 |
a2 |
a3 |
a4 |
a5 |
| 2 |
xiaol |
xiaom |
xiaoh |
xiaoy |
xiaog |
1 2 3 4 5 6 7 8 9 10 11 12
| val schema = StructType(List( StructField("c1", StringType, nullable = false), StructField("c2", StringType, nullable = false), StructField("c3", StringType, nullable = false), StructField("c4", StringType, nullable = false), StructField("c5", StringType, nullable = false))) .option("useHeader", "false") .schema(schema) df.show()
|
| c1 |
c2 |
c3 |
c4 |
c5 |
| a1 |
a2 |
a3 |
a4 |
a5 |
| xiaol |
xiaom |
xiaoh |
xiaoy |
xiaog |
6.保存数据到Excel文件中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| import hnbian.spark.utils.SparkUtils import org.apache.spark.sql.{DataFrame, SparkSession} import org.apache.spark.sql.types._
object ExcelData { def main(args: Array[String]): Unit = { val spark = SparkUtils.getSparkSession("ExcelData", 4) val sqlContext = spark.sqlContext val filePath = "D:\\test.xlsx" val fileSavePath = "D:\\testWrite.xlsx" val schema = StructType(List( StructField("c1", StringType, nullable = false), StructField("c2", StringType, nullable = false), StructField("c3", StringType, nullable = false), StructField("c4", StringType, nullable = false), StructField("c5", StringType, nullable = false), StructField("c6", DateType, nullable = false))) val df = load(filePath,spark,schema) save(fileSavePath,df) }
def save(filePath:String,df:DataFrame): Unit ={ df.write .format("com.crealytics.spark.excel") .option("dataAddress", "'Sheet'!A1:E2") .option("useHeader", "true") .mode("append") .save(filePath) }
def load(filePath:String,spark:SparkSession,schema:StructType): DataFrame ={ val df = spark.read .format("com.crealytics.spark.excel") .option("dataAddress", "'Sheet2'!A1:E2") .option("useHeader", "false") .option("treatEmptyValuesAsNulls", "true") .option("inferSchema", "true") .schema(schema) .load(filePath) df.show() df } }
|