XWPFDocument document = null;document = new XWPFDocument(POIXMLDocument.openPackage(mdlepath));
这种方法读取docx文档,修改后另存为另一个文档
FileOutputStream outputStream = new FileOutputStream(tempPath);document.write(outputStream);outputStream.close();
然后这个文档就可以使用勒。是不是很简单,是不是很方便。但是,这个代码我是在网上找的,这个代码有个巨坑无比的地方。
我在操作一个word的时候,调用了一个copyTable方法。这个方法的作用就是复制某一个表格到指定位置。中间使用了一个document.setTable(pos,table)方法。这个方法有个巨坑的点,其中table是我需要复制的表格。再执行完这个代码之后,doc.getTable()这个函数的返回值正确,没有问题,逐行遍历表格也没有问题。但是在操作这个表格的时候发现了问题。使用逐行操作表格会无效。究其原因我猜测是因为引用问题。POI在操作table的时候并不能像List一样。new 一个对象就新分配一个空间。POI在操作很多东西的时候并不能新分配一个对象,而没有引用。所以就导致我的setTable方法传入参数的table,永远是同一个table。我是怎么知道的呢,是因为我每次把这个table的某一个单元格setText("i="+i)会发现复制的几个表格里,最后一个表格输出了很多个i=.......在逐个遍历表格赋值的时候,会造成每次修改的表格都是同一个。并不能修改到复制出来的表格。解决办法就是必须把这个文件另存为,再打开。这是背景。
那么我就需要调用两次上面的代码。而且第二次调用的docx文件是第一次的输出文件。
这个东西我是要挂载在服务器上的,我肯定是要删除掉的。那么坑就来了。
我第一次生成的文件叫temp1,第二次生成的文件叫temp2.
我执行这一段代码:
out1.getFD().valid();out2.getFD().valid();
输出结果为false和false。然后我删除文件。输出删除结果,均为true。然后我打开文件夹,发现temp
,删除了temp2没删除。我心态崩掉了。然后我file(temp1).exists();发现结果为false。就是说我删除成功而且检查删除后文件已经不存在了。然后我debug,发现删除那句话并没有执行,却返回true。没删除掉exists却返回false。然后我怀疑是文件占用或者是别的原因,我就怀疑是这个封装方法出了问题。
解决办法:
try (FileInputStream argIS = new FileInputStream(mdlepath);XWPFDocument document = new XWPFDocument(argIS)){//这里面的代码就是操作整个document的具体操作了。//不需要关闭 FileInputStream 会自动关闭}
我换了一种方法读取docx文件,而且写在try()中间.就不会出现占用或者流未关闭的问题了。
解决办法是看的官方例程http://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/xwpf/usermodel/examples/
public static void copyTable(XWPFDocument doc, Integer mdlIndex, Integer startPos, Integer copysiz, List<String> titlelist,XWPFParagraph sourse) throws Exception { if (mdlIndex == null || mdlIndex >= doc.getTables().size() || mdlIndex < 0) { return; } XWPFTable table = doc.getTables().get(mdlIndex); // Copying a existing table CTTbl ctTbl = CTTbl.Factory.newInstance(); // Create a new CTTbl for the new table ctTbl.set(table.getCTTbl()); // Copy the template table's CTTbl // Create a new table using the CTTbl upon.0 XWPFTable table2 = new XWPFTable(ctTbl, doc);//这个table2是个引用类型,放到循环里也不会改变他引用的对象是他的模板table,这是个坑; for (int i = 0; i < copysiz; i++) { //创建表之前先创建头 XWPFParagraph paragraph = doc.createParagraph(); paragraph.getCTP().setPPr(sourse.getCTP().getPPr());// paragraph.setPageBreak(true);// paragraph.setAlignment(ParagraphAlignment.CENTER); XWPFRun xwpfRun = paragraph.createRun(); xwpfRun.setFontSize(18);//设置字体大小 xwpfRun.setBold(true); xwpfRun.setText("表-" + titlelist.get(i+1)); paragraph.setPageBreak(true);//分页符 //创建表并且修改表 doc.createTable(); // Create a empty table in the document // 这里有一个坑,必须重新打开该文件这个这个替换掉的table才能修改。不然改不了。或者在创建table2的时候就把数据加上 doc.setTable(doc.getTables().size() - 1, table2); } }
这个例程有两个坑爹的地方:
1.图表不能设置的东西很多。比如:我想生成这样的图表:
我不能设置没有表头,官方有个类似的方法没有用。不生效。我想设置是否标出数据大小,比如2,7,11,5啥的,没有。我想设置样式,也没有。
解决办法,,我创建模板压,创建完之后修改数据就完事了。把表头设置为空字符串,看起来就和没有差不多。
List<XWPFChart> chartList = document.getCharts();XWPFChart chart = chartList.get(0);String[] categories = (String[]) barChartMap.get("categories");Integer[] value = (Integer[]) barChartMap.get("value");setBarData(chart, categories, value); private static void setBarData(XWPFChart chart, String[] categories, Integer[] values1) { final List<XDDFChartData> data = chart.getChartSeries(); final XDDFBarChartData bar = (XDDFBarChartData) data.get(0); final int numOfPoints = categories.length; final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0)); final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1)); final String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, 2, 2)); final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0); final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange, 1); XDDFChartData.Series series1 = bar.getSeries().get(0); series1.replaceData(categoriesData, valuesData); series1.setTitle("123", chart.setSheetTitle("123", 0)); bar.setBarDirection(BarDirection.COL); chart.plot(bar); solidFillSeries(bar, 0, PresetColor.GRAY); chart.setTitleText(""); // https://stackoverflow.com/questions/30532612 chart.setAutoTitleDeleted(true); chart.setTitleOverlay(false); //改变颜色 } private static void solidFillSeries(XDDFChartData data, int index, PresetColor color) { //改变柱状图的第index的颜色 XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color)); XDDFChartData.Series series = data.getSeries().get(index); XDDFShapeProperties properties = series.getShapeProperties(); if (properties == null) { properties = new XDDFShapeProperties(); } properties.setFillProperties(fill); series.setShapeProperties(properties); }
类似√×这样的特殊字符。有的甚至要输出一些奇奇怪怪的东西。
思路有两个:
1.直接在java里打出来,然后添加到word里面
2.在word里生成特殊字符。
方法1,我试过是可以的。
方法2 这里附上解决办法和思路:poi插入word 2007 Wingdings字符。可行,可能以后会出现版本问题。那篇帖子挺老的了。
还有一点心得:如果你的POI版本比较新,比如说我使用的是POI 4.1.0版本的,百度上面差到的资料是很少的,而且百度辣鸡,用谷歌能查到一些,最好的地方是去官方文档里去寻找答案。或者到国外的开发者论坛:https://stackoverflow.com/经常是可以搜到的。
下面是一些用到的代码:
/** * 替换段落文本 * * @param document docx解析对象 * @param textMap 需要替换的信息集合 */ public static void changeText(XWPFDocument document, Map<String, Object> textMap) { //获取段落集合 List<XWPFParagraph> paragraphs = document.getParagraphs(); for (XWPFParagraph paragraph : paragraphs) { //判断此段落时候需要进行替换 String text = paragraph.getText(); if (checkText(text)) { List<XWPFRun> runs = paragraph.getRuns(); for (XWPFRun run : runs) { //替换模板原来位置 Object ob = changeValue(run.toString(), textMap); //System.out.println("段落:" + run.toString()); if (ob instanceof String) { if(textMap.containsKey(run.toString())){ run.setText((String) ob, 0); } } } } } } public static void changePic(XWPFDocument document, Map<String, Object> textMap) throws Exception{ //获取段落集合 List<XWPFParagraph> paragraphs = document.getParagraphs(); for (XWPFParagraph paragraph : paragraphs) { //判断此段落时候需要进行替换 String text = paragraph.getText(); if (checkText(text)) { List<XWPFRun> runs = paragraph.getRuns(); for (XWPFRun run : runs) { //替换模板原来位置 Object ob = changeValue(run.toString(), textMap); //System.out.println("段落:" + run.toString()); if (ob instanceof String) { if(textMap.containsKey(run.toString())){ run.setText("", 0); try(FileInputStream is=new FileInputStream((String)ob)){ run.addPicture(is,XWPFDocument.PICTURE_TYPE_PNG,(String)ob, Units.toEMU(50),Units.toEMU(50)); } } } } } } } public static boolean checkText(String text) { boolean check = false; if (text.indexOf("$") != -1) { check = true; } return check; } public static void changeTableText(XWPFDocument document, Map<String, Object> data) { List<XWPFTable> tableList = document.getTables(); //循环所有需要进行替换的文本,进行替换 for (int i = 0; i < tableList.size(); i++) { XWPFTable table = tableList.get(i); if (checkText(table.getText())) { List<XWPFTableRow> rows = table.getRows(); System.out.println("简单表格替换:" + rows); //遍历表格,并替换模板 eachTable(document, rows, data); } } } public static void changeTablePic(XWPFDocument document, Map<String, Object> pic) throws Exception{ List<XWPFTable> tableList = document.getTables(); //循环所有需要进行替换的文本,进行替换 for (int i = 0; i < tableList.size(); i++) { XWPFTable table = tableList.get(i); if (checkText(table.getText())) { List<XWPFTableRow> rows = table.getRows(); System.out.println("简单表格替换:" + rows); //遍历表格,并替换模板 eachTablePic(document, rows, pic); } } } public static void eachTablePic(XWPFDocument document, List<XWPFTableRow> rows, Map<String, Object> pic) throws Exception{ for (XWPFTableRow row : rows) { List<XWPFTableCell> cells = row.getTableCells(); for (XWPFTableCell cell : cells) { //判断单元格是否需要替换 if (checkText(cell.getText())) { //System.out.println("cell:" + cell.getText()); List<XWPFParagraph> paragraphs = cell.getParagraphs(); for (XWPFParagraph paragraph : paragraphs) { List<XWPFRun> runs = paragraph.getRuns(); for (XWPFRun run : runs) { Object ob = changeValue(run.toString(), pic); if (ob instanceof String) { System.out.println("run:"+"'"+run.toString()+"'"); if(pic.containsKey(run.toString())){ System.out.println("run:"+run.toString()+"替换为"+(String)ob); run.setText("", 0); try(FileInputStream is=new FileInputStream((String)ob)){ run.addPicture(is,XWPFDocument.PICTURE_TYPE_PNG,(String)ob,Units.toEMU(50),Units.toEMU(100)); } } else{ System.out.println("'"+run.toString()+"'不匹配"); } } } } } } } } public static Object changeValue(String value, Map<String, Object> textMap) { Set<Map.Entry<String, Object>> textSets = textMap.entrySet(); Object valu = ""; for (Map.Entry<String, Object> textSet : textSets) { //匹配模板与替换值 格式${key} String key = textSet.getKey(); if (value.indexOf(key) != -1) { valu = textSet.getValue(); } } return valu; } public static void eachTable(XWPFDocument document, List<XWPFTableRow> rows, Map<String, Object> textMap) { for (XWPFTableRow row : rows) { List<XWPFTableCell> cells = row.getTableCells(); for (XWPFTableCell cell : cells) { //判断单元格是否需要替换 if (checkText(cell.getText())) { //System.out.println("cell:" + cell.getText()); List<XWPFParagraph> paragraphs = cell.getParagraphs(); for (XWPFParagraph paragraph : paragraphs) { List<XWPFRun> runs = paragraph.getRuns(); for (XWPFRun run : runs) { Object ob = changeValue(run.toString(), textMap); if (ob instanceof String) { System.out.println("run:"+"'"+run.toString()+"'"); if(textMap.containsKey(run.toString())){ System.out.println("run:"+run.toString()+"替换为"+(String)ob); run.setText((String) ob, 0); } else{ System.out.println("'"+run.toString()+"'不匹配"); } } } } } } } } public static void insertTable(XWPFTable table, List<String> tableList, List<String[]> daList, Integer type) { if (2 == type) { //创建行和创建需要的列 for (int i = 0; i < daList.size() - 1; i++) { //添加一个新行// XWPFTableRow row = table.insertNewTableRow(1 + i); XWPFTableRow row = table.getRow(1); copy(table, row, i + 1);// for (int k = 0; k < daList.get(i).length; k++) {// row.createCell();// } } System.out.println("插入表格数据"); //创建行,根据需要插入的数据添加新行,不处理表头 for (int i = 0; i < daList.size(); i++) { List<XWPFTableCell> cells = table.getRow(i + 1).getTableCells(); for (int j = 0; j < cells.size(); j++) { XWPFTableCell cell02 = cells.get(j); cell02.setText(daList.get(i)[j]); } } } else if (4 == type) { //插入表头下面第一行的数据 for (int i = 0; i < tableList.size(); i++) { XWPFTableRow row = table.createRow(); List<XWPFTableCell> cells = row.getTableCells(); cells.get(0).setText(tableList.get(i)); } } } /** * 复制两行 * * @param table * @param sourceRow * @param rowIndex */ public static void copy(XWPFTable table, XWPFTableRow sourceRow, int rowIndex) { //在表格指定位置新增一行 XWPFTableRow targetRow = table.insertNewTableRow(rowIndex); //复制行属性 targetRow.getCtRow().setTrPr(sourceRow.getCtRow().getTrPr()); List<XWPFTableCell> cellList = sourceRow.getTableCells(); if (null == cellList) { return; } //复制列及其属性和内容 XWPFTableCell targetCell = null; for (XWPFTableCell sourceCell : cellList) { targetCell = targetRow.addNewTableCell(); //列属性 targetCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr()); //段落属性 if (sourceCell.getParagraphs() != null && sourceCell.getParagraphs().size() > 0) { targetCell.getParagraphs().get(0).getCTP().setPPr(sourceCell.getParagraphs().get(0).getCTP().getPPr()); if (sourceCell.getParagraphs().get(0).getRuns() != null && sourceCell.getParagraphs().get(0).getRuns().size() > 0) { XWPFRun cellR = targetCell.getParagraphs().get(0).createRun(); cellR.setText(sourceCell.getText()); cellR.setBold(sourceCell.getParagraphs().get(0).getRuns().get(0).isBold()); } else { targetCell.setText(sourceCell.getText()); } } else { targetCell.setText(sourceCell.getText()); } } } /** * 合并行 * @param table * @param col * @param fromRow * @param toRow */ public static void mergeCellVertically(XWPFTable table, int col, int fromRow, int toRow) { for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) { CTVMerge vmerge = CTVMerge.Factory.newInstance(); if (rowIndex == fromRow) { vmerge.setVal(STMerge.RESTART); } else { vmerge.setVal(STMerge.CONTINUE); } XWPFTableCell cell = table.getRow(rowIndex).getCell(col); CTTcPr tcPr = cell.getCTTc().getTcPr(); if (tcPr != null) { tcPr.setVMerge(vmerge); } else { tcPr = CTTcPr.Factory.newInstance(); tcPr.setVMerge(vmerge); cell.getCTTc().setTcPr(tcPr); } } } /** * 合并列 * * @param table * @param row * @param fromCell * @param toCell */ public void mergeCellsHorizontal(XWPFTable table, int row, int fromCell, int toCell) { for (int cellIndex = fromCell; cellIndex <= toCell; cellIndex++) { XWPFTableCell cell = table.getRow(row).getCell(cellIndex); if (cellIndex == fromCell) { // The first merged cell is set with RESTART merge value cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART); //cellCount为表格总列数 int cellCount = table.getRow(row).getTableCells().size(); Integer width = (toCell - fromCell + 1) / cellCount * table.getCTTbl().getTblPr().getTblW().getW().intValue(); cell.getCTTc().getTcPr().addNewTcW().setW(BigInteger.valueOf(width)); } else { // Cells which join (merge) the first one, are set with CONTINUE cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE); } } }
原网址: 访问
创建于: 2023-05-06 18:23:24
目录: default
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
最新评论