java使⽤freemarker导出word(xlsx格式,含图表)
使⽤java程序导出word,此次使⽤的是模板值替换⽅式,⽽导出的word版本是xlsx。
直接替换⽂本和图⽚,可以直接使⽤⼀个word改造的ftl模板,替换启⽤的参数即可,但是对于图表就⽐较⿇烦。
也参照了很多⼤佬的做法,针对xlsx07版本,主要是将xlsx⽂件解压,得到很多xml⽂件,其中⽂字内容是在l中,如果要替换⽂本内容,将xml中参数使⽤freemarker替换即可。
如果是图⽚,则按照图⽚的先后顺序,保存在word/media/下,以image1.png这个格式开头,则在最后写⼊压缩包时替换相应的图⽚。
图表也就和⽂本l的⽅式⼀样,word中的每个图表都会有⼀个chart[1].xml⽂件,将这个xml中的参数使⽤freemarker替换。
下⾯就是⼀个导出word,含图表的⼯具类,供参考
其中的⼏个DTO就是关于模板⽂件名称和参数。
public class WordWriter {
public static void write(String outFileName, WordTemplate wordTemplate, boolean zip, HttpServletResponse httpServletResponse){
//获取临时⽂件存放路径
outFileName = getWordFileName(outFileName);
File file = ateFile(outFileName);
//创建xml临时存放⽂件夹
Path parent = Path().getParent();
File xmlDir = (String(), lDirName).toFile();
if(!ists()){
boolean mkdir = xmlDir.mkdir();
log.debug("创建xml临时存放⽂件夹{}", mkdir);
}
//创建l
WordXmlTemplateDTO documentDTO = DocumentDTO();
Path documentXmlOutPath = appendXmlPath(xmlDir, "l");
FreemarkerUtils.XmlName(), DataList(), String());
//替换l
List<WordXmlTemplateDTO> chartDTOList = ChartDTOList();
List<Path> chartXmlPaths = new ArrayList<>();
if(!CollectionUtils.isEmpty(chartDTOList)){
int i = 1;
for (WordXmlTemplateDTO chartDTO : chartDTOList) {
Path chartXmlOutPath = appendXmlPath(xmlDir, "chart" + i++ + ".xml");
FreemarkerUtils.XmlName(), DataList(), String());
chartXmlPaths.add(chartXmlOutPath);
}
}
java xml是什么//写⼊
Path templatePath = TemplatePath();
Path originDocPath = (String(), OriginDocName());
Path outDocPath = (Path(), outFileName);
replaceDocXml(documentXmlOutPath, WordImageDTO(), chartXmlPaths, originDocPath, outDocPath);
Path zipPath = null;
if(zip){
zipPath = FileUtil.File()), outFileName);
}
if(httpServletResponse != null){
try (OutputStream outputStream = OutputStream();){
if(zipPath != null){
httpServletResponse.setHeader("Content-Disposition",
"attachment;filename=" + File().getName(), "utf-8"));
httpServletResponse.setHeader("Content-Type", "application/octet-stream");
}else {
httpServletResponse.setHeader("Content-Disposition",
"attachment;filename=" + File().getName(), "utf-8"));
httpServletResponse.setHeader("Content-Type", "application/msword");
}
} catch (Exception e) {
<("导出⽂件失败" + outDocPath, e);
}
}else {
<("web导出Word,httpResponse为空");
}
log.String());
FileUtil.Path().getParent());
}
private static void replaceDocXml(Path documentXmlOutPath, List<WordImageDTO> wordImageDTOList, List<Path> chartXmlPaths, Path originDocPath, Path
int len;
byte[] buffer=new byte[1024];
try (ZipOutputStream zipout = new ZipOutputStream(new File()))){
ZipFile zipFile = new File());
Enumeration<? extends ZipEntry> zipEntrys = ies();
while(zipEntrys.hasMoreElements()) {
ZipEntry next = Element();
String name = String();
zipout.putNextEntry(new ZipEntry(name));
int chartIndex;
if ("l".equals(name)) {
try (InputStream in = new File())){
while ((len = in.read(buffer)) != -1) {
zipout.write(buffer, 0, len);
}
}
} else if (!CollectionUtils.isEmpty(wordImageDTOList)
&& name.startsWith("word/media/")
&& getImageIndex(name) > 0) {
int lastIndexOf = name.lastIndexOf("/");
String imageName = name.substring(lastIndexOf + 1);
boolean flag = false;
for (WordImageDTO wordImageDTO : wordImageDTOList) {
byte[] bytes = Bytes();
String docxImageName = DocxImageName();
if(imageName.equalsIgnoreCase(docxImageName)){
zipout.write(bytes);
flag = true;
break;
}
}
if(!flag){
if(!flag){
originWrite(buffer, zipout, zipFile, next);
}
}else if(!CollectionUtils.isEmpty(chartXmlPaths)
&& name.startsWith("word/charts/")
&& (chartIndex = getChartIndex(name)) > 0
&& chartXmlPaths.size() >= chartIndex){
Path path = (chartIndex - 1);
try (InputStream in = new File())){
while ((len = in.read(buffer)) != -1) {
zipout.write(buffer, 0, len);
}
}
}else {
originWrite(buffer, zipout, zipFile, next);
}
zipout.flush();
}
} catch (Exception e) {
<("写⼊docx异常", e);
}
}
private static void originWrite(byte[] buffer, ZipOutputStream zipout, ZipFile zipFile, ZipEntry next) throws IOException { int len;
try (InputStream is = InputStream(next)){
while((len = is.read(buffer))!=-1){
zipout.write(buffer,0,len);
}
}
}
/**
* docx解压包中,图⽚名称是按照image[1-9].[png|...]规律命名的
*/
private static int getImageIndex(String name){
int index = -1;
String reg = ".*image([0-9]+)\\.\\w+$";
Pattern pattern = Patternpile(reg);
Matcher matcher = pattern.matcher(name);
if (matcher.find()) {
index = Integer.up(1));
}
return index;
}
/**
* docx解压包中,图表xml⽂件是按照chart[1-9].xml规律命名的
*/
private static int getChartIndex(String name){
int index = -1;
String reg = ".*chart([0-9]+).xml$";
Pattern pattern =Patternpile(reg);
Matcher matcher = pattern.matcher(name);
if (matcher.find()) {
index = Integer.up(1));
}
return index;
}
private static Path appendXmlPath(File xmlDir, String fileName){
if(!dsWith(".xml")){
if(!dsWith(".xml")){
fileName = fileName + ".xml";
}
(Path().toString(), fileName);
}
private static String getWordFileName(String fileName){
Assert.isTrue(fileName != null && im().length() > 0, "导出⽂件名称不能为空"); if(!dsWith(Suffix())){
fileName = fileName + Suffix();
}
return fileName;
}
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论