【问题标题】:Pasting an array of values over a ListObject (Excel table) destroys the Listobject将一组值粘贴到 ListObject(Excel 表)上会破坏 Listobject
【发布时间】:2015-03-21 02:47:33
【问题描述】:

在我的一个工作表中,我有一个

Private Sub BuggingVba()

应该用一组值替换表中的数据

    Dim MyTable As ListObject, myData() As Variant
    Set MyTable = Me.ListObjects(1)
    myData = collectMyData ' a function defined somewhere else in my workbook

这可能无关紧要,但在这样做之前,我调整了列表对象的大小 (我逐行扩展,因为如果我一次这样做,我会覆盖我的表格下方的内容切换它。)

    Dim current As Integer, required As Integer, saldo As Integer
    current = MyTable.DataBodyRange.Rows.Count
    required = UBound(sourceData, 1) - LBound(sourceData, 1)
    ' current and required are size of the body, excluding the header

    saldo = required - current

    If required < current Then
        ' reduce size
        Range(DestinBody.Rows(1), DestinBody.Rows(current - required)).Delete xlShiftUp
    Else
        ' expland size
        DestinBody.Rows(1).Copy
        For current = current To required - 1
            DestinBody.Rows(2).Insert xlShiftDown
        Next saldo
    End If

如果要插入任何数据,我会覆盖这些值

    If required Then
        Dim FullTableRange As Range
        Set FullTableRange = MyTable.HeaderRowRange _
            .Resize(1 + required, MyTable.HeaderRowRange.Columns.Count)
        FullTableRange.Value = sourceData
    End If

然后 BAM,我的 table/ListObject 不见了!为什么会发生这种情况,我该如何避免?

End Sub

【问题讨论】:

  • 你试过不覆盖标题吗?
  • 我想过MyTable.DataRange = slice(1 + souceData, LBound(sourceData, 1), UBound(sourceData, 1)),@Rory,但是1. VBA 没有切片功能2. 我也必须更新我的标题。
  • 那么在最后添加表格可能很容易。
  • 我可以,但我应该先保存使用的排序和过滤,然后再重建它。
  • 我现在通过逐个单元格更新来纠正它。这样可行。 @Rory,如果没有更好的解决方案,您认为值得将其作为解决方案输入,还是我应该删除问题?

标签: excel excel-2010 listobject vba


【解决方案1】:

当我们粘贴整个表格或清除整个表格的内容时,附带的结果是表格对象(ListObject)被删除。这就是代码在逐行更改数据时起作用的原因。

但是,如果我们使用ListObject 的属性,则不需要逐行进行,甚至不需要插入新行,如下面的代码所示。

在这些过程中,我们假设 “目标” Table“新数据” 在同一个 workbook 中保存代码,位于工作表12 分别为:

由于我们将使用ListObjectHeaderRowRangeDataBodyRange,因此我们需要获取“新数据”以以相同的方式替换表中的数据。下面的代码将生成两个包含 Header 和 Body Arrays 的数组。

Sub Dta_Array_Set(vDtaHdr() As Variant, vDtaBdy() As Variant)
Dim vArray As Variant
    With ThisWorkbook.Worksheets("Sht(1)").Range("DATA") 'Change as required
        vArray = .Rows(1)
        vDtaHdr = vArray
        vArray = .Offset(1, 0).Resize(-1 + .Rows.Count)
        vDtaBdy = vArray
    End With
End Sub

然后使用此代码将表中的数据替换为“新数据”

Private Sub ListObject_ReplaceData()
Dim MyTable As ListObject
Dim vDtaHdr() As Variant, vDtaBdy() As Variant
Dim lRowsAdj As Long

    Set MyTable = ThisWorkbook.Worksheets(1).ListObjects(1) 'Change as required

    Call Data_Array_Set(vDtaHdr, vDtaBdy)

    With MyTable.DataBodyRange
        Rem Get Number of Rows to Adjust
        lRowsAdj = 1 + UBound(vDtaBdy, 1) - LBound(vDtaBdy, 1) - .Rows.Count

        Rem Resize ListObject
        If lRowsAdj < 0 Then
            Rem Delete Rows
            .Rows(1).Resize(Abs(lRowsAdj)).Delete xlShiftUp

        ElseIf lRowsAdj > 0 Then
            Rem Insert Rows
            .Rows(1).Resize(lRowsAdj).Insert Shift:=xlDown

    End If: End With

    Rem Overwrite Table with New Data
    MyTable.HeaderRowRange.Value = vDtaHdr
    MyTable.DataBodyRange.Value = vDtaBdy

End Sub

【讨论】:

  • 感谢您指出我可以将MyTable.DataBodyRange.Value 设置为某些东西。如果你及时的话,这会喜欢我的问题。 但是我计算内存中的值,而不是另一个电子表格,因为更改数千个单元格的值需要很长时间,即使使用ScreenUpdating = False 并且我尝试了类似.Rows(1).Resize(lRowsAdj).Insert Shift:=xlDown但这弄乱了我的床单。 更正您的错字:Dta_ArraySet 不是 Dta_Array_Set
【解决方案2】:

旧帖子,但我粘贴到 listobject 表的方式是删除 databodyrange,将范围设置为数组大小,然后将范围设置为数组。类似于上面提供的解决方案,但不需要调整表格大小。

'Delete the rows in the table
    If lo.ListRows.Count > 0 Then
        lo.DataBodyRange.Delete
    End If

'Assign the range to the array size then assign the array values to the range
    Set rTarget = wsTemplate.Range("A2:K" & UBound(arrTarget) + 1)
    rTarget = arrTarget

【讨论】:

  • 您介意要么为我使用的对象使用相同的名称清楚地描述它们包含更多代码, 以便我们更轻松地了解您?我的反对票可能会变成赞成票。
猜你喜欢
  • 2018-12-31
  • 2019-03-15
  • 2018-09-12
  • 1970-01-01
  • 1970-01-01
  • 2019-05-14
  • 2019-05-04
  • 2016-07-20
  • 2020-01-29
相关资源
最近更新 更多