How to Collect Row Indices Based on Table Cell Content?

Hi everyone,

I’m trying to collect the line indices (y values) from a table where the cell in column 2 is empty. I attempted the following approach:

#let LinhasAmarelas_disso = (
  array..table.height()
  .where(i => table.cell(x: 2, y: i).body == [])
)

However, this doesn’t seem to work as expected. My goal is to later use LinhasAmarelas_disso to apply conditional formatting to specific lines (with fill).

Is there a correct way to dynamically collect and store these row indices in Typst? Or is there another recommended approach to achieve this?

Thanks in advance!

Here’s a function that I think does what you are looking for. It won’t count properly if you use any cells with colspan or rowspan. And it requires passing the arguments differently than a normal table: cells come first as an array, all other arguments afterwards.

#let countable(cells, rowToCount: 0, ..args) = {
  //Get the number of columns if given
  let columns = args.named().at("columns", default: 1)

  //Break cells into rows (skip first row which is assumed to be the header)
  let rows = cells.slice(1).chunks(columns)
  
  let totalRows = rows.len()

  //Filter a list of integers (0, 1, ...) based on whether the row with that index has
  // a blank in the correct place
  let rowIndices = range(totalRows).filter(i => rows.at(i).at(rowToCount) == [])

  //The actual table to be displayed
  table(
    ..args,
    ..cells
  )
  
  //Do something with the variable set earlier
  [Rows (not counting the header) where the #rowToCount#h(0pt)th cell is empty: #rowIndices]
}

#countable(
  (
    table.header([a], [b]),
    [1], [],
    [2], [doesn't count],
    [3], []
  ),
  rowToCount: 1,
  columns: 2,
)

#countable(
  (
    table.header([c], [d]),
    [4], [],
    [5], [doesn't count],
    [6], [also doesn't]
  ),
  rowToCount: 1,
  columns: 2,
)
Summary

image

It’s for a different use case, but the following post could be useful reading:

This effectively what @gezepi has done by defining the countable function.

Btw

You can get around this by splitting the args into the named and positional parts yourself:

#let countable(rowToCount: 0, ..args) = {
  let cells = args.pos()
  let args = args.named()

  //Get the number of columns if given
  let columns = args.named().at("columns", default: 1)
  // in case the columns are given as `(1fr, 1fr)` or similar
  if type(columns) == array { columns = coulumns.len() }
  ...
}

#countable(
  rowToCount: 1,
  columns: 2,
  table.header([a], [b]),
  [1], [],
  [2], [doesn't count],
  [3], [],
)

...

I have also added a small fix regarding counting columns. Feel free to incorporate any or all of this into your answer if you want :slight_smile:

1 Like