简体   繁体   English

SpecialCells(xlCellTypeConstants)在仅一个像元作为基本范围的情况下导致意外结果

[英]SpecialCells(xlCellTypeConstants) results unexpected result on just one cell as the base range

To summarize: if the base range of the SpecialCells is just one cell, then the result of range .SpecialCells(xlCellTypeConstants, xlNumbers) yields not just that cell or nothing. 总结一下:如果SpecialCells的基本范围只是一个单元格,则range .SpecialCells(xlCellTypeConstants,xlNumbers)的结果不仅生成该单元格,也不生成任何内容。 I supposed, SpecialCells should yield a range inside that object it is applied... or am I wrong? 我猜想,SpecialCells应该在要应用的对象内产生一个范围...还是我错了?

I've "developed" a little new excel book, just to show what I don't understand, as follows: 我已经“开发”了一些新的excel书籍,只是为了显示我不明白的内容,如下所示:

  1. Created a new excel book 创建了一本新的Excel书

  2. Filled the A1:B3, as follows: 填充A1:B3,如下所示:

      AB ... 1 1 12 2 2 22 3 3 32 . 

    All the other cells of the sheet are untouched. 表格中的所有其他单元格都保持不变。

  3. Inside a new module I've added the following code: 在一个新模块中,我添加了以下代码:

     Private Sub test() Dim oSet As Range, oSpec As Range, oUsed As Range Worksheets("Sheet1").Activate Set oSet = ActiveSheet.Range("A1:A1") Set oSpec = oSet.SpecialCells(xlCellTypeConstants, xlNumbers) Set oUsed = ActiveSheet.UsedRange Set oSet = Nothing Set oSpec = Nothing Set oUsed = Nothing End Sub 
  4. Running the subroutine, and stopping it at the first range reset, it yields: 运行该子例程,并在第一次范围重置时将其停止,它将产生:

     oSet.Address = "$A$1" oSpec.Address = "$A$1:$B$3" ' this seems to be wrong; should it be just "$A$1" ? oUsed.Address = "$A$1:$B$3" 
  5. Having been changed the value of A1 to A, rerun the sub, and stop at the same place, it gives (consistently with the previous, which shows it works consequtively): A1的值更改为A,重新运行子项,然后在同一位置停止,它给出了(与前一个一致,这表明它可以正常工作):

     oSet.Address = "$A$1" oSpec.Address = "$B$1","$A$2:$B$3" ' this seems to be wrong; should oSpec be nothing ? oUsed.Address = "$A$1:$B$3" 
  6. However, resetting the value of A1 to the original 1, but changing the range of the first Set operation in the Subroutine from just the cell "A1" to a true range of cells "A1:A2", then rerun the sub, and stop at the place, it gives very different (and more expected) result: 但是,将A1的值重置为原始1,但是将子例程中第一个Set操作的范围从仅单元格“ A1”更改为单元格“ A1:A2”的真实范围,然后重新运行该子级并停止在这个地方,它给出了截然不同的结果(并且还有更多预期):

     oSet.Address = "$A$1:$A$2" oSpec.Address = "$A$1:$A$2" ' this is good oUsed.Address = "$A$1:$B$3" 

I would appreciate, if somebody would explain the results. 如果有人可以解释结果,我将不胜感激。 Thanks ahead. 谢谢你

This is happening because in case of one cell, it considers UsedRange instead. 发生这种情况是因为在一个单元格的情况下,它考虑使用UsedRange。
References: 参考文献:
1) Super secret SpecialCells 1) 超级秘密SpecialCells
2) Using SpecialCells in Excel VBA 2) 在Excel VBA中使用SpecialCells

As a helpful note, I will give you my wrapper function for SpecialCells and its helper method (in C#, not in VBA): 作为有用的注释,我将为您提供SpecialCells的包装函数及其辅助方法(在C#中,在VBA中):

    /// <summary>
    /// <para>Wrapper for SpecialCells function.</para>
    /// </summary>
    /// <param name="inputRange"></param>
    /// <param name="cellType"></param>
    /// <returns></returns>
    /// <remarks>Throws null when there are no cells in <paramref name="inputRange"/> corresponding to <paramref name="cellType"/>, unlike SpecialCells which throws exception</remarks>
    public static Range GetRangeSpecialCells(this Microsoft.Office.Interop.Excel.Range inputRange, XlCellType cellType)
    {
        try
        {
            if (inputRange.Cells.Count == 1)
            {
                if (cellType == XlCellType.xlCellTypeComments)
                {
                    if (inputRange.Comment != null)
                    {
                        return inputRange;
                    }
                    else
                    {
                        return null;
                    }
                }
                else if (cellType == XlCellType.xlCellTypeFormulas)
                {
                    if (inputRange.HasFormula == true)
                    {
                        return inputRange;
                    }
                    else
                    {
                        return null;
                    }
                }
                else if (cellType == XlCellType.xlCellTypeBlanks)
                {
                    if (string.IsNullOrEmpty(inputRange.Value2) == true)
                    {
                        return inputRange;
                    }
                    else
                    {
                        return null;
                    }
                }
                else if (cellType == XlCellType.xlCellTypeLastCell)
                {
                    return inputRange;
                }
                else
                {
                    // since inputRange has a single cell, SpecialCells will apply to entire worksheet
                    // this range has all cells from worksheet (UsedRange) of type provided: cellType
                    Range temp = inputRange.SpecialCells(cellType);

                    // intersect range with single cell (inputRange) with above range
                    Range rangeOverlap = Intersect(inputRange, temp);

                    // if range with single cell is contained in that intersection, then this cell is of type xlCellTypeConstants
                    if (rangeOverlap.Count == inputRange.Count && rangeOverlap.Rows.Count == inputRange.Rows.Count && rangeOverlap.Columns.Count == inputRange.Columns.Count)
                    {
                        return inputRange;
                    }
                    else
                    {
                        return null;
                    }
                }
            }
            else
            {
                return inputRange.SpecialCells(cellType);
            }
        }
        catch (System.Runtime.InteropServices.COMException ex)
        {
            return null;
        }
    }


    /// <summary>
    /// <para>Customized function for intersection of two ranges (<paramref name="rangeA"/> ∩ <paramref name="rangeB"/>)</para>
    /// </summary>
    /// <param name="rangeA"></param>
    /// <param name="rangeB"></param>
    /// <returns>Range corresponding to intersection of the two provided ranges</returns>
    /// <remarks>This function returns null if any of provided ranges is null or malformed, unlike Application.Intersect which throws exception</remarks>
    public static Range Intersect(Range rangeA, Range rangeB)
    {
        Range rngIntersect;
        if (rangeA == null)
        {
            rngIntersect = null;
        }
        else if (rangeB == null)
        {
            rngIntersect = null;
        }
        else if (rangeA.Worksheet != rangeB.Worksheet)
        {
            rngIntersect = null;
        }
        else
        {
            try
            {
                rngIntersect = Globals.ThisAddIn.Application.Intersect(rangeA, rangeB);
            }
            catch (Exception ex)
            {
                rngIntersect = null;
            }
        }

        return rngIntersect;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM