简体   繁体   English

通过调用“评估”检查工作表是否存在,此技巧是否存在任何缺陷?

[英]Is there any flaw in this trick to check whether a sheet exists by calling Evaluate?

I need to check whether a sheet with some specific name exists in a given workbook. 我需要检查给定工作簿中是否存在具有某些特定名称的工作表。

The naive way to do this is something like: 天真的方法是这样的:

using Excel = Microsoft.Office.Interop.Excel;

bool ContainsSheet (Excel.Workbook workbook, string sheetName)
{
    try
    {
        Excel.Worksheet sheet = workbook.get_Item(sheetName)
                                as Excel.Worksheet;
        return sheet != null;
    }
    catch (System.Runtime.InteropServices.COMException ex)
    {
        return false;
    }
}

But that exception is annoying. 但是这种例外很烦人。 It is wasting my time once and again while debugging other unrelated parts of my program. 在调试程序的其他不相关部分时,这一次又一次地浪费了我的时间。

I also want to avoid iterating through every worksheet of the workbook, comparing names. 我还想避免在工作簿的每个工作表中都进行迭代,以比较名称。 That looks to me profoundly inefficient. 在我看来,这是非常低效的。

After some research, I made up this solution, whis is based on the fact that Evaluate() returns an error code when it fails instead of throwing an exception: 经过研究,我组成了这个解决方案,这是基于以下事实:Evaluate()在失败时返回错误代码,而不是引发异常:

using Excel = Microsoft.Office.Interop.Excel;

bool ContainsSheet (Excel.Workbook workbook, string sheetName)
{
    // Sadly, I need a sheet to call Evaluate

    Excel.Worksheet someSheet = workbook.Worksheets[1]
                                as Excel.Worksheet;

    if (someSheet == null)   // Is this even possible?
        return false;

    // Try to get a range referring the first cell (upper-left corner). Note that
    // Evaluate() returns a number if an error occurs...

    Excel.Range someRange = someSheet.Evaluate("\'"+sheetName+"\'!A1")
                            as Excel.Range;

    return someRange != null;
}

But this fails if the "R1C1 reference style" is activated in Excel (menu: Tools / Options / General). 但是,如果在Excel中激活了“ R1C1参考样式”,则此操作将失败(菜单:工具/选项/常规)。 Taking that into account... 考虑到这一点...

using Excel = Microsoft.Office.Interop.Excel;

bool ContainsSheet (Excel.Workbook workbook, string sheetName)
{
    // Sadly, I need a sheet to call Evaluate

    Excel.Worksheet someSheet = workbook.Worksheets[1]
                                as Excel.Worksheet;

    if (someSheet == null)   // Is this even possible?
        return false;

    // Try to get a range referring the first cell (upper-left corner). Note that
    // Evaluate() returns a number if an error occurs...

    Excel.Range someRange = someSheet.Evaluate("\'"+sheetName+"\'!A1")
                            as Excel.Range;

    if (someRange != null)
        return true;

    // Try again with the alternative "R1C1 reference style", which can be activated
    // in the menu: Tools / Options / General

    someRange = someSheet.Evaluate("\'"+sheetName+"\'!R1C1")
                as Excel.Range;

    return someRange != null;
}

I know I could check ReferenceStyle first and then call Evaluate() just once with the correct style. 我知道我可以先检查ReferenceStyle,然后使用正确的样式调用Evaluate()一次。 Something like: 就像是:

Excel.Application excel = ExcelDna.Integration.ExcelDnaUtil.Application as Excel.Application;
System.Nullable<Excel.XlReferenceStyle> style = excel.ReferenceStyle as System.Nullable<Excel.XlReferenceStyle>;
string corner = style == null                          ? null :
                style == Excel.XlReferenceStyle.xlA1   ? "A1" :
                style == Excel.XlReferenceStyle.xlR1C1 ? "R1C1" : null;

Anyway, my question is: Is there any other flaw in my ContainsSheet() function? 无论如何,我的问题是: ContainsSheet()函数是否还有其他缺陷?

UPDATE : The method proposed here takes a very short time (about 30 us) when the sheet exists, but a long time when it does not exist (about 150 us). 更新 :当工作表存在时,此处提出的方法需要很短的时间(大约30 us),而当工作表不存在时,则需要很长时间(大约150 us)。 Evaluate() must be provoking and catching an exception internally. Evaluate()必须在内部引发并捕获异常。 Instead, iterating through the Sheets collection, as proposed by DGibbs below, takes even shorter times when there are just a few sheets (13 us, no matter whether the sheet exists or not). 相反,如下面的DGibbs所建议的那样,在Sheets集合中进行迭代时,如果只有几张图纸(无论是否存在,则为13 us),花费的时间甚至更短。 But these timings grow with the number of sheets. 但是,这些时间随印张数量的增加而增加。 With 77 sheets, if the sheet searched is one of the last ones or does not exist, iterating takes about 200 us. 使用77张纸,如果搜索到的纸是最后一张纸或不存在,则迭代大约需要200 us。 However, that's a lot of sheets! 但是,床单很多!

Could you not do something like: 你能不能做这样的事情:

public static bool ContainsSheet(this Excel.Workbook workbook, string sheetName)
{
     if(workbook.Sheets == null || !workbook.Sheets.Any())
           return false;

     foreach (var sheet in workbook.Sheets)
     {
          if (sheet.Name.Equals(sheetName))
          {
               return true;
          }
     }

     return false;
}

Much simpler and is a handy extension method. 简单得多,并且是一种方便的扩展方法。

var hasSheet = workbook.ContainsSheet("foo");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 检查是否选择了整张纸? - Check whether whole sheet is selected or not? 我的算法中的缺陷在哪里找出是否存在两个数组A,B的排列,使得它们具有(A [i] + B [i])&gt; = k - Where is the flaw in my algorithm to find whether there exists a permutation of two arrays A,B such that they have (A[i]+B[i]) >= k 如何在调用函数之前检查函数“ App.ServisTanimId.getValue”是否作为属性存在? - How to check whether the function “App.ServisTanimId.getValue” exists as a property before calling it? 检查Excel工作表中是否存在列 - check if a column exists in Excel sheet 检查是否正在播放动画 - Check whether any animation is playing or not 我在确定是否存在一个整数N从而使x1 + v1 * N = x2 + v2 * N时存在缺陷的地方在哪里? - Where is my flaw in determining whether there exists an int N such that x1 + v1 * N = x2 + v2 * N 检查SQL表中是否存在值 - Check whether value exists in SQL table 使用Jquery检查电子邮件是否存在于数据库中 - To check whether the email exists in database using Jquery 如何动态检查数组中的索引是否存在? - How to check dynamically whether an index in the array exists or not? 如何检查输入的表是否存在于数据库中? - how to check whether the entered table exists in database?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM