我在excel中有两个表,一个主表和一个数据表。 数据表包含某些需要在主数据库中更新的更新记录。我发现一个宏可以很好地完成此工作,除了在更新后,它会将表转换为范围并删除表。
在修改如何保留表但仍更新更改方面有帮助吗?
代码:
Option Explicit
Sub NewNameandCostCenter()
Dim start As Double
start = Timer
Dim countOfChangedRows As Long
'set rngMap array
Dim rngMap As Range
Set rngMap = Worksheets("Map").Range("A1:D51")
'set rngData array
Dim rngData As Range
Set rngData = Worksheets("Data").Range("J2:M20001")
Dim aMap As Variant
aMap = rngMap.Value
Dim aData As Variant
aData = rngData.Value
Dim mapRow As Long
Dim datarow As Long
Dim mapcol As Long
For mapRow = LBound(aMap, 1) To UBound(aMap, 1)
For datarow = LBound(aData) To UBound(aData)
'Check the key matches in both tables
If aData(datarow, 1) = aMap(mapRow, 1) Then
countOfChangedRows = countOfChangedRows + 1
'Assumes the columns in map and data match
For mapcol = LBound(aMap, 2) + 1 To UBound(aMap, 2)
aData(datarow, mapcol) = aMap(mapRow, mapcol)
Next mapcol
End If
Next datarow
Next mapRow
rngData.Value = aData
Debug.Print countOfChangedRows & " of "; UBound(aData, 1) & " rows updated in " & Timer - start & " seconds"
End Sub
答案 0 :(得分:0)
在工作簿的副本上尝试 快速编辑 。已对其进行编辑以直接在主表中进行更改,而不是将数据拉入数组然后粘贴回已编辑的副本。
说明
正在使用的现有代码有几个步骤:
aData
(工作表数据中的数组)以匹配aMap
(工作表Map中的数组)aData
粘贴回它来自的范围将数组数据粘贴回工作表范围时遇到的问题。可以通过直接在表中进行更改,而不是对要粘贴回的数组进行更改来解决此问题。
在VBA中,可以使用工作表的ListObjects
集合以及所需Table对象的索引或名称来访问表对象。该列表对象具有各种有用的集合。 .ListRows
,.ListColumns
,.DataBodyRange
等(我想可能还会有标头范围吗?)。对于大多数表,我发现.ListRows
最有用。
ListRow(或ListColumn)的属性之一是其.Range
功能。它需要一个行和一个列变量(类似于工作表中的.Cells
)。在这种特殊情况下(代码循环遍历Tables ListRows集合-For each datarow in rngData.ListRows
),数据行将只保留一行,因此row变量为常数1。column变量是相同的变量/从数组访问数据时使用的值。 (尽管我忘记了数组可能是从零开始的,所以我猜我们很幸运。)
ListRows和ListColumns集合的另一方面是.Count
属性。我在一些地方使用了这个:
mapcol
分配适当的值范围以访问ListRows的每一列中的值Debug.Print
语句表中ListRows的总数该代码可以通过.Range
访问每个ListRow中的每个范围,因此代码能够:
还可以重写代码,因此,无需将任何数据提取到数组中,而只是在一个表和下一个表之间进行直接比较(您可以在 Edited Code < / strong> )。
快速编辑
Option Explicit
Sub NewNameandCostCenter()
Dim start As Double
start = Timer
Dim countOfChangedRows As Long
'set rngMap array
Dim rngMap As Range
Set rngMap = Worksheets("Map").Range("A1:D51")
'set rngData table (previously set rngData array)
Dim rngData As ListObject
Set rngData = Worksheets("Data").ListObjects("TableName") 'Adjust to name of your master table
Dim aMap As Variant
aMap = rngMap.Value
Dim mapRow As Long
Dim datarow As ListRow 'For cycling through the table rows
Dim mapcol As Long
For mapRow = LBound(aMap, 1) To UBound(aMap, 1)
For each datarow in rngData.ListRows
'Check the key matches in both tables
If datarow.Range(1, 1) = aMap(mapRow, 1) Then
countOfChangedRows = countOfChangedRows + 1
'Assumes the columns in map and data match
For mapcol = LBound(aMap, 2) + 1 To UBound(aMap, 2)
datarow.Range(1, mapcol) = aMap(mapRow, mapcol)
Next mapcol
End If
Next datarow
Next mapRow
Debug.Print countOfChangedRows & " of "; rngData.ListRows.Count & " rows updated in " & Timer - start & " seconds"
End Sub
修改后的代码
Option Explicit
Sub NewNameandCostCenter()
Dim start As Double
start = Timer
Dim countOfChangedRows As Long
'set rngMap array
Dim rngMap As ListObject
Set rngMap = Worksheets("Map").ListObjects("TableName") 'Adjust to name of your data table
'set rngData table (previously set rngData array)
Dim rngData As ListObject
Set rngData = Worksheets("Data").ListObjects("TableName") 'Adjust to name of your master table
Dim mapRow As ListRow
Dim datarow As ListRow 'For cycling through the table rows
Dim mapcol As Long
For each mapRow in rngMap
For each datarow in rngData.ListRows
'Check the key matches in both tables
If datarow.Range(1, 1) = mapRow.Range(1, 1) Then
countOfChangedRows = countOfChangedRows + 1
'Assumes the columns in map and data match
For mapcol = 2 To rngMap.ListColumns.Count
datarow.Range(1, mapcol) = mapRow.Range(1, mapcol)
Next mapcol
End If
Next datarow
Next mapRow
Debug.Print countOfChangedRows & " of "; rngData.ListRows.Count & " rows updated in " & Timer - start & " seconds"
End Sub