返回目录:word文档
各位朋友大家好,好久没跟各位见面了。因为最近刚刚入职了一家新公司,上班第一天技术经理就给分配了一个小任务:既不是加入一个团队,也不是提前熟悉即将开始的新项目,而是让我写一个小程序。
这个小程序听起来很简单,就是将数据库中部分字段的内容填写到WORD模板中,而需要填写的内容就是写入乙方的信息,如图:
文档整体是一个合同格式
其实这个小程序主要考验JAVA的基础知识(当然这也是程序做完之后才有了这个感觉),比如说数据库连接工具,集合等等,最重要的是如何将获取到的内容添加到相应的位置。一开始接到这项任务我以为会在很短的时间搞定它,因为经理没有说什么时候交项目,只能是越快越好了。在准备阶段我接收了同事发给我的sql数据,启用了公司的数据库,同时给电脑安装了软件(因为是重装的系统),我配置的是JDK1.8,eclipse用的官网最新版(地址:https://www.eclipse.org/downloads/,版本Eclipse IDE 201809
),选择使用哪种方式来制作这个小程序。最开始我是想做的完美一些,成为一个真正的程序,以后随时都能用,所以提前考虑了一下到底用哪种方式来写,当时心里有好多备选答案,灵感有很多,确实很纠结。可是当下手开始敲代码的时候,却没了底,验证了好多方法都行不通,觉得有些失望了,经理看我很纠结,就说基本能用就行,不需要太高大上。所以,我就用了最简单的办法来解决这个问题,如下所示:
DBUtil连接数据库:
/**
* 数据库连接工具
* @author Administrator
*
*/
public class DBConn {
// 路径
private String db;
// 账户
private String username;
// 密码
private String password;
public DBConn (String db,String username,String password) {
this.db=db;
this.username=username;
this.password=password;
}
public String getDb() {
return db;
}
public void setDb(String db) {
this.db = db;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
// 获取数据库连接
public Connection getConnection() {
Connection conn=null;
try {
// 加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("数据库驱动异常");
return null;
}
String url="jdbc:mysql:数据库路径"+this.db+"?&useUnicode=true"
+"&characterEncoding=UTF-8&useSSL=false";
try {
// 连接mysal数据库
conn=DriverManager.getConnection(url, this.username, this.password);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("连接数据库异常");
return null;
}
System.out.println("连接数据库成功");
return conn;
}
// 关闭数据库
public void closeConn(Connection conn) {
if (conn!=null) {
try {
conn.close();
System.out.println("关闭数据库连接");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public List
Connection conn=getConnection();
PreparedStatement ps=null;
ResultSet rs=null;
List
try {
ps=conn.prepareStatement(sql);
if(obj!=null) {
for(int i=0;i ps.setObject(i+1, obj[i]); } } rs=ps.executeQuery(); ResultSetMetaData rsmd=rs.getMetaData(); while(rs.next()) { Map for(int i = 0;i String columName=rsmd.getColumnName(i+1); String columValue=rs.getString(i+1); map.put(columName, columValue); } list.add(map); } } catch (SQLException e) { e.printStackTrace(); }finally { isClose(ps,conn,rs); } return list; } private void isClose(PreparedStatement ps, Connection conn, ResultSet rs) { try { if (ps!=null) { ps.close(); } if (conn!=null) { conn.close(); } if (rs!=null) { rs.close(); } } catch (Exception e) { } } public static void main(String[] args) { DBConn dbc=new DBConn("数据库名称", "账户", "密码""); Connection conn=dbc.getConnection(); dbc.closeConn(conn); } } DAO层: 主要是将从数据获得的内容赋值到word模板中(.docx格式) public class UsrDao { // 取出数据库中的内容 public List // 获取数据库连接 DBConn dbc=new DBConn("数据库名称", "登录名", "密码"); Connection conn=dbc.getConnection(); // 判断连接 if(conn==null) { System.out.println("数据库连接出错"); return null; } String sql="select cust_name,rsrv_str3,juristic,email,cell_phone,company_address,registration_time from company where cust_id=?"; Object[]obj= {cust_id}; PreparedStatement pStatement=null; ResultSet rs=null; List try { // 预编译处理sql语句 pStatement=conn.prepareStatement(sql); if(obj!=null) { for(int i=0;i pStatement.setObject(i+1, obj[i]); } } rs=pStatement.executeQuery(); ResultSetMetaData rsmd=rs.getMetaData(); Map List UsrBean usr=new UsrBean(); while(rs.next()) { for(int i=0;i String columName=rsmd.getColumnName(i+1); String columValue=rs.getString(i+1); map.put(columName, columValue); } maps.add(map); // 赋值 usr.setCust_name(maps.get(0).get("CUST_NAME")); usr.setRsrv_str3(maps.get(0).get("RSRV_STR3")); usr.setJuristic(maps.get(0).get("JURISTIC")); usr.setEmail(maps.get(0).get("EMAIL")); usr.setCell_phone(maps.get(0).get("CELL_PHONE")); usr.setCompany_address(maps.get(0).get("COMPANY_ADDRESS")); usr.setRegistration_time(maps.get(0).get("REGISTRATION_TIME")); // 将变量存入数组中 lists.add(usr); } } catch (Exception e) { e.printStackTrace(); System.out.println("SQL语句有误,数据库无法查询"); //return null; } finally { dbc.closeConn(conn); } return lists; } // 内部测试 public static void main(String[] args) { UsrDao usrDao=new UsrDao(); System.out.println(usrDao.getAllUsrs(6348).get(0).getRegistration_time()); } } public class GetId { /** * 找到数据库中所有的id * 得出的结果是集合 * @return */ public List // 获取数据库连接 DBConn dbc=new DBConn("数据库名称", "账户", "密码"); Connection conn=dbc.getConnection(); List // 判断连接 if(conn==null) { System.out.println("数据库连接出错"); return null; } // 查询公司名称除了"______"的sql语句 String sql="需要的SQL语句"; Map List // 预编译语句 try { PreparedStatement ps=conn.prepareStatement(sql); ResultSet rs=ps.executeQuery(); ResultSetMetaData rsmd=rs.getMetaData(); UsrBean usr=new UsrBean(); while(rs.next()) { for(int i=0;i String columName=rsmd.getColumnName(i+1); String columValue=rs.getString(i+1); map.put(columName, columValue); } int cid = Integer.parseInt(map.get("大写的字段名")); // 赋值 lists.add(cid); } } catch (SQLException e) { e.printStackTrace(); System.out.println("SQL语句有误,数据库无法查询"); //return null; } finally { dbc.closeConn(conn); } return lists; } public static void main(String[] args) { GetId gd=new GetId(); for (Integer usr : gd.getAllId()) { System.out.println(usr); } } } *非常重要的地方 段落的设置,获取文档,操作赋值,完成工作。当然这是网上的大神分享的,很专业很实用。链接写在文章下方,想要具体了解的朋友可以点击查看。 /** * 替换段落里面的变量 * * @param doc * 要替换的文档 * @param params * 参数 */ private void replaceInPara(XWPFDocument doc, Map Iterator XWPFParagraph para; while (iterator.hasNext()) { para = iterator.next(); this.replaceInPara(para, params); } } /** * 替换段落里面的变量 * * @param para * 要替换的段落 * @param params * 参数 */ private void replaceInPara(XWPFParagraph para, Map List Matcher matcher; if (this.matcher(para.getParagraphText()).find()) { runs = para.getRuns(); for (int i = 0; i < runs.size(); i++) { XWPFRun run = runs.get(i); String runText = run.toString(); matcher = this.matcher(runText); if (matcher.find()) { while ((matcher = this.matcher(runText)).find()) { runText = matcher.replaceFirst(String.valueOf(params.get(matcher.group(1)))); } // 直接调用XWPFRun的setText()方法设置文本时,在底层会重新创建一个XWPFRun,把文本附加在当前文本后面, // 所以我们不能直接设值,需要先删除当前run,然后再自己手动插入一个新的run。 para.removeRun(i); if(runText.equals("null")){ runText=""; } para.insertNewRun(i).setText(runText); } } } } /** * 替换表格里面的变量 * * @param doc * 要替换的文档 * @param params * 参数 */ private void replaceInTable(XWPFDocument doc, Map Iterator XWPFTable table; List List List while (iterator.hasNext()) { table = iterator.next(); rows = table.getRows(); for (XWPFTableRow row : rows) { cells = row.getTableCells(); for (XWPFTableCell cell : cells) { String cellTextString = cell.getText(); for (Entry if (cellTextString.contains("${"+e.getKey()+"}")) cellTextString = cellTextString.replace("${"+e.getKey()+"}", e.getValue().toString()); } cell.removeParagraph(0); if(cellTextString.contains("${") && cellTextString.contains("}")){ cellTextString = ""; } cell.setText(cellTextString); // paras = cell.getParagraphs(); // for (XWPFParagraph para : paras) { // this.replaceInPara(para, params); // } } } } } /** * 正则匹配字符串 * * @param str * @return */ private Matcher matcher(String str) { Pattern pattern = Pattern.compile("${(.+?)}", Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(str); return matcher; } /** * 关闭输入流 * * @param is */ private void close(InputStream is) { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 关闭输出流 * * @param os */ private void close(OutputStream os) { if (os != null) { try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 输出CoreProperties信息 * * @param coreProps */ private void printCoreProperties(CoreProperties coreProps) { // System.out.println(coreProps.getCategory()); // 分类 // System.out.println(coreProps.getCreator()); // 创建者 // System.out.println(coreProps.getCreated()); // 创建时间 // System.out.println(coreProps.getTitle()); // 标题 } /** * word占位用${object}有缺陷不能填充图片 * @param filePath * @param params * @throws Exception */ public static String templateWrite(String filePath, Map InputStream is = new FileInputStream(filePath); WriteWordUtil writeWordUtil = new WriteWordUtil(); XWPFDocument doc = new XWPFDocument(is); // 替换段落里面的变量 writeWordUtil.replaceInPara(doc, params); // 替换表格里面的变量 writeWordUtil.replaceInTable(doc, params); OutputStream os = new FileOutputStream(outFilePath); doc.write(os); writeWordUtil.close(os); writeWordUtil.close(is); os.flush(); os.close(); return ""; } /** * 使用方法将内容填充 * @param args * @throws Exception */ public static void main(String[] args) throws Exception{ // 从数据库获取数据 GetId getId=new GetId(); List for (Integer int1 : allId) { List if(usrs==null) { System.out.println("数据库获取失败"); return; } // 将数据具体信息展示 String name= usrs.get(0).getCust_name(); String num=usrs.get(0).getRsrv_str3(); String user=usrs.get(0).getJuristic(); String email=usrs.get(0).getEmail(); String phone=usrs.get(0).getCell_phone(); // 注册时间 String time=usrs.get(0).getRegistration_time(); String address=usrs.get(0).getCompany_address(); Map } 上述模板生成器转载至:https://blog.csdn.net/chen497147884/article/details/79678513 需要生成的WORD模板里需要修改的内容: 文档模板中需要插入字段的地方 我所使用的是最新版本的WPS2019 打开文档模板所需的软件 挺好用的,很方便。 更重要的差点忘了,那就是写程序必备的jar包,强烈推荐的是POI3.1.7版本, jar包 别用最新的版本,实测4.0.1的没法用。下载地址:http://www.33lc.com/soft/75246.html。因为CSDN上边的需要花费积分,所以我等新手就地取材就好! 这是我第一次写关于工作上的成果,还是希望大家多多支持,非常感谢。业界大神可与在下互相关注,提携后辈温故知新!