从零开始—我的开源项目4:代码完善(上)

计划逐步完善这款软件,让不懂编程的用户也可以轻松使用。


模板篇:

针对设计中的1、2步骤

第一步:从目录中读取.xml模板文件,而不是将模板文件内置到代码项目中。

原代码中用

configure.setClassForTemplateLoading(this.getClass(),"/excel2word/template");

读取项目中的模板目录,修改为

config.setDirectoryForTemplateLoading(new File("D:/temp/") );
即可实现从系统文件夹中读取模板文件。

第二步:word另存为.xml时${}之间产生的多余字符问题。在word中采用特殊字符如crmark01 替代${01}。

读取.xml文件之后,通过正则replaceAll将自定义标记格式替换为freemarker标记,存储为temp.xml文件,完成操作后再删除此文件。

正则表达式如下:

String xmlStr ="crmark09";
String str = xmlStr.replaceAll("crmark0?(\\d{1,2})", "\\${m$1}");
System.out.println(str);

将模板的文件导入、加载以及移除等功能抽象为一个TemplateManager类,并将路径等信息暂时存放在某个常量类中。

先将word另存为的template.xml文件读取为String,然后replaceAll掉所有的crmark标签为${m数字}格式,最后再生成一个新的temp.xml文件

注意:生成temp.xml的方式一定要采用字节流!字符流会造成生成的word格式错误。


WorkConstant代码:

package excel2word.config.constants;

public class WorkConstant {

	public static final String WORK_PATH = "D:/temp/";
	public static final String TEMPLATE_NAME = "template";
	public static final String TEMP_NAME = "temp";
	
}

FileType代码:

package excel2word.config.enumerations;

public enum FileType {
	XML_TYPE(".xml"),
	WORD_03_TYPE(".doc"),
	EXCEL_03_TYPE(".xls")
	;
	private String label;
	
	private FileType(String label) {
		this.label = label;
	}

	public String getLabel() {
		return label;
	}
}

TemplateManager代码:

package excel2word.template;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Writer;

import org.apache.commons.lang.StringUtils;

import excel2word.config.constants.WorkConstant;
import excel2word.config.enumerations.FileType;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;

public class TemplateManager {

	private static Configuration config = null;
	
	private static String templatePath;
	
	/**
	 * 生成模板temp文件
	 * 
	 * @param TemplateType type 模板类型
	 * @return Template 模板
	 * @throws IOException 
	 */
	public static Template loading(FileType templateType) throws IOException {
		config = new Configuration();
		config.setDefaultEncoding("utf-8");
		//TODO work目录不存在 可自动创建
		Template template  = null;
		InputStream in = null;
		BufferedReader reader = null;
//		Writer out = null;
		FileOutputStream fos = null;
		config.setObjectWrapper(new DefaultObjectWrapper());
		config.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
		try {
			config.setDirectoryForTemplateLoading(new File(WorkConstant.WORK_PATH) );
			in = new FileInputStream(new File(WorkConstant.WORK_PATH
					+ WorkConstant.TEMPLATE_NAME + templateType.getLabel()));
			reader = new BufferedReader(new InputStreamReader(in));
			String line = null;
			StringBuilder sb = new StringBuilder();
			while ((line = reader.readLine()) != null) {
				sb.append(line);
			}
			TemplateManager.templatePath = WorkConstant.WORK_PATH
					+ WorkConstant.TEMP_NAME + templateType.getLabel();
//			out = new BufferedWriter(new FileWriter(templatePath));
//			out.write(sb.toString().replaceAll("crmark0?(\\d{1,2})", "\\${m$1}"));
			
			fos = new FileOutputStream(new File(templatePath));
			fos.write(sb.toString().replaceAll("crmark0?(\\d{1,2})", "\\${$1}").getBytes());
			template = config.getTemplate(WorkConstant.TEMP_NAME + templateType.getLabel());
		} catch (IOException e) {
			e.printStackTrace();
			destory();
			throw e;
		} finally {
			try {
				if (fos != null) {
					fos.close();
				}
//				if (out != null) {
//					out.close();
//				}
				if (in != null) {
					in.close();
				}
				if (reader != null) {
					reader.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
//				out = null;
				fos = null;
				in = null;
				reader = null;
			}
		}
		return template;
	}
	
	/**
	 * 销毁模板,清除temp文件
	 */
	public static void destory() {
		if(StringUtils.isNotBlank(TemplateManager.templatePath)) {
			File file = new File(TemplateManager.templatePath);
			if (file.exists()) {
				file.delete();
			}
			TemplateManager.templatePath = null;
			config.clearTemplateCache();
		}
	}
}


工具篇:

针对设计中的3、4步骤

第一步:创建excel数据读取工具类;

原计划提取的数据形式应为List<Map<Integer, Object>>,excel中的列号=标签中数字=Map中的key。

template.process方法没有解析Integer类型的key,因此将标签修改为${m数字}

XlsUtil代码:

package excel2word.utils;

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

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

public class XlsUtil {

	public static Map<String, Object> extractRow(Row row){
		//默认第一行为生成文件名,所以不能为null
		if (null == row || null == row.getCell(0)) {
			return null;
		}
		Map<String, Object> params = new HashMap<String, Object>();
		for (int i=0; i<100; i++) {
			//key对应列,为空显示为空字段
			params.put("m"+(i+1), row.getCell(i)==null?"":row.getCell(i));
		}
		return params; 
	}
	
	public static List<Map<String, Object>> extractXls(FileInputStream fis) throws IOException{
		List<Map<String, Object>> results = new ArrayList<Map<String,Object>>();
		try {
			Workbook book = new HSSFWorkbook(fis);
			Sheet sheet = book.getSheetAt(0);
			for (int i=sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) {
				Map<String, Object> param = extractRow(sheet.getRow(i));
				results.add(param);
			}
		} catch (IOException e) {
			throw e;
		} 
		return results;
	}
	
}


word工具类比较简单,唯一需要注意的是重名问题。

DocUtil代码:

package excel2word.utils;

import java.io.File;

import excel2word.config.constants.WorkConstant;
import excel2word.config.enumerations.FileType;

public class DocUtil {

	public static File create(FileType type, String docName) {
		//解决重名问题
		int i = 1;
		String outPath = WorkConstant.WORK_PATH + docName+type.getLabel();
		File doc = new File(outPath);
		while (doc.exists()) {
			outPath = WorkConstant.WORK_PATH + docName+"("+i+")"+type.getLabel();
			doc = new File(outPath);
			i++;
		}
		return doc;
	} 
}



最后再来看一下main方法,顺序为

创建模板,读取excel数据,遍历数组创建word文件。

MainUtil代码:

package excel2word;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.List;
import java.util.Map;

import excel2word.config.constants.WorkConstant;
import excel2word.config.enumerations.FileType;
import excel2word.template.TemplateManager;
import excel2word.utils.DocUtil;
import excel2word.utils.XlsUtil;
import freemarker.template.Template;

public class MainUtil {

	public static void main(String[] args) {
		Template template = null;
		FileInputStream xlsFin = null;
		Writer out = null;
		List<Map<String, Object>> xlsList = null;
		try {
			template = TemplateManager.loading(FileType.XML_TYPE);
			xlsFin = new FileInputStream(new File(WorkConstant.WORK_PATH+WorkConstant.TEMPLATE_NAME+FileType.EXCEL_03_TYPE.getLabel()));
			xlsList = XlsUtil.extractXls(xlsFin);
			for (Map<String, Object> xls : xlsList) {
				//默认第一列为doc文件名
				File doc = DocUtil.create(FileType.WORD_03_TYPE, xls.get("m1").toString());
				out= new BufferedWriter(new OutputStreamWriter(new FileOutputStream(doc),"utf-8"));
				template.process(xls, out);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			TemplateManager.destory();
			if (null != xlsFin) {
				try {
					xlsFin.close();
				} catch (IOException e) {
					e.printStackTrace();
				} finally {
					xlsFin = null;
				}
			}
		}
	}
}


遇到的问题:

字节流导致的word格式错误。

行号作为key的Map<Integer, Object> 不能解析。

constant指定路径方式不灵活。

word文件的标签容易增加一些格式标签。


明天继续改造







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值