Bug 59180

Summary: XSSFGraphicFrame hides anchor from XSSFShape
Product: POI Reporter: Tony BenBrahim <tony.benbrahim>
Component: XSSFAssignee: POI Developers List <dev>
Status: NEW ---    
Severity: normal    
Priority: P2    
Version: 3.14-FINAL   
Target Milestone: ---   
Hardware: PC   
OS: All   
Attachments: inspection of anchor field

Description Tony BenBrahim 2016-03-14 16:13:27 UTC
Created attachment 33674 [details]
inspection of anchor field

XSSFGraphicFrame incorrectly declares its own anchor field, hiding the anchor property from XSSFShape. The achor property from XSSFShape has the anchor value, the one from XSSFGraphicFrame is always null.

I was working with the graphic frame for a chart. I was able to get the anchor through the chart parent:

final XSSFDrawing parent = (XSSFDrawing) chart.getParent();
final CTTwoCellAnchor twoCellAnchorArray = parent.getCTDrawing().getTwoCellAnchorArray(0);
		final XSSFClientAnchor xssfClientAnchor = new XSSFClientAnchor((int) twoCellAnchorArray.getFrom().getColOff(),
				(int) twoCellAnchorArray.getFrom().getRowOff(), (int) twoCellAnchorArray.getTo().getColOff(),
				(int) twoCellAnchorArray.getTo().getRowOff(), twoCellAnchorArray.getFrom().getCol(),
				twoCellAnchorArray.getFrom().getRow(), twoCellAnchorArray.getTo().getCol(),
Comment 1 Tony BenBrahim 2016-03-21 15:37:34 UTC
Workaround above did not work in one case of three (wrong parent returned by chart.getParent().

I ended up using this (ugly but works)

if (shape instanceof XSSFGraphicFrame) {
    try {
	final Field anchorField = XSSFShape.class.getDeclaredField("anchor");
	final XSSFClientAnchor anchor = (XSSFClientAnchor) anchorField.get(shape);
    } catch (NoSuchFieldException | SecurityException | IllegalAccessException |
 IllegalArgumentException e) {
	LOG.info("unable to extract anchor for chart", e);
Comment 2 Dominik Stadler 2016-03-28 20:44:03 UTC
One thing that makes it a bit more complex to fix this is that  XSSFGraphicFrame uses an XSSFClientAnchor, but XSSFShape the superclass XSSFAnchor. XSSFClientAnchor seems to hold a bit more information, so I am not sure how this can be combined without causing compatibility problems and missing functionality. 

The best way I can think of is to rename the field/getters/setters in  XSSFGraphicFrame to get/setClientAnchor() to have both available for now, however this still could cause some compatibility errors for other users of  XSSFGraphicFrame.