bootstaptable動態合並單元格和jxls動態合並單元格


項目中有個需求,根據計划單號進行對應的單元格合並,還有對應的導出功能也是需要,前台使用的是bootstrap插件,還好bootstrap有自己的合並功能。

下面看下具體的實現

一、前台bootstap實現動態合並單元格

1.在onLoadSuccess : function(data) {

}方法中進行實現合並單元格,注意,一定是其他操作完成之后再合並單元格,我的是有合計功能,剛開始是先合並再實現合計,結果合計功能一直出不來,很納悶,試了一下更改順序,結果就出來了,把整個的代碼都貼一下吧

function loadTable(flag) {
        if(flag=="1")
            {
            searchStr = $(".search__inp").val().trim();
            }
        var pageNumber = 1;
        $("#mainTable").bootstrapTable("destroy");
        var options = {
            pagination : true
            //, height: 400
            ,
            showFooter : false,
            paginationLoop : false
            //,sortable: true
            ,
            cache : false,
            pageNumber : pageNumber,
            pageSize : 10,
            pageList : [ 10],//[ 10, 20, 50 ],
            method : "get",
            contentType : 'application/x-www-form-urlencoded; charset=UTF-8',
            url : basePath + "student/productionReport/getReportList",
            queryParamsType : "",
            sidePagination : "server",
            queryParams : queryParamsMain,
            columns : [[
                    {
                        field : "id",
                        title : "序號",
                        align : "center",
                        valign : "middle",
                        colspan: 1,
                        rowspan: 2,
                        formatter : function(value, row, index) {
                        
                            //獲取每頁顯示的數量
                            var pageSize = $('#mainTable').bootstrapTable(
                                    'getOptions').pageSize;
                            //獲取當前是第幾頁  
                            var pageNumber = $('#mainTable').bootstrapTable(
                                    'getOptions').pageNumber;
                            //返回序號,注意index是從0開始的,所以要加上1

                            if (value == "total") {
                                return "合計";
                            } else {
                                return pageSize * (pageNumber - 1) + index + 1;
                            }
                        },
                        //width : 40
                    },
                    
                    
                    {
                        field : "planType",
                        title : "生產類型",
                        align : "center",
                        valign : "middle",
                        colspan: 1,
                        rowspan: 2,
                        formatter : function(value, row, index) {
                            var str="";
                            if(value==1)
                                {
                                str="內部生產";
                                }
                            else if(value==2)
                                {
                                str="委托加工";
                                }
                            return str;
                        },
                        //width : 68
                    },

                    {
                        field : "planCode",
                        title : "生產計划單號",
                        align : "center",
                        valign : "middle",
                        colspan: 1,
                        rowspan: 2,
                        formatter : function(value, row, index) {
                            return value;
                        },
                        //width : 58
                    },

                    {
                        //field : "code",
                        title : "生產信息",
                        align : "center",
                        valign : "middle",
                        colspan: 4,
                        rowspan: 1
                        //width : 145
                    },
                    {
                        //field : "code",
                        title : "用料明細",
                        align : "center",
                        valign : "middle",
                        colspan: 4,
                        rowspan: 1
                        //width : 145
                    },
                    {
                        field : "roundNo",
                        title : "輪次",
                        align : "center",
                        valign : "middle",
                        colspan: 1,
                        rowspan: 2,
                        //sortable: true,
                        formatter : function(value, row, index) {
                            if (value != "") {
                                return "第" + value + "輪";
                            } else {
                                return "";
                            }
 
                        },

                        //width : 46
                    } 
                    ],
                    [{
                        field : "productName",
                        title : "產品名稱",
                        align : "center",
                        valign : "middle",
                        formatter : function(value, row, index) {
                            return value;
                        },
                        //width : 67
                    },
                    {
                        field : "productCode",
                        title : "型料號",
                        align : "center",
                        valign : "middle",
                        formatter : function(value, row, index) {
                            return value;
                        },
                        //width : 73
                    },
                    {
                        field : "actualQuantity",
                        title : "實際生產數量",
                        align : "center",
                        valign : "middle",
                        formatter : function(value, row, index) {
                            return value;
                        },
                        //width : 28
                    },

                    {
                        field : "qualificationRate",
                        title : "合格率(%)",
                        align : "center",
                        valign : "middle",
                        formatter : function(value, row, index) {
                            return value;
                        },
                        //width : 28
                    },
                    {
                        field : "bomType",
                        title : "產品類型",
                        align : "center",
                        valign : "middle",
                        formatter : function(value, row, index) {
                            switch(value)
                            {
                            case 1:value="產成品";break;
                            case 2:value="半成品";break;
                            case 3:value="原材料";break;
                            }
                            return value;
                        },
                        //width : 53
                    },
                    {
                        field : "bomProductName",
                        title : "產品名稱",
                        align : "center",
                        valign : "middle",
                        formatter : function(value, row, index) {
                            return value;
                        },
                        //width : 86
                    },
                    {
                        field : "bomProductCode",
                        title : "型料號",
                        align : "center",
                        valign : "middle",
                        formatter : function(value, row, index) {
                            return value;
                        },
                        //width : 190
                    },
                    {
                        field : "bomQuantity",
                        title : "生產實際用量",
                        align : "center",
                        valign : "middle",
                        formatter : function(value, row, index) {
                            return value;
                        },
                        //width : 65
                    }
                ]],
            onLoadSuccess : function(data) {
                

                
                var sum_1 = 0;
                var sum_2 = 0;
                var planCode="";
                for ( var o in data.rows) {
                    if (!isNaN(o)) {
                        if(data.rows[o].planCode!=planCode)
                            {
                            if(!isNaN(data.rows[o].actualQuantity))
                            {
                            sum_1 = parseFloat(sum_1)+ parseFloat(data.rows[o].actualQuantity);
                            }
                            }
                        
                        sum_2 = parseFloat(sum_2)+ parseFloat(data.rows[o].bomQuantity);
                        planCode=data.rows[o].planCode;
                    }

                }
                if(data.rows.length>0)
                    {
                    var rows = [];
                    rows.push({
                        id : "total",
                        planType : "",
                        planCode : "",
                        productName : "",
                        productCode : "",
                        actualQuantity : sum_1,
                        qualificationRate : "",
                        bomType : "",
                        bomProductName : "",
                        bomProductCode : "",
                        bomQuantity : sum_2,
                        roundNo : ""
                    });
                    $('#mainTable').bootstrapTable('append', rows);
                    }
                    mergeCells(data.rows,"planCode", "planCode", 1, $('#mainTable'));
                    mergeCells(data.rows,"planCode", "actualQuantity", 1, $('#mainTable'));
                    mergeCells(data.rows,"planCode", "productName", 1, $('#mainTable'));
                    mergeCells(data.rows,"planCode", "productCode", 1, $('#mainTable'));
                    mergeCells(data.rows,"planCode", "qualificationRate", 1, $('#mainTable'));

            },
            responseHandler : function(data) {
                return {
                    total : data.totalCount,
                    rows : data.result,
                };
            },
            onPageChange : function(number, size) {
                pageNumber = number;
            },
            onLoadError : function(textStatus, XMLHttpRequest) {
            }
        };
        $("#mainTable").bootstrapTable(options);
    }
    
View Code

2.具體的進行單元格合並,mergeCells可以實現單元格合並,此功能還是非常簡單的

 1 /**
 2      * 合並單元格
 3      * @param data  原始數據(在服務端完成排序)
 4      * @param fieldName 合並屬性名稱
 5      * @param colspan   合並列
 6      * @param target    目標表格對象
 7      */
 8     function mergeCells(data,exhibitionName,fieldName,colspan,target){
 9         //聲明一個map計算相同屬性值在data對象出現的次數和
10         var sortMap = {};
11         for(var i = 0 ; i < data.length ; i++){
12             for(var prop in data[i]){
13                 if(prop == exhibitionName){
14                     var key = data[i][prop];
15                     if(sortMap.hasOwnProperty(key)){
16                         sortMap[key] = sortMap[key] * 1 + 1;
17                     } else {
18                         sortMap[key] = 1;
19                     }
20                     break;
21                 } 
22             }
23         }
24         
25         var index = 0;
26         for(var prop in sortMap){
27             var count = sortMap[prop] * 1;
28             $("#mainTable").bootstrapTable('mergeCells',{index:index, field:fieldName, colspan: colspan, rowspan: count});   
29             index += count;
30         }
31     }
View Code

二、導出excle中實現動態單元格合並

1、在pom.xml中引入jar包

 1 <!-- exel導出依賴 -->
 2         <dependency>
 3             <groupId>net.sf.jxls</groupId>
 4             <artifactId>jxls-reader</artifactId>
 5             <version>0.9.9</version>
 6         </dependency>
 7         <dependency>
 8             <groupId>net.sf.jxls</groupId>
 9             <artifactId>jxls-core</artifactId>
10             <version>0.9.9</version>
11         </dependency>
12         <dependency>
13             <groupId>jexcelapi</groupId>
14             <artifactId>jxl</artifactId>
15             <version>2.4.2</version>
16         </dependency>
View Code

2、業務功能實現,

3、導出方法(合並單元格),含有非合並的代碼

List<Merge> ml = getMerge(list, "getPlanCode");這個是合並的關鍵字

// 起始行號,終止行號, 起始列號,終止列號
sheet.addMergedRegion(new CellRangeAddress(m.getFromRow() + 3, m.getToRow() +3, 3, 3));這個進行具體的合並,從網上找的帖子,用的反射降低耦合度,其實可以不用反射,直接用對應功能實現

  1 package com.gta.scm.component.common.utils;
  2 
  3 /**
  4  * 
  5  */
  6 
  7 
  8 import java.io.BufferedInputStream;
  9 import java.io.ByteArrayOutputStream;
 10 import java.io.FileInputStream;
 11 import java.io.FileNotFoundException;
 12 import java.io.IOException;
 13 import java.io.InputStream;
 14 import java.io.OutputStream;
 15 import java.io.UnsupportedEncodingException;
 16 import java.lang.reflect.InvocationTargetException;
 17 import java.util.ArrayList;
 18 import java.util.HashMap;
 19 import java.util.List;
 20 import java.util.Map;
 21 import javax.servlet.ServletOutputStream;
 22 import javax.servlet.http.HttpServletRequest;
 23 import javax.servlet.http.HttpServletResponse;
 24 
 25 import net.sf.jxls.exception.ParsePropertyException;
 26 import net.sf.jxls.transformer.XLSTransformer;
 27 import org.apache.commons.codec.binary.Base64;
 28 import org.apache.poi.hssf.usermodel.HSSFSheet;
 29 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 30 import org.apache.poi.ss.util.CellRangeAddress;
 31 import org.slf4j.Logger;
 32 import org.slf4j.LoggerFactory;
 33 
 34 import com.fasterxml.jackson.databind.exc.InvalidFormatException;
 35 import com.gta.scm.common.entity.Merge;
 36 
 37 
 38 /**
 39  * @author jingshu.deng
 40  *
 41  */
 42 public class FileUtils {
 43     private static Logger logger = LoggerFactory.getLogger(FileUtils.class);
 44 
 45     /**
 46      * @param fileName
 47      * @return
 48      */
 49     public static String getFileExtension(String fileName) {
 50         if (StringUtils.isEmpty(fileName)) {
 51             return StringUtils.EMPTY;
 52         }
 53 
 54         return StringUtils.substringAfter(fileName, ".");
 55     }
 56 
 57     /**
 58      * 
 59      * 解決文件下載時文件名的中文亂碼及Firefox下空格被截斷的問題
 60      * 
 61      * @param request
 62      * @param fileName
 63      * @return
 64      */
 65     public static String decodeFileName(HttpServletRequest request,    String fileName) {
 66         String agent = (String) request.getHeader(CharEncodingCons.USER_AGENT);
 67         try {
 68             // check whether Firefox according to USER-AGENT
 69             // 增加條件 agent.indexOf("Trident") == -1 針對IE10以上
 70             if (agent != null && agent.indexOf(CharEncodingCons.BROWSER_IE) == -1 && agent.indexOf("Trident") == -1) {
 71                 byte[] bytes = Base64.encodeBase64(fileName.getBytes(CharEncodingCons.HTTP_CHARSET));
 72                 fileName = new String(bytes, CharEncodingCons.HTTP_CHARSET);
 73                 fileName = "=?" + CharEncodingCons.HTTP_CHARSET + "?B?" + fileName + "?=";
 74             } 
 75             else {
 76                 byte[] bytes = fileName.getBytes(CharEncodingCons.DOWNLOAD_CHARSET);
 77                 fileName = new String(bytes, CharEncodingCons.WEB_CHARSET);
 78             }
 79         } 
 80         catch (UnsupportedEncodingException e) {
 81             logger.error("UnsupportedEncodingException occurs while flushing file", e);
 82         }
 83         return fileName;
 84     }
 85     
 86     /**
 87      * 導出Excel文件,按模板方式
 88      * @param response
 89      * @param templateName 模板名稱及完全路徑
 90      * @param map 
 91      * @param fileName 要導出的文件名
 92      */
 93     public static void exportXlsFile(HttpServletRequest request,HttpServletResponse response,String templateName,Map<String,Object> map,String fileName){
 94         try
 95         {
 96             XLSTransformer transformer=new XLSTransformer();
 97             //XLSTransformer transformer = new XLSTransformer();    
 98             InputStream in = new BufferedInputStream(new FileInputStream(templateName),25000);
 99             HSSFWorkbook workbook = transformer.transformXLS(in, map);
100             //write to buffer
101             ByteArrayOutputStream buf = new ByteArrayOutputStream(40000);
102             workbook.write(buf);
103             // write to response
104             in.close();
105             response.setContentType("application/vnd.ms-excel");
106             response.setHeader("Content-disposition", "attachment; filename=" + decodeFileName(request,fileName)); 
107             ServletOutputStream out = response.getOutputStream();
108             out.write(buf.toByteArray());
109             out.flush();
110             out.close();
111         }catch (IOException e){
112             e.printStackTrace();
113         }
114     }
115     
116     // 先用String
117         public static <T> Object useMethod(T t, String sx) throws IllegalAccessException, IllegalArgumentException,
118                 InvocationTargetException, NoSuchMethodException, SecurityException {
119             // 一般傳入get方法
120             return (Object) t.getClass().getMethod(sx, null).invoke(t, null);
121 
122         }
123 
124         public static <T> List<Merge> getMerge(List<T> list, String sx) throws IllegalAccessException,
125                 IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
126             // 可以傳入 想合並的屬性值 傳入一個字符串 用反射找到相應的get方法 指定調用此方法。。這里先寫死
127             List<Merge> ml = new ArrayList<Merge>();
128             for (int i = 0; i < list.size() - 1; i++) {
129                 if (useMethod(list.get(i), sx).equals(useMethod(list.get(i + 1), sx))) {
130                     Object property = useMethod(list.get(i), sx);
131                     logger.debug("property"+property);
132                     Merge merge = new Merge();
133                     int fromRow = i, toRow = i + 1;
134                     if (i + 2 < list.size()) {
135                         for (int j = i + 2; j < list.size(); j++) {
136                             if (useMethod(list.get(j), sx).equals(property) ) {
137                                 toRow++;
138                             } else {
139                                 i = j - 1;
140                                 break;
141                             }
142                         }
143                     }
144                     merge.setFromRow(fromRow);
145                     merge.setToRow(toRow);
146                     ml.add(merge);
147                 }
148             }
149             return ml;
150         }
151         
152         public static <T> void exportXlsFileMerge(HttpServletRequest request,HttpServletResponse response,String templateName,List<T> list,Map<String,Object> map,String fileName)
153                 throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException,
154                 SecurityException, FileNotFoundException, ParsePropertyException, InvalidFormatException {
155             String templateFile = fileName;
156             Map<String, Object> beans = new HashMap<String, Object>();
157             InputStream in = new FileInputStream(templateName);
158     
159             XLSTransformer transformer = new XLSTransformer();
160 
161             HSSFWorkbook workBook = (HSSFWorkbook) transformer.transformXLS(in, map); // 傳入模板的輸入流和map
162             // 開始進行合並單元格
163             HSSFSheet sheet = workBook.getSheetAt(0);// 1 1
164             List<Merge> ml = getMerge(list, "getPlanCode");
165             for (Merge m : ml) {
166                 // 起始行號,終止行號, 起始列號,終止列號
167                 sheet.addMergedRegion(new CellRangeAddress(m.getFromRow() + 3, m.getToRow() +3, 3, 3));
168                 sheet.addMergedRegion(new CellRangeAddress(m.getFromRow() + 3, m.getToRow() +3, 4, 4));
169                 sheet.addMergedRegion(new CellRangeAddress(m.getFromRow() + 3, m.getToRow() +3, 5, 5));
170                 sheet.addMergedRegion(new CellRangeAddress(m.getFromRow() + 3, m.getToRow() +3, 6, 6));
171                 sheet.addMergedRegion(new CellRangeAddress(m.getFromRow() + 3, m.getToRow() +3, 2, 2));
172             }
173             try {
174                 
175                 ByteArrayOutputStream buf = new ByteArrayOutputStream(40000);
176                 workBook.write(buf);
177                 // write to response
178                 in.close();
179                 response.setContentType("application/vnd.ms-excel");
180                 response.setHeader("Content-disposition", "attachment; filename=" + decodeFileName(request,fileName)); 
181                 ServletOutputStream out = response.getOutputStream();
182                 out.write(buf.toByteArray());
183                 out.flush();
184                 out.close();
185                 
186                 
187             } catch (IOException ie) {
188                 ie.printStackTrace();
189             } catch (ParsePropertyException e) {
190                 // TODO Auto-generated catch block
191                 e.printStackTrace();
192             }
193 
194         }
195 
196 }
View Code

 

添加merge類進行記錄行號
 1 public class Merge {
 2     private int fromRow;
 3     private int toRow;
 4     private int fromIndex;
 5     private int toIndex;
 6     public int getFromRow() {
 7         return fromRow;
 8     }
 9     public void setFromRow(int fromRow) {
10         this.fromRow = fromRow;
11     }
12     public int getToRow() {
13         return toRow;
14     }
15     public void setToRow(int toRow) {
16         this.toRow = toRow;
17     }
18     public int getFromIndex() {
19         return fromIndex;
20     }
21     public void setFromIndex(int fromIndex) {
22         this.fromIndex = fromIndex;
23     }
24     public int getToIndex() {
25         return toIndex;
26     }
27     public void setToIndex(int toIndex) {
28         this.toIndex = toIndex;
29     }
30     
31 }
View Code

調用的地方需要特別注意的地方

String templateFileName = request.getServletContext().getRealPath("/")
+ "/reportTemplate//ProductionReportTemplate.xls";
String destFileName = "生產產品明細匯總表.xls";

map.put("productionReportList", productionReport);

4.exlce模板

5.導出結果

 

 哈,這樣前后台都進行了實現了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM