In Ledger commander the rows in account balances are generated automatically. Each account has an opening date and a closing date. If the account is not closed then the current day can be used as closing date. You take each account and each date from the Dates table and if the selected date is in the [opening date; closing date] period for the selected account then an account balance row is created. In Ledger commander this is done by an Sql query. In Scutum ledger there are two options.
Manual row creation
You have to fill the Id, Date Id and Account Id manually, the rest of the columns are calculated automatically. You have to perform the algorithm above by hand. Fortunately, you do not open or close an account every month so creating the rows for a new date can be fast.
Here you already have the rows for Date Id 7.
Drag down the selection and refresh the sheet. Of course, if you closed an account, for example, the Cib current account in mid February then delete the row where the Id is 30.
Row generation by macro
I f you prefer the automatic generation of the account balance rows then enable the macros and press the "Generate Account Balances" button.
Public Sub GenearteAccountBalances() Dim dateSheet As Worksheet Set dateSheet = Worksheets("Dates") Dim dateDates As Range Set dateDates = dateSheet.Range("Dates[Date]") Set accountSheet = Worksheets("Accounts") Dim accountIds As Range Set accountIds = accountSheet.Range("Accounts[Id]") Dim result As Boolean
Dim creates a variable and Set will assign a value to the variable. dateSheet represents a worksheet of the excel workbook. In the next row we say we need the worksheet whose name is "Dates". So you know if you change the name of the worksheet (e.g., you localize it) then this macro should be modified as well.
Next we create a Range which is a bunch of excel cells. dateDates corresponds to the Date column of the Dates table. Notice that "Dates" is the name of the sheet but also the name of a table. Also notice that the sheet where the table can be found had to be also provided.
Next the accountSheet and the accountIds range is created. In the naming of a column table the first part refers to the table, the second to the column. So, now we are talking about the Id column of the account table. At the end, a Boolean variable is created.
Dim parametersSheet As Worksheet Set parametersSheet = Worksheets("Parameters") Dim baseCurrencyId As Integer baseCurrencyId = parametersSheet.Range("Parameters[Base currency Id]").Value2 Dim AccountBalancesSheet As Worksheet Set AccountBalancesSheet = Worksheets("AccountBalances") Dim accountBalancesIdRange As Range Set accountBalancesIdRange = AccountBalancesSheet.Range("AccountBalances[Id]") Dim accountBalancesDateIdRange As Range Set accountBalancesDateIdRange = AccountBalancesSheet.Range("AccountBalances[Date Id]") Dim accountBalancesAccountIdRange As Range Set accountBalancesAccountIdRange = AccountBalancesSheet.Range("AccountBalances[Account Id]")
The parametersSheet has no novelty but then an integer is created, baseCurrencyId. We create a range for a column as before but then we use the Value2 property to give back the value of a cell. The parameters table contains a single row, so it is unambiguous which cell we mean. The rest of the code creates variables which will be used later.
'based on Account.Id Dim typeIdOffset As Integer typeIdOffset = 2 Dim openingDateOffset As Integer openingDateOffset = 14 Dim closingDateOffset As Integer closingDateOffset = 15
The first row is a comment. Next we create integer constants about the Account table. For example, the openingDateOffset specifies the column position of the opening date of an account. If you reorder the columns in the Account table then these constants must be also modified.
'Delete old values accountBalancesIdRange.Clear accountBalancesDateIdRange.Clear accountBalancesAccountIdRange.Clear
'Calculate numberOfRows numberOfRows = 0 For Each validDate In dateDates For Each accountId In accountIds If accountId.Offset(0, typeIdOffset).Value2 = 1 Then 'if Asset account result = IsDateInPeriod(validDate, accountId.Offset(0, openingDateOffset), accountId.Offset(0, closingDateOffset)) If result Then numberOfRows = numberOfRows + 1 End If End If Next accountId Next validDate
'Resize the table (does not delete if the table is decreased) Dim AccountBalances As ListObject Set AccountBalances = AccountBalancesSheet.ListObjects("AccountBalances") If AccountBalances.Range.Rows.Count - 2 <= numberOfRows Then correctedNumberOfRows = numberOfRows + 2 Else correctedNumberOfRows = numberOfRows + 1 End If AccountBalances.Resize AccountBalances.Range.Resize(correctedNumberOfRows)
The AccountBalances table is defined here with the ListObjects method. According to my experience it is not enough to use the Resize method with the numberOfRows variable but you have to modify this variable depending on increase or decrease. The last row uses the Resize method twice because first the range of the table has to be resized then the table itself based on the new range.
'Write new values actualRow = 1 For Each validDate In dateDates For Each accountId In accountIds If accountId.Offset(0, 2).Value2 = 1 Then 'if Asset account result = IsDateInPeriod(validDate, accountId.Offset(0, openingDateOffset), accountId.Offset(0, closingDateOffset)) 'is account alive If result Then dateId = validDate.Offset(0, -1) accountBalancesIdRange.Cells(actualRow, 1) = actualRow accountBalancesDateIdRange.Cells(actualRow, 1) = dateId accountBalancesAccountIdRange.Cells(actualRow, 1) = accountId actualRow = actualRow + 1 End If End If Next accountId Next validDate End Sub
This code is very similar to the size calculation. The difference is that inside the second loop the dateId is determined. Then the actualRow, the dateId and the accountId is set. accountBalancesDateIdRange represents a column, the Cell method selects the actual row in that column.
Public Function IsDateInPeriod(ByVal actDate As Date, ByVal openingDate As Date, ByVal closingDate As Date) As Boolean 'check if the validDate is in ]opening date; closingDate[ If openingDate < actDate And (actDate <= closingDate Or closingDate = 0) Then IsDateInPeriod = True Else IsDateInPeriod = False End If End Function
IsDateInPeriod is a function which returns true if the first parameter is between the next two parameters. If the third parameter is 0 it means the account is not closed which must be taken into account.