1. 程式人生 > >poi用jdom解析xml檔案方式定製Excel模板

poi用jdom解析xml檔案方式定製Excel模板

java程式碼

package com.td.store.utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List;

import org.apache.poi.hssf.usermodel.DVConstraint;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFDataValidation;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STIconSetType;

public class ExcelUtil {

	public static void main(String[] ager){
		createTemplate("shangping.xml");
	}
	
	
	//定製生成使用者模板資訊
	/**
	 * path 是模板資訊  XML檔案的路徑  模板資訊統一存放在專案下template資料夾下  傳檔名稱即可
	 * 
	 * **/
	public static void createTemplate(String path){
		//獲取模板配置資訊的XML檔案路徑
		String realPath = System.getProperty("user.dir")+"/template/"+path;
		File file = new File(realPath);
		//用jdom解析XML模板配置檔案
		SAXBuilder builder =  new SAXBuilder();
		try {
			//解析XML檔案
			Document parse = builder.build(file);
			//建立工作薄
			HSSFWorkbook wb =  new HSSFWorkbook();
			//建立sheet工作表  引數給工作表起個名
			HSSFSheet sheet = wb.createSheet("sheet0");
			
			//獲取XML檔案根節點   (excel節點)
			Element rootElement = parse.getRootElement();
			//獲取模板名稱
			String templateName = rootElement.getAttribute("name").getValue();
			//變數行號
			int rownum = 0;
			//變數列號
			int j = 0;
			//獲取colgroup節點物件
			Element colgroup = rootElement.getChild("colgroup");
			//設定列寬
			setColumnWidth(sheet,colgroup);
			
			//設定標題
			//獲取標題節點
			Element title = rootElement.getChild("title");
			//獲取標題內的tr節點list
			List<Element> trs = title.getChildren("tr");
			//迴圈trs節點
			for (int i = 0; i < trs.size(); i++) {
				//獲取單個tr節點物件
				Element tr = trs.get(i);
				//獲取tr裡面的tds物件 (也可能是個集合)
				List<Element> tds = tr.getChildren("td");
				//建立sheet裡面的一行
				HSSFRow row = sheet.createRow(rownum);
				//建立單元格格式
				CellStyle cStyle = wb.createCellStyle();
				//迴圈每一個td
				for (j = 0; j < tds.size(); j++) {
					//獲取td
					Element td = tds.get(j);
					//建立單元格物件
					HSSFCell cell = row.createCell(j);
					//獲取td裡面的屬性物件
					Attribute rowspan = td.getAttribute("rowspan");
					Attribute colspan = td.getAttribute("colspan");
					Attribute value = td.getAttribute("value");
					
					//獲取value屬性的值 
					String val = value.getValue();
					//給cell設定值
					cell.setCellValue(val);
					//Excel單元格列計數從0開始  需要轉換下
					int rspan = rowspan.getIntValue()-1;
					int cspan = colspan.getIntValue()-1;
					
					//設定字型
					HSSFFont font = wb.createFont();
					font.setFontName("仿宋_GB2312");
					font.setFontHeightInPoints((short)12);
					cStyle.setFont(font); 
					//合併單元格
					sheet.addMergedRegion(new CellRangeAddress(rspan, rspan, 0, cspan));
				}
				rownum++;
			}
			
			//設定表頭資訊
			//獲取表頭物件
			Element theah = rootElement.getChild("thead");
			trs = theah.getChildren("tr");
			for (int i = 0; i < trs.size(); i++) {
				Element tr = trs.get(i);
				HSSFRow row = sheet.createRow(rownum);
				List<Element> ths = tr.getChildren("th");
				for (j=0; j < ths.size(); j++) {
					Element th = ths.get(j);
					Attribute valueAttr = th.getAttribute("value");
					HSSFCell cell = row.createCell(j);
					String value = valueAttr.getValue();
					cell.setCellValue(value);
				}
				rownum++;
			}
			
			//設定資料區域樣式
			Element tbody = rootElement.getChild("tbody");
			Element tr = tbody.getChild("tr");
			//獲取配置檔案中,需要設定樣式的行數
			int repeat = tr.getAttribute("repeat").getIntValue();
			
			//獲取tr下面的td 每一列對應的屬性
			List<Element> tds = tr.getChildren("td");
			for (int i = 0; i < repeat; i++) {
				//建立行物件
				HSSFRow row = sheet.createRow(rownum);
				for(j=0;j<tds.size();j++){
					Element td = tds.get(j);
					HSSFCell cell = row.createCell(j);
					setType(wb,cell,td);
				}
				rownum++;
			}
			
			File tempFile = new File("E:\\"+templateName+".xls");
			OutputStream stream = new FileOutputStream(tempFile);
			wb.write(stream);
			//關閉流
			stream.close();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	
	//設定單元格樣式
	private static void setType(HSSFWorkbook wb, HSSFCell cell, Element td) {
		//獲取XML TD物件的type屬性
		Attribute typeAttr = td.getAttribute("type");
		//獲取type屬性值,代表資料型別
		String type = typeAttr.getValue();
		//單元格樣式
		HSSFDataFormat format = wb.createDataFormat();
		HSSFCellStyle cellStyle = wb.createCellStyle();
		//判斷節點型別屬性
		if("string".equals(type)){
			//設定預設值
			cell.setCellValue("");
			cell.setCellType(CellType.STRING);
		}else if("double".equals(type)){
			cell.setCellType(CellType.NUMERIC);
		}else if("int".equals(type)){
			cell.setCellValue(0);
			cell.setCellType(CellType.NUMERIC);
		}else if("enum".equals(type)){
			CellRangeAddressList regions = 
					new CellRangeAddressList(cell.getRowIndex(), cell.getRowIndex(), 
							cell.getColumnIndex(), cell.getColumnIndex());
			Attribute enumAttr = td.getAttribute("format");
			String enumValue = enumAttr.getValue();
			DVConstraint constraint = 
					DVConstraint.createExplicitListConstraint(enumValue.split(","));
			HSSFDataValidation dataValidation = new HSSFDataValidation(regions, constraint);
			wb.getSheetAt(0).addValidationData(dataValidation);
		}
		cell.setCellStyle(cellStyle);
	}

	//設定列寬的方法
	private static void setColumnWidth(HSSFSheet sheet,Element colgroup){
		List<Element> cols = colgroup.getChildren("col");
		for (int i = 0; i < cols.size(); i++) {
			Element col = cols.get(i);
			Attribute width = col.getAttribute("width");
			//獲取到配置的寬度,擷取計量單位  是em或者px
			String unit = width.getValue().replaceAll("[0-9,\\.]", "");
			//獲取到配置的寬度,擷取設定值
			String value = width.getValue().replaceAll(unit, "");
			int v = 0;
			//判斷單位為空 或者為em  這裡我不用String的isEmpty判斷空是因為如果String是null,會報空指標異常,但是我不知道什麼問題,StringUtils在lang包下面沒找到,先用String的isEmpty方法
			//同時計量單位為px時進入方法
			if(unit.isEmpty()||"px".equals(unit)){
				//poi寬度轉換為excel寬度
				v = Math.round(Float.parseFloat(value)*37F);
			}else if("em".equals(unit)){
				v = Math.round(Float.parseFloat(value)*267.5F);
			}
			//設定進去值
			sheet.setColumnWidth(i, v);
		}
	}
}

XML模板

<?xml version="1.0" encoding="UTF-8"?>
<excel id="shangping" code="shangping" name="商品資訊模板">
	<!-- 列寬資訊設定 -->
	<colgroup>
		<col index="A" width="20em"></col>
		<col index="B" width="20em"></col>
		<col index="C" width="20em"></col>
		<col index="D" width="20em"></col>
		<col index="E" width="20em"></col>
		<col index="F" width="20em"></col>
		<col index="G" width="20em"></col>
	</colgroup>
	
	<!-- 表頭標題資訊設定 -->
	<title>
		<tr heigth="16px">
			<td rowspan="1" colspan="7" value="商品資訊匯入"></td>
		</tr>
	</title>
	
	<!-- 表頭單元格每列名稱 -->
	<thead>
        <tr height="16px">
        	<th value="商品名" />
            <th value="市場價" />
            <th value="售價" />
            <th value="數量" />
            <th value="分類" />
            <th value="商品簡述" />
           	<th value="圖片路徑"></th>
        </tr>
    </thead>
    
    <!-- 每列輸入資訊指定型別  repeat屬性代表多少行需要遵循設定的樣式-->
    <tbody>
        <tr height="16px" repeat="30">
            <td type="string" maxlength="40" /><!--商品名稱 -->
            <td type="double" /><!--市場價 -->
            <td type="double" /><!--售價 -->
            <td type="int" /><!--數量 -->
            <td type="enum" format="1,2,3,4,5,6,7,8,9,10" /><!--分類 -->
            <td type="string" maxlength="100" /><!--商品簡述 -->
            <td type="string" maxlength="100" /><!--圖片全名 -->
        </tr>
    </tbody>
	
	
	
	
</excel>