C# VSTO Excel NamedRange Change 事件:迭代范围

C# VSTO Excel NamedRange Change event: Iterate the range

我正在为 Excel sheet 创建一个 VSTO 解决方案,它有一个包含 16 行和 3 列(总共 48 个单元格)的命名范围。当这些单元格中的一个被更改时,我需要迭代所有 48 个单元格以进行一些计算。 我试图向 namedRange 添加一个 Change 事件,但问题是这只允许我访问当前更改的单元格。当其中一个被更改时,是否有可能迭代 namedRange 的所有单元格?

谢谢,大卫

这可以通过 SheetChange 事件、一些条件逻辑和命名范围中的枚举器来实现。

为了清楚起见,我已经包含了评论。希望这有帮助。

更新: 包括检查以确保更改的单元格在命名范围内。这样,如果 sheet 上的单元格发生更改但不在 NAMED RANGE 内(以某些条件逻辑为代价),它可以避免不必要的处理。

    //must be declared in scope
    Range myNamedRange;

    private void SetupEventHandlerForRange(Workbook wb, String namedRange)
    {
        //get the Range object of the namedRange
        myNamedRange = wb.Worksheets.GetRangeByName(namedRange);
        //subscribe to the SheetChange event
        this.SheetChange += new
            Excel.WorkbookEvents_SheetChangeEventHandler(
            CheckNamedRangeOnCellChange);
    }

    void CheckNamedRangeOnCellChange(object Sh, Excel.Range Target)
    {
        //get the Worksheet object
        Excel.Worksheet sheet = (Excel.Worksheet)Sh;
        //check if worksheet is the desired sheet name (optional)
        if(sheet.Name == "The Name Of The Sheet You Want To Check")
        {
            //will stay false until it finds a cell in range
            bool cellInRange = false;
            //get the range enumerator for the ALTERED range
            IEnumerator altRangeEnum = Target.GetEnumerator();

            while (altRangeEnum.MoveNext())
            {
                //get the cell object and check if it is in the namedRange
                Cell cell = (Cell)altRangeEnum.Current;
                cellInRange = IsCellIsInRange(cell, myNamedRange);
                //if the cell is in the namedRange break
                //we want to continue if any of the cells altered are in
                //the namedRange
                if(cellInRange) break;
            }

            //changed cell is not in namedRange, return
            if(!cellInRange) return;

            //get the range enumerator
            IEnumerator rangeEnum = myNamedRange.GetEnumerator();

            while (rangeEnum.MoveNext())
            {
                Cell cell = (Cell)rangeEnum.Current;
                //do something with cell
            }
        }
    }

    public bool IsCellInRange(Cell cell, Range range)
    {
        if (cell.Row < range.Row ||
            cell.Row > range.Column ||
            cell.Column < range.Row + range.Rows.Count - 1 ||
            cell.Column > range.Column + range.Columns.Count - 1)
        {
              //cell is outside the range we want to check
              return false;
        }
        else
        {
            return true;
        }
    }