Index: ssts-customform/src/main/java/com/forgon/disinfectsystem/customform/forminstance/action/FormInstanceAction.java =================================================================== diff -u -r36524 -r39278 --- ssts-customform/src/main/java/com/forgon/disinfectsystem/customform/forminstance/action/FormInstanceAction.java (.../FormInstanceAction.java) (revision 36524) +++ ssts-customform/src/main/java/com/forgon/disinfectsystem/customform/forminstance/action/FormInstanceAction.java (.../FormInstanceAction.java) (revision 39278) @@ -1,8 +1,12 @@ package com.forgon.disinfectsystem.customform.forminstance.action; +import java.util.Date; import java.util.HashMap; import java.util.Map; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; + import net.sf.json.JSONObject; import org.apache.struts2.convention.annotation.Action; @@ -13,6 +17,7 @@ import com.forgon.disinfectsystem.entity.customform.forminstance.FormInstance; import com.forgon.tools.StrutsParamUtils; import com.forgon.tools.StrutsResponseUtils; +import com.forgon.tools.date.DateTools; import com.forgon.tools.db.DatabaseUtil; import com.forgon.tools.json.JSONUtil; import com.forgon.tools.string.StringTools; @@ -115,6 +120,37 @@ StrutsResponseUtils.output(result); } + /** + * 不良事件导出 + */ + public void exportAdverseEventFormInstance(){ + Long id = StrutsParamUtils.getPraramLongValue("id", null); + HttpServletResponse response = StrutsParamUtils.getResponse(); + try { + FormInstance formInstance = formInstanceManager.get(id); + if(formInstance == null){ + throw new RuntimeException("id无效!"); + } + String fileName = getAdverseEventFormInstanceFileName(formInstance); + ServletOutputStream servletOutputStream = response.getOutputStream(); + response.setContentType("application/octet-stream"); + response.addHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("GBK"), "ISO8859_1")); + formInstanceManager.exportAdverseEventFormInstance(formInstance, servletOutputStream); + servletOutputStream.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 导出文件的名称 + * @param formInstance + * @return + */ + private String getAdverseEventFormInstanceFileName(FormInstance formInstance) { + String formName = formInstance.getFormDefinition().getFormName() + formInstance.getFormDefinition().getVersion() + DateTools.getFormatDateStr(formInstance.getCreateDate(), DateTools.COMMON_DATE_HM); + return formName + ".docx"; + } public FormInstance getModel() { return formInstance; Index: ssts-customform/src/main/java/com/forgon/disinfectsystem/customform/forminstance/vo/FormInstanceOptionExportVo.java =================================================================== diff -u --- ssts-customform/src/main/java/com/forgon/disinfectsystem/customform/forminstance/vo/FormInstanceOptionExportVo.java (revision 0) +++ ssts-customform/src/main/java/com/forgon/disinfectsystem/customform/forminstance/vo/FormInstanceOptionExportVo.java (revision 39278) @@ -0,0 +1,58 @@ +package com.forgon.disinfectsystem.customform.forminstance.vo; + +/** + * 不良事件导出vo + */ +public class FormInstanceOptionExportVo { + + /** + * 要显示到word表格单元格的文本,可以是表单元素名称,也可以是表单元素内容 + */ + private String cellText = ""; + + /** + * 表单元素类型:日期、时间、时间段、单选、多选、文本、数字、文本框 + */ + private String type; + + /** + * 是否表单元素名称 + */ + private Boolean isOptionName; + + public FormInstanceOptionExportVo(){ + + } + + public FormInstanceOptionExportVo(String cellText, String type, Boolean isOptionName) { + super(); + this.cellText = cellText; + this.type = type; + this.isOptionName = isOptionName; + } + + public String getCellText() { + return cellText; + } + + public void setCellText(String cellText) { + this.cellText = cellText; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Boolean getIsOptionName() { + return isOptionName; + } + + public void setIsOptionName(Boolean isOptionName) { + this.isOptionName = isOptionName; + } + +} Index: build.gradle =================================================================== diff -u -r39053 -r39278 --- build.gradle (.../build.gradle) (revision 39053) +++ build.gradle (.../build.gradle) (revision 39278) @@ -456,6 +456,9 @@ // spring 4不支持该版本的POI,要3.8以上版本,需要验证处理 compile group: 'org.apache.poi', name: 'poi', version:'3.6' + compile group: 'org.apache.poi', name: 'poi-ooxml', version:'3.6' + compile group: 'org.apache.poi', name: 'poi-ooxml-schemas', version: '3.8' + compile group: 'org.apache.xmlbeans', name: 'xmlbeans', version: '2.3.0' //pdf转图片 compile group: 'org.apache.pdfbox', name: 'fontbox', version: '2.0.8' compile group: 'org.apache.pdfbox', name: 'pdfbox', version: '2.0.8' Index: ssts-customform/src/main/java/com/forgon/disinfectsystem/customform/forminstance/service/FormInstanceManagerImpl.java =================================================================== diff -u -r36524 -r39278 --- ssts-customform/src/main/java/com/forgon/disinfectsystem/customform/forminstance/service/FormInstanceManagerImpl.java (.../FormInstanceManagerImpl.java) (revision 36524) +++ ssts-customform/src/main/java/com/forgon/disinfectsystem/customform/forminstance/service/FormInstanceManagerImpl.java (.../FormInstanceManagerImpl.java) (revision 39278) @@ -1,22 +1,43 @@ package com.forgon.disinfectsystem.customform.forminstance.service; +import java.io.FileInputStream; +import java.math.BigInteger; import java.sql.ResultSet; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; +import javax.servlet.ServletOutputStream; + import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.poi.xwpf.usermodel.ParagraphAlignment; +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.apache.poi.xwpf.usermodel.XWPFParagraph; +import org.apache.poi.xwpf.usermodel.XWPFRun; +import org.apache.poi.xwpf.usermodel.XWPFTable; +import org.apache.poi.xwpf.usermodel.XWPFTableCell; +import org.apache.poi.xwpf.usermodel.XWPFTableRow; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDecimalNumber; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc; import com.forgon.directory.acegi.tools.AcegiHelper; import com.forgon.directory.vo.LoginUserData; import com.forgon.disinfectsystem.customform.formdefinition.service.FormDefinitionManager; +import com.forgon.disinfectsystem.customform.forminstance.vo.FormInstanceOptionExportVo; import com.forgon.disinfectsystem.entity.customform.formdefinition.FormDefinition; import com.forgon.disinfectsystem.entity.customform.formdefinition.FormDefinitionItem; import com.forgon.disinfectsystem.entity.customform.formdefinition.FormDefinitionItemOption; @@ -26,6 +47,8 @@ import com.forgon.disinfectsystem.entity.sterilizationmanager.sterilizationrecord.SterilizationRecord; import com.forgon.exception.SystemException; import com.forgon.security.service.OperationManager; +import com.forgon.tools.Path; +import com.forgon.tools.date.DateTools; import com.forgon.tools.db.DatabaseUtil; import com.forgon.tools.hibernate.BasePoManagerImpl; import com.forgon.tools.util.ConfigUtils; @@ -359,5 +382,287 @@ } objectDao.deleteAll(formInstances); } + + @Override + public void exportAdverseEventFormInstance(FormInstance formInstance, ServletOutputStream servletOutputStream) throws Exception { + + String templateFilePath = Path.getWebAppRoot()+ "/disinfectsystem/basedatamanager/importbasedata/adverseEventTempalte.docx"; + // 加载Word文档 + FileInputStream fis = new FileInputStream(templateFilePath); + XWPFDocument document = new XWPFDocument(fis); + + //基本信息表格 + XWPFTable baseInfoTable = null; + //表单元素表格 + XWPFTable formInfoTable = null; + + // 遍历文档中的表格 + Iterator j = document.getTablesIterator(); + while(j.hasNext()){ + XWPFTable table = j.next(); + if(baseInfoTable == null){ + baseInfoTable = table; + continue; + } + if(formInfoTable == null){ + formInfoTable = table; + continue; + } + } + + //填充基本信息 + fillBaseInfoTable(formInstance, baseInfoTable); + + //填充表单信息 + fillFormInfoTable(formInstance, formInfoTable); + + document.write(servletOutputStream); + } + /** + * 填充基本信息 + * @param formInstance + * @param baseInfoTable + */ + private void fillBaseInfoTable(FormInstance formInstance, XWPFTable table) { + + FormDefinition formDefinition = formInstance.getFormDefinition(); + XWPFTableRow firstRow = table.getRow(0); + int rowNumbers = table.getNumberOfRows(); + for(int rowIndex = 0; rowIndex < rowNumbers; rowIndex++){ + XWPFTableRow row = table.getRow(rowIndex); + if(row == null){ + row = table.createRow(); + row.getCtRow().setTrPr(firstRow.getCtRow().getTrPr()); + } + if(rowIndex == 0){ + //表单名称 + XWPFTableCell cell01 = row.getCell(1); + setXWPFTableCellText(cell01, formDefinition.getFormName()); + }else if(rowIndex == 1){ + //登记时间 + XWPFTableCell cell11 = row.getCell(1); + setXWPFTableCellText(cell11, DateTools.getFormatDateStr(formInstance.getCreateDate(), DateTools.COMMON_DATE_HM)); + //登记人 + XWPFTableCell cell13 = row.getCell(3); + setXWPFTableCellText(cell13, formInstance.getCreateUserName()); + }else if(rowIndex == 2){ + //备注 + XWPFTableCell cell21 = row.getCell(1); + //row.getCtRow().getTrPr().removeTrHeight(0); + setXWPFTableCellText(cell21, formInstance.getRemark()); + } + } + } + + /** + * 填充表单信息 + * @param formInstance + * @param formInfoTable + */ + private void fillFormInfoTable(FormInstance formInstance, XWPFTable table) { + //表格单元格填充的内容vo + List exportVoList = getFormInstanceOptionExportVoList(formInstance); + if(CollectionUtils.isEmpty(exportVoList)){ + return; + } + + int columnNuber = 4; + int rowNumber = exportVoList.size() / columnNuber; + int cellIndex = 0; + for(int i = 0; i < rowNumber; i++){ + XWPFTableRow row = table.getRow(i); + if(row == null){ + row = table.createRow(); + } + boolean includeTextArea = false; + for(int columnIndex = 0; columnIndex < columnNuber; columnIndex++){ + XWPFTableCell cell = row.getCell(columnIndex); + FormInstanceOptionExportVo exportVo = exportVoList.get(cellIndex++); + //设置单元格段落水平对齐方式 + setXWPFTableCellParagraphAlignment(cell, exportVo.getIsOptionName()); + //填充文字 + setXWPFTableCellText(cell, exportVo.getCellText()); + includeTextArea = StringUtils.equals(exportVo.getType(), FormDefinitionItem.TYPE_TEXTAREA); + } + if(includeTextArea){ + //文本框单独占用一行,合并单元格,只留下2列 + mergeTableCell(row, 1, 3); + } + } + } + + /** + * 构建导出的单元格vo + * @param formInstance + * @return + */ + private List getFormInstanceOptionExportVoList(FormInstance formInstance) { + List exportVoList = new ArrayList(); + List items = formInstance.getItems(); + if(CollectionUtils.isEmpty(items)){ + return exportVoList; + } + for (FormInstanceItem formInstanceItem : items) { + FormDefinitionItem formDefinitionItem = formInstanceItem.getDefinitionItem(); + String type = formDefinitionItem.getType(); + if(StringUtils.equals(type, FormDefinitionItem.TYPE_CHECK)){ + //表格最后一行不足4列时,补足4列 + appendEmptyCellTextVo(exportVoList); + List checkCellTextVoList = buildCheckCellTextVoList(formInstanceItem); + exportVoList.addAll(checkCellTextVoList); + continue; + } + + String name = formDefinitionItem.getName(); + String answer = formInstanceItem.getShowAnswer(); + exportVoList.add(new FormInstanceOptionExportVo(name+":", type, true)); + exportVoList.add(new FormInstanceOptionExportVo(answer, type, false)); + + if(StringUtils.equals(type, FormDefinitionItem.TYPE_TEXTAREA)){ + //表格最后一行不足4列时,补足4列 + appendEmptyCellTextVo(exportVoList); + } + } + return exportVoList; + } + + /** + * 表格最后一行不足4列时,补足4列 + * @param exportVoList + */ + private void appendEmptyCellTextVo(List exportVoList) { + int columnNuber = 4; + //最后一行的单元格数 + int lastRowCellCount = exportVoList.size() % columnNuber; + if(lastRowCellCount > 0){ + String lastVoType = exportVoList.get(exportVoList.size() - 1).getType(); + for(int i = 0; i < columnNuber -lastRowCellCount; i++){ + boolean isOptionName = (i % 2 == 0); + exportVoList.add(new FormInstanceOptionExportVo("", lastVoType, isOptionName)); + } + } + } + + /** + * 构建多选项的单元格导出vo + * @param formInstanceItem + * @return + */ + private List buildCheckCellTextVoList(FormInstanceItem formInstanceItem) { + List checkCellTextVoList = new ArrayList(); + List optionValues = formInstanceItem.getOptionValues(); + Map checkedMap = new HashMap(); + if(CollectionUtils.isNotEmpty(optionValues)){ + for (int i = 0; i < optionValues.size(); i++) { + FormDefinitionItemOption option = optionValues.get(i).getItemOption(); + if(option != null){ + checkedMap.put(option.getId(), true); + } + } + } + List options = formInstanceItem.getDefinitionItem().getOptions(); + if(CollectionUtils.isEmpty(options)){ + return checkCellTextVoList; + } + + checkCellTextVoList.add(new FormInstanceOptionExportVo(formInstanceItem.getDefinitionItem().getName()+":", FormDefinitionItem.TYPE_CHECK, true)); + appendEmptyCellTextVo(checkCellTextVoList); + for (FormDefinitionItemOption option : options) { + String optionValue = option.getValue() + ":"; + /*if(index == 0){ + optionValue = formInstanceItem.getDefinitionItem().getName() + optionValue; + }*/ + checkCellTextVoList.add(new FormInstanceOptionExportVo(optionValue, FormDefinitionItem.TYPE_CHECK, true)); + Boolean checked = checkedMap.get(option.getId()); + if(BooleanUtils.isTrue(checked)){ + //方形勾选框 + checkCellTextVoList.add(new FormInstanceOptionExportVo("\u2611", FormDefinitionItem.TYPE_CHECK, false)); + }else{ + //空心方形 + checkCellTextVoList.add(new FormInstanceOptionExportVo("□", FormDefinitionItem.TYPE_CHECK, false)); + } + //index++; + } + + if(checkCellTextVoList.size() % 4 != 0){ + checkCellTextVoList.add(new FormInstanceOptionExportVo("", FormDefinitionItem.TYPE_CHECK, true)); + checkCellTextVoList.add(new FormInstanceOptionExportVo("", FormDefinitionItem.TYPE_CHECK, false)); + } + return checkCellTextVoList; + } + + /** + * 表格单元格设置文字 + * @param cell + * @param text + */ + private void setXWPFTableCellText(XWPFTableCell cell, String text) { + //先删除单元格内的段落,只保留一个段落 + CTTc ctTc = cell.getCTTc(); + int psize = ctTc.sizeOfPArray(); + for(int pIndex = 1; pIndex < psize; pIndex++){ + ctTc.removeP(1); + } + CTTcPr CTTcPr = ctTc.addNewTcPr(); + //设置单元格宽度(固定大小) + //CTTcPr.addNewTcW().setW(new BigInteger("2075")); + //垂直居中 + CTTcPr.addNewVAlign().setVal(STVerticalJc.CENTER); + + CTP ctP = (ctTc.sizeOfPArray() == 0) ? ctTc.addNewP() : ctTc.getPArray(0); + XWPFParagraph par = new XWPFParagraph(ctP); + XWPFRun run = par.createRun(); + CTRPr CTRPr = run.getCTR().addNewRPr(); + //设置字体 + CTFonts rFonts = CTRPr.addNewRFonts(); + rFonts.setAscii("宋体"); + rFonts.setHAnsi("宋体"); + //设置字体大小 + //CTHpsMeasure CTHpsMeasure = CTRPr.addNewSz(); + //CTHpsMeasure.setVal(new BigInteger("24")); + run.setText(text); + } + + /** + * 合并单元格 + * @param row + * @param cellIndex + */ + private void mergeTableCell(XWPFTableRow row, int cellIndex, int mergeCellCount) { + XWPFTableCell cell = row.getCell(cellIndex); + //单元格熟悉 + CTTcPr CTTcPr = cell.getCTTc().addNewTcPr(); + //合并单元格 + CTDecimalNumber CTDecimalNumber = CTTcPr.addNewGridSpan(); + CTDecimalNumber.setVal(new BigInteger(mergeCellCount+"")); + //合并单元格后,删除被合并的单元格 + for(int i = 0; i < mergeCellCount - cellIndex; i++){ + row.getCtRow().removeTc(cellIndex + 1); + } + //删除单元格内的段落,只保留一个段落 + CTTc ctTc = cell.getCTTc(); + int psize = ctTc.sizeOfPArray(); + for(int pIndex = 1; pIndex < psize; pIndex++){ + ctTc.removeP(1); + } + } + + /** + * 设置单元格段落文字水平对齐方式 + * @param cell + * @param isOptionName + */ + private void setXWPFTableCellParagraphAlignment(XWPFTableCell cell, Boolean isOptionName) { + XWPFParagraph paragraph = cell.getParagraph(); + if(isOptionName){ + //表单元素名称列右对齐 + paragraph.setAlignment(ParagraphAlignment.RIGHT); + }else{ + //表单元素内容列左对齐 + paragraph.setAlignment(ParagraphAlignment.LEFT); + } + } + + } Index: ssts-customform/src/main/java/com/forgon/disinfectsystem/customform/forminstance/service/FormInstanceManager.java =================================================================== diff -u -r36524 -r39278 --- ssts-customform/src/main/java/com/forgon/disinfectsystem/customform/forminstance/service/FormInstanceManager.java (.../FormInstanceManager.java) (revision 36524) +++ ssts-customform/src/main/java/com/forgon/disinfectsystem/customform/forminstance/service/FormInstanceManager.java (.../FormInstanceManager.java) (revision 39278) @@ -4,6 +4,8 @@ import java.util.List; import java.util.Map; +import javax.servlet.ServletOutputStream; + import com.forgon.disinfectsystem.entity.customform.forminstance.FormInstance; import com.forgon.tools.hibernate.BasePoManager; @@ -51,4 +53,11 @@ */ public void batchDeleteFormInstanceById(Collection formInstanceIds); + /** + * 不良事件导出 + * @param formInstance + * @param servletOutputStream + */ + public void exportAdverseEventFormInstance(FormInstance formInstance, ServletOutputStream servletOutputStream) throws Exception ; + }