excel 将带有格式和公式的一行数据移动到指定工作表

ozxc1zmp  于 2023-08-08  发布在  其他
关注(0)|答案(4)|浏览(117)

我有一本很大的工作簿,里面有很多产品,包括规格、定价和分类计算。当一个产品到期时,我想把它移到一个EOL表,这样我就可以保留一个旧产品的日志。
此脚本应查看选定的行,将内容移动到工作表“EOL”,从原始工作表中删除它,并跳过所有隐藏的行。
如果我选择一个单元格,它就可以工作,但是如果我选择更多的单元格,它就不能正确地遍历整个范围。

Sub MoveRows()
    Call SpeedUp
    Dim SourceSheet As Worksheet
    Dim TargetSheet As Worksheet
    Dim LastRow As Long
    Dim rng As Range
            
    Set rng = Selection
    
    Set SouceSheet = ActiveSheet
    Set TargetSheet = ActiveWorkbook.Sheets("EOL")

    TargetRow = ActiveCell.row
    LastRow = TargetSheet.Cells(TargetSheet.Rows.Count, "D").End(xlUp).row + 1
     
    For Each row In rng.Rows
        If row.Rows.Hidden Then
            TargetRow = TargetRow + 1
        
        Else
            ActiveSheet.Rows(TargetRow).Copy
            TargetSheet.Rows(LastRow).PasteSpecial xlPasteFormulasAndNumberFormats
            TargetSheet.Rows(LastRow).PasteSpecial xlPasteFormats
            Rows(TargetRow).EntireRow.Delete
            LastRow = LastRow + 1
        End If
             
    Next row
        
    Call SpeedDown
      
End Sub

字符串

  • 注意:SpeedUp/SpeedDown功能是关闭screnupdating等。为了效率。不会影响脚本本身。*

当我测试它注解删除函数时,它重复复制第一个单元格,显然是因为TargetRow没有改变。
当我在End If之后添加TargetRow = TargetRow + 1时,它可以工作。
当我取消注解删除部分时,它不像我期望的那样工作。
当TargetRow被删除时,我会认为下一行将是新的TargetRow,但似乎没有发生这种情况。
我想我的问题是TargetRow和rng. Row的迭代之间没有直接的联系。
我该如何解决这个问题?是否有一种方法可以将所有移动的行存储在一个列表中,然后通过新的迭代删除它们?或者这对于VBA来说有点太“python-thinking”了?

zi8p0yeb

zi8p0yeb1#

移动选区可见行

  • 顺便说一句,如果你使用Option Explicit,它会警告你关于未声明的变量rowSet SouceSheet = ActiveSheet中的错别字。
  • Row属性通常使用大写字母R。在您的代码中,会出现.row,因为您正在使用名为row的变量。为了再次说明属性资本的情况,声明Dim Row As Range。然后你可以使用另一个变量名来代替Row,例如。rrg(行范围),srrg ...
Option Explicit

Sub MoveRows()
    
    If Selection Is Nothing Then Exit Sub ' no visible workbooks open
    If Not TypeOf Selection Is Range Then Exit Sub ' not a range
    
    Dim sws As Worksheet: Set sws = Selection.Worksheet
    
    Dim srg As Range: Set srg = Intersect(Selection.EntireRow, sws.UsedRange)
    If srg Is Nothing Then Exit Sub ' not in rows of the used range
    
    Dim svrg As Range
    On Error Resume Next
        Set svrg = srg.SpecialCells(xlCellTypeVisible)
    On Error GoTo 0
    If svrg Is Nothing Then Exit Sub ' no visible cells
    
    Dim dws As Worksheet
    On Error Resume Next
        Set dws = sws.Parent.Sheets("EOL")
    On Error GoTo 0
    If dws Is Nothing Then Exit Sub ' worksheet 'EOL' doesn't exist
    
    Dim dfcell As Range
    With dws.UsedRange
        Set dfcell = dws.Cells(.Row + .Rows.Count, "A")
    End With
    
    Application.ScreenUpdating = False
    
    svrg.Copy
    dfcell.PasteSpecial xlPasteFormulasAndNumberFormats
    dfcell.PasteSpecial xlPasteFormats
        
    svrg.Delete xlShiftUp
      
    Application.ScreenUpdating = True

    MsgBox "Rows moved.", vbInformation
      
End Sub

字符串

jw5wzhpr

jw5wzhpr2#

您正在使用For Each,但您很少使用row,除非您想检查它是否被隐藏。为什么需要TargetRow?试试看:

For Each row In rng.Rows
    If Not row.Rows.Hidden Then
        row.Copy
        TargetSheet.Rows(LastRow).PasteSpecial xlPasteFormulasAndNumberFormats
        TargetSheet.Rows(LastRow).PasteSpecial xlPasteFormats
        row.EntireRow.Delete
        LastRow = LastRow + 1
    End If    
Next row

字符串

lymnna71

lymnna713#

  • 更新 *

因此,经过大量的时间花,我终于得到了一个解决方案,做的伎俩。

Sub MoveRows()
   
    Dim SourceSheet As Worksheet
    Dim TargetSheet As Worksheet
    Dim rng As Range
    Dim TargetRow As Integer
    Dim StartRow As Integer
    Dim EndRow As Integer
    Dim LastRow As Long
     
    Set rng = Selection
    Set SourceSheet = ActiveSheet
    Set TargetSheet = ActiveWorkbook.Sheets("EOL")
    
    LastRow = TargetSheet.Cells(TargetSheet.Rows.Count, "D").End(xlUp).row + 1
    StartRow = rng.row
    EndRow = rng.Rows.Count + StartRow - 1
        
    For i = EndRow To StartRow Step -1
        If Not Rows(i).Hidden Then
            ActiveSheet.Rows(i).Copy
            TargetSheet.Rows(LastRow).PasteSpecial xlPasteFormulasAndNumberFormats
            TargetSheet.Rows(LastRow).PasteSpecial xlPasteFormats
            Rows(i).EntireRow.Delete
            LastRow = LastRow + 1
         End If
    Next i

    Cells(EndRow, 1).Select

End Sub

字符串
感谢大家的帮助!

0wi1tuuw

0wi1tuuw4#

以下是一些改进VBA代码以在工作表之间移动行的建议:
声明所有的变量靠近它们被使用的地方。例如,在For Each循环之前声明TargetRow。使用更具描述性的变量名,如sourceSheet,而不是SourceSheet。添加一些注解,解释代码正在做什么。举例来说:vb
复制码
'循环遍历选定区域中的每一行For Each row In rng.行
'检查行是否隐藏如果行。隐藏然后
'如果hidden TargetRow = TargetRow + 1,则递增目标行
埃尔瑟
'复制可见行到目标工作表ActiveSheet.Rows(TargetRow).复制TargetSheet.Rows(LastRow).PasteSpecial xlPasteFormats
'删除源工作表上的行Rows(TargetRow).EntireRow.Delete
'递增最后一行计数器LastRow = LastRow + 1
如果结束
下一行添加一些错误处理,以防复制/粘贴失败。尽可能避免使用Select和ActiveSheet。完全限定像SouceSheet.Rows(TargetRow).Copy这样的对象考虑将源表和目标表作为参数传递,而不是依赖于ActiveSheet。在顶部添加Option Explicit以要求变量声明。如果有任何部分需要更多的解释,请告诉我!

相关问题