Yes, you are correct.
Our approach of generating the images is pretty basic, nothing fancy. Below is the core function which we use to generate the images.
public Tuple<Image, bool> GenerateImageFromExcelCellRange(ReportsExcelLinkObject reportLinkedExcelObject, CellRangeObject selectedCellRangeObject, bool isFromReports)
{
Image imageToReturn = null;
if (reportLinkedExcelObject == null)
return null;
bool isImageLoadedFromDatabase = false;
Workbook workbook = null;
try
{
workbook = new Workbook(reportLinkedExcelObject.ExcelFilePath);
}
catch (DirectoryNotFoundException ex)
{
isImageLoadedFromDatabase = true;
if (isFromReports)
ex.LogException("Reports Excel Link Warning: Excel data could not be loaded directly from the file but from database, since file directory could not be found!");
}
catch (FileNotFoundException ex)
{
isImageLoadedFromDatabase = true;
if (isFromReports)
ex.LogException("Reports Excel Link Warning: Excel data could not be loaded directly from the file but from database, since file could not be found!");
}
catch (Exception ex)
{
// Under Observation: Earlier we were catching any aspose related exceptions here, as we already handled filenotfound and directorynotfound exceptions,
// but in production some other exceptions like user access restrictions or others might come, so will be loading the file from db,
// in such cases as we are not sure of how many kinds of exceptions may come for UNC paths in production.
isImageLoadedFromDatabase = true;
// throw new Exception("Aspose Error Occured: Unable to read excel workbook/sheet using aspose!, please contact administrator", asposeException);
if (isFromReports)
ex.LogException("Reports Excel Link Warning: Excel data could not be loaded directly from the file but from database, since an error occured while trying to fetch the excel file!");
}
if (isImageLoadedFromDatabase)
{
if (reportLinkedExcelObject.ExcelWorkSheetByteData.Length > 0)
workbook = AsposeCellsCommonFunction.BytesToWorkbook(reportLinkedExcelObject.ExcelWorkSheetByteData);
}
try
{
if (workbook != null && reportLinkedExcelObject.CellRangeList != null && reportLinkedExcelObject.CellRangeList.Count > 0)
{
// For reports, whenever user adds the report link, if file is found in the file system, we are updating the workbook to db.
if (!isImageLoadedFromDatabase)
UpdateExcelData(reportLinkedExcelObject.ReportLinkId, workbook);
// Required, when user is still editing one excel sheet which has dependency on other sheets within the same workbook.
workbook.CalculateFormula(true);
if (selectedCellRangeObject != null)
{
Worksheet sourceWorksheet = workbook.Worksheets[selectedCellRangeObject.SheetName];
// If worksheet is not there in the system file, then just fetch the file from database and load the workbook again.
if (!isImageLoadedFromDatabase && sourceWorksheet == null)
{
workbook = null;
if (reportLinkedExcelObject.ExcelWorkSheetByteData.Length > 0)
workbook = AsposeCellsCommonFunction.BytesToWorkbook(reportLinkedExcelObject.ExcelWorkSheetByteData);
if (workbook != null)
{
workbook.CalculateFormula(true);
sourceWorksheet = workbook.Worksheets[selectedCellRangeObject.SheetName];
}
}
if (sourceWorksheet != null)
{
AsposeCellsFontWarningCallback asposeCellsWarnings = null;
reportLinkedExcelObject.WarningsForUser = new StringBuilder();
reportLinkedExcelObject.WarningsCount = 0;
#region image options and worksheet settings
// Set all margins as 0
ApplyWorkSheetSettings(sourceWorksheet, reportLinkedExcelObject, selectedCellRangeObject, isFromReports);
ImageOrPrintOptions imageOrPrintOptions = GetImageOrPrintOptionsSettings(sourceWorksheet, reportLinkedExcelObject);
if (!isFromReports)
{
asposeCellsWarnings = new AsposeCellsFontWarningCallback();
imageOrPrintOptions.WarningCallback = asposeCellsWarnings;// Show warning, if customer font not found in Dev/QA/Prod instances.
}
#endregion
ExcelDataRangeType rangeType = GetExcelDataRangeType(sourceWorksheet, selectedCellRangeObject.CellRange);
// This generates the image from excellink and also stores the image and workbook bytes in respective class properties.
// If the user has already set Print_Area in excel sheet then ExcelDataRangeType will be None, but still image has to be shown for the print area.
bool isPrintAreaSpecified = (rangeType == ExcelDataRangeType.None && !string.IsNullOrEmpty(sourceWorksheet.PageSetup.PrintArea) && selectedCellRangeObject.CellRange.ToLower() == "print_area");
if (rangeType == ExcelDataRangeType.TabularData || isPrintAreaSpecified)
{
bool isInvalidRange = false;
try
{
// When both user defined cellRange and print area seems valid, cell range should be considered for creating image.
if (rangeType == ExcelDataRangeType.TabularData)
sourceWorksheet.PageSetup.PrintArea = selectedCellRangeObject.CellRange;
}
catch (Exception)
{
isInvalidRange = true;
}
if (!isInvalidRange)
{
SheetRender sr = new SheetRender(sourceWorksheet, imageOrPrintOptions);
try
{
if (isPrintAreaSpecified)
{
string[] printAreas = sourceWorksheet.PageSetup.PrintArea.Split(',');
if (printAreas.Length > 0)
{
if (printAreas.Length > 1)
imageToReturn = MergeMultiplePrintAreaImages(printAreas, sr, sourceWorksheet);
else
imageToReturn = sr.ToImage(0);
}
}
else
imageToReturn = sr.ToImage(0);
}
catch
{
// if invalid range is given, then aspose fails to convert the range into image.
}
}
}
else if (rangeType == ExcelDataRangeType.ChartData)
{
Aspose.Cells.Charts.Chart sourceChart = sourceWorksheet.Charts[selectedCellRangeObject.CellRange];
sourceChart.Calculate();
try
{
// Aspose.Cells Bug Fix[CELLSNET-47202-chart legends overlapping issues in previous v19.4.5.0]:- Fixed in latest v20.2.4.0.
// Note: Vertical legends in MS Excel chart when printed using Print command, by default MS Excel aligns the legends horizontally,
// same behavior can be seen in Aspose.Cells as they rely on MS excel's print command internally while converting chart to image.
imageToReturn = sourceChart.ToImage(imageOrPrintOptions);
}
catch
{
// if invalid range is given, then aspose fails to convert the range into image.
}
}
if (!isFromReports && asposeCellsWarnings != null && asposeCellsWarnings.FontWarningDetails != null)
{
foreach (string fontWarning in asposeCellsWarnings.FontWarningDetails)
{
if (!string.IsNullOrEmpty(fontWarning))
reportLinkedExcelObject.WarningsForUser.AppendLine(fontWarning);
}
reportLinkedExcelObject.WarningsCount += asposeCellsWarnings.FontWarningDetails.Count;
}
}
}
}
}
catch (Exception ex)
{
throw new Exception("Error: Generating Image from Cell Range failed!, please contact administrator", ex);
}
return new Tuple<Image, bool>(imageToReturn, isImageLoadedFromDatabase);
}
The exception is thrown with any kind of excel files with some content like a table or chart.
Below is the list of our other settings, which made the Aspose.cells to throw the exception.
All Margins set to => 9.99
Horizontal and Vertical Resolution set to : 600
OnePagePerSheet = true;
ImageType = ImageType.Png;
Also calling → Worksheet.AutoFitColumns();
As you said, Individually when we apply these settings, there won’t be any issue, but when we combine these settings, we get the exception.
This is a very weird test case in our QA env, The exception is thrown randomly, ex: if we generate the image 10 times, out of 10 , exception is thrown 3 or 4 times. Another observation, When we debug the solution, we see this behavior only in our ‘release’ versions but when we debug the same app in our visual studio IDE in debug mode, it throws the exception consistently.
Thanks,
Prathap