精华内容
下载资源
问答
  • Java实现Excel导入数据

    2020-12-28 09:59:17
    Apache POI(Poor Obfuscation Implementation)是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office格式档案读和写的功能。API文档:...

    1.引入org.apache.poi相关jar包
    Apache POI(Poor Obfuscation Implementation)是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office格式档案读和写的功能。API文档:http://poi.apache.org/apidocs/index.html ,我这里以SSM项目为例,在pom.xml配置文件中配置。

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

    2.在页面编写Excel上传的方法(这里使用了Layui组件),代码如下:

    <!---------------------- 设置隐藏表单 ----------------------->
    <div style="display: none;">
    	<form method="post" id="formFile" action=""
    		enctype="multipart/form-data">
    		<button type="button" id="uploadFile"></button>
    	</form>
    </div>
    
    <script>
    	var upload = layui.upload;
    	//上传Excel文件(添加数据)
    	function uploadExcelFile(){
    		$("#uploadFile").click();
    	}
    	
    	//监听文件上传
    	upload.render({
    		elem : '#formFile',
    		url : '${ctx}/dataManage/importDidInfo.do',
    		accept: 'file', //普通文件
    		acceptMime:'.xls,.xlsx,.XLS',//设置文件的筛选
    	    exts: 'xls|xlsx|XLS', //允许上传的文件后缀
    		field:"uploadFile", //默认文件域是file,也可以自己定义,与后台struts中获取文件名有关
    		before:function(obj){
    			onload();//加载层
    		},
    		done : function(res) {
    			layer.msg(res.text);//提示
    			searchAddDidInfo();//刷新数据表格
    			onclose();//关闭加载层
    		}
    	});
    	
    	//显示加载层
    	function onload(){
    		layer.msg("正在上传", {
    			icon:16,
    			shade:[0.2, '#000'],
    			time:false//取消自动关闭
    		});
    	}
    	//关闭加载层
    	function onclose(){
    		layer.closeAll('loading');
    	}
    </script>
    

    3.controller层代码,如下所示:

    @Controller
    @RequestMapping("/dataManage")
    @Api(value = "数据管理接口", description = "数据管理相关api")
    public class DataManageController {
    	private Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
    
    	@SuppressWarnings({ "resource", "unused", "unchecked" })
    	@ResponseBody
    	@RequestMapping(value = "/importDidInfo", method = RequestMethod.POST)
    	public Object importDidInfo(HttpServletRequest request, HttpSession session,
    			@RequestParam(value = "uploadFile", required = false) MultipartFile uploadFile)
    			throws IOException {
    		JsonReturn jsonReturn = new JsonReturn();
    
    		// poi--exl解析
    		InputStream is = uploadFile.getInputStream();
    		// 获取文件名称
    		String name = uploadFile.getOriginalFilename();
    		// 获取文件后缀名
    		String suffixName = name.substring(name.lastIndexOf("."));
    		Workbook work = null;//创建工作簿
    		if (".xls".equals(suffixName)) {
    			work = new HSSFWorkbook(is); // 2003-
    		} else {
    			work = new XSSFWorkbook(is); // 2007+
    		}
    		int successRows = 0;
    		if (work != null) {
    			Sheet sheet = null;
    			Row row = null;
    			
    			// 获取session中的数据
    			List<DidInfo> listDid = (List<DidInfo>) session.getAttribute("listDid");
    			if (listDid == null) {
    				listDid = new ArrayList<DidInfo>();
    			} 
    
    			// 判断工作簿中的工作表(Sheet)的个数
    			if (work.getNumberOfSheets() > 0) {
    				// 获取第一个工作表
    				sheet = work.getSheetAt(0);
    				if (sheet == null) {
    					jsonReturn.setText("这是一个空的工作簿");
    					return gson.toJson(jsonReturn);
    				}
    
    				// 遍历当前sheet中的所有行
    				if (sheet.getLastRowNum() > 0) {
    					for (int j = sheet.getFirstRowNum(); j <= sheet.getLastRowNum(); j++) {
    						row = sheet.getRow(j);
    						// 排除第一行和空的行
    						if (row == null || row.getFirstCellNum() == j) {
    							continue;
    						}
    
    						// 遍历所有的列
    						Cell cell0 = row.getCell(0);// 数据类型
    						Cell cell1 = row.getCell(1);// 数据标识符
    						Cell cell2 = row.getCell(2);// 描述
    						Cell cell3 = row.getCell(3);// 单位
    						Cell cell4 = row.getCell(4);// 备注
    						DidInfo didInfo = new DidInfo();
    
    						// 赋值
    						didInfo.setDataType(cell0.toString());
    						didInfo.setDataIdentifier(cell1.toString());
    						didInfo.setDidDescribe(cell2.toString());
    						didInfo.setDidUnit(cell3.toString());
    						didInfo.setDidRemark(cell4.toString());
    
    						listDid.add(didInfo);
    						successRows++;// 成功条数
    					}
    					if (successRows == sheet.getLastRowNum()) {
    						jsonReturn.setText("导入成功");
    					} else if (successRows >= 0 && successRows < sheet.getLastRowNum()) {
    						int failRows = sheet.getLastRowNum() - successRows;
    						jsonReturn.setText(successRows + "条数据导入成功," + failRows + "条数数据导入失败");
    					}
    					
    					// 将信息保存到session中
    					session.setAttribute("listDid", listDid);
    				} else {
    					jsonReturn.setText("物理行数为0");
    				}
    			}
    		} else {
    			jsonReturn.setText("创建Excel工作薄为空!");
    		}
    		is.close();
    		return gson.toJson(jsonReturn);
    	}
    }
    

    返回参数JsonReturn,示例代码:

    package com.gx.vo;
    
    import java.io.Serializable;
    
    public class JsonReturn implements Serializable{
    	
    	/**
    	 * 
    	 */
    	private static final long serialVersionUID = 1L;
    
    	private int code;
    	
    	private String text;
    	
    	private Object data;
    
    	public int getCode() {
    		return code;
    	}
    
    	public void setCode(int code) {
    		this.code = code;
    	}
    
    	public String getText() {
    		return text;
    	}
    
    	public void setText(String text) {
    		this.text = text;
    	}
    
    	public Object getData() {
    		return data;
    	}
    
    	public void setData(Object data) {
    		this.data = data;
    	}
    }
    

    4.上传的Excel文档以及上传成功后的截图,如下图所示:
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • Java实现Excel多表头动态数据导出

    千次阅读 2020-07-23 13:05:12
    好久没时间写帖子了,由于工作需要,写一个基于JAVA实现Excel多表头动态导出功能,首先可能这个叫法比较啰嗦,下面我们先看看什么是Excel多表头动态导出(效果图): 它包含两部分:1、是表头,就像大家看到的...

       好久没时间写帖子了,由于工作需要,写一个基于JAVA实现的Excel多表头动态导出功能,首先可能这个叫法比较啰嗦,下面我们先看看什么是Excel多表头动态导出(效果图):

     它包含两部分:1、是表头,就像大家看到的样子它的表头是多行合并的(多表头);2.内容部分,就是下方的数据数据内容。

    两个内容都是有后台人员分别由两个接口返回的(也可以一个,但一个会显得格式冗余),因此他的表头数据是不固定的,可能有甲方要求,甲方、乙方、丙方要求等,是随机看后台数据的,所以我们就不能事先画好Excel模板进行导出,好以上就是我对java实现Excel多表头动态导出的说明下面开始吧。

    一、在开发前我们要撸一下思路,该怎么去做?会遇到什么坑?首先不用多说肯定识这个多表头的问题了,后端返回的Json数据一般都:

    不难发现一个list<Map>发现虽然都有一、二级目录的区分,但是分开的不符合我们的需要,因此我们需要转换分组为想要的数据类型

    Map<String, List<Map>>格式的数据:既把同一个一级目录下的二级目录放到一个List<Map>中方便后面的Excel渲染

    二、就是在Excel做数据渲染时的数据角标的计算问题,以及如何让经过我们分组后的表头数据与内容匹配上,因为数据是动态生成的,所以在生成数据是一定要注意,后几列的数据再前几列数据生成的基础上向后推的。

    三、主要的坑应该就是上面两个问题了,那我们开发撸代码吧:

    1、我使用的实现语言是JAVA中的servlet,关于servlet不太熟悉的小伙伴可以百度自行科普一下,简单说就是(1):

    集成HttpServlet并实现其几个方法;(2)配置web.xlm文件等。

    代码:

    /**
     * 自定义表头导出方法
     * @throws: l
     * @param :resultParam 导出excel名称、模板名称、导出地址
     */
    public void exportExcelByDiyTitle(HttpServletRequest request, HttpServletResponse response)throws IOException{
       System.out.println("进入自定义导出表头方法");
       response.reset();// 清空输出流
       String templateName ="按异常原因统计";
       //获取导出参数进行查询orgId=06&date=2020-07
       String orgId = request.getParameter("orgId");//组织ID
       String date = request.getParameter("date");//日期
       String type = request.getParameter("type");//日期
       List<Map<String,Object>> listtitle=null;
       List<Map<String,Object>> list=null;
       WorkOrderInforShowService workOrderInforShowService = new WorkOrderInforShowServiceImpl();
       //这是调用后台Execl表头数据接口
          listtitle = workOrderInforShowService.getYCLXTypeOfYY(orgId,date);
         //获取Excell内容数据接口
          list = workOrderInforShowService.getAppWorkOrderStatisticsOfYY(orgId,date);
       //设置谷歌和Ie浏览器导出表单乱码问题
       String userAgent = request.getHeader("User-Agent");
       if (userAgent.contains("MSIE")||userAgent.contains("Trident")){
          templateName = java.net.URLEncoder.encode(templateName, "UTF-8");
       }else{
          templateName = new String(templateName.getBytes("UTF-8"),"ISO-8859-1");
       }
       response.setHeader("Content-disposition", "attachment; filename="
             + templateName+ ".xls");// 设定输出文件头
          response.setContentType("application/msexcel");
          // 创建一个工作薄
           HSSFWorkbook workbook = new HSSFWorkbook();
           // 生成一个表格
           HSSFSheet sheet = workbook.createSheet("数据明细");
       HSSFCellStyle cellStyle = workbook.createCellStyle();
       //设置表头字体
       HSSFFont font2 = workbook.createFont();
       font2.setFontName("仿宋_GB2312");
       font2.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);//粗体显示
       font2.setFontHeightInPoints((short) 10);
       //TODO 水平垂直居中 列宽
       cellStyle.setAlignment(HorizontalAlignment.CENTER_SELECTION);
       cellStyle.setFont(font2);
       // 产生表格标题行
           HSSFRow firrow = sheet.createRow(0);
       // 产生表格标题行
       HSSFRow row = sheet.createRow(1);
       CellRangeAddress cellRange = null;
       //一级表头
       String manKey=null;
       //判断表头是否有数据
       if(listtitle.size()==0){
          return;
       }
    //这就是我们对无序的表头数据进行分组得等满足要求的Map<String, List<Map>> 格式数据
          Map<String, List<Map>> temp =new HashMap<String, List<Map>>();
          for(Map item:listtitle){
             String key = item.get("VAL_ONE").toString();
             if(temp.get(key) == null){
                List<Map> list1 = new ArrayList<>();
                temp.put(key,list1);
             }else{
                temp.put(key,temp.get(key));
             }
             temp.get(key).add(item);
          }
        
       //设置固定单位列
       HSSFCell organizeCell = firrow.createCell(0);
       organizeCell.setCellStyle(cellStyle);
       //由于后台数据并没有返回项目名称这一列接口数据,因此我们只能自己生成
       organizeCell.setCellValue("项目名称");
       sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, 0));
           //遍历生成一、二级表头
       int count = 1;
           for(Map.Entry<String, List<Map>> entry : temp.entrySet()){
               List<Map> mapValue = entry.getValue();
                 manKey=entry.getKey();
               if(mapValue.size()>0){
                   //设置一级表头
             HSSFCell fircell = firrow.createCell(count);
             fircell.setCellStyle(cellStyle);
             fircell.setCellValue(manKey);
             //对合并列进行判断,当二级目录为一时既不需要合并
             if(mapValue.size()>1){
               //设置单元格合并操作,可以查询Excel导出api
                cellRange = new CellRangeAddress(0, 0, count, count + mapValue.size()-1);
                try {
                   sheet.addMergedRegion(cellRange);
                   addBorderLine(sheet,cellRange,workbook);
                }catch (Exception e){
                   e.printStackTrace();
                }
             }
           for (short i = 0; i < mapValue.size(); i++) {
                try {
                   //设置二级表头
                       HSSFCell cell = row.createCell(count+i);
                      HSSFRichTextString text = new HSSFRichTextString(mapValue.get(i).get("VAL_TWO").toString());
                      cell.setCellValue(text);
                //设置二级表头宽度
                sheet.setColumnWidth(count+i, text.toString().getBytes("UTF-8").length*256);
                cell.setCellStyle(cellStyle);
                CellRangeAddress cellRange1 = new CellRangeAddress(1, 1, count-1, count+i);
                //sheet.addMergedRegion(cellRange1);
                   //设置水平位置
                 addBorderLine(sheet, cellRange1, workbook);
                     }catch (Exception e){
                    e.printStackTrace();
                }
                  }
             count = count + mapValue.size();
          }
       }
           // 遍历集合数据,产生数据行
           if(list!=null && list.size() > 0){
               int index = 1;
               int count1 = 1;
          for (short i = 0; i < list.size(); i++) {
                   index++;
                   // 从表头下一行开始插入数据
                   row = sheet.createRow(index);
             row.createCell(0).setCellValue(list.get(i).get("XLMC").toString());
             for(Map.Entry<String, List<Map>> entry : temp.entrySet()){
                List<Map> mapValue = entry.getValue();
                manKey=entry.getKey();
                if(mapValue.size()>0){
                   for (short ii = 0; ii < mapValue.size(); ii++) {
                      try {
                         HSSFCell cell = row.createCell(count1 + ii);
                        //通过遍历表头二级表单“CODE_TWO”值 匹配内容接口数据
                         if(null==list.get(i).get(mapValue.get(ii).get("CODE_TWO").toString())||("null").equals(list.get(i).get(mapValue.get(ii).get("CODE_TWO").toString()))){
                            cell.setCellValue("0");
                         }else {
                            cell.setCellValue(list.get(i).get(mapValue.get(ii).get("CODE_TWO").toString()).toString());
                         }
                      }catch (Exception e){
                         e.printStackTrace();
                      }
                   }
                   count1 = count1 + mapValue.size();
                }
             }//当该行数据遍历完成之后,下一行从第二列开始
             count1=1;
               }
           }
           OutputStream outputStream = response.getOutputStream();// 打开流
           workbook.write(outputStream);// HSSFWorkbook写入流
           workbook.close();// HSSFWorkbook关闭
           outputStream.flush();// 刷新流
           outputStream.close();// 关闭流
           System.out.println("导出成功");
    }
    private void addBorderLine(HSSFSheet sheet,CellRangeAddress cellRangeAddress,HSSFWorkbook workbook){
       RegionUtil.setBorderTop(1, cellRangeAddress, sheet, workbook);
       RegionUtil.setBorderBottom(1, cellRangeAddress, sheet, workbook);
       RegionUtil.setBorderLeft(1, cellRangeAddress, sheet, workbook);
       RegionUtil.setBorderRight(1, cellRangeAddress, sheet, workbook);
    }
    

    内容接口:

     

    展开全文
  • Java实现Excel表读取数据并入库

    千次阅读 2019-04-12 11:05:50
    先介绍一下需求:现在有一张Excel表,表里面数据并不是统一的,而是有三个数据库表对应的数据类似如图: 类似于这样的一张表。分别对应三张数据库表,下面先说一下我的思路。用的是POI的jar包。 <...

    慢慢学习慢慢成长

           先介绍一下需求:现在有一张Excel表,表里面数据并不是统一的,而是有三个数据库表对应的数据类似如图:

    类似于这样的一张表。分别对应三张数据库表,下面先说一下我的思路。用的是POI的jar包。

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

    1.想要操作Excel表,那么我们肯定需要先拿到这张表对象。

    2.在对内容未知的情况下,我们不确定这张表共有多少页。所以通过Excel对象去拿到页长度

     

    3.循环页数组取出每一页

     

    4:通过当前页拿到当前页的所有行,注意有个坑

    5.循环取出每一行

    坑:POI的坑就在于,空行不算有效行,所以如果数据与数据之间存在空行的情况下,你不做出改变,数据就可能造成丢失

    解决思路:我去判断当前行如果是空行的情况下,我就将总行数再去+1,然后跳过这一行去下一行

    接下来需要自己理解了,因为每个人的需求不同,所以做的功能也不同,只能从别人的经验中吸取对自己有用的

    5.根据改行的第一列的值判断我接下来的数据对什么表操作,注意也有一个坑,解决思路后面说

    坑:因为需求原因,我需要操作的表不同,所以字段数量也不相同,但是就和获取有效行一样,获取有效列也只能获取到有

    数据的列,比如我有10个字段需要获取,但是有两个存在null的情况。那我能获取到的列的有效长度就是8,就丢了两个,这样数据乱了

    解决思路:我定义三个状态,一张表对应一个状态,只能有一个状态是true,通过状态决定操作什么表,并且因为表头是不会存在空值的情况,那么我就可以根据表头来决定有效列的长度,并且在没有遇到下一个表头的情况下,这个值不变,这样我就能获取完整的一条数据了,不管他有多少列的null数据。

    遇到的第三个坑:空指针,因为我之前没有想过定义状态,就是通过获取第一列的值来决定操作什么表

    但是没有考虑到第一列为null的情况,如果第一列为空我却使用null对象调用了方法。所以才决定使用状态来判断,避

    开这个坑。

    中间还遇到了许多问题,不过都是因为需求原因,所以就不多说了。希望能对看到这篇帖子的你起到帮助,那就够了。

    上完整代码,注释都还在。因为我就很讨厌那些没有注释的帖子。看不懂才不尴尬,但是思路都没有才是最尴尬的!!!!!

    import org.apache.poi.hssf.usermodel.HSSFCell;
    import org.apache.poi.ss.usermodel.Cell;
    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.xssf.usermodel.XSSFWorkbook;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class ExcelUtilTest {
    
        /**
         * Excel 三张表导入思想
         * 1.拿到Excel表对象         √
         * 2.拿到这个对象的总页数     √
         * 3.计算当前页的有效行数,注意空行不算有效行数
         * (这种情况就需要排除空行所以每次遇到空行的时候有效行数在循环过程中需要+1,通过这样来避免数据取不完)
    
         * 4.获取当前行的第一列的值,如果是所指定的内容,就获取改行的有效列。因为这是每张表的表头
         * 作为表头不会存在空列的情况,后面的数据都以表头的总列数循环
         *
         * 5.将数据根据判断的内容不同添加到不同的List集合中
         * 6.循环结束条件为一个变量,连续遇到指定数量的空行以后,默认为全部读取完毕。
         * 7.数据入库
         * 8。结束
         */
    
        public static void main(String[] args)throws Exception{
            List<Map<String,Object>> listPD = new ArrayList<Map<String,Object>>();
            boolean statePD=false;
    
            List<Map<String,Object>> listPDD = new ArrayList<Map<String,Object>>();
            boolean statePDD=false;
    
            List<Map<String,Object>> listPDP = new ArrayList<Map<String,Object>>();
            boolean statePDP=false;
    
            int nullCount = 0;
    
    
            /**1.拿到Excel表*/
            File excelFile = new File("D:\\ImportFile\\dataCheck\\Test.xlsx");
            InputStream is = new FileInputStream(excelFile);
            Workbook wb = new XSSFWorkbook(is);
            /**2.拿到这个对象的总页数*/
            int sheeetNum = wb.getNumberOfSheets();//总页数
            for (int i = 0;i < sheeetNum;i ++){
                /**2-1.拿到当前页对象*/
                Sheet sheetObj = wb.getSheetAt(i);//当前页对象
                /**3.拿到当前页的有效行数*/
                int rowNum = sheetObj.getLastRowNum();//有效行数
                int cellNum = 0;
                for (int j = 0;j < rowNum;j ++){///循环的是每一行
                    /**3-1.拿到当前行对象*/
                    Row rowObj = sheetObj.getRow(j);//行级对象
                    /**这种情况就需要排除空行所以每次遇到空行的时候有效行数在循环过程中需要+1,通过这样来避免数据取不完)*/
                    if (rowObj == null) {
                        rowNum++;
                        nullCount++;//出现的空值数量计数器
                        if (nullCount>3)break;//如果连续遇到三次或者指定次数的空行,代表这张表已经读取完了就break跳过本次循环去下一页
                        continue;
                    }else{
                        nullCount=0;//只要不是连续空值,就刷新计数器
                    }
                    /**4.获取当前行的第一列的值,如果这个值不是空值,我就拿出来对比一下是不是符合我的要求符合我就改变我所定义的状态*/
                    if (rowObj.getCell(0) != null) {
                        Cell cell = null;
                        rowObj.getCell(0).setCellType(HSSFCell.CELL_TYPE_STRING);
                        cell = rowObj.getCell(0);
                        if (cell.toString().indexOf("对等")>-1 || cell.toString().indexOf("注册")>-1) {
                            statePD=true;
                            statePDD=false;
                            statePDP=false;
                            cellNum  = rowObj.getLastCellNum();//只有在符合我所定的条件的时候我才去查询当前行的有效列数然后因为不对表头做操作,所以可以直接跳过这一行
                            continue;
                        }else
                        if (cell.toString().indexOf("起始电路号")>-1) {
                            statePD=false;
                            statePDD=true;
                            statePDP=false;
                            cellNum  = rowObj.getLastCellNum();//只有在符合我所定的条件的时候我才去查询当前行的有效列数然后因为不对表头做操作,所以可以直接跳过这一行
                            continue;
                        }else
                        if (cell.toString().indexOf("目的")>-1 || cell.toString().indexOf("索引")>-1) {
                            statePD=false;
                            statePDD=false;
                            statePDP=true;
                            cellNum  = rowObj.getLastCellNum();//只有在符合我所定的条件的时候我才去查询当前行的有效列数然后因为不对表头做操作,所以可以直接跳过这一行
                            continue;
                        }
                    }
                    /**那么现在我就不需要考虑了,什么表的状态是true我就对什么表做数据添加,因为如果为true说明这张表的数据还没有读取完*/
                    /**4-1.获取作为表头行所在行的有效列*/
                    if (statePD){//如果true就说明第一张表的数据还没有取完
                        Map<String,Object> mapPD = new HashMap<String,Object>();//最长的
                              for (int k = 0; k < cellNum; k++) {/循环的是每一列
                                  if (rowObj.getCell(k) != null ) rowObj.getCell(k).setCellType(HSSFCell.CELL_TYPE_STRING);
                                  Cell cellObj = rowObj.getCell(k);
                                  insertMapPD(cellObj,k,mapPD);
                              }
                              listPD.add(mapPD);
                    }else if (statePDD){
                        Map<String,Object> mapPDD = new HashMap<String,Object>();//最短的
                        for (int k = 0; k < cellNum; k++) {/循环的是每一列
                            if (rowObj.getCell(k) != null ) rowObj.getCell(k).setCellType(HSSFCell.CELL_TYPE_STRING);
                            Cell cellObj = rowObj.getCell(k);
                            insertMapPDD(cellObj,k,mapPDD);
                        }
                        listPDD.add(mapPDD);
                        mapPDD.clear();
                    }else if (statePDP){
                        Map<String,Object> mapPDP = new HashMap<String,Object>();//中间的
                        for (int k = 0; k < cellNum; k++) {/循环的是每一列
                            if (rowObj.getCell(k) != null ) rowObj.getCell(k).setCellType(HSSFCell.CELL_TYPE_STRING);
                            Cell cellObj = rowObj.getCell(k);
                            insertMapPDP(cellObj,k,mapPDP);
                        }
                        listPDP.add(mapPDP);
                        mapPDP.clear();
                    }
                }
            }
        }
    //这个位置的注释我就干掉了!因为是公司的表。我想这个也不需要去怎么理解。看下就懂了。就是一个数据的保存方法;
        public static void insertMapPD(Object obj,int i,Map mapPD){
            i+=1;
            switch (i){
                case 1:
                    mapPD.put("FD_TYPE",obj);
                    break;
                case 2:
                    mapPD.put("FD_OFCNAME",obj);
                    break;
                case 3:
                    mapPD.put("FD_INTERID",obj);
                    break;
                case 4:
                    mapPD.put("FD_INTERTYPE",obj);
                    break;
                case 5:
                    mapPD.put("FD_INTERGTN",obj);
                    break;
                case 6:
                    mapPD.put("FD_PORT",obj);
                    break;
                case 7:
                    mapPD.put("FD_SIGNSLOT",obj);
                    break;
                case 8:
                    mapPD.put("FD_PARAMSPF9",obj);
                    break;
                case 9:
                    mapPD.put("FD_SUBSPF",obj);
                    break;
                case 10:
                    mapPD.put("FD_MODULE",obj);
                    break;
                case 11:
                    mapPD.put("FD_LINK",obj);
                    break;
                case 12:
                    mapPD.put("FD_TRUNK",obj);
                    break;
                case 13:
                    mapPD.put("FD_CALL",obj);
                    break;
                case 14:
                    mapPD.put("FD_MINL",obj);
                    break;
                case 15:
                    mapPD.put("FD_MAXL",obj);
                    break;
                case 16:
                    mapPD.put("FD_MGWID",obj);
                    break;
            }
        }
    
        public static void insertMapPDD(Object obj,int i,Map mapPDD){
            i+=1;
            switch (i){
                case 1:
                    mapPDD.put("FD_SID",obj);
                    break;
                case 2:
                    mapPDD.put("FD_EID",obj);
                    break;
                case 3:
                    mapPDD.put("FD_TERMID",obj);
                    break;
            }
        }
    
        public static void insertMapPDP(Object obj,int i,Map mapPD){
            i+=1;
            switch (i){
                case 1:
                    mapPD.put("FD_SIGNINDEX",obj);
                    break;
                case 2:
                    mapPD.put("FD_SIGN",obj);
                    break;
                case 3:
                    mapPD.put("FD_BSGMODULE",obj);
                    break;
                case 4:
                    mapPD.put("FD_M2UA",obj);
                    break;
                case 5:
                    mapPD.put("FD_TID",obj);
                    break;
                case 6:
                    mapPD.put("FD_SOURSIGN",obj);
                    break;
                case 7:
                    mapPD.put("FD_ROUTE",obj);
                    break;
                case 8:
                    mapPD.put("FD_NUM",obj);
                    break;
            }
        }
    
    }

    祝愿大家越努力越幸运!!!!!!!!!2019/4/12

     

     

     

    展开全文
  • Java实现Excel数据表,MySQL数据库,具体步骤如下… 实现批量导入时需要导入的pom.xml文件 <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> &...

    Java实现Excel批量导入数据库

    前言:项目开发中最容易碰到的需求即将Excel数据批量上传到数据库中存储 -> Java实现,Excel数据表,MySQL数据库,具体步骤如下…
    

    实现批量导入时需要导入的pom.xml文件

    <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>
    

    一.前端页面传入Excel表格

    1.新建Excel表格在这里插入图片描述
    2.前端html实现(这里使用的是layui前端框架实现的前端页面)

    (1).HTML标签

    <!-- 上传按钮,拖拽上传--> 
           <div class="layui-col-lg3">
                  <div class="layui-upload-drag layui-input-block" id="uploadExcel"
                        style="display: block;margin-left: 0px;">
                       <i class="layui-icon"></i>
                       <p>点击批量上传,或将文件拖拽到此</p>
                   </div>
            </div>
    

    (2).使用layui中jQuery进行对传入模板的处理,并限制传入的文件后缀名格式

    //1.拖拽、点击自动上传  选完文件后不自动上传
            upload.render({
                elem: '#uploadExcel'
                ,url: "upload/uploadExcelSendedNumUp"
                ,multiple: true
                ,accept: 'file' //文件  后台:@RequestParam("file")
                ,acceptMime:'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel,application/vnd.ms-excel.sheet.macroEnabled.12'
                //文件窗口默认显示 xlsx|xls|xlsm 的文件
                ,exts:'xlsx|xls|xlsm' //限制后缀名
                ,progress: function(n){
                    var percent = n + '%' //获取进度百分比
                    element.progress('demo', percent); //可配合 layui 进度条元素使用
                }
                ,done: function(res){
                    var errorArray = res.msg.split(";");
                    var error=res.msg;
                    var prefix = "<ul>"
                    var suffix = "</ul>"
                    var errorCon = "";
                    var errorRemind = "<b>上传失败:</b>"
                    for(var i = 0;i<errorArray.length-1;i++){
                        errorCon += '<li>'+(i+1)+'、'+errorArray[i]+'</li>';
                    }
                    var errorReal = errorRemind + prefix + errorCon + suffix;
                    if(!errorCon){
                        if( error !== null || error !== undefined || error !== ''){
                            errorReal = "<b>"+error+"</b>";
                            table.reload('dcSendedNum');
                        }else{console.log(error);
                            errorReal = "<b>上传成功</b>";
                            table.reload('dcSendedNum');//重新渲染,局部页面刷新
                        }
                    }
                    layer.open({
                         id:"openErrorMsg"
                        ,btnAlign:'c'
                        ,title:'提示信息'
                        ,content:errorReal
                    });
                    //調用此方法,使数据回显渲染
                    table.reload('dcSendedNumFileInfo');
    
            },error:function (res) {
                layer.msg("上传异常,请检查上传的Excel表格");
            }
        });
    

    二.后台处理(以下为主要的实现代码)

    建议:应将下面的某些方法进行分割开来

    1.Controller层实现

    @RequestMapping(value = "/uploadExcelSendedNumUp")
    @ResponseBody
    public WebMapPageResult uploadExcelFile(@RequestParam("file") MultipartFile mulFile) {
       //批量插入数据
        List<SendedNumber> sendedNumbers = localSaveObj.saveExcelFile(mulFile, new SendedNumber());
     }
    

    在这里插入图片描述

    2.localSaveObj处理类中对Excel表格的处理

    public <T> List<T> saveExcelFile(MultipartFile mulFile, T t) {
            if (!mulFile.isEmpty()) {
                try {
                    String filename = mulFile.getOriginalFilename();
                    String suffix = filename.substring(filename.lastIndexOf("."));// 后缀名
                    String uuid = UUID.randomUUID().toString();
                    String uuidName = uuid + suffix;
                    String path = uploadConfig.getPath()+uuidName;
                    String saveType = getSaveFileType(t);
                    saveFileInfo(filename,uuidName,path,saveType);//文件信息插入到数据库
                    File file = new File(path);
                    file.mkdirs();
                    File dest = new File(path);
    
                /*取出Excel表中的每一个单元格的值,存放在list集合中*/
                InputStream in = mulFile.getInputStream();
                //lastIndexOf() 方法可返回一个指定的字符串值最后出现的位置,如果指定第二个参数 start,则在一个字符串中的指定位置从后向前搜索。”
                String type = t.toString().substring(t.toString().lastIndexOf(".")+1, t.toString().lastIndexOf("#"));
                List<List<Object>> bankListByExcel = importExcelHelperObj.getBankListByExcel(in, filename,type);
                /*保存上传的Excel文件到本地目录*/
                mulFile.transferTo(dest);
    
                String errors = ImportExcelHelper.getErrors();
                List<T> list = null;
                if(errors.isEmpty()){
                    list = shiftType.listDisToObj(bankListByExcel, t, filename);
                }
                return list;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    

    在这里插入图片描述
    3.importExcelHelperObj类中的处理 对相关的字段进行校验

    /**
         * Excel导入
         */
        public List<List<Object>> getBankListByExcel(InputStream in, String fileName, String type) throws Exception {
            List<List<Object>> list = null;
            // 创建Excel工作薄
            Workbook work = getWorkbook(in, fileName); //获取work对象
            if (null == work) {
                throw new Exception("创建Excel工作薄为空!");
            }
            Sheet sheet = null;
            Row row = null;
            Cell cell = null;
            list = new ArrayList<List<Object>>();
    
        // 遍历Excel中所有的sheet  只遍历第一张表
        for (int i = 0; i < 1; i++) {  //没有分表分list,多个表的数据放在一个list集合下。  work.getNumberOfSheets()
       // for (int i = 0; i < work.getNumberOfSheets(); i++) {  //没有分表分list,多个表的数据放在一个list集合下。  work.getNumberOfSheets()
    
            sheet = work.getSheetAt(i);//获取工作薄的第i个sheet页
            if (sheet == null) {
                continue;
            }
    
            //真正的行数,去掉没有数值,但有样式的行。
            int realRowNum = getRealRowNum(sheet); //获取当前sheet总共有多少真实有效的行
    
            // 遍历当前sheet中的所有行
            // 包涵头部,所以要小于等于最后一列数,这里也可以在初始值加上头部行数,以便跳过头部
            for (int j = sheet.getFirstRowNum(); j <= realRowNum; j++) { //j为实际行数
    
                row = sheet.getRow(j);//返回当前j的行数
                if (row == null || j==0) {//若当前行是第一行则跳过,即使xmls中标题部分
                    continue;
                }
    
                // 遍历所有的列
                List<Object> li = new ArrayList<Object>();
    
                //校验3:列数与模板列数不一致
                Row firstRow = sheet.getRow(0); //获取到当前0行,这里是获取第一行标题部分。
                Cell firstCell= firstRow.getCell(0); //获取0行第一列的数值
                if(firstCell==null){
                    continue;
                }
                String firstCellVal = getCellValue(firstCell,type,0).toString().trim();//对0行第0列的表格中数值进行格式化,获取单元格中数据
                String errCellNumMsg = DataValidation.verifyCellsNum(firstRow.getLastCellNum(),firstCellVal,type);//校验Excel表格有效单元格数量
                if (!errCellNumMsg.equals("")){
                    errors += errCellNumMsg;
                    break;
                }
    
                String isCharge = "";
                for (int y = firstRow.getFirstCellNum(); y < firstRow.getLastCellNum(); y++) { //得到一行记录,y是每一行记录中的第几个单元格(从零开始计数)
                    cell = row.getCell(y);//获取第y个单元格的值
                    String cellValue = getCellValue(cell,type,y).toString().trim();//对表格中数值进行格式化
    
                    //校验4.1:为空校验,必填单元格(字段)校验
                    if (type.equals("SendedNumber") || type.equals("SpamMessageFeeReceipt")) {
    
                        if (type.equals("SendedNumber")){
                            if (y==2 && "".equals(cellValue) && cellValue.trim().length()==0){
                                cellValue="0";
                            }else {
                                String errorCellEmp = DataValidation.verifyIsNullCell(j, y, cellValue);
                                verifyErrorMsg(errorCellEmp);
                                if(!errorCellEmp.isEmpty()){
                                    continue;
                                }
                            }
                        }
    
    
                        //对distribute导入模板进行非空验证
                    }else if(y<16) {//对16个单元格进行非空校验(即必填校验)
                        if (!type.equals("DistributeAccess")){
                            if (y == 5) { //这样写是:当y= 5时,对y=5进行特殊处理,y=5表示表格信息是 sP代码,Sp代码不能为空
                                String errorCellEmp = DataValidation.verifyIsNullCell(j, y, cellValue);//单元格为"",也是必填校验
                                if (!errorCellEmp.isEmpty()) {//当error不为空,添加错误补充信息
                                    verifyErrorMsg(errorCellEmp);
                                    break;
                                }
                                /*else {  //error 为空,表示此次验证没有出现问题
                                    verifyErrorMsg(errorCellEmp);
                                    if(!errorCellEmp.isEmpty()){
                                        continue;
                                    }
                                }*/
    
    
                            } else {
    
                                String errorCellEmp = DataValidation.verifyIsNullCell(j, y, cellValue);
                                verifyErrorMsg(errorCellEmp);
                                if (!errorCellEmp.isEmpty()) {
                                    continue;
                                }
    
                            }
                        }
                    }
                    //5.0 校验:校验码号分配表中同一个partyCode(SpCode),是否得到同一批数据,同一个partyCode的一行数据是相同的
                    if(type.equals("Distribute")){
    
                        if(y==5){//y= 5:时的单元格的值就是SP代码的值
                            String errorCellEmp = DataValidation.verifyIsNullCell(j, y, cellValue);//非空校验
                            if (errorCellEmp.isEmpty()){
                                dataValidationObj.setMapDataDist(cellValue); //将Distribute表中数据放到Map中
                            }
    
                            String  errorCellMdmCode = dataValidationObj.verifyIsNotFoundMdmCode(j, y, cellValue);
                            verifyErrorMsg(errorCellMdmCode);
    
                        }else if(y>5 &&y <16){     //同一个sp代码、业务类型可以不同、备注可以不同,其他的需要相同。
                                                   //对必填项进行校验,分配表前16个全为必填项
                            String errorDifferData = dataValidationObj.verifySpcodeOneRowDifferent(j,y, cellValue);
                            verifyErrorMsg(errorDifferData);
                        }
                    }
    
                    //校验5.1:码号唯一校验
                    if (y == 0 && !type.equals("DistributeAccess")) {
                        String errorUnique = dataValidationObj.verifyCodeUnique(j, y, cellValue, type);
                        verifyErrorMsg(errorUnique);
    
                    }
    
                    //校验6:垃圾短信费用单记录唯一性 与 使用量记录的唯一性
                   if(y < 5 && type.equals("SpamMessageFeeReceipt") || type.equals("SendedNumber")){
                       String errorMsgUnique = dataValidationObj.verifySpamMsgUnique(j, y, cellValue,type);
                       verifyErrorMsg(errorMsgUnique);
                   }
    
                    //对DistributeAccess信息导入模板   必填项进行非空验证  码号开通接入信息上报
                    if(type.equals("DistributeAccess")){
                        //码号开通接入信息上报   非空效验
                        if (y<11 && y!=7 ){
                            String errorCellEmp = DataValidation.verifyIsNullCell(j, y, cellValue);//非空校验
                            verifyErrorMsg(errorCellEmp);
                            //将结果直接存到verifyErrorMsg()中  若都有值则不会中断程序的执行,若errorCellEmp不会'',则程序会中断,上传失败
                            if (!errorCellEmp.isEmpty()){
                                continue;
                            }
                        }
    
                        if (y==0){
                            String code = getCellValue(row.getCell(0),type,0).toString().trim();
                            boolean b = ValueByKey.IsDigit(code);
                            String errorCellEmp="";
                            if (!b){
                                String coordinate = DataValidation.getCoordinate(j, y);
                                String errorDescribe = ErrorEnumMessage.ITCANONLYBENUMBERS.getErrorDescribe();
                                errorCellEmp = coordinate+errorDescribe;
                                System.out.println("errorCellEmp = " + errorCellEmp);
                            }
                            verifyErrorMsg(errorCellEmp);
                            if (!errorCellEmp.isEmpty()){
                                continue;
                            }
                        }
    
                        //处理条件必填项
                        if (y==12 && "拆机".equals(getCellValue(row.getCell(4),type,4).toString().trim())){
                            //对条件必填项进行 处理 先验证必填项 然后再去验证与之关联的项
                            if (StringUtils.isBlank(cellValue)){
                                String coordinate = DataValidation.getCoordinate(j,y);
                                String errorCellEmp = coordinate + ErrorEnumMessage.CONDITIONISREQUIRED.getErrorDescribe();
                                verifyErrorMsg(errorCellEmp);
                                if (!errorCellEmp.isEmpty()){
                                    continue;
                                }
                            }
                        }
                        
                        //处理条件必填项
                        if ((y==7 || y==17) && !"自营".equals(getCellValue(row.getCell(6),type,6).toString().trim())){
                            String errorCellEmp = DataValidation.verifyIsNullCell(j, y, cellValue);//非空校验
                            verifyErrorMsg(errorCellEmp);
                            //将结果直接存到verifyErrorMsg()中  若都有值则不会中断程序的执行,若errorCellEmp不会'',则程序会中断,上传失败
                            if (!errorCellEmp.isEmpty()){
                                continue;
                            }
                        }
    
    
                    }
    
                    li.add(cellValue);
                }
                dataValidationObj.setEmptyMemberVar("");
                list.add(li);//装载一行的数据到list中
            }
        }
    
        dataValidationObj.setEmptyMapVar();
        return list;
    }
    

    4.DataValidation中的处理,对Excel表格中有效单元格列数的处理

     /**
         *  校验5:校验Excel表格有效单元格数量   DistributeAccess为实体类对象
         */
        public static String verifyCellsNum(int end,String firstCellVal,String type){
            String error = "";
            String str = firstCellVal.substring(0,2);
            if(type.equals("DistributeAccess") && end==28){
                return error;
            }if(type.equals("Distribute") && end==38){
                return error;
            }else if(type.equals("SendedNumber") && end==4 && str.equals("码号")){
                return error;
            }else if(type.equals("SpamMessageFeeReceipt") && end==5 && str.equals("SP")){
                return error;
            }
            return ErrorEnumMessage.COMMONERRORS.getErrorDescribe();
        }
    
      /**
         * 校验4:单元格为"",也是必填校验
         */
        public static String verifyIsNullCell(int x,int y,String cellValue){
            String error = "";
            if(StringUtils.isBlank(cellValue)){
                String coordinate = DataValidation.getCoordinate(x,y);
                error = coordinate + ErrorEnumMessage.CELLEMPTY.getErrorDescribe();
            }
            return error;
        }
    

    至此,以上为后台对Excel表格中,每一行和每一列数据进行数据处理

    因此从Excel表格中获取每行的数据信息,生成list对象集合
    在这里插入图片描述

    根据获得到的对象集合,便可以实现数据批量导入数据库了

    展开全文
  • 如题,ssm框架 table 里面的数据需要实时刷新 数据大概两三秒会变化一次, 有没有比较高效的方法去实现,除了ajax每隔3s调用后台还有其他更优的方法吗
  • 背景:项目中用到邮件发送功能,需要将数据导入excel表格然后发送给供应商,第一次做的时候是直接创建了一个excel,领导说比较丑,就找甲方要了个模板,所以本篇文章除了介绍直接生成excel导入数据的功能以外,也...
  • Java 创建、刷新Excel透视表/设置透视表行折叠、展开透视表是依据已有数据源来创建的交互式表格,我们可在excel中创建透视表,也可编辑已有透视表。本文以创建透视表、刷新透视表以及设置透视表的行展开或折叠为例,...
  • JAVA实现数据库数据导入/导出到Excel(POI) 准备工作: 1. 导入 POI 包:POI下载地址 http://mirrors.tuna.tsinghua.edu.cn/apache/poi/release/src/ (重要) 如下 2 .导入Java界面美化包 Beauty...
  • 使用了POI来对Excel进行操作 package emmm;//可删掉 import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.Set; import org.apache.poi.hssf.usermodel....
  • java实现Excel表格导出

    2020-05-26 15:20:46
    Excel表格导出工具类 import org.apache.poi.hssf.usermodel.*; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.http.HttpStatus; ...
  • HSSF是POI工程对Excel 97(-2007)文件操作的纯Java实现XSSF是POI工程对Excel 2007 OOXML (.xlsx)文件操作的纯Java实现 SXSSF通过一个滑动窗口来限制访问Row的数量从而达到低内存占用的目录,XSSF可以访问所有行。旧...
  • java解析Excel表格数据

    万次阅读 2018-09-18 21:03:05
    我们使用的包为jxl.jar,可以实现Excel文件中读取指定的行和列的值。 java代码、Excel表格和jar包已经提交到Git上:https://github.com/buder-cp/base_component_learn/tree/master/get_excel_values Excel表格...
  • java实现Excel导入功能(前端+后台)

    千次阅读 2020-07-29 11:57:21
    java:导入功能的实现(前端+后台)
  • 写东西,遇到需要导出所显示的表格内容到excel,研究了一阵子,完成。记录一下! 项目使用的是spring+springMVC+ibatis框架。...jsp页面代码实现: <input type="button" class="newBtn" onclick="export...
  • 基于java实现下载excel

    2020-03-19 17:45:53
    excel生成并下载 注意事项 ajax请求的数据类型不能以二进制流形式返回,所以建议以 表单形式提交,附带参数可以以隐藏域传值或者url后拼接。 使用window.location.href。 在前端拿到二进制流在处理等等。 前台代码...
  • 使用导入的excel模板,模板中已有对应的公式,即改变单元格 A 的值,可以影响单元格 B【=A*10】 的值。 但是现在,直接操作写入数据到 A 单元格,发现 B 并没有对应改变。 原代码: Workbook workbook = null; ...
  • // 刷新 bwSuccess.flush(); } else { bwError.write(s); bwError.write(" "); bwError.flush(); bwError.newLine(); bwError.flush(); } } System.out.println("写入结束"); } catch (BiffException e)...
  • 导入:(poi-3.7的版本不支持2007版及以上的excel文件,所以这里使用3.9版本) poi-3.9-20121203.jar poi-ooxml-3.9.jar poi-ooxml-3.9-sources.jar poi-ooxml-schemas-3.9-20121203.jar xmlbeans-2.3.0.jar(如果.....
  • java实现读写excel表格

    2016-05-03 15:54:44
    需要jar包 poi-3.15-beta1.jar poi-excelant-3.15-beta1.jar poi-ooxml-3.15-beta1.jar curvesapi-1.03.jar xmlbeans-2.6.0.jar poi-ooxml-schemas-3.15-beta1....创建一个excel public static void
  • 如何刷新Excel数据透视表 (How to Refresh an Excel Pivot Table) If you change any of the information in a pivot table's source data, the pivot table won't immediately show your latest changes....
  • 公司要求增加一个上传excel,并读取其中数据批量写入数据库的功能,测试完遂整理一下方便以后使用,同时也给大家实现类似功能一个参考,框架使用ssm,导入excel使用的第三方依赖Poi,结合自身业务修改即可。...
  • java导入excel

    千次阅读 2018-01-09 15:07:11
    java导入excel
  • 在word2003的时代,word中图表的实现,还是通过MSChart(如图1)来实现...但MSChart的图表对象确实在样式和美观上远不及word2007之后的excel图表。如图2,MSChart图表的样式。 figure 1. 添加MSChart对象 fig...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,983
精华内容 3,193
关键字:

java实现excel数据刷新

java 订阅