通过调用Evaluate来检查工作表是否存在的技巧是否存在缺陷
本文关键字:存在 是否 缺陷 工作 调用 Evaluate 检查 | 更新日期: 2023-09-27 18:18:14
我需要检查给定的工作簿中是否存在具有某些特定名称的工作表
简单的方法是:
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;
}
}
但是那个例外很烦人。它一次又一次地浪费了我调试程序中其他不相关部分的时间。
我还想避免遍历工作簿的每个工作表,比较名称。在我看来,这种做法效率极低。
经过一番研究,我想出了这个解决方案,它是基于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;
}
但是如果在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()函数?
UPDATE:此处提出的方法在表单存在时花费的时间很短(约30 us),但在表单不存在时花费的时间很长(约150 us)。Evaluate()必须在内部触发并捕获异常。相反,正如下面DGibbs所建议的那样,当只有几个表(13个,不管表是否存在)时,迭代遍历Sheets集合所需的时间甚至更短。但这些时间随着纸张数量的增加而增加。对于77个表,如果搜索的表是最后一个表或不存在,迭代大约需要200个操作。然而,那是很多床单!
你能不能这样做:
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");