Sfoglia il codice sorgente

202103250658

master
teddyhuang 5 anni fa
parent
commit
81f16c4f0d
10 ha cambiato i file con 667 aggiunte e 62 eliminazioni
  1. +191
    -59
      app/src/components/Inventory.vue
  2. +24
    -0
      pom.xml
  3. +29
    -0
      src/main/java/com/moze/rms/controller/InventoryController.java
  4. +2
    -2
      src/main/java/com/moze/rms/dao/AssertDAO.java
  5. +20
    -0
      src/main/java/com/moze/rms/dao/InventoryDAO.java
  6. +1
    -1
      src/main/java/com/moze/rms/dao/MappingColDAO.java
  7. +176
    -0
      src/main/java/com/moze/rms/utils/ExcelExpoter.java
  8. +194
    -0
      src/main/java/com/moze/rms/utils/ExcelImporter.java
  9. +26
    -0
      src/main/java/com/moze/rms/utils/JsonUtil.java
  10. +4
    -0
      src/main/resources/application.properties

+ 191
- 59
app/src/components/Inventory.vue Vedi File

@@ -1,6 +1,6 @@
<template>
<div>
<v-data-table class="pa-3 pt-5" :headers="headers" :items="items" :height="fullHeight*7/9"
<v-data-table class="" :headers="headers" :items="items"
fixed-header
:footer-props="{'items-per-page-options': [30, 40, 50, 60]}"
:items-per-page="30">
@@ -12,8 +12,63 @@
inset
vertical
/>
<p v-if="mockSearch===true" class="mb-0">搜尋條件: 資產群組: H8 儲存設備</p>
<div class="row align-center">
<p v-if="haveSearch" class="mb-0 pa-0">搜尋條件:</p>
<div v-for="(val, key, index) in searchItem" :key="index" class="pa-0 ma-0">
<v-chip color="secondary" v-if="val !== null">
{{mappingHeaders[key]}} 包含: {{val}}
<v-icon @click="clearSinglePropInSearchItem(key)">mdi-close</v-icon>
</v-chip>
</div>
</div>
<v-spacer/>
<!--匯入檔案對話-->
<v-dialog
v-model="dialogImport"
@click:outside="close"
:retain-focus="false"
max-width="500"
>
<template v-slot:activator="{ on, attrs }">
<v-btn
color="white"
class="primary mr-5"
v-bind="attrs"
v-on="on"
icon
>
<v-icon>mdi-file-import-outline</v-icon>
</v-btn>

</template>
<v-card>
<v-card-title>
<span class="headline font-weight-bold">匯入</span>
</v-card-title>
<v-card-text>
<v-container>
<input id="file" type="file" @change="onFileChange" />
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="blue darken-1"
text
@click="close"
>
關閉
</v-btn>
<v-btn
color="blue darken-1"
text
@click="importFile"
>
匯入
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-btn
color="white"
class="primary mr-5"
@@ -49,32 +104,30 @@
<v-row>
<v-col

v-for="(val, key, index) in searchItem"
v-for="(header, index) in headers"
:key="index"
cols="12"
sm="6"
md="4"
>
<div v-if="headers[index].text !== '編號'">
<div v-if="headers[index] && headers[index].text !== '編號'">
<v-text-field
dense
v-if="isTextField(key) && headers[index].text"
:label="headers[index].text"
:disabled="isDisabled(key)"
v-bind:value="val"
:persistent-hint="isRequire(key)"
v-if="isTextField(header.value) && headers[index].text"
:label="header.text"
:disabled="isDisabled(header.value)"
v-model="searchItem[header.value]"
:persistent-hint="isRequire(header.value)"
hint="必填"
v-on:input="oninput(searchItem, key, $event)"
/>
<v-select
dense
v-if="isSelect(key) && headers[index].text"
:persistent-hint="isRequire(key)"
v-if="isSelect(header.value) && headers[index].text"
:persistent-hint="isRequire(header.value)"
hint="必選"
:label="headers[index].text"
:value="val"
v-on:input="oninput(searchItem, key, $event)"
:items="selectItem[key]"
:label="header.text"
v-model="searchItem[header.value]"
:items="selectItem[header.value]"
item-text="item"
item-value="item"
/>
@@ -88,6 +141,13 @@
<v-btn
color="blue darken-1"
text
@click="clearSearchItem"
>
清空
</v-btn>
<v-btn
color="blue darken-1"
text
@click="close"
>
關閉
@@ -95,7 +155,7 @@
<v-btn
color="blue darken-1"
text
@click="mockSearch=true"
@click="search"
>
搜尋
</v-btn>
@@ -128,32 +188,32 @@
<v-row>
<v-col

v-for="(val, key, index) in insertItem"
v-for="(header, index) in headers"
:key="index"
cols="12"
sm="6"
md="4"
>
<div v-if="headers[index].text !== '編號'">
<div v-if="headers[index] && headers[index].text !== '編號'">
<v-text-field
dense
v-if="isTextField(key) && headers[index].text"
:label="headers[index].text"
:disabled="isDisabled(key)"
v-bind:value="val"
:persistent-hint="isRequire(key)"
v-if="isTextField(header.value) && headers[index].text"
:label="header.text"
:disabled="isDisabled(header.value)"
v-bind:value="insertItem[header.value]"
:persistent-hint="isRequire(header.value)"
hint="必填"
v-on:input="oninput(insertItem, key, $event)"
v-on:input="oninput(insertItem, header.value, $event)"
/>
<v-select
dense
v-if="isSelect(key) && headers[index].text"
:persistent-hint="isRequire(key)"
v-if="isSelect(header.value) && headers[index].text"
:persistent-hint="isRequire(header.value)"
hint="必選"
:label="headers[index].text"
:value="val"
v-on:input="oninput(insertItem, key, $event)"
:items="selectItem[key]"
:label="header.text"
:value="insertItem[header.value]"
v-on:input="oninput(insertItem, header.value, $event)"
:items="selectItem[header.value]"
item-text="item"
item-value="item"
/>
@@ -213,33 +273,36 @@
<v-row>
<v-col

v-for="(val, key, index) in modifyItem"
v-for="(header, index) in headers"
:key="index"
cols="12"
sm="6"
md="4"
class="d-flex"
>
<v-text-field
v-if="isTextField(key) && headers[index].text"
:label="headers[index].text"
:disabled="isDisabled(key)"
v-bind:value="val"
:persistent-hint="isRequire(key)"
hint="必填"
v-on:input="oninput(modifyItem, key, $event)"
/>
<v-select
v-if="isSelect(key) && headers[index].text"
:persistent-hint="isRequire(key)"
hint="必選"
:label="headers[index].text"
:value="val"
v-on:input="oninput(modifyItem, key, $event)"
:items="selectItem[key]"
item-text="item"
item-value="item"
/>
<div v-if="headers[index] && headers[index].text !== '編號'">
<v-text-field
dense
v-if="isTextField(header.value) && headers[index].text"
:label="header.text"
:disabled="isDisabled(header.value)"
v-bind:value="modifyItem[header.value]"
:persistent-hint="isRequire(header.value)"
hint="必填"
v-on:input="oninput(modifyItem, header.value, $event)"
/>
<v-select
dense
v-if="isSelect(header.value) && headers[index].text"
:persistent-hint="isRequire(header.value)"
hint="必選"
:label="header.text"
:value="modifyItem[header.value]"
v-on:input="oninput(modifyItem, header.value, $event)"
:items="selectItem[header.value]"
item-text="item"
item-value="item"
/>
</div>
</v-col>
</v-row>
</v-container>
@@ -266,6 +329,9 @@
</div>
</template>
<script>
let cancel;
let CancelToken;
let cancel2;
export default {
name: '',
data() {
@@ -276,6 +342,7 @@
dialogSearch: false,
title: '',
headers: [],
mappingHeaders: {},
cols: {},
items: [],
isselect: [],
@@ -285,17 +352,19 @@
selectItem: {},
searchItem: {},
mockSearch: false,
haveSearch:false,
dialogImport: false,
file: null,
}
},
async mounted() {
CancelToken = this.$axios.CancelToken;
this.getHeaders();
this.getInventories();
this.getTitle();
this.getSelectItem();
this.fullHeight = window.innerHeight;
console.log(this.fullHeight);
window.onresize = () => {
// this.fullWidth = window.innerWidth;
this.fullHeight = window.innerHeight;
};
},
@@ -305,7 +374,7 @@
},
},
watch: {
async tablename() {
tablename() {
if (this.$route.params.tablename) {
this.headers = [];
this.items = [];
@@ -337,12 +406,20 @@
},
getHeaders() {
this.headers.push({'text': '', 'value': 'actions', sortable: false});
this.$axios.get(`/headers?tablename=${this.tablename}`).then((resp) => {
if (cancel) {
cancel();
}
this.$axios.get(`/headers?tablename=${this.tablename}`,{
cancelToken: new CancelToken(((c) => {
cancel = c;
})),
}).then((resp) => {
this.cols = resp.data.data;
resp.data.data.forEach((item) => {
let header = {'text': null, 'value': null};
header.text = item.descript;
header.value = item.colname;
this.mappingHeaders[item.colname] = item.descript;
this.headers.push(header);
if (item.isselect === 'true') {
this.isselect.push(item.colname);
@@ -356,7 +433,14 @@
});
},
getInventories() {
this.$axios.get(`/inventory?tablename=${this.tablename}`).then((resp) => {
if (cancel2) {
cancel2();
}
this.$axios.get(`/inventory?tablename=${this.tablename}`,{
cancelToken: new CancelToken(((c) => {
cancel = c;
})),
}).then((resp) => {
this.items = resp.data.data;
});
},
@@ -373,6 +457,7 @@
this.dialogInsert = false;
this.dialogModify = false;
this.dialogSearch = false;
this.dialogImport = false;
},
isDisabled(key) {
const disabledKey = ['id'];
@@ -408,9 +493,56 @@
alert('已刪除');
});
}
console.log(item);
},
search() {
this.searchItem.tablename = this.tablename;
this.$axios.post(`/search`, this.searchItem).then((resp) => {
delete this.searchItem.tablename;
this.items = resp.data.data;
this.haveSearch = true;
this.dialogSearch = false;
});
},
clearSinglePropInSearchItem(key) {
console.log(key);
this.searchItem[key] = null;
console.log(this.searchItem);
this.haveSearch = false;
Object.keys(this.searchItem).forEach(function(key){
if (self.searchItem[key] !== null) {
this.haveSearch = true;
}
});
},
async clearSearchItem() {
const self = this;
Object.keys(this.searchItem).forEach(function(key){
self.searchItem[key] = null;
});
// this.searchItem = {};
// await this.cols.forEach((item) => {
// this.searchItem[item.colname] = null;
//
// });
this.haveSearch = false;
},
onFileChange(e) {
const files = e.target.files || e.dataTransfer.files;
if (files.length > 0) {
console.log(files[0].name);
// eslint-disable-next-line prefer-destructuring
this.file = files[0];
}
},
importFile() {
const formData = new FormData();
formData.append('file', this.file);
this.$axios.post(`/importFile`, formData).then(() => {
document.getElementById('file').value = null;
this.getInventories();
this.file = null;
this.dialogImport = false;
});

},
exportFile() {


+ 24
- 0
pom.xml Vedi File

@@ -103,6 +103,30 @@
<version>9.2.1.jre8</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<!-- <dependency>-->
<!-- <groupId>org.apache.poi</groupId>-->
<!-- <artifactId>poi</artifactId>-->
<!-- <version>5.0.0</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.apache.poi</groupId>-->
<!-- <artifactId>poi-ooxml</artifactId>-->
<!-- <version>3.9</version>-->
<!-- </dependency>-->

<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.0</version>
</dependency>


</dependencies>



+ 29
- 0
src/main/java/com/moze/rms/controller/InventoryController.java Vedi File

@@ -5,9 +5,13 @@ import com.moze.rms.dao.InventoryDAO;
import com.moze.rms.dao.MappingColDAO;
import com.moze.rms.dao.MappingTableDAO;
import com.moze.rms.entity.dto.SelectItemDTO;
import com.moze.rms.utils.ExcelImporter;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -81,5 +85,30 @@ public class InventoryController {
}


@PostMapping("/search")
public JsonResult searchInventory(@RequestBody Map<String, Object> data) {
System.out.println(data);

return new JsonResult(StatusCode.SUCCESS, inventoryDAO.search(data));
}

@PostMapping("/importFile")
public JsonResult importFile(@RequestParam(required = false) MultipartFile file) throws IOException, InvalidFormatException {

File f = File.createTempFile(file.getOriginalFilename().split("\\.")[0], file.getOriginalFilename().split("\\.")[1]);
System.out.println(f.getName());
file.transferTo(f);


ExcelImporter excelImporter2 = new ExcelImporter(f);
System.out.println(excelImporter2.readAll());
f.deleteOnExit();



return new JsonResult(StatusCode.SUCCESS, null);
}



}

+ 2
- 2
src/main/java/com/moze/rms/dao/AssertDAO.java Vedi File

@@ -44,7 +44,7 @@ public interface AssertDAO extends SqlObject {
Handle handle = this.getHandle();
String sql = "create table " + data.get("assertGroupTablename") +
"(" +
" id int not null" +
" id int not null IDENTITY(1,1)" +
" constraint " + data.get("assertGroupTablename") + "_pk" +
" primary key nonclustered," +
" type nvarchar(256)," +
@@ -155,7 +155,7 @@ public interface AssertDAO extends SqlObject {
//新增欄位sql
default void addColToTable(MappingCol m) {
Handle handle = this.getHandle();
String sql = "ALTER TABLE " + m.getTablename() + " ADD " + m.getColname() + " " + "varchar";
String sql = "ALTER TABLE " + m.getTablename() + " ADD " + m.getColname() + " " + "nvarchar(256)";
handle.createUpdate(sql).execute();

}


+ 20
- 0
src/main/java/com/moze/rms/dao/InventoryDAO.java Vedi File

@@ -72,4 +72,24 @@ public interface InventoryDAO extends SqlObject {
handle.execute(sql);
}


@RegisterBeanMapper(Object.class)
default List<Map<String, Object>> search(Map<String, Object> data) {
Handle handle = this.getHandle();
String sql = "select * from " + data.get("tablename") + " where";
data.remove("tablename");
Iterator<Map.Entry<String, Object>> iterator = data.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Object> next = iterator.next();
String key = next.getKey();
Object value = next.getValue();
System.out.println(key);
if (key != "tablename" && key != "id" && value != null) {
sql += " " + key + " like '%" + value + "%' and";
}
}
sql = sql.substring(0, sql.length() - 3);
System.out.println(sql);
return handle.createQuery(sql).mapToMap().list();
}
}

+ 1
- 1
src/main/java/com/moze/rms/dao/MappingColDAO.java Vedi File

@@ -11,6 +11,6 @@ import java.util.List;
public interface MappingColDAO {


@SqlQuery("select * from mapping.mapping_col where tablename = ? order by [index];")
@SqlQuery("select * from mapping.mapping_col where tablename = ? order by convert(int, [index]);")
List<MappingCol> findByTable(String tablename);
}

+ 176
- 0
src/main/java/com/moze/rms/utils/ExcelExpoter.java Vedi File

@@ -0,0 +1,176 @@
package com.moze.rms.utils;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;


public class ExcelExpoter {
private String outputPath;
private String nullString;
private Set<String> columnAutoSized = new HashSet<>();
List<SheetInfo> sheets = new LinkedList<>();

public ExcelExpoter(String outputPath) {
this.outputPath = outputPath;
this.nullString = "<NULL>";
}

public ExcelExpoter(String outputPath, String nullString) {
this.outputPath = outputPath;
this.nullString = nullString;
}

// public void export() throws FileNotFoundException, IOException {
// try (FileOutputStream outputStream = new FileOutputStream(outputPath);
// XSSFWorkbook workbook = new XSSFWorkbook()) {
// for(SheetInfo sheet : sheets) {
// exportSheet(workbook, sheet.getSheetName(), sheet.getHeaderMap(), sheet.getData());
// }
// System.out.println("Start flush out workbook!");
// workbook.write(outputStream);
// System.out.println("Created excel: " + outputPath);
// }
// }

public void addSheet(String sheetName, Map<String, String> headerMap, List<?> data) {
sheets.add(new SheetInfo(sheetName, headerMap, data));
}

// public void export(String sheetName, Map<String, String> headerMap, List<?> data) throws FileNotFoundException, IOException {
// try (FileOutputStream outputStream = new FileOutputStream(outputPath);
// XSSFWorkbook workbook = new XSSFWorkbook()) {
// exportSheet(workbook, sheetName, headerMap, data);
// System.out.println("Start flush out workbook!");
// workbook.write(outputStream);
// System.out.println("Created excel: " + outputPath);
// }
// }

private void exportSheet(XSSFWorkbook workbook, String sheetName, Map<String, String> headerMap, List<?> data) {
XSSFSheet sheet = workbook.createSheet(sheetName);

int rowCount = 0;

// If Header not set
if (headerMap == null) {
headerMap = new LinkedHashMap<>();
if (!data.isEmpty()) {
for(String k: JsonUtil.pojo2Map(data.get(0)).keySet()) {
headerMap.put(k, k);
}
}
}

Font headerFont = workbook.createFont();
headerFont.setBold(true);
headerFont.setFontHeightInPoints((short) 12);
headerFont.setColor(IndexedColors.BLACK.getIndex());
CellStyle headerCellStyle = workbook.createCellStyle();
headerCellStyle.setFont(headerFont);

// Create Header Row
Row row = sheet.createRow(rowCount++);
int columnCount = 0;

for(String v: headerMap.values()) {
Cell cell = row.createCell(columnCount++);
cell.setCellValue(v);
cell.setCellStyle(headerCellStyle);
}

// Create Other rows and cells
CellStyle style = workbook.createCellStyle();
style.setWrapText(true);
style.setVerticalAlignment(VerticalAlignment.TOP);

for (Object item : data) {
@SuppressWarnings("unchecked")
Map<String, Object> obj = item instanceof Map ? (Map<String, Object>)item: JsonUtil.pojo2Map(item);
row = sheet.createRow(rowCount++);

columnCount = 0;
for(String k: headerMap.keySet()) {
Object v = obj.get(k);
Cell cell = row.createCell(columnCount++);
String value = v == null ? nullString : v.toString();
cell.setCellValue(value);
cell.setCellStyle(style);
}
if (rowCount % 10000 == 0) {
System.out.println("Created row " + rowCount);
}
if (rowCount == 350)
autoSizeColumn(sheet);
}
System.out.println("[" + sheetName + "] Created all row " + rowCount);
autoSizeColumn(sheet);
}

private void autoSizeColumn(XSSFSheet sheet) {
if (columnAutoSized.contains(sheet.getSheetName()))
return;
System.out.println("Start auto size columns");
int maxWidth = 256 * 120;
int minWidth = 256 * 16;
int rowCount = sheet.getRow(0).getLastCellNum();
System.out.println(rowCount);
for (int j = 0; j < rowCount; j++) {
sheet.autoSizeColumn(j);
if (sheet.getColumnWidth(j) > maxWidth) {
sheet.setColumnWidth(j, maxWidth);
}
if (sheet.getColumnWidth(j) < minWidth) {
sheet.setColumnWidth(j, minWidth);
}
}
columnAutoSized.add(sheet.getSheetName());
System.out.println("End auto size columns");
}

private static class SheetInfo {
private String sheetName;
private Map<String, String> headerMap;
private List<?> data;
public SheetInfo(String sheetName, Map<String, String> headerMap, List<?> data) {
super();
this.sheetName = sheetName;
this.headerMap = headerMap;
this.data = data;
}
public String getSheetName() {
return sheetName;
}
public void setSheetName(String sheetName) {
this.sheetName = sheetName;
}
public Map<String, String> getHeaderMap() {
return headerMap;
}
public void setHeaderMap(Map<String, String> headerMap) {
this.headerMap = headerMap;
}
public List<?> getData() {
return data;
}
public void setData(List<?> data) {
this.data = data;
}

}
}

+ 194
- 0
src/main/java/com/moze/rms/utils/ExcelImporter.java Vedi File

@@ -0,0 +1,194 @@
package com.moze.rms.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;

public class ExcelImporter {

private File file;

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");

public ExcelImporter(File file) {
this.file = file;
}

public ExcelImporter(String filePath) {
this(new File(filePath));
}

public Map<String, List<Map<String, String>>> readAll() throws IOException, InvalidFormatException {
File excelFile = file;
Map<String, List<Map<String, String>>> ret = new LinkedHashMap<>();
try (FileInputStream fis = new FileInputStream(excelFile);
Workbook workbook = WorkbookFactory.create(fis)) {
for (int sn=0; sn < workbook.getNumberOfSheets(); sn++) {
if (workbook.isSheetHidden(sn) || workbook.isSheetVeryHidden(sn)) {
continue;
}
Sheet sheet = workbook.getSheetAt(sn);
List<Map<String, String>> data = readSheet(sheet, 0);
ret.put(sheet.getSheetName(), data);
}
}
return ret;
}

/**
* read a sheet
* @param sheetName
* @param headerRow - header row number, 0 based
* @return
* @throws IOException
*/
public List<Map<String, String>> readSheet(String sheetName, int headerRow) throws IOException {
File excelFile = file;
try (FileInputStream fis = new FileInputStream(excelFile);
Workbook workbook = WorkbookFactory.create(fis)) {
Sheet sheet = workbook.getSheet(sheetName);
if (sheet == null) {
throw new IOException("Sheet " + sheetName + " not exist!");
}
return readSheet(sheet, headerRow);
}
}
public List<Map<String, String>> readSheet(Sheet sheet, int headerRow) {
List<Map<String, String>> ret = new LinkedList<>();
// we iterate on rows
Iterator<Row> rowIt = sheet.iterator();
List<String> headerValues = null;
int headerLength = 0;
while (rowIt.hasNext()) {
Row row = rowIt.next();
if (row.getRowNum() < headerRow)
continue;
List<String> rowValues = readRow(row);
headerValues = rowValues.stream().map(this::getFirstLine).collect(Collectors.toList());
headerLength = headerValues.size();
break;
}

while (rowIt.hasNext()) {
Row row = rowIt.next();
List<String> rowValues = readRow(row, headerValues, headerLength);

if (row.getRowNum() == headerRow) {
headerValues = rowValues.stream().map(this::getFirstLine).collect(Collectors.toList());
continue;
}
// if (row.getZeroHeight() || row.getFirstCellNum() == -1)
// continue;
// break at empty line;
Integer strlen = rowValues.stream().map(String::length).reduce(0, Integer::sum);
if (strlen == 0)
break;
// if (rowValues.isEmpty() || rowValues.get(0).isEmpty())
// break;
Map<String, String> pairs = getRowPairs(headerValues, rowValues);
ret.add(pairs);
}
return ret;
}

public List<String> readRow(Row row) {
List<String> ret = new ArrayList<>();
Iterator<Cell> cellIterator = row.cellIterator();
DataFormatter dataFormatter = new DataFormatter();

while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
// if (cell.getSheet().isColumnHidden(cell.getAddress().getColumn()))
// continue;
String value = null;

if (cell.getCellType() == CellType.NUMERIC && DateUtil.isCellDateFormatted(cell))
value = df.format(cell.getDateCellValue());
else
value = dataFormatter.formatCellValue(cell);

ret.add(value.trim());
}
return ret;
}
/* 沒有加最大行數參數的版本,會有略掉空白 cell 的問題
*
*/
public List<String> readRow(Row row, List<String> headers, int length) {
List<String> ret = new ArrayList<>();
DataFormatter dataFormatter = new DataFormatter();
for (int i = 0; i < length; i++) {
Cell cell = row.getCell(i);
if (cell == null) {
ret.add("");
continue;
}

String value = null;

if (cell.getCellType() == CellType.NUMERIC && DateUtil.isCellDateFormatted(cell))
value = df.format(cell.getDateCellValue());
else
value = dataFormatter.formatCellValue(cell);

ret.add(value.trim());
}
return ret;
}

private String getFirstLine(String str) {
if (str == null)
return null;
return str.split("\n")[0].trim();
}

public Map<String, String> getRowPairs(List<String> headerValues, List<String> rowValues) {
Map<String, String> ret = new LinkedHashMap<>();
for (int i = 0; i < headerValues.size(); i++) {
String key = headerValues.get(i);
String value = i >= rowValues.size() ? "" : rowValues.get(i);
ret.put(key, value);
}
return ret;
}

public static boolean isValidSheet(List<Map<String, String>> sheetData, List<String> headerList) {
if (sheetData.isEmpty())
return false;
Map<String, String> row1 = sheetData.get(0);

int[] count = new int[]{0};
row1.forEach((key, v) -> {
if (headerList.contains(key))
count[0]++;
});
return count[0] == headerList.size();
}
}

+ 26
- 0
src/main/java/com/moze/rms/utils/JsonUtil.java Vedi File

@@ -0,0 +1,26 @@
package com.moze.rms.utils;

import java.util.LinkedHashMap;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;


public interface JsonUtil {
static ObjectMapper mapper = new ObjectMapper()
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

public static <T> T map2Pojo(Map<String, Object> map, Class<T> clazz) {
T ret = mapper.convertValue(map, clazz);
return ret;
}

public static Map<String, Object> pojo2Map(Object obj) {
@SuppressWarnings("unchecked")
Map<String, Object> ret = mapper.convertValue(obj, LinkedHashMap.class);
return ret;
}
}

+ 4
- 0
src/main/resources/application.properties Vedi File

@@ -1,2 +1,6 @@
spring.profiles.active=dev
#spring.profiles.active=pro


spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=1000MB

Caricamento…
Annulla
Salva