按照word模版生成文件,此处为高版本docx,采用ftl的方式
一、前期准备word模版
首先准备好word模版,将docx直接改为zip,双击打开zip,在word文件夹下将document.xml和document.xml.rels两个文件剪切出,将剩余部分最好放置项目中,我为了方便放在了jsp同目录下,将document.xml和document.xml.rels这两个文件直接加后缀‘.ftl’。
用idea打开document.xml.ftl文件,如果格式比较乱,可通过Ctrl+Alt+L格式化,然后添加你需要的参数
这里需要注意如果模版中涵盖图片,如统计图,两个文件需注意参数一致
二、代码生成
import org.apache.commons.io.FileUtils;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;
public ActionForward exportRec(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
response.setCharacterEncoding("GBK");
PrintWriter pw = response.getWriter();
String basepath = request.getSession().getServletContext().getRealPath("/");
String realpath = basepath + "\\tmp\\";
String directory = GeneratorUUID.generateUUID();
String filepath = realpath + directory + "\\";
JSONObject jsonObject = new JSONObject();
File fsub = new File(filepath);
if (!fsub.getParentFile().exists()) {
fsub.getParentFile().mkdir();
}
if (!fsub.exists()) {
fsub.mkdir();
}
try {
String param = request.getParameter("param");
param = URLDecoder.decode(param, "UTF-8");
JSONObject object = Common.getInstance().jsonFormatObject(param);
String beginDate = object.get("beginDate") == null ? "" : (String)object.get("beginDate");
String endDate = object.get("endDate") == null ? "" : (String)object.get("endDate");
String templatedoc = basepath + "\\文件路径\\wordrec.zip";
ZipUtil.decompress(templatedoc, filepath + "tmp\\");
Map<String, Object> dataset = WordUtils.getInstance().getWordDataset(beginDate,endDate,filepath);
WordUtils.getInstance().createWord(dataset, "document.xml.ftl", filepath + "\\tmp\\word\\", "document.xml");
WordUtils.getInstance().createWord(dataset, "document.xml.rels.ftl", filepath + "\\tmp\\word\\_rels\\", "document.xml.rels");
ZipUtil.compress(filepath + "tmp\\", filepath + filename);
try {
FileUtils.deleteDirectory(new File(filepath + "tmp\\"));
} catch (Exception e) {
}
File outZipFile = new File(
filepath + "\\" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + ".zip");
InputStream in = null;
ZipOutputStream zipOutputStream = new ZipOutputStream(outZipFile);
String filesStr[] = fsub.list();
for (String ffn : filesStr) {
if (!ffn.endsWith("zip")) {
File zpfile = new File(filepath + ffn);
in = new FileInputStream(zpfile);
zipOutputStream.putNextEntry(new ZipEntry(ffn));
int len = 0;
byte b[] = new byte[1024];
while ((len = in.read(b)) > -1) {
zipOutputStream.write(b, 0, len);
}
zpfile.delete();
in.close();
zipOutputStream.closeEntry();
}
}
zipOutputStream.close();
if (outZipFile.exists()) {
jsonObject.put("code", "0");
jsonObject.put("id", GeneratorUUID.generateUUID().toLowerCase().replace("-", ""));
jsonObject.put("name", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
jsonObject.put("url", "\\tmp\\" + directory + "\\" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + ".zip");
}
} catch (Exception e) {
e.printStackTrace();
jsonObject.put("code", "1");
jsonObject.put("msg", e.getMessage());
throw e;
} finally {
try {
File[] filesubs = fsub.listFiles();
for (File fa : filesubs) {
if (!fa.getName().endsWith(".zip")) {
boolean flag = fa.delete();
if (!flag) {
System.gc();
fa.delete();
}
}
}
} catch (Exception e) {
}
}
pw.write(jsonObject.toJSONString());
pw.flush(); pw.close();
return (mapping.findForward(null));
}
生成word工具类
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.jfree.chart.*;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.StandardCategoryLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.BarRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.CategoryDataset;
import org.jfree.data.DefaultCategoryDataset;
import org.jfree.data.DefaultPieDataset;
import org.jfree.ui.TextAnchor;
public class WordUtils {
private static final class InstanceHolder {
static final WordUtils instance = new WordUtils();
}
public static WordUtils getInstance() {
return WordUtils.InstanceHolder.instance;
}
private String getDateStr(String day,int num){
String str = "";
try {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date dd = format.parse(day);
Calendar calendar1 = Calendar.getInstance();
calendar1.setTime(dd);
calendar1.add(Calendar.DATE, num);
str = format.format(calendar1.getTime());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return str;
}
public Map<String,Object> getWordDataset(String orgid,String exptype
,String orgname,String title,String beginDate,String endDate
,String filepath){
String docimgpath = filepath + "\\tmp\\word\\media\\";
Map<String, Object> dataMap = new HashMap<String, Object>();
/**
* word模板操作流程:①在word文档中编写变量(${}) ②将docx改为zip
* ③双击zip,找到word文件夹下拿到document.xml,加后缀.ftl
* ④找到word\_rels文件夹下document.xml.rels,加后缀.ftl
* ⑤调整document.xml.ftl、document.xml.rels.ftl
*/
// 0.标题、日期
dataMap.put("title", title);
dataMap.put("riqi",sjd);
String jbtbid = "tb"+GeneratorUUID.generateUUID().toLowerCase();
dataMap.put("jbtbid",jbtbid);
if(total > 0){
// 图表标题
String tbtitle = ttitle + "XX统计分析";
DefaultCategoryDataset bardataset = new DefaultCategoryDataset();
bardataset.addValue(10,"昨日","湿度");
bardataset.addValue(5,"今日","湿度");
bardataset.addValue(2,"昨日","温度");
bardataset.addValue(5,"今日","温度");
createBarChart(tbtitle, "", ytitle, bardataset, false, docimgpath + jbtbid + ".jpg");
}
dataMap.put("list",数据list);
return dataMap;
}
/**
* 生成word文档
*
* @param dataMap
* @param templateName
* @param filePath
* @param fileName
*/
public void createWord(Map<String, Object> dataMap, String templateName, String filePath, String fileName) {
Writer out = null;
try {
Configuration configuration = new Configuration();
configuration.setDefaultEncoding("UTF-8");
configuration.setClassForTemplateLoading(WordUtils.class, "xml.ftl地址");
Template template = configuration.getTemplate(templateName);
File outFile = new File(filePath + File.separator + fileName);
if (!outFile.getParentFile().exists()) {
outFile.getParentFile().mkdir();
}
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));
template.process(dataMap, out);
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void createBarChart(String title, String xtitle, String ytitle, CategoryDataset dataset, boolean islegend, String path) {
String str = "";
JFreeChart chart = createBarChart(title, xtitle, ytitle, dataset, islegend);
copyJFreeChartFile(chart, path);
}
private void createPieChart(String title, DefaultPieDataset dataset, boolean islegend, String path) {
String str = "";
JFreeChart chart = createPieChart(title, dataset, islegend);
copyJFreeChartFile(chart, path);
}
/**
* 创建柱状图
*
* @param title
* @param xtitle
* @param ytitle
* @param dataset
* @param islegend
* @return
*/
private JFreeChart createBarChart(String title, String xtitle, String ytitle, CategoryDataset dataset, boolean islegend) {
JFreeChart chart = ChartFactory.createBarChart(title, xtitle, ytitle, dataset, PlotOrientation.VERTICAL, islegend, false, false);
chart.setTitle(new TextTitle(title,new Font("黑体",Font.BOLD,28)));
chart.setBackgroundPaint(Color.white);
chart.setAntiAlias(true);
//图例
StandardLegend legend = (StandardLegend) chart.getLegend();
if (legend != null) {
legend.setDisplaySeriesShapes(true);
legend.setShapeScaleX(1.5);
legend.setShapeScaleY(1.5);
legend.setDisplaySeriesLines(true);
legend.setAnchor(Legend.NORTH_NORTHEAST);
legend.setItemFont(new Font("宋体", Font.PLAIN, 16));
}
CategoryPlot plot = chart.getCategoryPlot();
plot.setBackgroundPaint(Color.white);
plot.setDomainGridlinePaint(Color.white);
plot.setRangeGridlinePaint(Color.white);
plot.setBackgroundAlpha(0.5f);
plot.setForegroundAlpha(0.7f);
plot.setRangeGridlinePaint(Color.BLACK);
plot.setOutlinePaint(Color.BLACK);
// 设置是否显示水平方向背景线,默认值为true
plot.setRangeGridlinesVisible(true);
// 设置垂直方向背景线颜色
plot.setDomainGridlinePaint(Color.BLACK);
// 设置是否显示垂直方向背景线,默认值为false
plot.setDomainGridlinesVisible(false);
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
rangeAxis.setUpperMargin(0.1D);
rangeAxis.setAutoRange(true);
//rangeAxis.setRange(0.0D, 100.0D);
rangeAxis.setLabelFont(new Font("宋体", Font.BOLD, 16));
rangeAxis.setTickLabelFont(new Font("宋体", Font.BOLD, 16));
BarRenderer renderer = (BarRenderer) plot.getRenderer();
renderer.setSeriesItemLabelsVisible(0, Boolean.TRUE);
//renderer.setSeriesItemLabelFont(0, new Font("宋体", Font.BOLD, 16));
//renderer.setSeriesItemLabelFont(1, new Font("宋体", Font.BOLD, 16));
renderer.setItemLabelFont(new Font("宋体", Font.BOLD, 16));
renderer.setDrawBarOutline(false); // Bar的外轮廓线不画
GradientPaint gradientpaint = new GradientPaint(0.0F, 0.0F, Color.blue, 0.0F, 0.0F, new Color(0, 0, 64)); //设定特定颜色
renderer.setSeriesPaint(0, gradientpaint);
renderer.setLabelGenerator(new StandardCategoryLabelGenerator());
renderer.setItemLabelsVisible(true);
renderer.setItemMargin(0.05);
renderer.setMaxBarWidth(0.05);
renderer.setSeriesItemLabelFont(0, new Font("宋体", Font.BOLD, 16));
ItemLabelPosition p = new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.BASELINE_CENTER, TextAnchor.CENTER, 0);
renderer.setPositiveItemLabelPosition(p);
//renderer.setNegativeItemLabelPosition(p);
CategoryAxis domainAxis = plot.getDomainAxis();
domainAxis.setCategoryLabelPositions(CategoryLabelPositions.STANDARD);
domainAxis.setTickLabelFont(new Font("宋体", Font.BOLD, 16));
return chart;
}
/**
* 生成jfreechart图片
*
* @param chart
* @param path
*/
private void copyJFreeChartFile(JFreeChart chart, String path) {
File newFile = new File(path);
try {
ChartUtilities.saveChartAsJPEG(newFile, 100, chart, 1000, 800, null);
} catch (IOException e) {
e.printStackTrace();
}
}
public JFreeChart createPieChart(String title,DefaultPieDataset pds, boolean islegend) {
// 分别是:显示图表的标题、需要提供对应图表的DateSet对象、是否显示图例、是否生成贴士以及是否生成URL链接
JFreeChart chart = ChartFactory.createPieChart(title, pds, islegend, false, false);
chart.setBackgroundPaint(Color.white);
// 如果不使用Font,中文将显示不出来
Font font = new Font("宋体", Font.BOLD, 28);
// 设置图片标题的字体
chart.getTitle().setFont(font);
// 得到图块,准备设置标签的字体
PiePlot plot = (PiePlot) chart.getPlot();
// 设置标签字体
plot.setLabelFont(font);
plot.setStartAngle(new Float(3.14f / 2f));
// 设置plot的前景色透明度
plot.setForegroundAlpha(0.7f);
// 设置plot的背景色透明度
plot.setBackgroundAlpha(0.5f);
plot.setLabelBackgroundPaint(Color.white);
// 饼图连接线
plot.setLabelLinkStroke(new BasicStroke(5.0f));
return chart;
}
}
ZipUtil工具类
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.*;
/**
* java.util.zip压缩/解压文件
*/
public class ZipUtil {
/**
* 缓冲器大小
*/
private static final int BUFFER = 512;
/**
* 得到源文件路径的所有文件
*
* @param dirFile 压缩源文件路径
*/
public static List<File> getAllFile(File dirFile) {
List<File> fileList = new ArrayList<File>();
File[] files = dirFile.listFiles();
for (File file : files) {//文件
if (file.isFile()) {
fileList.add(file);
System.out.println("add file:" + file.getName());
} else {//目录
if (file.listFiles().length != 0) {//非空目录
fileList.addAll(getAllFile(file));//把递归文件加到fileList中
} else {//空目录
fileList.add(file);
System.out.println("add empty dir:" + file.getName());
}
}
}
return fileList;
}
/**
* 获取相对路径
*
* @param dirPath 源文件路径
* @param file 准备压缩的单个文件
*/
public static String getRelativePath(String dirPath, File file) {
File dirFile = new File(dirPath);
String relativePath = file.getName();
while (true) {
file = file.getParentFile();
if (file == null) {
break;
}
if (file.equals(dirFile)) {
break;
} else {
relativePath = file.getName() + "/" + relativePath;
}
}
return relativePath;
}
/**
* @param destPath 解压目标路径
* @param fileName 解压文件的相对路径
*/
public static File createFile(String destPath, String fileName) {
String[] dirs = fileName.split("/");//将文件名的各级目录分解
File file = new File(destPath);
if (dirs.length > 1) {//文件有上级目录
for (int i = 0; i < dirs.length - 1; i++) {
file = new File(file, dirs[i]);//依次创建文件对象知道文件的上一级目录
}
if (!file.exists()) {
file.mkdirs();//文件对应目录若不存在,则创建
try {
System.out.println("mkdirs: " + file.getCanonicalPath());
} catch (IOException e) {
e.printStackTrace();
}
}
file = new File(file, dirs[dirs.length - 1]);//创建文件
return file;
} else {
if (!file.exists()) {//若目标路径的目录不存在,则创建
file.mkdirs();
try {
System.out.println("mkdirs: " + file.getCanonicalPath());
} catch (IOException e) {
e.printStackTrace();
}
}
file = new File(file, dirs[0]);//创建文件
return file;
}
}
/**
* 没有指定压缩目标路径进行压缩,用默认的路径进行压缩
*
* @param dirPath 压缩源文件路径
*/
public static void compress(String dirPath) {
int firstIndex = dirPath.indexOf("/");
int lastIndex = dirPath.lastIndexOf("/");
String zipFileName = dirPath.substring(0, firstIndex + 1) + dirPath.substring(lastIndex + 1);
compress(dirPath, zipFileName);
}
/**
* 压缩文件
*
* @param dirPath 压缩源文件路径
* @param zipFileName 压缩目标文件路径
*/
public static void compress(String dirPath, String zipFileName) {
File dirFile = new File(dirPath);
List<File> fileList = getAllFile(dirFile);
byte[] buffer = new byte[BUFFER];
ZipEntry zipEntry = null;
int readLength = 0; //每次读取出来的长度
try {
// 对输出文件做CRC32校验
CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream(
zipFileName), new CRC32());
ZipOutputStream zos = new ZipOutputStream(cos);
for (File file : fileList) {
if (file.isFile()) { //若是文件,则压缩文件
zipEntry = new ZipEntry(getRelativePath(dirPath, file)); //
zipEntry.setSize(file.length());
zipEntry.setTime(file.lastModified());
zos.putNextEntry(zipEntry);
InputStream is = new BufferedInputStream(new FileInputStream(file));
while ((readLength = is.read(buffer, 0, BUFFER)) != -1) {
zos.write(buffer, 0, readLength);
}
is.close();
System.out.println("file compress:" + file.getCanonicalPath());
} else { //若是空目录,则写入zip条目中
zipEntry = new ZipEntry(getRelativePath(dirPath, file) + "/");
zos.putNextEntry(zipEntry);
System.out.println("dir compress: " + file.getCanonicalPath() + "/");
}
}
zos.close(); //最后得关闭流,不然压缩最后一个文件会出错
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 解压
*/
public static void decompress(String zipFileName, String destPath) {
try {
ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFileName));
ZipEntry zipEntry = null;
byte[] buffer = new byte[BUFFER];//缓冲器
int readLength = 0;//每次读出来的长度
while ((zipEntry = zis.getNextEntry()) != null) {
if (zipEntry.isDirectory()) {//若是目录
File file = new File(destPath + "/" + zipEntry.getName());
if (!file.exists()) {
file.mkdirs();
System.out.println("mkdirs:" + file.getCanonicalPath());
continue;
}
}//若是文件
File file = createFile(destPath, zipEntry.getName());
System.out.println("file created: " + file.getCanonicalPath());
OutputStream os = new FileOutputStream(file);
while ((readLength = zis.read(buffer, 0, BUFFER)) != -1) {
os.write(buffer, 0, readLength);
}
os.close();
System.out.println("file uncompressed: " + file.getCanonicalPath());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}