Permalink
Browse files

initial commit

  • Loading branch information...
axtstar committed Jun 26, 2018
1 parent 02a442a commit b15b9e80147a341f4d69dff2034eee628cfe8282
View
@@ -0,0 +1 @@
target/
View
@@ -0,0 +1,14 @@
name := "asta4e"
version := "0.0.1"
scalaVersion := "2.12.4"
libraryDependencies ++= Seq(
// https://mvnrepository.com/artifact/org.apache.poi/poi
"org.apache.poi" % "poi" % "3.17",
"org.apache.poi" % "poi-ooxml" % "3.17",
"junit" % "junit" % "4.12" % Test,
"org.specs2" %% "specs2-core" % "4.2.0" % Test,
"org.specs2" %% "specs2-junit" % "4.3.0-9613e1025-20180617171339" % Test
)
View
@@ -0,0 +1 @@
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.7")
View
@@ -0,0 +1 @@
sbt.version=1.1.2
View
@@ -0,0 +1,3 @@
# asta4e
This library provide a template engine functionality for Excel as sama as asta4d
@@ -0,0 +1,221 @@
package com.astamuse.asta4e
import java.io.{File, FileInputStream, FileOutputStream}
import org.apache.poi.ss.usermodel.{Cell, WorkbookFactory}
import org.apache.poi.ss.util.{CellAddress, CellReference}
object ExcelMapper {
val allReplaceBrace = "\\$\\{([^\\}]*)\\}".r
/**
* xlsファイルから${}の文字列を探し出してそのロケーションと文字列のペアを返す
* @param xlsPath
*
*/
def getExcelLocation(xlsPath:String) = {
val f = new FileInputStream(xlsPath)
val workbook = WorkbookFactory.create(f)
val results = (for (i <- 0 to workbook.getNumberOfSheets - 1) yield {
val sheet = workbook.getSheetAt(i)
(for (rowID <- 0 to sheet.getLastRowNum) yield {
val row = sheet.getRow(rowID)
(for (columnID <- 0 to row.getLastCellNum) yield {
val cell = row.getCell(columnID)
cell match {
case null =>
(null, "", "", Nil)
case x:Cell =>
val all = allReplaceBrace.findAllIn(x.toString)
var result:List[String] = Nil
while(all.hasNext){
val d = all.next()
result = d :: result
}
if (result==Nil){
(null, "", "", Nil)
}else {
//シート名 -> セルアドレス -> バインダの値 -> List(バインダ)
(sheet.getSheetName, cell.getAddress, cell, result.reverse)
}
}
})
.filter(_._1!=null) //nullを省く
.toList
})
.filter(_.size > 0)
.toList
}).flatten.flatten.toList
workbook.close()
results
}
/**
* データバインドをExcelに出力
* @param dataTemplateXls ${}のあるひな形ファイルテンプレート
* @param outTemplate ひな形ファイル(出力用フォーマット)
* @param outXlsPath 出力先のExcel
* @param locationDataArray
*/
def setDataAsTemplate(
dataTemplateXls:String,
outTemplate:String,
outXlsPath:String,
locationDataArray:List[(String,Any)] *
)={
val locations = getExcelLocation(dataTemplateXls)
val f = new FileInputStream(outTemplate)
val workbook = WorkbookFactory.create(f)
var sheetIndex = 0
locationDataArray.map {
locationData =>
//sheetの決定
val sheet = if (sheetIndex==0) {
workbook.getSheet(locations.head._1)
}
else{
//シートをコピー
val sheet = workbook.cloneSheet(0)
sheet
}
locations.foreach {
x =>
//${}のList取得
x._4.foreach {
xx => {
val ref = new CellReference(x._2.toString)
val row = sheet.getRow(ref.getRow)
val target = row.getCell(ref.getCol)
target.setCellValue(
locationData
.foldLeft(x._3.toString) {
(acc, xxx) =>
val alt = if (xxx._2==null){
""
} else {
xxx._2.toString
}
acc.replaceAll("\\$\\{" + s"${xxx._1}" + "\\}", alt)
}
)
}
}
}
sheetIndex = sheetIndex + 1
}
val w = new File(outXlsPath)
val out = new FileOutputStream(w)
workbook.write(out)
workbook.close()
}
/**
* Excelからデータバインドを取得
* @param dataTemplateXls ${}のあるひな形ファイルテンプレート
* @param inputXlsPath ひな形ファイル(出力用フォーマット)
*/
def getDataAsTemplate(
dataTemplateXls:String,
inputXlsPath:String,
ignoreSheet:List[String]=List("設定")
)={
val locations = getExcelLocation(dataTemplateXls)
val f = new FileInputStream(inputXlsPath)
val workbook = WorkbookFactory.create(f)
val result = (for (index <- 0 until workbook.getNumberOfSheets) yield {
val sheet = workbook.getSheetAt(index)
if(ignoreSheet.contains(sheet.getSheetName)) {
null
} else {
var results = scala.collection.mutable.Map[String,String]()
locations.map {
x =>
//${}のList取得
val ref = new CellReference(x._2.toString)
val row = sheet.getRow(ref.getRow)
val target = row.getCell(ref.getCol)
val regEx = ("(?s)" + x._4.foldLeft(if (x._3==null){""}else{x._3.toString}) {
(acc, xx) =>
val xxx = xx.replace("$", "\\$")
.replace("{", "\\{")
.replace("}", "\\}")
acc.replaceFirst(xxx, "(.+)")
})
.r
val all = regEx.findFirstMatchIn(target.getStringCellValue)
if (all.size>0) {
(for (i <- 0 until all.get.groupCount) yield {
results += (x._4(i).replaceAll("^\\$\\{", "").replaceAll("\\}$", "") -> all.get.group(i + 1))
x._4(i).replaceAll("^\\$\\{", "").replaceAll("\\}$", "") -> all.get.group(i + 1)
}).toList
}
else {
(x._4.map {
xx =>
results += (xx.replaceAll("^\\$\\{", "").replaceAll("\\}$", "") -> "")
xx.replaceAll("^\\$\\{", "").replaceAll("\\}$", "") -> ""
}).toList
}
}.flatten
results
}
}).filter(_!=null).toList
workbook.close()
result
}
def setData(dataTempleteXls:String, outXlsPath:String, locationData:List[(String,String,Any)])={
val f = new File(dataTempleteXls)
val workbook = WorkbookFactory.create(f)
locationData.foreach{
x =>
val sheet = workbook.getSheet(x._1)
val ref = new CellReference(x._2)
val row = sheet.getRow(ref.getRow)
val target = row.getCell(ref.getCol)
x._3 match {
case xx:String =>
target.setCellValue(xx)
case xx:Int =>
target.setCellValue(xx)
case _ =>
target.setCellValue(x._3.toString)
}
}
val w = new File(outXlsPath)
val out = new FileOutputStream(w)
workbook.write(out)
workbook.close()
}
}
@@ -0,0 +1,17 @@
package com.astamuse.asta4e.converter
import scala.language.implicitConversions
object E {
implicit class ExcelConverter(s: (String, String)) {
def &(that: (String, String)): List[(String, String)] = {
s :: that :: Nil
}
}
implicit class ExcelConverterList(s: List[(String, String)]) {
def &(that: (String, String)): List[(String, String)] = {
(that :: s).reverse
}
}
}
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,60 @@
package com.astamuse.asta4e
import java.io.File
import org.junit.runner.RunWith
import org.specs2.mutable.Specification
import org.specs2.runner.JUnitRunner
import com.astamuse.asta4e.converter.E._
@RunWith(classOf[JUnitRunner])
class ExcelMapperTest extends Specification {
val currentDir = new File(".").getAbsoluteFile().getParent()
"ExcelMapper" should {
"getExcelLocation" in {
val target = ExcelMapper.getExcelLocation(s"${currentDir}/src/test/resources/excel/bind_template1.xlsx")
target.size must be_==(240)
}
"getDataAsTemplate" in {
val target = ExcelMapper.getDataAsTemplate(
s"${currentDir}/src/test/resources/excel/bind_template1.xlsx",
s"${currentDir}/src/test/resources/excel/read_sample1.xlsx")
target(0).size must be_==(240)
target(0)("A1") must be_==("A1")
target(0)("A2") must be_==("A2")
target(0)("B3") must be_==("B3")
target(0)("C5") must be_==("C5")
}
"setDataAsTemplate to getDataAsTemplate" in {
val target = ExcelMapper.setDataAsTemplate(
s"${currentDir}/src/test/resources/excel/bind_template1.xlsx",
s"${currentDir}/src/test/resources/excel/read_sample1.xlsx",
s"${currentDir}/target/output1.xlsx",
"A1" -> "test1" &
"A2" -> "test2" &
"A3" -> "test3"
)
val result = ExcelMapper.getDataAsTemplate(
s"${currentDir}/src/test/resources/excel/bind_template1.xlsx",
s"${currentDir}/target/output1.xlsx")
result(0)("A1") must be_==("test1")
result(0)("A2") must be_==("test2")
result(0)("A3") must be_==("test3")
}
}
}

0 comments on commit b15b9e8

Please sign in to comment.