java 导出excel

public class ExportReportForExcel implements IExportReport{


/**

* Function 生成Excel报表 CreateTime 2014年7月22日

* @author yyh

* @version 1.2.0

* @param HttpServletRequest

*            request

* @param HttpServletResponse

*            response

* @param Map

*            <?,?> reportInfo 生成报表所需要的数据

*/

@Override

public void createReport(HttpServletRequest request,

HttpServletResponse response, Map<?, ?> reportInfo)

throws Exception {

String[] tableList = (String[]) reportInfo.get("tableList");

// 判断生成数据是否为空

if (tableList == null || tableList.length < 0) {

System.out.println("没有导出数据");

}


// 设置文件响应信息

String showFileName = URLEncoder.encode(reportInfo.get("title") + ".xls", "UTF-8");

showFileName = new String(showFileName.getBytes("iso8859-1"), "gb2312");


// 定义输出类型

response.reset();

response.setContentType("application/msexcel");

response.setHeader("Pragma", "public");

response.setHeader("Cache-Control", "max-age=30");

response.setHeader("Content-disposition", "attachment; filename="

+ new String(showFileName.getBytes("gb2312"), "iso8859-1"));


// 生成Excel并响应客户端

ServletOutputStream out = response.getOutputStream();

ByteArrayOutputStream bos = (ByteArrayOutputStream) getStream(reportInfo);

response.setContentLength(bos.size());

bos.writeTo(out);

out.close();

out.flush();

bos.close();

bos.flush();

}

/**

* Function 构建报表数据 CreateTime 2014年7月22日

* @author yyh

* @version 1.2.0

* @param reportInfo

*            生成报表所需要的数据

* @return OutputStream

* @throws IOException

* @throws BadElementException

*/

private OutputStream getStream(Map<?, ?> reportInfo) throws IOException,

BadElementException {


// 实例化HSSFWorkbook

HSSFWorkbook wb = new HSSFWorkbook();

HSSFSheet sheet = wb.createSheet("" + reportInfo.get("title"));


// 创建表头样式

HSSFCellStyle cellStyle = wb.createCellStyle();

// 文本位置(居中)

cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);

// 设置字体

HSSFFont font = wb.createFont();

font.setFontName("宋体");

font.setFontHeightInPoints((short) 10);// 字体大小

font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);// 加粗

// font.setColor(HSSFColor.BLUE.index);//字体颜色

cellStyle.setFont(font);

cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);

cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);

cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);

cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);


String[] tableCaptionList = (String[]) reportInfo.get("tableCaptionList");

String[] tableList = (String[]) reportInfo.get("tableList");

String[] tableColList = (String[]) reportInfo.get("tableColList"); // 记录每一个<table>的最大列数


int rowIndex = 0;

HSSFRow row = null;

HSSFCell cell = null;

BufferedImage bufferImg = null;

for (int a = 0; a < tableColList.length; a++) {

int tableRowIndex = 0;

String colInfo = tableColList[a];

String colStr = colInfo.indexOf("#PAGINATION#") >= 0 ? colInfo.substring(0,colInfo.indexOf("#PAGINATION#")) : colInfo;

colStr = colStr.indexOf("#NOBORDER#") >= 0 ? colStr.substring(0,colStr.indexOf("#PAGINATION#")) : colStr;

int col = Integer.parseInt(colStr);


boolean flag = false;  // 判断是否存在图片

if (tableCaptionList.length > 0) {


sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 0, col-1));// 合并   --> 用于跨行、跨列

row = sheet.createRow(rowIndex);

cell = row.createCell(a);

cell.setCellValue(tableCaptionList[a]);

cell.setCellStyle(cellStyle);

flag = tableCaptionList[a].indexOf("#IMG#") >= 0 ? true : false;

}

if (col > 0) {


if (rowIndex > 0) {

rowIndex++;

}

String[] rows = null;

Object[][]  cellInfo = null;

for (int j = 0; j < tableList.length; j++) {

if (a == j) {

rows = tableList[j].split("#ROW#");


// 截取<table>对应行<row>对应列<td>的值存入二维数组

for (int k = 0; k < rows.length; k++) {

String tds[] = rows[k].split("#TD#");

if (cellInfo == null) {

cellInfo = new Object[rows.length][tds.length];

}

cellInfo[k] = tds;

}


/*

* 数组rowsInfo记录<table>对应位置的状态信息(指<td>的状态)

* 1、跨行标识:(1111/1122)   如:状态1111 表示该<td>被当前行所跨;状态1122  表示该<td>被当前行之前的行所跨

* 2、跨列标识:(2222/2233)   如:状态2222 表示该<td>是所跨列中最后一列之前的列;状态2233  表示该<td>是所跨列中最后的一列

* 3、跨行且跨列标志:(1111/1122)  为了方便操作,使用跨行标识

* 4、不跨行且不跨列标志:0 (数组的默认值)

* 说明:如跨行标识:(1111/1122)使用两种标志是为了方便识别某<td>的状态,与使用一种状态(如1111)效果一样

*/

int [][] rowsInfo = new int[rows.length][col];

// 生成excel数据

for (int rNum = 0; rNum < cellInfo.length; rNum++) {


if (tableCaptionList.length == 0 && rNum == 0) {

rowIndex--;

}

row = sheet.createRow(++rowIndex);

Object[] dataExcel = cellInfo[rNum];

boolean preHasRowSpan = false;// 记录当前行是否存在跨行(针对当前行被之前的行所跨的情况)

for (int l = 0; l < col ; l++) {

if (rowsInfo[tableRowIndex][l]==1122) { 

preHasRowSpan = true;

break;

}

}

/*

* currentRow: 用于保存当前行对应位置的实时状态信息

* 如:currentRow[0]=1122       表示 当前行 的第一个<td>已被         前面的行     所占用

* 如:currentRow[0]=1234       表示 当前行 的第一个<td>已被         当前行          占用

* 如:currentRow[0]=0               表示 当前行 的第一个<td>未被占用

*  int[] currentRow = rowsInfo[tableRowIndex]; 

*  数组为对象是引用传递,故而重新new一个数组

*/

int[] currentRow = new int[rowsInfo[tableRowIndex].length] ; 

for (int i = 0; i < currentRow.length; i++) {

currentRow[i] = rowsInfo[tableRowIndex][i];

}

for (int cNum = 0; cNum < dataExcel.length; cNum++) {

String data = dataExcel[cNum].toString();

if (flag) {// 图片

ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();


// ImageIO.read(参数):

// 参数是File时,只能是本地路径,如:e:/login.jpg

// 参数是URL时,可以是远程路径 ,

// 如:http://localhost:8080/eam/temp/login.jpg

bufferImg = ImageIO.read(new URL(URLDecoder.decode(data.trim(),"utf-8")));


ImageIO.write(bufferImg,"jpg",byteArrayOut);


HSSFPatriarch patriarch = sheet.createDrawingPatriarch();

HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 512, 255,(short) 1, 1,(short) 10, 20);

// 插入图片

patriarch.createPicture(anchor,wb.addPicture(byteArrayOut.toByteArray(),HSSFWorkbook.PICTURE_TYPE_JPEG));


} else {


String value = data.indexOf("#COLSPAN#") >= 0 ? data.substring(0,data.indexOf("#COLSPAN#")) : data;

value = value.indexOf("#ROWSPAN#") >= 0 ? value.substring(0,value.indexOf("#ROWSPAN#")) : value;

value = value.indexOf("#ALIGN#") >= 0 ? value.substring(value.indexOf("#ALIGN#")+7) : value;

value = value.indexOf("#VALIGN#") >= 0 ? value.substring(value.indexOf("#VALIGN#")+8) : value;


int tempNum = cNum; // 标识当前<td>在写入的excel中的位置

// 获取该<td>在Excel中(Cell)的位置

tempNum = getCurrentCellIndex(

tableRowIndex, col,

preHasRowSpan,

currentRow, cNum,

tempNum);


// 跨行、跨列

setRowSpanAndColSpan(sheet,

rowIndex,

tableRowIndex,

rowsInfo, currentRow,

data, tempNum);

cellStyle = setAlign(wb, data);// 对齐方式 (针对单个的Cell)

cell = row.createCell(tempNum);// 为该<td>创建对应Cell

cell.setCellValue(" " + value);

cell.setCellStyle(cellStyle);

}

}

tableRowIndex++;

}

// 

}

}

}

}


// 写入字节流

ByteArrayOutputStream bos = new ByteArrayOutputStream();

wb.write(bos);


// 返回bos

return bos;

}

/**

*  水平对齐方式、垂直对齐方式 控制

* @param cellStyle   样式

* @param data <td>的内容

*/

private HSSFCellStyle setAlign(HSSFWorkbook wb , String data) {

String alignStr = data;


HSSFCellStyle cellStyle = wb.createCellStyle(); // 创建表格体样式

// 默认

cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 水平居中

cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); // 垂直居中

cellStyle.setWrapText(true); // 自动换行

cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);

cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);

cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);

cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);

// 水平对齐方式:居中、右、左对齐

if (alignStr.indexOf("#ALIGN#") >=0) {

String align = alignStr.substring(0, alignStr.indexOf("#ALIGN#")).trim();

if ("right".equals(align)) {

cellStyle.setAlignment(HSSFCellStyle.ALIGN_RIGHT);

}else if ("left".equals(align)) {

cellStyle.setAlignment(HSSFCellStyle.ALIGN_LEFT);

}else if ("center".equals(align)) {

cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);

}

}

// 垂直对齐方式:

if (alignStr.indexOf("#VALIGN#") >=0) {

String vAlign = alignStr.substring(alignStr.indexOf("#ALIGN#")>=0?(alignStr.indexOf("#ALIGN#")+7):0, alignStr.indexOf("#VALIGN#")).trim();

if ("top".equals(vAlign)) {

cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_TOP);

}else if ("bottom".equals(vAlign)) {

cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_BOTTOM);

}else if ("middle".equals(vAlign)) {

cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

}

}

return cellStyle;

}


/**

* 获取该<row>下当前<td>在Excel中(Cell)的位置(解决跨行跨列情况中Cell下标的控制)

* @param tableRowIndex 标识二维数组    rowsInfo[row][col]   的外层下标

* @param col 标识<table>的最大列数

* @param preHasRowSpan 记录当前行<row>是否存在跨行(针对当前行被之前的行所跨的情况)

* @param currentRow 记录当前行<row>对应位置的实时状态信息(指<td>的状态)

* @param cNum

* @param tempNum 标识当前<td>在写入的Excel(Cell)中的位置

* @return

* @author yyh     createTime 2014-07-22

*/

private int getCurrentCellIndex(int tableRowIndex, int col,

boolean preHasRowSpan, int[] currentRow, int cNum, int tempNum) {

if (preHasRowSpan) {

if (tableRowIndex > 0) {

int usedNum = 0; //  记录当前行被使用(跨行或跨列)的最后一个<td>的下标

if (cNum==0) {

for (int i = 0; i < col ; i++) {

if (currentRow[i]==1122) { 

usedNum ++;

continue;

}

break;

}

}else{

for (int i = 0; i < col ; i++) {

if (currentRow[i]==1234) { 

usedNum = i;

}

}

usedNum ++; //  +1 标识当前被使用的最后一个td的下一个td的下标

int num = 0;

for (int i = 0; i < col ; i++) {

if (currentRow[usedNum+i]==1122) { // 判断当前被使用的最后一个td的下一个td是否跨行

num ++;

continue;

}

break;

}

usedNum = usedNum + num;

}

tempNum = usedNum;

}

}else{


for (int i = 0; i < col ; i++) {

if (currentRow[i]==1234) { 

tempNum = i+1;

}

}

}

return tempNum;

}


/**

* Excel 跨行跨列控制

* @param sheet sheet对象

* @param rowIndex 标识sheet的行下标

* @param tableRowIndex 标识二维数组    rowsInfo[row][col]   的外层下标

* @param rowsInfo 记录<table>对应位置的状态信息(指<td>的状态)

* @param currentRow 记录当前行<row>对应位置的实时状态信息(指<td>的状态)

* @param data <td>的内容

* @param tempNum 标识当前<td>在写入的Excel(Cell)中的位置

* @author yyh     createTime 2014-07-22

*/

private void setRowSpanAndColSpan(HSSFSheet sheet, int rowIndex,

int tableRowIndex, int[][] rowsInfo, int[] currentRow, String data,

int tempNum) {

int colspan = 0;

int rowspan = 0;

// 跨行、跨列

if (data.indexOf("#COLSPAN#") >= 0 && data.indexOf("#ROWSPAN#") >= 0) {

colspan = Integer.parseInt(data.substring(data.indexOf("#COLSPAN#")+9).trim());

rowspan = Integer.parseInt(data.substring(data.indexOf("#ROWSPAN#")+9 , data.indexOf("#COLSPAN#")).trim());

}else if (data.indexOf("#ROWSPAN#") >= 0) {// 跨行

rowspan = Integer.parseInt(data.substring(data.indexOf("#ROWSPAN#")+9).trim());

}else if (data.indexOf("#COLSPAN#") >= 0) {// 跨列

colspan = Integer.parseInt(data.substring(data.indexOf("#COLSPAN#")+9).trim());

}

if (rowspan > 1 && colspan > 1) { // 跨行、跨列

// 跨行且跨列   使用跨行的状态标志

sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex+rowspan-1, tempNum, tempNum+colspan-1));

for (int l = 0; l < rowspan; l++) {

for (int i = 0; i < colspan; i++) {

currentRow[tempNum+i] = 1234;

if (l > 0) {

rowsInfo[tableRowIndex+l][tempNum+i] = 1122;

}else{

rowsInfo[tableRowIndex+l][tempNum+i] = 1111; // 用于标识跨行的第一行

}

}

}

}else if (rowspan > 1){ //只跨行的单元格合并方法

sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex+rowspan-1, tempNum, tempNum));

for (int i = 0; i < rowspan; i++) {

if (i > 0) {

rowsInfo[tableRowIndex+i][tempNum] = 1122;

}else{

rowsInfo[tableRowIndex+i][tempNum] = 1111; // 用于标识跨行的第一行

}

}

currentRow[tempNum] = 1234; // 用于标识当前位置已经被占用

}else if (colspan > 1){ //只跨列的单元格合并方法


sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, tempNum, tempNum+colspan-1));

for (int i = 0; i < colspan; i++) {

currentRow[tempNum+i] = 1234; // 用于标识当前位置已经被占用

if (i==(colspan-1)) {

rowsInfo[tableRowIndex][tempNum+i] = 2233; // 用于标识跨列的最后一列

}else{

rowsInfo[tableRowIndex][tempNum+i] = 2222;

}

}

}else{ // 不跨行、不跨列

currentRow[tempNum]=1234;

}

}



}


你可能感兴趣的:(java 导出excel)