Index: src/java/org/apache/poi/ss/util/SheetUtil.java =================================================================== --- src/java/org/apache/poi/ss/util/SheetUtil.java (revision 1712220) +++ src/java/org/apache/poi/ss/util/SheetUtil.java (working copy) @@ -227,7 +227,7 @@ * @param wb the workbook to get the default character width from * @return default character width */ - private static int getDefaultCharWidth(final Workbook wb) { + public static int getDefaultCharWidth(final Workbook wb) { Font defaultFont = wb.getFontAt((short) 0); AttributedString str = new AttributedString(String.valueOf(defaultChar)); @@ -248,7 +248,7 @@ * @param useMergedCells whether to use merged cells * @return the width in pixels or -1 if cell is empty */ - private static double getColumnWidthForRow( + public static double getColumnWidthForRow( Row row, int column, int defaultCharWidth, DataFormatter formatter, boolean useMergedCells) { if( row == null ) { return -1; Index: src/ooxml/java/org/apache/poi/xssf/streaming/AutosizeColumnTracker.java =================================================================== --- src/ooxml/java/org/apache/poi/xssf/streaming/AutosizeColumnTracker.java (revision 0) +++ src/ooxml/java/org/apache/poi/xssf/streaming/AutosizeColumnTracker.java (working copy) @@ -0,0 +1,82 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.streaming; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.poi.ss.usermodel.DataFormatter; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.util.SheetUtil; + +/** + * Tracks maximum column width when adding rows to an SXSSF sheet + * so the column width can be calculated although not all rows are + * held in memory. +*/ +public class AutosizeColumnTracker { + private SXSSFSheet sheet; + private int defaultCharWidth = -1; + + private final Set monitoredColumns = new HashSet(); + private final Map maxColumnWidths = new HashMap(); + private DataFormatter dataFormatter; + + public AutosizeColumnTracker(SXSSFSheet sheet) { + this.sheet = sheet; + } + + public void monitorColumn(int columnIndex) { + monitoredColumns.add(columnIndex); + } + + public void trackRow(Row row) { + trackRow(row, false); + } + + public void trackRow(Row row, boolean useMergedCells) { + + if (defaultCharWidth < 0) { + defaultCharWidth = SheetUtil.getDefaultCharWidth(sheet.getWorkbook()); + } + + if (dataFormatter == null) { + dataFormatter = new DataFormatter(); + } + + for (int monitoredColumn : monitoredColumns) { + final double columnWidth = SheetUtil.getColumnWidthForRow(row, monitoredColumn, defaultCharWidth, + dataFormatter, useMergedCells); + if (!maxColumnWidths.containsKey(monitoredColumn) || columnWidth > maxColumnWidths.get(monitoredColumn)) { + maxColumnWidths.put(monitoredColumn, columnWidth); + } + } + } + + public void applyAutosizeToColumn(int columnIndex) { + if (maxColumnWidths.containsKey(columnIndex)) { + + double maxColumnWidth = maxColumnWidths.get(columnIndex); + maxColumnWidth = Math.min(maxColumnWidth, 255); // The maximum column width for an individual cell is 255 characters + sheet.setColumnWidth(columnIndex, (int) (maxColumnWidth*256)); + } + } + +} Property changes on: src/ooxml/java/org/apache/poi/xssf/streaming/AutosizeColumnTracker.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestSXSSFBugs.java =================================================================== --- src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestSXSSFBugs.java (revision 1712220) +++ src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestSXSSFBugs.java (working copy) @@ -19,12 +19,19 @@ import static org.junit.Assert.assertEquals; +import java.io.IOException; + import org.apache.poi.ss.usermodel.BaseTestBugzillaIssues; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.PrintSetup; +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.ss.util.SheetUtil; import org.apache.poi.xssf.SXSSFITestDataProvider; import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.junit.Assume; import org.junit.Ignore; import org.junit.Test; @@ -77,4 +84,38 @@ wb1.close(); wb2.close(); } + + @Ignore("Shows the problem that Bug 57450 will fix") + @Test + public final void bug57450_testAutoSizeWithStreamingAndSmallWindow() throws IOException { + SXSSFWorkbook wb = new SXSSFWorkbook(null, 1); // Window size 1 so only last row will be in memory + Sheet sheet = wb.createSheet("Sheet1"); + + Row row0 = sheet.createRow(0); + Cell cellRow0 = row0.createCell(0); + String longValue = "www.hostname.com, www.hostname.com, " + + "www.hostname.com, www.hostname.com, www.hostname.com, " + + "www.hostname.com, www.hostname.com, www.hostname.com, " + + "www.hostname.com, www.hostname.com, www.hostname.com, " + + "www.hostname.com, www.hostname.com, www.hostname.com, " + + "www.hostname.com, www.hostname.com, www.hostname.com, www.hostname.com"; + cellRow0.setCellValue(longValue); + + Row row1 = sheet.createRow(1); + Cell cellRow1 = row1.createCell(0); + String shortValue = "www.hostname.com"; + cellRow1.setCellValue(shortValue); + + // autoSize will fail if required fonts are not installed, skip this test then + Font font = wb.getFontAt(cellRow0.getCellStyle().getFontIndex()); + Assume.assumeTrue("Cannot verify autoSizeColumn() because the necessary Fonts are not installed on this machine: " + font, + SheetUtil.canComputeColumnWidth(font)); + + sheet.autoSizeColumn(0); + + assertEquals("Expected maximum column width 255*256, but found ", 255 * 256, sheet.getColumnWidth(0)); + + wb.close(); + } + }