Excel宏将数据从一个工作表移动到另一个工作表非常慢

zsohkypk  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(110)

`我得到一个带有ID的Excel,并以概述格式关联其他ID。
例如
x1c 0d1x的数据
在此图像中- 5647326 是主ID,关联ID是 8798965,它们使用轮廓进行分组。
我有要求,我需要从这个工作表转移到其他工作表在同一工作簿中的数据,在线性格式-如在原始Excel中,我们在一行中获得主ID和下一行中的相关ID,在新的工作表中,主ID和相关ID应该在同一行,如果有多个相关ID,那么主ID应该添加两次,并在各自的行中添加2个相关ID,如在



我们已经开发了一个宏,工作正常,但非常慢,如500行,需要4-5分钟。任何人都可以帮助我如何提高以下宏的性能(从A6开始输入工作表数据,因为前5行有通用信息,可以从传输到其他工作表跳过:

Private Sub Workbook_Open() 
' ' MoveRows Macro ' 
' Keyboard Shortcut: Ctrl+w

Dim lastrow As Long 
Dim lastcol As Long 
Dim i As Integer 
Dim iNewRow As Integer 
Dim ws As Worksheet 
Dim cell As Range
Dim row As Long 
Dim crtLvl As Integer 
Dim rgRow As Range 
Dim orgSelect As Range

lastrow = Sheet1.Cells(Rows.Count, 3).End(xlUp).row 
lastcol = Sheet1.Cells(1, Columns.Count).End(xlToLeft).Column

'MsgBox lastrow

'Delete all worksheets other than Sheet1 
Application.DisplayAlerts = False 
For Each ws In Worksheets 
If ws.Name <> "Sheet1" 
Then ws.Delete 
End If 
Next 
Application.DisplayAlerts = True

'Create a new worksheet 
Sheets.Add(after:=Sheet1).Name = "Export" 
With Sheets("Export") 
.Range("A1") = "ID" 
.Range("B1") = "Name" 
.Range("C1") = "Type" 
.Range("D1") = "Owner" 
.Range("E1") = "Task Status" 
.Range("F1") = "Associated Resource ID" 
.Range("G1") = "Associated Resource Name" 
.Range("H1") = "Associated Resource Type" 
.Range("I1") = "Associated Resource Owner" 
.Range("J1") = "Associated Resource Status"

.Range("A1:J1").Interior.ColorIndex = 8
End With

i = 6 
iNewRow = 2 
Dim sht As Worksheet 
Dim Lr As Long 
Dim Lc As Long 
Dim FirstCell As Range
Set sht = Worksheets("Sheet1") 
Set FirstCell = Range("A6") 
Dim inp As Integer 
Dim iFirstLevelRow As Integer

With Sheet1 
For Each cell In .Range("a6", .Cells(lastrow, lastcol)) 
'rg2c = Range(FirstCell, .Cells(i, 1).Select) 
rangeName = i & ":" & i 
rg2c = Worksheets("Sheet1").Range(rangeName)

inp = Worksheets("Sheet1").Rows(i).OutlineLevel 

If i <= lastrow Then
   If inp = 1 Then
   iFirstLevelRow = cell.row
  
        i = i + 1
 End If
  If inp = 2 Then
  .Cells(iFirstLevelRow, 1).Copy Sheets("Export").Cells(iNewRow, 1)
        .Cells(iFirstLevelRow, 2).Copy Sheets("Export").Cells(iNewRow, 2)
        .Cells(iFirstLevelRow, 3).Copy Sheets("Export").Cells(iNewRow, 3)
           .Cells(iFirstLevelRow, 4).Copy Sheets("Export").Cells(iNewRow, 4)
           .Cells(iFirstLevelRow, 5).Copy Sheets("Export").Cells(iNewRow, 5)
           .Cells(iFirstLevelRow, 6).Copy Sheets("Export").Cells(iNewRow, 6)
  .Cells(cell.row, 1).Copy Sheets("Export").Cells(iNewRow, 7)
        .Cells(cell.row, 2).Copy Sheets("Export").Cells(iNewRow, 8)
        .Cells(cell.row, 3).Copy Sheets("Export").Cells(iNewRow, 9)
         .Cells(cell.row, 4).Copy Sheets("Export").Cells(iNewRow, 10)
        i = i + 1
        iNewRow = iNewRow + 1
 End If
 End If

Next

End With

Worksheets("Export").UsedRange.EntireColumn.AutoFit
Worksheets("Export").UsedRange.EntireRow.AutoFit 
End Sub

字符串

wmomyfyw

wmomyfyw1#

请测试下一种方式。你没有回答我的澄清问题,所以它假设主要任务是那些在C:C列中有“任务”的任务。即使要处理大范围,它也应该非常快。使用数组并立即删除处理过的数组内容,它主要在内存中工作:

Sub ProcessTasks()
  Dim ws As Worksheet, destws As Worksheet, lastR As Long, i As Long, iRow As Long, rg As Range
  Dim arr, arr1, arrTsk, arrIt, arrHd, arrFin, dKey, dict As Object
  
  Set ws = ActiveSheet 'use here the sheet you need
  Set destws = ws.Next 'destination sheet (here, the next one)
  destws.UsedRange.Clear
  
  Set rg = ws.UsedRange.Find("*", , xlFormulas, , xlByRows, xlPrevious)
  lastR = rg.Row 'last row (hidden rows included)
  
  arr = ws.Range("A2:E" & lastR).Value2
  
  Set dict = CreateObject("Scripting.Dictionary")
  For i = 1 To UBound(arr)
    If arr(i, 3) = "Task" Then
        arrTsk = Array(arr(i, 1), arr(i, 2), arr(i, 3), arr(i, 4), arr(i, 5))
        dict(arr(i, 1)) = Array(arrTsk, Array(""))
        dKey = arr(i, 1)
    Else
        arrIt = dict(dKey)
        If Not IsArray(arrIt(1)(0)) Then
            arrIt(1)(0) = Array(arr(i, 1), arr(i, 2), arr(i, 3), arr(i, 4), arr(i, 5))
            dict(dKey) = arrIt
        Else
            arr1 = arrIt(1)
            ReDim Preserve arr1(UBound(arr1) + 1)
            arr1(UBound(arr1)) = Array(arr(i, 1), arr(i, 2), arr(i, 3), arr(i, 4), arr(i, 5))
            arrIt(1) = arr1:  dict(dKey) = arrIt
        End If
        iRow = iRow + 1
    End If
  Next i
  
  ReDim arrFin(1 To iRow + 1, 1 To 10) 'redim the final array according to the determined number of rows (iRow)
  
  'Load headers array:
  arrHd = Split("ID,Name,Type,Owner,Task Status,Associated Resource ID,Associated Resources Name,Associated Resource Type, Associated Resource Owner,Associated Resource Status", ",")
  
  'load the final aray header:
  For i = 0 To UBound(arrHd)
    arrFin(1, i + 1) = arrHd(i)
  Next i
  
  'process the dictionary items:
  Dim k As Long, m As Long, j As Long: k = 1
  For i = 0 To dict.count - 1
    For m = 0 To UBound(dict.Items()(i)(1))
        k = k + 1
        'fill the final array first 5 columns corresponding to the main IDs:
        For j = 0 To UBound(dict.Items()(i)(0))
            arrFin(k, j + 1) = dict.Items()(i)(0)(j): 'Stop
        Next j
        'fill the rest of the final array columns corresponding to associated IDs
        For j = 0 To UBound(dict.Items()(i)(1)(m))
            arrFin(k, j + 6) = dict.Items()(i)(1)(m)(j): 'Stop
        Next j
    Next m
  Next i
  
  'Drop the final array content, at once:
  With destws.Range("A1").Resize(UBound(arrFin), UBound(arrFin, 2))
    .Value2 = arrFin
    .EntireColumn.AutoFit
  End With
  
  MsgBox "Ready..."
End Sub

字符串

628mspwn

628mspwn2#

作为对你对我的评论的回复的回应-这里有一些使用范围的方法。这包括@lorenz albert的建议(赞成)

Sub demo()

    'Method 1 - use the Range to copy/paste instead of column by column or row by row
    ThisWorkbook.Sheets("Sheet1").Range("A4:I5").Copy ThisWorkbook.Sheets("Sheet2").Range("A3:I4")

    'Method 2 - assign the values directly
    ThisWorkbook.Sheets("Sheet2").Range("A5:I6").Value = ThisWorkbook.Sheets("Sheet1").Range("A6:I7").Value
    
    'Method 3 - use arrays as an intermediary - useful if you need to examine or amend the contents of any cells first
    Dim vArr As Variant
    vArr = ThisWorkbook.Sheets("Sheet1").Range("A8:I9").Value
    ThisWorkbook.Sheets("Sheet2").Range("A7:I8").Value = vArr

End Sub

字符串

相关问题