Added project
This commit is contained in:
152
src/main/kotlin/ru/resprojects/exceltojson/Main.kt
Normal file
152
src/main/kotlin/ru/resprojects/exceltojson/Main.kt
Normal file
@@ -0,0 +1,152 @@
|
||||
package ru.resprojects.exceltojson
|
||||
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import com.mongodb.ConnectionString
|
||||
import com.mongodb.client.MongoCollection
|
||||
import mu.KotlinLogging
|
||||
import org.apache.commons.collections4.list.UnmodifiableList
|
||||
import org.apache.poi.ss.usermodel.CellType
|
||||
import org.apache.poi.xssf.usermodel.XSSFSheet
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook
|
||||
import org.litote.kmongo.KMongo
|
||||
import org.litote.kmongo.findOne
|
||||
import org.litote.kmongo.getCollection
|
||||
import java.io.File
|
||||
import java.net.URI
|
||||
import java.nio.file.FileSystems
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
private val logger = KotlinLogging.logger {}
|
||||
private val mapper = jacksonObjectMapper()
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
if (args.isEmpty()) {
|
||||
println("""
|
||||
usage exceltojson <path_to_excel_file> for generate json file
|
||||
usage exceltojson --mongo=mongodb://<host>:<port>/<database>/<collection_name> <path_to_file_xlsx> for export to mongo
|
||||
""".trimIndent())
|
||||
return
|
||||
}
|
||||
if (args.first().startsWith("--mongo=")) {
|
||||
excelToMongo(args, URI(args.first().substring("--mongo=".length)))
|
||||
} else {
|
||||
args.forEach {
|
||||
if (!it.startsWith("--")) {
|
||||
println("Start process file $it")
|
||||
excelToJson(it)
|
||||
println("------")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun excelToMongo(fileNames: Array<String>, mongoUri: URI) {
|
||||
try {
|
||||
val client = KMongo.createClient(ConnectionString(mongoUri.scheme + "://" + mongoUri.host + ":" + mongoUri.port))
|
||||
client.use { mongoClient ->
|
||||
val database = mongoClient.getDatabase(mongoUri.path.removePrefix("/").split("/")[0])
|
||||
val collectionName = mongoUri.path.removePrefix("/").split("/")[1]
|
||||
val collection = database.getCollection<Dict>(collectionName)
|
||||
fileNames.forEach { fileName ->
|
||||
if (!fileName.startsWith("--")) {
|
||||
println("Start process file $fileName")
|
||||
val book = XSSFWorkbook(File(fileName).inputStream())
|
||||
book.use { xssfWorkbook ->
|
||||
collectToList(xssfWorkbook.getSheetAt(0)).forEach {dict ->
|
||||
if (!isEntryExistsInMongo(collection, dict)) {
|
||||
collection.insertOne(dict)
|
||||
} else {
|
||||
val message = "--> Entry {id=${dict.id}, field=${dict.field}, value=${dict.value}, value_map=${dict.value_map}} is exist in collection '$collectionName' and was skipped"
|
||||
println(message)
|
||||
logger.warn { message }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
println("Process is end. All entry was success added to mongo")
|
||||
println("------")
|
||||
} catch (e: Exception) {
|
||||
println("Error process ${e.message}")
|
||||
logger.error(e) { "Error process" }
|
||||
}
|
||||
}
|
||||
|
||||
fun isEntryExistsInMongo(collection: MongoCollection<Dict>, entry: Dict): Boolean {
|
||||
return collection.findOne(
|
||||
"""
|
||||
{
|
||||
"id": ${entry.id},
|
||||
"field": "${entry.field}",
|
||||
"value": "${entry.value}",
|
||||
"value_map": "${entry.value_map}"
|
||||
}
|
||||
""".trimIndent()
|
||||
) != null
|
||||
}
|
||||
|
||||
fun excelToJson(fileName: String) {
|
||||
try {
|
||||
if (!Files.exists(Paths.get(fileName))) {
|
||||
val message = "File $fileName not found"
|
||||
println(message)
|
||||
logger.error { message }
|
||||
return
|
||||
}
|
||||
val file = File(fileName)
|
||||
val book = XSSFWorkbook(file.inputStream())
|
||||
book.use {
|
||||
val lst = file.name.split(".")
|
||||
val defaultFileName = "file-${LocalDateTime.now().format(DateTimeFormatter.ofPattern("ddMMyyyy-HHmm"))}.json"
|
||||
val outFilename = "${if (file.toPath().parent != null) file.toPath().parent.toString() + FileSystems.getDefault().separator else ""}${if (lst.isNotEmpty()) file.name.split(".")[0] else defaultFileName}.json"
|
||||
mapper.writeValue(File(outFilename), collectToList(it.getSheetAt(0)))
|
||||
println("End process file. Write result to $outFilename")
|
||||
println("-----------")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
val message = "Error while process file $fileName"
|
||||
println(message)
|
||||
logger.error(e) { message }
|
||||
}
|
||||
}
|
||||
|
||||
fun collectToList(sheet: XSSFSheet): List<Dict> {
|
||||
val list = ArrayList<Dict>()
|
||||
if (sheet.first().lastCellNum - sheet.first().firstCellNum < 4) {
|
||||
throw RuntimeException("Column count < 4")
|
||||
}
|
||||
for (i in 1 until sheet.lastRowNum) {
|
||||
val row = sheet.getRow(i)
|
||||
if (row.getCell(0) == null) {
|
||||
continue
|
||||
}
|
||||
val id = if (row.getCell(0).cellType == CellType.NUMERIC) {
|
||||
row.getCell(0).numericCellValue.toInt()
|
||||
} else {
|
||||
row.getCell(0).stringCellValue.toInt()
|
||||
}
|
||||
val value = if (row.getCell(2).cellType == CellType.NUMERIC) {
|
||||
row.getCell(2).numericCellValue.toInt().toString()
|
||||
} else {
|
||||
row.getCell(2).stringCellValue
|
||||
}
|
||||
val valueMap = if (row.getCell(3).cellType == CellType.NUMERIC) {
|
||||
row.getCell(3).numericCellValue.toInt().toString()
|
||||
} else {
|
||||
row.getCell(3).stringCellValue
|
||||
}
|
||||
list.add(Dict(
|
||||
id,
|
||||
row.getCell(1).stringCellValue,
|
||||
value,
|
||||
valueMap,
|
||||
))
|
||||
}
|
||||
return UnmodifiableList(list)
|
||||
}
|
||||
|
||||
data class Dict (var id: Int, var field: String, var value: String, var value_map: String)
|
||||
5
src/main/resources/log4j.properties
Normal file
5
src/main/resources/log4j.properties
Normal file
@@ -0,0 +1,5 @@
|
||||
log4j.rootLogger=INFO, file
|
||||
log4j.appender.file=org.apache.log4j.FileAppender
|
||||
log4j.appender.file.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.file.layout.ConversionPattern=%5p [%t] (%F:%L) %-30.90c - %m%n
|
||||
log4j.appender.file.file=${java.io.tmpdir}/exceltojson.log
|
||||
28
src/test/kotlin/ru/resprojects/exceltojson/MainTest.kt
Normal file
28
src/test/kotlin/ru/resprojects/exceltojson/MainTest.kt
Normal file
@@ -0,0 +1,28 @@
|
||||
package ru.resprojects.exceltojson
|
||||
|
||||
import mu.KotlinLogging
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
|
||||
data class DictVal (var id: Int, var field: String, var value: String, var value_map: String)
|
||||
|
||||
private val logger = KotlinLogging.logger {}
|
||||
|
||||
class MainTest {
|
||||
|
||||
@Test
|
||||
fun `when input correct xml file when expected not null list`() {
|
||||
val book = XSSFWorkbook(File(loadResource("xlsx/test.xlsx").toURI()).inputStream())
|
||||
book.use {
|
||||
assertEquals(2, collectToList(book.getSheetAt(0)).size)
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadResource(path: String): URL {
|
||||
return Thread.currentThread().contextClassLoader.getResource(path) ?: throw RuntimeException("File $path not found")
|
||||
}
|
||||
}
|
||||
BIN
src/test/resources/xlsx/test.xlsx
Normal file
BIN
src/test/resources/xlsx/test.xlsx
Normal file
Binary file not shown.
Reference in New Issue
Block a user