EDIT: enter the number of columns in the group from 3 to N (ColumnInGroup)
EDIT: Some bugs are fixed and an empty "NAME" field is allowed, the type "T" is considered as existing if there is a name, start date, end date, improved performance, assigning a block instead of a cell to the ROW unit
EDIT: bug fixed
EDIT: I get the value of these constants in VBA, you open excel, Alt + F11 to open the VB Editor, Crtl + G open the nearest window, enter ?xlUp , it will show the xlUp value below
The code below is in VBS, it works on the sheet that you are showing now and the performance should be fine ... Change the full path of the book, the name of the worksheet to use
Option Explicit Dim xlApp Dim xlBook dim xlSheet Set xlApp = CreateObject("Excel.Application") xlApp.Visible = False xlApp.EnableEvents = False xlApp.ScreenUpdating = False 'xlApp.Calculation = -4135 'xlCalculationManual set xlBook = xlApp.Workbooks.Open("C:\Users\wangCL\Desktop\data.xlsx") set xlSheet = xlBook.Worksheets("data (4)") 'CONTENT HERE Dim count Dim dataArray Dim height Dim width Dim rWidth Dim packArray Dim i Dim j dim rowArray dim ColumnInGroup dim k dim b With xlSheet .activate ColumnInGroup= 4 height = .Cells(.Rows.count, 1).End(-4162).Row ' assume 1st line is header ' start from 2nd line If height > 1 Then For i = 2 To height width = .Cells(i, .Columns.count).End(-4159).Column 'round width if (width -1 )mod columnInGroup <> 0 then width = (((width -1)\columnInGroup )+1)* columnInGroup + 1 end if if width > 1 then 'finding the last unit originally packed redim rowArray(0,width-1) rowArray = .range(.cells(i,1), .cells(i,width)).value 'default value rWidth = width for j = 2 to width step ColumnInGroup if j+ColumnInGroup -1 <= width then b = false for k = 0 to ColumnInGroup - 1 if rowArray(1,j+k) <> "" then b = true exit for end if next if not b then rWidth = j - 1 exit for end if else rWidth = width end if next 'rWidth = .Cells(i, 1).End(-4161).Column 'If .Cells(i, rWidth - 1).Value = "" Then ' rWidth = 1 'End If ''check for each new "T" - 1 'If rWidth Mod 3 = 0 Then ' rWidth = rWidth + 1 'ElseIf rWidth Mod 3 = 1 Then ' rWidth = rWidth 'ElseIf rWidth Mod 3 = 2 Then ' rWidth = rWidth + 2 'End If ' if is not packed If width > rWidth Then ReDim dataArray(1 ,(width - rWidth)) dataArray = .Range(.Cells(i, rWidth + 1), .Cells(i, width)).Value count = 0 For j = LBound(dataArray, 2) To UBound(dataArray, 2) Step ColumnInGroup if j+ColumnInGroup - 1<= ubound(dataArray,2) then b = false for k = 0 to ColumnInGroup - 1 if dataArray(1,j+k) <> "" then b = true exit for end if next if b then count = count + 1 end if else exit for end if Next ReDim packArray(0, count * columnInGroup - 1) count = 0 For j = LBound(dataArray, 2) To UBound(dataArray, 2) Step columnInGroup ' we found a "T" Unit if j+columnInGroup -1<= ubound(dataArray,2) then b = false for k = 0 to ColumnInGroup - 1 if dataArray(1,j+k) <> "" then b = true exit for end if next if b then count = count + 1 for k = 0 to columnInGroup - 1 If j + k <= UBound(dataArray, 2) Then packArray(0, (count - 1) * columnInGroup + k ) = dataArray(1, j + k) end if next end if else exit for end if Next 'clear original data .Range(.Cells(i, rWidth + 1), .Cells(i, width)).ClearContents 'for j = 1 to ubound(packArray,2) ' .cells(i,rWidth+j).value = packArray(1,j) ' next .Range(.Cells(i, rWidth + 1), .Cells(i, rWidth + count * columnInGroup)).Value = packArray End If end if Next End If End With xlBook.save xlApp.Quit set xlSheet = nothing set xlBook = nothing set xlApp = nothing msgbox "Done"