By having the possibility of tracking specific rows only, one gains the capability to exclude some rows from autosizing calculations. This is useful independently of type of Sheet. Example usecase is a row of column headings. This was also proposed by the issue reporter, see his latest comment [1]. Although not strictly related to the SXSSF autosizing bug, it would be a nice side-effect to gain.
[1] https://bz.apache.org/bugzilla/show_bug.cgi?id=57450#c4 Den 9 nov 2015 17:30 skrev "Javen O'Neal" <[email protected]>: > Tracking is simply unnecessary for XSSFSheet and HSSFSheet because the rows > never fall outside the memory window. Keep in mind that tracking rows uses > a little more memory and performs some expensive sizing logic that may not > get used. I'd keep the autosizing tracker at the SXSSF level since it only > applies for windowed memory sheets. > > I expect users needing to write themselves into the SXSSFSheet API when it > differs from the Sheet interface, and this is certainly one of those cases. > On 9 Nov 2015 05:14, "ST" <[email protected]> wrote: > > > Javen, > > > > Regarding your critical feedback given in your first email of this email > > thread, I've updated my patch. But let's first have the other discussions > > triggered by your second email of this email thread. > > > > I actually like the tightly-coupled extreme of your vision: completely > > hiding the tracker logic behind the Sheet API. Internally we could still > > use a private class (same for all Sheet impls) to do the autosizing. I > can > > see the following benefits with this hide-behind-Sheet-API approach: > > * "Solves" the problem of backward compatibility: same window-dependant > > behaviour as before for SXSSFSheets, which can be fixed by using newly > > added API (see below) > > * Keeps same API for the different Sheet implementations > > * Will still allow to exclude some rows from autosize calculation > > > > I propose to add the following tracker API methods to the Sheet > interface: > > * trackRowForAutoSizing(Row) > > * autoSizeAllColumnsByTrackedRows() > > * autoSizeAllColumnsByTrackedRows(bool) // not sure if needed > > These will complement the two existing autosize methods: > > * autoSizeColumn(int) // keep this existing method > > * autoSizeColumn(int,bool) // keep this existing method > > > > What do you think about this? > > > > The quicker but uglier solution would be to add the new tracker API only > to > > SXSSFSheet. But this in my opinion defeats the whole idea of the Sheet > > interface since POI users will have to do the autosizing differently > based > > on the actual Sheet implementation. > > > > I'll give it a try when I find the time. > > stefan. > > > > > > > > > > On Wed, Nov 4, 2015 at 6:37 AM, Javen O'Neal <[email protected]> > wrote: > > > > > Here's what I had in mind about keeping support for > > > SXSSFSheet.autoSizeColumn(int) and autoSizeColumn(int, bool): > > > > > > int rowAccessWindowSize = 1; > > > SXSSFWorkbook wb = new SXSSFWorkbook(rowAccessWindowSize); > > > SXSSFSheet sh = wb.createSheet(); > > > AutosizeColumnTracker tracker = sh.getAutosizeColumnTracker(); //this > > > probably needs to be a singleton. Can be lazily-created. > > > // tell workbook to keep track of column widths as they *might* be > > > auto-sized at the end of the sheet > > > > > > boolean useMergedCells = false; > > > tracker.monitorColumn(0, useMergedCells); > > > tracker.monitorColumn(2, useMergedCells); > > > tracker.monitorColumn(4); // equivalent to monitorColumn(4, true); > > > > > > // create a bunch of rows and cells, write some values to the cells, > > merge > > > some cells across columns and rows so auto-size has something > meaningful > > to > > > do > > > Row row; > > > Cell cell; > > > for (int r=0; r<=10; r++) { > > > row = sh.createRow(r); > > > for (int c=0; c<=10; c++) { > > > cell = row.createCell(0); > > > cell.setCellValue("row=" + r + ", column=" + c + ", > > > somethingToMakeColumnsHaveDifferentWidth=" + ((int) Math.pow(r, c))); > > > } > > > } > > > // ... etc > > > > > > sh.autoSizeColumn(0); // okay > > > sh.autoSizeColumn(0, false); // okay > > > sh.autoSizeColumn(0, true); // throws exception: column widths were > > > calculated using merged cell widths, but this pre-requisite is no > longer > > > valid. > > > sh.autoSizeColumn(1); // throws exception: column was not monitored for > > > auto-sizing > > > sh.autoSizeColumn(2); // okay > > > > > > // and if we want to allow a user to auto-size a column that wasn't > > > previously monitored, we might need to add an extra method that will > > > indicate that the user understands that auto-sizing is computed solely > > from > > > the row access window, and not to throw an UnmonitoredColumnForAutosize > > > (insert your favorite name here) exception. > > > autoSizeRowAccessWindowOnly = true; > > > sh.autoSizeColumn(0, false, autoSizeRowAccessWindowOnly); // okay: > makes > > > existing functionality available > > > // alternatively, if you want to allow the user to determine if a > column > > > gets autosized using merged cells or not at the time autoSizeColumn is > > > called, the AutosizeColumnTracker would need to calculate and remember > > the > > > widths for both cases (useMergedCells=true and useMergedCell=false). > > > > > > > > > // finish up > > > // ... etc > > > wb.write(new FileOutputStream('example.xlsx')); > > > > > > > > > I think the relationship between the tracker object and the SXSSFSheet > > > warrants more discussion, as there are several ways to do this. > > > Considerations: > > > * extensibility: how can the AutosizeColumnTracker class be subclassed > by > > > users of POI? how can the SXSSFSheet be subclassed by users of POI? > > Should > > > AutosizeColumnTracker be final or @Internal to avoid this question? > > > * reusability: is there a need to create one autosize column tracker > > object > > > that can be applied to multiple sheets (whether this is just the index > of > > > the monitored columns or also the column widths)? > > > * if sh.autoSizeColumn uses the tracker, either the tracker needs to be > > > passed in as a third argument or the sheet needs to know what tracker > it > > is > > > associated with. Every time a column goes outside the window, the > > > SXSSFSheet needs to know which tracker object its associated with so it > > can > > > update the column widths in the tracker (or maintain its own column > > > widths). In your code, you require the user to explicitly call > trackRow, > > > but XSSFSheet and HSSFSheet don't have a similar construct: auto-sizing > > > applies to ALL rows and this is not user configurable. > > > * My vision of the AutosizeColumnTracker may be too tightly coupled > with > > > the SXSSFSheet. At the tightly-coupled extreme, AutosizeColumnTracker > may > > > be a private class (or just a private TreeMap member variable) inside > of > > > SXSSFSheet that maintains a TreeMap of tracked columns and column > widths; > > > all intents are registered directly on the SXSSFSheet: > > > sxssfSheet.monitorColumnForAutosizing(0); > > > > > > Thoughts? > > > Javen > > > > > >
