【问题标题】:How to paste the data in a range where the starting row and column of the range is defined in a cell?如何将数据粘贴到范围的起始行和列在单元格中定义的范围中?
【发布时间】:2022-01-27 20:20:12
【问题描述】:

我的 excel 文件中有两张工作表:

输入表: Sheet1

目标表: Sheet2

我想要实现的是将值从我在单元格C5 中定义的列开始粘贴,并从我在单元格C6 中定义的行开始粘贴。如果单元格C5C6定义的范围已经有数据,那么它将根据单元格C5中的列找到下一个空行并将数据粘贴到该空行中。

例如在上面的屏幕截图中,单元格C5C6中定义的起始列和行是B8,因此复制的值将从单元格B8开始粘贴,直到E8。但是,如果该行已经有数据,那么它将根据 B 列(即B9)找到下一个空行并将其粘贴到那里。

我不确定如何修改我当前的脚本:

Public Sub CopyData()

    Dim InputSheet As Worksheet ' set data input sheet
    Set InputSheet = ThisWorkbook.Worksheets("Sheet1")
    
    Dim InputRange As Range ' define input range
    Set InputRange = InputSheet.Range("G6:J106")
    
    Dim TargetSheet As Worksheet
    Set TargetSheet = ThisWorkbook.Worksheets("Sheet2")
    
    Const TargetStartCol As Long = 2        ' start pasting in this column in target sheet
    Const PrimaryKeyCol As Long = 1         ' this is the unique primary key in the input range (means first column of B6:G6 is primary key)
    
    Dim InsertRow As Long

    InsertRow = TargetSheet.Cells(TargetSheet.Rows.Count, TargetStartCol + PrimaryKeyCol - 1).End(xlUp).Row + 1
  
    ' copy values to target row
    TargetSheet.Cells(InsertRow, TargetStartCol).Resize(ColumnSize:=InputRange.Columns.Count).Value = InputRange.Value

End Sub

任何帮助或建议将不胜感激!

测试场景 1

测试场景 1 的输出

【问题讨论】:

  • 能否解释一下为什么第一行数据重复了5次?
  • 因为我运行脚本5次,所以输出是这样的,再次运行脚本会覆盖第二行
  • 你试过我的解决方案了吗?你能告诉它有什么问题吗?没关系,我知道该怎么做。
  • 是的,我也测试过,输出是一样的

标签: excel vba copy-paste


【解决方案1】:

请尝试下一个代码:

Public Sub CopyData_()
    Dim InputSheet As Worksheet: Set InputSheet = ThisWorkbook.Worksheets("Sheet1")
    Dim InputRange As Range: Set InputRange = InputSheet.Range("G6:J106")
    Dim arr: arr = InputRange.Value
    
    Dim TargetSheet As Worksheet: Set TargetSheet = ThisWorkbook.Worksheets("Sheet2")
    Dim TargetStartCol As String, PrimaryKeyRow As Long
    TargetStartCol = TargetSheet.Range("C5").Value       ' start pasting in this column in target sheet
    PrimaryKeyRow = TargetSheet.Range("C6").Value        ' this is the row after the result to be copied
    
    Dim InsertRow As Long

    InsertRow = TargetSheet.cells(TargetSheet.rows.Count, TargetStartCol).End(xlUp).row + 1
    If InsertRow < PrimaryKeyRow Then InsertRow = PrimaryKeyRow + 1 'in case of no entry after PrimaryKeyRow (neither the label you show: "Row")
    ' copy values to target row
    TargetSheet.cells(InsertRow, TargetStartCol).Resize(UBound(arr), UBound(arr, 2)).Value = arr
End Sub

未经测试,但我认为应该可以。如果有不清楚或出错的地方,请毫不犹豫地提及错误,它对您有什么作用/没有对您的需要或其他任何需要纠正的事情。

【讨论】:

  • 感谢FaneDuru,如果输入范围超过1行,似乎只能复制和粘贴输入范围的第一行。当前输入范围是G6:J106,因此理想情况下,该范围内的所有数据都将被复制并粘贴到目标工作表中。不过,粘贴目的地完美无缺!
  • @weizer 代码可以很容易地适应这一点。我会在几秒钟内完成。但是您没有指定复制的范围可能有多行...
  • @weizer 改编。使用arr 数组很容易适应代码。请测试更新的版本并发送一些反馈。
  • @weizer 你有时间测试更新的代码吗?如果经过测试,它没有按您的需要工作吗?
  • 已经可以粘贴整个范围的数据了!我测试了一个场景,但似乎第二行数据将被覆盖,我猜是因为 `PrimaryKeyRow?我用 2 个新屏幕截图编辑了我的问题
【解决方案2】:

将数据复制到另一个工作表

Option Explicit

Sub CopyData()
    
    Const sName As String = "Sheet1"
    Const rgAddress As String = "G6:J106"

    Dim wb As Workbook: Set wb = ThisWorkbook
    Dim ws As Worksheet: Set ws = wb.Worksheets(sName)
    Dim rg As Range: Set rg = ws.Range(rgAddress)

    WriteCopyData rg

    ' or just:
    'WriteCopyData ThisWorkbook.Worksheets("Sheet1").Range("G6:J106")

End Sub

Sub WriteCopyData(ByVal SourceRange As Range)

    Const dName As String = "Sheet2"
    Const dRowAddress As String = "C6"
    Const dColumnAddress As String = "C5"
    
    Dim rCount As Long: rCount = SourceRange.Rows.Count
    Dim cCount As Long: cCount = SourceRange.Columns.Count
    
    Dim dws As Worksheet
    Set dws = SourceRange.Worksheet.Parent.Worksheets(dName)
    
    Dim dRow As Long: dRow = dws.Range(dRowAddress).Value
    Dim dCol As String: dCol = dws.Range(dColumnAddress).Value

    Dim dfrrg As Range: Set dfrrg = dws.Cells(dRow, dCol).Resize(1, cCount)
    Dim dlCell As Range
    Set dlCell = dfrrg.Resize(dws.Rows.Count - dRow + 1) _
        .Find("*", , xlFormulas, , xlByRows, xlPrevious)
    
    If Not dlCell Is Nothing Then
        Set dfrrg = dfrrg.Offset(dlCell.Row - dRow + 1)
    End If
    
    Dim drg As Range: Set drg = dfrrg.Resize(rCount)
    drg.Value = SourceRange.Value
    
End Sub

【讨论】:

  • 我已经解决了这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-01
  • 2014-06-08
  • 2018-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多