当前位置: 首页 > 工具软件 > EXCEL-UTIL4J > 使用案例 >

数据转EXCEL后直接用流的形式发送邮件的方式(文件不落地)(完成java转excel的Util类)

松献
2023-12-01

领导最近交给一个任务,要求定时任务,发送邮件。

具体要求为,要求指定数据库库中查出指定数据,并且放到Excel表格中,最后发送到指定邮箱,但是要求文件不落地。
java中能把数据从流转为excel文件的由两种包,一种是apache开发的poi另一种是net.sourceforge.jexcelapi,听说是一个韩国人开发的包。
我尽量两种包都写到。在公司要求中我使用的是poi。我先用poi实现了这个转换。其中没有设置表格的样式内容。
poi设置Excel单元格样式:https://www.cnblogs.com/linkstar/p/5910916.html
具体代码借鉴了这个老哥的思路:https://blog.csdn.net/yixin605691235/article/details/82429156
具体实现如下(poi实现):
数据转Excel工具类:

package com.www.kx;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

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

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.formula.functions.T;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

public class Data2Excel {

	/**
	 * 对象转Excel文件
	 * 
	 * @param list
	 *            传入的数据
	 *            			对应的
	 * @param sheetSize
	 *            工作表的大小
	 * @param request
	 *            网页传来的请求
	 * @param response
	 *            网页传来的相应
	 * @param fileName
	 *            文件名
	 * @param sheetName
	 *            工作表名字
	 * @param title
	 *            表头  
	 *            key-为英文表头 表要javabean对应所以要遵循如下规则
	 *            	根据带路径或不带路径的属性名获取属性值,即接受简单属性名,如userName等,又接受带路径的属性名,如student.department.name等
	 *            value-对应中文在excel中产生的表头名
	 */
	public static void list2ExcelFile(List<T> list, int sheetSize, HttpServletRequest request,
			HttpServletResponse response, String fileName, String sheetName, LinkedHashMap<String, String> title) {
		OutputStream outputStream = null;
		// 首先判断list里面是不是有值
		if (list == null || list.size() == 0) {
			// 如果空或者大小为0就直接return 或者抛出异常
			return;
			// throw new Exception("传入的数据为空或者大小为零");
		}
		try {
			// 前台页面显示下载
			setResp(request, response, fileName);
			outputStream = response.getOutputStream();
			Workbook wb = new HSSFWorkbook();
			Sheet sheet = wb.createSheet(sheetName);
			fillVeticalSheet(sheet, list, title);
			wb.write(outputStream);
			if (wb != null) {
				wb.close();
			}
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			if (outputStream != null) {
				try {
					outputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 对象转流
	 * 
	 * @param list
	 *            传入的数据
	 * @param sheetSize
	 *            工作表的大小
	 * @param request
	 *            网页传来的请求
	 * @param response
	 *            网页传来的相应
	 * @param fileName
	 *            文件名
	 * @param sheetName
	 *            工作表名字
	 * @param title
	 *            表头  
	 *            key-为英文表头 表要javabean对应所以要遵循如下规则
	 *            	根据带路径或不带路径的属性名获取属性值,即接受简单属性名,如userName等,又接受带路径的属性名,如student.department.name等
	 *            value-对应中文在excel中产生的表头名
	 * @return ByteArrayInputStream 字节流对象
	 * @throws Exception
	 *             传入数据为空
	 */
	public static ByteArrayInputStream list2EcelStream(List<T> list, int sheetSize,
			/* HttpServletRequest request,HttpServletResponse response, */String fileName, String sheetName,
			LinkedHashMap<String, String> title) throws Exception {
		byte[] data = null;
		ByteArrayOutputStream out = null;
		ByteArrayInputStream in = null;
		// 首先判断list里面是不是有值
		if (list == null || list.size() == 0) {
			// 如果空或者大小为0就直接return 或者抛出异常
			// return;
			throw new Exception("传入的数据为空或者大小为零");
		}
		try {
			// 前台页面显示下载
			/*
			 * setResp(request,response,fileName); outputStream =
			 * response.getOutputStream();
			 */
			out = new ByteArrayOutputStream();
			Workbook wb = new HSSFWorkbook();
			Sheet sheet = wb.createSheet(sheetName);
			fillVeticalSheet(sheet, list, title);
			wb.write(out);
			data = out.toByteArray();
			in = new ByteArrayInputStream(data);
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return in;
	}

	/**
	 * 缓存数据转Excel文件
	 * 
	 * @param list
	 *            传入的数据 对应的是map类型 key-value 这里的key 要与表头中的key规则一致
	 * @param sheetSize
	 *            工作表的大小
	 * @param request
	 *            网页传来的请求
	 * @param response
	 *            网页传来的相应
	 * @param fileName
	 *            文件名
	 * @param sheetName
	 *            工作表名字
	 * @param title
	 *            表头  
	 *            key-为英文表头 表要javabean对应所以要遵循如下规则
	 *            	根据带路径或不带路径的属性名获取属性值,即接受简单属性名,如userName等,又接受带路径的属性名,如student.department.name等
	 *            value-对应中文在excel中产生的表头名
	 */
	public static void map2ExcelFile(List<Map<String, Object>> list, int sheetSize, HttpServletRequest request,
			HttpServletResponse response, String fileName, String sheetName, LinkedHashMap<String, String> title) {
		OutputStream outputStream = null;
		// 首先判断list里面是不是有值
		if (list == null || list.size() == 0) {
			// 如果空或者大小为0就直接return 或者抛出异常
			return;
			// throw new Exception("传入的数据为空或者大小为零");
		}
		try {
			// 前台页面显示下载
			setResp(request, response, fileName);
			outputStream = response.getOutputStream();
			Workbook wb = new HSSFWorkbook();
			Sheet sheet = wb.createSheet(sheetName);
			fillVeticalSheet(sheet, list, title);
			wb.write(outputStream);
			if (wb != null) {
				wb.close();
			}
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			if (outputStream != null) {
				try {
					outputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 缓存数据转Excel文件
	 * 
	 * @param list
	 *            传入的数据 对应的是map类型 key-value 这里的key 要与表头key的规则一一致
	 * @param sheetSize
	 *            工作表的大小
	 * @param request
	 *            网页传来的请求
	 * @param response
	 *            网页传来的相应
	 * @param fileName
	 *            文件名
	 * @param sheetName
	 *            工作表名字
	 * @param title
	 *            表头  
	 *            key-为英文表头 表要javabean对应所以要遵循如下规则
	 *            	根据带路径或不带路径的属性名获取属性值,即接受简单属性名,如userName等,又接受带路径的属性名,如student.department.name等
	 *            value-对应中文在excel中产生的表头名
	 * @return ByteArrayInputStream 
	 * 			   字节流对象
	 * @throws Exception
	 *            传入数据为空
	 */
	public static ByteArrayInputStream map2ExcelSteam(List<Map<String, Object>> list, int sheetSize,
			/* HttpServletRequest request,HttpServletResponse response, */String fileName, String sheetName,
			LinkedHashMap<String, String> title) throws Exception {
		byte[] data = null;
		ByteArrayOutputStream out = null;
		ByteArrayInputStream in = null;
		// 首先判断list里面是不是有值
		if (list == null || list.size() == 0) {
			// 如果空或者大小为0就直接return 或者抛出异常
			// return;
			throw new Exception("传入的数据为空或者大小为零");
		}
		try {
			// 前台页面显示下载
			/*
			 * setResp(request,response,fileName); outputStream =
			 * response.getOutputStream();
			 */
			out = new ByteArrayOutputStream();
			Workbook wb = new HSSFWorkbook();
			Sheet sheet = wb.createSheet(sheetName);
			fillVeticalSheet(sheet, list, title);
			wb.write(out);
			data = out.toByteArray();
			in = new ByteArrayInputStream(data);
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return in;
	}

	/**
	 * 下载使用的设置编码格式
	 * 
	 * @param request
	 * @param response
	 * @param fileName
	 *            文件名
	 */
	private static void setResp(HttpServletRequest request, HttpServletResponse response, String fileName) {
		// 获取用户使用的浏览器,系统 内核版本等信息
		final String userAgent = request.getHeader("USER-AGENT");
		response.reset();
		// response.setContentType("application/vnd.ms-excel");
		response.setContentType("application/x-msdownload");
		try {
			String finalFileName = null;
			if (StringUtils.contains(userAgent, "MSIE")) {// IE
				finalFileName = URLEncoder.encode(fileName, "UTF8");
			} else if (StringUtils.contains(userAgent, "Mozilla")) {// chrome firefox
				finalFileName = new String(fileName.getBytes(), "ISO8859-1");
			} else {
				finalFileName = URLEncoder.encode(fileName, "UTF8");
			}
			String dataStr = new SimpleDateFormat("yyyMMddHHmmss").format(new Date()).toString();
			// 设置浏览器下载提示,不是直接在浏览器中打开文件
			response.setHeader("COntent-Disposition", "attachment; filename=" + finalFileName + "_" + dataStr + ".xls");
		} catch (UnsupportedEncodingException e) {// 编码异常
			e.printStackTrace();
		}
	}

	/**
	 * 设置表头 数据
	 * 
	 * @param sheet
	 *            工作表对象
	 * @param list
	 *            存放对象的list
	 * @param title
	 *            中英英文对应的表头数据
	 */
	private static void fillVeticalSheet(Sheet sheet, List<T> list, LinkedHashMap<String, String> title) {
		if (null == list || null == title) {
			return;
		}
		// 定义存放英文字段名和中文字段名称的数组
		String[] enFields = new String[title.size()];
		String[] cnFields = new String[title.size()];
		// 填充数组
		int count = 0;
		for (Entry<String, String> entry : title.entrySet()) {
			enFields[count] = entry.getKey();
			cnFields[count] = entry.getValue();
			count++;
		}
		// 填充表头
		Row row = sheet.createRow(0);
		for (int j = 0; j < cnFields.length; j++) {
			Cell cell = row.createCell(j);
			cell.setCellValue(cnFields[j]);
		}
		// 填充数据
		for (int i = 0; i < list.size(); i++) {
			T item = list.get(i);
			row = sheet.createRow(i + 1);
			for (int j = 0; j < enFields.length; j++) {
				Object objValue = getFieldValueByNameSequence(enFields[j], item);
				if (objValue instanceof String) {
					row.createCell(j).setCellValue((String) objValue);
				} else if (objValue instanceof Double) {
					row.createCell(j).setCellValue((Double) objValue);
				} else if (objValue instanceof RichTextString) {
					row.createCell(j).setCellValue((RichTextString) objValue);
				} else if (objValue instanceof Date) {
					row.createCell(j).setCellValue((Date) objValue);
				} else if (objValue instanceof Boolean) {
					row.createCell(j).setCellValue((Boolean) objValue);
				}
			}
		}
	}

	/**
	 * 设置表头 数据
	 * 
	 * @param sheet
	 *            工作表对象
	 * @param list
	 *            防止list 中 map的结构为Key为alue的对应字段
	 * @param title
	 *            中英英文对应的表头数据
	 */
	private static void fillVeticalSheet(Sheet sheet, List<Map<String, Object>> list, Map<String, String> title) {
		if (null == list) {
			return;
		}
		// 解析list 将 标题和字段解析出来
		String[] enFields = new String[title.size()];
		String[] cnFields = new String[title.size()];
		int count = 0;
		for (Entry<String, String> entry : title.entrySet()) {
			enFields[count] = entry.getKey();
			cnFields[count] = entry.getValue();
			count++;
		}
		// 填充表头
		Row row = sheet.createRow(0);
		for (int j = 0; j < cnFields.length; j++) {
			Cell cell = row.createCell(j);
			cell.setCellValue(cnFields[j]);
		}
		// 填充数据
		int i = 1;
		for (Map<String, Object> map : list) {
			row = sheet.createRow(i + 1);
			for (int j = 0; j < cnFields.length; j++) {
				Object objValue = map.get(enFields[j]);
				if (objValue instanceof String) {
					row.createCell(j).setCellValue((String) objValue);
				} else if (objValue instanceof Double) {
					row.createCell(j).setCellValue((Double) objValue);
				} else if (objValue instanceof RichTextString) {
					row.createCell(j).setCellValue((RichTextString) objValue);
				} else if (objValue instanceof Date) {
					row.createCell(j).setCellValue((Date) objValue);
				} else if (objValue instanceof Boolean) {
					row.createCell(j).setCellValue((Boolean) objValue);
				}
			}
		}
	}

	/**
	 * 根据带路径或不带路径的属性名获取属性值,即接受简单属性名,如userName等,又接受带路径的属性名,如student.department.
     * name等
	 * 
	 * @param fieldNameSequence
	 *            对象名
	 * @param o
	 *            对象
	 * @return 对象的值
	 */
	private static Object getFieldValueByNameSequence(String fieldNameSequence, Object o) {

		Object value = null;
		try {
			// 将fieldNameSequence进行拆分
			String[] attributes = fieldNameSequence.split("\\.");
			if (attributes.length == 1) {
				value = PropertyUtils.getProperty(o, fieldNameSequence);

			} else {
				// 根据属性名获取属性对象
				Object fieldObj = PropertyUtils.getProperty(o, attributes[0]);

				String subFieldNameSequence = fieldNameSequence.substring(fieldNameSequence.indexOf(".") + 1);
				value = getFieldValueByNameSequence(subFieldNameSequence, fieldObj);
			}

			if (value instanceof Date) {
				value = new SimpleDateFormat("yyyy-MM-dd").format(value).toString();
			}

			// if (value.toString().endsWith(".0000")) {
			// String txt =value.toString();
			// value = txt.substring(0, txt.lastIndexOf("."));
			// }
		} catch (Exception e) {
			e.printStackTrace();
		}
		return value;
	}
}

 类似资料: