I'm trying to convert each sheet of an excel file to an image using excel.Interop. What I have so far is
var a = new Microsoft.Office.Interop.Excel.Application();
try
{
Workbook w = a.Workbooks.Open(@"C:\Path\to\excelFile.xlsx");
foreach (Worksheet ws in w.Sheets)
{
string range = ws.PageSetup.PrintArea;
ws.Protect(Contents: false);
Range r = ws.UsedRange;
r.CopyPicture(XlPictureAppearance.xlScreen, XlCopyPictureFormat.xlBitmap);
Bitmap image = new Bitmap(System.Windows.Forms.Clipboard.GetImage());
string BitmapName = ws.Name;
image.Save($@"C:\Path\to\bitmapsToSave\{BitmapName}.bmp");
}
a.DisplayAlerts = false;
w.Close(SaveChanges: false);
}
finally
{
a.Quit();
}
And I happen to get an image from the clipboard, which uses the range.CopyPicture method. The thing is that the range I'm getting contains some blank cells, and I read somewhere that once a cell is accessed will extend the range even if it's blank.
That means that my bitmap outputs contain a blank offset which I don't want. I'm trying to select the exact range and I've tried the following
Range r = ws.UsedRange.SpecialCells(XlCellType.xlCellTypeAllFormatConditions);
And this returns my table without headers. I don't know why, but it has something to do with them being frozen
also I tried clearing my sheet of formatting before copying range into clipboard
ws.Columns.ClearFormats();
ws.Rows.ClearFormats();
this works okay, but my table now lost all of the nice formatting it had. (Which also means this works for non-formatted tables, which is nice)
I'm trying to copy the ws instance into a new one, get the cleared Range from it, and copy it to the actual sheet but I can't access them properly
//creates a copy of the worksheet to extract its range
Worksheet _ws = ws;
//These two lines do the magic.
_ws.Columns.ClearFormats();
_ws.Rows.ClearFormats();
Range _r = _ws.UsedRange;
//Copies range of aux ws into current ws
_r.Copy(r);
This returns the same output of the previous case, a correct cropped range but the image has no excel formatting.
The last thing I have not tried and that's because I don't know why, is to access to the Print Area and cast it somehow as a range.
I want to know how to do this or what I'm doing wrong.
EDIT:
basically with interop
opens an excel file with a table on each sheet
for each sheet get UsedRange of sheet as a Range object
pass that range into clipboard
using Copypicture save Clipboard to a bmp image
close file
the range that interop picks is bigger than the one that actually contains data, because if I click on a cell and delete its contents will still be considered as it contains data.
this results in bitmaps that contain my tables, but also a lot of white cells around because they had data once, but not anymore.
Code is in https://github.com/diegoquintanav/Excel2BMP