【问题标题】:Detect dependent cells from another sheet从另一个工作表中检测依赖单元格
【发布时间】:2013-05-24 16:05:01
【问题描述】:

这是说明我的问题的简化示例。 我在单元格 A1 公式中的 sheet1 中有:

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

当 sheet2 中的单元格 C1 发生更改时,我想检测所有相关单元格,这意味着 sheet2 中的单元格 B1 和 sheet1 中的单元格 A1。但是 range.Dependents 只返回活动工作表中的单元格。我只得到单元格B1。 在 Range interop API 文档中指出,依赖项将仅返回活动工作表中的范围。 有谁知道如何从所有工作表、其他 API 调用或其他方法中检测所有依赖项?

【问题讨论】:

  • 您使用哪种语言进行互操作 - C# 或 VB.NET(或另一种)?
  • @AndyBrown 我正在使用 C#
  • 我找到了一个解决方案,我在我的内部结构中跟踪感兴趣的细胞,而不是从工作表中读取所有细胞并检测不同的值。

标签: c# excel excel-formula excel-interop


【解决方案1】:

这将是一个很长的代码示例,但基本上您只需要按照箭头进行操作(我假设您使用的是 C#,因为您没有指定用于互操作的语言)。

下面示例的输出是(Sheet1 上有两个单元格来演示如何遍历所有远程引用):

表 1!A1 Sheet1!A2 表 2!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;
    }
}

【讨论】:

  • 这是非常讨厌的方式,因为在执行此操作时用户会看到 excel 中的箭头闪烁,这是我的客户请求无法接受的。我找到了解决方法,但它与这个问题无关,所以我不会把它作为答案。
  • @Vajda。在您执行此类操作时,使用Application.ScreenUpdating 属性关闭屏幕更新是标准做法;因此,这是进行依赖跟踪的常用方法。您没有将其声明为要求,因此我没有包含它,但是如果您需要我可以添加它吗?
  • 该解决方案将比工作。我会选择您的答案作为已接受的答案。
  • @Vajda。 Application.ScreenUpdating = false 还有其他好处,主要是复杂操作的处理速度。您可以就此提出另一个问题,看看人们为什么以及如何使用它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多