Home » excel » c# – Detect dependent cells from another sheet

c# – Detect dependent cells from another sheet

Posted by: admin May 14, 2020 Leave a comment

Questions:

This is simplified example that illustrates my problem.
I have in my sheet1 in cell A1 formula:

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

And when cell C1 from sheet2 is changed, I want to detect all dependent cells, that means cell B1 from sheet2 and cell A1 from sheet1. But range.Dependents only returns cells from Active sheet. and I get only cell B1.
In Range interop API documantation is stated that dependents will return only ranges from active sheet.
Does anyone knows way how to detect all dependencies from all sheets, some other API call, or some other approach?

How to&Answers:

This is going to be a long code sample, but basically you just need to follow the arrows (I’m assuming you are using C#, as you haven’t specified a language that you are using for the interop).

The output from the sample below is (there are two cells on Sheet1 to demonstrate how you walk all the remote references):

    Sheet1!A1
    Sheet1!A2
    Sheet2!B1

Health warning. This sample doesn’t do any interop cleanup or app closing – this is for demonstration only

Edit Use Application.ScreenUpdating to prevent screen flicker during the tracing function.

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