Reputation: 306
I'm working with a dataset in Excel that represents journal entries, and I'm encountering an issue where parts of a transaction are on the wrong row. I need a VBA macro that can identify the start of a transaction, find all related rows that belong to it, and shift these rows up to align correctly with the transaction's starting point.
The transaction data follows these rules:
The challenge is:
Current Macro Behavior:
Example of Issue:
Please note:
Here's the core part of the macro I'm using:
Sub HighlightAndFixGlitches()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Clean Journals") ' Change to your actual sheet name if different
Dim lastRow As Long
Dim startRow As Long
Dim endRow As Long
Dim i As Long
Dim j As Long
Application.ScreenUpdating = False ' Disable screen updating for performance
With ws
lastRow = .Cells(.Rows.Count, "I").End(xlUp).row ' Assuming column I ('journal_id') indicates new transactions
' Loop through each row from bottom to top
For i = lastRow To 2 Step -1
' Highlight the row if 'invoice_date', 'payment_reference', 'journal_id' are filled and 'account_id' is empty
If Not IsEmpty(.Cells(i, "I")) And IsEmpty(.Cells(i, "T")) Then
.Rows(i).Interior.Color = RGB(255, 0, 0) ' Highlight in red
' Find the start and end of the current transaction block
startRow = i
endRow = i
While IsEmpty(.Cells(startRow - 1, "I")) And startRow > 2
startRow = startRow - 1
Wend
While IsEmpty(.Cells(endRow + 1, "I")) And endRow < lastRow
endRow = endRow + 1
Wend
' Shift all rows from startRow to endRow up by one row
For j = startRow To endRow
.Range(.Cells(j + 1, "K"), .Cells(j + 1, "AJ")).Copy
.Range(.Cells(j, "K"), .Cells(j, "AJ")).PasteSpecial Paste:=xlPasteValues
.Range(.Cells(j + 1, "K"), .Cells(j + 1, "AJ")).ClearContents
Next j
' We need to skip the shifted block to avoid reprocessing
i = startRow - 1
End If
Next i
End With
Application.CutCopyMode = False ' Clear clipboard
Application.ScreenUpdating = True ' Re-enable screen updating
End Sub
I suspect the issue might be related to how I'm identifying the transaction blocks or perhaps in the loop logic that shifts the rows.
My question is:
How can I adjust my VBA macro to consistently identify the full block of rows for each transaction and shift them up correctly without affecting the already aligned transactions?
Upvotes: 0
Views: 83
Reputation: 18778
Your code is close to finish.
lastRow
by the content in column AOption Explicit
Sub HighlightAndFixGlitches()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Clean Journals") ' Change to your actual sheet name if different
Dim lastRow As Long
Dim endRow As Long
Dim i As Long
Dim j As Long
Application.ScreenUpdating = False ' Disable screen updating for performance
With ws
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row ' Assuming column I ('journal_id') indicates new transactions
endRow = 0
' Loop through each row from bottom to top
For i = lastRow To 2 Step -1
If IsEmpty(.Cells(i, "I")) Then
If endRow = 0 Then endRow = i
Else
If IsEmpty(.Cells(i, "T")) Then
.Rows(i).Interior.Color = RGB(255, 0, 0) ' Highlight in red
For j = i To endRow - 1
.Range(.Cells(j, "K"), .Cells(j, "AJ")).Value = .Range(.Cells(j + 1, "K"), .Cells(j + 1, "AJ")).Value
Next j
.Range(.Cells(endRow, "K"), .Cells(endRow, "AJ")).ClearContents
End If
endRow = 0
End If
Next i
End With
Application.ScreenUpdating = True ' Re-enable screen updating
End Sub
Upvotes: 1
Reputation: 1162
Here's the code which should do the trick.
You have to update the range to copy according to your data: Range(sht.Cells(i + 1, 10), sht.Cells(i + j, 21)).Cut sht.Cells(i, 10)
- the last cell here is sht.Cells(i + j, 21)
which is an equivalent for the column U.
Dim sht As Worksheet
Set sht = ThisWorkbook.Sheets("Clean Journals")
Dim lRow As Long, i As Long, j As Integer
' get the last row in column "journal_id"
lRow = sht.Cells(Rows.Count, 9).End(xlUp).Row
' looping through the "journal_id" column from Top to Bottom
For i = 2 To lRow
' identifying shifted data: "journal_id" is not empty and "invoice_line_ids/account_ids"
' is empty (column T in your file)
If Not sht.Cells(i, 9).Value = "" And sht.Cells(i, 20) = "" Then
' assigning variable to jump 1 row below to find out
' how many rows in this transaction
j = 1
' looping through column "invoice_line_ids/account_ids" (T)
' until "journal_id" is empty and it is not
Do While sht.Cells(i + j, 4).Value = "" And Not sht.Cells(i + j, 7).Value = ""
j = j + 1
Loop
' removing one row jump to bottom
j = j - 1
' moving the range with needed data to its place,
' depending on number of rows in transaction
Range(sht.Cells(i + 1, 10), sht.Cells(i + j, 21)).Cut sht.Cells(i, 10)
' removing the blank row, which is left after we moved data
sht.Cells(i + j, 1).EntireRow.Delete
' re-determining the last row because we have deleted some of them
' one step up
lRow = sht.Cells(Rows.Count, 9).End(xlUp).Row
End If
Next
Upvotes: 0