根据table导出Excel

2 篇文章 0 订阅

最近写一个html的table表格导出excel的功能,由于表格是定制的,即表格的行列都不是固定的,包括单元格跨行跨列。用js导出excel需要依赖于IE浏览器,兼容性不太好。于是就写了个java类来导出html的table到excel。

代码如下:

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

/**
 * 根据Table生成Excel
 * @author zhy 
 * @version 1.0
 * @since 2015-3-20
 * 
 */
public class Excel {

	private static final Logger	log		= Logger.getLogger( Excel.class );
	/*导出文件名*/
	private String				name;
	private String				html;
	private Table				table;
	private HttpServletResponse	response;
	/*数据集*/
	private List<List<Node>>	data	= new ArrayList<List<Node>>();

	public Excel ( String html, HttpServletResponse response ) {
		super();
		this.html = html;
		this.response = response;
		parse();
	}

	public Excel ( String name, String html, HttpServletResponse response ) {
		super();
		this.name = name;
		this.html = html;
		this.response = response;
		parse();
	}

	public Excel ( String name, Table table, HttpServletResponse response ) {
		super();
		this.name = name;
		this.table = table;
		this.response = response;
		parseTable();
	}

	/**
	 * 解析html
	 */
	void parse() {
		// 补数据 合并单元格用 可以补html也可以补node结果集
		if ( log.isDebugEnabled() )
			log.debug( "/- Excel - html :" + html );
		Document doc = Jsoup.parse( html );
		// 遍历thead
		Elements trs = doc.select( "thead tr" );
		List<Node> thead = null;
		for ( int i = 0; i < trs.size(); i++ ) {
			thead = new ArrayList<Node>();
			Node cell;
			Elements ths = trs.get( i ).select( "th" );
			for ( int j = 0; j < ths.size(); j++ ) {
				Element th = ths.get( j );
				int rs = span( th, "rowspan" );
				int cs = span( th, "colspan" );
				cell = new Node( rs, cs, th.text() );
				thead.add( cell );
			}
			if ( thead != null )
				data.add( thead );
		}
		// 遍历tbody
		trs = doc.select( "tbody tr" );
		List<Node> tbody = null;
		for ( int i = 0; i < trs.size(); i++ ) {
			tbody = new ArrayList<Node>();
			Node cell;
			Elements tds = trs.get( i ).select( "td" );
			for ( int j = 0; j < tds.size(); j++ ) {
				Element td = tds.get( j );
				int rs = span( td, "rowspan" );
				int cs = span( td, "colspan" );
				cell = new Node( rs, cs, td.text() );
				tbody.add( cell );
			}
			if ( tbody != null )
				data.add( tbody );
		}
		// repair 导出excel合并单元格用
		for ( int i = 0; i < data.size(); i++ ) {
			List<Node> records = data.get( i );
			for ( int j = 0; j < records.size(); j++ ) {
				Node node = records.get( j );
				if ( node.cs > 1 ) {
					// 补列
					for ( int k = 1; k < node.cs; k++ ) {
						Node _node = new Node( node.value );
						records.add( j + k, _node );
					}
				}
				if ( node.rs > 1 ) {
					// 补行
					for ( int k = 1; k < node.rs; k++ ) {
						Node _node = new Node( node.value );
						data.get( i + k ).add( j, _node );
					}
				}
			}
		}
		if ( log.isDebugEnabled() )
			log.debug( "/- Excel - data:" + data );
	}

	/**
	 * 解析Table
	 */
	void parseTable() {
	}

	/**
	 * 表格的单元格
	 */
	class Node {

		/*跨行*/
		private int		rs	= 1;
		/*跨列*/
		private int		cs	= 1;
		/*value*/
		private String	value;

		/*是否数字*/
		// private boolean isNumber = false;
		public Node ( String value ) {
			super();
			this.value = value;
		}

		public Node ( int rs, int cs, String value ) {
			super();
			this.rs = rs;
			this.cs = cs;
			this.value = value;
		}

		public int rs() {
			return rs;
		}

		public int cs() {
			return cs;
		}

		public boolean isNumber() {
			return value.matches( "[0-9]+" );
		}

		public String value() {
			return value;
		}

		@Override
		public String toString() {
			return "{rs=" + rs + ", cs=" + cs + ", value=" + value + ", isNumber=" + isNumber()
				+ "}";
		}
	}

	/*生成excel*/
	public void write() {
		if ( data.isEmpty() ) {
			log.error( "/- Excel data is empty." );
			return;
		}
		// 创建Excel的工作书册 Workbook,对应到一个excel文档
		XSSFWorkbook wb = new XSSFWorkbook();
		// 创建Excel的工作sheet,对应到一个excel文档的tab
		XSSFSheet sheet = wb.createSheet( "sheet1" );
		XSSFCellStyle stringStyle = wb.createCellStyle(); // 样式对象
		stringStyle.setVerticalAlignment( XSSFCellStyle.VERTICAL_CENTER );// 垂直
		stringStyle.setAlignment( XSSFCellStyle.ALIGN_CENTER );// 水平
		stringStyle.setBorderTop( XSSFCellStyle.BORDER_THIN );
		stringStyle.setBorderBottom( XSSFCellStyle.BORDER_THIN );
		stringStyle.setBorderLeft( XSSFCellStyle.BORDER_THIN );
		stringStyle.setBorderRight( XSSFCellStyle.BORDER_THIN );
		XSSFCellStyle numberStyle = wb.createCellStyle(); // 样式对象
		numberStyle.setVerticalAlignment( XSSFCellStyle.VERTICAL_CENTER );// 垂直
		numberStyle.setAlignment( XSSFCellStyle.ALIGN_RIGHT );// 水平
		numberStyle.setBorderTop( XSSFCellStyle.BORDER_THIN );
		numberStyle.setBorderBottom( XSSFCellStyle.BORDER_THIN );
		numberStyle.setBorderLeft( XSSFCellStyle.BORDER_THIN );
		numberStyle.setBorderRight( XSSFCellStyle.BORDER_THIN );
		/*此处数据格式为1,234:每三位带,*/
		// XSSFDataFormat df = wb.createDataFormat(); // 此处设置数据格式
		// numberStyle.setDataFormat( df.getFormat( "#,#0" ) );
		// 创建Excel的sheet的一行
		for ( int i = 0; i < data.size(); i++ ) {
			XSSFRow row = sheet.createRow( i );
			// 创建一个Excel的单元格
			List<Node> records = data.get( i );
			for ( int j = 0; j < records.size(); j++ ) {
				Node node = records.get( j );
				if ( node.rs > 1 || node.cs > 1 ) {
					// 合并单元格(startRow,endRow,startColumn,endColumn)
					sheet.addMergedRegion( new CellRangeAddress( i, i + ( node.rs - 1 ), j, j
						+ ( node.cs - 1 ) ) );
				}
				XSSFCell cell = row.createCell( j );
				// 给Excel的单元格设置样式和赋值
				if ( node.isNumber() ) {
					cell.setCellStyle( numberStyle );
					cell.setCellValue( Integer.parseInt( node.value() ) );
				} else {
					cell.setCellStyle( stringStyle );
					cell.setCellValue( node.value() );
				}
			}
		}
		OutputStream os = null;
		try {
			response.reset(); 
			response.setContentType( "application/x-msdownload" );
			response.setHeader( "Content-Disposition", "attachment; filename="
				+ ( name == null ? "report" : name ) + ".xlsx" );
			os = response.getOutputStream();
			wb.write( os );
			os.flush();
		} catch ( IOException e ) {
			log.error( "/- Excel - error:", e );
		} finally {
			if ( os != null ) {
				try {
					os.close();
				} catch ( IOException e ) {
					e.printStackTrace();
				}
			}
		}
	}

	private int span( Element e, String attr ) {
		return "".equals( e.attr( attr ) ) ? 1 : Integer.parseInt( e.attr( attr ) );
	}

	public String getName() {
		return name;
	}

	public void setName( String name ) {
		this.name = name;
	}

	public String getHtml() {
		return html;
	}

	public void setHtml( String html ) {
		this.html = html;
	}

	public Table getTable() {
		return table;
	}

	public void setTable( Table table ) {
		this.table = table;
	}

}
注:需要依赖  jsoup   Apache POI

jsoup is a Java library for working with real-world HTML. It provides a very convenient API for extracting and manipulating data, using the best of DOM, CSS, and jquery-like methods.

Apache POI - the Java API for Microsoft Documents.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值