A User's view of Hledger

Learning about hledger

The code to generate random hledger transactions

As per last week’s plan, further down in this posting is the current version of my R code to generate random hledger transactions. The program uses the function create_random_transactions to, well, generate the random transactions. If you supply no arguments, as in create_random_transactions(), the program will give you 20 transactions from random dates that fall in the last 6 months.

If you prefer a different number of transactions, you can specify the number as the first argument. For example, to create 3 random dates, run create_random_transactions(3). When I ran this in early February of 2024, I got the following output:

2023-11-17 Mom&Pop 
   expenses:home                       $16.36 
   liabilities:Universal Credit Card  -$16.36 

2023-12-05 Mom&Pop 
   expenses:automotive   $13.34 
   assets:cash          -$13.34 

2024-01-17 Convenience 
   expenses:home   $18.99 
   assets:cash    -$18.99 

Additionally, you can choose a beginning date instead of the default one of 6 months prior to today’s date. For example: create_random_transactions(3, as.Date(“2024-01-01”)) gives us 3 transactions dated between the first of the year and today’s date (in my case, a date in early February, when I ran the above command):

2024-01-20 BigStore 
   expenses:groceries   $13.21 
   assets:cash         -$13.21 

2024-01-16 Sales-R-Us 
   expenses:automotive   $7.80 
   assets:cash          -$7.80 

2024-01-12 Convenience 
   expenses:groceries                  $22.77 
   liabilities:Universal Credit Card  -$22.77

Finally, if you need to adjust the end date, you can do so by specifying it as a third argument. For example, to create 3 random transactions in 2023, we could call create_random_transactions(3, as.Date(“2023-01-01”), as.Date(“2023-12-31”)). Output is shown below:

2023-03-04 BigStore 
   expenses:groceries                  $22.24 
   liabilities:Universal Credit Card  -$22.24 

2023-11-20 Sales-R-Us 
   expenses:automotive                 $15.12 
   liabilities:Universal Credit Card  -$15.12 

2023-06-25 Acme 
   expenses:automotive                 $17.24 
   liabilities:Universal Credit Card  -$17.24

And here is the full R code needed for the above to work. You can easily modify the program to change the payees, expense categories, and payment categories.

It still needs some more work, as when I copy and paste the output from the R console, the line returns get changed to a single character “^M.” I had to replace all the ^Ms with an actual return so that the text appeared in proper ledger/hledger format.

However, I can now very quickly generate example transactions to use when needed for educational videos or anything else.

payees <- list("BigStore", "Acme", "Sales-R-Us", "Mom&Pop", "Convenience")
expense_categories <- list("expenses:gas", "expenses:groceries", "expenses:entertainment", "expenses:home", "expenses:automotive")
payment_categories <- list("assets:checking", "liabilities:Universal Credit Card", "assets:cash")

create_random_transactions <- function(number_of_transactions=NULL, earliest_date=NULL, latest_date=NULL) {
  if(missing(number_of_transactions)) number_of_transactions <- 20
  if(missing(earliest_date)) earliest_date <- Sys.Date() - 180
  if(missing(latest_date)) latest_date <- Sys.Date()
  for (i in 1:number_of_transactions) {
    transaction_date <- get_a_date(earliest_date, latest_date)
    transaction_payee <- get_a_payee()
    transaction_expense_category <- get_an_expense_category()
    transaction_payment_category <- get_a_payment_category()
    width_expense_category <- nchar(transaction_expense_category)
    width_payment_category <- nchar(transaction_payment_category)
    width_difference <- width_expense_category - width_payment_category
    if(width_difference > 0) {
      pad_payment_string <- strrep(" ", width_difference)
      pad_expense_string <- " "
    }
    else {
      pad_expense_string <- strrep(" ", ((width_difference) * -1) + 1)
      pad_payment_string <- ""
    }
    expense_amount <- get_an_amount()
    negative_amount <- paste0("-", expense_amount)
    one_transaction <- paste(transaction_date, transaction_payee, "\n  ",
                             transaction_expense_category, pad_expense_string, expense_amount, "\n  ",
                             transaction_payment_category, pad_payment_string, negative_amount, "\n\n"
    )
    cat(one_transaction)
  }
}


get_a_date <- function(start_date, end_date) {
  days_diff <- end_date - start_date
  date_range <- 0:days_diff
  random_date <- sample(date_range, 1)
  new_date <- start_date + random_date
  return(new_date)
  }

get_a_payee <- function() {
  random_payee <- sample(1:length(payees), 1)
  return(payees[random_payee])
}

get_an_expense_category <- function(){
  random_expense_category <- sample(1:length(expense_categories), 1)
  return(expense_categories[random_expense_category])
}

get_an_amount <- function() {
  dollars <- sample(5:24, 1)
  cents <- sample(0:99, 1)
  cents <- sprintf("%02d", cents)
  amount_string <- paste0("$", dollars, ".", cents)
  return(amount_string)
}

get_a_payment_category <- function() {
  random_payment_category <- sample(1:length(payment_categories), 1)
  return(payment_categories[random_payment_category])
}