1.合同复制的三种方法
第一种方法:通过旧对象,新对象,拷贝属性,get/set。绑定关联关系。
这种方式非常好理解,缺点:代码冗长。代码:
public String copy1(){ /* * 操作步骤: * 1、获得用户选中的合同 * 2、创建一个新的合同 * 3、将旧合同的属性值设置到对应新合同的属性中。 * 4、保存 * 5、复制货物信息 * 6、复制附件信息 */ ContractDAO cDao = (ContractDAO) this.getDao("daoContract"); Contract oldContract = (Contract) cDao.get(Contract.class, model.getId()); //拿到旧的合同 Contract newContract = new Contract(); //创建新合同 newContract.setContractNo("[复制]" + oldContract.getContractNo()); newContract.setCustomName(oldContract.getCustomName()); newContract.setCheckBy(oldContract.getCheckBy()); //... //复制货物信息 Set<ContractProduct> cpSet = new HashSet(); for(ContractProduct cp :oldContract.getContractProducts()){ ContractProduct newcp = new ContractProduct(); //创建新的货物 newcp.setProductNo(cp.getProductNo()); newcp.setProductDesc(cp.getProductDesc()); newcp.setCnumber(cp.getCnumber()); newcp.setBoxNum(cp.getBoxNum()); newcp.setPrice(cp.getPrice()); //数据的初始化 newcp.setFinished(false); //复制附件信息 Set<ExtCproduct> epSet = new HashSet(); for(ExtCproduct ep :cp.getExtCproducts()){ ExtCproduct newep = new ExtCproduct(); //创建新的附件 newep.setProductNo(ep.getProductNo()); newep.setProductDesc(ep.getProductDesc()); newep.setCnumber(ep.getCnumber()); newep.setBoxNum(ep.getBoxNum()); newep.setPrice(ep.getPrice()); //数据的初始化 newep.setFinished(false); newep.setContractProduct(newcp); //绑定关系 epSet.add(newep); } newcp.setExtCproducts(epSet); //绑定关系 newcp.setContract(newContract); //绑定关系 cpSet.add(newcp); } //数据的初始化 newContract.setState(0); //0草稿1已上报 newContract.setContractProducts(cpSet); //绑定关系 cDao.saveOrUpdate(newContract); return list(); }
第二种方法:
先查出旧对象,将其对象的id设置为null。然后保存。代码:
public String copy(){ /** * 1.拿到要复制的合同的id * 2.将旧合同的主键置空, * 3.两层循环将关联的货物和附件的主键都置空即可 */ ContractDAO oDao = (ContractDAO) this.getDao("daoContract"); Contract oldContract = (Contract) oDao.get(Contract.class, model.getId());//用客户选择的合同id去查询对应的合同对象 oldContract.setContractNo("[复件]"+oldContract.getContractNo());//在复制的合同号之前加上复件以示区分 /** * hibernate有一个特性,如果一条记录没有主键,其他就算都有在保存的时候也会将数据当做新的数据保存进数据库并赋主键值 * 正好可以利用这个特性巧妙的完成合同复制而不用写过多的代码,但是一些初始状态值必须设置。 */ oldContract.setId(null);//重置合同主键id oldContract.setState(0);//初始化复制的合同状态为草稿(0) Set<ContractProduct> products = oldContract.getContractProducts(); for(ContractProduct cp : products){ for(ExtCproduct ep : cp.getExtCproducts()){ ep.setFinished(false); ep.setId(null);//遍历附件表,把每个附件的主键都置空 } cp.setId(null); //遍历货物表,将每个货物的主键都置空 cp.setFinished(false); } oDao.saveOrUpdate(oldContract); return list(); }
第三种方法,Spring copyProperties 不推荐使用。
BUG,在拷贝单个对象,关联对象。不推荐使用。代码:
public String copy3(){ ContractDAO cDao = (ContractDAO)this.getDao("daoContract"); Contract oldcontract = (Contract) cDao.get(Contract.class, model.getId()); Contract newContract = new Contract(); BeanUtils.copyProperties(oldcontract, newContract); //利用工具类复制属性 newContract.setId(null); newContract.setContractNo("[复制]" + newContract.getContractNo()); for(ContractProduct cp : oldcontract.getContractProducts()){ cp.setId(null); for(ExtCproduct ep : cp.getExtCproducts()){ ep.setId(null); } } cDao.saveOrUpdate(newContract); return list(); }
2.合同查看
在查看购销合同的页面jContractView.jsp中把货物页面中的货物信息表单还有附件信息的表单table粘贴过来,jsp黏贴过来的代码如下:
<div> <div class="textbox-header"> <div class="textbox-inner-header"> <div class="textbox-title"> 货物信息列表 </div> </div> </div> <div class="eXtremeTable" > <table id="ec_table" border="0" cellspacing="0" cellpadding="0" class="tableRegion" width="98%" > <thead> <tr> <td class="tableHeader">序号</td> <td class="tableHeader">货号</td> <td class="tableHeader">货物描述</td> <td class="tableHeader">生产厂家</td> <td class="tableHeader">装率</td> <td class="tableHeader">包装单位</td> <td class="tableHeader">数量</td> <td class="tableHeader">箱数</td> <td class="tableHeader">单价</td> <td class="tableHeader">总金额</td> </tr> </thead> <tbody class="tableBody" > <!--这里是循环遍历货物表,列出这个合同里面的所有货物,注意从哪里去取这个contractProducts,是从ActionContext中的request域中去取,由于这是个map集合,等于是拿key去取value--> <s:iterator value="#request.contractProducts" var="cp" status="lineNo"> <tr class="odd" onmouseover="this.className='highlight'" onmouseout="this.className='odd'" > <td> <s:property value="#lineNo.index+1"/></td> <td>${productNo}</td> <td width="310">${productDesc}</td> <td>${factory.factoryName}</td> <td>${loadingRate}</td> <td>${packingUnit}</td> <td>${cnumber}</td> <td>${boxNum}</td> <td>${price}</td> <td>${amount}</td> </tr> <!--这里是两层嵌套循环,上面从一个合同中取出每一个货物,记为cp,现在再遍历这个cp去取每一个货物的每一个附件--> <s:iterator value="#cp.extCproducts" var="ep" status="lineNo"> <tr class="odd" onmouseover="this.className='highlight'" onmouseout="this.className='odd'" > <td> </td> <td> <font color="blue">附件 <s:property value="#lineNo.index+1"/></font>: ${productNo}</td> <td width="310">${productDesc}</td> <td>${factory.factoryName}</td> <td>${loadingRate}</td> <td>${packingUnit}</td> <td>${cnumber}</td> <td>${boxNum}</td> <td>${price}</td> <td>${amount}</td> </tr> </s:iterator> </s:iterator> </tbody> </table> </div> </div>
然后自己排一下版,添加空格,标明是附件等。。。
valueStack中有一个List是root,有一个map是ognlContext
ognlContext中保存了root,ognlContext在ActionContext保存了
ognlContext中保存了root,ognlContext在ActionContext保存了
3.出货表制作:
在jContextProductList中加入出货表超链接:
<li id="new"><a href="#" onclick="formSubmit('/outproduct/outProductAction_toedit','_self');this.blur();">出货表</a></li>
新建一个出货表jsp页面 jOutProduct.jsp
<%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title></title> <link rel="stylesheet" rev="stylesheet" type="text/css" href="../../skin/default/css/default.css" media="all" /> <script type="text/javascript" src="../../js/datepicker/WdatePicker.js"></script> <script type="text/javascript" src="../../js/common.js"></script> </head> <body> <form name="icform" method="post"> <div id="menubar"> <div id="middleMenubar"> <div id="innerMenubar"> <div id="navMenubar"> <ul> <li id="save"><a href="#" onclick="formSubmit('/outproduct/outProductAction_print','_self');this.blur();">打印</a></li> <li id="back"><a href="#" onclick="formSubmit('/contract/contractAction_list','_self');this.blur();">返回</a></li> </ul> </div> </div> </div> </div> <div> <div class="textbox-header"> <div class="textbox-inner-header"> <div class="textbox-title"> 出货表月统计 </div> </div> </div> <div> <table class="commonTable" cellspacing="1"> <tr> <td class="columnTitle">船期:</td> <td class="tableContent"> <input type="text" style="width:90px;" name="inputDate" value="2011-12" readonly onclick="WdatePicker({el:this,isShowOthers:true,dateFmt:'yyyy-MM'});"/> </td> </tr> </table> </div> </div> </form> </body> </html>
/outproduct/outProductAction_print这时要创建一个新的action
然后配置struts.xml,
jContractList中点击出货表进入OutProduct.Action的toedit方法进入OutProduct.jsp页面,然后点击打印进入acion的toprint页面打印
action中的方法:
public String toedit(){ return "pedit"; } public void print() throws FileNotFoundException, IOException, ParseException, InterruptedException{ /* * 操作步骤: * 1、获取数据 like inputDate% * 2、模板技术实现,例如:报表标题,列宽,静态文字 * 3、循环货物对象,访问关联对象,输出到单元格中 * 4、保存 * 5、下载 */ PoiUtil poiUtil = new PoiUtil(); ContractProductDAO cpDao = (ContractProductDAO) this.getDao("daoContractProduct");//获得货物dao对象 /** * 用页面模型驱动传过来的inputDate去数据库进行模糊查询(我们以查询货物为基础,遍历厂商,附件等) * sql语句:SELECT * FROM contract_c WHERE ship_time LIKE '2011-12%' * 查询出来的是货物的集合 */ List<ContractProduct> dataList = cpDao.find("from ContractProduct o where o.contract.shipTime like '" + inputDate + "%'"); String rootpath = ServletActionContext.getRequest().getRealPath("/"); //获取绝对路径 /** * 从这里开始用poi模板来创建工作表 */ HSSFWorkbook wb = new HSSFWorkbook( new FileInputStream(rootpath+"/make/xlsprint/tOUTPRODUCT.xls")); //获取模板文件 HSSFSheet sheet = wb.getSheetAt(0); //获得工作表 HSSFRow nRow = null; //创建行对象 值从0开始 HSSFCell nCell = null; //创建单元格对象 值从0开始 HSSFCellStyle curStyle = wb.createCellStyle(); //创建样式 HSSFFont curFont = wb.createFont(); int rowNo = 0; short colNo = 1; //获取模板中已经有的单元格,这样样式,合同单元格等无需设置 /** * 这里记得是获取行和单元格对象而不是创建 */ nRow = sheet.getRow(rowNo++); nCell = nRow.getCell((short)1); //yyyy-MM yyyy-0x yyyy-x yyyy-xx /** * 这里有个小技巧,第一个replaceFirst进行匹配,有-0的直接把0去掉变成-,没有的则不改变,第二个则是把-换成年,配合后面的月组成”XXXX年X月份出货表“的效果 */ nCell.setCellValue(inputDate.replaceFirst("-0", "-").replaceFirst("-", "年") + "月份出货表"); //至此,标题修改完毕 rowNo++;//换到下一行 //以货物来循环 //for(int i=0;i<200;i++){ //test /** * 这里是以循环货物为基础,内嵌循环附件,厂家等 */ for(ContractProduct cp : dataList){ colNo = 1; nRow = sheet.createRow(rowNo++); nRow.setHeightInPoints(22); nCell = nRow.createCell(colNo++); nCell.setCellValue(cp.getContract().getCustomName()); nCell.setCellStyle(this.text(wb, curStyle, curFont)); nCell = nRow.createCell(colNo++); nCell.setCellValue(cp.getContract().getContractNo()); nCell.setCellStyle(this.text(wb, curStyle, curFont)); nCell = nRow.createCell(colNo++); nCell.setCellValue(cp.getProductNo()); nCell.setCellStyle(this.text(wb, curStyle, curFont)); nCell = nRow.createCell(colNo++); nCell.setCellValue(cp.getCnumber()+cp.getPackingUnit()); nCell.setCellStyle(this.text(wb, curStyle, curFont)); nCell = nRow.createCell(colNo++); nCell.setCellValue(cp.getFactory().getFactoryName()); nCell.setCellStyle(this.text(wb, curStyle, curFont)); //初始化 样式、字体有变化 curStyle = wb.createCellStyle(); //创建样式 curFont = wb.createFont(); //附件 nCell = nRow.createCell(colNo++); String _extProduct = ""; /** * 这里开始循环附件 */ for(ExtCproduct extcp : cp.getExtCproducts()){ _extProduct += extcp.getTypeName() + "\n"; //换行符 } _extProduct = UtilFuns.delLastChar(_extProduct); if(_extProduct.equals("")){ nCell.setCellValue("无"); }else{ nCell.setCellValue(_extProduct); nRow.setHeightInPoints(poiUtil.getCellAutoHeight(_extProduct, 12f)); //单元格自适应高度 } nCell.setCellStyle(this.extText(wb, curStyle, curFont)); //初始化 curStyle = wb.createCellStyle(); //创建样式 curFont = wb.createFont(); nCell = nRow.createCell(colNo++); //工具类UtilFuns.dateTimeFormat,实现将日期类型转换字符串yyyy-MM nCell.setCellValue(UtilFuns.dateTimeFormat(cp.getContract().getDeliveryPeriod())); nCell.setCellStyle(this.text(wb, curStyle, curFont)); nCell = nRow.createCell(colNo++); nCell.setCellValue(UtilFuns.dateTimeFormat(cp.getContract().getShipTime())); nCell.setCellStyle(this.text(wb, curStyle, curFont)); nCell = nRow.createCell(colNo++); nCell.setCellValue(cp.getContract().getTradeTerms()); nCell.setCellStyle(this.text(wb, curStyle, curFont)); //Thread.sleep(1); //休息一下。 } //} //获取文件名,获取文件扩展名,产生新文件,遍历目录 FileUtil fu = new FileUtil(); String dir = rootpath+"/web/tmp/"+ UtilFuns.sysDate() + "/"; //返回一个当前日期串 //创建目录 File file = new File(dir); if(!file.exists()){ //不存在时,才创建目录 file.mkdirs(); //创建多级目录,只要前面的目录不存在,自动创建。 } String xlsFile = fu.newFile(dir, "outproduct.xls"); //工具类方法只返回文件名 FileOutputStream fOut = new FileOutputStream(new File(dir + xlsFile)); wb.write(fOut); //将厂家的wb所有写入文件 fOut.flush(); fOut.close(); //下载工具类 HttpServletResponse response = ServletActionContext.getResponse(); DownloadBaseAction down = new DownloadBaseAction(); down.prototypeDownload(new File(dir + xlsFile), "outproduct.xls", response, true); } //设置文字样式 private HSSFCellStyle text(HSSFWorkbook wb, HSSFCellStyle curStyle, HSSFFont curFont){ curStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); //垂直居中 curStyle.setBorderTop(HSSFCellStyle.BORDER_THIN); //画表格细线 curStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); curStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN); curStyle.setBorderRight(HSSFCellStyle.BORDER_THIN); curFont.setFontName("Times New Roman"); curFont.setFontHeightInPoints((short)10); curStyle.setFont(curFont); //绑定 return curStyle; } //设置文字样式 private HSSFCellStyle extText(HSSFWorkbook wb, HSSFCellStyle curStyle, HSSFFont curFont){ curStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); //垂直居中 curStyle.setWrapText(true); //换行 curStyle.setBorderTop(HSSFCellStyle.BORDER_THIN); //画表格细线 curStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); curStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN); curStyle.setBorderRight(HSSFCellStyle.BORDER_THIN); curFont.setFontName("Times New Roman"); curFont.setFontHeightInPoints((short)10); curStyle.setFont(curFont); //绑定 return curStyle; }