I ran into a problem today, testing my new NPOI DataTable web export function… While running some large queries that resulted in 65K+ rows of data, my function blew up. As you know, Excel 2003 and the BIFF format only support 65,536 rows! To make sure this never happens again, I’ve added a little block of code around my details loop to create an additional sheet every time you reach row 65,536.

code excerpt based on using a DataTable as your data source
int rowIndex = 1;               // Starting Row (0 = Header)
int sheetIndex = 1;             // Starting sheet is always set to "Sheet1"
const int maxRows = 65536;      // Max rows p/sheet in Excel 2003

// Start loop of details to write to sheet
foreach (DataRow row in DataTableToExport.Rows)
	// Check if max rows hit, if so start new sheet and copy headers from current sheet.
	if(rowIndex % maxRows == 0)
		// Auto size columns on current sheet
		for (int h = 0; h < headerRow.LastCellNum; h++)

		// Increment sheet counter

		// Create new sheet
		sheet = workbook.CreateSheet("Sheet" + sheetIndex);

		// Create header on new sheet
		HSSFRow additionalHeaderRow = sheet.CreateRow(0);

		// Copy headers from first sheet
		for (int h = 0; h < headerRow.LastCellNum; h++)
			HSSFCell additionalHeaderColumn = additionalHeaderRow.CreateCell(h);
			additionalHeaderColumn.CellStyle = headerRow.GetCell(h).CellStyle;

		rowIndex = 1;

	// Create new detail row in sheet
	HSSFRow dataRow = sheet.CreateRow(rowIndex);
	// Loop the columns from the DataRow and add using dataRow.CreateCell(#)....

In a nutshell, I create some counters before going into the detail row loop to track the Row and Sheet number. When I hit the max Row number number on a sheet, I create a new Sheet. To keep everything pretty, I copy the header row from the first sheet to the first row of the new sheet. The only output limitation now is the max sheets of 255.