2

C# コードで NAmesManager から名前を削除する際に問題に直面しています。私の要件に従って、Names Manager からすべての無効な名前を削除する必要があります。現在、名前の値を確認して、値が「#REF!」の場合は削除しています。これは私が使用しているコードです

foreach (Name RangeName in namesManager2)
                {

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

コードは正常に動作しますが、名前が同じでスコープが異なる 2 つの名前が存在するという奇妙な状況がいくつかあります。セル 1 の名前が「TESTNAME」でスコープが「Workbook」で、セル 2 の名前も「TESTNAME」でスコープが「Sheet1」であるとします。Cell2 を参照する名前には有効な値があります。

そのため、「#REF!」を含む名前の場合はループしています。値が検出された場合、上記のコードは両方の名前を削除しています。有効な値を持つ名前を保持したいが、無効な名前だけを削除したい。

誰かがこれを達成する方法を提案できますか?

4

3 に答える 3

1

ローカル/グローバル名が重複しているバグがあります。
アクティブなシートがそのシートに対してローカルで同じ名前の名前を持っているときにグローバル名にアクセスすると、名前がワークブック名​​で完全に修飾されていても、グローバル名ではなくローカル名のプロパティが変更されます。

したがって、これを回避するには、次のことを行う必要があります:
- 名前が重複しているかどうかを検出します - 重複
している場合は、ローカル名の親ではないワークシートに切り替えます (もちろん、各シートに 1 つずつ、複数のローカル名が存在する可能性があります。安全な方法は、別の一時的なワークシートを追加してそれに切り替えることです)
- 次に、ワークブック名​​コレクションまたはワークシート名コレクションのいずれかで必要な名前にアクセスします。

これは、JK Pieterse と私が開発した無料の Name Manager Addin で使用される手法です。
Name manager Download
組み込みの Name Manager よりも多くの機能を備えています。

于 2013-09-12T15:09:27.277 に答える
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();
    }
}
于 2013-09-10T00:08:30.873 に答える
0

残念ながら、名前が一意であると想定しているように見えます。そのため、実行された削除は期待どおりの動作をしません。これを回避する 1 つの方法は、すべての 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];
}
于 2013-09-11T14:48:46.627 に答える