1

これは、私の問題を示す簡単な例です。私はセルA1式のシート1に持っています:

sheet1!A1 cell has formula '=sheet2!C1'
sheet2!B1 cell has formula '=C1'

そして、シート2のセルC1が変更された場合、すべての依存セル、つまりシート2のセルB1とシート1のセルA1を検出したいと考えています。ただし、range.Dependents はアクティブ シートのセルのみを返します。セルB1のみを取得します。Range interop API のドキュメントでは、従属オブジェクトはアクティブなシートからの範囲のみを返すと記載されています。すべてのシート、他の API 呼び出し、または他のアプローチからすべての依存関係を検出する方法を知っている人はいますか?

4

1 に答える 1

3

これは長いコード サンプルになりますが、基本的には矢印に従うだけです (相互運用に使用する言語を指定していないため、C# を使用していると想定しています)。

以下のサンプルの出力は次のとおりです (Sheet1 には、すべてのリモート参照をどのようにウォークするかを示すために 2 つのセルがあります)。

    Sheet1!A1
    シート 1!A2
    Sheet2!B1

健康警告。このサンプルでは、​​相互運用のクリーンアップやアプリの終了は行われません。これはデモンストレーションのみを目的としています。

編集Application.ScreenUpdatingトレース機能中の画面のちらつきを防止するために使用します。

using xl = Microsoft.Office.Interop.Excel;
// use in a console app
class Program
{
    static void Main(string[] args)
    {
        xl.Application app = new xl.Application();
        app.Visible = true;
        xl.Workbook wb = app.Workbooks.Add();
        xl.Worksheet worksheet1 = wb.Sheets[1];
        xl.Worksheet worksheet2 = wb.Sheets[2];
        xl.Range rngS1A1 = worksheet1.Range["A1"];
        xl.Range rngS1A2 = worksheet1.Range["A2"];
        xl.Range rngS2B1 = worksheet2.Range["B1"];
        xl.Range rngS2C1 = worksheet2.Range["C1"];

        rngS1A1.Formula = @"=sheet2!C1";
        rngS1A2.Formula = @"=sheet2!C1";
        ((xl._Worksheet)worksheet2).Activate();
        rngS2B1.Formula = @"=C1";

        List<string> dependentAddresses = ListDependents(rngS2C1);

        foreach (string address in dependentAddresses)
        {
            Console.WriteLine(address);
        }
        Console.WriteLine("done, press enter to exit");
        Console.ReadLine();
    }

    private static List<string> ListDependents(xl.Range sourceRange)
    {
        sourceRange.ShowDependents(false);
        string sourceAddress = sourceRange.Worksheet.Name + "!" + sourceRange.Address;
        int arrowNumber = 1;
        List<string> dependentAddresses = new List<string>();
        do
        {
            string targetAddress = null;
            int linkNumber = 1;
            do
            {
                try
                {
                    xl.Range target = sourceRange.NavigateArrow(TowardPrecedent: false, ArrowNumber: arrowNumber, LinkNumber: linkNumber++);
                    targetAddress = target.Worksheet.Name + "!" + target.Address;

                    if (sourceAddress == targetAddress) break;

                    dependentAddresses.Add(targetAddress);
                }
                catch (COMException cex)
                {
                    if (cex.Message == "NavigateArrow method of Range class failed")
                    {
                        break;
                    }
                    throw;
                } 
            } while (true);
            if (sourceAddress == targetAddress) break;
            arrowNumber++;
        } while (true);

        sourceRange.Worksheet.ClearArrows();
        return dependentAddresses;
    }
}
于 2013-05-23T19:45:48.597 に答える