导入Excel表数据到-数据库中

1.目的:excel->读数据->存数据库表中


2.项目前后端不分离、工具Idea

3.前端使用jsp+jQuery+bootstrap

4.后端使用SpringBoot框架

5.excel是xlsx后缀

前端页面:

1.放入插件:需要引入插件:4个

<head>

    <!-- //css和js都需要放在初始化方法后引用,否则可能导致页面不能正常渲染。一般引用min版,提高页面加载速度 -->

    <!--bootstrap-fileinput的css插件:用于文件上传-->


/css/fileinput-rtl.min.css" rel="stylesheet">

    <link href="<%=bootstrap%>/css/fileinput.min.css" rel="stylesheet">

</head>

 2.添加按钮

<body>

<!--文件上传按钮-->

<input id="upfile" type="file" 

accept="image/*,application/pdf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" 

multiple="multiple">

</div>


    <script src="<%=bootstrap%>/js/fileinput.js"></script>

    <script src="<%=bootstrap%>/js/fileinput_locale_zh.js"></script>

</body>

3.js处写法

3.3前后端交互路径

var urlUpload = path +'/building/upfile.do'; //文件上传

3.1//初始化

$(function() {

  fileinput1();

})

3.2//实现excel导入功能

function fileinput1() {

//初始化 - 插件的初始化方法应该在页面加载后立即调用,并且只调用一次

  $("#upfile").fileinput({

theme:"fa",

      language:"zh", //设置语言

      uploadAsync:true, //异步上传

      dropZoneEnabled:false, //是否显示拖拽区域

      showPreview:false, //显示预览信息

      uploadUrl: urlUpload,

      showPreview:false, //是否显示预览

      maxFileSize:20 *1024, //单个文件大小,单位为kb,如果为0表示不限制文件大小

      maxFileCount:10, //允许上传的最大文件个数

      minFileCount:1, //允许上传的最小文件个数

    //uploadExtraData: { "bid": "1"},  //参数

      uploadExtraData:function() {//向后台动态传递参数

        var data = {bid: buildingid};

       return data;

      },

      allowedFileExtensions: ["xlsx"],

      showUpload:true ,//显示上传按钮

  }).on("fileuploaded", function(event, data, previewId, index) {

//根据data.response判断是否上传成功

      if (data.response.meta.code =="200") {

//alert("123");

        $(event.target).fileinput('clear').fileinput('unlock');

        swal("上传成功!", "您已经上传了这条信息。", "success");

      }else {

swal({

title: data.response.meta.msg, //失败的错误信息

            type:"error",

            confirmButtonText:"确定"

        });

      }

});

}

后端:

controller层:

package com.maptechinc.practice.gengqn.building.controller;

import java.io.File;

@Controller

@RequestMapping("/building")

public class BuildingController extends AbstractBaseController {

    @Autowired

    private BuildingService buildingService;

@Autowired

    private HouseService houseService;

    //引入配置的路径

    @Value("${fileSaveDir}")

  private String fileSaveDir;


    /**

    * excel表上传

    * @param request

    * @param response

    * @throws BusinessException

    * @throws IOException

    */

    @RequestMapping(value = "/upfile.do")

    public void upfile( MultipartFile file_data,HttpServletRequest request, HttpServletResponse response) throws BusinessException, IOException{

    Map<String, Object> map = conditionalTransitions(request);

    //获取参数,bid=buildingid

    String bid = map.get("bid")==null?"":map.get("bid").toString();


    List<List<HousePO>> list = this.importExcel(request);


//判断是否选中一条

    if("".equals(bid)){

responseJsonWriter(response, Result.failed("请先选择一行数据再上传,谢谢"));

}else{

//excel导入

Result result = buildingService.importHouseExcel(file_data,request,response,bid);

if(result.ok){

responseJsonWriter(response,Result.success("上传成功"));

}else {

responseJsonWriter(response, map, result.msg);

}}}}

Service层:

package com.maptechinc.practice.gengqn.building.service;

import java.io.InputStream;

/**

* <p>类描述:楼房管理 </p>

* <p>类名称:com.maptechinc.practice.gengqn.building.service.BuildingService </p>

* <p>创建人:耿倩楠 </p>

* <p>邮箱:${email} </p>

* <p>创建时间:2023-07-25 11:22:20 </p>

*/

@Service

public class BuildingService{

@Autowired

BuildingDao buildingDao;

@Autowired

HouseDao houseDao;

@Autowired

HousePODao housePODao;

@Autowired

BuildingPODao buildingPODao;

/**

* 导入excel

* 导入字段说明:

* unit<单元>、

* floor<所在层>、

* serialNo<房号>为一个合适大小的正整数,且不可空缺。

* houseCode<单元间号>如果空缺,则系统自动拼接:<单元>+<所在层>+<房号>,用“-”连接,比如1-3-2,如果不空缺,则读取导入的数据。

* houseType<房屋用途>不可空缺,且只能为以下几种之一:住宅,商业,工业,设备用房,其他。

* coveredArea<建筑面积>,privateArea<套内面积>可空缺,空缺时数据库存入0,但如果有值则必须为数字。

* chanjiNo<产籍号>可空缺,空缺时以0补齐。

*/

public Result importHouseExcel(MultipartFile file_data, HttpServletRequest request, HttpServletResponse response,String bid) {

StringBuffer  returnmess=new StringBuffer();//用于拼接 上传excel 错误信息

String regex = "^\\d+$";  //正则表达式 只能是数字

Pattern pattern = Pattern.compile(regex); //正则表达式 只能是数字

//flag用于校验的标识

boolean flag=false;

//创建datainsertList,用于存放表格数据

List<Map<String,Object>> datainsertList=new ArrayList<Map<String,Object>>();

try {

//获取文件流

InputStream inputStream = file_data.getInputStream();

//根据路径获取这个操作excel的实例

XSSFWorkbook excel = new XSSFWorkbook(inputStream);

//根据页面index 获取sheet页

Sheet sheet = excel.getSheetAt(0);

//获取sheet页共有多少行

int totalRos = sheet.getPhysicalNumberOfRows();

//System.out.println("=========总行数为:"+totalRos);

for (int i = 2; i <totalRos; i++) {//第1/2行是表头 不需要取

Map<String,Object> aa=new HashMap<String, Object>();

//获取某行数据

int lastCellNum = sheet.getRow(i).getLastCellNum();

aa.put("id",UUID.randomUUID().toString().replaceAll("-", ""));

//判断house表中是否有此buildingId

int count = houseDao.checkByBuildingId(bid.toString());

if(count>0){

flag=true;

returnmess.append("第"+i+"楼栋已存在房屋信息,不可再次导入,请检查");

}else{

aa.put("buildingId",bid);

}

//获取第i行  第几格的数据

aa.put("unit", sheet.getRow(i).getCell(0).toString());

aa.put("floor", sheet.getRow(i).getCell(1).toString());

aa.put("serialNo", sheet.getRow(i).getCell(2).toString());

aa.put("houseCode", sheet.getRow(i).getCell(3).toString());

//获取第i行  第4格的数据

String cellValueHouseType =sheet.getRow(i).getCell(4).toString(); 

//校验字段,有问题返回

if("".equals(cellValueHouseType)){

flag=true;

returnmess.append("第"+i+"行房屋用途为空,请检查");

}

if(!"住宅".equals(cellValueHouseType)&&

!"商业".equals(cellValueHouseType)&&

!"工业".equals(cellValueHouseType)&&

!"设备用房".equals(cellValueHouseType)){

flag=true;

returnmess.append("第"+i+"行房屋用途,只能为以下几种之一:住宅,商业,工业,设备用房,请检查;");

}

aa.put("houseType", sheet.getRow(i).getCell(4).toString());

//校验字段,有问题返回

String cellValueCoveredArea =sheet.getRow(i).getCell(5).toString();

if(cellValueCoveredArea==""){

aa.put("coveredArea", "0");

}else{

Matcher matcher = pattern.matcher(cellValueCoveredArea);

if (matcher.matches()) { //正则匹配:如果是数字则返回false  反之返回true

flag=true;

returnmess.append("第"+i+"行建筑面积只能是数字,请检查;");

}else{

aa.put("coveredArea", sheet.getRow(i).getCell(5).toString());

}

}

aa.put("privateArea", sheet.getRow(i).getCell(6).toString());

aa.put("status","0");

//校验字段,有问题返回

String cellValueChanjiNo =sheet.getRow(i).getCell(7).toString();

if(cellValueChanjiNo == ""){

aa.put("chanjiNo", "0");

}else{

aa.put("chanjiNo", sheet.getRow(i).getCell(7).toString());

}

datainsertList.add(aa);

}

} catch (Exception e) {

e.printStackTrace();

}

if(flag){

//responseJsonWriter(response, Result.failed(returnmess.toString()));

return Result.failed(returnmess.toString());

}else{

//将数据存到house数据库中

for(int r=0;r<datainsertList.size();r++){

Map<String,Object> map3 = datainsertList.get(r);

houseDao.insert(map3);

}

return Result.success("上传成功");

}

}

}

Dao层:

package com.maptechinc.practice.gengqn.building.dao;

import java.util.List;

@Mapper

public interface BuildingDao {

/**

* 新增一条数据

* @param map

* @return

*/

int insert(Map<String, Object> map);

/**

* 判断楼栋名称是否重复

* @param map

* @return

*/

int checkByName(Map<String, Object> map);

}

XML:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.maptechinc.practice.gengqn.building.dao.BuildingDao">

<select id="dataList" parameterType="java.util.Map" resultType="java.util.Map"> 

SELECT pb.id,pb.projectId,p.projectName projectName,pb.buildingNo buildingNo,pb.address address,pb.cost cost,COUNT(pb.id) houseCount

FROM practice_building pb

LEFT JOIN practice_project p ON pb.projectId = p.id

LEFT JOIN practice_house ph ON pb.id = ph.buildingId

GROUP BY pb.id,pb.projectId,p.projectName,pb.buildingNo,pb.address,pb.cost;

</select>

<select id="checkByName" parameterType="java.util.Map" resultType="java.lang.Integer">

SELECT COUNT(1)

FROM practice_building

WHERE buildingNo=#{buildingNo};

</select>

<select id="projectDropDown" resultType="com.maptechinc.practice.gengqn.project.bo.Project" parameterType="java.util.Map">

select p.id,p.projectName from `practice_project` p

</select>

    <delete id="deleteByProjectId" parameterType="java.util.Map">

      DELETE FROM practice_building

      WHERE projectId=#{id}

    </delete>


</mapper>

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 227,967评论 6 531
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 98,273评论 3 415
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 175,870评论 0 373
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,742评论 1 309
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,527评论 6 407
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,010评论 1 322
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,108评论 3 440
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,250评论 0 288
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,769评论 1 333
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,656评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,853评论 1 369
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,371评论 5 358
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,103评论 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,472评论 0 26
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,717评论 1 281
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,487评论 3 390
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,815评论 2 372

推荐阅读更多精彩内容