这个技巧是否有任何缺陷通过调用Evaluate来检查表单是否存在?

我需要检查给定工作簿中是否存在具有某个特定名称的工作表。

天真的做法是这样的:

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

但是这个例外令人讨厌。 这是浪费我的时间一次又一次,而我的程序debugging其他无关的部分。

我也想避免遍历工作簿的每个工作表,比较名称。 这在我看来是非常低效的。

经过一番研究,我做出了这个解决scheme,whis是基于这样一个事实:Evaluate()在失败而不是抛出exception时返回一个错误代码:

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

但是,如果在Excel中激活“R1C1参考样式”(菜单:工具/选项/常规),则失败。 考虑到这一点…

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

我知道我可以先检查ReferenceStyle,然后用正确的风格调用一次Evaluate()。 就像是:

 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; 

无论如何,我的问题是: 我的ContainsSheet()函数有没有其他的缺陷?

更新 :这里提出的方法需要非常短的时间(大约30 us)时,表存在,但很长一段时间,它不存在(约150 us)。 Evaluate()必须在内部激发和捕捉exception。 相反,按照下面的DGibbs的build议迭代Sheets集合,当只有几张纸(13 us,无论纸张是否存在)时甚至需要更短的时间。 但是这些时间随着纸张的数量而增长。 有77页,如果search到的页面是最后一个或者不存在的页面,迭代大约需要200 us。 但是,这是很多床单!

你可不可以这样做:

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

更简单,是一个方便的扩展方法。

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