poi和weboffice

2019-07-08 14:06:54 huangqing510 阅读数 435

利用FreeMarker导出word相关经验分享

1.FreeMarker简介:

​ FreeMarker生成word文档的功能是由XML+FreeMarker来实现的。先把word文件另存为xml,在xml文件中插入特殊的字符串占位符($),将xml翻译为FreeMarker模板(ftl文件),最后用java来解析FreeMarker模板,编码调用FreeMarker实现文本替换并输出Doc。优点:纯Java编程,能够根据模版生成Word文档,能够很好的操作word的文档的样式等信息。

2.关键代码:


以吴中word导出为例,dataMap为计算之后所有数据和图片的map

//获取插入模板的数据和图片
Map<String,Object> dataMap = wzWordManager.getDataMap(year, month, start_date, end_date);
Configuration configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
configuration.setDirectoryForTemplateLoading(new File(ftlPath));
//获取模板
Template freemarkerTemplate = configuration.getTemplate("monthReport_wuzhong.ftl");
if (!outFile.getParentFile().exists()){
	outFile.getParentFile().mkdirs();
}
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));
//生成文件
freemarkerTemplate.process(dataMap, out);
//关闭流
out.flush();
out.close();

绘制图表方法,涉及到标题、图例、柱体、x/y轴的样式配置

[外链图片转存失败(img-uGTVL1mm-1562565936322)(1.png)]

	public void getImgDataBarCharts(List<Map<String,Object>> list, Map<String, Object> dataMap, String title,
									String nameColumn, List<String> columns, String imgName,int positionFlag,int legendFlag) {
		//多系列柱形图 绘制带数值
		if(null == list || list.size() == 0){
			dataMap.put(imgName + "_str", "");
			return;
		}
		if(null == columns || columns.size() == 0){
			dataMap.put(imgName + "_str", "");
			return;
		}
		//图表数据集合
		DefaultCategoryDataset dataset = new DefaultCategoryDataset();
		for(int i=0;i<list.size();i++){
			for(int n=0;n<columns.size();n++){
                dataset.addValue(Double.parseDouble(list.get(i).get(columns.get(n)).toString()), columns.get(n), list.get(i).get(nameColumn).toString());
			}
		}
        //创建主题样式 解决乱码问题
        StandardChartTheme standardChartTheme = new StandardChartTheme("CN");
        standardChartTheme.setRegularFont(new Font("宋书", Font.PLAIN, 15));
        ChartFactory.setChartTheme(standardChartTheme);
		JFreeChart chart = ChartFactory.createBarChart(title, null, null, dataset, PlotOrientation.VERTICAL, true, true, false);
        chart.getLegend().setFrame(new BlockBorder(Color.WHITE));
        chart.getLegend().setPosition(RectangleEdge.TOP);
        if(legendFlag!=1) {
			chart.removeLegend();
		}
		updateFont(chart);
		CategoryPlot plot = (CategoryPlot) chart.getPlot();
		//去掉标尺栏
		plot.setAxisOffset(new RectangleInsets(0, 0, 0, 0));
		BarRenderer renderer = (BarRenderer) plot.getRenderer();
		renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
		renderer.setBaseItemLabelsVisible(true);
		renderer.setBaseItemLabelFont(new Font("黑体", Font.PLAIN, 10));
		renderer.setMaximumBarWidth(0.050);// 设置柱子最大宽度
        renderer.setItemMargin(0.0);
		renderer.setShadowVisible(false); //柱子不显示阴影
		renderer.setBarPainter(new StandardBarPainter());//柱子纯色
		//设置柱子颜色
		renderer.setSeriesPaint(0,Color.decode("#4F81BD"));
		renderer.setSeriesPaint(1,Color.decode("#002060"));
		renderer.setSeriesPaint(2,Color.decode("#90ED7D"));
		renderer.setSeriesPaint(3,Color.decode("#8B4513"));
		plot.setRenderer(renderer);
		plot.setBackgroundPaint(null);//去掉背景色
		//优化x.y轴
		setXAixs(plot);
		setYAixs(plot);
		if(positionFlag==1){
			CategoryAxis axis = plot.getDomainAxis(); //x轴
			axis.setMaximumCategoryLabelLines(10); //标题行数,每个字显示一行
			axis.setMaximumCategoryLabelWidthRatio(1f); //每个标题宽度,控制为1个字的宽度
//			CategoryAxis categoryaxis = plot.getDomainAxis();
//			//x轴45度倾斜
//			if(null != categoryaxis){ categoryaxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);}
		}
		chartToImgToBase64ToDataMap(chart, dataMap, imgName);
	}

3.JFreeChart相关api

  • ChartFactory 类。提供了实用方法的集合,用于生成标准的图表。以下是几个主要方法:

    • createPieChart()使用默认设置创建一个饼图。
    • createPieChart3D()使用指定的数据集三维/3D饼图。
    • createBarChart()创建一个条形图。
    • createBarChart3D()创建一个柱形图具有3D效果。
    • createLineChart()创建折线图。
    • createLineChart3D()创建一个折线图与3D效果。
    • createXYLineChart()使用默认设置创建基于XYDataset的折线图。
  • ChartUtilities 类。提供JFreeCharts包括将图表转换成图像文件格式,如PNG,JPEG和创建HTML图像映射方法的实用方法的集合。

    • saveChartAsPNG()转换和保存图表为PNG格式指定的文件
    • saveChartAsJPEG()转换并保存一个图表,以JPEG格式指定的文件。
  • StandardChartTheme类。JfreeChart主题样式有StandardChartTheme进行统一管理,包括字体,绘制颜色,线条类型,坐标轴样式等。

    • new StandardChartTheme(“CN”)创建主题样式 解决乱码问题
    • setRegularFont()设置字体样式
    • setTitlePaint()设置标题字体颜色
    • setLegendItemPaint()设置字体颜色
    • setPlotBackgroundPaint()设置绘制区域背景色
  • BarRenderer类。柱状图渲染

    • setBaseItemLabelFont()设置条目标签字体
    • setBaseItemLabelGenerator()设置条目标签
    • setBaseItemLabelsVisible()设置条目标签是否显示
    • setMaximumBarWidth()设置柱子最大宽度
    • setItemMargin()设置每个bar间距(0-1)
    • setShadowVisible()不显示柱子阴影
    • setBarPainter(new StandardBarPainter())设置柱状图基本渲染,不采用渐变
    • setSeriesPaint()设置柱子颜色
  • Legend类。图例类

    • setFrame()设置图例背景色
    • setPosition()设置图例位置(上下左右)
    • setItemFont()设置图例字体
    • setItemPaint()设置图例字体颜色
    • chart.removeLegend()不显示图例
  • x轴标题45度倾斜

CategoryAxis categoryaxis = plot.getDomainAxis();
if(null != categoryaxis){
    categoryaxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);
}

[外链图片转存失败(img-JBhpcrZF-1562565936323)(3.png)]

  • x轴标题竖直显示
CategoryAxis axis = plot.getDomainAxis(); //x轴
axis.setMaximumCategoryLabelLines(10); //标题行数,每个字显示一行
axis.setMaximumCategoryLabelWidthRatio(1f); //每个标题宽度,控制为1个字的宽度

[外链图片转存失败(img-WtSUuic4-1562565936323)(2.png)]

参考资料:https://blog.csdn.net/fireofjava/article/details/44629025
https://www.yiibai.com/jfreechart/jfreechart_referenced_apis.html

2010-01-05 18:45:00 jzdzhiyun 阅读数 592

  1. 需要引用Microsoft.Office.Interop.Word

 

#region WordDoc

        public void WordDoc()
        {
            Microsoft.Office.Interop.Word.Application appWord = null;
            Microsoft.Office.Interop.Word.Document doc = null;
            try
            {
                appWord = new Microsoft.Office.Interop.Word.ApplicationClass();
                appWord.Visible = false;
                object objTrue = true;
                object objFalse = false;
                object objTemplate = @"G:"123.doc";
                //System.Web.HttpContext.Current.Server.MapPath(@"G:"123.doc");//模板路径
                object objDocType = Microsoft.Office.Interop.Word.WdDocumentType.wdTypeDocument;
                doc = appWord.Documents.Add(ref objTemplate, ref objFalse, ref objDocType, ref objTrue);
                //第一步生成word文档
                //定义书签变量
                object obDD_Name = "DD_Name";//姓 名
                object obDD_Sex = "DD_Sex";//性 别
                object obDD_Age = "DD_Age";//年龄
                object obDD_Birthday = "DD_Birthday"; //出生年月
                object obDD_Nation = "DD_Nation"; //民 族
                object obDD_Native = "DD_Native"; //籍 贯
                //...
                //第二步 读取数据,填充数据集
                //SqlDataReader dr = null;//读取出来的数据集
                //第三步 给书签赋值
                //给书签赋值
                object missing = System.Reflection.Missing.Value;
                object BookMarkName = "obDD_Name";
                object what = Microsoft.Office.Interop.Word.WdGoToItem.wdGoToBookmark;
                doc.ActiveWindow.Selection.GoTo(ref what, ref missing, ref missing, ref BookMarkName);
                doc.ActiveWindow.Selection.TypeText("朱一鸣");
                doc.ActiveWindow.Selection.TypeParagraph();
                //doc.Bookmarks.get_Item(ref i).Range.Text = "朱一鸣"; //姓 名
                //doc.Bookmarks.get_Item(ref j).Range.Text = "男";//性 别
                //doc.Bookmarks.get_Item(ref k).Range.Text = "23";//年龄
                // ....
                //第四步 生成word
                object filename = @"G:"zym" + DateTime.Now.ToString("yyyyMMddHHmmssffff") + ".doc";
                object miss = System.Reflection.Missing.Value;
                doc.SaveAs(ref filename, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss);
                object missingValue = Type.Missing;
                object doNotSaveChanges = Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges;
                doc.Close(ref doNotSaveChanges, ref missingValue, ref missingValue);
                appWord.Application.Quit(ref miss, ref miss, ref miss);
                doc = null;
                appWord = null;

                Response.Buffer = true;
                Response.Clear();
                Response.ClearContent();
                Response.ClearHeaders();
                Response.ContentType = "application/msword";

                Response.Charset = "utf-8";
                Response.ContentEncoding = System.Text.Encoding.GetEncoding("utf-8");
                System.IO.FileInfo file = new System.IO.FileInfo(filename.ToString());

                Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(file.Name, System.Text.Encoding.UTF8) + "");
                //attachment --- 作为附件下载
                //inline --- 在线打开
                //filename如过是中文,则可以用HttpUtility.UrlEncode(fileName,System.Text.Encoding.UTF8)
                //进行进行编码,以解决文件名乱码的问题


                Response.WriteFile(file.FullName);
                Response.Flush();
                Response.Close();
                File.Delete(filename.ToString());
            }
            catch (System.Exception e)
            {
                //捕捉异常,如果出现异常则清空实例,退出word,同时释放资源
                string aa = e.ToString();
                object miss = System.Reflection.Missing.Value;
                object missingValue = Type.Missing;
                object doNotSaveChanges = Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges;
                doc.Close(ref doNotSaveChanges, ref missingValue, ref missingValue);
                appWord.Application.Quit(ref miss, ref miss, ref miss);
                doc = null;
                appWord = null;
            }

        }
        #endregion

 

转自:http://www.cnblogs.com/zym23l/archive/2008/10/08/1306630.html

2018-08-11 13:59:31 x308561498 阅读数 10295

公司最近需要开发一个在线word功能,开始用pageoffice开发的功能被否决因为pageoffice的版权问题,后采用点聚weboffice的免费版开发.因为多个页面需要使用在线word功能,对于weboffice提供的activeX对象进行一定的封装,减少代码的冗余 和开发时的方便.
一 简单分析
weboffice是需要安装ocx控件来完成对本地word的调用,因为activex的原因,所以在IE上的兼容肯定比较好.由于技术和资源问题该实现不支持谷歌和火狐.
对于ocx控件可以提供两种安装方式,如果放在web服务器上的话,可以提供cab文件实现在线安装. 第二种方式,直接在客户端安装exe文件.
二 实现方式
这里写图片描述
首先需要成功调用activex对象,实现上图效果.因为activex obj的原因. 背景自己无法实现改变,别人说:可以通过iframe调整z-index效果,再配合js中object的param属性配置实现.但是尝试多次,无法实现,可能和IE版本有关系
这里写图片描述
a)新建文档
新建文档调用了封装的webofficeTool的createWord方法,因为开发时间原因没有提供完全的封装
只是使用了weboffice的LoadOriginalFile方法来打开服务器的模板文件,并且简单提供了提示消息.(本来打算改成bootstrap的tooltip来提示,后来因为web服务器样式原因需统一风格,还得修改N多的css样式来达到系统一致的风格而放弃)
这里写图片描述
加载成功后效果
这里写图片描述
因为word的滚动和 浏览器滚动效果的不一致,和高度的控制, 统一放置在iframe中实现控制
这里写图片描述
直接滚动iframe来实现操作word的浏览,同时放出weboffice的全屏功能,方便编辑文档的方便.因为全屏时开发完成后提的功能,当时没有详细研究文档中是否有具体接口所以直接把菜单栏隐藏的全屏功能放出来使用 ,具体还有打印和打印预览 另存为等等可以查看weboffice的具体接口文档
这里写图片描述
提供资源下载地址(因为开发时,csdn资源比较好,苦于c币原因,无奈积分下载)
原生接口的saveAsPDF不能用的原因,是缺少TrustedPDF插件原因,后来点聚在收费的weboffice中才提供原生word转PDF,所以在上传时的转换WORD为PDF的想法破灭了(POI转换过于影响样式放弃,libreoffice转换简单,但是linux配置麻烦,暂时打印和预览还是通过weboffice重新加载word后使用ocx的打印和预览功能)
weboffice6的安装程序和js封装实例https://download.csdn.net/download/x308561498/10597330

2019-04-17 09:45:47 qq_40238006 阅读数 2135

实现思想介绍

文件上传的同时就做好文件处理。所有的文件交由服务器处理,避免客户端安装插件,数据库设计上要提供保存两个文件的存放地址的字段,一个是供给下载原件使用,另一个供给在线预览使用。
1、使用OpenOffice将office文件转成PDF文件
2、使用SwfTools将PDF等类型文件转成swf文件

使用插件(在服务器上下载并安装,紧记安装路径,后面会用到)

OpenOffice

  • Apache_OpenOffice_4.1.6_Win_x86_install_zh-CN.exe
  • 下载地址

SwfTools

使用的jar

<!-- 在线预览office文件 	start-->
    	<!-- https://mvnrepository.com/artifact/commons-cli/commons-cli -->
		<dependency>
		    <groupId>commons-cli</groupId>
		    <artifactId>commons-cli</artifactId>
		    <version>1.4</version>
		</dependency>
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.4</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.artofsolving/jodconverter -->
		<dependency>
		    <groupId>com.artofsolving</groupId>
		    <artifactId>jodconverter</artifactId>
		    <version>2.2.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.openoffice/juh -->
		<dependency>
		    <groupId>org.openoffice</groupId>
		    <artifactId>juh</artifactId>
		    <version>4.1.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.openoffice/jurt -->
		<dependency>
		    <groupId>org.openoffice</groupId>
		    <artifactId>jurt</artifactId>
		    <version>4.1.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.openoffice/ridl -->
		<dependency>
		    <groupId>org.openoffice</groupId>
		    <artifactId>ridl</artifactId>
		    <version>4.1.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
		<dependency>
		    <groupId>org.slf4j</groupId>
		    <artifactId>slf4j-api</artifactId>
		    <version>1.7.25</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-jdk14 -->
		<dependency>
		    <groupId>org.slf4j</groupId>
		    <artifactId>slf4j-jdk14</artifactId>
		    <version>1.7.25</version>
		    <scope>test</scope>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.openoffice/unoil -->
		<dependency>
		    <groupId>org.openoffice</groupId>
		    <artifactId>unoil</artifactId>
		    <version>4.1.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream -->
		<dependency>
		    <groupId>com.thoughtworks.xstream</groupId>
		    <artifactId>xstream</artifactId>
		    <version>1.3.1</version>
		</dependency>
		<!-- 在线预览office文件 	end-->

注意jodconverter-2.2.1.jar版本不支持07版本以后的office文件,jodconverter-2.2.2.jar Maven仓库内没有,需要自己手动导入jar(将会在下面介绍如何导入)

前端页面所需要的JS

  • flexpaper_flash.js
  • flexpaper_flash_debug.js
  • jquery-1.8.3.min.js
    下载地址

jodconverter-2.2.2.jar下载

下载之后,解压开来的项目中就有jar包,直接复制出来即可
下载地址

也可以从我CSDN里面下载全部的插件以及手动导入的jar包
下载地址

后台代码实现

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.ConnectException;

import com.artofsolving.jodconverter.DocumentConverter;
import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.converter.OpenOfficeDocumentConverter;

/**
 * <p>
 * FileConverter.java 1、office文件转成PFD文件</dt> 2、PDF文件转成Swf文件</dt>
 * </p>
 * 
 * @since 2019年4月15日 上午11:13:36
 * @author XinLau
 * @version 1.0
 */
@SuppressWarnings("unused")
public class FileConverter {

	private static final int environment = 1;// 环境 1:Windows 2:Linux
	
	/**
	 * OpenOffice相关配置
	 */
	private static final String OpenOffice_HOME = "D:\\DevelopmentTools\\OpenOffice";
	private static final String host_Str = "127.0.0.1";
	private static final String port_Str = "8100";
	
	/**
	 * SWFTools相关配置
	 */
	private static final String SWFTools_HOME = "D:/DevelopmentTools/SWFTools";
	

	private String fileString;// (只涉及PDF2swf路径问题)
	private String outputPath = "";// 输入路径 ,如果不设置就输出在默认 的位置
	private String fileName;

	private File pdfFile;
	private File swfFile;
	private File docFile;

	public FileConverter(String fileString) {
		ini(fileString);
		System.out.println("文件路径" + fileString);
	}

	/**
	 * <p>
	 * setFile 重新设置file
	 * </p>
	 * 
	 * @param fileString
	 * @return void
	 * @author XinLau
	 * @since 2019年4月15日上午11:33:46
	 */
	public void setFile(String fileString) {
		ini(fileString);
	}

	/**
	 * <p>
	 * ini 初始化
	 * </p>
	 * 
	 * @param fileString
	 * @return void
	 * @author XinLau
	 * @since 2019年4月15日上午11:34:03
	 */
	private void ini(String fileString) {
		this.fileString = fileString;
		fileName = fileString.substring(0, fileString.lastIndexOf("."));
		docFile = new File(fileString);
		pdfFile = new File(fileName + ".pdf");
		swfFile = new File(fileName + ".swf");
	}

	/**
	 * <p>
	 * office2pdf 转为PDF
	 * </p>
	 * 
	 * @throws Exception
	 * @return void
	 * @author XinLau
	 * @since 2019年4月15日上午11:34:44
	 */
	private void office2pdf() throws Exception {
		if (docFile.exists()) {
			if (!pdfFile.exists()) {
				try {
					// 启动OpenOffice的服务
					String command = OpenOffice_HOME + "\\program\\soffice.exe -headless -accept=\"socket,host=" + host_Str
							+ ",port=" + port_Str + ";urp;\"-nofirststartwizard";
					System.out.println("###\n" + command);
					Process pro = Runtime.getRuntime().exec(command);
					// 连接openoffice服务
					OpenOfficeConnection connection = new SocketOpenOfficeConnection(host_Str, Integer.parseInt(port_Str));
					connection.connect();
					// 转换
					DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
					converter.convert(docFile, pdfFile);
					// 关闭连接和服务 close the connection
					connection.disconnect();
					pro.destroy();
					System.out.println("****pdf转换成功,PDF输出: " + pdfFile.getPath() + "****");
				} catch (java.net.ConnectException e) {
					e.printStackTrace();
					System.out.println("****swf转换器异常,openoffice 服务未启动!****");
					throw e;
				} catch (com.artofsolving.jodconverter.openoffice.connection.OpenOfficeException e) {
					e.printStackTrace();
					System.out.println("****swf转换器异常,读取转换文件 失败****");
					throw e;
				} catch (Exception e) {
					e.printStackTrace();
					throw e;
				}
			} else {
				System.out.println("****已经转换为pdf,不需要再进行转化 ****");
			}
		} else {
			System.out.println("****swf转换器异常,需要转换的文档不存在, 无法转换****");
		}
	}
	
	/**
	 * <p>
	 * pdf2swf 转换成 swf,删除pdf文件
	 * </p>
	 * 
	 * @throws Exception
	 * @return void
	 * @author XinLau
	 * @since 2019年4月15日上午11:35:31
	 */
	private void pdf2swf() throws Exception {
		Runtime r = Runtime.getRuntime();
		if (!swfFile.exists()) {
			if (pdfFile.exists()) {
				if (environment == 1) {// windows环境处理
					try {
						// 注意修改 SWFTools工具的安装路径
						String processArdess = SWFTools_HOME + "/pdf2swf.exe " + pdfFile.getPath() + " -o " + swfFile.getPath() + " -T 9";
						Long fileLength = pdfFile.length();
						//processArdess = processArdess + " -s poly2bitmap";
						Process p = r.exec(processArdess);
						System.out.print(loadStream(p.getInputStream()));
						System.err.print(loadStream(p.getErrorStream()));
						System.out.print(loadStream(p.getInputStream()));
						System.err.println("****swf转换成功,文件输出: " + swfFile.getPath() + "****");
						if (pdfFile.exists()) {
							pdfFile.delete();
						}
					} catch (IOException e) {
						e.printStackTrace();
						throw e;
					}
				} else if (environment == 2) {// linux环境处理
					try {
						Process p = r.exec("pdf2swf" + pdfFile.getPath() + " -o " + swfFile.getPath() + " -T 9");
						System.out.print(loadStream(p.getInputStream()));
						System.err.print(loadStream(p.getErrorStream()));
						System.err.println("****swf转换成功,文件输出: " + swfFile.getPath() + "****");
						if (pdfFile.exists()) {
							pdfFile.delete();
						}
					} catch (Exception e) {
						e.printStackTrace();
						throw e;
					}
				}
			} else {
				System.out.println("****pdf不存在,无法转换****");
			}
		} else {
			System.out.println("****swf已经存在不需要转换****");
		}
	}

	/**
	 * 
	 * <p>
	 * pdfConverterSwf pdf文件转成swf文件,保留pdf文件
	 * </p>
	 * 
	 * @throws Exception
	 * @return void
	 * @author XinLau
	 * @since 2019年4月16日上午9:14:34
	 */
	public void pdfConverterSwf() throws Exception {
		Runtime r = Runtime.getRuntime();
		if (!swfFile.exists()) {
			if (pdfFile.exists()) {
				if (environment == 1) {// windows环境处理
					try {
						// 注意修改 SWFTools工具的安装路径
						String processArdess = SWFTools_HOME + "/pdf2swf.exe " + pdfFile.getPath() + " -o " + swfFile.getPath() + " -T 9";
						Long fileLength = pdfFile.length();
						Process p = r.exec(processArdess);
						System.out.print(loadStream(p.getInputStream()));
						System.err.print(loadStream(p.getErrorStream()));
						System.out.print(loadStream(p.getInputStream()));
						System.err.println("****swf转换成功,文件输出: " + swfFile.getPath() + "****");
						/*
						 * if (pdfFile.exists()) { pdfFile.delete(); }
						 */
					} catch (IOException e) {
						e.printStackTrace();
						throw e;
					}
				} else if (environment == 2) {// linux环境处理
					try {
						Process p = r.exec("pdf2swf" + pdfFile.getPath() + " -o " + swfFile.getPath() + " -T 9");
						System.out.print(loadStream(p.getInputStream()));
						System.err.print(loadStream(p.getErrorStream()));
						System.err.println("****swf转换成功,文件输出: " + swfFile.getPath() + "****");
						/*
						 * if (pdfFile.exists()) { pdfFile.delete(); }
						 */
					} catch (Exception e) {
						e.printStackTrace();
						throw e;
					}
				}
			} else {
				System.out.println("****pdf不存在,无法转换****");
			}
		} else {
			System.out.println("****swf已经存在不需要转换****");
		}
	}

	static String loadStream(InputStream in) throws IOException {
		int ptr = 0;
		in = new BufferedInputStream(in);
		StringBuffer buffer = new StringBuffer();
		while ((ptr = in.read()) != -1) {
			buffer.append((char) ptr);
		}
		return buffer.toString();
	}

	/**
	 * <p>
	 * conver 转换主方法
	 * </p>
	 * 
	 * @return
	 * @return boolean
	 * @author XinLau
	 * @since 2019年4月15日上午11:36:32
	 */
	public boolean conver() {
		if (swfFile.exists()) {
			System.out.println("****swf转换器开始工作,该文件已经转换为 swf****");
			return true;
		}
		if (environment == 1) {
			System.out.println("****swf转换器开始工作,当前设置运行环境 windows****");
		} else {
			System.out.println("****swf转换器开始工作,当前设置运行环境 linux****");
		}
		try {
			office2pdf();
			pdf2swf();
			//pdfConverterSwf();
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		System.out.println("文件存在吗?" + swfFile);
		if (swfFile.exists()) {
			System.out.println("存在");
			return true;
		} else {
			System.out.println("不存在");
			return false;
		}
	}

	/**
	 * <p>
	 * getswfPath 返回文件路径
	 * </p>
	 * 
	 * @return String
	 * @author XinLau
	 * @since 2019年4月15日上午11:37:17
	 */
	public String getswfPath() {
		if (this.swfFile.exists()) {
			String tempString = swfFile.getPath();
			tempString = tempString.replaceAll("\\\\", "/");
			System.out.println("最后文件路径为" + tempString);
			return tempString;
		} else {
			return "文件不存在";
		}
	}

	/**
	 * <p>
	 * setOutputPath 设置输出路径
	 * </p>
	 * 
	 * @param outputPath
	 * @return void
	 * @author XinLau
	 * @since 2019年4月15日上午11:37:40
	 */
	public void setOutputPath(String outputPath) {
		this.outputPath = outputPath;
		if (!outputPath.equals("")) {
			String realName = fileName.substring(fileName.lastIndexOf("/"), fileName.lastIndexOf("."));
			if (outputPath.charAt(outputPath.length()) == '/') {
				swfFile = new File(outputPath + realName + ".swf");
			} else {
				swfFile = new File(outputPath + realName + ".swf");
			}
		}
	}

	public static void main(String[] args) {

		String fileName = "D:\\DevelopmentTools\\apache-tomcat-7.0.86\\webapps\\property-web\\upload\\doc\\d881c0f6bfcf458fb826502177e02123.docx";
		FileConverter fileConverter = new FileConverter(fileName);
		
		try { 
			//fileConverter.pdf2swf();
		} catch (Exception e) { 
			// TODO Auto-generated catch block 
			e.printStackTrace(); 
		}
		 
		
		try {
			/*fileConverter.office2pdf();
			String tempString = fileConverter.swfFile.getPath();
			tempString = tempString.replaceAll("\\\\", "/");
			System.out.println("最后文件路径为" + tempString);*/
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		

		boolean mark = fileConverter.conver();
		
		String path = fileConverter.getswfPath();
		System.out.println(path);

		path = path.substring(path.lastIndexOf("/property-web"));
		System.out.println(path);
		
	}

}

前端展示页面

<%@page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%
	String contextPath = request.getContextPath();
	String onlinePreviewLocation = request.getParameter("onlinePreviewLocation");
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>

	<head>
		<meta content="text/html;charset=UTF-8" http-equiv="Content-Type">
		<script type="text/javascript" src="<%=contextPath %>/lib/jquery-1.8.3.min.js"></script>
		<script type="text/javascript" src="<%=contextPath %>/js/util/flexpaper_flash.js"></script>
		<script type="text/javascript" src="<%=contextPath %>/js/util/flexpaper_flash_debug.js"></script>

		<style type="text/css" media="screen">
			html,
			body {
				height: 100%;
			}
			
			body {
				margin: 0;
				padding: 0;
				overflow: auto;
			}
			
			#flashContent {
				display: none;
			}
		</style>
		<title>在线文档预览</title>
	</head>

	<body>
		<!-- <div style="position: absolute; left: 50px; top: 10px;"> -->
		<div>
			<a id="viewerPlaceHolder" style="width: 100%; height: 100%; display: block;"></a>
			<script type="text/javascript">
				var afterUrl =  window.location.search.substring(1);//(问号以后的字符串)
				var afterEqual = afterUrl.substring(afterUrl.indexOf('=')+1);//.toUpperCase();//(等号以后的字符串,及你所要的参数)
				console.log(afterEqual);
				var host = window.location.host;
				var port = window.location.port;
				var onlinePreviewLocation = host + afterEqual
				console.log(onlinePreviewLocation);
				var fp = new FlexPaperViewer(
					'FlexPaperViewer',
					'viewerPlaceHolder', {
						config: {
							SwfFile: decodeURI('<%=onlinePreviewLocation%>'),
							Scale: 1.2,
							ZoomTransition: 'easeOut',
							ZoomTime: 0.5,
							ZoomInterval: 0.2,
							FitPageOnLoad: false,
							FitWidthOnload: false,
							FullScreenAsMaxWindow: true,
							ProgressiveLoading: false,
							MinZoomSize: 0.2,
							MaxZoomSize: 5,
							SearchMatchAll: false,
							InitViewMode: 'SinglePage',
							RenderingOrder: 'flash',
							ViewModeToolsVisible: true,
							ZoomToolsVisible: true,
							NavToolsVisible: true,
							CursorToolsVisible: true,
							SearchToolsVisible: true,
							localeChain: 'zh_CN'
						}
					});
			</script>
		</div>
	</body>

</html>
2020-03-19 16:29:41 weixin_43018505 阅读数 57
   需求描述:本次主要是对后端生成word的页眉的改造,之前是使用前端控件WebOffice生成的,这种生成方式,对于PC端的操作是没有什么问题,但是对于手机App端生成页眉就造成了影响,没办法通过前端控件去实现。所以必须要把整个word的生成,全部通过后端去实现,到时候App只需要实现调用后端代码就行。由于前期word的生成,是POI技术通过替换合同模板的占位符形式实现的,所以本次主要的改造点主要就是实现页眉的生成,但是页眉的生成还要考虑以下几点情况:

   1.合同文本的首页页眉与其它页页眉是不同的,首页页眉是展示条形码,条形码就是直接使用word里面的字体:C39HrP24DlTt实现的,其它页展示的是合同编号。

   2.页眉的生成还有3种情况,第一种是本身合同模板是有页眉的,且页眉是有内容的;第二种是合同模板是没有页眉的;第三种是合同模板加了页眉,但是页眉里面是没有值的,值为空。所以在生成页眉的时候,需要考虑这几种情况,处理的方式会有些许差别。

   好了,问题分析完了之后,进入正题:

首先需要强调一点的是,目前生成word页眉的POI版本貌似都是4.0之后的版本才行,4.0之前的版本我试了很多种方案都不行(我用的是4.1.1的版本,4.0.1也是OK的)。如果你的系统本来用的是4.0之前的版本,那么升级4.0之后,很多类对应的属性也会改变,尤其是生成EXCEL的很多属性,具体可以百度一下,改变前后的都有对照说明。

还要补充一点的是,如果你的pom.xml文件中有xbean这个依赖,一定要删除,否则会和4.0之后的POI依赖产生冲突。
我就卡在这个坑里,卡了很久,一直报: java.lang.NoClassDefFoundError: Could not initialize class org.apache.poi.ooxml.POIXMLTypeLoader的错,但是打开对应的类里面,明明是可以直接跳转过去,jar包里面明明是有POIXMLTypeLoader这个jar包的,最后才发现了是这个原因导致的。

    下面直接上代码:

public static void main(String[] args) throws Exception{
File is = new File(“D:\Desktop\oldWord.docx”);//文件路径
FileInputStream fis = new FileInputStream(is);
XWPFDocument doc = new XWPFDocument(fis);//文档对象

    //获取页眉,判断页眉是否为空
    List<XWPFHeader> pageHeaders = doc.getHeaderList();
    
    //若判断合同没有页眉时
    if(pageHeaders.isEmpty()) {
    //生成首页页眉
    XWPFParagraph paragraph=doc.createHeader(HeaderFooterType.FIRST).createParagraph();
    XWPFRun run =paragraph.createRun();
    paragraph.setAlignment(ParagraphAlignment.CENTER);
    run.setText("我是一个首页页眉");
    run.setFontFamily("C39HrP24DlTt");//设置页眉字体,这里是条形码字体
    
    //生成偶数页的页眉
    paragraph=doc.createHeader(HeaderFooterType.EVEN).createParagraph();
    run =paragraph.createRun();
    paragraph.setAlignment(ParagraphAlignment.LEFT);
    run.setText("我是与首页页眉不一样的其它页页眉");
    run.setFontSize(8);//设置页眉字体大小
    
    //生成奇数页的页眉
    paragraph=doc.createHeader(HeaderFooterType.DEFAULT).createParagraph();
    run =paragraph.createRun();
    paragraph.setAlignment(ParagraphAlignment.LEFT);
    run.setText("我是与首页页眉不一样的其它页页眉");//其它页页眉内容与首页不同,但奇数页和偶数页要单独设置成一样的内容

    Field filedSet = XWPFDocument.class.getDeclaredField("settings");
    filedSet.setAccessible(true);
    XWPFSettings xwpfsettings = (XWPFSettings)filedSet.get(doc);
    
    Field filedCtSet = XWPFSettings.class.getDeclaredField("ctSettings");
    filedCtSet.setAccessible(true);
    CTSettings ctSettings =(CTSettings)filedCtSet.get(xwpfsettings);
    ctSettings.addNewEvenAndOddHeaders();
    }else {
        //当合同文本有页眉时,内容不为空,将原内容进行替换
        for(XWPFHeader pageHeader : pageHeaders){
            List<XWPFParagraph> paragraphs = pageHeader.getParagraphs();
            for(XWPFParagraph paragraph : paragraphs){
                List<XWPFRun> runs = paragraph.getRuns();

                //合同有页眉,但是内容可能为空,对照上面第2 点
                if(!runs.isEmpty()) {
                for(int i=0;i<runs.size();i++){
                    XWPFRun run = runs.get(i);
                    run.setText("我是一个页眉,我要替换本来的页眉",0);
                    paragraph.setAlignment(ParagraphAlignment.RIGHT);//设置页眉左对齐
                }
                }else {
                  //生成首页页眉
                    XWPFParagraph paragraph2=doc.createHeader(HeaderFooterType.FIRST).createParagraph();
                    XWPFRun run =paragraph2.createRun();
                    paragraph2.setAlignment(ParagraphAlignment.CENTER);//设置页眉居中
                    run.setText("我是一个首页页眉");
                    run.setFontFamily("C39HrP24DlTt");
                    
                    //生成偶数页的页眉
                    paragraph2=doc.createHeader(HeaderFooterType.EVEN).createParagraph();
                    run =paragraph2.createRun();
                    paragraph2.setAlignment(ParagraphAlignment.LEFT);
                    run.setText("我是与首页页眉不一样的其它页页眉");
                    run.setFontSize(8);
                    
                    //生成奇数页的页眉
                    paragraph2=doc.createHeader(HeaderFooterType.DEFAULT).createParagraph();
                    run =paragraph2.createRun();
                    paragraph2.setAlignment(ParagraphAlignment.LEFT);
                    run.setText("我是与首页页眉不一样的其它页页眉");

                    Field filedSet = XWPFDocument.class.getDeclaredField("settings");
                    filedSet.setAccessible(true);
                    XWPFSettings xwpfsettings = (XWPFSettings)filedSet.get(doc);
                    
                    Field filedCtSet = XWPFSettings.class.getDeclaredField("ctSettings");
                    filedCtSet.setAccessible(true);
                    CTSettings ctSettings =(CTSettings)filedCtSet.get(xwpfsettings);
                    ctSettings.addNewEvenAndOddHeaders();
                     //此处一定要断开循环

                     break;                      

                     
                }
        }
    }
}
    doc.write(new FileOutputStream("D:\\Users\\newWord.docx"));
    doc.close();
    System.out.println("OK");
}

以上生成的逻辑说明:我们的情况是,如果合同没有页眉,则默认首页塞入条形码,其它页塞入合同编号;
若合同有页眉且有值的情况下,就全部页眉都塞入合同编号,不区分首页和其它页。