flex AdvanceDatagrid 通用导出到excel

原创
2012/11/23 23:00
阅读数 5.8K

先说说思路:flex端把表头(包含:dataField、headText、children)组织成json格式传到后台。后台提供List<Map<String, Object>>格式的数据源(Map的key值和dataField一一对应)调用通用导出模块。

下面上代码:

前台提供的json:

[{"children":"","dataField":"index","headerText":"序号"},
{"children":[{"children":"","dataField":"name","headerText":"昵称"},
{"children":"","dataField":"userName","headerText":"用户名"}],"dataField":"","headerText":"用户信息"},
{"children":"","dataField":"requestUri","headerText":"URI"},
{"children":"","dataField":"ip","headerText":"IP"},
{"children":"","dataField":"accessDate","headerText":"日期"}]

通过调用servlet传到后台

package com.sddl.action;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONArray;
import org.springframework.util.StringUtils;

import com.sddl.bean.ExpSimpleAdvanceDataGridBean;
import com.sddl.util.Tool;

public class ExpSimpleAdvanceDataGridAction extends HttpServlet {
	private static final long serialVersionUID = 1L;
	public void service(HttpServletRequest req, HttpServletResponse rep)
			throws ServletException, IOException {
		rep.setContentType("text/xml;charset=utf-8");
		
		String tmp = req.getParameter("header");//前台传过来的json表头
		JSONArray ja = JSONArray.fromObject(tmp);
		
		List<Map<String, Object>> dataProvideList = DAO.findAll("from LogBook");//伪代码。。。
		ExpSimpleAdvanceDataGridBean bean = new ExpSimpleAdvanceDataGridBean(ja);
		bean.setExcelHeaderTitle("日志列表");//表头
		bean.setWorkSheetTitle("日志");//sheet name
		bean.setDataProvideList(dataProvideList);
		//bean.getExcelInputStream();
		
		InputStream in = bean.getExcelInputStream();
		OutputStream out = rep.getOutputStream();
		byte[] by = new byte[1024];
		int len = -1;
		while((len=in.read(by))!=-1){
			out.write(by, 0, len);
		}
		in.close();
		out.close();
	}
	
	private String checkString(String str){
		if(StringUtils.hasLength(str) && !str.trim().equals("null"))
			return str;
		return null;
	}
}
package com.sddl.bean;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.springframework.util.StringUtils;

import com.sddl.util.Tool;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import jxl.Workbook;
import jxl.format.Alignment;
import jxl.format.VerticalAlignment;
import jxl.write.Label;
import jxl.write.Number;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;

public class ExpSimpleAdvanceDataGridBean {
	private List<AdvanceDataGridColumnBean> headerList;
	private List<Map<String, Object>> dataProvideList;
	private String excelHeaderTitle;
	private String workSheetTitle;
	private int maxLevel;
	
	Map<String, Integer> maxLevelMap = new HashMap<String, Integer>();
	public ExpSimpleAdvanceDataGridBean(JSONArray ja){
		this.headerList = getHeaderList(ja, null);
		maxLevelMap.put("level", 0);
		getMaxLevel(ja);
		this.maxLevel = maxLevelMap.get("level");
	}
	
	public InputStream getExcelInputStream() {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		exportPassedData(out);
		return new ByteArrayInputStream(out.toByteArray());
	}	

	WritableCellFormat format1 = null;
	Map<String, RowColumnBean> rangeMap = null;
	private void exportPassedData(ByteArrayOutputStream os) {
		try {
			    WritableWorkbook workbook = Workbook.createWorkbook(os);
			
			    //定义格式
			    WritableFont font = new WritableFont(WritableFont.TIMES, 14, WritableFont.BOLD);
		        WritableCellFormat format = new WritableCellFormat(font);
		        format.setAlignment(Alignment.CENTRE);

  		        WritableFont font1 = new WritableFont(WritableFont.TIMES, 10, WritableFont.BOLD);
		        format1 = new WritableCellFormat(font1);
		        format1.setVerticalAlignment(VerticalAlignment.CENTRE);
		        format1.setAlignment(Alignment.CENTRE);

		        WritableCellFormat format4 = new WritableCellFormat();
		        format4.setAlignment(Alignment.LEFT);
		        format4.setVerticalAlignment(VerticalAlignment.BOTTOM);
		        format4.setWrap(false);
		      
		        WritableSheet sheet = workbook.createSheet(workSheetTitle, 0);
		      
		        Label labelTitle = new Label(0, 0, excelHeaderTitle, format);
		        
		        int columnIndex = 0;
		        int rowIndex = 1;
		        rangeMap = getRangeList(headerList, columnIndex, rowIndex);
		        setLabel(sheet, headerList, rowIndex);

		        //设置表头的长度
		        for (AdvanceDataGridColumnBean columnBean: headerList) {
		        	columnIndex += columnBean.getColumnSize();
		        }
		        sheet.mergeCells(0, 0, columnIndex - 1, 0);
		        sheet.addCell(labelTitle);

		        Pattern pa = Pattern.compile("[0-9.]*");
		        rowIndex = maxLevel+1;
		        for(int i=0; i<dataProvideList.size(); i++){
			    	  Label dataLabel = null;
			    	  Number cellNum = null;
			    	  Map<String, Object> dpMap = dataProvideList.get(i);
			    	  for(int j=0; j<matchMap.size(); j++){
			    		  Object data = dpMap.get(matchMap.get(j));
			    		  String cellStr = stringTool(data);
//			    		  if(StringUtils.hasLength(cellStr) && pa.matcher(cellStr).matches()){
//			    			  DecimalFormat df = new DecimalFormat("0.##");
//		    				  cellNum = new Number(j, rowIndex, Tool.sToF(df.format(Tool.sToF(cellStr, 0)), 0), format4);
//		    				  sheet.addCell(cellNum);
//			    		  } else {
			    			  dataLabel = new Label(j, rowIndex, cellStr, format4);
		    				  sheet.addCell(dataLabel);
//			    		  }
			    	  }
			    	  rowIndex++;
			      }
		        
		       workbook.write();
		       workbook.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	/***
	 * 为非首行设置“坐标”
	 * @param columnBean
	 */
	private void setRange(AdvanceDataGridColumnBean columnBean){
		AdvanceDataGridColumnBean parent = columnBean.getParent();
		if(rangeMap.get(parent.getHeaderText()+parent.getDataField()) == null){ //递归
			setRange(parent);
		} else {
			RowColumnBean range = rangeMap.get(parent.getHeaderText()+parent.getDataField());
			for(int i=0; i<parent.getChildren().size(); i++){
				AdvanceDataGridColumnBean childrenBean = parent.getChildren().get(i);
				int childrenIndex = parent.getChildren().indexOf(childrenBean);
				
				if(childrenIndex == 0){// 判断子节点在父节点的位置:老大还是老二?
					RowColumnBean rangeBean = getRange(childrenBean.getColumnSize(), range.getBeginColumnIndex(), range.getBeginRowIndex()+1); // 判断子节点在父节点的位置:老大还是老二?
					rangeMap.put(childrenBean.getHeaderText()+childrenBean.getDataField(), rangeBean);
				} else {
					range = rangeMap.get(parent.getChildren().get(i-1).getHeaderText()+ parent.getChildren().get(i-1).getDataField()); //得到哥哥的“坐标”,弟弟排在哥哥后面!
					RowColumnBean rangeBean = getRange(childrenBean.getColumnSize(), range.getEndColumnIndex()+1, range.getEndRowIndex());
					rangeMap.put(childrenBean.getHeaderText()+childrenBean.getDataField(), rangeBean);
				}
				
				if(childrenBean.getChildren() != null){ //如果有子节点,就再调用以给子节点赋值
					for(AdvanceDataGridColumnBean childrenChildrenBean :childrenBean.getChildren()){
						if(rangeMap.get(childrenChildrenBean.getHeaderText()+childrenChildrenBean.getDataField()) == null){
							setRange(childrenChildrenBean);
						}
					}
				}
			}
		}
	}
	
	/***
	 * 写入excel
	 * @param sheet
	 * @param headerList
	 * @param rowIndex
	 * @return
	 * @throws Exception
	 */
	private List<Label> setLabel(WritableSheet sheet, List<AdvanceDataGridColumnBean> headerList, int rowIndex) throws Exception{
		List<Label> list = new ArrayList<Label>();
		Label label = null;
		for (AdvanceDataGridColumnBean columnBean : headerList) {
    		RowColumnBean range = rangeMap.get(columnBean.getHeaderText()+columnBean.getDataField());
    		if(range == null){
    			setRange(columnBean);
    			range = rangeMap.get(columnBean.getHeaderText()+columnBean.getDataField());
    		}
    		sheet.mergeCells(range.getBeginColumnIndex(), range.getBeginRowIndex(), range.getEndColumnIndex(), range.getEndRowIndex());
    		label = new Label(range.getBeginColumnIndex(), range.getBeginRowIndex(), columnBean.getHeaderText(), format1);

    		sheet.addCell(label);
	    	if(columnBean.getChildren() != null){
	    		setLabel(sheet, columnBean.getChildren(), rowIndex++);
	    	}
		}
		return list;
	}
	
	/***
	 * 获取首行的”坐标“
	 * @param headerList
	 * @param columnIndex
	 * @param rowIndex
	 * @return Map<String, RowColumnBean>
	 */
	private Map<String, RowColumnBean> getRangeList(List<AdvanceDataGridColumnBean> headerList, int columnIndex, int rowIndex){
		Map<String, RowColumnBean> map = new HashMap<String, RowColumnBean>();
		
		for (AdvanceDataGridColumnBean columnBean : headerList) {
			List<AdvanceDataGridColumnBean> childrenColumnList = columnBean.getChildren();
	    	if (childrenColumnList ==null || !childrenColumnList.isEmpty()) {
    			map.put(columnBean.getHeaderText()+columnBean.getDataField(), getRange(columnBean.getColumnSize(), columnIndex, rowIndex));
	    		columnIndex += columnBean.getColumnSize();
	    	}
		}
		return map; 
	}
	
	/***
	 * 设置“坐标”
	 * @param columnSize
	 * @param columnIndex
	 * @param rowIndex
	 * @return RowColumnBean
	 */
	private RowColumnBean getRange(int columnSize, int columnIndex, int rowIndex){
		RowColumnBean bean = new RowColumnBean();
		bean.setBeginColumnIndex(columnIndex);
		bean.setBeginRowIndex(rowIndex);
		bean.setEndColumnIndex(columnIndex + columnSize - 1);
		if(columnSize==1){
			bean.setEndRowIndex(maxLevel);
		} else {
			bean.setEndRowIndex(rowIndex);
		}
		return bean;
	}
	
	/***
	 * 获取单元格的长度
	 * @param jb
	 * @return Integer
	 */
	private Integer getColumnSize(JSONObject jb){
		int columnSize = 0;
		if(StringUtils.hasLength(jb.get("children").toString()) && !jb.get("children").toString().equals("null")){
			JSONArray childrenJA = jb.getJSONArray("children");
			for(int i=0; i<childrenJA.size(); i++){
				columnSize += getColumnSize(JSONObject.fromObject(childrenJA.get(i)));	
			}
		} else {
			++columnSize;
		}
		return columnSize; 
	}
	
	/**
	 * 表头最多有多少“级别”
	 * @param JSONArray ja
	 * @return Integer
	 */
	private Integer getMaxLevel(JSONArray ja){
		int level = 1;
		for(int i=0; i<ja.size(); i++){
			JSONObject jb = JSONObject.fromObject(ja.get(i));
			int tmp = 1;
			
			if(StringUtils.hasLength(jb.get("children").toString()) && !jb.get("children").toString().equals("null")){
				tmp += getMaxLevel(jb.getJSONArray("children"));
				level = tmp;
			} 
			if(maxLevelMap.get("level")< level){
				maxLevelMap.put("level", level);
			}
		}
		return level;
	}
	
	
	Map<Integer, String> matchMap = new HashMap<Integer, String>(); //用于和数据源对应的map
	int matchIndex = 0;
	/***
	 * 遍历表头
	 * @param JSONArray ja 需要遍历的数据源
	 * @param AdvanceDataGridColumnBean parent 父节点
	 * @return  List<AdvanceDataGridColumnBean>
	 */
	private List<AdvanceDataGridColumnBean> getHeaderList(JSONArray ja, AdvanceDataGridColumnBean parent){
		List<AdvanceDataGridColumnBean> headerList = new ArrayList<AdvanceDataGridColumnBean>();
		for(int i=0; i<ja.size(); i++){
			AdvanceDataGridColumnBean bean = new AdvanceDataGridColumnBean();
			JSONObject jb = JSONObject.fromObject(ja.get(i));
			bean.setHeaderText(jb.getString("headerText"));
			bean.setDataField(jb.getString("dataField"));
			bean.setColumnSize(getColumnSize(jb));
			
			if(StringUtils.hasLength(jb.get("children").toString()) && !jb.get("children").toString().equals("null")){
				bean.setChildren(getHeaderList(jb.getJSONArray("children"), bean));
			} else {
				matchMap.put(matchIndex++, bean.getDataField()); //设置dataField和列的对应关系
			}
			if(parent != null){
				bean.setParent(parent);
			}
			headerList.add(bean);
		}
		return headerList;
	}
	
	public String stringTool(Object obj){
		if(obj == null){
			return null;
		} else {
			return obj.toString();
		}
	}
	
	public List<Map<String, Object>> getDataProvideList() {
		return dataProvideList;
	}

	public void setDataProvideList(List<Map<String, Object>> dataProvideList) {
		this.dataProvideList = dataProvideList;
	}

	public String getExcelHeaderTitle() {
		return excelHeaderTitle;
	}

	public void setExcelHeaderTitle(String excelHeaderTitle) {
		this.excelHeaderTitle = excelHeaderTitle;
	}
	public String getWorkSheetTitle() {
		return workSheetTitle;
	}

	public void setWorkSheetTitle(String workSheetTitle) {
		this.workSheetTitle = workSheetTitle;
	}

	public List<AdvanceDataGridColumnBean> getHeaderList() {
		return headerList;
	}

	public void setHeaderList(List<AdvanceDataGridColumnBean> headerList) {
		this.headerList = headerList;
	}
	protected class RowColumnBean{
		private Integer BeginColumnIndex;
		private Integer BeginRowIndex;
		private Integer endColumnIndex;
		private Integer endRowIndex;
		public Integer getBeginColumnIndex() {
			return BeginColumnIndex;
		}
		public void setBeginColumnIndex(Integer beginColumnIndex) {
			BeginColumnIndex = beginColumnIndex;
		}
		public Integer getBeginRowIndex() {
			return BeginRowIndex;
		}
		public void setBeginRowIndex(Integer beginRowIndex) {
			BeginRowIndex = beginRowIndex;
		}
		public Integer getEndColumnIndex() {
			return endColumnIndex;
		}
		public void setEndColumnIndex(Integer endColumnIndex) {
			this.endColumnIndex = endColumnIndex;
		}
		public Integer getEndRowIndex() {
			return endRowIndex;
		}
		public void setEndRowIndex(Integer endRowIndex) {
			this.endRowIndex = endRowIndex;
		}
	}
	public int getMaxLevel() {
		return maxLevel;
	}

	public void setMaxLevel(int maxLevel) {
		this.maxLevel = maxLevel;
	}

}
package com.sddl.bean;

import java.util.List;

public class AdvanceDataGridColumnBean {
	private String dataField;
	private String headerText;
	private AdvanceDataGridColumnBean parent;
	private List<AdvanceDataGridColumnBean> children;
	private Integer columnSize;
	
	public String getDataField() {
		return dataField;
	}

	public void setDataField(String dataField) {
		this.dataField = dataField;
	}

	public String getHeaderText() {
		return headerText;
	}

	public void setHeaderText(String headerText) {
		this.headerText = headerText;
	}

	public List<AdvanceDataGridColumnBean> getChildren() {
		return children;
	}

	public void setChildren(List<AdvanceDataGridColumnBean> children) {
		this.children = children;
	}

	public AdvanceDataGridColumnBean getParent() {
		return parent;
	}

	public void setParent(AdvanceDataGridColumnBean parent) {
		this.parent = parent;
	}

	public Integer getColumnSize() {
		return columnSize;
	}

	public void setColumnSize(Integer columnSize) {
		this.columnSize = columnSize;
	}

}

导出的数据:

展开阅读全文
打赏
0
4 收藏
分享
加载中
振哥哥博主

引用来自“chokee”的评论

dopost中
bean.getExcelInputStream();

InputStream in = bean.getExcelInputStream();

要执行2次,什么原因啊??高手
还真是嘞,手误手误。。。刚才给屏蔽掉了
2016/03/04 13:47
回复
举报
dopost中
bean.getExcelInputStream();

InputStream in = bean.getExcelInputStream();

要执行2次,什么原因啊??高手
2016/03/04 11:06
回复
举报
振哥哥博主

引用来自“pj_style”的评论

你这个复杂表头都行吗?

可以的
2013/12/27 12:19
回复
举报
你这个复杂表头都行吗?
2013/12/26 21:25
回复
举报
振哥哥博主

引用来自“城南往事”的评论

祝贺该文章发表一周年!

还真是咧。。。
2013/11/22 20:16
回复
举报
祝贺该文章发表一周年!
2013/11/22 11:48
回复
举报
木有权限哦~
2013/02/25 09:53
回复
举报
振哥哥博主

引用来自“wbhadad”的评论

木有权限阅读

已修改
2012/12/07 18:48
回复
举报
木有权限阅读
2012/12/07 14:12
回复
举报
振哥哥博主
存在问题:1、未设置列宽;2、数据量较大时会内存溢出;3、还未发现~
2012/11/23 23:10
回复
举报
更多评论
打赏
10 评论
4 收藏
0
分享
返回顶部
顶部