Set top row and left column for an XSSFSheet

2019-07-28 03:43发布

问题:

I am trying to make sure an XLSX sheet is at the top left when the file is open.

The XSSFSheet has a getTopCol() and a getLeftCol() methods, but there is no setter.

XSSFSheet.showInPane(int, int) does work, but only if pane is frozen or split.

    PaneInformation pane = sheet.getPaneInformation();
    if (pane == null) {
        // FIXME doesn't work when there is no pane
        sheet.showInPane(CellAddress.A1.getRow(), CellAddress.A1.getColumn());
    } else {
        // OK
        sheet.showInPane(pane.getHorizontalSplitPosition(), pane.getVerticalSplitPosition());
    }

I tried to view what could be accessed from the XSSFSheet class, but all underlying methods are private.

Does anybody know of a way to reset the view of a sheet to the top left cell?

回答1:

Seems as if there is not such setting directly with the POI objects. But it is possible with CTWorksheet. http://grepcode.com/file/repo1.maven.org/maven2/org.apache.poi/ooxml-schemas/1.1/org/openxmlformats/schemas/spreadsheetml/x2006/main/CTWorksheet.java#CTWorksheet

...
((XSSFSheet)sheet).getCTWorksheet().getSheetViews().getSheetViewArray(0).setTopLeftCell("D10");
...

Best possibility getting such informations is creating a simple file directly with Excel. Then save this as *.xlsx. Then unzip this file and look in /xl/worksheets/sheet1.xml. There you find:

...
<sheetViews>
 <sheetView workbookViewId="0" tabSelected="true" topLeftCell="D10"/>
</sheetViews>
...


回答2:

To add some more background on this:

If you look at the respective implementations of getTopRow() and getLeftCol() they both get their values from an instance of CTSheetView (via two different ways which, I suppose, is not completely intentional).

In contrast, showInPane() is based on a CTPane which is a data structure that lives one level below a CTSheetView. According to ECMA-376 (page 3904) such a CTPane is optional (i.e. you do not have to apply a "split" to your CTSheetView).

However, what remains dubious to me is the following: showInPane() (via getPane()) does, in fact, try to create a new pane if there is none, yet. On this new pane it then calls setTopLeftCell() - which according to ECMA-376 (page 1657) only applies to a bottom right pane. The default type of a new pane is top left, though (see page 2460 of that spec for a list of available panes).

This means:

  • There may be an error in that monstrous ECMA-376 spec. So setting the top left cell is actually possible for all pane types.
  • POI probably contains a bug somewhere around the getPane()-method which prevents it from actually inserting a new pane into the sheet view.

... for a pragmatic solution how to get around this you should stick to Axel Richter's answer, though. This sets the visible cells directly on the CTSheetView which is most likely what you are after.