将单元格从一个工作表复制并重新格式化为另一个工作表

时间:2015-03-26 08:28:44

标签: excel vba excel-vba

我正在整理一系列宏,并且已经达到VBA技能的最终目标(仅限于开始)。

我有两张纸,第二张依赖于第一张纸的内容。目前,用户需要将第一张中的内容复制并插入到第二张中,然后对其进行操作,这是可以理解的,没有人这样做,因为他们要么是懒惰的,要么是恐吓的。

为了让他们更有可能将信息复制到第二张,我想使用从按钮调用的宏。

基本上我需要克服两个问题,并且我祈祷你能够提供帮助。

  1. 要复制的区域不是静态的,并且需要复制的行数会有所不同;和
  2. 并非所有复制范围内的列都需要插入目标工作表。
  3. 要解决第一个问题,我知道我需要使用本回答中提供的LastrRow的一些变体:https://stackoverflow.com/a/11169920/4693144

    我已经尝试过如下使用该代码,但它一直在踢"错误'下标超出范围"回到我身边:

    Sub CopyBudget()
    
    Dim LastRow As Long
    Dim CopyRange As Range
        With Sheets("Project Budget")
            If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
            LastRow = .Cells.Find(What:="*", _
                    After:=.Range("A8"), _
                    Lookat:=xlPart, _
                    LookIn:=xlFormulas, _
                    SearchOrder:=xlFormulas, _
                    SearchDirection:=xlPrevious, _
                    MatchCase:=False).Row
    
        Else
            LastRow = 1
        End If
     End With
    
     Sheets("Project Plan").Range("D60").Resize(LastRow) = _
                Sheets("Project Budget").Range("A8").Resize(LastRow).Value
                    If Not CopyRange Is Nothing Then
                    CopyRange.Copy Sheets("Project Plan").Cells(60, "D")
                End If
    
    
    End Sub
    
    编辑:我很抱歉在我最初撰写帖子时没有发布我的错误参考(我在工作时跑出了门)。错误突出显示整个代码块:

            LastRow = .Cells.Find(What:="*", _
                    After:=.Range("A8"), _
                    Lookat:=xlPart, _
                    LookIn:=xlFormulas, _
                    SearchOrder:=xlFormulas, _
                    SearchDirection:=xlPrevious, _
                    MatchCase:=False).Row
    

    我意识到这段代码只能用于复制范围本身而不用于区分列。问题是,我不确定如何确保复制的行只包含所需的列。我应该根据所需的列串行运行上面代码的功能版本的几种变体来独立地复制和插入每一列,或者我应该抓住它然后使用代码来选择从复制或插入的单元格中我想要的列?

    我真的在寻找尽可能多的帮助。

2 个答案:

答案 0 :(得分:0)

对于仅复制特定列的问题,我认为使用范围会更难。

您可以尝试在要扫描的缓冲区上复制所选范围,以删除无用的列,然后复制到最终工作表。您可以使用它来删除列:

Sub Column_Delete(ByVal Sheets_Index As Integer, ByVal Str_to_Find As String)

Dim Ws As Worksheet
Set Ws = Worksheets(Sheets_Index)


Dim EndColumn As Integer
EndColumn = Ws.Cells(1, Columns.Count).End(xlToLeft).Column

'descending travel of the columns as we are going to delete some of them
For j = 1 To EndColumn
    If InStr(Ws.Cells(1, EndColumn - j + 1), Str_to_Find) > 0 Then
        Ws.Columns(EndColumn - j + 1).EntireColumn.Delete Shift:=xlToLeft
    End If
Next j

'Don't forget to free Ws (like I did...)
Set Ws = Nothing

End Sub

Function ColLet(x As Integer) As String
With ActiveSheet.Columns(x)
    ColLet = Left(.Address(False, False), InStr(.Address(False, False), ":") - 1)
End With
End Function

要复制粘贴,你不要在你给的代码中使用你的范围,personnaly我经常使用它:

    Sub AddDataToAnotherSheet(ByVal DataSheetName As String, ByVal StackSheetName As String)
'
Dim ShIn As Worksheet
Dim ShOut As Worksheet
Set ShIn = ThisWorkbook.Sheets(DataSheetName)
Set ShOut = ThisWorkbook.Sheets(StackSheetName)

'ShIn.Cells(2, 1).End(xlToRight).Column
Dim RgTotalInput As String
Dim RgTotalOutput As String

RgTotalInput = "$A$2:$" & ColLet(ShIn.Cells(1, 1).End(xlToRight).Column) & "$" & ShIn.Cells(Rows.Count, 1).End(xlUp).Row
RgTotalOutput = "$A$" & ShOut.Cells(Rows.Count, 1).End(xlUp).Row + 1

ShIn.Range(RgTotalInput).Copy Destination:=ShOut.Range(RgTotalOutput)


End Sub



Function ColLet(x As Integer) As String
With ActiveSheet.Columns(x)
    ColLet = Left(.Address(False, False), InStr(.Address(False, False), ":") - 1)
End With
End Function

答案 1 :(得分:0)

一个。因此,一般来说,如果您要移动的是从第一张到第二张的值(包括由公式计算的结果值,而不是公式本身),则应使用VBA赋值语句复制值,而不是剪切 - 和粘贴。对于要复制的中等单元格,它将更快地工作,您将完全控制要复制的行和列(特别是如果不复制某些行和/或列),程序员在以后更容易理解-fact,配置起来要简单得多,代码通常要小得多,并且更容易调试。

因此,如果我们假设您在两个不同的工作表上预先定义了两个范围srcRng和destRng,那么您所做的就是通常两个嵌套循环中的以下内容:

destRng.Cells(destRow, destCol).value = srcRng.Cells(srcRow, srcCol).value

您的外部循环通常用于要复制的行,您的内部循环通常用于要复制的列。当然,如果只复制两到三列,就不要进行内循环,只需用不同的destCol / srcCol对重复上述复制语句两次或三次。

B中。如果你确实需要自己复制公式,并且需要公式来自动调整它们对其他复制数据的相对引用,那么实际上你被迫使用Excel的剪切和粘贴,因为只有公式相对引用调整。您处理的策略是是否有更多行要跳过或者要跳过更多列...如果它是所有行(甚至是可变数量的行),那么最好选择并创建列的副本范围移动跨越所有行。

℃。在调试帮助方面,您必须告诉我们发生故障的路线。 VBA调试器通过突出显示代码行为您提供哪条线路失败。最糟糕的情况是放入断点并逐步执行子程序以找到它。但几乎所有在这里提出问题的人都无法提供明显的必要信息。

d。以下行似乎组成不当。 Cells属性采用数值,而不是字符串值。列“D”是4。

CopyRange.Copy Sheets("Project Plan").Cells(60, "D")