简化VBA代码-从列到8*12格式



我对VBA很陌生,我想要一些关于简化/使代码更动态的建议,这样它就不会局限于特定的范围。我想将同一列中的数据从不同的行复制到8 x 12(x到y(格式。我目前的代码是完全有效的,但我只是想知道是否有一种更动态的方法可以做到这一点,因为我花了很多时间才在循环公式中找到关系,它们被固定为只有384行。我还打算在行为空时退出sub,以防止出现无限循环。以下是我设法制作的代码:

Private Sub columnto96()
Dim x As Long, y As Long, z As Long, a As Long, lr As Long
Dim src As Worksheet, dst As Worksheet
Set src = Sheet1 'setsheetsource
Set dst = Sheet3 'setsheetdest
lr = src.Cells(Rows.Count, 4).End(xlUp).Row
'for one plate
If lr <= 96 Then
For y = 1 To 12
For x = 1 To 8
dst.Cells(x, y) = src.Cells(8 * y - 8 + x + 1, 4)
Next x
Next y
Exit Sub

'for >1 plate
ElseIf lr > 96 Then
For y = 1 To 12
For x = 1 To 8
dst.Cells(x, y) = src.Cells(8 * y - 8 + x + 1, 4)
Next x
Next y

'for more than 96 samples
For x = 87 To 94
For y = 1 To 12
For z = 97 To 104
dst.Cells(z - x, y) = src.Cells(z, 4)

If z - x >= 17 Then Call nextcolumn Else
Next z

If src.Cells(lr + 1, 4) = "" Then Exit Sub

Next y
Next x

End If
End Sub
Private Sub nextcolumn()
Dim x As Long, z As Long, y As Long, lr As Long
Dim src As Worksheet, dst As Worksheet
Set src = Sheet1 'setsheetsource
Set dst = Sheet3 'setsheetdest
lr = src.Cells(Rows.Count, 4).End(xlUp).Row
For y = 1 To 12
For x = 1 To 8
dst.Cells(x + 9, y) = src.Cells(8 * y + x + 89, 4)
If src.Cells(8 * y + x + 89, 4) = "" Then Exit Sub
Next x
Next y
If lr < 289 Or lr >= 193 Then
For y = 1 To 12
For x = 1 To 8
dst.Cells(x + 18, y) = src.Cells(8 * y + x + 184, 4)
If src.Cells(8 * y + x + 184, 4) = "" Then Exit Sub
Next x
Next y


ElseIf lr >= 289 Or lr < 385 Then
For y = 1 To 12
For x = 1 To 8
dst.Cells(x + 27, y) = src.Cells(8 * y + x + 279, 4)
If src.Cells(8 * y + x + 279, 4) = "" Then Exit Sub
Next x
Next y

Else: Exit Sub
End If
End Sub

提前感谢!:(

获取列集(逐列逐行格式(

  • 前两个过程执行相同的操作,并且都使用了附带的三个函数
  • "节目之星"是最后一个承担大部分重任的角色
  • 调整第一个过程的常量部分和工作表引用中的值
  • 如果选择第二个过程,请调整找到它们的位置的值
Option Explicit
Sub getColumnSetsFlexible()

' Define constants.
Const sFirst As String = "D2"
Const dFirst As String = "A2"
Const rCount As Long = 8
Const cCount As Long = 12
Const ByColumns As Boolean = True
Const includeRemainder As Boolean = False
Const EmptyRows As Long = 1

' Create worksheet references.
Dim sws As Worksheet: Set sws = Sheet1
Dim dws As Worksheet: Set dws = Sheet3

' Create a reference to the Source Column Range.
Dim rg As Range: Set rg = refColumn(sws.Range(sFirst))
' Validate Source Column Range.
If rg Is Nothing Then Exit Sub

' Write the values from the Source Column Range to Source Data Array.
Dim sData As Variant: sData = getColumn(rg)

' Write the column sets from Source Data Array to arrays of Data Array.
Dim Data As Variant: Data = getColumnSets( _
sData, rCount, cCount, ByColumns, includeRemainder)

' Create a reference to the Current Destination Range.
Dim drg As Range: Set drg = dws.Range(dFirst).Resize(rCount, cCount)

' Declare Data Array Arrays Counter.
Dim n As Long

' Loop through the arrays of Data Array.
For n = 1 To UBound(Data, 1)
' Write the values of the current array of Data Array
' to the Current Destination Range.
drg.Value = Data(n)
' Create a reference to the Next Destination Range.
Set drg = drg.Offset(EmptyRows + rCount)
Next n
End Sub
Sub getColumnSetsReadable()

' Create a reference to the Source Column Range.
Dim rg As Range: Set rg = refColumn(Sheet1.Range("D2"))
' Validate Source Column Range.
If rg Is Nothing Then Exit Sub

' Write the values from the Source Column Range to Source Data Array.
Dim sData As Variant: sData = getColumn(rg)

' Write the column sets from Source Data Array to arrays of Data Array.
Dim Data As Variant: Data = getColumnSets(sData, 8, 12, True, False)

' Create a reference to the Current Destination Range.
Dim drg As Range: Set drg = Sheet3.Range("A2").Resize(8, 12)

' Declare Data Array Arrays Counter.
Dim n As Long

' Loop through the arrays of Data Array.
For n = 1 To UBound(Data, 1)
' Write the values of the current array of Data Array
' to the Current Destination Range.
drg.Value = Data(n)
' Create a reference to the Next Destination Range.
Set drg = drg.Offset(9)
Next n
End Sub

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose:      In a worksheet column, creates a reference to the range
'               from a given cell 'FirstCellRange' to the bottom-most
'               unoccupied cell i.e. all cells below the latter are empty
'               (="", ="'"... are not included).
'               If `NonBlankInsteadOfNonEmpty` is 'True', the bottom-most cell,
'               whose contents have a length of greater than 0, is condsidered
'               as the bottom-most unoccupied cell i.e. all cells below
'               the latter are blank ('Empty', ="", ="'"...).
' Remarks:      Although 'FirstCellRange' can be a range of any size,
'               only its first cell will be considered.
' Limitations:  If the worksheet contains filtered rows, both options may fail.
'               If it contains hidden rows, then only 'NonBlank' may fail.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function refColumn( _
FirstCellRange As Range, _
Optional ByVal NonBlankInsteadOfNonEmpty As Boolean = False) _
As Range
Const ProcName As String = "refColumn"
On Error GoTo clearError

If Not FirstCellRange Is Nothing Then
With FirstCellRange.Cells(1)
Dim cLookIn As XlFindLookIn
If NonBlankInsteadOfNonEmpty Then
cLookIn = xlValues
Else
cLookIn = xlFormulas
End If
Dim cel As Range
Set cel = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , cLookIn, , , xlPrevious)
If Not cel Is Nothing Then
Set refColumn = .Resize(cel.Row - .Row + 1)
End If
End With
End If
ProcExit:
Exit Function
clearError:
Debug.Print "'" & ProcName & "': Unexpected Error!" & vbLf _
& "    " & "Run-time error '" & Err.Number & "':" & vbLf _
& "        " & Err.Description
Resume ProcExit
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose:      Writes the values from a column ('ColumnNumber')
'               of a range ('rg') to a 2D one-based array.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function getColumn( _
rg As Range, _
Optional ByVal ColumnNumber As Long = 1, _
Optional ByVal doTranspose As Boolean = False) _
As Variant
Const ProcName As String = "getColumn"
On Error GoTo clearError

If Not rg Is Nothing Then
If ColumnNumber > 0 And ColumnNumber <= rg.Columns.Count Then
With rg.Columns(ColumnNumber)
Dim rCount As Long: rCount = rg.Rows.Count
Dim Result As Variant
If rCount > 1 Then
If doTranspose Then
Dim Data As Variant: Data = .Value
ReDim Result(1 To 1, 1 To rCount)
Dim r As Long
For r = 1 To rCount
Result(1, r) = Data(r, 1)
Next r
getColumn = Result
Else
getColumn = .Value
End If
Else
ReDim Result(1 To 1, 1 To 1): Result(1, 1) = .Value
getColumn = Result
End If
End With
End If
End If
ProcExit:
Exit Function
clearError:
Debug.Print "'" & ProcName & "': Unexpected Error!" & vbLf _
& "    " & "Run-time error '" & Err.Number & "':" & vbLf _
& "        " & Err.Description
Resume ProcExit
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose:      Writes the values of a 2D one-based one-column array
'               to a jagged array (array of arrays) consisting of arrays
'               of a given number of rows and columns.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function getColumnSets( _
ByVal ColumnData As Variant, _
ByVal RowsCount As Long, _
ByVal ColumnsCount As Long, _
Optional ByColumns As Boolean = False, _
Optional includeRemainder As Boolean = False) _
As Variant

Dim srCount As Long: srCount = UBound(ColumnData, 1)
Dim fCount As Long: fCount = Int(srCount / (RowsCount * ColumnsCount))
Dim dRem As Long: dRem = srCount - fCount
Dim dCount As Long: dCount = fCount
If includeRemainder Then
If dRem > 0 Then
dCount = dCount + 1
End If
End If

Dim Data As Variant: ReDim Data(1 To dCount)
Dim NewData As Variant: ReDim NewData(1 To RowsCount, 1 To ColumnsCount)
Dim n As Long, r As Long, c As Long, i As Long

If ByColumns Then
If fCount > 0 Then
For n = 1 To fCount
Data(n) = NewData
For c = 1 To ColumnsCount
For r = 1 To RowsCount
i = i + 1
Data(n)(r, c) = ColumnData(i, 1)
Next r
Next c
Next n
End If
If includeRemainder Then
If dRem > 0 Then
Data(n) = NewData
For c = 1 To ColumnsCount
For r = 1 To RowsCount
i = i + 1
If i <= srCount Then
Data(n)(r, c) = ColumnData(i, 1)
End If
Next r
Next c
End If
End If
Else
If fCount > 0 Then
For n = 1 To fCount
Data(n) = NewData
For r = 1 To RowsCount
For c = 1 To ColumnsCount
i = i + 1
Data(n)(r, c) = ColumnData(i, 1)
Next c
Next r
Next n
End If
If includeRemainder Then
If dRem > 0 Then
Data(n) = NewData
For r = 1 To RowsCount
For c = 1 To ColumnsCount
i = i + 1
If i <= srCount Then
Data(n)(r, c) = ColumnData(i, 1)
End If
Next c
Next r
End If
End If
End If

getColumnSets = Data

End Function

最新更新