Summary: | Saved file that uses a XSSFFont without a specifically set FontFamily won't open in Excel | ||
---|---|---|---|
Product: | POI | Reporter: | anna |
Component: | XSSF | Assignee: | POI Developers List <dev> |
Status: | RESOLVED FIXED | ||
Severity: | blocker | CC: | gwoolsey |
Priority: | P2 | ||
Version: | 3.15-FINAL | ||
Target Milestone: | --- | ||
Hardware: | PC | ||
OS: | All | ||
Attachments: | unit test |
Description
anna
2016-09-28 15:27:54 UTC
Created attachment 34312 [details]
unit test
I am unable to reproduce this on the trunk (currently a few commits after 3.15) using LibreOffice 4.2.8.2. I can check with Microsoft Excel later.
Is this behavior a regression in 3.15?
Can you verify that my unit test is the same as yours (if not, could you submit your unit test)?
LibreOffice doesn't have the problem, Excel does. Also reproducible in Excel Viewer. Does the status change mean that you couldn't reproduce the issue with Excel Viewer? Behaviour was already present in 3.12, not sure about older ones. Don't have a unit test, tested manually in existing project. I tested the files attached to the linked ticket on Excel 2013 and Excel Viewer, with Libre Office they worked fine. Not-so-nice workaround: Copy over StylesTable.java to local projet, change writeTo to contain for (XSSFFont f : fonts) { if (FontFamily.NOT_APPLICABLE.getValue() == f.getFamily()) { f.setFamily(FontFamily.SWISS); } ctfnt[idx++] = f.getCTFont(); } instead of for(XSSFFont f : fonts) ctfnt[idx++] = f.getCTFont(); and do that again every time you update the version. Guys is this fixed in version POI 3.15 or do you plan to fix it in near future? I obtained poi src from git read only repo and built it accordingly. Using MS Excel 2016 (with a MS office home subscription, which expired recently but doesn't restrict much of the functionality of excel 2016 that I needed for trying to reproduce the error), I was unable to reproduce the issue. Here's the code which I used: import java.io.*; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.apache.poi.xssf.usermodel.XSSFFont; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class bz60184 { public static void main(String[] args) throws IOException, InvalidFormatException { File f = new File("file.xlsx"); //already created with excel in the user.dir XSSFWorkbook wb = new XSSFWorkbook(f); XSSFCellStyle styl = wb.createCellStyle(); XSSFFont font = wb.createFont(); styl.setFont(font); wb.getSheetAt(0).getRow(0).getCell(0).setCellStyle(styl); File f2 = new File("save.xlsx"); if(f2.exists()) f2.delete(); FileOutputStream os = new FileOutputStream(f2); wb.write(os); wb.close(); os.close(); System.out.println("DONE"); } } //OS - WIN 10 ; JDK - jdk_8u102 I just now found this issue, wish I'd seen it earlier. I see the problem now. XSSFFont can be created without a family. This is what happens when calling XSSFWorkbook.createFont(). This is fine per the OOXML XSD. However, XSSFFont.getFamily() creates an empty family element if none exist. This is invalid, as the family element is required to have a val attribute. Further, it's really bad practice for things that are defined as property getters to have side effects like this. Since the API's been out there a while, we should maintain backward compatibility, but I don't like it too much. I think in the missing element case it should just return 0, the index for NOT_APPLICABLE, which appears to coincide with "auto" in the spec, but NOT create a family element. Better would be a method that returns an instance of the enum or null if not defined, or NOT_APPLICABLE if null is undesirable. For now though, I'll just update to not create the empty element if missing. |