Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions main/HSSF/Model/InternalSheet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2339,6 +2339,21 @@ public int GetColumnOutlineLevel(int columnIndex)
return _columnInfos.GetOutlineLevel(columnIndex);
}

public int MinColumnIndex
{
get
{
return _columnInfos.MinColumnIndex;
}
}

public int MaxColumnIndex
{
get
{
return _columnInfos.MaxColumnIndex;
}
}
}

public class UnsupportedBOFType : RecordFormatException
Expand Down
42 changes: 34 additions & 8 deletions main/HSSF/Model/InternalWorkbook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1001,11 +1001,12 @@ public int GetFontIndex(FontRecord font)
}
throw new ArgumentException("Could not find that font!");
}

/**
* Returns the StyleRecord for the given
* xfIndex, or null if that ExtendedFormat doesn't
* have a Style set.
*/
* Returns the StyleRecord for the given
* xfIndex, or null if that ExtendedFormat doesn't
* have a Style set.
*/
public StyleRecord GetStyleRecord(int xfIndex)
{
// Style records always follow after
Expand All @@ -1032,6 +1033,31 @@ public StyleRecord GetStyleRecord(int xfIndex)
}
return null;
}

/**
* Update the StyleRecord to point to the new
* given index.
*
* @param oldXf the extended format index that was previously associated with this StyleRecord
* @param newXf the extended format index that is now associated with this StyleRecord
*/
public void UpdateStyleRecord(int oldXf, int newXf)
{
// Style records always follow after
// the ExtendedFormat records
for(int i = records.Xfpos; i<records.Count; i++)
{
Record r = records[i];
if(r is StyleRecord)
{
StyleRecord sr = (StyleRecord)r;
if(sr.XFIndex == oldXf)
{
sr.XFIndex = (short)newXf;
}
}
}
}
/**
* Gets the ExtendedFormatRecord at the given 0-based index
*
Expand Down Expand Up @@ -2047,10 +2073,10 @@ private static ExtendedFormatRecord CreateExtendedFormat()
}

/**
* Creates a new StyleRecord, for the given Extended
* Format index, and adds it onto the end of the
* records collection
*/
* Creates a new StyleRecord, for the given Extended
* Format index, and adds it onto the end of the
* records collection
*/
public StyleRecord CreateStyleRecord(int xfIndex) {
// Style records always follow after
// the ExtendedFormat records
Expand Down
43 changes: 43 additions & 0 deletions main/HSSF/Record/Aggregates/ColumnInfoRecordsAggregate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -770,5 +770,48 @@ public int GetOutlineLevel(int columnIndex)
return 0;
}
}

public int MinColumnIndex
{
get
{
if(records.Count == 0)
{
return 0;
}

int minIndex = int.MaxValue;
int nInfos = records.Count;
for(int i = 0; i< nInfos; i++)
{
ColumnInfoRecord ci = GetColInfo(i);
minIndex = Math.Min(minIndex, ci.FirstColumn);
}

return minIndex;
}

}

public int MaxColumnIndex
{
get
{
if(records.Count == 0)
{
return 0;
}

int maxIndex = 0;
int nInfos = records.Count;
for(int i = 0; i< nInfos; i++)
{
ColumnInfoRecord ci = GetColInfo(i);
maxIndex = Math.Max(maxIndex, ci.LastColumn);
}

return maxIndex;
}
}
}
}
147 changes: 113 additions & 34 deletions main/HSSF/UserModel/HSSFOptimiser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ limitations under the License.
==================================================================== */
namespace NPOI.HSSF.UserModel
{
using System.Collections;
using NPOI.SS.UserModel;

using NPOI.HSSF.Record;
using NPOI.SS.UserModel;
using System;
using System.Collections;

/// <summary>
/// Excel can Get cranky if you give it files containing too
Expand Down Expand Up @@ -217,49 +217,86 @@ public static void OptimiseCellStyles(HSSFWorkbook workbook)

// Loop over each style, seeing if it is the same
// as an earlier one. If it is, point users of the
// later duplicate copy to the earlier one, and
// later duplicate copy to the earlier one, and
// mark the later one as needing deleting
// Only work on user added ones, which come after 20
for (int i = 21; i < newPos.Length; i++)
for(int i = 21; i < newPos.Length; i++)
{
// Check this one for being a duplicate
// of an earlier one
int earlierDuplicate = -1;
for (int j = 0; j < i && earlierDuplicate == -1; j++)
for(int j = 0; j < i && earlierDuplicate == -1; j++)
{
ExtendedFormatRecord xfCheck = workbook.Workbook.GetExFormatAt(j);
if (xfCheck.Equals(xfrs[i]))
if(xfCheck.Equals(xfrs[i]) &&
// newer duplicate user defined styles
!IsUserDefined(workbook, j))
{
earlierDuplicate = j;
}
}

// If we got a duplicate, mark it as such
if (earlierDuplicate != -1)
if(earlierDuplicate != -1)
{
newPos[i] = (short)earlierDuplicate;
newPos[i] = (short) earlierDuplicate;
zapRecords[i] = true;
}
// If we got a duplicate, mark the one we're keeping as used
if (earlierDuplicate != -1)
{
isUsed[earlierDuplicate] = true;
}
}

// Loop over all the cells in the file, and identify any user defined
// styles aren't actually being used (don't touch built-in ones)
for (int sheetNum = 0; sheetNum < workbook.NumberOfSheets; sheetNum++)
for(int sheetNum = 0; sheetNum < workbook.NumberOfSheets; sheetNum++)
{
HSSFSheet s = (HSSFSheet)workbook.GetSheetAt(sheetNum);
foreach (IRow row in s)
HSSFSheet s = workbook.GetSheetAt(sheetNum) as HSSFSheet;
foreach(IRow row in s)
{
foreach (ICell cellI in row)
foreach(ICell cellI in row)
{
HSSFCell cell = (HSSFCell) cellI;
short oldXf1 = cell.CellValueRecord.XFIndex;
// some documents contain invalid values here
if(oldXf1 < newPos.Length)
{
isUsed[oldXf1] = true;
}
}

// also mark row style as being used
short oldXf = ((HSSFRow) row).RowRecord.XFIndex;
// some documents contain invalid values here
if(oldXf < newPos.Length)
{
HSSFCell cell = (HSSFCell)cellI;
short oldXf = cell.CellValueRecord.XFIndex;
isUsed[oldXf] = true;
}
}

// also mark column styles as being used
for(int col = s.Sheet.MinColumnIndex; col <= s.Sheet.MaxColumnIndex; col++)
{
short oldXf = s.Sheet.GetXFIndexForColAt((short) col);
// some documents contain invalid values here
if(oldXf < newPos.Length)
{
isUsed[oldXf] = true;
}
}
}

// Propagate isUsed for duplicates and always set user styles to being used to never optimize them away
for(int i = 21; i < isUsed.Length; i++)
{
// user defined styles are always "used"
if(IsUserDefined(workbook, i))
{
isUsed[i] = true;
}

// If we got a duplicate which is used, mark the one we're keeping as used
if(newPos[i] != i && isUsed[i])
{
isUsed[newPos[i]] = true;
}
}
// Mark any that aren't used as needing zapping
for (int i = 21; i < isUsed.Length; i++)
Expand Down Expand Up @@ -288,6 +325,20 @@ public static void OptimiseCellStyles(HSSFWorkbook workbook)

// Update the new position
newPos[i] = newPosition;
// also update StyleRecord and Parent-link
if(i != newPosition && newPosition != 0)
{
workbook.Workbook.UpdateStyleRecord(i, newPosition);

ExtendedFormatRecord exFormat = workbook.Workbook.GetExFormatAt(i);
short oldParent = exFormat.ParentIndex;
// some documents contain invalid values here
if(oldParent < newPos.Length)
{
short newParent = newPos[oldParent];
exFormat.ParentIndex = newParent;
}
}
}

// Zap the un-needed user style records
Expand All @@ -307,27 +358,55 @@ public static void OptimiseCellStyles(HSSFWorkbook workbook)
}

// Finally, update the cells to point at their new extended format records
for (int sheetNum = 0; sheetNum < workbook.NumberOfSheets; sheetNum++)
for(int sheetNum = 0; sheetNum < workbook.NumberOfSheets; sheetNum++)
{
HSSFSheet s = (HSSFSheet)workbook.GetSheetAt(sheetNum);
//IEnumerator rIt = s.GetRowEnumerator();
//while (rIt.MoveNext())
HSSFSheet s = workbook.GetSheetAt(sheetNum) as HSSFSheet;
foreach(IRow row in s)
{
//HSSFRow row = (HSSFRow)rIt.Current;
//IEnumerator cIt = row.GetEnumerator();
//while (cIt.MoveNext())
foreach (ICell cell in row)
foreach(ICell cell in row)
{
//ICell cell = (HSSFCell)cIt.Current;
short oldXf = ((HSSFCell)cell).CellValueRecord.XFIndex;
NPOI.SS.UserModel.ICellStyle newStyle = workbook.GetCellStyleAt(
newPos[oldXf]
);
cell.CellStyle = (newStyle);
short oldXf1 = ((HSSFCell) cell).CellValueRecord.XFIndex;
// some documents contain invalid values here
if(oldXf1 >= newPos.Length)
{
continue;
}
HSSFCellStyle newStyle1 = workbook.GetCellStyleAt(newPos[oldXf1]) as HSSFCellStyle;
cell.CellStyle = newStyle1;
}

// adjust row column style
short oldXf = ((HSSFRow) row).RowRecord.XFIndex;
// some documents contain invalid values here
if(oldXf >= newPos.Length)
{
continue;
}
HSSFCellStyle newStyle = workbook.GetCellStyleAt(newPos[oldXf]) as HSSFCellStyle;
row.RowStyle = newStyle;
}

// adjust cell column style
for(int col = s.Sheet.MinColumnIndex; col <= s.Sheet.MaxColumnIndex; col++)
{
short oldXf = s.Sheet.GetXFIndexForColAt((short) col);
// some documents contain invalid values here
if(oldXf >= newPos.Length)
{
continue;
}
HSSFCellStyle newStyle = workbook.GetCellStyleAt(newPos[oldXf]) as HSSFCellStyle;
s.SetDefaultColumnStyle(col, newStyle);
}
}
}

private static bool IsUserDefined(HSSFWorkbook workbook, int index)
{
StyleRecord styleRecord = workbook.Workbook.GetStyleRecord(index);
return styleRecord != null &&
!styleRecord.IsBuiltin &&
styleRecord.Name != null;
}
}
}
2 changes: 1 addition & 1 deletion main/SS/Util/CellRangeAddress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol)
{
if (lastRow < firstRow || lastCol < firstCol)
throw new ArgumentException("Invalid cell range, having lastRow < firstRow || lastCol < firstCol, " +
"had rows " + lastRow + " >= " + firstRow + " or cells " + lastCol + " >= " + firstCol);
"had rows " + lastRow + " >= " + firstRow + " or cells " + lastCol + " >= " + firstCol);
}

public CellRangeAddress(RecordInputStream in1)
Expand Down
Loading
Loading