检索UsedRange而不使用空白单元

时间:2017-03-21 14:40:26

标签: c# excel excel-interop

我尝试使用excel.Interop将每张excel文件转换为图像。到目前为止我所拥有的是

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();
        }

我碰巧从剪贴板中获取了一个图像,它使用了range.CopyPicture方法。问题是我得到的范围包含一些空白单元格,我读到某处,一旦访问单元格,即使它是空白的,也会扩展范围。

这意味着我的位图输出包含一个我不想要的空白偏移量。我试图选择确切的范围,我尝试了以下

Range r = ws.UsedRange.SpecialCells(XlCellType.xlCellTypeAllFormatConditions);

这会返回没有标题的表格。我不知道为什么,但它与被冻结有关

我还尝试在将范围复制到剪贴板之前清除我的格式化文件

ws.Columns.ClearFormats();
ws.Rows.ClearFormats();

这个工作没问题,但我的桌子现在丢失了所有漂亮的格式。 (这也意味着这适用于非格式化的表,这很好)

我试图将ws实例复制到新实例中,从中获取已清除的范围,然后将其复制到实际工作表但我无法正确访问它们

//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);    

这将返回前一个案例的相同输出,正确的裁剪范围,但图像没有Excel格式。

我没有尝试过的最后一件事,因为我不知道为什么,是访问打印区域并以某种方式将其投射为范围。

我想知道如何做到这一点或我做错了什么。

编辑:

基本上与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

互操作选择的范围大于实际包含数据的范围,因为如果我单击一个单元格并删除其内容仍将被视为包含数据。

这导致包含我的表的位图,但周围还有很多白色单元,因为它们只有一次数据,但不再存在。

代码位于https://github.com/diegoquintanav/Excel2BMP

2 个答案:

答案 0 :(得分:1)

我认为它与UsedRange返回的范围有关。此方法似乎正常工作,但我的理解是该方法可能返回在使用范围的左侧或右侧的顶部,底部和/或空列中存在空行的范围。您在下面的评论描述了这种情况。

  

_“我读到某处,一旦访问一个单元格,即使它是空白的,也会扩展范围。”

我个人从来没有经历过这种情况,当这种情况确实发生在其他人身上时......在我见过的几乎所有情况下,当一个看似空的单元格有某种不正常的格式或不可见的字符时,问题就解决了。如果使用的范围返回实际数据上方,下方或左侧的空行或列,则其中一个单元格中存在某些内容。此外,应该很明显WHICH单元格具有此不可见的数据或格式。例如:

如果在使用范围的TOP处有“明显的”空行或使用范围的LEFT的“明显”空列,则TOP / LEFT单元格具有不可见数据或某种非“正常”该行和/或列中的一个或多个单元格中的单元格格式。

如果在使用范围的BOTTOM处有“明显”的空行或在使用范围的右边有“明显”空列,则BOTTOM / RIGHT单元格具有不可见数据或某种非“正常”该行和/或列中的一个或多个单元格中的单元格格式。

打开Excel工作表并选择上面的一个问题单元格以删除任何数据并清除任何格式,最少会删除空行,列或两者。

检查那些“明显的”空单元格。删除内容,并清除所有格式,并查看使用的范围是否无法按预期工作。

修改:删除额外的行和列

由于存在大量会导致usedRange属性返回这些空行和列的事物,这包括合并的单元格,最简单的方法是完全“删除”单元格。幸运的是,图片显示了您需要删除的行数或列数。

使用您发布的链接中名为Cont4的工作表作为示例,UsedRange在右侧返回十(10)个额外的空列,在底部返回39个空行。我在col AA的某个地方找到了一个合并的单元格。我们可以尝试在逐个单元的基础上找出导致这种情况的原因,但是可以更容易地简单地选择从列“R”开始到列“AA”或任何列PAST列“AA”的所有列。换句话说,选择数据右侧的10个或更多列。选中这些列后,右键单击选择并选择“删除”。这显然应该删除那些单元格中的任何格式/合并并解决问题。同样的事情适用于底部的空行,在数据下方选择至少39行或更多行,然后右键单击选择并选择“删除”。

顶行有点不同。如果工作表顶部有一个或多个空行,则将从UsedRange返回一个额外的顶部空行。除非我删除了所有空的顶行,否则我无法摆脱这个额外的顶行。

最后,我在上一条评论中指出的代码将删除这些空行和列以及顶部额外行,因为它完全忽略格式化和合并,并将删除任何完全为空的行而不考虑格式。只要你有代码为你工作,那就是最重要的。祝你好运。

答案 1 :(得分:0)

我终于使用

中的答案设法正确获取位图

How to find first and last cell in ExcelInterop and graph range in C#

我替换了

 Range r = ws.UsedRange;

使用

 Range r = ws.get_Range("B2", System.Type.Missing).CurrentRegion;

我必须假设每个工作表上的每个表都在同一个Cell中开始,在本例中为B2。这给了我应有的每个位图。