package cn.hmsoft.ltc.common.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.poi.hssf.OldExcelFormatException;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFShape;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFSimpleShape;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.util.Units;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.poi.xwpf.usermodel.Document;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.TextAlignment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFRun.FontCharRange;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.impl.xb.xmlschema.SpaceAttribute;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFldChar;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STFldCharType;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr;
import org.springframework.util.StringUtils;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import cn.hmsoft.ltc.common.constants.LtContext;
import cn.hmsoft.ltc.model.Course;
import cn.hmsoft.ltc.model.CourseQuestion;
import cn.hmsoft.ltc.model.DetailTable;
import cn.hmsoft.ltc.model.QuestionType;
import cn.hmsoft.ltc.model.Subject;
import cn.hmsoft.ltc.model.TestPaper;
import cn.hmsoft.ltc.service.iface.CourseService;
import cn.hmsoft.ltc.service.impl.CourseServiceImpl;


/**
 * 
 * @author zq
 *
 */
public class POIUtil {
	
	private static CourseService courseService = new CourseServiceImpl();

	private POIUtil() {}
	
	public static Map<String, Object> readExcel(final File excelFile, List<Course> exsitCourseList) throws SQLException {
		InputStream is = null;
		try {
			is = new BufferedInputStream(new FileInputStream(excelFile));
			if (excelFile.getName().toLowerCase().endsWith("xls")) {
				return readFromXls(is, exsitCourseList);
			} else if (excelFile.getName().toLowerCase().endsWith("xlsx")) {
				return readFromXlsx(is, exsitCourseList);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (OldExcelFormatException e) {
			throw e; 
		}
		finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return null;
	}
	
	private static Map<String, Object> readFromXls(final InputStream is, List<Course> exsitCourseList) throws SQLException {
		HSSFWorkbook book = null;
		final Map<String, Object> result = new HashMap<String, Object>();
		final List<Course> list = new ArrayList<Course>();
		final StringBuilder errorSb = new StringBuilder();
		final Map<String, String> existCourseMap = new HashMap<String, String>();
		for (Course c : exsitCourseList) {
			existCourseMap.put(c.getCode(), c.getName());
		}
		try {
			book = new HSSFWorkbook(is);
        	final HSSFSheet sheet = book.getSheetAt(0);  
            int lastRow = sheet.getLastRowNum();
            for (int m=1; m<=lastRow; m++) {
            	final HSSFRow row = sheet.getRow(m);
            	row.getCell(0).setCellType(CellType.STRING);
            	row.getCell(1).setCellType(CellType.STRING);
            	row.getCell(2).setCellType(CellType.STRING);
            	row.getCell(3).setCellType(CellType.STRING);
            	row.getCell(4).setCellType(CellType.STRING);
            	row.getCell(5).setCellType(CellType.STRING);
            	row.getCell(6).setCellType(CellType.STRING);
            	row.getCell(7).setCellType(CellType.STRING);
            	row.getCell(8).setCellType(CellType.STRING);
            	row.getCell(9).setCellType(CellType.STRING);
            	String courseCode = row.getCell(0).getStringCellValue().trim();
            	String courseName = row.getCell(1).getStringCellValue().trim();
            	String chapers = row.getCell(2).getStringCellValue().trim();
            	String teachBook = row.getCell(3).getStringCellValue().trim();
            	String editor = row.getCell(4).getStringCellValue();
            	String edition = row.getCell(5).getStringCellValue();
            	String press = row.getCell(6).getStringCellValue();
            	String teachOutline = row.getCell(7).getStringCellValue();
            	String schoolsName = row.getCell(8).getStringCellValue();
            	String batchNumber = row.getCell(9).getStringCellValue();

            	//赋值
            	final Course courplan = new Course();
            	courplan.setCode(courseCode);
            	courplan.setName(courseName);
            	courplan.setChapterNumber(Integer.valueOf(chapers));
            	courplan.setTeachBook(teachBook);
            	courplan.setTeachOutline(teachOutline);
            	courplan.setSchoolName(schoolsName);
            	courplan.setBatchNumber(batchNumber);
            	courplan.setEditor(editor);
            	courplan.setEdition(edition);
            	courplan.setPress(press);
            	courplan.setRemark("");
            	boolean flag = courseService.checkCode(courseCode);
            	if (existCourseMap.get(courseCode) != null || flag==false) {
            		errorSb.append("第").append(m).append("行,课程编码:'" ).append(courseCode).append("'已经存在或重复;");
            	}else if(batchNumber.length()!=6) {
            		errorSb.append("第").append(m).append("行,批次:'" ).append(courseCode).append("'批次应该为6位数，格式如YYMMRR;");
            	}else {
            		existCourseMap.put(courseCode, courseName);
            		list.add(courplan);
            	}
            }
		} catch (IOException e) {
			errorSb.append("导入错误:").append(e.getMessage()).append(";");
			e.printStackTrace();
		} catch (OldExcelFormatException e) {
			throw e; 
		} finally {
			if (book != null) {
				try {
					book.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		result.put("data", list);
		result.put("errMsg", errorSb.toString());
		return result;
	}
	
	private static Map<String, Object> readFromXlsx(final InputStream is, List<Course> exsitCourseList) {
		XSSFWorkbook book = null;
		final Map<String, Object> result = new HashMap<String, Object>();
		final List<Course> list = new ArrayList<Course>();
		final StringBuilder errorSb = new StringBuilder();
		final Map<String, String> existCourseMap = new HashMap<String, String>();
		for (Course c : exsitCourseList) {
			existCourseMap.put(c.getCode(), c.getName());
		}
		try {
            book = new XSSFWorkbook(is);
            XSSFSheet sheet = book.getSheetAt(0);  
            int lastRow = sheet.getLastRowNum();
            // 将数据项存入map(除去表头即第一行)  
            for (int m=1; m<=lastRow; m++) {
            	final XSSFRow row = sheet.getRow(m);
            	row.getCell(0).setCellType(CellType.STRING);
            	row.getCell(1).setCellType(CellType.STRING);
            	row.getCell(2).setCellType(CellType.STRING);
            	row.getCell(3).setCellType(CellType.STRING);
            	row.getCell(4).setCellType(CellType.STRING);
            	row.getCell(5).setCellType(CellType.STRING);
            	row.getCell(6).setCellType(CellType.STRING);
            	row.getCell(7).setCellType(CellType.STRING);
            	row.getCell(8).setCellType(CellType.STRING);
            	row.getCell(9).setCellType(CellType.STRING);
            	String courseCode = row.getCell(0).getStringCellValue();
            	String courseName = row.getCell(1).getStringCellValue();
            	String chapers = row.getCell(2).getStringCellValue();
            	String teachBook = row.getCell(3).getStringCellValue();
            	String editor = row.getCell(4).getStringCellValue();
            	String edition = row.getCell(5).getStringCellValue();
            	String press = row.getCell(6).getStringCellValue();
            	String teachOutline = row.getCell(7).getStringCellValue();
            	String schoolName = row.getCell(8).getStringCellValue();
            	String batchNumber = row.getCell(9).getStringCellValue();
            	
            	final Course courplan = new Course();
            	courplan.setCode(courseCode);
            	courplan.setName(courseName);
            	courplan.setChapterNumber(Integer.valueOf(chapers));
            	courplan.setTeachBook(teachBook);
            	courplan.setTeachOutline(teachOutline);
            	courplan.setSchoolName(schoolName);
            	courplan.setBatchNumber(batchNumber);
            	courplan.setEditor(editor);
            	courplan.setEdition(edition);
            	courplan.setPress(press);
            	courplan.setRemark("");
            	//add
            	if (existCourseMap.get(courseCode) != null) {
            		existCourseMap.put(courseCode, courseName);
            		errorSb.append("第").append(m).append("行,课程编码:'" ).append(courseCode).append("'已经存在;");
            	} else if(batchNumber.length()!=6) {
            		errorSb.append("第").append(m).append("行,批次【'" ).append(batchNumber).append("'】，批次应该为6位数，格式如【210701】;");
            	} else {
            		list.add(courplan);
            	}
            }
		} catch (IOException e) {
			errorSb.append("导入错误:").append(e.getMessage()).append(";");
			e.printStackTrace();
		} finally {
			if (book != null) {
				try {
					book.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		result.put("data", list);
		result.put("errMsg", errorSb.toString());
		return result;
	}
	
	
	/**
	 * 导出计划.
	 * @param path
	 * @param planList
	 */
	public static void writeToXlsx(final List<Course> planList, final String path) {
		HSSFWorkbook workbook = new HSSFWorkbook();
		HSSFSheet sheet = workbook.createSheet("课程");
		sheet.setDefaultColumnWidth((short) 15);
		HSSFRow row = sheet.createRow(0);
		HSSFCell cell0 = row.createCell(0);
		HSSFCell cell1 = row.createCell(1);
		HSSFCell cell2 = row.createCell(2);
		HSSFCell cell3 = row.createCell(3);
		HSSFCell cell4 = row.createCell(4);
		HSSFCell cell5 = row.createCell(5);
		HSSFCell cell6 = row.createCell(6);
		HSSFCell cell7 = row.createCell(7);
		HSSFCell cell8 = row.createCell(7);
		HSSFCell cell9 = row.createCell(7);
		HSSFCell cell10 = row.createCell(7);
		cell0.setCellValue(new HSSFRichTextString("课程代码"));
		cell1.setCellValue(new HSSFRichTextString("课程名称"));
		cell2.setCellValue(new HSSFRichTextString("章节数"));
		cell3.setCellValue(new HSSFRichTextString("教材"));
		cell4.setCellValue(new HSSFRichTextString("编者"));
		cell5.setCellValue(new HSSFRichTextString("版次"));
		cell6.setCellValue(new HSSFRichTextString("出版社"));
		cell7.setCellValue(new HSSFRichTextString("教材大纲"));
		cell8.setCellValue(new HSSFRichTextString("学校"));
		cell9.setCellValue(new HSSFRichTextString("批次"));
		cell10.setCellValue(new HSSFRichTextString("备注"));
		for (int i=0; i<planList.size(); i++) {
			HSSFRow datarow = sheet.createRow(i+1);
			Course plan = planList.get(i);
			HSSFCell datacell0 = datarow.createCell(0);
			datacell0.setCellType(CellType.STRING);
			datacell0.setCellValue(new HSSFRichTextString(plan.getCode()));
			HSSFCell datacell1 = datarow.createCell(1);
			datacell1.setCellType(CellType.STRING);
			datacell1.setCellValue(new HSSFRichTextString(plan.getName()));
			HSSFCell datacell2 = datarow.createCell(2);
			datacell2.setCellType(CellType.STRING);
			datacell2.setCellValue(new HSSFRichTextString(plan.getChapterNumber() + ""));
			HSSFCell datacell3 = datarow.createCell(3);
			datacell3.setCellType(CellType.STRING);
			datacell3.setCellValue(new HSSFRichTextString(plan.getTeachBook()));
			
			HSSFCell datacell4 = datarow.createCell(4);
			datacell4.setCellType(CellType.STRING);
			datacell4.setCellValue(new HSSFRichTextString(plan.getTeachOutline()));
			
			HSSFCell datacell5 = datarow.createCell(5);
			datacell5.setCellType(CellType.STRING);
			datacell5.setCellValue(new HSSFRichTextString(plan.getEditor()));
			
			HSSFCell datacell6 = datarow.createCell(6);
			datacell6.setCellType(CellType.STRING);
			datacell6.setCellValue(new HSSFRichTextString(plan.getEdition()));
			
			HSSFCell datacell7 = datarow.createCell(7);
			datacell7.setCellType(CellType.STRING);
			datacell7.setCellValue(new HSSFRichTextString(plan.getPress()));
			
			HSSFCell datacell8 = datarow.createCell(8);
			datacell8.setCellType(CellType.STRING);
			datacell8.setCellValue(new HSSFRichTextString(plan.getSchoolName()));
			HSSFCell datacell9 = datarow.createCell(9);
			datacell9.setCellType(CellType.STRING);
			datacell9.setCellValue(new HSSFRichTextString(plan.getBatchNumber()));
			HSSFCell datacell10 = datarow.createCell(10);
			datacell10.setCellType(CellType.STRING);
			datacell10.setCellValue(new HSSFRichTextString(plan.getRemark()));
		}
		try {
			FileOutputStream fos = new FileOutputStream(new File(path));
			workbook.write(fos);
			fos.close();
			workbook.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 导出细目表.
	 * @param detailTableList 细目表
	 * @param chapters 章节数
	 * @param keyChapters 重点章节
	 * @param path 保存路径
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	public static void writeDetailTableToXls(List<DetailTable> detailTableList, int chapters, String keyChapters, String path,TestPaper paper) throws IOException, ClassNotFoundException {
		String fileName = paper.getPaperNo();
		FileOutputStream fos = new FileOutputStream(path + fileName+"_细目表.xls");
		HSSFWorkbook wb = new HSSFWorkbook();
		HSSFSheet sheet = wb.createSheet("细目表");
		sheet.setDefaultColumnWidth(6);
		sheet.setDefaultRowHeight((short) (1.2 * 256));
		//
		CellRangeAddress capRange = new CellRangeAddress(0, 2, 0, 2);
		setRangeMergeBorder(capRange, sheet);//设置边框
		sheet.addMergedRegion(capRange);
		drawSlashUpToDown((short)0, 0, (short)3, 3, sheet);//跨3行3列
		
        HSSFFont fontTitle = wb.createFont();
        fontTitle.setFontHeightInPoints((short) 12);  
        fontTitle.setFontName("新宋体");
        fontTitle.setColor(HSSFColorPredefined.BLACK.getIndex());
        //fontTitle.setBold(true);
        //居左样式
		HSSFCellStyle styleNomal = wb.createCellStyle();
		styleNomal.setAlignment(HorizontalAlignment.LEFT);
		styleNomal.setFont(fontTitle);//调用字体样式对象  
		styleNomal.setWrapText(true);//重要!
		//居中样式
		HSSFCellStyle styleCenter = wb.createCellStyle();
		styleCenter.setAlignment(HorizontalAlignment.CENTER);
		styleCenter.setFont(fontTitle);//调用字体样式对象  
		styleCenter.setWrapText(true);//重要!
		
		styleNomal.setBorderTop(BorderStyle.THIN);
		styleNomal.setBorderLeft(BorderStyle.THIN);
		styleNomal.setBorderTop(BorderStyle.THIN);
		styleNomal.setBorderBottom(BorderStyle.THIN);
		styleNomal.setBorderRight(BorderStyle.THIN);
		
		styleCenter.setBorderTop(BorderStyle.THIN);
		styleCenter.setBorderLeft(BorderStyle.THIN);
		styleCenter.setBorderTop(BorderStyle.THIN);
		styleCenter.setBorderBottom(BorderStyle.THIN);
		styleCenter.setBorderRight(BorderStyle.THIN);
		
		HSSFRow row0 = sheet.createRow(0);
		HSSFRow row1 = sheet.createRow(1);//章节数字行
		HSSFRow row2 = sheet.createRow(2);//标识重点章节行
		//章节/题型
		final String text = "             章节\n\n题型";
		HSSFCell cellCap = row0.createCell(0);
		cellCap.setCellStyle(styleNomal);
		cellCap.setCellValue(text);
		
		//17道题型
		CellRangeAddress chRange = new CellRangeAddress(0, 0, 3, chapters + 3 - 1);
		setRangeMergeBorder(chRange, sheet);//设置边框
		sheet.addMergedRegion(chRange);
		HSSFCell cellHL = row0.createCell(3);
		cellHL.setCellStyle(styleCenter);
		cellHL.setCellValue("题量分布");
		
		Map<Integer, Integer> keyChMap = new HashMap<Integer, Integer>();
		String[] keys = keyChapters.split(",");
		for (String key : keys) {
			keyChMap.put(Integer.valueOf(key), Integer.valueOf(key));
		}
		for (int i=0; i<chapters; i++) {
			HSSFCell chHeaderCell = row1.createCell(3 + i);
			chHeaderCell.setCellValue((i+1));
			chHeaderCell.setCellStyle(styleCenter);
			//输出重点章节标志
			HSSFCell keyChapterCell = row2.createCell(3 + i);
			if (keyChMap.get((i+1)) != null) {
				keyChapterCell.setCellValue("√");
			} else {
				keyChapterCell.setCellValue("");
			}
			
			keyChapterCell.setCellStyle(styleCenter);
		}
		//小题分
		CellRangeAddress xflRange = new CellRangeAddress(0, 2, chapters + 3, chapters + 3);
		setRangeMergeBorder(xflRange, sheet);//设置边框
		sheet.addMergedRegion(xflRange);
		HSSFCell xtfCell = row0.createCell(chapters + 3);
		xtfCell.setCellValue("小\n题\n分");
		xtfCell.setCellStyle(styleCenter);
		//小题量
		CellRangeAddress xtlRange = new CellRangeAddress(0, 2, chapters + 3 + 1, chapters + 3 + 1);
		setRangeMergeBorder(xtlRange, sheet);//设置边框
		sheet.addMergedRegion(xtlRange);
		HSSFCell xtlCell = row0.createCell(chapters + 3 + 1);
		xtlCell.setCellValue("小\n题\n量");
		xtlCell.setCellStyle(styleCenter);
		//小计
		CellRangeAddress xjRange = new CellRangeAddress(0, 2, chapters + 3 + 2, chapters + 3 + 2);
		setRangeMergeBorder(xjRange, sheet);//设置边框
		sheet.addMergedRegion(xjRange);
		HSSFCell xjCell = row0.createCell(chapters + 3 + 2);
		xjCell.setCellValue("小\n\n计");
		xjCell.setCellStyle(styleCenter);
		
		//********************输出每个题型的细目内容*************************
		Class<DetailTable> CLAZZ = DetailTable.class;
		int totalXtl = 0;//所有行的xtl求和
		final Map<Integer, Integer> chapterXtlMap = new HashMap<Integer, Integer>();//每章节 小题量map
		final Map<Integer, Double> chapterXtfMap = new HashMap<Integer, Double>();//每章节 小题分map
		for (int j=1; j<=chapters; j++) {
			chapterXtlMap.put(j, 0);
			chapterXtfMap.put(j, 0.0);
		}
		for (int m=0; m<detailTableList.size(); m++) {
			final HSSFRow rowM = sheet.createRow(m + 3);
			DetailTable dt = detailTableList.get(m);
			
			CellRangeAddress txRange = new CellRangeAddress(m + 3, m + 3, 0, 2);
			setRangeMergeBorder(txRange, sheet);//设置边框
			sheet.addMergedRegion(txRange);
			HSSFCell txHeaderCell = rowM.createCell(0);
			txHeaderCell.setCellValue(dt.getQuestionTypeName());
			txHeaderCell.setCellStyle(styleCenter);
			//设置方法map
			int sumXtl = 0;
			for (int j=1; j<=chapters; j++) {
				try {
					HSSFCell txInputCell = rowM.createCell(3 + j - 1);
					Object obj = CLAZZ.getMethod("getTx" + j + "Nums", null).invoke(dt, null);
					txInputCell.setCellValue(obj.toString());
					txInputCell.setCellStyle(styleCenter);
					int tempXtl = Integer.parseInt(obj.toString());
					chapterXtlMap.put(j, chapterXtlMap.get(j) + tempXtl);
					chapterXtfMap.put(j, chapterXtfMap.get(j) + tempXtl * dt.getItemScore());
					sumXtl += tempXtl;//记录该行的小题量
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					e.printStackTrace();
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				} catch (SecurityException e) {
					e.printStackTrace();
				}
			}
			totalXtl += sumXtl;
			//输出该行的小题分
			HSSFCell txXtfCell = rowM.createCell(3 + chapters);
			txXtfCell.setCellValue(dt.getItemScore());
			txXtfCell.setCellStyle(styleCenter);
			//输出该行的小体量
			HSSFCell txXtlCell = rowM.createCell(3 + chapters + 1);
			txXtlCell.setCellValue(sumXtl);
			txXtlCell.setCellStyle(styleCenter);
			//输出该行的 小计
			HSSFCell txXjCell = rowM.createCell(3 + chapters + 2);
			txXjCell.setCellValue(sumXtl * dt.getItemScore());
			txXjCell.setCellStyle(styleCenter);
		}
		
		//********************统计行***********************************
		HSSFRow tjRow = sheet.createRow(3 + detailTableList.size());//统计行1
		HSSFRow tjNextRow = sheet.createRow(3 + detailTableList.size() + 1);//统计行2
		CellRangeAddress hjRange = new CellRangeAddress(3 + detailTableList.size(), 3 + detailTableList.size() + 1, 0, 2);
		setRangeMergeBorder(hjRange, sheet);
		sheet.addMergedRegion(hjRange);
		HSSFCell hjCell = tjRow.createCell(0);
		hjCell.setCellValue("合计");
		hjCell.setCellStyle(styleCenter);
		
		DecimalFormat nf = new DecimalFormat("###");
		for (int i=0; i<chapters; i++) {
			CellRangeAddress tjRange_i = new CellRangeAddress(3 + detailTableList.size(), 3 + detailTableList.size() + 1, 3 + i, 3 + i);
			setRangeMergeBorder(tjRange_i, sheet);
			sheet.addMergedRegion(tjRange_i);
			//drawSlashUpToDown((short)(3+i), 5, (short)(3 + i + 1), 5 + 2, sheet);//跨2行1列
			HSSFCell chHeaderCell = tjRow.createCell(3 + i);
			chHeaderCell.setCellValue(chapterXtlMap.get((i+1)) + "/" + nf.format(chapterXtfMap.get((i+1))));//每章节对应的 章节体量/章节总题分
			chHeaderCell.setCellStyle(styleCenter);
		}
		//总分汇总
		CellRangeAddress tjRange = new CellRangeAddress(3 + detailTableList.size(), 3 + detailTableList.size() + 1, chapters + 3, chapters + 3 + 2);
		setRangeMergeBorder(tjRange, sheet);
		sheet.addMergedRegion(tjRange);
		HSSFCell tjCell = tjRow.createCell(chapters + 3);
		tjCell.setCellValue(totalXtl + "/100");//总体量/总题分
		tjCell.setCellStyle(styleCenter);
		
		wb.write(fos);
		fos.flush();
		fos.close();
		wb.close();
	}
	
	//合并单元格后 加边框
	public static void setRangeMergeBorder(CellRangeAddress range, HSSFSheet sheet) {
		RegionUtil.setBorderBottom(BorderStyle.THIN, range, sheet);
		RegionUtil.setBorderRight(BorderStyle.THIN, range, sheet);
		RegionUtil.setBorderLeft(BorderStyle.THIN, range, sheet);
		RegionUtil.setBorderTop(BorderStyle.THIN, range, sheet);
	}
	
	//上到下 斜对角线
	/**
	 * 
	 * @param fromCol 开始列
	 * @param fromRow 开始行
	 * @param toCol 结束列
	 * @param toRow 结束行
	 * @param sheet
	 */
	public static void drawSlashUpToDown(short fromCol, int fromRow, short toCol, int toRow, HSSFSheet sheet) {
		HSSFClientAnchor anchor = new HSSFClientAnchor();
		HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
		//试着改变第二个参数和第六个参数来改变线的位置
		anchor.setAnchor(fromCol, fromRow, 0, 0, toCol, toRow, 0, 0);
		HSSFSimpleShape line = patriarch.createSimpleShape(anchor);
		line.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
		line.setLineStyle(HSSFShape.LINESTYLE_SOLID);
		// 在NPOI中线的宽度12700表示1pt,所以这里是0.5pt粗的线条。
		line.setLineWidth(6350);
	}
	
	/**
	 * 读取文档各段落的文本.
	 * @param path
	 * @return
	 * @throws Exception 
	 */
    public static String[] readWordParaCaption(String path) throws Exception {
    	String[] paras = null;
    	XWPFDocument word = new XWPFDocument(new FileInputStream(path));
		try {
			List<XWPFParagraph> paragraphs = word.getParagraphs();
			paras = new String[paragraphs.size()];
			for (int i=0; i<paragraphs.size(); i++) {
				XWPFParagraph paragraph = paragraphs.get(i);
				StringBuffer text = new StringBuffer();
				List<XWPFRun> runs = paragraph.getRuns();
				
				for (XWPFRun run : runs) {
					Node runNode = run.getCTR().getDomNode();
					text.append(getText(runNode));
				}
				
				paras[i] = text.toString().trim();
			}
		} finally {
			word.close();
		}
		return paras;
    }
    
    /**
	 * 获取字符串
	 * 
	 * @param runNode
	 * @return
	 */
	private static String getText(Node runNode) {
		Node textNode = getChildNode(runNode, "w:t");
		if (textNode == null) {
			return "";
		}
		if (textNode.getFirstChild() == null) {
			return "";
		}
		return textNode.getFirstChild().getNodeValue();
	}
	
	private static Node getChildNode(Node node, String nodeName) {
		if (!node.hasChildNodes()) {
			return null;
		}
		NodeList childNodes = node.getChildNodes();
		for (int i = 0; i < childNodes.getLength(); i++) {
			Node childNode = childNodes.item(i);
			if (nodeName.equals(childNode.getNodeName())) {
				return childNode;
			}
			childNode = getChildNode(childNode, nodeName);
			if (childNode != null) {
				return childNode;
			}
		}
		return null;
	}
    
	/**
	 * 纯净试题word 不包含答案：
	 * @param fromPath
	 * @param asPath
	 * @throws Exception 
	 */
	public static void createAndWriteQsWord(String fromQuesSm, String asPath) throws Exception {
		String emptyDocx = System.getProperty("user.dir") + File.separator + "resources" + File.separator + "word-factory" + File.separator + "empty.docx";
    	File asDocxFile = new File(asPath);
		FileUtils.copyFile(new File(emptyDocx), asDocxFile);
    	//目标答案文档
        XWPFDocument src1Document = new XWPFDocument(OPCPackage.open(new FileInputStream(asPath)));
    	//源ques文档
        XWPFDocument src2Document = new XWPFDocument(OPCPackage.open(new FileInputStream(fromQuesSm)));
    	
        appendToQs2(src1Document, src2Document);
        
        OutputStream desOut = new FileOutputStream(asDocxFile);
        src1Document.createNumbering();//操作_1
        src1Document.write(desOut);
        
        desOut.close();
        src1Document.close();
	}
	
	/**
	 * 查找是否有答案-通过poi方式，xml方式无法很好获取run的text，解决自动分了多个单元run的问题.
	 * @param document
	 * @return
	 */
	public static int getAnswerParaPos(XWPFDocument document) {
		List<XWPFParagraph> paras = document.getParagraphs();
		for (int i=0; i<paras.size(); i++) {
			StringBuffer text = new StringBuffer();
			List<XWPFRun> runs = paras.get(i).getRuns();
			for (XWPFRun run : runs) {
				Node runNode = run.getCTR().getDomNode();
				text.append(getText(runNode));
			}
			if (text.toString().contains("答案及评分参考：")) {
				return i;
			}
		}
		return -1;
	}
	
	/**
	 * 分拆写入答案word---仅仅针对选择题
	 * @param fromQuesSm
	 * @param asPath
	 * @param qsNo
	 * @throws Exception 
	 */
	public static void splitAndWriteAsWord(String fromQuesSm, String asPath, int qsNo) throws Exception {
		String emptyDocx = System.getProperty("user.dir") + File.separator + "resources" + File.separator + "word-factory" + File.separator + "empty.docx";
    	File asDocxFile = new File(asPath);
		FileUtils.copyFile(new File(emptyDocx), asDocxFile);
    	//目标答案文档
        XWPFDocument src1Document = new XWPFDocument(OPCPackage.open(new FileInputStream(asPath)));
    	//源ques文档
        XWPFDocument src2Document = new XWPFDocument(OPCPackage.open(new FileInputStream(fromQuesSm)));
    	
        appendToAs2(src1Document, src2Document, qsNo);
        
        OutputStream desOut = new FileOutputStream(asDocxFile);
        src1Document.createNumbering();//操作_1
        src1Document.write(desOut);
        
        desOut.close();
        src1Document.close();
	}
	
	
	/**
	 * 加粗写内容到word-试卷头
	 * @param path
	 * @param textArr
	 */
	public static void appendToPaperHeaderDocx(String path, String courseCode, String courseName, String AB, int bigQs, int smQs, int totalScore, int examMins) {
		try {
			XWPFDocument document = new XWPFDocument();
			FileOutputStream out = new FileOutputStream(new File(path));
			//绝密★启用前
			XWPFParagraph secretPara = document.createParagraph();
			secretPara.setAlignment(ParagraphAlignment.LEFT);
			XWPFRun secretRun = secretPara.createRun();
			secretRun.setBold(true);
			secretRun.setFontSize(11);
			secretRun.setText("绝密★启用前");
			secretPara.setIndentationFirstLine(480);
			createFont(secretRun, "黑体");
			
			//20  年  月湖北省高等教育自学考试
			XWPFParagraph titlePara = document.createParagraph();
			titlePara.setAlignment(ParagraphAlignment.CENTER);
			XWPFRun titleRun = titlePara.createRun();
			titleRun.setFontSize(14);
			titleRun.setText("20  年  月湖北省高等教育自学考试");
			createFont(titleRun, "宋体");
			titlePara.setSpacingAfter(150);//行间距下面
			
			XWPFParagraph courseNamePara = document.createParagraph();
			courseNamePara.setAlignment(ParagraphAlignment.CENTER);
			XWPFRun courseNameRun = courseNamePara.createRun();
			courseNameRun.setBold(true);
			courseNameRun.setFontSize(20);
			courseNameRun.setText(courseName + "  试卷" + AB);
			createFont(courseNameRun, "方正小标宋");
			
			XWPFParagraph courseCodePara = document.createParagraph();
			courseCodePara.setAlignment(ParagraphAlignment.CENTER);
			XWPFRun courseCodeRun = courseCodePara.createRun();
			courseCodeRun.setFontSize(14);
			courseCodeRun.setText("（课程代码  " + courseCode + "）");
			createFont(courseCodeRun, "宋体");
			
			XWPFParagraph quesPara = document.createParagraph();
			quesPara.setAlignment(ParagraphAlignment.LEFT);
			XWPFRun quesRun = quesPara.createRun();
			quesRun.setFontSize(11);
			quesRun.setText("本试卷共" + bigQs + "大题，" + smQs + "小题，满分" + totalScore + "分；考试时间为" + examMins + "分钟。");
			createFont(quesRun, "黑体");
			quesPara.setSpacingAfter(150);//行间距下面
			
			//注意事项开始-----
			XWPFParagraph notePara = document.createParagraph();
			notePara.setAlignment(ParagraphAlignment.LEFT);
			XWPFRun noteRun = notePara.createRun();
			//noteRun.setFontFamily("黑体", FontCharRange.cs);
			noteRun.setFontSize(11);
			noteRun.setText("注意事项：\r");
			createFont(noteRun, "黑体");
			
			XWPFParagraph note1Para = document.createParagraph();
			note1Para.setAlignment(ParagraphAlignment.LEFT);
			XWPFRun note1Run = note1Para.createRun();
			note1Run.setFontFamily("黑体", FontCharRange.cs);
			note1Run.setFontSize(11);
			note1Run.setText("1.答题前，考生先将自己的准考证号、姓名、课程代码、课程名称填写清楚，并认真核准条形码上的信息，在答题卡上指定的位置粘贴条形码。\r");
			note1Para.setIndentationFirstLine(480);
			createFont(note1Run, "黑体");
			
			XWPFParagraph note2Para = document.createParagraph();
			note2Para.setAlignment(ParagraphAlignment.LEFT);
			XWPFRun note2Run = note2Para.createRun();
			note2Run.setFontFamily("黑体", FontCharRange.cs);
			note2Run.setFontSize(11);
			note2Run.setText("2.选择题的作答：考生必须使用2B铅笔，在答题卡对应的题号上填涂选择项。应使用正确填涂方法： ");
			InputStream is = new FileInputStream(System.getProperty("user.dir") + File.separator + "resources" + File.separator + "black.jpg");
			note2Run.addPicture(is, XWPFDocument.PICTURE_TYPE_JPEG, "", Units.toEMU(30), Units.toEMU(10));
			note2Run.setText("，将选择项涂满涂黑。 若需对答案进行修改，用橡皮擦擦除干净后再重新填涂。答在试卷、草稿纸上无效。\r");//多次setText 内容会拼接，不是覆盖!
			note2Para.setIndentationFirstLine(480);
			createFont(note2Run, "黑体");
			
			XWPFParagraph note3Para = document.createParagraph();
			note3Para.setAlignment(ParagraphAlignment.LEFT);
			XWPFRun note3Run = note3Para.createRun();
			note3Run.setFontFamily("黑体", FontCharRange.cs);
			note3Run.setFontSize(11);
			note3Run.setText("3.非选择题的作答：必须使用黑色墨水签字笔作答。答题时要求依试题顺序作答，首先在“大题号”列依次注明大题号，在“小题号”列依次注明小题号，按题号顺序依次在答题卡规定的区域内作答，超出“非选择题答题区”的部分作答无效。答在试卷、草稿纸上无效。\r");
			note3Para.setIndentationFirstLine(480);
			createFont(note3Run, "黑体");
			
			XWPFParagraph note4Para = document.createParagraph();
			note4Para.setAlignment(ParagraphAlignment.LEFT);
			XWPFRun note4Run = note4Para.createRun();
			note4Run.setFontFamily("黑体", FontCharRange.cs);
			note4Run.setFontSize(11);
			note4Run.setText("4.考生必须保持答题卡的清洁。考试结束后，请将本试卷和答题卡一并上交。\r");
			note4Para.setIndentationFirstLine(480);
			createFont(note4Run, "黑体");
			
			document.write(out);
			out.close();
			document.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private static void createFont(XWPFRun run, String caption) {
		CTFonts font = run.getCTR().addNewRPr().addNewRFonts();
		font.setEastAsia(caption);
		font.setAscii(caption);
		font.setCs(caption);
		font.setHAnsi(caption);
	}
    
    public static void createFooter(XWPFDocument document, String courseCode, String courseName, boolean isAnswerDocx, String AB) {
        CTP ctp = CTP.Factory.newInstance();  
        XWPFParagraph codePara = new XWPFParagraph(ctp, document);  
       
        XWPFRun r0 = codePara.createRun();
        r0.setText(courseCode);
        r0.setFontSize(10);  
        CTFonts fontss = r0.getCTR().addNewRPr().addNewRFonts();  
        fontss.setAscii("Times New Roman");  
        fontss.setEastAsia("Times New Roman");  
        fontss.setHAnsi("Times New Roman");  
        
        XWPFRun r1 = codePara.createRun();  
        if (isAnswerDocx) {
        	r1.setText("·" + courseName + "试题答案及评分参考第");
        } else {
        	r1.setText("·" + courseName + "试卷" + AB + "第");
        	//r1.setText(courseCode + "·" + courseName + "试卷第");
        }
        r1.setFontSize(10);  
        CTFonts fonts = r1.getCTR().addNewRPr().addNewRFonts();  
        fonts.setAscii("宋体");  
        fonts.setEastAsia("宋体");  
        fonts.setHAnsi("宋体");  
  
        r1 = codePara.createRun();  
        CTFldChar fldChar = r1.getCTR().addNewFldChar();  
        fldChar.setFldCharType(STFldCharType.Enum.forString("begin"));  
  
        r1 = codePara.createRun();  
        CTText ctText = r1.getCTR().addNewInstrText();  
        ctText.setStringValue("PAGE  \\* MERGEFORMAT");  
        ctText.setSpace(SpaceAttribute.Space.Enum.forString("preserve"));  
        r1.setFontSize(10); 
        
//      XWPFRun r2 = codePara.createRun();
//      r2 = codePara.createRun();  
//      CTText ctText = r2.getCTR().addNewInstrText();  
//      ctText.setStringValue("PAGE  \\* MERGEFORMAT");  
//      ctText.setSpace(SpaceAttribute.Space.Enum.forString("preserve"));  
//      r2.setFontSize(10);  
//      fontss.setAscii("Times New Roman");  
//      fontss.setEastAsia("Times New Roman");  
//      fontss.setHAnsi("Times New Roman");  
  
        fldChar = r1.getCTR().addNewFldChar();  
        fldChar.setFldCharType(STFldCharType.Enum.forString("end"));  
  
        r1 = codePara.createRun();  
        r1.setText("页（共");  
        r1.setFontSize(10);  
  
        r1 = codePara.createRun();  
        fldChar = r1.getCTR().addNewFldChar();  
        fldChar.setFldCharType(STFldCharType.Enum.forString("begin"));  
  
        r1 = codePara.createRun();  
        ctText = r1.getCTR().addNewInstrText();  
        ctText.setStringValue("NUMPAGES  \\* MERGEFORMAT ");  
        ctText.setSpace(SpaceAttribute.Space.Enum.forString("preserve"));  
        r1.setFontSize(10);  
        
//        XWPFRun r3 = codePara.createRun();
//        r3 = codePara.createRun();  
//        ctText = r3.getCTR().addNewInstrText();  
//        ctText.setStringValue("NUMPAGES  \\* MERGEFORMAT ");  
//        ctText.setSpace(SpaceAttribute.Space.Enum.forString("preserve"));  
//        r3.setFontSize(10);  
//        fontss.setAscii("Times New Roman");  
//        fontss.setEastAsia("Times New Roman");  
//        fontss.setHAnsi("Times New Roman");  
  
        fldChar = r1.getCTR().addNewFldChar();  
        fldChar.setFldCharType(STFldCharType.Enum.forString("end"));  
  
        r1 = codePara.createRun();  
        r1.setText("页）");  
        r1.setFontSize(10);  
  
        codePara.setAlignment(ParagraphAlignment.CENTER);  
        codePara.setVerticalAlignment(TextAlignment.CENTER);  
        //codePara.setBorderTop(Borders.THICK);  
        XWPFParagraph[] newparagraphs = new XWPFParagraph[1];  
        newparagraphs[0] = codePara;  
        CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();  
        XWPFHeaderFooterPolicy headerFooterPolicy = new XWPFHeaderFooterPolicy(document, sectPr);  
        headerFooterPolicy.createFooter(STHdrFtr.DEFAULT, newparagraphs);  
    }
    
    //组卷题目文档数组
	public static Map<QuestionType, List<String>> getSrcDocxArr(Map<Integer, QuestionType> quesMap, String srcDir, List<CourseQuestion> cqList) {
		Map<QuestionType, List<String>> retMap = new LinkedHashMap<QuestionType, List<String>>();
		
		List<String> headList = new ArrayList<String>();
		headList.add(srcDir + File.separator + "0.docx");
		retMap.put(null, headList);
		
		int qsNo = 1;
		for (CourseQuestion cq : cqList) {
			List<String> docList = new ArrayList<String>();
			docList.add(srcDir + File.separator + (cq.getOrd() * 100) + ".docx");
			for (int i=0; i<cq.getQuesNums(); i++) {
				docList.add(srcDir + File.separator + qsNo + ".docx");
				qsNo++;
			}
			retMap.put(quesMap.get(cq.getQuesTypeId()), docList);
		}

		return retMap;
	}
	
    /**
     * 合并试卷方法.
     * @param srcDocxs
     * @param destDocx
     * @param courseCode
     * @param courseName
     * @param isAnswerDocx 是否答案文档
     * @return
     */
    public static void mergeDoc(Map<QuestionType, List<String>> srcDocxMap, String destDocx, String courseCode, String courseName, 
    		String AB) throws Exception {
        OutputStream dest = null;
        dest = new FileOutputStream(destDocx);
        OPCPackage src1Package = OPCPackage.open(new FileInputStream(srcDocxMap.get(null).get(0)));
        XWPFDocument src1Document = new XWPFDocument(src1Package);
        
        Iterator<QuestionType> it = srcDocxMap.keySet().iterator();
        while (it.hasNext()) {
        	QuestionType qt = it.next();
        	if (qt != null) {
        		List<String> list = srcDocxMap.get(qt);
                for (Integer i=0; i< list.size(); i++) {
                    OPCPackage src2Package = OPCPackage.open(new FileInputStream(list.get(i)));
                    XWPFDocument src2Document = new XWPFDocument(src2Package);
                    //单选、多选 选项格式化,i==0是每个题型的 题干描述word 从i==1开始才是每个题型对应的 试题
                    try {
                    	if (i>0 && (qt.getId() == LtContext.TYPE_SINGLE_SELECT_ID || qt.getId() == LtContext.TYPE_MULTI_SELECT_ID)) {
                    		boolean isSingleSelect = false;
                    		if (qt.getId() == LtContext.TYPE_SINGLE_SELECT_ID) {
                    			isSingleSelect = true;
                    		}
                    		buildPaperChoiceFormat(src1Document, src2Document, isSingleSelect);
                    	} else {
                        	appendBody(src1Document, src2Document);
                    	}
                    } catch(Exception e) {
                    	e.printStackTrace();
                    	//DialogUtil.showAlertDialog(GUIState.getStage(), AlertType.ERROR, "错误", e.getMessage());
                    }
                	
                    src2Document.close();
                    src2Package.close();
                }
        	}
        }
        
        src1Document.createNumbering();//操作_1
        //创建页脚
    	createFooter(src1Document, courseCode, courseName, false, AB);
        src1Document.write(dest);
        //关闭
    	dest.close();
        src1Document.close();
        src1Package.close();
    }
    
    public static void mergeAnswerDoc(Map<QuestionType, List<String>> srcDocxMap, String destDocx, String courseCode, String courseName, 
    		String AB) throws Exception {
    	String baseDocx = srcDocxMap.get(null).get(0);
    	OutputStream dest = new FileOutputStream(destDocx);
        OPCPackage src1Package = OPCPackage.open(new FileInputStream(baseDocx));//以header 头为 基础
        XWPFDocument src1Document = new XWPFDocument(src1Package);
        
        Iterator<QuestionType> it = srcDocxMap.keySet().iterator();
        while (it.hasNext()) {
        	QuestionType qt = it.next();
        	if (qt != null) {
        		List<String> list = srcDocxMap.get(qt);
        		
            	if (qt.getCorrectOptionsNum() == 1 || qt.getCorrectOptionsNum() == 2) {//选择题,多选
            		List<String> tpList = getAnPStartTemplate();
                    buildChoiceAnswerFormat(list, src1Document, tpList);
            	} else {
                    for (Integer i=0; i< list.size(); i++) {
                        InputStream item = new FileInputStream(list.get(i));   
                        OPCPackage src2Package = OPCPackage.open(item);  
                        XWPFDocument src2Document = new XWPFDocument(src2Package);  
                    	appendBody(src1Document, src2Document);
                        src2Document.close();
                        src2Package.close();
                    }
            	}
        	}
        }

        src1Document.createNumbering();//操作_1
        //创建页脚
    	createFooter(src1Document, courseCode, courseName, true, AB);
        src1Document.write(dest);
        //关闭
    	dest.close();
        src1Document.close();
        src1Package.close();

    }
    
    public static void appendBody(XWPFDocument src, XWPFDocument append) throws Exception {
        CTBody src1Body = src.getDocument().getBody();
        CTBody src2Body = append.getDocument().getBody();
  
        List<XWPFPictureData> allPictures = append.getAllPictures();
        // 记录图片合并前及合并后的ID  
        Map<String,String> map = new HashMap<String,String>();
        for (XWPFPictureData picture : allPictures) {
            String before = append.getRelationId(picture);
            //将原文档中的图片加入到目标文档中  
            String after = src.addPictureData(picture.getData(), Document.PICTURE_TYPE_PNG);
            map.put(before, after.replace("rId", "myKey"));  //操作_2
        }
        appendBodyDetail(src1Body, src2Body, map);
  
    }
  
    private static void appendBodyDetail(CTBody src, CTBody append, Map<String, String> map) throws Exception {
        XmlOptions optionsOuter = new XmlOptions();
        optionsOuter.setSaveOuter();
        String appendString = append.xmlText(optionsOuter);
        String srcString = src.xmlText();
        String prefix = srcString.substring(0, srcString.indexOf(">") + 1);
        String mainPart = srcString.substring(srcString.indexOf(">") + 1, srcString.lastIndexOf("<"));
        String sufix = srcString.substring(srcString.lastIndexOf("<"));
        String addPart = appendString.substring(appendString.indexOf(">") + 1, appendString.lastIndexOf("<"));
        if (map != null && !map.isEmpty()) {
            //对xml字符串中图片ID进行替换  
            for (Map.Entry<String, String> set : map.entrySet()) {
                addPart = addPart.replace(set.getKey(), set.getValue());
            }
            addPart = addPart.replace("myKey", "rId");//操作_3
        }
        //将两个文档的xml内容进行拼接  
        //去除<w:sectPr
        int sPos = addPart.indexOf("<w:sectPr");
        if (sPos > 0) {
        	int ePos = addPart.indexOf("</w:sectPr>");
        	addPart = addPart.substring(0, sPos) + addPart.substring(ePos + 11, addPart.length());
        }
        CTBody makeBody = CTBody.Factory.parse(prefix + mainPart + addPart + sufix);
        src.set(makeBody);
    }
    
    //追加到答案word中
    @Deprecated
    public static void appendToAs(XWPFDocument src, XWPFDocument append, int qsNo) throws Exception {
        CTBody src1Body = src.getDocument().getBody();
        CTBody src2Body = append.getDocument().getBody();
        List<XWPFPictureData> allPictures = append.getAllPictures();
        // 记录图片合并前及合并后的ID  
        Map<String,String> map = new HashMap<String,String>();
        for (XWPFPictureData picture : allPictures) {
            String before = append.getRelationId(picture);
            //将原文档中的图片加入到目标文档中  
            String after = src.addPictureData(picture.getData(), Document.PICTURE_TYPE_PNG);
            map.put(before, after.replace("rId", "myKey"));  //操作_2
        }
        //查找答案段落-从最后段落往上开始找
        String asPBody = "";
        XmlOptions optionsOuter = new XmlOptions();
        int asPos = getAnswerParaPos(append);
        CTP[] ctpArr = src2Body.getPArray();
        List<CTP> othCtpList = new ArrayList<CTP>();
        List<XWPFParagraph> ps = append.getParagraphs();
        XWPFParagraph keyP = null;
        for (int i=0; i<ctpArr.length; i++) {
        	CTP ctp = ctpArr[i];
        	if (i == asPos) {
        		asPBody = ctp.xmlText(optionsOuter);
        		keyP = ps.get(i);
        	}
        	if (i > asPos) {
        		othCtpList.add(ctp);
        	}
        }
        if (StringUtils.isEmpty(asPBody) || asPos == -1) {
        	throw new Exception("标准文档必须包含'答案及评分参考：'!");
        }
        appendToAsDetail(src1Body, getParaCaption(keyP), asPBody, map, qsNo);
        //加答案下面的段落,不是和答案在一行
        if (othCtpList.size() > 0) {
        	CTP[] lastCtpArr = src.getDocument().getBody().getPArray();
        	CTP[] newArr = new CTP[lastCtpArr.length + othCtpList.size()];
        	for (int i=0;i<lastCtpArr.length;i++) {
        		newArr[i] = lastCtpArr[i];
        	}
        	int idx = lastCtpArr.length;
        	for (int j=0; j<othCtpList.size(); j++) {
        		newArr[idx] = othCtpList.get(j);
        		idx++;
        	}
        	src.getDocument().getBody().setPArray(newArr);
        }
    }
    
    
    public static void appendToAs2(XWPFDocument src, XWPFDocument append, int qsNo) throws Exception {
        CTBody src1Body = src.getDocument().getBody();
        CTBody src2Body = append.getDocument().getBody();
        List<XWPFPictureData> allPictures = append.getAllPictures();
        
        // 记录图片合并前及合并后的ID  
        Map<String,String> map = new HashMap<String,String>();
        for (XWPFPictureData picture : allPictures) {
            String before = append.getRelationId(picture);
            //将原文档中的图片加入到目标文档中  
            String after = src.addPictureData(picture.getData(), Document.PICTURE_TYPE_PNG);
            map.put(before, after.replace("rId", "myKey"));  //操作_2
        }
        //查找答案段落-从最后段落往上开始找
        String asPBody = "";
        XmlOptions optionsOuter = new XmlOptions();
        int asPos = getAnswerParaPos(append);
        CTP[] ctpArr = src2Body.getPArray();
        
        String addPart = "";
        StringBuilder xml = new StringBuilder();
        
        for (int i=0; i<ctpArr.length; i++) {
        	CTP ctp = ctpArr[i];
        	if (i == asPos) {
        		asPBody = ctp.xmlText(optionsOuter);
        		if (StringUtils.isEmpty(asPBody) || asPos == -1) {
                	throw new Exception("标准文档必须包含'答案及评分参考：'!");
                }
        	}
        	if (i >= asPos) {
        		String temp = ctp.xmlText(optionsOuter);
        		temp = temp.substring(temp.indexOf(">") + 1, temp.lastIndexOf("<"));
        		temp = temp.replace("答案及评分参考：", qsNo + "．");
//        		temp = temp.replace("答案及评分参考：",  "qsNo ．");
        		xml.append("<w:p w:rsidP=\"00832626\" w:rsidR=\"00CD1FE5\" w:rsidRDefault=\"00BF1FE7\" w:rsidRPr=\"00F25393\">");
        		xml.append(temp);
        		xml.append("</w:p>");
 
        	}
        }
        addPart = xml.toString();
        //图片对应的嵌入对象改r:id不然会去找，找不到会报错----图片的<v:imagedata创建对应的rid到配置文件document.xml.rels，但是<o:OLEObject标签的rid没有创建到配置文件document.xml.rels中
        addPart = addPart.replace("Type=\"Embed\" r:id", "Type=\"Embed\" r:id_bak");
        //获取答案内容
        if (map != null && !map.isEmpty()) {
            //对xml字符串中图片ID进行替换  
            for (Map.Entry<String, String> set : map.entrySet()) {
                addPart = addPart.replace(set.getKey(), set.getValue());
            }
            addPart = addPart.replace("myKey", "rId");//操作_3
        }
        String srcString = src1Body.xmlText();
        String prefix = srcString.substring(0, srcString.indexOf(">") + 1);
        String mainPart = srcString.substring(srcString.indexOf(">") + 1, srcString.lastIndexOf("<"));
        String sufix = srcString.substring(srcString.lastIndexOf("<"));
        CTBody makeBody = CTBody.Factory.parse(prefix + mainPart + addPart + sufix);
        src1Body.set(makeBody);
    }
    
    public static void appendToQs2(XWPFDocument src, XWPFDocument append) throws Exception {
        CTBody src1Body = src.getDocument().getBody();
        CTBody src2Body = append.getDocument().getBody();
        List<XWPFPictureData> allPictures = append.getAllPictures();
        
        // 记录图片合并前及合并后的ID  
        Map<String,String> map = new HashMap<String,String>();
        for (XWPFPictureData picture : allPictures) {
            String before = append.getRelationId(picture);
            //将原文档中的图片加入到目标文档中  
            String after = src.addPictureData(picture.getData(), Document.PICTURE_TYPE_PNG);
            map.put(before, after.replace("rId", "myKey"));  //操作_2
        }
        //查找答案段落-从最后段落往上开始找
        XmlOptions optionsOuter = new XmlOptions();
        int asPos = getAnswerParaPos(append);
        CTP[] ctpArr = src2Body.getPArray();
        
        String addPart = "";
        StringBuilder xml = new StringBuilder();
        
        for (int i=0; i<ctpArr.length; i++) {
        	CTP ctp = ctpArr[i];
        	if (i < asPos) {
        		String temp = ctp.xmlText(optionsOuter);
        		temp = temp.substring(temp.indexOf(">") + 1, temp.lastIndexOf("<"));
        		xml.append("<w:p w:rsidP=\"00832626\" w:rsidR=\"00CD1FE5\" w:rsidRDefault=\"00BF1FE7\" w:rsidRPr=\"00F25393\">");
        		xml.append(temp);
        		xml.append("</w:p>");
        	}
        }
        addPart = xml.toString();
        //图片对应的嵌入对象改r:id不然会去找，找不到会报错----图片的<v:imagedata创建对应的rid到配置文件document.xml.rels，但是<o:OLEObject标签的rid没有创建到配置文件document.xml.rels中
        addPart = addPart.replace("Type=\"Embed\" r:id", "Type=\"Embed\" r:id_bak");
        //获取答案内容
        if (map != null && !map.isEmpty()) {
            //对xml字符串中图片ID进行替换  
            for (Map.Entry<String, String> set : map.entrySet()) {
                addPart = addPart.replace(set.getKey(), set.getValue());
            }
            addPart = addPart.replace("myKey", "rId");//操作_3
        }
        String srcString = src1Body.xmlText();
        String prefix = srcString.substring(0, srcString.indexOf(">") + 1);
        String mainPart = srcString.substring(srcString.indexOf(">") + 1, srcString.lastIndexOf("<"));
        String sufix = srcString.substring(srcString.lastIndexOf("<"));
        CTBody makeBody = CTBody.Factory.parse(prefix + mainPart + addPart + sufix);
        src1Body.set(makeBody);
    }
    
    //qsNo为小题的序号
    private static void appendToAsDetail(CTBody src, String keyExp, String appendString, 
    		Map<String, String> map, int qsNo) throws Exception {
        String srcString = src.xmlText();
        String prefix = srcString.substring(0, srcString.indexOf(">") + 1);
        String mainPart = srcString.substring(srcString.indexOf(">") + 1, srcString.lastIndexOf("<"));
        String sufix = srcString.substring(srcString.lastIndexOf("<"));
        //获取答案段落-并包进段落里面
        StringBuilder content = new StringBuilder();
        content.append("<w:p w:rsidP=\"00832626\" w:rsidR=\"00CD1FE5\" w:rsidRDefault=\"00BF1FE7\" w:rsidRPr=\"00F25393\">");
        content.append(" <w:r>");
        content.append("  <w:rPr>");
        content.append("	<w:rFonts w:eastAsia=\"Times New Roman\"/>");
        content.append("	<w:bCs/>");
        content.append("	<w:szCs w:val=\"21\"/>");
        content.append("  </w:rPr>");
        content.append("  <w:t>"+ qsNo +"·</w:t>");
        content.append(" </w:r>");
        
        String keyAn = appendString.substring(appendString.indexOf("</w:r>") + 6, appendString.lastIndexOf("<"));
        if ("".equals(keyAn)) {
        	keyAn = keyExp.substring(keyExp.indexOf("答案及评分参考：") + "答案及评分参考：".length());
        	keyAn = "<w:r><w:rPr><w:rFonts w:hint=\"eastAsia\"/><w:szCs w:val=\"21\"/></w:rPr><w:t>" + keyAn + "</w:t></w:r>";
        } 
        content.append(keyAn);
        content.append("</w:p>");
        
        String addPart = content.toString();
        //获取答案内容
        if (map != null && !map.isEmpty()) {
            //对xml字符串中图片ID进行替换  
            for (Map.Entry<String, String> set : map.entrySet()) {
                addPart = addPart.replace(set.getKey(), set.getValue());
            }
            addPart = addPart.replace("myKey", "rId");//操作_3
        }
        //将两个文档的xml内容进行拼接  
        CTBody makeBody = CTBody.Factory.parse(prefix + mainPart + addPart + sufix);
        src.set(makeBody);
    }
    
    /**
   	 * 导出试卷难度预估表信息
   	 * @param path
   	 * @param planList
   	 */
   	public static void exportPaperEstimatedToXlsx(final List<Subject> planList, final String path) {
   		HSSFWorkbook workbook = new HSSFWorkbook();
   		HSSFSheet sheet = workbook.createSheet("试卷难度预估统计表");
   		sheet.setDefaultColumnWidth((short) 15);
   		HSSFRow row = sheet.createRow(0);
   		HSSFCell cell0 = row.createCell(0);
   		HSSFCell cell1 = row.createCell(1);
   		HSSFCell cell2 = row.createCell(2);
   		HSSFCell cell3 = row.createCell(3);
   		HSSFCell cell4 = row.createCell(4);
   		HSSFCell cell5 = row.createCell(5);
   		
   		cell0.setCellValue(new HSSFRichTextString("题号"));
   		cell1.setCellValue(new HSSFRichTextString("题型"));
   		cell2.setCellValue(new HSSFRichTextString("预估难度层次"));
   		cell3.setCellValue(new HSSFRichTextString("分数"));
   		cell4.setCellValue(new HSSFRichTextString("难度值范围"));
   		cell5.setCellValue(new HSSFRichTextString("预估难度值"));
   	
   		for (int i=0; i<planList.size(); i++) {
   			HSSFRow datarow = sheet.createRow(i+1);
   			Subject plan = planList.get(i);
   			HSSFCell datacell0 = datarow.createCell(0);
   			datacell0.setCellType(CellType.STRING);
   			datacell0.setCellValue(new HSSFRichTextString(plan.getOrd().toString()));
   			HSSFCell datacell1 = datarow.createCell(1);
   			datacell1.setCellType(CellType.STRING);
   			datacell1.setCellValue(new HSSFRichTextString(plan.getQuestionTypeName()));
   			HSSFCell datacell2 = datarow.createCell(2);
   			datacell2.setCellType(CellType.STRING);
   			datacell2.setCellValue(new HSSFRichTextString(plan.getDifficult()));
   			HSSFCell datacell3 = datarow.createCell(3);
   			datacell3.setCellType(CellType.STRING);
   			datacell3.setCellValue(new HSSFRichTextString(plan.getScoreStr()));
   			
   			HSSFCell datacell4 = datarow.createCell(4);
   			datacell4.setCellType(CellType.STRING);
   			datacell4.setCellValue(new HSSFRichTextString(plan.getChapter()));
   			
   			HSSFCell datacell5 = datarow.createCell(5);
   			datacell5.setCellType(CellType.STRING);
   			datacell5.setCellValue(new HSSFRichTextString(plan.getRemark()));
   		}
   		try {
   			FileOutputStream fos = new FileOutputStream(new File(path));
   			workbook.write(fos);
   			fos.close();
   			workbook.close();
   		} catch (IOException e) {
   			e.printStackTrace();
   		}
   	}
    
    public static void main666(String[] args) throws Exception  {
    	//复制到空答案和试题
    	FileUtils.copyFile(new File("G:\\javaFx\\LT-client\\resources\\word-factory\\empty.docx"), 
    			new File("G:\\javaFx\\LT-client\\papers\\02363190601\\02363190601A\\as\\1.docx"));
    	
        InputStream item1 = new FileInputStream("G:\\javaFx\\LT-client\\papers\\02363190601\\02363190601A\\as\\1.docx");
        OPCPackage src1Package = OPCPackage.open(item1);
        XWPFDocument src1Document = new XWPFDocument(src1Package);
    	
        InputStream item2 = new FileInputStream("G:\\javaFx\\LT-client\\papers\\02363190601\\02363190601A\\ques\\300.docx");
        OPCPackage src2Package = OPCPackage.open(item2);
        XWPFDocument src2Document = new XWPFDocument(src2Package);
    	
        appendToAs(src1Document, src2Document, 1);
        
        OutputStream desOut = new FileOutputStream(new File("G:\\javaFx\\LT-client\\papers\\02363190601\\02363190601A\\as\\1.docx"));
        src1Document.createNumbering();//操作_1
        src1Document.write(desOut);
        
        desOut.close();
        src1Document.close();
    }
    
    public static List<String> getAnPStartTemplate() {
    	List<String> tList = new ArrayList<String>();
    	StringBuilder tp1 = new StringBuilder();
    	//第一行
    	tp1.append("<w:p w:rsidR=\"00F14F23\" w:rsidRDefault=\"00F14F23\">");
    	tp1.append("<w:pPr>");
    	tp1.append("<w:tabs>");
    	tp1.append("<w:tab w:val=\"left\" w:pos=\"525\"/>");
    	tp1.append("<w:tab w:val=\"left\" w:pos=\"2100\"/>");
    	tp1.append("<w:tab w:val=\"left\" w:pos=\"3780\"/>");
    	tp1.append("<w:tab w:val=\"left\" w:pos=\"5460\"/>");
    	tp1.append("<w:tab w:val=\"left\" w:pos=\"7140\"/>");
    	tp1.append("</w:tabs>");
    	tp1.append("<w:spacing w:line=\"340\" w:lineRule=\"exact\"/>");
    	tp1.append("<w:rPr>");
    	tp1.append("<w:rFonts w:hint=\"eastAsia\"/>");
    	tp1.append("<w:bCs/>");
    	tp1.append("<w:szCs w:val=\"21\"/>");
    	tp1.append("</w:rPr>");
    	tp1.append("</w:pPr>");
    	//第二行
    	StringBuilder tp2 = new StringBuilder();
    	tp2.append("<w:p w:rsidR=\"00F14F23\" w:rsidRDefault=\"00F14F23\">");
    	tp2.append("<w:pPr>");
    	tp2.append("<w:tabs>");
    	tp2.append("<w:tab w:val=\"left\" w:pos=\"525\"/>");
    	tp2.append("<w:tab w:val=\"left\" w:pos=\"2100\"/>");
    	tp2.append("<w:tab w:val=\"left\" w:pos=\"3780\"/>");
    	tp2.append("<w:tab w:val=\"left\" w:pos=\"5460\"/>");
    	tp2.append("<w:tab w:val=\"left\" w:pos=\"7035\"/>");
    	tp2.append("</w:tabs>");
    	tp2.append("<w:spacing w:line=\"340\" w:lineRule=\"exact\"/>");
    	tp2.append("<w:rPr>");
    	tp2.append("<w:rFonts w:hint=\"eastAsia\"/>");
    	tp2.append("<w:bCs/>");
    	tp2.append("<w:szCs w:val=\"21\"/>");
    	tp2.append("</w:rPr>");
    	tp2.append("</w:pPr>");
    	//第三行--到第N行
    	StringBuilder tp3 = new StringBuilder();
    	tp3.append("<w:p w:rsidR=\"00F14F23\" w:rsidRDefault=\"00F14F23\">");
    	tp3.append("<w:pPr>");
    	tp3.append("<w:tabs>");
    	tp3.append("<w:tab w:val=\"left\" w:pos=\"420\"/>");
    	tp3.append("<w:tab w:val=\"left\" w:pos=\"1995\"/>");
    	tp3.append("<w:tab w:val=\"left\" w:pos=\"3675\"/>");
    	tp3.append("<w:tab w:val=\"left\" w:pos=\"5355\"/>");
    	tp3.append("<w:tab w:val=\"left\" w:pos=\"7035\"/>");
    	tp3.append("</w:tabs>");
    	tp3.append("<w:spacing w:line=\"340\" w:lineRule=\"exact\"/>");
    	tp3.append("<w:rPr>");
    	tp3.append("<w:rFonts w:hint=\"eastAsia\"/>");
    	tp3.append("<w:bCs/>");
    	tp3.append("<w:szCs w:val=\"21\"/>");
    	tp3.append("</w:rPr>");
    	tp3.append("</w:pPr>");
    	tList.add(tp1.toString());
    	tList.add(tp2.toString());
    	tList.add(tp3.toString());
    	return tList;
    }
    //一行4列
    public static String get1Row4ColStart() {
    	StringBuilder tp3 = new StringBuilder();
    	tp3.append("<w:p w:rsidR=\"008F0380\" w:rsidRPr=\"009D636A\" w:rsidRDefault=\"009D636A\" w:rsidP=\"009D636A\">");
    	tp3.append("<w:pPr>");
    	tp3.append("<w:tabs>");
    	tp3.append("<w:tab w:val=\"left\" w:pos=\"420\"/>");
    	tp3.append("<w:tab w:val=\"left\" w:pos=\"2520\"/>");
    	tp3.append("<w:tab w:val=\"left\" w:pos=\"4620\"/>");
    	tp3.append("<w:tab w:val=\"left\" w:pos=\"6720\"/>");
    	tp3.append("</w:tabs>");
    	tp3.append("<w:spacing w:line=\"340\" w:lineRule=\"exact\"/>");
    	tp3.append("<w:rPr>");
    	tp3.append("<w:rFonts w:hint=\"eastAsia\"/>");
    	tp3.append("<w:bCs/>");
    	tp3.append("<w:szCs w:val=\"21\"/>");
    	tp3.append("</w:rPr>");
    	tp3.append("</w:pPr>");
    	return tp3.toString();
    }
    //一行2列 
    public static String get1Row2ColStart() {
    	StringBuilder tp3 = new StringBuilder();
    	tp3.append("<w:p w:rsidR=\"008F0380\" w:rsidRPr=\"009D636A\" w:rsidRDefault=\"009D636A\" w:rsidP=\"009D636A\">");
    	tp3.append("<w:pPr>");
    	tp3.append("<w:tabs>");
    	tp3.append("<w:tab w:val=\"left\" w:pos=\"420\"/>");
    	tp3.append("<w:tab w:val=\"left\" w:pos=\"4620\"/>");
    	tp3.append("</w:tabs>");
    	tp3.append("<w:spacing w:line=\"340\" w:lineRule=\"exact\"/>");
    	tp3.append("<w:rPr>");
    	tp3.append("<w:rFonts w:hint=\"eastAsia\"/>");
    	tp3.append("<w:bCs/>");
    	tp3.append("<w:szCs w:val=\"21\"/>");
    	tp3.append("</w:rPr>");
    	tp3.append("</w:pPr>");
    	return tp3.toString();
    }
    //一行3列  --多选使用
    public static String get1Row3ColStart() {
    	StringBuilder tp3 = new StringBuilder();
    	tp3.append("<w:p w:rsidR=\"00B729E5\" w:rsidRDefault=\"00AE265D\" w:rsidP=\"00B729E5\">");
    	tp3.append("<w:pPr>");
    	tp3.append("<w:tabs>");
    	tp3.append("<w:tab w:val=\"left\" w:pos=\"420\"/>");
    	tp3.append("<w:tab w:val=\"left\" w:pos=\"2940\"/>");
    	tp3.append("<w:tab w:val=\"left\" w:pos=\"5460\"/>");
    	tp3.append("</w:tabs>");
    	tp3.append("<w:spacing w:line=\"360\" w:lineRule=\"exact\"/>");
    	tp3.append("<w:rPr>");
    	tp3.append("<w:rFonts w:hint=\"eastAsia\"/>");
    	tp3.append("<w:bCs/>");
    	tp3.append("<w:szCs w:val=\"21\"/>");
    	tp3.append("</w:rPr>");
    	tp3.append("</w:pPr>");
    	return tp3.toString();
    }
    //文档选项是否包含图片
    public static boolean choiceHasPicture(XWPFDocument src1Document) {
		List<XWPFParagraph> ps = src1Document.getParagraphs();
		for (int i=0; i<ps.size(); i++) {
			if (i == 0) {//i==0是题干word
				continue;
			}
			XWPFParagraph p = ps.get(i);
			if (p.getCTP().toString().indexOf("<w:drawing>") > 0 || p.getCTP().toString().indexOf("<v:imagedata") > 0) {
				return true;
			}
		}
		return false;
    }
    
    //获取段落的文本长度-注意这里不区分 汉字和字符数字
    public static int getMaxChoiceLength(List<XWPFParagraph> ps) {
    	int maxLen = 0;
    	for (int i=0; i<ps.size(); i++) {
    		if (i == 0) {
    			continue;//题干不算
    		}
    		XWPFParagraph p = ps.get(i);
    		String text = getParaCaption(p);
    		if (text.length() > maxLen) {
    			maxLen = text.length();
    		}
    	}
		return maxLen;
    }
    
    public static String getParaCaption(XWPFParagraph p) {
		StringBuffer text = new StringBuffer();
		List<XWPFRun> runs = p.getRuns();
		for (XWPFRun run : runs) {
			Node runNode = run.getCTR().getDomNode();
			text.append(getText(runNode));
		}
		return text.toString();
    }
    
    public static List<String> getChoiceParaList(XWPFDocument appendDocument, List<XWPFParagraph> ps) {
    	List<String> retList = new ArrayList<String>();
    	if (ps.size() == 5) {//单选题
			String p0Xml = ps.get(0).getCTP().toString();//单选题干
			String p1Xml = ps.get(1).getCTP().toString();//选项1
			String p2Xml = ps.get(2).getCTP().toString();//选项2
			String p3Xml = ps.get(3).getCTP().toString();//选项3
			String p4Xml = ps.get(4).getCTP().toString();//选项4
			retList.add(p0Xml.substring(p0Xml.indexOf(">") + 1, p0Xml.indexOf("</xml-fragment>")));
			retList.add(p1Xml.substring(p1Xml.indexOf(">") + 1, p1Xml.indexOf("</xml-fragment>")));
			retList.add(p2Xml.substring(p2Xml.indexOf(">") + 1, p2Xml.indexOf("</xml-fragment>")));
			retList.add(p3Xml.substring(p3Xml.indexOf(">") + 1, p3Xml.indexOf("</xml-fragment>")));
			retList.add(p4Xml.substring(p4Xml.indexOf(">") + 1, p4Xml.indexOf("</xml-fragment>")));
    	} else if (ps.size() == 6) {//可能是多选题、或是题干换行后的单选题
			String p0Xml = ps.get(0).getCTP().toString();//单选题干
			String p1Xml = ps.get(1).getCTP().toString();//选项1
			String p2Xml = ps.get(2).getCTP().toString();//选项2
			String p3Xml = ps.get(3).getCTP().toString();//选项3
			String p4Xml = ps.get(4).getCTP().toString();//选项4
			String p5Xml = ps.get(5).getCTP().toString();//选项5
			
			String cap0 = getParaCaption(ps.get(0));
			String cap1 = getParaCaption(ps.get(1));
			String cap2 = getParaCaption(ps.get(2));
			String cap3 = getParaCaption(ps.get(3));
			String cap4 = getParaCaption(ps.get(4));
			String cap5 = getParaCaption(ps.get(5));
			
			//题干换行的单选题
			if ((cap1.indexOf("A·") == -1) && 
    					(cap2.indexOf("A·") >= 0) && 
    					(cap3.indexOf("B·") >= 0) && 
    					(cap4.indexOf("C·") >= 0) && 
    					(cap5.indexOf("D·") >= 0)) {
    			String dry = p0Xml.substring(p0Xml.indexOf(">") + 1, p0Xml.indexOf("</xml-fragment>")) + "\n" + p1Xml.substring(p1Xml.indexOf(">") + 1, p1Xml.indexOf("</xml-fragment>"));
				retList.add(dry);
				retList.add(p2Xml.substring(p2Xml.indexOf(">") + 1, p2Xml.indexOf("</xml-fragment>")));//A
				retList.add(p3Xml.substring(p3Xml.indexOf(">") + 1, p3Xml.indexOf("</xml-fragment>")));//B
				retList.add(p4Xml.substring(p4Xml.indexOf(">") + 1, p4Xml.indexOf("</xml-fragment>")));//C
				retList.add(p5Xml.substring(p5Xml.indexOf(">") + 1, p5Xml.indexOf("</xml-fragment>")));//D
    		} else {//正常的多选题
				retList.add(p0Xml.substring(p0Xml.indexOf(">") + 1, p0Xml.indexOf("</xml-fragment>")));
				retList.add(p1Xml.substring(p1Xml.indexOf(">") + 1, p1Xml.indexOf("</xml-fragment>")));
				retList.add(p2Xml.substring(p2Xml.indexOf(">") + 1, p2Xml.indexOf("</xml-fragment>")));
				retList.add(p3Xml.substring(p3Xml.indexOf(">") + 1, p3Xml.indexOf("</xml-fragment>")));
				retList.add(p4Xml.substring(p4Xml.indexOf(">") + 1, p4Xml.indexOf("</xml-fragment>")));
				retList.add(p5Xml.substring(p5Xml.indexOf(">") + 1, p5Xml.indexOf("</xml-fragment>")));
    		}
    	} else if (ps.size() == 7) {
			String p0Xml = ps.get(0).getCTP().toString();//单选题干
			String p1Xml = ps.get(1).getCTP().toString();//选项1
			String p2Xml = ps.get(2).getCTP().toString();//选项2
			String p3Xml = ps.get(3).getCTP().toString();//选项3
			String p4Xml = ps.get(4).getCTP().toString();//选项4
			String p5Xml = ps.get(5).getCTP().toString();//选项5
			String p6Xml = ps.get(6).getCTP().toString();//选项6
			
			String cap0 = getParaCaption(ps.get(0));
			String cap1 = getParaCaption(ps.get(1));
			String cap2 = getParaCaption(ps.get(2));
			String cap3 = getParaCaption(ps.get(3));
			String cap4 = getParaCaption(ps.get(4));
			String cap5 = getParaCaption(ps.get(5));
			String cap6 = getParaCaption(ps.get(6));
			if (cap1.indexOf("A·") == -1 && 
					cap2.indexOf("A·") >= 0 && 
					cap3.indexOf("B·") >= 0 && 
					cap4.indexOf("C·") >= 0 && 
					cap5.indexOf("D·") >= 0 && 
					cap6.indexOf("E·") >= 0) {
    			String dry = p0Xml.substring(p0Xml.indexOf(">") + 1, p0Xml.indexOf("</xml-fragment>")) + "\n" + p1Xml.substring(p1Xml.indexOf(">") + 1, p1Xml.indexOf("</xml-fragment>"));
				retList.add(dry);
				retList.add(p2Xml.substring(p2Xml.indexOf(">") + 1, p2Xml.indexOf("</xml-fragment>")));
				retList.add(p3Xml.substring(p3Xml.indexOf(">") + 1, p3Xml.indexOf("</xml-fragment>")));
				retList.add(p4Xml.substring(p4Xml.indexOf(">") + 1, p4Xml.indexOf("</xml-fragment>")));
				retList.add(p5Xml.substring(p5Xml.indexOf(">") + 1, p5Xml.indexOf("</xml-fragment>")));
				retList.add(p6Xml.substring(p6Xml.indexOf(">") + 1, p6Xml.indexOf("</xml-fragment>")));
			} else {
				retList.add(p0Xml.substring(p0Xml.indexOf(">") + 1, p0Xml.indexOf("</xml-fragment>")));
				retList.add(p1Xml.substring(p1Xml.indexOf(">") + 1, p1Xml.indexOf("</xml-fragment>")));
				retList.add(p2Xml.substring(p2Xml.indexOf(">") + 1, p2Xml.indexOf("</xml-fragment>")));
				retList.add(p3Xml.substring(p3Xml.indexOf(">") + 1, p3Xml.indexOf("</xml-fragment>")));
				retList.add(p4Xml.substring(p4Xml.indexOf(">") + 1, p4Xml.indexOf("</xml-fragment>")));
				retList.add(p5Xml.substring(p5Xml.indexOf(">") + 1, p5Xml.indexOf("</xml-fragment>")));
			}
    	}
    	return retList;
    }
    
    //构造试卷单选、多选题格式化
    public static void buildPaperChoiceFormat(XWPFDocument baseDocument, XWPFDocument appendDocument, boolean isSingleChoice) throws Exception {
    	//如果选项有图片按照原始默认方式拼接word
		if (choiceHasPicture(appendDocument)) {
			appendBody(baseDocument, appendDocument);
			return;
		}
        XmlOptions optionsOuter = new XmlOptions();
        optionsOuter.setSaveOuter();
        
        CTBody baseBody = baseDocument.getDocument().getBody();
        String srcString = baseBody.xmlText();
        String prefix = srcString.substring(0, srcString.indexOf(">") + 1);
        String mainPart = srcString.substring(srcString.indexOf(">") + 1, srcString.lastIndexOf("<"));
        String sufix = srcString.substring(srcString.lastIndexOf("<"));
        String addPart = "";
        //将两个文档的xml内容进行拼接  
        List<XWPFParagraph> ps = appendDocument.getParagraphs();
		List<String> psList = getChoiceParaList(appendDocument, ps);
		String p0Xml = psList.get(0);//单选题干
		String p1Xml = psList.get(1);//选项1
		String p2Xml = psList.get(2);//选项2
		String p3Xml = psList.get(3);//选项3
		String p4Xml = psList.get(4);//选项4
		
		String pDefaultStart = "<w:p w:rsidP=\"009D636A\" w:rsidR=\"00501D7A\" w:rsidRDefault=\"00D10651\" w:rsidRPr=\"009D636A\">\n";
		String pEnd = "</w:p>\n";
		
		int maxLength = getMaxChoiceLength(ps);
		
		if (isSingleChoice) {//单选题
			if (maxLength <= 7) {
				//一行4列
				addPart = addPart + pDefaultStart + p0Xml + getPermEndStr(p0Xml) + pEnd;//单选题干
				addPart = addPart + get1Row4ColStart();
				
				p1Xml = removeTag(p1Xml, "w:pPr");
				p2Xml = removeTag(p2Xml, "w:pPr");
				p3Xml = removeTag(p3Xml, "w:pPr");
				p4Xml = removeTag(p4Xml, "w:pPr");
				
				addPart = addPart + p1Xml + getPermEndStr(p1Xml) + "\n";//选项1
				addPart = addPart + p2Xml + getPermEndStr(p2Xml) + "\n";//选项2
				addPart = addPart + p3Xml + getPermEndStr(p3Xml) + "\n";//选项3
				addPart = addPart + p4Xml + getPermEndStr(p4Xml) + "\n";//选项4
				addPart = addPart + pEnd;
			} else if (maxLength > 7 && maxLength <= 17) {
				//第一行2列、第二行2列
				addPart = addPart + pDefaultStart + p0Xml + getPermEndStr(p0Xml) + pEnd;//单选题干
				addPart = addPart + get1Row2ColStart();
				
				p1Xml = removeTag(p1Xml, "w:pPr");
				p2Xml = removeTag(p2Xml, "w:pPr");
				p3Xml = removeTag(p3Xml, "w:pPr");
				p4Xml = removeTag(p4Xml, "w:pPr");
				
				addPart = addPart + p1Xml + getPermEndStr(p1Xml) + "\n";//选项1
				addPart = addPart + p2Xml + getPermEndStr(p2Xml) + "\n";//选项2
				addPart = addPart + pEnd;
				
				addPart = addPart + get1Row2ColStart();
				addPart = addPart + p3Xml + getPermEndStr(p3Xml) + "\n";//选项3
				addPart = addPart + p4Xml + getPermEndStr(p4Xml) + "\n";//选项4
				addPart = addPart + pEnd;
			} else if (maxLength > 17) {
				//一行1列
				appendBody(baseDocument, appendDocument);
				return;
			}
		} else {//多选题
			String p5Xml = psList.get(5);//选项5
			if (maxLength <= 10) {
				//第一行3列  第二行2列
				addPart = addPart + pDefaultStart + p0Xml + getPermEndStr(p0Xml) + pEnd;//多选题干
				addPart = addPart + get1Row3ColStart();
				
				p1Xml = removeTag(p1Xml, "w:pPr");
				p2Xml = removeTag(p2Xml, "w:pPr");
				p3Xml = removeTag(p3Xml, "w:pPr");
				p4Xml = removeTag(p4Xml, "w:pPr");
				p5Xml = removeTag(p5Xml, "w:pPr");
				
				addPart = addPart + "<w:r><w:tab/></w:r>" + p1Xml + getPermEndStr(p1Xml) + "\n";//选项1
				addPart = addPart + "<w:r><w:tab/></w:r>" + p2Xml + getPermEndStr(p2Xml) + "\n";//选项2
				addPart = addPart + "<w:r><w:tab/></w:r>" + p3Xml + getPermEndStr(p3Xml) + "\n";//选项3
				addPart = addPart + pEnd;
				
				addPart = addPart + get1Row3ColStart();
				addPart = addPart + "<w:r><w:tab/></w:r>" + p4Xml + getPermEndStr(p4Xml) + "\n";//选项4
				addPart = addPart + "<w:r><w:tab/></w:r>" + p5Xml + getPermEndStr(p5Xml) + "\n";//选项5
				addPart = addPart + pEnd;
			} else if (maxLength > 10) {
				//一行1列
				appendBody(baseDocument, appendDocument);
				return;
			}
		}
        addPart = removeTag(addPart, "w:sectPr");
        CTBody makeBody = CTBody.Factory.parse(prefix + mainPart + addPart + sufix);
        baseBody.set(makeBody);
        appendDocument.close();
    }
    
    public static String getPermEndStr(String pXml) {
	    String start = "<w:permStart w:edGrp=\"everyone\" w:id=\"";
  	    int spos = pXml.indexOf(start);
  	    if (spos > 0) {
  		    String tmep = pXml.substring(spos + start.length(), pXml.length());
  		    int epos = tmep.indexOf("\"/>");
  		    return "<w:permEnd w:id=\"" + tmep.substring(0, epos) + "\"/>";
  	    }
  	    return "";
    }
    
    public static void main22(String[] args) throws Exception  {
    	/*int qsNo = 38;
		String fromQuesSm = "G:\\javaFx\\LT-client\\papers\\01226200601\\01226200601A\\ques\\" + qsNo + ".docx";
		String toNewAs = "G:\\javaFx\\LT-client\\papers\\01226200601\\01226200601A\\as\\" + qsNo + ".docx";
    	splitAndWriteAsWord(fromQuesSm, toNewAs, qsNo);//分拆迁移答案到新word*/
    	
		String fromQuesSm = "G:\\javaFx\\LT-client\\papers\\01226200601\\01226200601A\\ques\\" + 2 + ".docx";
		String toNewAs = "G:\\javaFx\\LT-client\\papers\\01226200601\\01226200601A\\qs\\" + 2 + ".docx";
    	createAndWriteQsWord(fromQuesSm, toNewAs);
    }
    
    public static void main(String[] args) throws Exception  {
    	String baseDocx = "C:\\Users\\Lenovo\\Desktop\\empty.Docx";
    	OutputStream dest = new FileOutputStream("C:\\Users\\Lenovo\\Desktop\\final.docx");
    	
    	OPCPackage basePackage = OPCPackage.open(new FileInputStream(baseDocx));
        XWPFDocument baseDocument = new XWPFDocument(OPCPackage.open(new FileInputStream(baseDocx)));
    	
		List<String> docxList = new ArrayList<String>();
		docxList.add("G:\\javaFx\\LT-client\\papers\\01226200601\\01226200601A\\ques\\100.docx");//题干
		docxList.add("G:\\javaFx\\LT-client\\papers\\01226200601\\01226200601A\\qs\\37.docx");
		//docxList.add("G:\\javaFx\\LT-client\\papers\\01226200601\\01226200601A\\qs\\3.docx");
		
		
        for (Integer i=0; i< docxList.size(); i++) {
            OPCPackage src2Package = OPCPackage.open(new FileInputStream(docxList.get(i)));
            XWPFDocument src2Document = new XWPFDocument(src2Package);
            //单选、多选 选项格式化,i==0是每个题型的 题干描述word 从i==1开始才是每个题型对应的 试题
            try {
            	/*if (i > 0) {
            		buildPaperChoiceFormat(baseDocument, src2Document, false);
            	} else {*/
            		appendBody(baseDocument, src2Document);
            		
            	//}
            	
            } catch(Exception e) {
            	e.printStackTrace();
            }
            src2Document.close();
            src2Package.close();
        }
		
        baseDocument.createNumbering();//操作_1
        //创建页脚
    	createFooter(baseDocument, "", "", false, "A");
    	baseDocument.write(dest);
        //关闭
    	dest.close();
    	baseDocument.close();
        basePackage.close();
    }

    //eg : 
    private static String removeTag(String source, String tag) {
    	String ret = source;
        int sPos = source.indexOf("<" + tag);
        if (sPos > 0) {
        	int ePos = source.indexOf("</" + tag + ">");
        	ret = source.substring(0, sPos) + source.substring(ePos + (tag.length() + 3), source.length());
        }
        return ret;
    }

    //选择题答案格式
	private static void buildChoiceAnswerFormat(List<String> srcDocxs, XWPFDocument src1Document, 
			List<String> tpList) throws Exception {
        //i==0 是大题描述 i>=1是选项答案
        for (int i=0; i<srcDocxs.size(); i++) {
            OPCPackage src2Package = OPCPackage.open(new FileInputStream(srcDocxs.get(i)));
            XWPFDocument src2Document = new XWPFDocument(src2Package);  
            
            CTBody src1Body = src1Document.getDocument().getBody();
            CTBody src2Body = src2Document.getDocument().getBody();
            
            XmlOptions optionsOuter = new XmlOptions();
            optionsOuter.setSaveOuter();
            String srcString = src1Body.xmlText();
            String appendString = src2Body.xmlText(optionsOuter);
            
            String prefix = srcString.substring(0, srcString.indexOf(">") + 1);
            String mainPart = srcString.substring(srcString.indexOf(">") + 1, srcString.lastIndexOf("<"));
            String sufix = srcString.substring(srcString.lastIndexOf("<"));
            //<w:tab/>加空格
            String addPart = "";
            String newBody = "";
            String choiceXmlStart = "";
            
            if (i == 0) {//选择题题干word合并
            	addPart = appendString.substring(appendString.indexOf("<w:p "), appendString.lastIndexOf("</w:p>"));//
            	newBody = prefix + mainPart + addPart + "</w:p>" + sufix;
            } else if (i >= 1) {//选择题答案合并
            	addPart = "<w:r><w:tab/></w:r>" + appendString.substring(appendString.indexOf("<w:r>"), appendString.lastIndexOf("</w:p>"));
                if (i % 5 == 1) {
                	if (i == 1) {
                		choiceXmlStart = tpList.get(0);
                	} else if (i == 6) {
                		choiceXmlStart = tpList.get(1);
                	} else if (i >= 11) {
                		choiceXmlStart = tpList.get(2);
                	}
                	newBody = prefix + mainPart + choiceXmlStart + addPart + "</w:p>" + sufix;
                } else {
                	mainPart = mainPart.substring(0, mainPart.length() - 6);
                	newBody = prefix + mainPart + addPart + "</w:p>" + sufix;
                }
            }
            
            CTBody makeBody = CTBody.Factory.parse(newBody);
            src1Body.set(makeBody);
            
            src2Document.close();
            src2Package.close();
        }
	}
}
