1 changed files with 141 additions and 0 deletions
@ -0,0 +1,141 @@
@@ -0,0 +1,141 @@
|
||||
|
||||
package apelet.tenantadmin.tenant.controller; |
||||
|
||||
import apelet.common.core.annotation.MyRequestBody; |
||||
import apelet.common.core.exception.MyRuntimeException; |
||||
import apelet.common.core.object.ObjectValue; |
||||
import apelet.common.generator.utils.OrmGenDataSourceUtil; |
||||
import cn.hutool.core.io.IoUtil; |
||||
import org.apache.poi.xwpf.usermodel.*; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.core.io.ClassPathResource; |
||||
import org.springframework.web.bind.annotation.*; |
||||
|
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.*; |
||||
import java.net.URLEncoder; |
||||
import java.nio.charset.StandardCharsets; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
import java.util.regex.Matcher; |
||||
import java.util.regex.Pattern; |
||||
|
||||
@RestController |
||||
@RequestMapping("/api/template") |
||||
public class DocxTemplateController { |
||||
|
||||
|
||||
@Autowired |
||||
private OrmGenDataSourceUtil ormGenDataSourceUtil; |
||||
|
||||
private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\$\\{(.+?)\\}"); |
||||
|
||||
/** |
||||
* 替换字符串中 ${key},JDK8兼容 |
||||
*/ |
||||
private String replaceContent(String text, Map<String, Object> dataMap) { |
||||
if (text == null) return ""; |
||||
Matcher matcher = PLACEHOLDER_PATTERN.matcher(text); |
||||
StringBuffer sb = new StringBuffer(); |
||||
while (matcher.find()) { |
||||
String key = matcher.group(1).trim(); |
||||
Object val = dataMap.get(key); |
||||
String realVal = val == null ? "" : val.toString(); |
||||
matcher.appendReplacement(sb, Matcher.quoteReplacement(realVal)); |
||||
} |
||||
matcher.appendTail(sb); |
||||
return sb.toString(); |
||||
} |
||||
|
||||
@GetMapping("/downloadDocx") |
||||
public void downloadDocx(@RequestParam("id") String quotationId, HttpServletResponse response) { |
||||
XWPFDocument document = null; |
||||
InputStream templateIs = null; |
||||
OutputStream out = null; |
||||
try { |
||||
// 1. 查数据
|
||||
ObjectValue objectValue = ormGenDataSourceUtil.queryOne("quotation", quotationId); |
||||
Map<String, Object> hashMap = new HashMap<>(); |
||||
hashMap.put("name", objectValue.getString("name")); |
||||
hashMap.put("number", objectValue.getString("number")); |
||||
hashMap.put("create_time", objectValue.getString("create_time")); |
||||
hashMap.put("qty", objectValue.getObjectValue("qty")); |
||||
ObjectValue managerperson = objectValue.getObjectValue("managerperson"); |
||||
if(managerperson != null){ |
||||
managerperson = ormGenDataSourceUtil.queryOne(managerperson.getTableName(), managerperson.getString("id")); |
||||
hashMap.put("managerperson",1); |
||||
} |
||||
// 2. 读模板
|
||||
File file = new File("D:\\work\\xykj-project\\xhgl\\zz-resource\\quotation_template.docx"); |
||||
templateIs = new FileInputStream(file); |
||||
document = new XWPFDocument(templateIs); |
||||
// 3. 替换占位符
|
||||
replaceParagraph(document, hashMap); |
||||
replaceTable(document, hashMap); |
||||
// 4. 设置响应头 —— 关键!
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); |
||||
response.setCharacterEncoding("UTF-8"); |
||||
String fileName = URLEncoder.encode("报价单.docx", StandardCharsets.UTF_8.name()) |
||||
.replaceAll("\\+", "%20"); |
||||
// 兼容各浏览器的文件名写法
|
||||
response.setHeader("Content-Disposition", |
||||
"attachment; filename=\"" + fileName + "\"; filename*=UTF-8''" + fileName); |
||||
response.setHeader("Pragma", "no-cache"); |
||||
response.setHeader("Cache-Control", "no-cache"); |
||||
response.setDateHeader("Expires", 0); |
||||
// 5. 写出
|
||||
out = response.getOutputStream(); |
||||
document.write(out); |
||||
out.flush(); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
throw new MyRuntimeException("导出失败: " + e.getMessage()); |
||||
} finally { |
||||
IoUtil.close(document); |
||||
IoUtil.close(templateIs); |
||||
IoUtil.close(out); |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
private void replaceParagraph(XWPFDocument document, Map<String, Object> dataMap) { |
||||
for (XWPFParagraph paragraph : document.getParagraphs()) { |
||||
String text = paragraph.getText(); |
||||
Matcher matcher = PLACEHOLDER_PATTERN.matcher(text); |
||||
if (!matcher.find()) { |
||||
continue; |
||||
} |
||||
//清空原有run
|
||||
for (XWPFRun run : paragraph.getRuns()) { |
||||
run.setText("", 0); |
||||
} |
||||
String newText = replaceContent(text, dataMap); |
||||
paragraph.createRun().setText(newText); |
||||
} |
||||
} |
||||
|
||||
private void replaceTable(XWPFDocument document, Map<String, Object> dataMap) { |
||||
for (XWPFTable table : document.getTables()) { |
||||
for (XWPFTableRow row : table.getRows()) { |
||||
for (XWPFTableCell cell : row.getTableCells()) { |
||||
for (XWPFParagraph paragraph : cell.getParagraphs()) { |
||||
String text = paragraph.getText(); |
||||
Matcher matcher = PLACEHOLDER_PATTERN.matcher(text); |
||||
if (!matcher.find()) { |
||||
continue; |
||||
} |
||||
for (XWPFRun run : paragraph.getRuns()) { |
||||
run.setText("", 0); |
||||
} |
||||
String newText = replaceContent(text, dataMap); |
||||
paragraph.createRun().setText(newText); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
} |
||||
Loading…
Reference in new issue