根据Excel的内容和Word模板的内容生产Word文档_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 根据Excel的内容和Word模板的内容生产Word文档

根据Excel的内容和Word模板的内容生产Word文档

 2012/3/23 23:51:12  yangpanwww  程序员俱乐部  我要评论(0)
  • 摘要:花了一个下午的时间。磨出来的一个东西..感觉好不错。。拿来分享下。。哈哈。。大体功能是:根据Excel的内容和Word模板的内容生产Word文档业务1:excle有1000个人..需要打印出1000个人的通知书。(单个的打印、分开管理)业务2:excle有1000个人..需要连续打印出1000个人的通知书。大体思路:*1、定义一个标签格式..本例中是:$(xxx)*2、在word中编辑好模板样式..另存为html模板。(也可以存为其他格式。但是注意编码问题。不然会乱码)*3
  • 标签:模板 excel 文档 内容

花了一个下午的时间。磨出来的一个东西..感觉好不错。。拿来分享下。。哈哈。。

?

大体功能是:根据Excel的内容和Word模板的内容生产Word文档

?

?业务1:excle 有 1000 个人..需要打印出 1000 个人的通知书。(单个的打印、分开管理)
?业务2:excle 有 1000 个人..需要连续打印出 1000 个人的通知书。

?

大体思路:

?

?? *??? 1、定义一个标签格式..本例中是:$(xxx)
?? *??? 2、在 word 中编辑好模板样式..另存为html模板。(也可以存为其他格式。但是注意编码问题。不然会乱码)
?? *??? 3、读取 excel 中的内容并封住为一个容器: list<map<String,String>>
?? *??? 4、读取html模板,并根据标签替换内容。再重新写个文件。
?? *???

?

开始都一路顺风...后面再连续的分页word文档的时候。遇到麻烦了.开始以为只要在每次循环的地方加上word的分页符就好了。。是的。思路是没错。。问题就出在了怎么加。。。。下面我在唠叨下我的经过:

?

?????我一次就是直接读取模板..替换..在循环的地方加上分页代码..结果失败了...效果是word..只看到了excel 第一条记录。开始我还以为是我的代码写错了。。后面在跟踪断点、查看源码才发现..其实循环的没错.....错在每次读模板的时候都有html的头部.等等代码....于是我仔细的查看了单个文件的源码。

?

???? 当我们把 word 模板另存为 html 的时候。。源码大致分为如下格式:

???? 头部:

<html xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:w="urn:schemas-microsoft-com:office:word"
xmlns="http://www.w3.org/TR/REC-html40">

<head>
···································省略

?

?? 中间:

??

<body lang=ZH-CN style='tab-interval:21.0pt;text-justify-trim:punctuation'>

<div class=Section1 style='layout-grid:15.6pt'>

<p class=MsoNormal align=center style='text-align:center'><b style='mso-bidi-font-weight:
normal'><span lang=EN-US style='font-size:14.0pt;font-family:黑体'><o:p>&nbsp;</o:p></span></b></p>
·························省略
</div><!-- 我故意把这个 结束的 div 分开..是为了让你们注意到..哈哈..后面还讲到.. --->

?

?? 底部

??

</body>

</html>

?

??? 嘿嘿...经过这么仔细的分析...我估计这下没问题了...于是我把 模板分为 三块...只循环中间的 部分.....满心期待的结果出来。。结果我打开一看 。。。。所有的数据都在一个word里面是...是没错....可是没分页...本来第二页的内容在第一页尾巴上面...

???? 额。。我开始还怀疑是不是 分页代码 写错了。。。我就手动下了一个测试word 另存为html 加上分页代码。在还原回 word? ...结果是 分页的....郁闷中.....反复的思考刚才的操作...是不是我的?分页代码放错地方了.....

?

??? 于是我在测试了下。。这次我把 分页代码 放到了 中部代码的 div 中间。。。O(∩_∩)O哈哈~...结果分页成功..

?

最后我在模板中插入了一个分页符(是分页符不是回车到第二页啊)

?

大体思路:

???*??? 1、定义一个标签格式..本例中是:$(xxx)
?? *??? 2、在 word 中编辑好模板样式..另存为html模板。但是这里要注意,我们要打开 html 的源码,
?? *?????? 分解源码为:头部和中间、底部等三部分。(底部模板简单。所以我就写在代码中了),
?? *??? 3、读取 excel 中的内容并封住为一个容器: list<map<String,String>>
?? *??? 4、读取html头部和中间、底部模板,并根据标签替换中间模板内容。替换完后,在加底部文件。重写文件。生成一个连续的有分页符的word
?? *???

?

? 下面的我的代码,附件中我也将上传我的类和文件:

?? excel操作类:

?

package cn.xsbiz.main;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;

/**
 * 业务:java读取Excel
 * 
 * 
 * @author 妞见妞爱
 * 
 */
public class OperatorExcel {
  
	
	/**
	 * 读取Excel文件的内容
	 * 
	 * @param file
	 *            待读取的文件
	 * @return
	 */
	public static String readExcel(File file) {
		StringBuffer sb = new StringBuffer();

		Workbook wb = null;
		try {
			// 构造Workbook(工作薄)对象
			wb = Workbook.getWorkbook(file);
		} catch (BiffException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		if (wb == null)
			return null;

		// 获得了Workbook对象之后,就可以通过它得到Sheet(工作表)对象了
		Sheet[] sheet = wb.getSheets();

		if (sheet != null && sheet.length > 0) {
			// 对每个工作表进行循环
			for (int i = 0; i < sheet.length; i++) {
				// 得到当前工作表的行数
				int rowNum = sheet[i].getRows();
				for (int j = 0; j < rowNum; j++) {
					// 得到当前行的所有单元格
					Cell[] cells = sheet[i].getRow(j);
					if (cells != null && cells.length > 0) {
						// 对每个单元格进行循环
						for (int k = 0; k < cells.length; k++) {
							// 读取当前单元格的值
							String cellValue = cells[k].getContents();
							sb.append(cellValue + "\t");
						}
					}
					sb.append("\r\n");
				}
				sb.append("\r\n");
			}
		}
		// 最后关闭资源,释放内存
		wb.close();
		return sb.toString();
	}

	/**
	 * 
	 * 读取 excel 返回  List<Map> 
	 * 
	 * @param file --待读取的文件
	 * @return
	 */
	public static List<Map<String, String>> readExcelReList(File file) { 
		Workbook wb = null;
		try {
			// 构造Workbook(工作薄)对象
			wb = Workbook.getWorkbook(file);
		} catch (BiffException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		if (wb == null)
			return null;

		// 获得了Workbook对象之后,就可以通过它得到Sheet(工作表)对象了
		Sheet[] sheet = wb.getSheets();
		
		List<Map<String, String>>  list = new ArrayList<Map<String, String>>();
		
		if (sheet != null && sheet.length > 0) {
			// 对每个工作表进行循环
			for (int i = 0; i < sheet.length; i++) {
				// 得到当前工作表的行数
				int rowNum = sheet[i].getRows();
				for (int j = 0; j < rowNum; j++) {
					// 得到当前行的所有单元格
					Cell[] cells = sheet[i].getRow(j);
					if (cells != null && cells.length > 0) {
						// 因为只需要单元格的部分内容...所以指定读取当前单元格的值
						Map<String, String> map = new HashMap<String, String>();
						
						String cellValue = cells[0].getContents().trim();
						map.put("town", cellValue);
						
						cellValue = cells[1].getContents().trim();
						map.put("village", cellValue);
						
						cellValue = cells[2].getContents().trim();
						map.put("name", cellValue);
						
						cellValue = cells[11].getContents().trim();
						map.put("tel", cellValue);
						
						cellValue = cells[10].getContents().trim();
						map.put("dw", cellValue);
						
						cellValue = cells[12].getContents().trim();
						map.put("money", cellValue);
						
						list.add(map);
					}
				}
			}
		}
		// 最后关闭资源,释放内存
		wb.close();
		return list;
	}
	
	public static void main(String[] args) { 
		OperatorExcel excel = new OperatorExcel();
		File filepath = new File("f://test//test.xls"); 
		String   str = excel.readExcel(filepath);
		System.out.println(str);
		 
		
	}
	
	
}

?

?

? word操作类:

?

package cn.xsbiz.main;
 
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 业务:java读取word的模板内容动态生成word
 * 
 * 思路:
 *   先用word编辑好模板格式再另存为html;在读取html的内容进行替换。最后保持为word格式
 *   
 *   开始我也另存为word自带的模板老是乱码,,不知道什么原因。。
 *   后面改为xml 乱码问题是没了。。但是提示xml内容错误打不开。。
 *   最后不得不改为html。测试成功
 * 
 * 
 * 标签:$(xxx)
 * 
 * @author 妞见妞爱
 *
 */

public class OperatorWord {
	 
	/**
	 * 替换文档的可变部分 
	 * 
	 * @param content
	 *            原来的文本
	 * @param markersign
	 *            标记符号
	 * @param replacecontent
	 *            替换的内容 用replacecontent替换markersign
	 * @return
	 */
	public String replaceModel(String content, String markersign,
			String replacecontent) {
		String rc = replacecontent;
		String target = "";
		markersign = "$(" + markersign + ")";
		target = content.replace(markersign, rc);
		return target;
	}

	/**
	 * 
	 * 生产单个的word 文档
	 * 
	 * @param inputPath --模板的路径
	 * @param outPath --生成文档的路径
	 * @param data --传入的数据
	 */
	public void replaceTemplate(String inputPath, String outPath, Map<String, String> data) {
		
		/* 字节形式读取模板文件内容,将结果转为字符串 */ 
		String sourcecontent = readTemplate(inputPath);
		 
		/* 修改变化部分 */
		String targetcontent = "";
		String oldText = "";
		Object newValue;
		/* 结果输出保存到文件 */
		try {
			Iterator keys = data.keySet().iterator();
			int keysfirst = 0;
			while (keys.hasNext()) {
				oldText = (String) keys.next();
				newValue = data.get(oldText);
				String newText = (String) newValue; 
				if (keysfirst == 0) {
					targetcontent = replaceModel(sourcecontent, oldText, newText);
					keysfirst = 1;
				} else {
					targetcontent = replaceModel(targetcontent, oldText, newText);
					keysfirst = 1;
				}
			}
			//System.out.println("=======输出=========");
			//System.out.println(targetcontent); 
			FileWriter fw = new FileWriter(outPath, true);
			PrintWriter out = new PrintWriter(fw);
			if (targetcontent.equals("")) {
				out.println(sourcecontent);
			} else {
				out.println(targetcontent);
			}
			out.close();
			fw.close();
			System.out.println(outPath + " 生成文件成功");
		} catch (IOException e) {

			e.printStackTrace();
		}
	}
	
	/**
	 * 读取模板的内容
	 * 
	 * @param inputPath --模板的路径
	 * @return
	 */
	public String readTemplate(String inputPath){ 
		
		/* 字节形式读取模板文件内容,将结果转为字符串 */
		String sourname = inputPath;
		StringBuffer sourcecontent = new StringBuffer();
		InputStream ins = null;
		try {
			ins = new FileInputStream(sourname);
			
			byte[] b = new byte[2048];// 可以修改[2048]提高对于文件的读取速度;
			int bytesRead = 0;
			while (true) { 
				bytesRead = ins.read(b, 0, 2048);
				if (bytesRead == -1) {// end of InputStream
					break;
				}
				sourcecontent.append(new String(new String(b, 0, bytesRead).getBytes(), "GBK")); // 转换字符串的 编码格式
			}
			// sourcecontent = new String(sourcecontent.getBytes(),"UTF-8");
			//System.out.println(sourcecontent);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return sourcecontent.toString();
	}
	
	
	/**
	 * 
	 * 生产一个内容连续的 word 文档
	 * 
	 * @param topPath --模板的头部内容路径
	 * @param inputPath --模板的主体内容路径
	 * @param outPath --生成的文件路径
	 * @param list --传入的数据
	 */
	public void replaceTemplateAll(String topPath,String inputPath, String outPath, List<Map<String, String>> list) {
		/* 字节形式读取模板文件内容,将结果转为字符串 */
		String stringTop = readTemplate(topPath);
		String stringCenter = readTemplate(inputPath);
    
		StringBuffer targetcontent = new StringBuffer();
		targetcontent.append(stringTop);
		
		/* 修改变化部分 */
		String tempcontent = "";
		String oldText = "";
		Object newValue;
		/* 结果输出保存到文件 */
		try {
			
			//日期
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy 年 MM 月 dd 日");
			String date = sdf.format(new Date());
			for(int i=0;i<list.size();i++){
				Map<String, String> data = list.get(i);
				data.put("date", date);
				Iterator keys = data.keySet().iterator();
				int keysfirst = 0;
				while (keys.hasNext()) {
					oldText = (String) keys.next();
					newValue = data.get(oldText);
					String newText = (String) newValue; 
					if (keysfirst == 0) {
						tempcontent = replaceModel(stringCenter, oldText, newText);
						keysfirst = 1;
					} else {
						tempcontent = replaceModel(tempcontent, oldText, newText);
						keysfirst = 1;
					}
				}
				targetcontent.append(tempcontent);
			}
			//模板的尾部
			targetcontent.append("</div></body></html>");
			//System.out.println("=======输出=========");
			//System.out.println(targetcontent.toString()); 
			FileWriter fw = new FileWriter(outPath, true);
			PrintWriter out = new PrintWriter(fw);
			if (targetcontent.length() == 0) {
				out.println("没有内容!");
			} else {
				out.println(targetcontent);
			}
			out.close();
			fw.close();
			System.out.println(outPath + " 生成文件成功");
		} catch (IOException e) {

			e.printStackTrace();
		}
	}

	public static void main(String[] args) {

		SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyyMMddHHmmss");
		Date current = new Date();
		String targetname = sdf.format(current)+".doc";
		 
		OperatorWord word = new OperatorWord();

		// *****************************************
		// 利用HashMap读取数据库中的数据
		HashMap map = new HashMap();
		
		map.put("username", "杨攀");
		map.put("sex", "男");
		map.put("idcard", "431228198701174625");
		// ******************************************
		word.replaceTemplate("F://test//test.htm", "F://test//" + targetname, map);

	}
}

??

? 测试类(把excel转为word):

?

?

package cn.xsbiz.main;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List; 
import java.util.Map;

import sun.java2d.pipe.SpanShapeRenderer.Simple;

/**
 * 
 * 功能:读取 excel 的内容根据wrod模板动态生产 wrod 文档
 * 
 * 标签:$(xxx)
 * 
 * author 妞见妞爱
 *
 */
public class RxlsWdocMain {

	
	public static void main(String[] args) {
		
		OperatorWord word = new OperatorWord();
		
		OperatorExcel excel = new OperatorExcel();
		 
		File filepath = new File("f://xsjsj//tmp001.xls"); 
		
		List<Map<String, String>>  list = excel.readExcelReList(filepath);
		System.out.println("共:"+list.size());
		
		/*
		 * ****************************************************************
		 * 下面的循环生产单个 word 的代码..
		 * 
		 * 业务:excle 有 1000 个人..需要打印出 1000 个人的通知书。(单个的打印、分开管理)
		 * 
		 * 功能:如果excle 中有 1000条 记录,那么就生成 1000 个word   
		 * 
		 * 思路:
		 *    1、定义一个标签格式..本例中是:$(xxx)
		 *    2、在 word 中编辑好模板样式..另存为html模板。(也可以存为其他格式。但是注意编码问题。不然会乱码)
		 *    3、读取 excel 中的内容并封住为一个容器: list<map<String,String>> 
		 *    4、读取html模板,并根据标签替换内容。再重新写个文件。 
		 *    
		 * ****************************************************************
		 * 
		 */
		
		StringBuffer sb = new StringBuffer();
		
		Date date = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy 年 MM 月 dd 日");
		
		for (int i = 0; i < list.size(); i++) {
			Map<String, String> map = list.get(i);
			sb.append(map.get("town")).append("-").append(map.get("village")).append("-").append(map.get("name"));
			map.put("date", sdf.format(date));
			
			word.replaceTemplate("f://xsjsj//template.htm", "f://xsjsj//doc//"+sb.toString()+".doc", map);
			sb.setLength(0);
		}
		
		/*
		 * ****************************************************************
		 * 下面的一个内容连续的 word 的代码..
		 * 
		 * 业务:excle 有 1000 个人..需要连续打印出 1000 个人的通知书。
		 * 
		 * 功能:如果excle 中有 1000条 记录,那么就生成一个 1000 也的 word, 
		 * 
		 * 思路:
		 *    1、定义一个标签格式..本例中是:$(xxx)
		 *    2、在 word 中编辑好模板样式..另存为html模板。但是这里要注意,我们要打开 html 的源码,
		 *       分解源码为:头部和中间、底部等三部分。(底部模板简单。所以我就写在代码中了),
		 *    3、读取 excel 中的内容并封住为一个容器: list<map<String,String>> 
		 *    4、读取html头部和中间、底部模板,并根据标签替换中间模板内容。替换完后,在加底部文件。重写文件。生成一个连续的有分页符的word 
		 *    
		 *    
		 * ****************************************************************
		 * 
		 */
		//word.replaceTemplateAll("f://xsjsj//tem_top.htm","f://xsjsj//tem_center.htm", "f://xsjsj//doc2//jisj.doc", list);
	}
	
	
}

?

?

? 真是辛苦...我发现些文档比代码辛苦多了。。。。哈哈。。。我在上传工程和测试的文档。。。。

?

? 需要的下载啊。。。里面的测试文件数据均为测试数据。。如果运行程序..注意文件的名称修改一致。。。。

?

? 注意路径问题。。我没有判断啊。。O(∩_∩)O哈哈~

  • 代码及文件.rar (665.4 KB)
  • 下载次数: 4
发表评论
用户名: 匿名