简体   繁体   English

Excel VBA将工作表中的每一列复制到右侧的下一列

[英]Excel VBA to Copy Every Column in a Sheet to the Next Column to the Right

I need to accomplish something very simple: copy a complete column to the next column to the right in the same worksheet (I have around 300 of those columns in one sheet of a workbook) meaning that the macros has to copy every odd column in range to next even column so that I end up having a range full of duplicate columns. 我需要完成一些非常简单的操作:将完整的列复制到同一工作表中右侧的下一列(我在工作簿的一页中大约有300列),这意味着宏必须复制范围中的每个奇数列到下一个偶数列,这样我最终会有一个充满重复列的范围。 I understand that I need to use the following formula in part or in full: 我了解我需要部分或全部使用以下公式:

cells(selection.row, columns.Count).end(xltoleft).offset(,1).select

What would be the complete macros though? 什么是完整的宏呢? Searched every available board and found only solutions with custom conditions. 搜索每个可用的电路板,仅找到具有自定义条件的解决方案。 Mine should be really simple. 我的应该很简单。 Thank you for your input. 谢谢您的意见。

Try (might need some error handling). 尝试(可能需要一些错误处理)。 Rather than copying entire columns I am using column A to determine the last row of data in the sheet (you can change this) then I am looping the even columns setting them equal to the prior odd columns. 而不是复制整个列,而是使用A列来确定工作表中的最后一行数据(可以更改此列),然后我将偶数列循环设置为等于先前的奇数列。

Option Explicit

Sub test()

    Dim loopRange As Range

    Set loopRange = ThisWorkbook.ActiveSheet.Columns("A:AE")

    Dim lastRow As Long

    With ThisWorkbook.ActiveSheet

        lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row

    End With

    Dim currentColumn As Long

    With loopRange

        For currentColumn = 2 To .Columns.Count Step 2

            .Range(.Cells(1, currentColumn), .Cells(lastRow, currentColumn)) = .Range(.Cells(1, currentColumn - 1), .Cells(lastRow, currentColumn - 1)).Value

        Next currentColumn

    End With

End Sub

If you know the last row: 如果您知道最后一行:

 Option Explicit

    Sub test()

        Dim loopRange As Range

        Set loopRange = ThisWorkbook.ActiveSheet.Columns("A:AE")

        Const lastRow As Long = 108

        Dim currentColumn As Long

        With loopRange

            For currentColumn = 2 To .Columns.Count Step 2

                .Range(.Cells(1, currentColumn), .Cells(lastRow, currentColumn)) = .Range(.Cells(1, currentColumn - 1), .Cells(lastRow, currentColumn - 1)).Value

            Next currentColumn

        End With

    End Sub

I'm not entirely sure I understood the issue, but please find below a suggestion. 我不确定我是否理解此问题,但请在下面的建议中查找。 The code may be a bit messy since I used a recorded macro: 由于我使用了录制的宏,因此代码可能有点混乱:

Sub CopyRows()

Range("A1").Activate

While Not IsEmpty(ActiveCell)
    ActiveCell.Columns("A:A").EntireColumn.Select
    Selection.Copy
    ActiveCell.Offset(0, 1).Columns("A:A").EntireColumn.Select
    Selection.Insert Shift:=xlToRight
    ActiveCell.Offset(0, 1).Range("A1").Select
Wend

End Sub

If you're hoping to essentially duplicate every column by inserting a copy of each column to the right I think you need the below code. 如果您希望通过在右侧插入每列的副本来实质上复制每列,我认为您需要以下代码。

ie this copies columns: 即这将复制列:

A | B | C 
---------
A | B | C 
1 | 2 | 3 

to

A | B | C | D | E | F
---------------------
A | A | B | B | C | C
1 | 1 | 2 | 2 | 3 | 3

VBA VBA

Option Explicit

Sub CopyAllColsOneToRight()

    Dim ws As Worksheet
    Dim lastCol As Long
    Dim lastRow As Long
    Dim currentCopyCol As Long

    Application.ScreenUpdating = False 'optimise performance by not updating the screen as we move stuff
    Set ws = ActiveSheet
    lastCol = GetLastUsedColumn(ws).Column
    lastRow = GetLastUsedRow(ws).Row

    For currentCopyCol = lastCol To 1 Step -1
        CopyColumnInsertRight ws, lastRow, currentCopyCol
        'CopyColumn ws, lastRow, currentCopyCol, lastRow, currentCopyCol * 2
        'CopyColumn ws, lastRow, currentCopyCol, lastRow, currentCopyCol * 2 - 1
    Next

End Sub

Sub CopyColumnInsertRight(ByRef ws As Worksheet, fromLastRow, fromCol)
    Dim fromRange As Range
    Set fromRange = ws.Range(ws.Cells(1, fromCol), ws.Cells(fromLastRow, fromCol))
    fromRange.Copy
    fromRange.Insert Shift:=XlDirection.xlToRight
End Sub

'Sub CopyColumn(ByRef ws As Worksheet, fromLastRow, fromCol, toLastRow, toCol)
'   Dim fromRange As Range
'   Dim toRange As Range
'   Set fromRange = ws.Range(ws.Cells(1, fromCol), ws.Cells(fromLastRow, fromCol))
'   Set toRange = ws.Range(ws.Cells(1, toCol), ws.Cells(toLastRow, toCol))
'   toRange.Value2 = fromRange.Value2
'End Sub

Function GetLastUsedColumn(ByRef ws As Worksheet) As Range
    Set GetLastUsedColumn = ws.Cells.Find( _
        What:="*" _
        , After:=ws.Cells(1, 1) _
        , LookIn:=XlFindLookIn.xlFormulas _
        , LookAt:=XlLookAt.xlPart _
        , SearchOrder:=XlSearchOrder.xlByColumns _
        , SearchDirection:=XlSearchDirection.xlPrevious _
        , MatchCase:=False _
    )
End Function

Function GetLastUsedRow(ByRef ws As Worksheet) As Range
    Set GetLastUsedRow = ws.Cells.Find( _
        What:="*" _
        , After:=ws.Cells(1, 1) _
        , LookIn:=XlFindLookIn.xlFormulas _
        , LookAt:=XlLookAt.xlPart _
        , SearchOrder:=XlSearchOrder.xlByRows _
        , SearchDirection:=XlSearchDirection.xlPrevious _
        , MatchCase:=False _
    )
End Function

Notes on the code: 关于代码的注释:

  • We disable screen updating; 我们禁用屏幕更新; this avoids refreshing the UI whilst the macro runs, making the process more efficient. 这样可以避免在宏运行时刷新UI,从而使过程更高效。
  • We get the last populated column so that instead of copying every column on the worksheet we can limit those copied to the ones which make a difference (ie much faster for spreadsheets using less that the full number of columns; which will be true of most) 我们得到了最后一个填充的列,因此不必复制工作表上的每一列,我们可以将复制的列限制为有区别的列(即,对于使用少于全部列数的电子表格,它要快得多;大多数情况下都是如此)
  • We get the last populated row so that instead of copying entire columns we only copy populated rows. 我们得到了最后一个填充的行,因此只复制填充的行,而不是复制整个列。 We could check for the last used cell per row, but that's likely less efficient since typically the last row will be the same for most columns in range. 我们可以检查每行最后使用的单元格,但是效率可能较低,因为通常情况下,大多数行的最后一行都是相同的。 Also, when using the insert method this is required to ensure that xlToRight doesn't cause cells to be shifted into the wrong columns. 同样,在使用insert方法时,这是确保xlToRight不会导致单元格移入错误列所必需的。
  • Our for loop has Step -1 since if we went from left to right we'd overwrite columns to the right as we copied others (eg copying A to B overwrites what's in B, then when we copy B to C we're actually copying the copy). 我们的for循环具有Step -1因为如果我们从左到右移动,则在复制其他列时将覆盖右边的列(例如,将A复制到B会覆盖B中的内容,那么当我们将B复制到C时,我们实际上是在复制副本)。 Instead we work backwards so that we're always copying to blank columns or to columns we've previously copied. 相反,我们向后工作,以便始终将其复制到空白列或以前复制的列。
  • I've provided a commented out version which only copies values (faster than copying formats), and another version which uses Insert to create the new columns. 我提供了一个注释掉的版本,该版本仅复制值(比复制格式要快),另一个版本是使用Insert创建新列。 One may perform better than the other, but I've not tested so far (NB: The copy has to copy twice as many cells as it doesn't keep the originals but creates 2 copies, whilst the insert method keeps the originals and inserts a copy to the right, but has the additional overhead of copying formatting data). 一种可能比另一种性能更好,但是到目前为止我还没有进行测试(注意:副本必须复制两倍的单元格,因为它不能保存原始文档,但是可以创建2份副本,而insert方法可以保留原始文档并插入右边的副本,但具有复制格式数据的额外开销)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM