码迷,mamicode.com
首页 > Web开发 > 详细

框架 day50 BOS项目 4 批量导入(ocupload插件,pinyin4J)/POI解析Excel/Combobox下拉框/分区组合条件分页查询(ajax)/分区数据导出(Excel)

时间:2016-06-12 02:20:51      阅读:793      评论:0      收藏:0      [点我收藏+]

标签:

知识点:

批量导入(ocupload插件,pinyin4J

/POI解析Excel(apache POI)

/区域分页查询

/Combobox下拉框

/分区组合条件分页查询(ajax)

/分区数据导出(Excel下载)


BOS项目笔记第4天





1.    区域批量导入功能


*Ajax不支持文件上传。

*上传并且不刷新上传页面原理:

Target到一个0,0,0的隐藏iframe里,造成一个没有刷新的假象

	<form target="myIframe" action="abc" method="post" enctype="multipart/form-data">
		<input type="file" name="myFile">
		<input type="submit" value="上传">
	</form>
	<iframe width="0" height="0" frameborder="0" name="myIframe"></iframe>	

*选择上传文件后自动上传(无上传按钮)原理:

文件输入框onchange事件 内容一变化就自动提交

 

 

1.1   一键上传插件使用

    将js文件复制到项目中

 jquery.ocupload-1.1.2.js

ocupload jquery 的应用代码

    $(function () {  
                $(".uploadfile").upload({  
                    action: 'CourseXMLFileUploadHander.ashx',  
                    name: 'xml',  
                    params: {  
                        'type': 'uploadCourseXMLFile',  
                        'rand': Math.random()  
                    },  
                    onSelect: function (self, element) {  
                        this.autoSubmit = false;  
                        var re = new RegExp("(xml){1}quot;, "i");  
      
                        if (!re.test(this.filename())) {  
                            alert("Only xml file can be uploaded");  
                        }  
                        else {  
                            this.submit();  
                        }  
                    },  
                    onSubmit: function (self, element) {  
                        $('.uploadfile').hide();  
                        $('#ajax_update').parent().show();  
                        //alert('Uploading file...');  
                    },  
                    onComplete: function (data, self, element) {  
                        $('#ajax_update').parent().hide();  
                        $('.uploadfile').show();  
                        self.resetInput();  
                        try {  
                            var ret = data;  
                            if (ret.indexOf("exception") >= 0) {  
                                alert('Upload file exception: ' + eval(data)[0].exception);  
                            }  
                            else {  
                                showSuccess('File is successfully Load.');  
      
                                uploadSuccess(ret);  
      
                            }  
                        } catch (err) {  
                            alert(data);  
                        }  
                    }  
                });  
            });  


    在需要使用一键上传插件的页面引入js文件,提供一个元素,调用插件的upload方法,动态修改html元素

 简单示例

<body>
	<input id="but1" type="button" value="上传">
	<script type="text/javascript">
		$("#but1").upload({
			action : 'abc',//form表单提交地址
			name : 'myFile'
		});
	</script>
</body>

原理:js插件会动态的创建form表单和iframe

 

1.1   在region.jsp页面应用一键上传插件

    引入js文件

<script
	src="${pageContext.request.contextPath }/js/jquery.ocupload-1.1.2.js"
	type="text/javascript"></script>

    调用插件的upload方法

	$(function(){
		$("#button-import").upload({
			action:'${pageContext.request.contextPath}/regionAction_importXls.action',
			name:'upload',
			onComplete: function (data, self, element) { 
				if(data == '1'){
					$.messager.alert("提示信息","导入数据成功!","info");
				}else{
					$.messager.alert("提示信息","导入数据失败!","warning");
				}
			}
		});
	});

1.2   创建RegionAction提供importXls方法

@Controller
@Scope("prototype")
public class RegionAction extends BaseAction<Region> {
	private File upload;// 用于接收上传的文件

	public void setUpload(File upload) {
		this.upload = upload;
	}

	// 导入区域数据
	public String importXls() throws FileNotFoundException, IOException {
		System.out.println(upload);
		// 加载Excel文件到内存中
		HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(upload));
		// 读取第一个Sheet页
		HSSFSheet sheet = workbook.getSheetAt(0);

		List<Region> list = new ArrayList<Region>();
		for (Row row : sheet) {
			// int rowNum = row.getRowNum();
			String value1 = row.getCell(0).getStringCellValue();// id
			String value2 = row.getCell(1).getStringCellValue();// provice
			String value3 = row.getCell(2).getStringCellValue();// city
			String value4 = row.getCell(3).getStringCellValue();// district
			String value5 = row.getCell(4).getStringCellValue();// postcode
			Region region = new Region(value1, value2, value3, value4, value5);

			// 简码
			String shortcode = StringUtils.join(
					PinYin4jUtils.getHeadByString(value2 + value3), "");
			// 城市编码
			String citycode = PinYin4jUtils.hanziToPinyin(value3, "");
			region.setShortcode(shortcode);
			region.setCitycode(citycode);
			list.add(region);
		}
		String f = "1";
		try {
			regionService.saveBatch(list);
		} catch (Exception e) {
			f = "0";
		}
		ServletActionContext.getResponse().setContentType(
				"text/html;charset=UTF-8");
		ServletActionContext.getResponse().getWriter().print(f);
		return NONE;
	}

配置struts.xml


*重复导入时出现主键冲突:

Duplicate entry ......

解决方法:使用saveOrUpdate


1.3   使用apache POI解析Excel文件


/**
 * 测试POI解析Excel文件
 */
public class POITest {
	@Test
	public void test1() throws FileNotFoundException, IOException {
		HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(new File(
				"d:\\abc.xls")));
		HSSFSheet sheet = workbook.getSheetAt(0);//读取第一个sheet页
		for (Row row : sheet) {//循环读取每一行
			String v1 = row.getCell(0).getStringCellValue();//获得当前行的第一个单元格的文字内容
			String v2 = row.getCell(1).getStringCellValue();
			String v3 = row.getCell(2).getStringCellValue();
			String v4 = row.getCell(3).getStringCellValue();
			String v5 = row.getCell(4).getStringCellValue();
			System.out.println(v1 + " " + v2 + " "  +v3 + " " + v4 + " " + v5);
		}
	}
}


Pinyin4J

 

	@Test
	public void test1() {
		String city = "北京市";
		String province = "河北省";
		String city2 = "石家庄市";
		String district = "长安区";

		// 城市编码 北京市-----》beijing
		String str1 = PinYin4jUtils.hanziToPinyin(
				city.substring(0, city.length() - 1), "");
		System.out.println(str1);

		String info = province.substring(0, province.length() - 1)
				+ city2.substring(0, city2.length() - 1)
				+ district.substring(0, district.length() - 1);
		// 简码河北省石家庄市长安区-----》hbsjzca
		String[] strings = PinYin4jUtils.getHeadByString(info);
		String join = StringUtils.join(strings, "");
		System.out.println(join);
	}
}



utils工具类

package cn.itcast.bos.utils;

import java.util.Arrays;

import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

public class PinYin4jUtils {
	/**
	 * 将字符串转换成拼音数组
	 * 
	 * @param src
	 * @return
	 */
	public static String[] stringToPinyin(String src) {
		return stringToPinyin(src, false, null);
	}

	/**
	 * 将字符串转换成拼音数组
	 * 
	 * @param src
	 * @return
	 */
	public static String[] stringToPinyin(String src, String separator) {

		return stringToPinyin(src, true, separator);
	}

	/**
	 * 将字符串转换成拼音数组
	 * 
	 * @param src
	 * @param isPolyphone
	 *            是否查出多音字的所有拼音
	 * @param separator
	 *            多音字拼音之间的分隔符
	 * @return
	 */
	public static String[] stringToPinyin(String src, boolean isPolyphone,
			String separator) {
		// 判断字符串是否为空
		if ("".equals(src) || null == src) {
			return null;
		}
		char[] srcChar = src.toCharArray();
		int srcCount = srcChar.length;
		String[] srcStr = new String[srcCount];

		for (int i = 0; i < srcCount; i++) {
			srcStr[i] = charToPinyin(srcChar[i], isPolyphone, separator);
		}
		return srcStr;
	}

	/**
	 * 将单个字符转换成拼音
	 * 
	 * @param src
	 * @return
	 */
	public static String charToPinyin(char src, boolean isPolyphone,
			String separator) {
		// 创建汉语拼音处理类
		HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
		// 输出设置,大小写,音标方式
		defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
		defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);

		StringBuffer tempPinying = new StringBuffer();

		// 如果是中文
		if (src > 128) {
			try {
				// 转换得出结果
				String[] strs = PinyinHelper.toHanyuPinyinStringArray(src,
						defaultFormat);

				// 是否查出多音字,默认是查出多音字的第一个字符
				if (isPolyphone && null != separator) {
					for (int i = 0; i < strs.length; i++) {
						tempPinying.append(strs[i]);
						if (strs.length != (i + 1)) {
							// 多音字之间用特殊符号间隔起来
							tempPinying.append(separator);
						}
					}
				} else {
					tempPinying.append(strs[0]);
				}

			} catch (BadHanyuPinyinOutputFormatCombination e) {
				e.printStackTrace();
			}
		} else {
			tempPinying.append(src);
		}

		return tempPinying.toString();

	}

	public static String hanziToPinyin(String hanzi) {
		return hanziToPinyin(hanzi, " ");
	}

	/**
	 * 将汉字转换成拼音
	 * 
	 * @param hanzi
	 * @param separator
	 * @return
	 */
	public static String hanziToPinyin(String hanzi, String separator) {

		// 创建汉语拼音处理类
		HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
		// 输出设置,大小写,音标方式
		defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
		defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);

		String pinyingStr = "";
		try {
			pinyingStr = PinyinHelper.toHanyuPinyinString(hanzi, defaultFormat,
					separator);
		} catch (BadHanyuPinyinOutputFormatCombination e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return pinyingStr;
	}

	/**
	 * 将字符串数组转换成字符串
	 * 
	 * @param str
	 * @param separator
	 *            各个字符串之间的分隔符
	 * @return
	 */
	public static String stringArrayToString(String[] str, String separator) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < str.length; i++) {
			sb.append(str[i]);
			if (str.length != (i + 1)) {
				sb.append(separator);
			}
		}
		return sb.toString();
	}

	/**
	 * 简单的将各个字符数组之间连接起来
	 * 
	 * @param str
	 * @return
	 */
	public static String stringArrayToString(String[] str) {
		return stringArrayToString(str, "");
	}

	/**
	 * 将字符数组转换成字符串
	 * 
	 * @param str
	 * @param separator
	 *            各个字符串之间的分隔符
	 * @return
	 */
	public static String charArrayToString(char[] ch, String separator) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < ch.length; i++) {
			sb.append(ch[i]);
			if (ch.length != (i + 1)) {
				sb.append(separator);
			}
		}
		return sb.toString();
	}

	/**
	 * 将字符数组转换成字符串
	 * 
	 * @param str
	 * @return
	 */
	public static String charArrayToString(char[] ch) {
		return charArrayToString(ch, " ");
	}

	/**
	 * 取汉字的首字母
	 * 
	 * @param src
	 * @param isCapital
	 *            是否是大写
	 * @return
	 */
	public static char[] getHeadByChar(char src, boolean isCapital) {
		// 如果不是汉字直接返回
		if (src <= 128) {
			return new char[] { src };
		}
		// 获取所有的拼音
		String[] pinyingStr = PinyinHelper.toHanyuPinyinStringArray(src);

		// 创建返回对象
		int polyphoneSize = pinyingStr.length;
		char[] headChars = new char[polyphoneSize];
		int i = 0;
		// 截取首字符
		for (String s : pinyingStr) {
			char headChar = s.charAt(0);
			// 首字母是否大写,默认是小写
			if (isCapital) {
				headChars[i] = Character.toUpperCase(headChar);
			} else {
				headChars[i] = headChar;
			}
			i++;
		}

		return headChars;
	}

	/**
	 * 取汉字的首字母(默认是大写)
	 * 
	 * @param src
	 * @return
	 */
	public static char[] getHeadByChar(char src) {
		return getHeadByChar(src, true);
	}

	/**
	 * 查找字符串首字母
	 * 
	 * @param src
	 * @return
	 */
	public static String[] getHeadByString(String src) {
		return getHeadByString(src, true);
	}

	/**
	 * 查找字符串首字母
	 * 
	 * @param src
	 * @param isCapital
	 *            是否大写
	 * @return
	 */
	public static String[] getHeadByString(String src, boolean isCapital) {
		return getHeadByString(src, isCapital, null);
	}

	/**
	 * 查找字符串首字母
	 * 
	 * @param src
	 * @param isCapital
	 *            是否大写
	 * @param separator
	 *            分隔符
	 * @return
	 */
	public static String[] getHeadByString(String src, boolean isCapital,
			String separator) {
		char[] chars = src.toCharArray();
		String[] headString = new String[chars.length];
		int i = 0;
		for (char ch : chars) {

			char[] chs = getHeadByChar(ch, isCapital);
			StringBuffer sb = new StringBuffer();
			if (null != separator) {
				int j = 1;

				for (char ch1 : chs) {
					sb.append(ch1);
					if (j != chs.length) {
						sb.append(separator);
					}
					j++;
				}
			} else {
				sb.append(chs[0]);
			}
			headString[i] = sb.toString();
			i++;
		}
		return headString;
	}
	
	public static void main(String[] args) {
		// pin4j 简码 和 城市编码 
		String s1 = "中华人民共和国"; 
		String[] headArray = getHeadByString(s1); // 获得每个汉字拼音首字母
		System.out.println(Arrays.toString(headArray));
		
		String s2 ="长城" ; 
		System.out.println(Arrays.toString(stringToPinyin(s2,true,",")));
		
		String s3 ="长";
		System.out.println(Arrays.toString(stringToPinyin(s3,true,",")));
	}
}



2.    区域分页查询

    修改region.jsp页面中datagrid的url地址

    在RegionAction中提供分页查询方法pageQuery

与上一天的代码重复需要提取到baseAction  


3.    重构分页代码

    在BaseAction中提取PageBean和DetachedCriteria对象

	protected PageBean pageBean = new PageBean();
	// 离线条件查询对象,用于包装查询条件
	DetachedCriteria detachedCriteria = null;

    在BaseAction中提供setPage和setRows方法

把分页ajax相应的两个参数row和page直接注入到上面提取的pageBean中

	public void setPage(int page) {
		pageBean.setCurrentPage(page);// 当前页码
	}

	public void setRows(int rows) {
		pageBean.setPageSize(rows);// 每页显示记录数
	}

    在BaseAction的构造方法中创建离线条件查询对象,并且注入给PageBean

 构造方法获取实体类型后创建离线查询条件对象并注入到pageBean中

	public BaseAction() {
		// 获得父类(BaseAction) 类型
		ParameterizedType superclass = (ParameterizedType) this.getClass()
				.getGenericSuperclass();
		// 获得父类上的泛型数组
		Type[] typeArguments = superclass.getActualTypeArguments();
		// 获得实体类型
		Class<T> domainClass = (Class<T>) typeArguments[0];
		// 获得实体类型后创建离线条件查询对象
		detachedCriteria = DetachedCriteria.forClass(domainClass);
		pageBean.setDetachedCriteria(detachedCriteria);
		try {
			model = domainClass.newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
	}

    在BaseAction中抽取方法writePageBean2Json和writeListBean2Json

	/**
	 * 将PageBean序列化为json返回
	 */
	public void writePageBean2Json(PageBean pageBean, String[] excludes) {
		// 使用jsonlib将PageBean对象序列化为json数据
		JsonConfig jsonConfig = new JsonConfig();
		jsonConfig.setExcludes(excludes);
		String json = JSONObject.fromObject(pageBean, jsonConfig).toString();

		ServletActionContext.getResponse().setContentType(
				"text/json;charset=UTF-8");
		try {
			ServletActionContext.getResponse().getWriter().print(json);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 将List序列化为json返回
	 */
	public void writeListBean2Json(List list, String[] excludes) {
		// 使用jsonlib将PageBean对象序列化为json数据
		JsonConfig jsonConfig = new JsonConfig();
		jsonConfig.setExcludes(excludes);
		String json = JSONArray.fromObject(list, jsonConfig).toString();

		ServletActionContext.getResponse().setContentType(
				"text/json;charset=UTF-8");
		try {
			ServletActionContext.getResponse().getWriter().print(json);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
 

    在RegionAction中的分页查询

分页查询代码简化为3条

	/**
	 * 分页查询方法
	 * @throws IOException 
	 */
	public String pageQuery() throws IOException{
		regionService.pageQuery(pageBean);
		this.writePageBean2Json(pageBean, new String[]{"currentPage","pageSize","detachedCriteria","subareas"});
		return NONE;
	}

  

4.    分区添加功能


4.1   Combobox下拉框使用

方式一:给静态的select标签应用

方式二:使用input标签通过url动态获取数据(json)

textField:为"option"下拉显示的内容

valueField::为最终提交的value值

<body>
	<!-- 方式一 -->
	<select class="easyui-combobox">
		<option value="1">河北省石家庄市桥西区</option>
		<option value="2">河北省石家庄市桥东区</option>
		<option value="3">河北省石家庄市长安区</option>
	</select>
	
	<!-- 方式二 -->
	<input
	 data-options="url:'${pageContext.request.contextPath }/json/data.json',
	 			textField:'name',valueField:'id'"
	 type="text" class="easyui-combobox"/>
</body>


subarea分区页面的添加分区弹窗区域选择下拉框数据获取(模糊查询)

及添加分区功能

 

第一步:修改subarea.jsp页面中combobox的url地址


mode属性

定义了当文本改变时如何读取列表数据。设置为‘remote‘时,下拉列表框将会从服务器加载数据。

当设置为“remote”模式时,用户输入将被发送到名为‘q‘的HTTP请求参数到服务器检索新数据。

 技术分享

						<td>
							<input class="easyui-combobox" name="region.id"  
    							data-options="mode:'remote',valueField:'id',textField:'name',
    							url:'${pageContext.request.contextPath }/regionAction_list.action'" />  
						</td>

对应分区类也应增加与下拉栏textField对应的name属性(省市区)

	private String id;//编号
	private String province;//省
	private String city;//市
	private String district;//区
	private String postcode;//邮编
	private String shortcode;//简码
	private String citycode;//城市编码
	private Set subareas = new HashSet(0);//区域对应的多个分区
	
	public String getName(){
		return province + city + district;
	}


第二步:在RegionAction中提供list方法查询区域数据

 

	private String q;//模糊查询参数	
	public void setQ(String q) {
		this.q = q;
	}
	/**
	 *  查询所有区域返回json
	 */
	public String list(){
		List<Region> list = null;
		if(StringUtils.isNotBlank(q)){
			//根据q进行模糊查询
			list = regionService.findByQ(q.trim());
		}else{
			//查询所有
			list = regionService.findAll();
		}
		String[] excludes = new String[]{"subareas"};
		this.writeListBean2Json(list, excludes);
		return NONE;
	}

Service中:

	@Override
	public List<Region> findByQ(String q) {	
		return regionDao.findByNameQuery("findByQ","%"+q+"%","%"+q+"%","%"+q+"%");
	}
baseIDaompl命名查询

	@Override
	public List<T> findByNameQuery(String hqlName, Object... params) {
		 List findByNamedQuery = this.getHibernateTemplate().findByNamedQuery(hqlName,params);
		 return findByNamedQuery;
	}

对应*hbm.xml提供query hql语句

注意:命名查询配置语句中不能出现双引号" "会报错,因为语句是按字符串来提取的,xml配置+" "来拼接也不行

    <query name="findByQ">
    	FROM Region WHERE city LIKE ? OR province LIKE ? OR district LIKE ? 
    </query>

第三步:为保存按钮绑定事件

				<a id="save" icon="icon-save" href="#" class="easyui-linkbutton" plain="true" >保存</a>
				<script type="text/javascript">
					$(function(){
						//为保存按钮绑定事件
						$("#save").click(function(){
							var v = $("#addForm").form("validate");
							if(v){
								$("#addForm").submit();
							}
						});
					});
				</script><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>

第四步:创建一个SubareaAction,提供add方法用于添加分区

 略

 

5.    分区组合条件分页查询

基于datagrid的load方法实现组合条件分页查询

 

*带关联查询的分页查询转换json会出错

freemarker.template.TemplateModelException:

Method public java.lang.Stringorg.apache.commons.lang.exception

.NestableRuntimeException.getMessage(int)threw an exception when invoked on net.sf.json.JSONException:

java.lang.reflect.InvocationTargetException

原因:关联对象延迟加载是代理对象无法转换成json数据

解决: 修改对应需关联对象hbm,xml文件的lazy属性为false 解决关联查询问题

        <many-to-one name="region" class="cn.feibai.bos.domain.Region" fetch="select" lazy="false">
            <column name="region_id" length="32" />
        </many-to-one>

第一步:提供组合条件查询窗口

第二步提供一个工具方法,将form表单中的输入项转为json数据,提交参数

	$.fn.serializeJson=function(){  
            var serializeObj={};  
            var array=this.serializeArray();
            $(array).each(function(){  
                if(serializeObj[this.name]){  
                    if($.isArray(serializeObj[this.name])){  
                        serializeObj[this.name].push(this.value);  
                    }else{  
                        serializeObj[this.name]=[serializeObj[this.name],this.value];  
                    }  
                }else{  
                    serializeObj[this.name]=this.value;   
                }  
            });  
            return serializeObj;  
        }; 


第三步:为查询按钮绑定事件,调用datagrid的load方法,重写发起ajax请求,提交参数

目的:这样发起的查询是ajax请求,条件参数会缓存在页面.

ajax没有全部刷新页面所以对应分页查询的条件也不会丢失


方法:load       

参数:param

详情:

加载和显示第一页的所有行。如果指定了‘param‘,它将取代‘queryParams‘属性。通常可以通过传递一些参数执行一次查询,通过调用这个方法从服务器加载新数据。


技术分享

 

	<!-- 查询分区 -->
	<script type="text/javascript">
		//为查询按钮绑定事件
		$(function(){
			$.fn.serializeJson=function(){  
	            var serializeObj={};  
	            var array=this.serializeArray();
	            $(array).each(function(){  
	                if(serializeObj[this.name]){  
	                    if($.isArray(serializeObj[this.name])){  
	                        serializeObj[this.name].push(this.value);  
	                    }else{  
	                        serializeObj[this.name]=[serializeObj[this.name],this.value];  
	                    }  
	                }else{  
	                    serializeObj[this.name]=this.value;   
	                }  
	            });  
	            return serializeObj;  
	        }; 
			$("#btn").click(function(){
				//获取查询条件---一次获取所有的查询条件,将查询条件封装成json数据
				var params = $("#searchForm").serializeJson();
				//重新发起一次ajax请求,提交参数
				$("#grid").datagrid("load",params);
				//关闭查询窗口
				$("#searchWindow").window("close");
			});
		});
	</script>


第四步:改造SubareaAction中的pageQuery方法,加入组合条件分页查询逻辑


Restrictions  API

技术分享


	/**
	 * 分页组合条件查询
	 */
	public String pageQuery() {
		DetachedCriteria subareaDC = pageBean.getDetachedCriteria();
		// 从模型对象中获取提交的查询参数
		String addresskey = model.getAddresskey();// 关键字
		// 单表查询
		if (StringUtils.isNotBlank(addresskey)) {
			// 添加查询条件,根据关键字进行模糊查询
			subareaDC.add(Restrictions.like("addresskey",
					"%" + addresskey.trim() + "%"));
		}
		Region region = model.getRegion();
		// 多表查询
		if (region != null) {
			String province = region.getProvince();
			String city = region.getCity();
			String district = region.getDistrict();
			DetachedCriteria regionDC = subareaDC.createCriteria("region");
			if (StringUtils.isNotBlank(province)) {
				// 添加查询条件,根据省进行模糊查询
				regionDC.add(Restrictions
						.like("province", "%" + province + "%"));
			}
			if (StringUtils.isNotBlank(city)) {
				// 添加查询条件,根据省进行模糊查询
				regionDC.add(Restrictions.like("city", "%" + city + "%"));
			}
			if (StringUtils.isNotBlank(district)) {
				// 添加查询条件,根据省进行模糊查询
				regionDC.add(Restrictions
						.like("district", "%" + district + "%"));
			}
		}
		subareaService.pageQuery(pageBean);
		String[] excludes = new String[] { "decidedzone", "subareas" };
		this.writePageBean2Json(pageBean, excludes);
		return NONE;
	}

 

6.    分区数据导出功能(Excel提供下载)

第一步:修改subarea.jsp页面中导出按钮的事件 

	function doExport(){
		//发起请求Action,查询所有分区数据,写到Excel文件中并提供下载
		window.location.href = "${pageContext.request.contextPath}/subareaAction_exportXls.action";
	}

第二步:在Action中提供exportXls方法

两种方法:

方式一:原始手动设置响应下载

文件名乱码工具类

import java.io.IOException;
import java.net.URLEncoder;

import sun.misc.BASE64Encoder;

public class FileUtils {
		/**
		 * 下载文件时,针对不同浏览器,进行附件名的编码
		 * 
		 * @param filename
		 *            下载文件名
		 * @param agent
		 *            客户端浏览器
		 * @return 编码后的下载附件名
		 * @throws IOException
		 */
		public static String encodeDownloadFilename(String filename, String agent)
				throws IOException {
			if (agent.contains("Firefox")) { // 火狐浏览器
				filename = "=?UTF-8?B?"
						+ new BASE64Encoder().encode(filename.getBytes("utf-8"))
						+ "?=";
				filename = filename.replaceAll("\r\n", "");
			} else { // IE及其他浏览器
				filename = URLEncoder.encode(filename, "utf-8");
				filename = filename.replace("+"," ");
			}
			return filename;
		}
}


	/**
	 * 导出分区数据到Excel文件并提供下载
	 * 
	 * @throws IOException
	 */
	public String exportXls() throws IOException {
		List<Subarea> list = subareaService.findAll();
		// 使用POI将查询的数据写入Excel文件中
		HSSFWorkbook workbook = new HSSFWorkbook();
		// 在工作表中创建一个sheet页
		HSSFSheet sheet = workbook.createSheet("分区数据");
		// 创建标题行
		HSSFRow headRow = sheet.createRow(0);
		// 创建单元格
		headRow.createCell(0).setCellValue("分区编号");
		headRow.createCell(1).setCellValue("关键字");
		headRow.createCell(2).setCellValue("地址");
		headRow.createCell(3).setCellValue("省市区");
		for (Subarea subarea : list) {
			// 创建数据行
			HSSFRow dataRow = sheet.createRow(sheet.getLastRowNum() + 1);
			String id = subarea.getId();
			String addresskey = subarea.getAddresskey();
			String position = subarea.getPosition();
			Region region = subarea.getRegion();
			dataRow.createCell(0).setCellValue(id);
			dataRow.createCell(1).setCellValue(addresskey);
			dataRow.createCell(2).setCellValue(position);
			if (region != null) {
				String province = region.getProvince();
				String city = region.getCity();
				String district = region.getDistrict();
				String info = province + city + district;
				dataRow.createCell(3).setCellValue(info);
			}
		}

		String filename = "分区数据.xls";
		String agent = ServletActionContext.getRequest().getHeader("user-agent");//浏览器类型
		filename = FileUtils.encodeDownloadFilename(filename, agent );
		
		//根据文件名称动态获得类型
		String contentType = ServletActionContext.getServletContext()
				.getMimeType(filename);
		// 通知客户端下载文件的类型
		ServletActionContext.getResponse().setContentType(contentType);
		
		//指定以附件形式下载,指定文件名称
		ServletActionContext.getResponse().setHeader("content-disposition", "attachment;filename=" + filename);
		// 通过输出流向客户端浏览器写Excel文件
		ServletOutputStream out = ServletActionContext.getResponse().getOutputStream();
		workbook.write(out);
		return NONE;
	}
}


方式二:通过struts2的stream结果集下载


思路百度自博客(http://xiaowei-qi-epro-com-cn.iteye.com/blog/2030671):

思路是,先创建一个输出流,将这个excel写入到输出流里面,然后再通过这个输出流来得到我们所需要的输入流.

使用了ByteArrayOutputStreamByteArrayInputStream...处理的思想是,HSSFWorkbook 写入ByteArrayOutputStream.然后用ByteArrayOutputStream来转换为字节流..然后再将字节流转换为ByteArrayInputStream ..至此,我们就在内存中将excel转换成了输入流

<pre name="code" class="java">	private InputStream target;  
	public InputStream getTarget() {  
	    return target;  
	} 
	//下载文件名,存在中文乱码  
	private String downloadFileName;  
	public String getDownloadFileName() throws UnsupportedEncodingException {  
	    // 处理中文乱码  
	    if(downloadFileName != null){  
	        return new String(downloadFileName.getBytes("GBK"),"ISO-8859-1");  
	    }  
	    return downloadFileName;  
	}  
	/**
	 * 下载所有分区信息以xls格式
	 * @return
	 * @throws IOException 
	 */
	public String export() throws IOException{
		List<Subarea> list=subareaService.findAll();
		//把list写入excel文档
		HSSFWorkbook book=new HSSFWorkbook();
		HSSFSheet sheet = book.createSheet("全部分区详情");
		//创建初始标题行
		HSSFRow row = sheet.createRow(0);
		row.createCell(0).setCellValue("分拣编号");
		row.createCell(1).setCellValue("省市区");
		row.createCell(2).setCellValue("关键字");
		row.createCell(3).setCellValue("位置");
		//遍历list
		for (Subarea subarea : list) {
			HSSFRow createRow = sheet.createRow(sheet.getLastRowNum()+1);
			String id = subarea.getId();
			String nameInfo = subarea.getRegion().getName();
			String addresskey = subarea.getAddresskey();
			String position = subarea.getPosition();
			createRow.createCell(0).setCellValue(id);
			createRow.createCell(1).setCellValue(nameInfo);
			createRow.createCell(2).setCellValue(addresskey);
			createRow.createCell(3).setCellValue(position);
		}
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		book.write(out);
		target = new ByteArrayInputStream(out.toByteArray());  
		out.close();  
		downloadFileName="分区详情.xls";		
		return "download";
	}
 


配置文件

		<!-- 分区 -->
		<action name="subareaAction_*" class="subareaAction" method="{1}">
			<result name="subareaList">/WEB-INF/pages/base/subarea.jsp</result>			
			<result name="download" type="stream">  
			    <!-- 设置响应头 -->  
			    <param name="contentDisposition">attachment;filename=${downloadFileName}</param>  
			    <!-- 确定流 -->  
			    <param name="inputName">target</param>  
			</result> 			
		</action>


框架 day50 BOS项目 4 批量导入(ocupload插件,pinyin4J)/POI解析Excel/Combobox下拉框/分区组合条件分页查询(ajax)/分区数据导出(Excel)

标签:

原文地址:http://blog.csdn.net/opopopwqwqwq/article/details/51626964

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!