使用C#Interop.Excel从NamesManager中删除重复的名称

时间:2013-09-07 00:14:50

标签: c# excel excel-interop

我在使用C#代码从NAmesManager中删除名称时遇到了一些问题。 根据我的要求,我需要从名称管理器中删除所有无效的名称。我目前正在检查Name的值,如果值为“#REF!”则将其删除。这是我正在使用的代码

foreach (Name RangeName in namesManager2)
                {

                    if(RangeName.Value.Contains("#REF!")) 
                    {
                        RangeName.Delete();
                    }
                 }

代码工作正常,但是有一些奇怪的情况,其中存在2个具有相同名称但名称不同的名称。 考虑单元格1被命名为“TESTNAME”,其范围为“Workbook”,单元格2也被命名为“TESTNAME”,范围为“Sheet1”。引用Cell2的名称具有有效值。

所以当我循环时如果名字带有“#REF!”遇到上面的代码是删除这两个名称。我想保留名称的有效值,但只删除无效的名称。

有人可以建议如何实现这个目标吗?

3 个答案:

答案 0 :(得分:1)

存在重复的本地/全球名称的错误 在活动工作表具有该工作表的本地名称相同的名称时访问全局名称将更改本地名称的属性而不是全局名称,即使该名称完全符合工作簿名称。

所以要绕过这个你必须:
- 检测姓名是否重复 - 如果是这样切换到不是本地名称的父项的工作表(当然可能有多个本地名称,每张表上有一个,所以唯一真正安全的方法是添加另一个临时工作表并切换到该名称)
- 然后在工作簿名称集合或工作表名称集合中访问您想要的任何名称。

这是由JK Pieterse和我开发的免费赠送名称管理器Addin所使用的技术:
Name manager Download
它具有比内置名称管理器更多的功能

答案 1 :(得分:0)

我建议您使用名称范围的唯一名称来避免此类问题。

var activeBook = (Workbook)currentInstance.ActiveWorkbook;
Range rnArea = activeSheet.Range["A1:A1"];
activeBook.Names.Add("TESTNAME", rnArea);
rnArea = activeSheet.Range["B1:B1"];
activeSheet.Names.Add("TESTNAME", rnArea);

List<Name> existingNamedRangeList1 = XlHelper.GetNamedRanges(currentInstance.ActiveWorkbook);
foreach (Name RangeName in existingNamedRangeList1)
{
    if (RangeName.Value.Contains("#REF!"))
    {
        RangeName.Delete();
    }
}

答案 2 :(得分:0)

不幸的是,看起来它假设Name是唯一的,因此任何Deletes完成都不会有预期的行为。解决此问题的一种方法是在遍历所有RangeNames时生成唯一名称,然后在完成删除后将其重置回原始名称。

var rangeNameHolder = new Dictionary<string, string>();
var rangeNames = activeBook.Names;
int counter = 0;
foreach (Name rangeName in rangeNames)
{
    var oldName = rangeName.Name;
    /*
     * This hack here is done because when you grab the name, it includes the prepended scope. 
     * However, when you set the name, it prepends the scope yet again! 
     * So when you grab it the first time you need to remove the scope so that it doesnt get
     * prepended twice
     */
    oldName =oldName.Substring(oldName.LastIndexOf('!')+1);
    var newName = string.Format("{0}{1}", oldName, counter++);
    rangeName.Name = newName;
    if (rangeName.Value.Contains("#REF!"))
    {
        rangeName.Delete();
        continue;
    }
    rangeNameHolder.Add(rangeName.Name,oldName);
}

//Reset names back to original
foreach (Name rangeName in rangeNames)
{
    if (rangeNameHolder.ContainsKey(rangeName.Name))
        rangeName.Name = rangeNameHolder[rangeName.Name];
}