Forum Discussion
KanwalNo1
May 25, 2024Iron Contributor
Allocating / Apportioning Challan Amounts to Different Receipts
(I Apologize Friends! I made the unpardonable mistake of uploading the wrong file here. Now I have Uploaded the correct file here. I sincerely apologize for the inconvenience ! Challan Allocation Ap...
- May 27, 2024
KanwalNo1 Thank you for providing the new file and additional clarification. The updated code below should do the trick for allocating amounts by ID and recording any shortages:
Option Explicit Sub AllocateReceipts() 'Clear the previous output range Application.ScreenUpdating = False Dim wsOutput As Worksheet Set wsOutput = Worksheets("ChallanAllocation") wsOutput.Range("A1").CurrentRegion.Offset(1).ClearContents 'Sort each table by id and date Dim loCha As ListObject, loRec As ListObject Set loCha = Worksheets("Challan").ListObjects("Challan") Set loRec = Worksheets("Receipts").ListObjects("Receipts") Call SortTable(loCha, 1, 3) Call SortTable(loRec, 1, 3) 'Load each table into an array Dim cha As Variant, rec As Variant cha = loCha.DataBodyRange.Value rec = loRec.DataBodyRange.Value 'Allocate receipts to challan amounts Dim arr(1 To 1, 1 To 6) As Variant, id As Variant, rowId As Long, i As Long, j As Long, k As Double rowId = 2 For i = 1 To UBound(rec, 1) ' check for new receipt id If rec(i, 1) <> id Then ' reset id and running total id = rec(i, 1) k = 0 End If ' validate receipt amount If rec(i, 4) > 0 Then ' loop through challan array until receipt amount has been exhausted For j = 1 To UBound(cha, 1) ' only allocate challan amounts with matching ids If cha(j, 1) = id And cha(j, 4) > 0 Then ' copy the transaction details to an array arr(1, 1) = rec(i, 1) '<-------------------------------------- ID arr(1, 2) = rec(i, 3) '<-------------------------------------- Receipt Date arr(1, 3) = IIf(cha(j, 4) < rec(i, 4), cha(j, 4), rec(i, 4)) ' Amount arr(1, 4) = arr(1, 3) + k '<---------------------------------- Running Total arr(1, 5) = cha(j, 2) '<-------------------------------------- CIN arr(1, 6) = cha(j, 3) '<-------------------------------------- CIN Date ' write the transaction array to the next output row wsOutput.Cells(rowId, 1).Resize(, 6).Value = arr rowId = rowId + 1 ' update the running total k = arr(1, 4) ' reduce the current amounts by the transaction amount cha(j, 4) = cha(j, 4) - arr(1, 3) rec(i, 4) = rec(i, 4) - arr(1, 3) If rec(i, 4) = 0 Then Exit For End If Next j ' verify receipt amount has been exhausted If rec(i, 4) > 0 Then ' record the shortage arr(1, 1) = rec(i, 1) '<--- ID arr(1, 2) = rec(i, 3) '<--- Receipt Date arr(1, 3) = rec(i, 4) '<--- Amount arr(1, 4) = arr(1, 3) + k ' Running Total arr(1, 5) = "Short" '<----- CIN arr(1, 6) = Null '<-------- CIN Date wsOutput.Cells(rowId, 1).Resize(, 6).Value = arr rowId = rowId + 1 k = arr(1, 4) End If End If Next i Application.ScreenUpdating = True End Sub Private Sub SortTable(table As ListObject, field1 As Long, field2 As Long) With table.Sort.SortFields .Clear .Add2 Key:=table.ListColumns(field1).Range, Order:=xlAscending .Add2 Key:=table.ListColumns(field2).Range, Order:=xlAscending End With With table.Sort .Header = xlYes .MatchCase = False .Orientation = xlTopToBottom .SortMethod = xlPinYin .Apply End With End Sub
Let me know how it goes. Cheers!
KanwalNo1
May 26, 2024Iron Contributor
Thanks Sir !
It seems to work perfectly as per the data provided in the original file.
Let me clarify that the actual purpose is to allocate the ID wise TOTAL Challan Amount to ID wise TOTAL Receipts, to the extent possible. It is not relevant whether the challan date is earlier or later than the receipt date. The JOINT sorting in the ChallanAllocation table is just to display the method of splitting the entries in case the challan need to be allocated.
So if for an ID
Challan Amount > Receipt Amount, we need to ignore that EXTRA amount and move to next ID. This Challan balance will be used in the next period for Allocation with the forthcoming period receipt entries.
Receipt Amount > Challan Amount, it means a shortfall in payment and so "Short" need to be mentioned instead of the CIN
djclements
May 27, 2024Bronze Contributor
KanwalNo1 Thank you for providing the new file and additional clarification. The updated code below should do the trick for allocating amounts by ID and recording any shortages:
Option Explicit
Sub AllocateReceipts()
'Clear the previous output range
Application.ScreenUpdating = False
Dim wsOutput As Worksheet
Set wsOutput = Worksheets("ChallanAllocation")
wsOutput.Range("A1").CurrentRegion.Offset(1).ClearContents
'Sort each table by id and date
Dim loCha As ListObject, loRec As ListObject
Set loCha = Worksheets("Challan").ListObjects("Challan")
Set loRec = Worksheets("Receipts").ListObjects("Receipts")
Call SortTable(loCha, 1, 3)
Call SortTable(loRec, 1, 3)
'Load each table into an array
Dim cha As Variant, rec As Variant
cha = loCha.DataBodyRange.Value
rec = loRec.DataBodyRange.Value
'Allocate receipts to challan amounts
Dim arr(1 To 1, 1 To 6) As Variant, id As Variant, rowId As Long, i As Long, j As Long, k As Double
rowId = 2
For i = 1 To UBound(rec, 1)
' check for new receipt id
If rec(i, 1) <> id Then
' reset id and running total
id = rec(i, 1)
k = 0
End If
' validate receipt amount
If rec(i, 4) > 0 Then
' loop through challan array until receipt amount has been exhausted
For j = 1 To UBound(cha, 1)
' only allocate challan amounts with matching ids
If cha(j, 1) = id And cha(j, 4) > 0 Then
' copy the transaction details to an array
arr(1, 1) = rec(i, 1) '<-------------------------------------- ID
arr(1, 2) = rec(i, 3) '<-------------------------------------- Receipt Date
arr(1, 3) = IIf(cha(j, 4) < rec(i, 4), cha(j, 4), rec(i, 4)) ' Amount
arr(1, 4) = arr(1, 3) + k '<---------------------------------- Running Total
arr(1, 5) = cha(j, 2) '<-------------------------------------- CIN
arr(1, 6) = cha(j, 3) '<-------------------------------------- CIN Date
' write the transaction array to the next output row
wsOutput.Cells(rowId, 1).Resize(, 6).Value = arr
rowId = rowId + 1
' update the running total
k = arr(1, 4)
' reduce the current amounts by the transaction amount
cha(j, 4) = cha(j, 4) - arr(1, 3)
rec(i, 4) = rec(i, 4) - arr(1, 3)
If rec(i, 4) = 0 Then Exit For
End If
Next j
' verify receipt amount has been exhausted
If rec(i, 4) > 0 Then
' record the shortage
arr(1, 1) = rec(i, 1) '<--- ID
arr(1, 2) = rec(i, 3) '<--- Receipt Date
arr(1, 3) = rec(i, 4) '<--- Amount
arr(1, 4) = arr(1, 3) + k ' Running Total
arr(1, 5) = "Short" '<----- CIN
arr(1, 6) = Null '<-------- CIN Date
wsOutput.Cells(rowId, 1).Resize(, 6).Value = arr
rowId = rowId + 1
k = arr(1, 4)
End If
End If
Next i
Application.ScreenUpdating = True
End Sub
Private Sub SortTable(table As ListObject, field1 As Long, field2 As Long)
With table.Sort.SortFields
.Clear
.Add2 Key:=table.ListColumns(field1).Range, Order:=xlAscending
.Add2 Key:=table.ListColumns(field2).Range, Order:=xlAscending
End With
With table.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
Let me know how it goes. Cheers!
- KanwalNo1May 27, 2024Iron Contributor
djclements
Wooooooo ! You are a professional / passionate VBA Developer ! It looks great Sir !I tried the following scenarios.
1. Changed the Challan amount in D18 to 1450. As expected, the row to add the "Short" entry was gone and receipt fully allocated. (10/10)
2. Changed the Challan Amount in D18 to 650. Shortfall inreased to 750 from 650 (10/10)3. Changed the ID in A16 (Challan) to A03. But no receipt was shown in Receipt sheet for this ID. As expected, Shortfall was calculated correctly. The challan balance for A03 will be carried forward. (10/10)
4. Changed the ID in A33 in Receipts without any corresponding change in Challan sheet. Code updated the entry to reflect the changes for A02 and added a new entry for A03 shortfall (10/10)
Full Marks Sir!
I got late in submitting a new workbook with two additional columns in Challan sheet, which also need to be carried to ExpectedResults sheet. I have appended that new file too in the original question.
I am going to accept this answer as final. I request that If there are not too many modifications involved, then can you have a look at those columns which are there and need to be included in final results. Highly appreciated! No strings attached. It was my mistake to have overseen those columns.
This place has its worth in GOLD due to people like you! MAY the Almighty Bless you!
Sincere Regards
Kanwaljit
- djclementsMay 27, 2024Bronze Contributor
KanwalNo1 Sorry, I must have been working on Rev.2 when you uploaded Rev.3. Here's the updated code to work with the additional columns:
Option Explicit Sub AllocateReceipts() 'Clear the previous output range Application.ScreenUpdating = False Dim wsOutput As Worksheet Set wsOutput = Worksheets("ChallanAllocation") wsOutput.Range("A1").CurrentRegion.Offset(1).ClearContents 'Sort each table by id and date Dim loCha As ListObject, loRec As ListObject Set loCha = Worksheets("Challan").ListObjects("Challan") Set loRec = Worksheets("Receipts").ListObjects("Receipts") Call SortTable(loCha, 1, 3) Call SortTable(loRec, 1, 4, 3) 'Load each table into an array Dim cha As Variant, rec As Variant cha = loCha.DataBodyRange.Value rec = loRec.DataBodyRange.Value 'Allocate receipts to challan amounts Dim arr(1 To 1, 1 To 😎 As Variant, id As Variant, rowId As Long, i As Long, j As Long, k As Double rowId = 2 For i = 1 To UBound(rec, 1) ' check for new receipt id If rec(i, 1) <> id Then ' reset id and running total id = rec(i, 1) k = 0 End If ' validate receipt amount If rec(i, 5) > 0 Then ' loop through challan array until receipt amount has been exhausted For j = 1 To UBound(cha, 1) ' only allocate challan amounts with matching ids If cha(j, 1) = id And cha(j, 4) > 0 Then ' copy the transaction details to an array arr(1, 1) = rec(i, 1) '<----------------------------------- ID arr(1, 2) = rec(i, 3) '<----------------------------------- Party arr(1, 3) = rec(i, 4) '<----------------------------------- Receipt Date arr(1, 4) = WorksheetFunction.Min(cha(j, 4), rec(i, 5)) ' Amount arr(1, 5) = WorksheetFunction.Round(arr(1, 4) * 0.001, 0) ' Tax Amt arr(1, 6) = arr(1, 4) + k '<------------------------------- Running Total arr(1, 7) = cha(j, 2) '<----------------------------------- CIN arr(1, 😎 = cha(j, 3) '<----------------------------------- CIN Date ' write the transaction array to the next output row wsOutput.Cells(rowId, 1).Resize(, 8).Value = arr rowId = rowId + 1 ' update the running total k = arr(1, 6) ' reduce the current amounts by the transaction amount cha(j, 4) = cha(j, 4) - arr(1, 4) rec(i, 5) = rec(i, 5) - arr(1, 4) If rec(i, 5) = 0 Then Exit For End If Next j ' verify receipt amount has been exhausted If rec(i, 5) > 0 Then ' record the shortage arr(1, 1) = rec(i, 1) '<----------------------------------- ID arr(1, 2) = rec(i, 3) '<----------------------------------- Party arr(1, 3) = rec(i, 4) '<----------------------------------- Receipt Date arr(1, 4) = rec(i, 5) '<----------------------------------- Amount arr(1, 5) = WorksheetFunction.Round(arr(1, 4) * 0.001, 0) ' Tax Amt arr(1, 6) = arr(1, 4) + k '<------------------------------- Running Total arr(1, 7) = "Short" '<------------------------------------- CIN arr(1, 😎 = Null '<---------------------------------------- CIN Date wsOutput.Cells(rowId, 1).Resize(, 8).Value = arr rowId = rowId + 1 k = arr(1, 6) End If End If Next i Application.ScreenUpdating = True End Sub Private Sub SortTable(table As ListObject, field1 As Long, field2 As Long, Optional field3 As Long) With table.Sort.SortFields .Clear .Add2 Key:=table.ListColumns(field1).Range, Order:=xlAscending .Add2 Key:=table.ListColumns(field2).Range, Order:=xlAscending If field3 > 0 Then .Add2 Key:=table.ListColumns(field3).Range, Order:=xlAscending End If End With With table.Sort .Header = xlYes .MatchCase = False .Orientation = xlTopToBottom .SortMethod = xlPinYin .Apply End With End Sub
Enjoy!
- KanwalNo1May 27, 2024Iron ContributorHeartily Appreciated!
No words are enough to convey my appreciation!
MAY the Almighty Bless you with Health and Happiness !