一:分析解决思想
1.需求:有一张含有父子级关系的跨行表格,需要将该表格的数据导入到数据库中存储,修改操作。(多行10列,每两列为同一级别的数据,共有5个不同级数据在表格中)
2.会出现的问题:由于多级跨行,跨行的数据只有第一行是有值的,第二行就是空值。也有可能由于某一级真的没有子级,造成真实的空值数据。
3.解决思想: 用一个变量来接受表格中的真实数据,跨行的时候不重新赋值,沿用本行的上一行数据,充当本行的数据。真实的空值数据,子级也会是空值,判断子级和本级是否同时为空值,同时为空值就是真实的空值数据。该数据不进入数据库。
4.实现原理:由于是多级存储,子级需要存入父级的id,id是自己生成的,所以先要存入最高级别的数据再存入,第二高级别的数据,由于跨行多子级数据就会出现很多重复数据,这样就考虑用map存取数据。一共有5级,那么需要5个map进行存储数据。
二:实现代码
1.编写controller
/**
* 表单导入方法
* @param request
* @param response
* @throws Exception
*/
@RequestMapping(value = "export")
public void exportEvaluationTemplate(ultipartFile file) throws Exception {
ocScopeService.uploadScopeExcel(file);
}
2.编写存储方法的service
@Transactional(readOnly = false)
public void uploadScopeExcel(MultipartFile file) throws IOException, Exception {
Map<String, OcScope> ocScopeMapDictOne = Maps.newHashMap();
List<OcScope > listOcScope = new ArrayList<>();
Map<String, OcScope> ocScopeMap = Maps.newHashMap();
Map<String, OcScope> ocScopeMapOne = Maps.newHashMap(); //用于存储第1级数据:最高级别数据
Map<String, OcScope> ocScopeMapTwo = Maps.newHashMap();//用于存储第2级数据
Map<String, OcScope> ocScopeMapThree = Maps.newHashMap();//用于存储第3级数据
Map<String, OcScope> ocScopeMapFour = Maps.newHashMap();//用于存储第4级数据
Map<String, OcScope> ocScopeMapFive = Maps.newHashMap();//用于存储第5级数据
String originalFileName = file.getOriginalFilename();
InputStream is = file.getInputStream();
int version = 0;
//判断版本号
if (originalFileName.endsWith(".xls")) {
version = 2003;
}else if (originalFileName.endsWith(".xlsx")) {
version = 2007;
}else {
throw new Exception("Incorrect file format,Only allowed '.xls,.xlsx' extension");
}
Workbook workbook = null;
switch (version) {
case 2003:
POIFSFileSystem fs = new POIFSFileSystem(new BufferedInputStream(is));
workbook = new HSSFWorkbook(fs);
break;
case 2007:
workbook = new XSSFWorkbook(new BufferedInputStream(is));
break;
}
int sheetIndex = workbook.getSheetIndex("评估模板");
Sheet sheet = workbook.getSheetAt(sheetIndex);
//由于表格是一张多级跨行的数据,所以不能简单的读取每一行的数据。需要引入几个变量进行数据存储赋值操作,
String p4 = ""; String p3 = ""; String p2 = ""; String p1 = ""; double w1 = 0D;double w2 = 0D;double w3 = 0D;double w4 = 0D;
int code1=0; int code2=0; int code3=0; int code4=0; int wCode1=0; int wCode2=0; int wCode3=0; int wCode4=0;
for (Row row : sheet) {
OcScope ocScope = new OcScope();
int rowNum = row.getRowNum();
// if(e==1){break;}
if(rowNum == 0){//跳出第一行 一般第一行都是表头没有数据意义
continue;
}
int startCell = 0; //
if(row.getCell(startCell)!=null ){//第1列数据
code4=0;
row.getCell(startCell).setCellType(Cell.CELL_TYPE_STRING);
if(!row.getCell(startCell).getStringCellValue().equals("")){
p4 = row.getCell(startCell).getStringCellValue();
code4=1; //用于判断 p4的值是虚值还是真实的值,便于真实空格的数据导入不出错
}
}
startCell++;
if(row.getCell(startCell)!=null){//第2列
wCode4=0;
row.getCell(startCell).setCellType(Cell.CELL_TYPE_NUMERIC);
if(row.getCell(startCell).getNumericCellValue()!=0.0){
w4 = row.getCell(startCell).getNumericCellValue();
wCode4=1;
}
}
startCell++;
if(row.getCell(startCell)!=null ){//第3列数据
code3=0;
row.getCell(startCell).setCellType(Cell.CELL_TYPE_STRING);
if(!row.getCell(startCell).getStringCellValue().equals("")){
p3 = row.getCell(startCell).getStringCellValue();
code3=1;
}
}
startCell++;
if(row.getCell(startCell)!=null){//第4列
wCode3=0;
row.getCell(startCell).setCellType(Cell.CELL_TYPE_NUMERIC);
if(row.getCell(startCell).getNumericCellValue()!=0.0){
w3 = row.getCell(startCell).getNumericCellValue();
wCode3=1;
}
}
startCell++;
if(row.getCell(startCell)!=null ){//第5列数据
code2=0;
row.getCell(startCell).setCellType(Cell.CELL_TYPE_STRING);
if(!row.getCell(startCell).getStringCellValue().equals("")){
p2 = row.getCell(startCell).getStringCellValue();
code2=1;
}
}
startCell++;
if(row.getCell(startCell)!=null){//第6列
wCode2=0;
row.getCell(startCell).setCellType(Cell.CELL_TYPE_NUMERIC);
if(row.getCell(startCell).getNumericCellValue()!=0.0){
w2 = row.getCell(startCell).getNumericCellValue();
wCode2=1;
}
}
startCell++;
if(row.getCell(startCell)!=null ){//第7列数据
code1=0;
row.getCell(startCell).setCellType(Cell.CELL_TYPE_STRING);
if(!row.getCell(startCell).getStringCellValue().equals("")){
p1 = row.getCell(startCell).getStringCellValue();
code1=1;
}
}
startCell++;
if(row.getCell(startCell)!=null){//第8列
wCode1=0;
row.getCell(startCell).setCellType(Cell.CELL_TYPE_NUMERIC);
if(row.getCell(startCell).getNumericCellValue()!=0.0){
w1 = row.getCell(startCell).getNumericCellValue();
wCode1=1;
}
}
//最后两行是第五级数据,由于该级不存在跨行,所以直接赋值
startCell++;
if(row.getCell(startCell)!=null ){//第9列数据
row.getCell(startCell).setCellType(Cell.CELL_TYPE_STRING);
if(!row.getCell(startCell).getStringCellValue().equals("")){
ocScope.setScopeName(row.getCell(startCell).getStringCellValue());
}
}
startCell++;
if(row.getCell(startCell)!=null){//第10列
row.getCell(startCell).setCellType(Cell.CELL_TYPE_NUMERIC);
if(row.getCell(startCell).getNumericCellValue()!=0.0){
ocScope.setWeights(row.getCell(startCell).getNumericCellValue());
}
}
ocScope.setP4ScopeName(p4); //此种赋值好处,是解决跨行数据内部第二行读到空值数据,直接将上一行的数据赋值给自身用
ocScope.setP4Weights(w4);
ocScope.setP3ScopeName(p3);
ocScope.setP3Weights(w3);
ocScope.setP2ScopeName(p2);
ocScope.setP2Weights(w2);
ocScope.setP1ScopeName(p1);
ocScope.setP1Weights(w1);
if(StringUtils.isEmpty(ocScope.getScopeName()) && code1==0){
ocScope.setP1ScopeName(""); //当子级为空,P1父级为虚值时,说明该行是个真实的空行
}
//由于Double类型的值在读表的时候会将空值读成0,所以需要判断其是真实的0值还是,跨行度的上一级的值
if(StringUtils.isEmpty(ocScope.getScopeName()) && code1==1 && wCode1==0){
ocScope.setP1Weights(0.00); //当子级为空,P1级的值是真实的时,w1读的值却是上一级的虚值,说明该行是个真实的0值,需要将真实的0值赋值给该行数据。
}
if(StringUtils.isEmpty(ocScope.getScopeName()) && code1==0 && code2==0){
ocScope.setP2ScopeName("");
}
if(StringUtils.isEmpty(ocScope.getScopeName()) && code1==0 && code2==1 && wCode2==0){
ocScope.setP2Weights(0.00);
}
if(StringUtils.isEmpty(ocScope.getScopeName()) && code1==0 && code2==0 && code3==0){
ocScope.setP3ScopeName("");
}
if(StringUtils.isEmpty(ocScope.getScopeName()) && code1==0 && code2==0 && code1==0 && wCode3==0){
ocScope.setP3Weights(0.00);
}
//实体可以用list接收,也可以用map,本列用map接收。
//istOcScope.add(ocScope);
ocScopeMap.put(p4+p3+p2+p1+ocScope.getScopeName(), ocScope);//key值是关键,将其四个直系父级和本身同时放入key值中。避免去重出错。
}
//遍历主map,取出1,2,3,4,5,级的数据。并包装到相应的map中去。
for (String key : ocScopeMap.keySet()) {
//获取第1级数据
OcScope ocScope1 = new OcScope();
ocScope1.setScopeName(ocScopeMap.get(key).getP4ScopeName());
ocScope1.setParentName(null);
ocScope1.setLevel("1");
ocScope1.setWeights(ocScopeMap.get(key).getP4Weights());
ocScopeMapDictOne.put(ocScopeMap.get(key).getP4ScopeName(), ocScope1) ;
//将数据封装到1级的map中在去
ocScopeMapOne.put(ocScopeMap.get(key).getP4ScopeName(), ocScope1);
//获取第2级数据
OcScope ocScope2 = new OcScope();
ocScope2.setParentName(ocScopeMap.get(key).getP4ScopeName());
ocScope2.setScopeName(ocScopeMap.get(key).getP3ScopeName());
ocScope2.setLevel("2");
ocScope2.setWeights(ocScopeMap.get(key).getP3Weights());
//将数据封装到2级的map中去
ocScopeMapTwo.put(ocScopeMap.get(key).getP4ScopeName()+ocScopeMap.get(key).getP3ScopeName(), ocScope2);
//获取第3级数据
OcScope ocScope3 = new OcScope();
//该级需要装GrandFatherName属性进去,避免错误的将数据存储在相同的父级名称,不同爷爷级别的数据中去
ocScope3.setGrandFatherName(ocScopeMap.get(key).getP4ScopeName());
ocScope3.setParentName(ocScopeMap.get(key).getP3ScopeName());
ocScope3.setScopeName(ocScopeMap.get(key).getP2ScopeName());
ocScope3.setLevel("3");
ocScope3.setWeights(ocScopeMap.get(key).getP2Weights());
//将数据封装到3级的map中去
ocScopeMapThree.put(ocScopeMap.get(key).getP3ScopeName()+ocScopeMap.get(key).getP2ScopeName(), ocScope3);
//获取第4级数据
OcScope ocScope4 = new OcScope();
//该级需要装GrandFatherName属性进去,避免错误的将数据存储在相同的父级名称,不同爷爷级别的数据中去
ocScope4.setGrandFatherName(ocScopeMap.get(key).getP3ScopeName());
ocScope4.setParentName(ocScopeMap.get(key).getP2ScopeName());
ocScope4.setScopeName(ocScopeMap.get(key).getP1ScopeName());
ocScope4.setLevel("4");
ocScope4.setWeights(ocScopeMap.get(key).getP1Weights());
//将数据封装到4级的map中去
ocScopeMapFour.put(ocScopeMap.get(key).getP2ScopeName()+ocScopeMap.get(key).getP1ScopeName(), ocScope4);
//获取第4级数据
OcScope ocScope5 = new OcScope();
//该级需要装GrandFatherName属性进去,避免错误的将数据存储在相同的父级名称,不同爷爷级别的数据中去
ocScope5.setGrandFatherName(ocScopeMap.get(key).getP2ScopeName());
ocScope5.setParentName(ocScopeMap.get(key).getP1ScopeName());
ocScope5.setScopeName(ocScopeMap.get(key).getScopeName());
ocScope5.setLevel("5");
ocScope5.setWeights(ocScopeMap.get(key).getWeights());
ocScopeMapFive.put(ocScopeMap.get(key).getP1ScopeName()+ocScopeMap.get(key).getScopeName(), ocScope5);
}
//从数据库查询出所有的数据
List<OcScope> ocScopelist= dao.findList(new OcScope());
List<OcScope> ocScopelistOne= new ArrayList<>();
List<OcScope> ocScopelistTwo= new ArrayList<>();
List<OcScope> ocScopelistThree= new ArrayList<>();
List<OcScope> ocScopelistFour= new ArrayList<>();
List<OcScope> ocScopelistFive= new ArrayList<>();
// 遍历封装1.2.3.4.5级的数据到list中去 (避免查询太多的数据库查询次数,导致性能不足)
for (OcScope ocScope : ocScopelist) {
if(ocScope.getLevel().equals("1")){
ocScopelistOne.add(ocScope);
}
if(ocScope.getLevel().equals("2")){
ocScopelistTwo.add(ocScope);
}
if(ocScope.getLevel().equals("3")){
ocScopelistThree.add(ocScope);
}
if(ocScope.getLevel().equals("4")){
ocScopelistFour.add(ocScope);
}
if(ocScope.getLevel().equals("5")){
ocScopelistFive.add(ocScope);
}
}
OcDict ocDict =new OcDict();
ocDict.setType("evaluation_dimension");
List<OcDict> ocDictLiset= ocDictService.findList(ocDict);
List<Integer> OcDictListValue= new ArrayList<>();
for (OcDict ocDict2 : ocDictLiset) {
OcDictListValue.add(Integer.valueOf(ocDict2.getValue()));
}
List<String> mapCode=new ArrayList<>();
Integer max = Collections.max(OcDictListValue);
for (String key : ocScopeMapDictOne.keySet()) {
for (OcDict ocDict1 : ocDictLiset) {
if(ocScopeMapDictOne.get(key).getScopeName().equals(ocDict1.getLabel())){
mapCode.add(key);
}
}
}
for (String str : mapCode) {
ocScopeMapDictOne.remove(str);
}
for (String key : ocScopeMapDictOne.keySet()) {
OcDict ocDict3 =new OcDict();
ocDict3.setLabel(ocScopeMapDictOne.get(key).getScopeName());
ocDict3.setType("evaluation_dimension");
max++;
String v=max.toString();
ocDict3.setValue(v);
ocDictService.save(ocDict3);
}
List<OcDict> ocDictLiset2= ocDictService.findList(ocDict);
for (String key : ocScopeMapOne.keySet()) { //遍历level=1的数据
for (OcDict ocDict1 : ocDictLiset2) {
if(ocScopeMapOne.get(key).getScopeName().equals(ocDict1.getLabel())){
ocScopeMapOne.get(key).setType(ocDict1.getValue());
OcScope OcScope = new OcScope();
OcScope.setId("0"); //由于其是第一级,故将其父级id设为0
ocScopeMapOne.get(key).setParent(OcScope); //将数据加入
}
}
}
List<String> map1CodeList= new ArrayList<>(); //用于记录map中的数据,和数据库中的数据是否有重复。
for (String key : ocScopeMapOne.keySet()) {
for (OcScope ocScope1 : ocScopelistOne) {
if(ocScopeMapOne.get(key).getScopeName().equals(ocScope1.getScopeName())){
map1CodeList.add(key); //记录key值
if(ocScopeMapOne.get(key).getWeights()!=ocScope1.getWeights()){
ocScope1.setWeights(ocScopeMapOne.get(key).getWeights());
OcScope OcScope = new OcScope();
OcScope.setId("0"); //由于其是第一级,故将其父级id设为0
ocScope1.setParent(OcScope);
save(ocScope1);
}
}
}
}
for (String str : map1CodeList) {
ocScopeMapOne.remove(str); //将map中包含的数据中的数据清除掉
}
for (String key : ocScopeMapOne.keySet()) {
if(ocScopeMapOne.get(key).getScopeName()!=null && !ocScopeMapOne.get(key).getScopeName().equals("")){
save(ocScopeMapOne.get(key));//将剩余的数据且不为空的存入到数据库中
}
}
OcScope ocScopeOne = new OcScope();
ocScopeOne.setLevel("1");
List<OcScope> ocScopelistOnes= dao.findList(ocScopeOne); //取出最新的level=2的数据
for (String key : ocScopeMapTwo.keySet()) {
for (OcScope ocScope1 : ocScopelistOnes) {
if(ocScopeMapTwo.get(key).getParentName().equals(ocScope1.getScopeName())){ //判断父级的名称是否等于一级的名称
ocScopeMapTwo.get(key).setParent(ocScope1); //将数据加入
ocScopeMapTwo.get(key).setType(ocScope1.getType());
}
}
}
List<String> map2CodeList= new ArrayList<>();
for (String key : ocScopeMapTwo.keySet()) { //遍历ocScopeMapTwo
for (OcScope ocScope2 : ocScopelistTwo) { //遍历ocScopelistTwo level=2的数据
if(ocScopeMapTwo.get(key).getScopeName().equals(ocScope2.getScopeName())){ //判断名称是否相等
map2CodeList.add(key); //相等加入map2CodeList 后面会将其处理掉,不新增该list中的数据 (易错点:对于批量增加数据而言需要判断相等记录下来,而不是判断不等就新增)
if(ocScopeMapTwo.get(key).getWeights()!=ocScope2.getWeights()){ //判断名称相等的情况下,权重是否改变,权重改变了要更新到数据库中
ocScope2.setWeights(ocScopeMapTwo.get(key).getWeights());
ocScope2.setType(ocScopeMapTwo.get(key).getType());
for (OcScope ocScope1 : ocScopelistOnes) {
if(ocScope2.getParentId().equals(ocScope1.getId())){
ocScope2.setParent(ocScope1);
save(ocScope2);
}
}
}
}
}
}
for (String str : map2CodeList) {
ocScopeMapTwo.remove(str); //在ocScopeMapTwo中移除数据库已近存在的数据
}
for (String key : ocScopeMapTwo.keySet()) {
if(ocScopeMapTwo.get(key).getScopeName()!=null && !ocScopeMapTwo.get(key).getScopeName().equals("")){
save(ocScopeMapTwo.get(key));//将剩余的数据且不为空的存入到数据库中
}
}
OcScope ocScopeTwo = new OcScope();
ocScopeTwo.setLevel("2");
List<OcScope> ocScopelistTwos= dao.findList(ocScopeTwo); //取出最新的level=2的数据
for (String key : ocScopeMapThree.keySet()) {
for (OcScope ocScope2 : ocScopelistTwos) {
//由于数据多存在不同父级,相同子级的数据,所以需判读其GrandFather级别的数据是否相等
if(ocScopeMapThree.get(key).getParentName().equals(ocScope2.getScopeName()) && ocScopeMapThree.get(key).getGrandFatherName().equals(ocScope2.getParentName())){
ocScopeMapThree.get(key).setParent(ocScope2);
ocScopeMapThree.get(key).setType(ocScope2.getType());
}
}
}
List<String> map3CodeList= new ArrayList<>();
for (String key : ocScopeMapThree.keySet()) {
for (OcScope ocScope3 : ocScopelistThree) {
if(ocScopeMapThree.get(key).getScopeName().equals(ocScope3.getScopeName())){
map3CodeList.add(key);
if(ocScopeMapThree.get(key).getWeights()!=ocScope3.getWeights()){
ocScope3.setWeights(ocScopeMapThree.get(key).getWeights());
ocScope3.setType(ocScopeMapThree.get(key).getType());
for (OcScope ocScope2 : ocScopelistTwos) {
if(ocScope3.getParentId().equals(ocScope2.getId())){
ocScope3.setParent(ocScope2);
save(ocScope3);
}
}
}
}
}
}
for (String str : map3CodeList) {
ocScopeMapThree.remove(str);
}
for (String key : ocScopeMapThree.keySet()) {
if(ocScopeMapThree.get(key).getScopeName()!=null && !ocScopeMapThree.get(key).getScopeName().equals("")){
save(ocScopeMapThree.get(key));
}
}
OcScope ocScopeThree = new OcScope();
ocScopeThree.setLevel("3");
List<OcScope> ocScopelistThrees= dao.findList(ocScopeThree); //取出最新的level=3的数据
//遍历 level=4的数据
for (String key : ocScopeMapFour.keySet()) {
for (OcScope ocScope3 : ocScopelistThrees) {
if(ocScopeMapFour.get(key).getParentName().equals(ocScope3.getScopeName()) && ocScopeMapFour.get(key).getGrandFatherName().equals(ocScope3.getParentName()) ){
ocScopeMapFour.get(key).setParent(ocScope3);
ocScopeMapFour.get(key).setType(ocScope3.getType());
}
}
}
List<String> map4CodeList= new ArrayList<>();
for (String key : ocScopeMapFour.keySet()) {
for (OcScope ocScope4 : ocScopelistFour) {
if(ocScopeMapFour.get(key).getScopeName().equals(ocScope4.getScopeName())){
map4CodeList.add(key);
if(ocScopeMapFour.get(key).getWeights()!=ocScope4.getWeights()){
ocScope4.setWeights(ocScopeMapFour.get(key).getWeights());
ocScope4.setType(ocScopeMapFour.get(key).getType());
for (OcScope ocScope3 : ocScopelistThrees) {
if(ocScope4.getParentId().equals(ocScope3.getId())){
ocScope4.setParent(ocScope3);
save(ocScope4);
}
}
}
}
}
}
for (String str : map4CodeList) {
ocScopeMapFour.remove(str);
}
for (String key : ocScopeMapFour.keySet()) {
if(ocScopeMapFour.get(key).getScopeName()!=null && !ocScopeMapFour.get(key).getScopeName().equals("")){
save(ocScopeMapFour.get(key));
}
}
OcScope ocScopeFour = new OcScope();
ocScopeFour.setLevel("4");
List<OcScope> ocScopelistFours= dao.findList(ocScopeFour); //取出最新的level=4的数据
//遍历 level=5的数据
for (String key : ocScopeMapFive.keySet()) {
for (OcScope ocScope4 : ocScopelistFours) {
if(ocScopeMapFive.get(key).getParentName().equals(ocScope4.getScopeName()) && ocScopeMapFive.get(key).getGrandFatherName().equals(ocScope4.getParentName()) ){
ocScopeMapFive.get(key).setParent(ocScope4);
ocScopeMapFive.get(key).setType(ocScope4.getType());
}
}
}
List<String> map5CodeList= new ArrayList<>();
for (String key : ocScopeMapFive.keySet()) {
for (OcScope ocScope5 : ocScopelistFive) {
if(ocScopeMapFive.get(key).getScopeName().equals(ocScope5.getScopeName())){
map5CodeList.add(key);
if(ocScopeMapFive.get(key).getWeights()!=ocScope5.getWeights()){
ocScope5.setWeights(ocScopeMapFive.get(key).getWeights());
ocScope5.setType(ocScopeMapFive.get(key).getType());
for (OcScope ocScope4 : ocScopelistFours) {
if(ocScope5.getParentId().equals(ocScope4.getId())){
ocScope5.setParent(ocScope4);
save(ocScope5);
}
}
}
}
}
}
for (String str : map5CodeList) {
ocScopeMapFive.remove(str);
}
for (String key : ocScopeMapFive.keySet()) {
if(ocScopeMapFive.get(key).getScopeName()!=null && !ocScopeMapFive.get(key).getScopeName().equals("")){
save(ocScopeMapFive.get(key));
}
}
}