Table ListObject不限于表行,而是计算整个表

时间:2016-03-13 14:55:47

标签: excel vba excel-vba with-statement

我使用insert / table命令在excel中创建了两个命名表,并将它们命名为如下所示。在excel中看起来都很好。表House_details的行数为50,包括标题行和Sale_price_schedule 15的行数,包括标题行。

我的相关vba代码是

        Set tblHouseDetails = Sheets("House details").ListObjects("House_details")
        Set tblSalePriceSchedule = Sheets("Sale price schedule").ListObjects("Sale_price_schedule")
        'Find the product type, look for the relevant price and insert it into the appropriate house details column
        With tblHouseDetails.DataBodyRange
            For iCount = 2 To Rows.Count
                iTemp = Rows.Count
                strProductType = Cells(iCount, 5).Value 'The fifth columns is the product type
                dSaleDate = Cells(iCount, 3).Value 'The third column is the sale date
                'Find the correct sale price in the SalePriceSchedule
                '----------------------------
                dblSalePrice = -999
                With tblSalePriceSchedule.DataBodyRange
                    iTemp = Rows.Count
                    For iCount2 = 2 To Rows.Count
                        If Cells(iCount2, 3) = strProductType And Cells(iCount2, 1) <= dSaleDate And Cells(iCount2, 2) >= dSaleDate Then
                            dblSalePrice = Cells(iCount2, 4)
                        End If


                    Next iCount2
                End With
                '------------------------------
                Cells(iCount, 6) = dblSalePrice
            Next iCount
        End With

我的问题是tblHouseDetails行数不是我在Excel中定义的50行,而是整张表(1048576)。

为什么我的Rows.Count不正确?

2 个答案:

答案 0 :(得分:1)

当&#34;行&#34;和&#34;细胞&#34;单独使用,它们指的是&#34; ActiveSheet.Rows&#34;和&#34; ActiveSheet.Cells&#34;。

如果您想参考&#34; With.DataBodyRange&#34;中的范围,您需要在前面添加一个点(&#34; .Rows&#34;,&#34; .Cells&#34 ):

Set tblHouseDetails = Sheets("House details").ListObjects("House_details")
Set tblSalePriceSchedule = Sheets("Sale price schedule").ListObjects("Sale_price_schedule")
'Find the product type, look for the relevant price and insert it into the appropriate house details column
With tblHouseDetails.DataBodyRange
    For iCount = 1 To .Rows.Count
        iTemp = .Rows.Count
        strProductType = .Cells(iCount, 5).Value 'The fifth columns is the product type
        dSaleDate = .Cells(iCount, 3).Value 'The third column is the sale date
        'Find the correct sale price in the SalePriceSchedule
        '----------------------------
        dblSalePrice = -999
        With tblSalePriceSchedule.DataBodyRange
            iTemp = .Rows.Count
            For iCount2 = 1 To .Rows.Count
                If .Cells(iCount2, 3) = strProductType And .Cells(iCount2, 1) <= dSaleDate And .Cells(iCount2, 2) >= dSaleDate Then
                    dblSalePrice = .Cells(iCount2, 4)
                End If
            Next iCount2
        End With
        '------------------------------
        .Cells(iCount, 6) = dblSalePrice
    Next iCount
End With

但更好的解决方案是将行用作变量:

Dim rowsA As Range, rowsB As Range
Set rowsA = tblHouseDetails.DataBodyRange.Rows
Set rowsB = tblSalePriceSchedule.DataBodyRange.Rows

'Find the product type, look for the relevant price and insert it into the appropriate house details column
For i = 1 To rowsA.Count
  strProductType = rowsA.Cells(i, 5).Value 'The fifth columns is the product type
  dSaleDate = rowsA.Cells(i, 3).Value 'The third column is the sale date

  'Find the correct sale price in the SalePriceSchedule
  dblSalePrice = -999
  For j = 1 To rowsB.Count
    If rowsB.Cells(j, 3) = strProductType And rowsB.Cells(j, 1) <= dSaleDate And rowsB.Cells(j, 2) >= dSaleDate Then
        rowsA.Cells(i, 6) = rowsB.Cells(j, 4)
    End If
  Next
Next

如果你正在寻找的是一个高性能的解决方案,我会使用数组中的值:

Dim dataA(), dataB(), i&, j&, strProductType$, dSaleDate, dblSalePrice

' Get all the values in an array
dataA = Sheets("House details").ListObjects("House_details").DataBodyRange.Value
dataB = Sheets("Sale price schedule").ListObjects("Sale_price_schedule").DataBodyRange.Value
For i = 0 To UBound(dataA)
  strProductType = dataA(i, 4) 'The fifth columns is the product type
  dSaleDate = dataA(i, 2) 'The third column is the sale date

  'Find the correct sale price in the SalePriceSchedule
  dblSalePrice = -999
  For j = 0 To UBound(dataB)
    If dataB(j, 2) = strProductType And dataB(j, 0) <= dSaleDate And dataB(j, 1) >= dSaleDate Then
        dataA(i, 5) = dataB(j, 3)
    End If
  Next
Next

' Copy the values back to the sheet
Sheets("House details").ListObjects("House_details").DataBodyRange.Value = dataA

答案 1 :(得分:0)

您正在House_details ListObject的.DataBodyRange property内工作。 With ... End With statement内部使用的所有引用都需要以句点(又名句号.)开头,以便传递父引用。

Rows.Count需要.Rows.CountCells(iCount2, 3)需要.Cells(iCount2, 3)等。

一旦您输入嵌套的With ... End With,Range.Parent property会转移到Sale_price_schedule表,这些Range.CellsRange.Rows属性需要相同的语法才能将其父引用调整为Sale_price_schedule表。

所有Cells(...)Rows.Count来电均默认为ActiveSheet property,没有前置时段。

    Set tblHouseDetails = Sheets("House details").ListObjects("House_details")
    Set tblSalePriceSchedule = Sheets("Sale price schedule").ListObjects("Sale_price_schedule")
    'Find the product type, look for the relevant price and insert it into the appropriate house details column
    With tblHouseDetails.DataBodyRange
        For iCount = 2 To .Rows.Count
            iTemp = .Rows.Count
            strProductType = .Cells(iCount, 5).Value 'The fifth columns is the product type
            dSaleDate = .Cells(iCount, 3).Value 'The third column is the sale date
            'Find the correct sale price in the SalePriceSchedule
            '----------------------------
            dblSalePrice = -999
            With tblSalePriceSchedule.DataBodyRange
                iTemp = .Rows.Count
                For iCount2 = 2 To .Rows.Count
                    If .Cells(iCount2, 3) = strProductType And .Cells(iCount2, 1) <= dSaleDate And .Cells(iCount2, 2) >= dSaleDate Then
                        dblSalePrice = .Cells(iCount2, 4)
                    End If


                Next iCount2
            End With
            '------------------------------
            .Cells(iCount, 6) = dblSalePrice
        Next iCount
    End With

在相关说明中,检索Range.Row属性将检索工作表上的实际行,并且必须通过.HeaderRowRange property的行进行调整,以返回表中的行位置。