When attempting to open an excel file my application generates with hidden rows I get the following warning message.
We found a problem with some content in 'all-harvests.xlsx'. Do you want us to try to recover as much as we can? If you trust the source of this workbook click Yes.
If you click 'Yes' then the expected output is displayed with all rows appropriately hidden.
In my web app I am generating an excel file with rows containing harvest information. The file then gets sent as an email attachment to different wildlife management authorities. I am trying to hide any rows that have a "Harvested" date outside of the current hunting season (Sept-Feb). The logic of determining whether to hide vs show the row works but the generated excel file displays the above warning.
If I remove the portion that hides rows (FilterExcelFile), then the Excel file is generated and can be opened without any issue. I have tried changing the file type to xls which resulted in a completely unreadable file. I also have looked up similar posts on Stackoverflow but haven't been able to get it working based off of those answers. I appreciate any assistance you might have as I am at a loss for what to try next.
The file is generated here:
private byte[] GenerateExcelFile(IEnumerable<HarvestSpreadsheetDataRow> data)
{
// Create Excel file with all harvested data
const string sheetName = "Harvest_Report";
var bytes = new PackageBuilder().WithWorksheet(w => w
.WithName(sheetName)
.WithTable<HarvestSpreadsheetDataRow>(t => t.WithData(data).IgnoreColumn(r => r.HarvestId))
.AutoFit()
).ToByteArray();
return bytes;
}
The row hiding takes place in this function
private byte[] FilterExcelFile(byte[] excelBytes)
{
using (MemoryStream stream = new MemoryStream(excelBytes))
{
using (ExcelPackage package = new ExcelPackage(stream))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets.FirstOrDefault();
if (worksheet != null)
{
// Find the index of the "Harvested" Date
int harvestedDateColumnIndex = 4;
// Get the total number of rows in the worksheet
int rowCount = worksheet.Dimension.Rows;
// Get the current date
DateTime currentDate = _dateTimeProvider.Now;
// Determine the hunting season range for the current year
DateTime huntingSeasonStart = new DateTime(currentDate.Month >= 9 ? currentDate.Year : currentDate.Year - 1, 9, 1); // September 1st
DateTime huntingSeasonEnd = new DateTime(currentDate.Month <= 2 ? currentDate.Year : currentDate.Year + 1, 2, 28).AddDays(1); // February 28th (or 29th in a leap year) + 1 day
for (int row = 2; row <= rowCount; row++)
{
var cellValue = worksheet.Cells[row, harvestedDateColumnIndex].Value;
if (cellValue != null && DateTime.TryParse(cellValue.ToString(), out DateTime harvestedDate))
{
if (!(harvestedDate >= huntingSeasonStart && harvestedDate < huntingSeasonEnd))
{
worksheet.Row(row).Hidden = true; // Hide rows with harvest dates outside the current hunting season
}
}
}
// Save the changes to the memory stream
package.Save();
}
return package.GetAsByteArray();
}
}
}
This function is where the other two are called and the excel file is sent as an email attachment:
public void SendReportEmail(string toEmailAddress, string subject, string message, string homeAddress)
{
if (string.IsNullOrWhiteSpace(toEmailAddress))
throw new ArgumentNullException(nameof(toEmailAddress));
// Retrieve completed harvests data
List<Harvest> harvests = _harvestService.GetCompletedHarvests();
// Convert data to HarvestSpreadsheetDataRow objects
var data = harvests.Select(h => new HarvestSpreadsheetDataRow(h));
// Create Excel file with all harvested data
byte[] excelBytes = GenerateExcelFile(data);
// Modify Excel file to hide rows not within the current hunting season
byte[] filteredExcelBytes = FilterExcelFile(excelBytes);
// Attach Excel file to the email
var attachment = new EasyAttachment
{
FileName = $"all-harvests.xlsx",
ContentStream = new MemoryStream(filteredExcelBytes)
};
var attachments = new List<EasyAttachment> { attachment };
// Serialize email body with subject, message, and home address
var year = DateTime.Now.Year.ToString();
var body = _emailTemplateService.SerializeHtml(subject, message, homeAddress, year);
// Create and send email with attached Excel file
var easyMessage = new EasyMessage("[email protected]", toEmailAddress)
{
Subject = subject,
Body = body,
IsBodyHtml = true,
Attachments = attachments
};
_easyEmailer.Send(easyMessage);
}