Bank statement

Generate a simple bank statement with Carbone

Download Template

Download data sample

  • Template type document docx expert
  • Carbone min. v5.0.0+
  • Features loop set count aggregator subtotal
  • Target bank insurance quote custom

Objectives

You want to generate a bank statement with the following features:

  • Display an intermediate balance on each page.
  • The number of lines that fit on each page is fixed.

Solution

Here’s how you can achieve this using Carbone:

Structuring data by page

  1. Based on your layout settings, estimate:

    • the number of block-lines that fit on a page (e.g., 15)
  2. Compute the objects to be printed on a same page using {d.operations[]:cumCount():div(15):ceil:set(.numPage)} where:

    • the cumulative count of entries cumCount is divided div by the number of block-lines (15), and rounded up ceil to the nearest whole number
    • the result is stored in a new variable using :set(.numPage).

    At this stage, each object has a new property named numPage, which indicates the page number on which it will be printed.

  3. Restructure the datas into a new array d.group by grouping objects that share the same numPage, using the following formula: {d.operations[]:set(d.group[id=.numPage].data[])}

  4. Use this new structure in the template to print the data: {d.group[i].data[i].transaction}.

JSON Before

{
  "operations": [
    {
      "transaction": "School fees payment",
      "amount": -300
    },
    {...},
    {
      "transaction": "Supermarket shopping",
      "amount": -130.2
    },
    {...}
  ]
}

JSON After

{
  "operations": [
    ...
  ],
  "group":[
    {
      "data": [
      {
        "transaction": "School fees payment",
        "amount": -300,
        "numPage": 1
      },
      {...}
      ]
    },
    {
      "data": [
      {
        "transaction": "Supermarket shopping",
        "amount": -130.2,
        "numPage": 2
      },
      {...}
      ]
    }
  ]
}

Subtotal computation

To print the subtotal per page, use the aggSum formatter.

In our example, since there is a column for debits and a column for credits, the subtotals are computed as follows:

  • For debits (negative amounts), set positive amounts to 0 using :ifGTE(0):show(0) before aggSum: {d.group[i].data[].amount:ifGTE(0):show(0):aggSum:formatC}

  • For credits (positive amounts), set negative amounts to 0 using :ifLT(0):show(0) before aggSum: {d.group[i].data[].amount:ifLT(0):show(0):aggSum:formatC}

Intermediate balance computation

To print the intermediate balance, combine the aggSum formatter with the cumSum formatter, and add it to the open_bal stored in the JSON:{d.group[i].data[].amount:aggSum:cumSum:add(...open_bal):formatC}`

Extra tip / Pagination

To ensure consistent rendering, insert a page break between each page. Define it after the different elements to be displayed on the same page and before the iteration [i+1].

As a result, the report ends with a final blank page. To avoid this, delete the page break conditionally if the last element of the list is printed. Use the following formula on the paragraph of the page break: {d.group[i]..group:len():sub(1):ifEQ(.i):drop(p)} , where

  • {d.list[i] : Access the list element using the iterator [i], the index i will be used for the condition.
  • ..list:len() : Retrieve the length of the list by backtracking to the parent object.
  • :sub(1): Subtract one from the list length, accounting for zero-based indexing. (The list length is counted from one, however the index from [i] is starting from zero.)
  • :ifEQ(.i):drop(p)}: Delete the paragraph, including the page break, if the current index .i is equal to the list size, indicating the last element.

And there you go!

Alternatives

Trusted by 600+ paid customers in 40+ countries

Finance
Healthcare
Public
Retail
Industries
Energy
Software
Telecom
1dior.png
22thales.png
23younited.png
2danfoss.png
3cma-cgm.png
3illumina.svg
4KparK.png
6scalingo.png
7defense.png
8bmw.png
8telus.png
bestseller.png
flagship_bioscience.png
insly.png
ninox.png
sodexo.png