How do i make a cell's colspan depend on the column title (in my data)?

i tried my best to make as small a reproduction i could and the below is what i came up with. what i mean with the title is i have a column title (Commodity Description) and i need to span 2 columns. but i want cells under that column title to span 2 columns as well.

i have below my Typst template and JSON data, and i confirm it works if you input it in Typst app.

this is what it looks like:

Hot Dogs and Grand Total need to occupy both columns of Commodity Description

Typst:

#set text(font: "Public Sans", size: 7pt, top-edge: 0.4em)

#let data = json("data-repro.json").shipments.at(0)

#if data.carrierInfo.tableInfo.len() > 4 {

for page in data.carrierInfo.supplementalPages {

let supplementalCarrierInformation = [  
  #table(
    columns: (10),
    align: center+bottom,
    table.cell(colspan: 2, inset: (top: 15pt), align: bottom)[#strong[Handling Unit]],
    table.cell(colspan: 2, inset: (top: 15pt))[#strong[Package Unit]],
    table.cell()[],
    table.cell()[],
    table.cell(colspan: 2, rowspan: 2)[
      #strong[Commodity Description]
      #linebreak()
      Commodities require special or additional care or attention in handling or stowing must be so marked and packaged as to ensure safe transport with ordinary care. See Section 2(e) or NMFC Item 360
    ],
    table.cell(colspan: 2, inset: (top: 15pt))[#text(red)[#strong[LTL Only]]],
    table.cell()[#strong[Qty]],
    table.cell()[#strong[Type]],
    table.cell()[#strong[Qty]],
    table.cell()[#strong[Type]],
    table.cell()[#strong[Weight]],
    table.cell()[#strong[H/M]],
    table.cell()[#strong[Class]],
    table.cell()[#strong[NMFC]],
    ..for row in page {(  
      ..for value in row.values() {(
        table.cell()[
            #value
        ],
      )}
    )},
    [],
    [],
    [],
    [],
    [],
    [],
    table.cell()[Grand Total],
  )
]


grid(
  columns: (1fr, 1fr),
  inset: 5pt,
  stroke: black,
  grid.cell(colspan: 2)[#supplementalCarrierInformation]
)

}

}

JSON:

{
  "shipments": [
    {
      "carrierInfo": {
        "tableInfo": [
          {
            "huQty": 4,
            "huType": "PALLET",
            "packageQty": 10,
            "packageType": "BOX",
            "weight": 5400,
            "hazmat": null,
            "commodity": "Hot Dogs",
            "class": 60,
            "nmfc": null,
            "bolPreview": null
          },
          {
            "huQty": null,
            "huType": null,
            "packageQty": null,
            "packageType": null,
            "weight": 1000,
            "hazmat": null,
            "commodity": "Ketchup",
            "class": 70,
            "nmfc": null,
            "bolPreview": null
          },
          {
            "huQty": null,
            "huType": null,
            "packageQty": null,
            "packageType": null,
            "weight": 1000,
            "hazmat": null,
            "commodity": "Mustard",
            "class": 55,
            "nmfc": null,
            "bolPreview": null
          },
          {
            "huQty": null,
            "huType": null,
            "packageQty": 8,
            "packageType": "BAG",
            "weight": 500,
            "hazmat": null,
            "commodity": "Rolls",
            "class": 92.5,
            "nmfc": null,
            "bolPreview": null
          },
          {
            "huQty": null,
            "huType": null,
            "packageQty": null,
            "packageType": null,
            "weight": 500,
            "hazmat": null,
            "commodity": "Buns",
            "class": 92.5,
            "nmfc": null,
            "bolPreview": null
          }
        ],
        "supplementalPages": [
          [
            {
              "huQty": 4,
              "huType": "PALLET",
              "packageQty": 10,
              "packageType": "BOX",
              "weight": 5400,
              "hazmat": null,
              "commodity": "Hot Dogs",
              "class": 60,
              "nmfc": null,
              "bolPreview": null
            }
          ]
        ]
      }
    }
  ]
}

Hello. First of all, please read how to properly add code blocks in How to post in the Questions category.

Next, your code is not small at all, but at least the result is reproducible. Try to cut away anything that doesn’t change the output and is not the main point of the example. Like this:

#let data = ```json
[
  [
    {
      "huQty": 4,
      "huType": "PALLET",
      "packageQty": 10,
      "packageType": "BOX",
      "weight": 5400,
      "hazmat": null,
      "commodity": "Hot Dogs",
      "class": 60,
      "nmfc": null,
      "bolPreview": null
    }
  ]
]
```.text

#let supplementalPages = json(bytes(data))

#set text(size: 7pt, top-edge: 0.4em)

#for page in supplementalPages {
  rect(table(
    columns: 10,
    align: center + bottom,
    table.header(
      table.cell(colspan: 2, inset: (top: 15pt))[*Handling Unit*],
      table.cell(colspan: 2)[*Package Unit*],
      [],
      [],
      table.cell(colspan: 2, rowspan: 2)[
        *Commodity Description* \
        Commodities require special or additional care or attention in handling or stowing must be so marked and packaged as to ensure safe transport with ordinary care. See Section 2(e) or NMFC Item 360
      ],
      table.cell(colspan: 2, text(red)[*LTL Only*]),
      [*Qty*],
      [*Type*],
      [*Qty*],
      [*Type*],
      [*Weight*],
      [*H/M*],
      [*Class*],
      [*NMFC*],
    ),
    ..page.map(row => row.values().map(v => [#v])).flatten(),
    table.cell(x: 6)[Grand Total],
  ))
}

Though you don’t have to put data in the same file.


What I’m reading is that you need to make “Commodity Description” cell to be 2 columns wide which you already did. And as for cells under that, I read that you want to do

    ..page
      .map(row => row
        .values()
        .enumerate()
        .filter(((i, _)) => i != 7)
        .map(((i, v)) => if i == 6 { table.cell(colspan: 2)[#v] } else [#v]))
      .flatten(),
    table.cell(x: 6, colspan: 2)[Grand Total],

And as a result completely discard second subcolumn because left cells need 2 columns. Making left and right cells 2 columns wide is impossible, because the parent uses only 2 columns total, not 4. So this is the part that I don’t understand at all.

You can read about table basics in Table guide – Typst Documentation.

1 Like

thanks a lot for the reply @Andrew!
i now understand how to add Typst code blocks.
the only problem now is that the filtered out values need to actually be under the Class column.

i wanted a way to “push” those values under the Class column and the way i thought about it was that Hot Dogs and the values under that needed to occupy the full colspan of Commodity Description.

basically i don’t want to lose any values, just push those to the right.

does this make better sense?

If you do, please update your post so that it uses appropriate syntax highlighting for Typst and JSON.

Then why do you span the top cell 2 columns? Don’t do it and you won’t have to push anything.

code
#for page in supplementalPages {
  rect(table(
    columns: page.first().len() - 1,
    align: center + bottom,
    table.header(
      table.cell(colspan: 2, inset: (top: 15pt))[*Handling Unit*],
      table.cell(colspan: 2)[*Package Unit*],
      [],
      [],
      table.cell(rowspan: 2)[
        *Commodity Description* \
        Commodities require special or additional care or attention in handling or stowing must be so marked and packaged as to ensure safe transport with ordinary care. See Section 2(e) or NMFC Item 360
      ],
      table.cell(colspan: 2, text(red)[*LTL Only*]),
      [*Qty*],
      [*Type*],
      [*Qty*],
      [*Type*],
      [*Weight*],
      [*H/M*],
      [*Class*],
      [*NMFC*],
    ),
    ..page.map(row => row.values().map(v => [#v])).flatten(),
    table.cell(x: 6)[Grand Total],
  ))
}

thanks a lot for all the help and feedback @Andrew! i have updated my code blocks, and if you have a suggestion for a more proper post title, i can update it too.

1 Like

Well, it’s hard to do it without putting the answer in it. And also, the answer would be still different from the question because the actual problem differs from the OP.

How do I automatically change colspan of data cells from one column?

But the answer, after understanding how table supposed to look like, would be to not add colspan to the top cell in the column (and reduce columns number).