如何使用java填写Excel文件

我有以下代码来填写Excel文件,使用Jsoup从Internet获得的信息。

package knvbj; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.List; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.nodes.TextNode; import org.jsoup.select.Elements; public class KNVBJ { private static int Clnummer=1; public static void main(String[] args) throws IOException { FileOutputStream out = new FileOutputStream("/Users/muratcanpinar/Downloads/KNVBJ/build/classes/knvbj/ClubInformation.xlsx"); List<String> urlList = ReadXlsx.readXlsx(); urlList.get(1); for (String url : urlList) { System.out.println("url: " + url); } for (int i = 0; i < urlList.size(); i++) { Document doc = Jsoup.connect(urlList.get(i)) .data("query", "Java") .userAgent("Mozilla") .cookie("auth", "token") .timeout(3000) .post(); Element content1 = doc.getElementsByClass("details").first(); String body = content1.toString(); Document docb = Jsoup.parseBodyFragment(body); Element bbd = docb.body(); String kkj = bbd.toString(); Document finalDocument = Jsoup.parse(kkj); Element ClubName = finalDocument.getElementsByClass("title").first(); String NameOfClub = ClubName.text(); System.out.println(NameOfClub); Element Adres = finalDocument.getElementsByClass("text").get(1); String[] addressParts = Adres.html().split("<br />"); String SplitString; String PlaatsName; String Straat; String telNo; String Accommodatie; String Postcode; Accommodatie = addressParts[0].trim(); Straat = addressParts[1].trim(); SplitString = addressParts[2].trim(); telNo = addressParts[3].trim(); String splitted[]= SplitString.split(" "); Postcode = splitted[0]; PlaatsName = splitted[1]; System.out.println(Accommodatie + " " + Straat + " " + " postcode " + Postcode + " Plaatsname " + PlaatsName+ " "+ telNo); Elements anchors = finalDocument.getElementsByTag("a"); String email = anchors.get(1).text(); String fname = "/Users/muratcanpinar/Downloads/KNVBJ/src/knvbj/Voetbalclubs.xlsx"; InputStream inp = new FileInputStream(fname); Workbook wb = new XSSFWorkbook(inp); Sheet sheet = wb.getSheetAt(0); Row r1 = sheet.getRow(0); r1.createCell(Clnummer++).setCellValue(NameOfClub); r1.createCell(Clnummer++).setCellValue(Accommodatie); r1.createCell(Clnummer++).setCellValue(Straat); r1.createCell(Clnummer++).setCellValue(Postcode); r1.createCell(Clnummer++).setCellValue(PlaatsName); r1.createCell(Clnummer++).setCellValue(telNo); r1.createCell(Clnummer++).setCellValue(email); wb.write(out); } out.close(); } } 

有了上面的代码,我可以只填写一行,然后得到这个错误

 Exception in thread "main" org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException: Fail to save: an error occurs while saving the package : The part /docProps/app.xml fail to be saved in the stream with marshaller org.apache.poi.openxml4j.opc.internal.marshallers.DefaultMarshaller@f46fdc1 at org.apache.poi.openxml4j.opc.ZipPackage.saveImpl(ZipPackage.java:479) at org.apache.poi.openxml4j.opc.OPCPackage.save(OPCPackage.java:1414) at org.apache.poi.POIXMLDocument.write(POIXMLDocument.java:179) at knvbj.KNVBJ.main(KNVBJ.java:101) Caused by: org.apache.poi.openxml4j.exceptions.OpenXML4JException: The part /docProps/app.xml fail to be saved in the stream with marshaller org.apache.poi.openxml4j.opc.internal.marshallers.DefaultMarshaller@f46fdc1 at org.apache.poi.openxml4j.opc.ZipPackage.saveImpl(ZipPackage.java:470) ... 3 more Java Result: 1 

有人能告诉我我在做什么吗? 非常感谢。

问题在于你的FileOutputStreamvariables在同一个Workbook被多次使用。 在循环内打开和closuresFileOutputStream可修复您的exception。 POI和/或xml / zip库,不喜欢多次使用同一个stream。

如果你使用与1循环相同的代码,它可以工作,2,它会崩溃,你有例外。

这里有一个简单的代码来replaceJSoup代码做的一个快速修复:

  private static int Clnummer = 1; public static void main(String[] args) throws IOException { for (int i = 0; i < 2; i++) { FileOutputStream out = new FileOutputStream("yourfilePath"); String NameOfClub = "Potaoes club"; System.out.println(NameOfClub); String PlaatsName; String Straat; String telNo; String Accommodatie; String Postcode; Accommodatie = "123"; Straat = "Potatoes club street"; telNo = "123456789"; Postcode = "P0P0P0"; PlaatsName = "PotatoCity"; String email = "potatoKing@potato.com"; String fname = "guessing this is a template file"; InputStream inp = new FileInputStream(fname); Workbook wb = new XSSFWorkbook(inp); Sheet sheet = wb.getSheetAt(0); Row r1 = sheet.getRow(0); r1.createCell(Clnummer++).setCellValue(NameOfClub); r1.createCell(Clnummer++).setCellValue(Accommodatie); r1.createCell(Clnummer++).setCellValue(Straat); r1.createCell(Clnummer++).setCellValue(Postcode); r1.createCell(Clnummer++).setCellValue(PlaatsName); r1.createCell(Clnummer++).setCellValue(telNo); r1.createCell(Clnummer++).setCellValue(email); wb.write(out); out.close(); } } } 

在当前代码中,您正试图将ClubInformation.xlsx写入一张Voetbalclubs.xlsx 。 因此这是一个错误。 (xslx是一个xml格式,因此在编写/docProps/app.xml会出错)。

我已经修改你的代码如下。 更改行List<String> urlList = Arrays.asList("http://google.com"); 根据你的需要。 让我知道这个是否奏效

 public class KNVBJ { private static int Clnummer=1; public static void main(String[] args) throws IOException { FileOutputStream out = new FileOutputStream("ClubInformation.xlsx"); List<String> urlList = Arrays.asList("http://google.com"); urlList.get(0); for (String url : urlList) { System.out.println("url: " + url); } String fname = "Voetbalclubs.xlsx"; FileOutputStream output = new FileOutputStream(fname); for (int i = 0; i < urlList.size(); i++) { Document doc = Jsoup.connect(urlList.get(i)) .data("query", "Java") .userAgent("Mozilla") .cookie("auth", "token") .timeout(3000) .post(); Element content1 = doc.getElementsByClass("details").first(); String body = content1.toString(); Document docb = Jsoup.parseBodyFragment(body); Element bbd = docb.body(); String kkj = bbd.toString(); Document finalDocument = Jsoup.parse(kkj); Element ClubName = finalDocument.getElementsByClass("title").first(); String NameOfClub = ClubName.text(); System.out.println(NameOfClub); Element Adres = finalDocument.getElementsByClass("text").get(1); String[] addressParts = Adres.html().split("<br />"); String SplitString; String PlaatsName; String Straat; String telNo; String Accommodatie; String Postcode; Accommodatie = addressParts[0].trim(); Straat = addressParts[1].trim(); SplitString = addressParts[2].trim(); telNo = addressParts[3].trim(); String splitted[]= SplitString.split(" "); Postcode = splitted[0]; PlaatsName = splitted[1]; System.out.println(Accommodatie + " " + Straat + " " + " postcode " + Postcode + " Plaatsname " + PlaatsName+ " "+ telNo); org.jsoup.select.Elements anchors = finalDocument.getElementsByTag("a"); String email = anchors.get(1).text(); Workbook wb = new XSSFWorkbook(); Sheet sheet = wb.getSheetAt(0); Row r1 = sheet.getRow(0); r1.createCell(Clnummer++).setCellValue(NameOfClub); r1.createCell(Clnummer++).setCellValue(Accommodatie); r1.createCell(Clnummer++).setCellValue(Straat); r1.createCell(Clnummer++).setCellValue(Postcode); r1.createCell(Clnummer++).setCellValue(PlaatsName); r1.createCell(Clnummer++).setCellValue(telNo); r1.createCell(Clnummer++).setCellValue(email); wb.write(output); } out.close(); } } 

使用固定的理智值对最后13行进行testing。 如果这也失败了,那么问题很可能就是input模板。 如果这样做的话,问题就是你从汤姆那里得到的价值。 打印它们,看是否有任何奇怪的值。

只发布较小的13行程序也会增加获得答案的机会。 当然你也可以尝试使用另一个Voetbalclubs.xlsx文件来获得乐趣。

首先:最好从一个实例开始,从那里开始工作。 因此,从示例代码开始,该代码将一个简单的string写入单个单元格,然后写入本地文件系统上的现有工作表,然后写入已经从Webparsing的数据。 这样,当遇到问题时,您最好在哪里寻找解决scheme。

您列出的exception是保存失败时ZipPackage引发的一般exception:

 if (!defaultPartMarshaller.marshall(part, zos)) throw new OpenXML4JException("The part " + part.getPartName().getURI() + " fail to be saved in the stream with marshaller " + defaultPartMarshaller); 

所以defaultPartMarshaller的marshall方法返回false,导致失败的内部exception丢失。 DefaultMarshaller没有太多的function,它只是要求零件将自己保存到OutputStream中。

从那里得到什么样的PackagePart正在被保存有一点确定。 但是,例如, ZipPartMarshaller捕获发生的任何exception,并在返回false之前logging它们:

 try { ... } catch (IOException ioe) { logger.log(POILogger.ERROR,"Cannot write: " + part.getPartName() + ": in ZIP", ioe); return false; } 

那么你可以看看其余的输出,看看有没有更多的相关信息之前logging此exception?

如果找不到更多相关的日志logging,这是默认情况下非常正常的原因,日志logging器是一个不logging事物的NullLogger。 你可以设置运行时属性org.apache.poi.util.POILogger=org.apache.poi.util.SystemOutLogger (例如,通过使用命令行参数-Dorg.apache.poi.util.POILogger=org.apache.poi.util.SystemOutLogger启动java -Dorg.apache.poi.util.POILogger=org.apache.poi.util.SystemOutLogger ),看看是否会产生更多的日志logging?

对我来说,这似乎是由AWS中的超时引起的,closures输出stream。 错误信息是没有帮助和误导。 这是我所能得到的最好的信息。

当用于创build输出stream的文件已经有数据时,我收到了类似的错误。 如果您正在寻找数据追加到文件中,则必须在文件输出stream对象中指明:

 FileOutputStream out = new FileOutputStream("/Users/muratcanpinar/Downloads/KNVBJ/build/classes/knvbj/ClubInformation.xlsx", true); 

当你这样做时, wb.write(out)应该按预期工作。

 package knvbj; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.List; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.nodes.TextNode; import org.jsoup.select.Elements; public class KNVBJ { private static int Clnummer=1; public static void main(String[] args) throws IOException { List<String> urlList = ReadXlsx.readXlsx(); urlList.get(1); for (String url : urlList) { System.out.println("url: " + url); } for (int i = 0; i < urlList.size(); i++) { Document doc = Jsoup.connect(urlList.get(i)) .data("query", "Java") .userAgent("Mozilla") .cookie("auth", "token") .timeout(3000) .post(); Element content1 = doc.getElementsByClass("details").first(); String body = content1.toString(); Document docb = Jsoup.parseBodyFragment(body); Element bbd = docb.body(); String kkj = bbd.toString(); Document finalDocument = Jsoup.parse(kkj); Element ClubName = finalDocument.getElementsByClass("title").first(); String NameOfClub = ClubName.text(); System.out.println(NameOfClub); Element Adres = finalDocument.getElementsByClass("text").get(1); String[] addressParts = Adres.html().split("<br />"); String SplitString; String PlaatsName; String Straat; String telNo; String Accommodatie; String Postcode; Accommodatie = addressParts[0].trim(); Straat = addressParts[1].trim(); SplitString = addressParts[2].trim(); telNo = addressParts[3].trim(); String splitted[]= SplitString.split(" "); Postcode = splitted[0]; PlaatsName = splitted[1]; System.out.println(Accommodatie + " " + Straat + " " + " postcode " + Postcode + " Plaatsname " + PlaatsName+ " "+ telNo); Elements anchors = finalDocument.getElementsByTag("a"); String email = anchors.get(1).text(); String fname = "/Users/muratcanpinar/Downloads/KNVBJ/src/knvbj/Voetbalclubs.xlsx"; InputStream inp = new FileInputStream(fname); Workbook wb = new XSSFWorkbook(inp); Sheet sheet = wb.getSheetAt(0); Row r1 = sheet.getRow(0); r1.createCell(Clnummer++).setCellValue(NameOfClub); r1.createCell(Clnummer++).setCellValue(Accommodatie); r1.createCell(Clnummer++).setCellValue(Straat); r1.createCell(Clnummer++).setCellValue(Postcode); r1.createCell(Clnummer++).setCellValue(PlaatsName); r1.createCell(Clnummer++).setCellValue(telNo); r1.createCell(Clnummer++).setCellValue(email); } FileOutputStream out = new FileOutputStream("/Users/muratcanpinar/Downloads/KNVBJ/build/classes/knvbj/ClubI nformation.xlsx",true); wb.write(out); out.close(); } } 

您需要在创build所有单元格后创build输出stream,然后将它们写入文件。 请参阅代码的详细信息。

在句子外面写下for循环

wb.write(下);