文件下载、excel导出、支持中文名字


文件下载、excel导出、支持中文

     导出excel、下载文件

     流程:导出都是从服务器下载文件,数据库中的数据查询出来 生成文件放到服务器上,再下载。下载之后可以根据需要自行删除或保留。

 

     一、数据库查询出的数据导出excel

         1.List<Map> 形式的数据

           1.1生成excel的工具类

 

import java.util.List;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/****
 * List<Map<String, Object>> 形式的数据 生成excel
 * CellStyle  为设置每个类型数据的样式
 * 内容设置里面的value  为得到数据类型,可根据需要补充
 *           else 里面为excel的类型数据。可根据需要补充
 * 建议:避免输入输出格式有误,建议全部用String格式走
 * 
 * @author tablemiao
 *
 */
public class CreateMapExcel {

	private static Logger logger = LoggerFactory.getLogger(CreateMapExcel.class);

	/**
	 * @param
	 * 		datas  	数据
	 * @param
	 * 		props	参数设置
	 * @param
	 * 		sheetName	单元格名称
	 * 
	 * */
	public static SXSSFWorkbook create(List<Map<String, Object>> datas,
			List<PropSetter> props, String sheetName) {

		long startTime = System.currentTimeMillis();
		SXSSFWorkbook workbook = new SXSSFWorkbook();
		Sheet sheet = workbook.createSheet();
		workbook.setSheetName(0, sheetName);

		Font titleFont = workbook.createFont();
		titleFont.setFontName("微软雅黑");
		titleFont.setFontHeightInPoints((short) 10); // 字体大小
		titleFont.setBoldweight(Font.BOLDWEIGHT_BOLD);// 加粗

		Font contentFont = workbook.createFont();
		contentFont.setFontName("微软雅黑");
		contentFont.setFontHeightInPoints((short) 9);
		
		
		DataFormat format = workbook.createDataFormat();
		CellStyle titleStyle = workbook.createCellStyle();
		titleStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 垂直
		titleStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);// 水平
		titleStyle.setBorderBottom(CellStyle.BORDER_THIN);
		titleStyle.setBorderLeft(CellStyle.BORDER_THIN);
		titleStyle.setBorderRight(CellStyle.BORDER_THIN);
		titleStyle.setBorderTop(CellStyle.BORDER_THIN);
		titleStyle.setFillForegroundColor(HSSFColor.LIGHT_GREEN.index);// 填暗红色
		titleStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
		titleStyle.setFont(titleFont);
		titleStyle.setWrapText(true);

		CellStyle stringStyle = workbook.createCellStyle();
		stringStyle.setAlignment(CellStyle.ALIGN_LEFT);
		stringStyle.setBorderBottom(CellStyle.BORDER_THIN);
		stringStyle.setBorderLeft(CellStyle.BORDER_THIN);
		stringStyle.setBorderRight(CellStyle.BORDER_THIN);
		stringStyle.setBorderTop(CellStyle.BORDER_THIN);
		stringStyle.setFont(contentFont);
		stringStyle.setWrapText(true);
		
		CellStyle longStyle = workbook.createCellStyle();
		longStyle.setAlignment(CellStyle.ALIGN_LEFT);
		longStyle.setBorderBottom(CellStyle.BORDER_THIN);
		longStyle.setBorderLeft(CellStyle.BORDER_THIN);
		longStyle.setBorderRight(CellStyle.BORDER_THIN);
		longStyle.setBorderTop(CellStyle.BORDER_THIN);
		longStyle.setFont(contentFont);
		longStyle.setDataFormat(format.getFormat("0"));
		longStyle.setWrapText(true);
		
		CellStyle doubleStyle = workbook.createCellStyle();
		doubleStyle.setAlignment(CellStyle.ALIGN_LEFT);
		doubleStyle.setBorderBottom(CellStyle.BORDER_THIN);
		doubleStyle.setBorderLeft(CellStyle.BORDER_THIN);
		doubleStyle.setBorderRight(CellStyle.BORDER_THIN);
		doubleStyle.setBorderTop(CellStyle.BORDER_THIN);
		doubleStyle.setFont(contentFont);
		doubleStyle.setDataFormat(format.getFormat("0.00"));
		doubleStyle.setWrapText(true);
		
		Row rowOne = sheet.createRow(0);
		rowOne.setHeight((short) 350);
		Cell cell;
		for (int i = 0; i < props.size(); i++) {// 标题的设置
			cell = rowOne.createCell(i);
			sheet.setColumnWidth(i, props.get(i).getWidth()); // 宽度
			cell.setCellStyle(titleStyle);
			cell.setCellValue(props.get(i).getrOne()); // 标题
		}
		// 内容设置
		Row row;
		if (datas.size() != 0) {
			for (int m = 0; m < datas.size(); m++) {
				row = sheet.createRow(m + 1);
				row.setHeight((short) 310);
				for (int i = 0; i < props.size(); i++) {
					Cell cont = row.createCell(i);
					Object value = datas.get(m).get(props.get(i).getProp());
					if (value == null) {
						cont.setCellValue("");
						cont.setCellStyle(stringStyle);
					}else{
						try{
							cont.setCellType(HSSFCell.CELL_TYPE_STRING);
							cont.setCellValue(Long.valueOf(String.valueOf(value)));
							cont.setCellStyle(longStyle);
						}catch(Exception e){
							try{
								cont.setCellType(HSSFCell.CELL_TYPE_STRING);
								cont.setCellValue((Double.valueOf(String.valueOf(value))));
								cont.setCellStyle(doubleStyle);
							}catch(Exception e1){
								cont.setCellType(HSSFCell.CELL_TYPE_STRING);
								cont.setCellValue(String.valueOf(value));
								cont.setCellStyle(stringStyle);
							}
						}
					}
				}
			}
		}
		logger.info("导出总计耗时: {}", System.currentTimeMillis() - startTime + "毫秒!");
		return workbook;
	}

}

      1.2 组成excel数据的实体

 

/***
 * 组成list数据的实体
 * 
 * @author tablemiao
 *
 */
public class PropSetter {

	private String rOne;
	
	private String rTwo;
	
	private String prop;
	
	private String type;
	
	private int width;
	
	private boolean color;

	/**** get、set 方法省略  ******/

	public PropSetter(String rOne, String rTwo, String prop, int width) {
		super();
		this.rOne = rOne;
		this.rTwo = rTwo;
		this.prop = prop;
		this.width = width;
	}

	public PropSetter(String rOne, String rTwo, String prop, int width,
			boolean color) {
		super();
		this.rOne = rOne;
		this.rTwo = rTwo;
		this.prop = prop;
		this.width = width;
		this.color = color;
	}

	public PropSetter(String rOne, String rTwo, String prop, String type,
			int width) {
		super();
		this.rOne = rOne;
		this.rTwo = rTwo;
		this.prop = prop;
		this.type = type;
		this.width = width;
	}

	public PropSetter() {
		super();
	}
	
}

      1.3 数据库的数据填充的excel里

 

/***
	 * map数据 直接 导出
	 * @param param  dao层参数,这里直接测试 不通过dao
	 * @param realFile  导出的生成文件名,用来下载 
	 * @throws IOException
	 */
	public void exportToMap(Map<String, String> param, String realFile) throws IOException{
               // param 为dao成过来的参数,可利用dao层查询数据库 得到一个需要导出的List<Map>数据
                
               //此处自定义这样的数据 导出测试,根据实际查询数据库即可
		List<Map<String, Object>> datas = new ArrayList<Map<String,Object>>();
		Map<String, Object> map = null;
		map = new HashMap<String, Object>();
		map.put("customersNum", "2101087118");
		map.put("customersName", "上海习正金融信息服务有限公司");
		map.put("logo", "CL-BQ-A-NULL-218840-ZB");
		datas.add(map);
		map = new HashMap<String, Object>();
		map.put("customersNum", "2100309828");
		map.put("customersName", "苏州银行股份有限公司");
		map.put("logo", "CL-XB-A-NULL-1211-0072");
		datas.add(map);
		map = new HashMap<String, Object>();
		map.put("customersNum", "2100311056");
		map.put("customersName", "中国移动国际有限公司");
		map.put("logo", "CL-JK-I-NULL-218446-XB");
		datas.add(map);
		
                //构造一个excel,每一行即为一个PropSetter
                //第一列为导出的excel的列名、第三列为map数据的key,大小写必须一致,第五列为excel每一格的宽度,具体可以在1.2的类里面自定义
		List<PropSetter> props = new ArrayList<PropSetter>();
		props.add(new PropSetter("集团编号qqqqq", null, "customersNum", null, 4000));
		props.add(new PropSetter("集团名称", null, "customersName", null, 6000));
		props.add(new PropSetter("专线编号", null, "logo", null, 6000));
		
                //调用1.1中的生成方法 生成excel
		OutputStream outputStream = new FileOutputStream(realFile);
		SXSSFWorkbook workbook = CreateMapExcel.create(datas, props,"ExcelToMap测试");
		workbook.write(outputStream);
		logger.info("ExcelToMap 测试 导出成功");
		outputStream.flush();
		outputStream.close();
	}

 

 

           1.4  servlet导出生成1.3生成的excel,下载文件也是如此

        组装下载地址

      

private final FastDateFormat dayFormat = FastDateFormat.getInstance("yyyyMMdd^yyyyMMddHHmmss^");

public String exportToMap() throws Exception {
		String fileName = "export" + File.separator + "Map数据直接导出测试_"
				+ dayFormat.format(System.currentTimeMillis()) + ".xlsx";
                //获取服务器地址加文件名字,即文件存放的位置
		String realFile = webPath + File.separator + fileName;
		fileOperate(realFile);//上传方法里的判断文件是否存在,根据需要删除
		exportExcel.exportToMap(new HashMap<String, String>(),realFile);
		return fileName;
	}

   private void fileOperate(String realFile) {
		File file = new File(realFile);
		if(file.exists()) {
			logger.info("文件已经存在, 执行文件删除操作");
			file.delete();
			logger.info("删除已经存在的文件, 文件名称: {}", realFile);
		}
	}

 

 

        1.5 暴露接口,通过一串地址在浏览器地址栏中输入下载服务器相应文件

 

@GET
	@Path("/export")
	@Produces("text/plain;charset=UTF-8")
	public String exportExcel() throws Exception {
		String fileName = servletUpload.exportToMap();
		logger.info("ExcelToMap导出 成功 FileName  : {} ", fileName);
		String tmp = getUrlCode(fileName);
		logger.info("组装后的文件名称: {}", tmp);
		return tmp;
	}

protected String getUrlCode(String fileName)
			throws UnsupportedEncodingException {
		String tmp = fileName.replace("export/", "");
		String[] fs = tmp.split("\\^");
		tmp = fs[0] + fs[2];
		tmp = "servletExportUtil/" + URLEncoder.encode(tmp, "utf-8") + "?timeId=" + fs[1];
		return tmp;
	}

     1.6  servlet 拦截地址下载文件

 

 

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLDecoder;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ServletExportUtil extends HttpServlet {

	protected final Logger logger = LoggerFactory.getLogger(this.getClass());

	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		String url = request.getRequestURI();
		String timeId = request.getParameter("timeId");
		String fileNameDecode = url.substring(url.lastIndexOf('/') + 1);
		logger.info("timeId: {}", timeId);
		fileNameDecode = URLDecoder.decode(fileNameDecode, "utf-8");
		String[] fs = fileNameDecode.split("\\.");
		String realFileName = fs[0] + "^" + timeId + "^." + fs[1];
//		fileNameDecode = fs[0] + fs[2];
		logger.info("转义后的文件名称: {}, {}", fileNameDecode);
		String savepath = getInitParameter("FilePath");
		logger.info("文件保存的路径: {}", savepath);
		logger.info("文件绝对路径: {}", savepath + File.separator + realFileName);
		File file = new File(savepath + File.separator + realFileName);
		if (!file.exists()) {
			throw new RuntimeException("文件不存在");
		} else {
			InputStream in = new FileInputStream(file);
			// 设置响应类型
			response.setContentType("application/force-download");
			response.setHeader("Content-Disposition", "attachment;filename="
							+ new String(fileNameDecode.getBytes("utf-8"), "ISO-8859-1"));
			// 把本地文件发送给客户端
			OutputStream out = response.getOutputStream();
			int len = 0;
			byte[] bs = new byte[in.available()];
			while ((len = in.read(bs)) != -1) {
				out.write(bs, 0, len);
			}
			in.close();
			out.flush();
			out.close();
		}
	}

}

         1.7    web.xml 配置servlet  即 webpath的 服务器路径(这个路径亦可以写死在代码里)

 

<servlet>
		<servlet-name>ServletExportUtil</servlet-name>
		<servlet-class>com.eastcom.linksight.ws.webservices.ext.ServletExportUtil</servlet-class>
		<init-param>
			<param-name>FilePath</param-name>
			<param-value>/home/table/tomcat-res1/webapps/shjkws/export</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>ServletExportUtil</servlet-name>
		<url-pattern>/servletExportUtil/*</url-pattern>
	</servlet-mapping>

<!-- class 对应相应webpath定义的类,value 就是初始化给的值,即服务器路径    -->
<bean class="com.eastcom.linksight.ws.elapse.service.impl.ElapseNoticeServiceImpl">
<property value="/home/table/tomcat-res1/webapps/shjkws" name="webPath"/>

</bean>

        总结流程:

 

               1.客户端调用导出接口拿到一个地址放在服务器请求

                   eg:http://10.221.xx.xx:8080/table/servletExportUtil/%E7%BB%9F%E8%AE%A1%E5%88%86%E6%9E%90.xlsx?timeId=20150430165132  以servletExportUtil为分割 前面一节为服务器地址,后面一节为export接口生成的地址,详见1.4和1.5

拿到1.4中的filename通过1.5中getUriCode方法转码拼接之后就得到了。

             2.该请求地址被servlet拦截(web.xml有配置),进入1.6解析,找到服务器中对应的文件 通过流方式 生成文件到客户端

 

 

     二   List<bean> 方式的数据处理,下载方式完全,生成文件到服务器有点差异。

         2.1生成excel的模板

 

package com.eastcom.linksight.ws.elapse.export;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;

import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

public class CreateExcel<Record> {

	private Logger logger = LoggerFactory.getLogger(getClass());

	public SXSSFWorkbook create(List<CellSetter> cellSetters,
			List<Record> records, String sheetName) {

		long xl = System.currentTimeMillis();
		CellSetter cellSetter;
		Cell cell;
		SXSSFWorkbook workbook = new SXSSFWorkbook();
		DataFormat format = workbook.createDataFormat();
		Method getMethod = null;
		try {
			int cols = cellSetters.size();
			int rows = records.size();

			Font titleFont = workbook.createFont();
			titleFont.setFontName("微软雅黑");
			titleFont.setFontHeightInPoints((short) 10); // 字体大小
			titleFont.setBoldweight(Font.BOLDWEIGHT_BOLD);// 加粗

			Font contentFont = workbook.createFont();
			contentFont.setFontName("微软雅黑");
			contentFont.setFontHeightInPoints((short) 8);

			CellStyle titleStyle = workbook.createCellStyle();
			CellStyle longStyle = workbook.createCellStyle();
			CellStyle stringStyle = workbook.createCellStyle();
			CellStyle dateStyle = workbook.createCellStyle();
			CellStyle booleanStyle = workbook.createCellStyle();
			CellStyle doubleStyle = workbook.createCellStyle();

			titleStyle.setAlignment(CellStyle.ALIGN_CENTER);
			titleStyle.setBorderBottom(CellStyle.BORDER_THIN);
			titleStyle.setBorderLeft(CellStyle.BORDER_THIN);
			titleStyle.setBorderRight(CellStyle.BORDER_THIN);
			titleStyle.setBorderTop(CellStyle.BORDER_THIN);
			titleStyle.setFillForegroundColor(HSSFColor.LIGHT_GREEN.index);// 填暗红色
			titleStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
			titleStyle.setFont(titleFont);
			titleStyle.setWrapText(true);

			longStyle.setAlignment(CellStyle.ALIGN_LEFT);
			longStyle.setBorderBottom(CellStyle.BORDER_THIN);
			longStyle.setBorderLeft(CellStyle.BORDER_THIN);
			longStyle.setBorderRight(CellStyle.BORDER_THIN);
			longStyle.setBorderTop(CellStyle.BORDER_THIN);
			longStyle.setFont(contentFont);
			longStyle.setWrapText(true);

			doubleStyle.setAlignment(CellStyle.ALIGN_LEFT);
			doubleStyle.setBorderBottom(CellStyle.BORDER_THIN);
			doubleStyle.setBorderLeft(CellStyle.BORDER_THIN);
			doubleStyle.setBorderRight(CellStyle.BORDER_THIN);
			doubleStyle.setBorderTop(CellStyle.BORDER_THIN);
			doubleStyle.setFont(contentFont);
			doubleStyle.setWrapText(true);

			stringStyle.setAlignment(CellStyle.ALIGN_LEFT);
			stringStyle.setBorderBottom(CellStyle.BORDER_THIN);
			stringStyle.setBorderLeft(CellStyle.BORDER_THIN);
			stringStyle.setBorderRight(CellStyle.BORDER_THIN);
			stringStyle.setBorderTop(CellStyle.BORDER_THIN);
			stringStyle.setFont(contentFont);
			stringStyle.setWrapText(true);

			dateStyle.setAlignment(CellStyle.ALIGN_LEFT);
			dateStyle.setBorderBottom(CellStyle.BORDER_THIN);
			dateStyle.setBorderLeft(CellStyle.BORDER_THIN);
			dateStyle.setBorderRight(CellStyle.BORDER_THIN);
			dateStyle.setBorderTop(CellStyle.BORDER_THIN);
			dateStyle.setFont(contentFont);
			dateStyle.setWrapText(true);

			booleanStyle.setAlignment(CellStyle.ALIGN_LEFT);
			booleanStyle.setBorderBottom(CellStyle.BORDER_THIN);
			booleanStyle.setBorderLeft(CellStyle.BORDER_THIN);
			booleanStyle.setBorderRight(CellStyle.BORDER_THIN);
			booleanStyle.setBorderTop(CellStyle.BORDER_THIN);
			booleanStyle.setFont(contentFont);
			booleanStyle.setWrapText(true);

			Sheet sheet = workbook.createSheet();
			workbook.setSheetName(0, sheetName);
			Row row = sheet.createRow(0);
//			Drawing draw = sheet.createDrawingPatriarch();
			Class<Record> clz = null;

			Method[] methods = new Method[cols];
			if (!CollectionUtils.isEmpty(records)) {
				clz = (Class<Record>) records.get(0).getClass();
			}

			// 设置标题
			for (int i = 0; i < cols; i++) {
				cell = row.createCell(i);
				cellSetter = cellSetters.get(i);
				cell.setCellValue(cellSetter.getTitle().trim());
				cell.setCellStyle(titleStyle);
//				if (cellSetters.get(i) != null) {
//					Comment comment = draw
//							.createCellComment(new XSSFClientAnchor(0, 0, 0, 0,
//									cell.getColumnIndex(), row.getRowNum(),
//									cell.getColumnIndex() + 1,
//									row.getRowNum() + 2));
//					comment.setString(new XSSFRichTextString(cellSetter
//							.getTitle()));
//					cell.setCellComment(comment);
//				}
				if (clz != null) {
					PropertyDescriptor pd = new PropertyDescriptor(
							cellSetter.getProperty(), clz);
					methods[i] = pd.getReadMethod();
				}
			}

			// 这是内容
			for (int i = 0; i < rows; i++) {

				row = sheet.createRow(i + 1);
				row.setHeight((short) 300);
				if ((i + 1) % 10000 == 0)
					logger.info("存了一万条记录  {}");
				for (int j = 0; j < cols; j++) {
					cellSetter = cellSetters.get(j);
					cell = row.createCell(j);
					Record record = records.get(i);

					getMethod = methods[j];
					if (getMethod.invoke(record) == null) {
						cell.setCellStyle(stringStyle);
						continue;
					}
					if (cellSetter.getRender() != null) {
						cell.setCellType(Cell.CELL_TYPE_STRING);
						cell.setCellStyle(stringStyle);
						cell.setCellValue(cellSetter.getRender().view(
								getMethod.invoke(record)));
//						Comment comment = draw
//								.createCellComment(new XSSFClientAnchor(0, 0,
//										0, 0, cell.getColumnIndex(), row
//												.getRowNum(), cell
//												.getColumnIndex() + 1, row
//												.getRowNum() + 2));
//						comment.setString(new XSSFRichTextString(cellSetter
//								.getRender().view(getMethod.invoke(record))));
//						cell.setCellComment(comment);
						continue;
					}
					if (cellSetter.getType().trim().toLowerCase()
							.equals("long")
							|| cellSetter.getType().trim().toLowerCase()
									.equals("int")
							|| cellSetter.getType().trim().toLowerCase()
									.equals("byte")
							|| cellSetter.getType().trim().toLowerCase()
									.equals("short")) {
						cell.setCellType(Cell.CELL_TYPE_NUMERIC);
						longStyle.setDataFormat(format.getFormat(cellSetter
								.getFormat()));
						cell.setCellValue(Long.parseLong(getMethod.invoke(
								record).toString()));
//						Comment comment = draw
//								.createCellComment(new XSSFClientAnchor(0, 0,
//										0, 0, cell.getColumnIndex(), row
//												.getRowNum(), cell
//												.getColumnIndex() + 1, row
//												.getRowNum() + 2));
//						comment.setString(new XSSFRichTextString(getMethod
//								.invoke(record).toString()));
//						cell.setCellComment(comment);
						cell.setCellStyle(longStyle);
						continue;
					}
					if (cellSetter.getType().trim().toLowerCase()
							.equals("double")
							|| cellSetter.getType().trim().toLowerCase()
									.equals("float")) {
						cell.setCellType(Cell.CELL_TYPE_NUMERIC);
						doubleStyle.setDataFormat(format.getFormat(cellSetter
								.getFormat()));
						cell.setCellValue(Double.parseDouble(getMethod.invoke(
								record).toString()));
//						Comment comment = draw
//								.createCellComment(new XSSFClientAnchor(0, 0,
//										0, 0, cell.getColumnIndex(), row
//												.getRowNum(), cell
//												.getColumnIndex() + 1, row
//												.getRowNum() + 2));
//						comment.setString(new XSSFRichTextString(getMethod
//								.invoke(record).toString()));
//						cell.setCellComment(comment);
						cell.setCellStyle(doubleStyle);
						continue;
					}
					if (cellSetter.getType().trim().toLowerCase()
							.equals("date")) {
						cell.setCellType(Cell.CELL_TYPE_NUMERIC);
						dateStyle.setDataFormat(format.getFormat(cellSetter
								.getFormat()));
						cell.setCellValue((Date) getMethod.invoke(record));
						cell.setCellStyle(dateStyle);
//						Comment comment = draw
//								.createCellComment(new XSSFClientAnchor(0, 0,
//										0, 0, cell.getColumnIndex(), row
//												.getRowNum(), cell
//												.getColumnIndex() + 1, row
//												.getRowNum() + 2));
//						comment.setString(new XSSFRichTextString(getMethod
//								.invoke(record).toString()));
//						cell.setCellComment(comment);
						continue;
					}
					if (cellSetter.getType().trim().toLowerCase()
							.equals("string")
							|| cellSetter.getType().trim().toLowerCase()
									.equals("char")) {
						cell.setCellType(Cell.CELL_TYPE_STRING);
						try {
							cell.setCellValue(Integer.parseInt(getMethod
									.invoke(record).toString()));
							cell.setCellStyle(longStyle);
						} catch (Exception e) {
							try {
								cell.setCellValue(Double.parseDouble(getMethod
										.invoke(record).toString()));
								cell.setCellStyle(doubleStyle);
							} catch (Exception e1) {
								cell.setCellStyle(stringStyle);
								cell.setCellValue(getMethod.invoke(record)
										.toString());
							}
						}
//						Comment comment = draw
//								.createCellComment(new XSSFClientAnchor(0, 0,
//										0, 0, cell.getColumnIndex(), row
//												.getRowNum(), cell
//												.getColumnIndex() + 1, row
//												.getRowNum() + 2));
//						comment.setString(new XSSFRichTextString(getMethod
//								.invoke(record).toString()));
//						cell.setCellComment(comment);
						continue;
					}
					if (cellSetter.getType().trim().toLowerCase()
							.equals("boolean")) {
						cell.setCellType(Cell.CELL_TYPE_BOOLEAN);
						booleanStyle.setDataFormat(format.getFormat(cellSetter
								.getFormat()));
						cell.setCellStyle(booleanStyle);
						cell.setCellValue((Boolean) getMethod.invoke(record));
//						Comment comment = draw
//								.createCellComment(new XSSFClientAnchor(0, 0,
//										0, 0, cell.getColumnIndex(), row
//												.getRowNum(), cell
//												.getColumnIndex() + 1, row
//												.getRowNum() + 2));
//						comment.setString(new XSSFRichTextString(getMethod
//								.invoke(record).toString()));
//						cell.setCellComment(comment);
						continue;
					}
				}
			}
			// 给每行设置单元格长度
			for (int i = 0; i < cellSetters.size(); i++) {
				cellSetter = cellSetters.get(i);
				sheet.setColumnWidth(i, cellSetter.getCellColumnWidth());
			}

			logger.info("总耗时 {} ", System.currentTimeMillis() - xl);
			return workbook;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

}

      2.2构造组成excel数据的实体

 

/***
* 该类 可根据具体需求设定
*
**/

public class CellSetter {

	private String title;
	private String property;
	private String type;
	private String format;
	private int cellColumnWidth;
	private ExeclColRnderer render;

      /****  省略 get、set *****/

	public CellSetter(String title, String property, String type, String format, int cellColumnWidth) {
		super();
		this.title = title;
		this.property = property;
		this.type = type;
		this.format = format;
		this.cellColumnWidth = cellColumnWidth;
	}
	

	public CellSetter(String title, String property, String type, String format, int cellColumnWidth, ExeclColRnderer render) {
		super();
		this.title = title;
		this.property = property;
		this.type = type;
		this.format = format;
		this.cellColumnWidth = cellColumnWidth;
		this.render = render;
	}

	public CellSetter() {

	}

}

interface ExeclColRnderer{
	String view(Object o);
}

       2.3   数据库的数据填充的excel里

 

/***
	 * 统计分析_kpi指标_售中kpi指标_售中kpi维护
	 * 
	 * @param data ws层直接传过来的数据
	 * @throws Exception 
	 */
	public void createKpiIndexSZ(List<KpiIndexSZ> data,String realFile) throws Exception{
		CreateExcel<KpiIndexSZ> createExcel = new CreateExcel<KpiIndexSZ>();
		logger.info("开始导出 统计分析_kpi指标_售中kpi指标_售中kpi维护   数据");
		//  CellSetter 第一列为 excel中的头、第二列为实体对应的字段、第三列为数据的类型、第4列为excel的类型、5列为宽度
		List<CellSetter> cellSetter = new ArrayList<CellSetter>();
		cellSetter.add(new CellSetter("月份", "saveDate", "String", "G/通用格式", 6000));
		cellSetter.add(new CellSetter("属地分公司", "dependency", "String", "G/通用格式", 6000));
		cellSetter.add(new CellSetter("售中开通及时率(%)", "ratio", "String", "G/通用格式", 6000));
		
		OutputStream outputStream = new FileOutputStream(realFile);
		SXSSFWorkbook workbook = createExcel.create(cellSetter, data,"售中kpi维护");
		workbook.write(outputStream);
		logger.info("统计分析_kpi指标_售中kpi指标  数据导出成功");
		outputStream.flush();
		outputStream.close();
	}

     其余下载为List<Map> 一致

  

  三、复杂表头的数据导出

    下载方式与上述一致,只是构造excel的模板不同,跨列和跨行其实就算坐标。合并坐标。

    比如:要导出这样的格式(客户信息跨两列,专线编号跨两行)


文件下载、excel导出、支持中文名字_第1张图片
 导出excel复杂表头模板类

 

import java.util.List;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CreateTwoMapExcel {

	private static Logger logger = LoggerFactory.getLogger(CreateMapExcel.class);

	/**
	 * @param
	 * 		datas  	数据
	 * @param
	 * 		props	参数设置
	 * @param
	 * 		fps		合并单元格坐标值
	 * @param
	 * 		sheetName	单元格名称
	 * 
	 * */
	public static SXSSFWorkbook create(List<Map<String, Object>> datas,
			List<PropSetter> props, List<FourPoint> fps, String sheetName) {

		long startTime = System.currentTimeMillis();
		SXSSFWorkbook workbook = new SXSSFWorkbook();
		Sheet sheet = workbook.createSheet();
		workbook.setSheetName(0, sheetName);

		Font titleFont = workbook.createFont();
		titleFont.setFontName("微软雅黑");
		titleFont.setFontHeightInPoints((short) 10); // 字体大小
		titleFont.setBoldweight(Font.BOLDWEIGHT_BOLD);// 加粗

		Font contentFont = workbook.createFont();
		contentFont.setFontName("微软雅黑");
		contentFont.setFontHeightInPoints((short) 9);

		CellStyle titleStyle = workbook.createCellStyle();
		titleStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 垂直
		titleStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);// 水平
		titleStyle.setBorderBottom(CellStyle.BORDER_THIN);
		titleStyle.setBorderLeft(CellStyle.BORDER_THIN);
		titleStyle.setBorderRight(CellStyle.BORDER_THIN);
		titleStyle.setBorderTop(CellStyle.BORDER_THIN);
		titleStyle.setFillForegroundColor(HSSFColor.LIGHT_GREEN.index);// 填暗红色
		titleStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
		titleStyle.setFont(titleFont);
		titleStyle.setWrapText(true);

		CellStyle stringStyle = workbook.createCellStyle();
		stringStyle.setAlignment(CellStyle.ALIGN_LEFT);
		stringStyle.setBorderBottom(CellStyle.BORDER_THIN);
		stringStyle.setBorderLeft(CellStyle.BORDER_THIN);
		stringStyle.setBorderRight(CellStyle.BORDER_THIN);
		stringStyle.setBorderTop(CellStyle.BORDER_THIN);
		stringStyle.setFont(contentFont);
		stringStyle.setWrapText(true);

		Row rowOne = sheet.createRow(0);
		rowOne.setHeight((short) 350);
		Row rowTwo = sheet.createRow(1);
		Cell cell;
		for(int i=0; i<props.size(); i++) {
			cell = rowOne.createCell(i);//	一级标题的设置
			cell.setCellStyle(titleStyle);
			cell.setCellValue(props.get(i).getrOne());
			cell = rowTwo.createCell(i);//	二级标题的设置
			cell.setCellStyle(titleStyle);
			cell.setCellValue(props.get(i).getrTwo());
			sheet.setColumnWidth(i, props.get(i).getWidth()); // 宽度
		}
		for(FourPoint fp : fps) {//	合并单元格
			sheet.addMergedRegion(new CellRangeAddress(fp.getRowStart(), fp.getRowEnd(),
					fp.getColStart(), fp.getColEnd()));
		}
		// 内容设置
		Row row;
		if (datas.size() != 0) {
			for (int m = 0; m < datas.size(); m++) {
				row = sheet.createRow(m + 2);
				row.setHeight((short) 310);
				for (int i = 0; i < props.size(); i++) {
					Cell cont = row.createCell(i);
					Object value = datas.get(m).get(props.get(i).getProp());
					if (value == null) {
						cont.setCellValue("");
//						cont.setCellType(HSSFCell.CELL_TYPE_STRING);
						cont.setCellStyle(stringStyle);
					} else {
							cont.setCellType(HSSFCell.CELL_TYPE_STRING);
							cont.setCellValue(String.valueOf(value));
							cont.setCellStyle(stringStyle);
					}
				}
			}
		}
		logger.info("导出总计耗时: {}", System.currentTimeMillis() - startTime + "毫秒!");
		return workbook;
	}
	
}

     3.2构造导出实体

 

package com.tm.util;

/***
 * 组成list数据的实体
 * 
 * @author tablemiao
 *
 */
public class PropSetter {

	private String rOne; //第一行标题
	
	private String rTwo; //第二行标题
	
	private String prop;//对应的导出数据的字段名
	
	private String type;//数据类型
	
	private int width;//表格宽度
	
	private boolean color;//颜色

	/******  Getter Setter  省略*****/

	public PropSetter(String rOne, String rTwo, String prop, int width) {
		super();
		this.rOne = rOne;
		this.rTwo = rTwo;
		this.prop = prop;
		this.width = width;
	}

	public PropSetter(String rOne, String rTwo, String prop, int width,
			boolean color) {
		super();
		this.rOne = rOne;
		this.rTwo = rTwo;
		this.prop = prop;
		this.width = width;
		this.color = color;
	}

	public PropSetter(String rOne, String rTwo, String prop, String type,
			int width) {
		super();
		this.rOne = rOne;
		this.rTwo = rTwo;
		this.prop = prop;
		this.type = type;
		this.width = width;
	}

	public PropSetter() {
		super();
	}
	
}

 3.3 填充数据并导出(此处简单起见,就直接导出测试,以单元测试的方式呈现,也可向上诉一样封装接口)

 

        @Test
	public void testMapExport1() throws Exception {
		List<Map<String, Object>> datas = new ArrayList<Map<String,Object>>();
		Map<String, Object> map = null;
		map = new HashMap<String, Object>();
		map.put("customersNum", "2101087118");
		map.put("customersName", "上海习正金融信息服务有限公司");
		map.put("logo", "CL-BQ-A-NULL-218840-ZB");
		datas.add(map);
		map = new HashMap<String, Object>();
		map.put("customersNum", "2100309828");
		map.put("customersName", "苏州银行股份有限公司");
		map.put("logo", "CL-XB-A-NULL-1211-0072");
		datas.add(map);
		map = new HashMap<String, Object>();
		map.put("customersNum", "2100311056");
		map.put("customersName", "中国移动国际有限公司");
		map.put("logo", "CL-JK-I-NULL-218446-XB");
		datas.add(map);
		
		List<PropSetter> props = new ArrayList<PropSetter>();
		props.add(new PropSetter("客户信息", "客户名称", "customersName", 4000));
		props.add(new PropSetter("", "客户编号", "customersNum", 4000));
		props.add(new PropSetter("专线编号", "", "logo", 4000));
		
		List<FourPoint> fps = new ArrayList<FourPoint>();
		//合并A,B列,坐标从0开始(客户信息这一栏为第一行所以是(0,0)纵左边跨AB所以是(0,1))
		fps.add(new FourPoint(0, 0, 0, 1));
		//合并1,2行,坐标从0开始(专线编号这一栏为1,2行所以是(0,1)纵左边为C列所以是(2,2))
		fps.add(new FourPoint(0, 1, 2, 2));
		
		OutputStream outputStream = new FileOutputStream("Z:/复杂表头导出.xlsx");
		SXSSFWorkbook workbook = CreateTwoMapExcel.create(datas, props, fps,
				"跨行跨列导出测试");
		workbook.write(outputStream);
		outputStream.flush();
		outputStream.close();
	}

 

     

 

 

 

 

 

 

你可能感兴趣的:(文件下载,excel下载,中文导出)