> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/latex/nl/diepgaande-artikelen/47-tex-tables-how-tex-calculates-spanned-column-widths.md).

# TeX-tabellen: Hoe TeX de breedtes van kolommen met samengevoegde cellen berekent

## Het doel van dit artikel

In dit artikel onderzoeken we hoe $$\mathrm\TeX$$ kolombreedtes van tabellen berekent wanneer tabellen items bevatten (bijv. tabelkoppen) die meerdere kolommen overspannen (bijv. met behulp van de $$\mathrm\TeX$$ primitieven `\omit` en `\span`). Met behulp van een eenvoudige [‘referentietabel’](#reference-table) als uitgangspunt creëren we een reeks voorbeelden — afgeleid van die referentietabel — door verschillende items aan te passen om overspannen kolommen te maken. Door het effect van die aanpassingen te onderzoeken kunnen we beginnen te begrijpen welk onderliggend algoritme dat $$\mathrm\TeX$$ wordt gebruikt om de breedte van overspannen kolommen te berekenen.

### Met behulp van $$\mathrm\TeX$$ niet $$\mathrm\LaTeX$$

Om te onderzoeken en uit te leggen *hoe* $$\mathrm\TeX$$ bepaalt welke breedtes overspannen kolommen krijgen, is het nodig om afstand te nemen van alle prachtige $$\mathrm\LaTeX$$ tabelpakketten en terug te keren naar fundamentele, laag-niveau (primitieve) tabelaanmaakcommando’s: in het bijzonder, `\halign{...}`, `\span` en `\omit`. [Bestaande $$\mathrm\TeX$$/$$\mathrm\LaTeX$$ tabelpakketten](https://ctan.org/topic/table) zijn natuurlijk essentiële productiviteitshulpmiddelen en bieden een schat aan uiterst nuttige functionaliteit waarmee gebruikers snel een enorme verscheidenheid aan tabelmateriaal kunnen produceren met behulp van $$\mathrm\LaTeX$$. Die pakketten bieden essentiële ‘macro-ondersteuning’ opgebouwd rond $$\mathrm\TeX$$’s gedrag op laag niveau en hun ontwikkelaars bieden zeer welkome abstracties en isolatielagen die de onderliggende complexiteit uit handen nemen. Veel van die pakketten zijn werkelijk ongelooflijke staaltjes van complexe $$\mathrm\TeX$$ programmering: we zouden allemaal dankbaar moeten zijn dat ze bestaan om ons te behoeden voor het gebruik van ruwe $$\mathrm\TeX$$!

Het eigenlijke algoritme dat $$\mathrm\TeX$$ gebruikt om de breedtes van overspannen kolommen te berekenen wordt uitgelegd op pagina 245 van de [$$\mathrm\TeX\text{book}$$](https://www.amazon.co.uk/TeXbook-Donald-E-Knuth/dp/0201134489) en, met verdere details, in sectie 801 (pagina 336) van het gedrukte boek dat $$\mathrm\TeX$$’s broncode [$$\mathrm\TeX\text{: The Program}$$](https://www.amazon.co.uk/Computers-Typesetting-Tex-Program-TEX/dp/0201134373). Voor veel mensen (mijzelf inbegrepen) zijn Knuths uitleggen echter soms nogal compact en bondig en kunnen ze op momenten moeilijk tot in detail te volgen zijn: geïllustreerde voorbeelden zijn altijd erg behulpzaam.

### Ja, tabellen zijn complex

In sectie 768 (pagina 322) van het boek [$$\mathrm\TeX\text{: The Program}$$](https://www.amazon.co.uk/Computers-Typesetting-Tex-Program-TEX/dp/0201134373), maakt Knuth een interessante opmerking:

> ‘Het is een soort wonder wanneer `\halign` en `\valign` werken, omdat ze door zoveel van de besturingsstructuren van $$\mathrm\TeX$$.”

Daarnaast wijdt deel IV van de vierdelige boekenreeks [$$\mathrm\TeX\text{ in Practice}$$](https://www.amazon.co.uk/Tex-Practice-Set-Stephan-Bechtolsheim/dp/038797296X/ref=sr_1_11?s=books\&ie=UTF8\&qid=1504256043\&sr=1-11\&keywords=TeX+in+Practice) maar liefst 180 pagina’s (pp. 199–379) aan het maken van tabellen in $$\mathrm\TeX$$ via `\halign` en `\valign`.

Dus het is veilig om vast te stellen dat $$\mathrm\TeX$$ tabellen inderdaad ‘tamelijk lastig’ zijn.

### Kolommen overspannen: \omit, \span en \multispan

Zoals opgemerkt, om $$\mathrm\TeX$$’s kolombreedteberekeningen moeten we ‘ruwe’ $$\mathrm\TeX$$; dit betekent een combinatie van primitieve commando’s en één $$\text{Plain }\mathrm\TeX$$ macro genaamd `\multispan`. Hoewel we deze commando’s niet direct zullen gebruiken om onze voorbeeldtabellen te illustreren (d.w\.z. alle $$\mathrm\TeX$$ code volledig uitleggen), is het de moeite waard om er een korte toelichting bij te geven:

* `\halign`: Een van de twee $$\mathrm\TeX$$ primitieven (commando’s) voor het maken van tabellen. De andere is `\valign` maar die wordt niet zo veel gebruikt en komt in dit artikel niet aan bod.
* `\omit`: Een $$\mathrm\TeX$$ primitief commando dat $$\mathrm\TeX$$ instrueert om het voorloopsjabloon van een tabelitem te negeren.
* `\span`: Een $$\mathrm\TeX$$ primitief commando dat wordt gebruikt om twee aangrenzende tabelitems te combineren.
* `\multispan{n}`: Een gewone $$\mathrm\TeX$$ macro om `n` kolommen te overspannen.

In wezen, om kolommen te overspannen $$\mathrm\TeX$$ negeert het juiste aantal voorloopsjablonen van de tabel en combineert het vereiste aantal tabelitems tot één enkel item. `\multispan{n}` werkt door uit te breiden naar de reeks `\omit` en `\span` tokens die nodig zijn om `n` kolommen te overspannen. Bijvoorbeeld, `\multispan{3}` wordt uitgebreid tot `\omit\span\omit\span\omit`.

## Introductie van onze ‘referentietabel’

Hier is onze referentietabel, gevolgd door een geannoteerde versie die de elementen uitlegt die bij de constructie ervan zijn gebruikt:

![{{{alt}}}](/files/839c43dc0c5ac2de9dde9453c096d08f390660a3)

Door onze referentietabel aan te passen zullen we zien wat er gebeurt met de breedte van de tabel en de breedte van afzonderlijke kolommen, terwijl we items toevoegen die verschillende kolommen overspannen. Deze referentietabel is gemaakt in ruwe $$\mathrm\TeX$$ met behulp van de `\halign{...}` primitieven samen met een aantal aangepaste macro’s die nodig zijn om de tabellen op te maken—we zullen die macro’s niet bespreken omdat ze niet essentieel zijn om de voorbeelden en uitleg te begrijpen.

Hier is een geannoteerde versie van onze referentietabel om de kenmerken ervan uit te leggen:

![{{{alt}}}](/files/6f6d883cc2e45795c4724e4c7ff900e855e9c492)

Onze eerste reeks voorbeeldtabellen en de initiële referentietabel hebben allemaal ingesteld `\tabskip=0pt` zodat $$\mathrm\TeX$$ geen ruimte tussen onze kolommen toevoegt: in feite raken ze elkaar allemaal. De reden hiervoor is om de eerste bespreking en de daaropvolgende berekeningen te vereenvoudigen—later in het artikel introduceren we niet-nul `\tabskip` glue opnieuw om het effect ervan op het berekenen van de breedtes van overspannen kolommen te onderzoeken.

Zoals in de annotaties is opgemerkt, hebben we aan het begin van alle niet-overspannende tabelitems (behalve de eerste rij) een kleine hoeveelheid witruimte (5pt) toegevoegd. Die 5pt witruimte maakt deel uit van de totale breedte van alle niet-overspannende items (behalve de eerste rij) en is alleen toegevoegd om de tabel er iets minder rommelig uit te laten zien.

### Een korte opmerking over tabelbreedtes

De `\halign{...}` commando heeft drie vormen:

* `\halign{...}`: stel de tabel in op welke breedte dan ook die $$\mathrm\TeX$$ berekent, op basis van de grootte van de items (en `\tabskip` glue);
* `\halign to *width* {...}`: instrueert $$\mathrm\TeX$$ om de tabel op te maken tot een opgegeven `*width*`;
* `\halign spread *amount*{...}`: pas de berekende breedte aan met `*amount*`.

Wanneer $$\mathrm\TeX$$ maakt een tabel op met behulp van `\halign{...}` moet het de hele tabel in het geheugen lezen om de verschillende berekeningen uit te voeren die nodig zijn om de tabel op te maken. Daarom kun je, tenzij je de breedte hebt opgegeven met behulp van `\halign to *width* {...}` de uiteindelijke breedte niet kennen totdat $$\mathrm\TeX$$ klaar is met het verwerken (opmaken) ervan. Een manier om de breedte van een door `\halign{...}` gemaakte tabel te verkrijgen, is eerst de tabel op te maken binnen een `\vbox{...}` (bijv., `\setbox0=\vbox{\halign{...}}`) en vervolgens bijvoorbeeld `\the\wd0` om de breedte te verkrijgen.

### Geen automatische regelafbreking in tabelitems

Het is belangrijk op te merken dat wanneer $$\mathrm\TeX$$ een tabel opmaakt die is gemaakt met `\halign{...}` alle tekst binnen tabelitems niet automatisch aan regelafbreking wordt onderworpen: tabelitems worden opgemaakt in *beperkte horizontale modus*—net als een `\hbox`. Om regelafbreking mogelijk te maken, moet de tekst van een tabelitem tussen `\vbox{...}` worden geplaatst, samen met het gebruik van een geschikte waarde voor `\hsize` binnen die `\vbox{...}`. Merk echter op dat tekst binnen een `\noalign{...}` commando (een $$\mathrm\TeX$$ primitief) dat in een `\halign{...}` onderworpen is aan $$\mathrm\TeX$$’s regelafbreking. In feite, en zoals de naam al suggereert, `\noalign{...}` laat $$\mathrm\TeX$$ toevraagt? Actually TeX command allows \noalign to escape from the alignment. Translate: "om uit de `\halign{...}` en materiaal tussen de rijen van de tabel te plaatsen—meestal om horizontale lijnen tussen tabelrijen te maken.

### Niet toegestaan: \halign{...} binnen \hbox{...}

Je kunt niet *rechtstreeks* een `\halign{...}` opmaken binnen een `\hbox{...}`. Proberen te gebruiken `\hbox{\halign{...}}` zal een nogal verwarrende fout opleveren:

```latex
! Ontbrekende } ingevoegd.
<ingevoegde tekst>
                }
<opnieuw te lezen>
                   \halign
l.1 \hbox{\halign
```

#### Een uitleg van deze fout

Door de omhullende `\hbox{...}` $$\mathrm\TeX$$ bevindt zich in *beperkte horizontale modus*; vervolgens detecteert het `\halign{...}` dat, wat een *verticale modus* commando is. Als je bijvoorbeeld `\halign{...}` binnen een alinea gebruikt, $$\mathrm\TeX$$ zal de alinea beëindigen, de `\halign{...}` verwerken en daarna doorgaan met de rest van de alinea.

Wanneer gebruikt binnen een `\hbox{...}`, de `\halign{...}` activeert $$\mathrm\TeX$$ om te proberen terug te ontsnappen naar de verticale modus door te proberen de huidige groep geforceerd te sluiten: $$\mathrm\TeX$$ meldt een ‘`! Ontbrekende }`’ en geeft een foutmelding omdat het denkt dat je een fout hebt gemaakt in je gebruik van groepering. Hoewel een rechter accolade (`}`) misschien niet ontbreekt in je $$\mathrm\TeX$$ code, is het foutbericht een symptoom van de `\hbox{...}` die ‘in de weg zit’ en $$\mathrm\TeX$$ zijn ‘beste gok’ doet naar de juiste koers van actie om het probleem op te lossen.

## Voorbeelden van tabellen met overspannen kolommen

De volgende reeks tabelafbeeldingen biedt een reeks voorbeelden om het effect van het overspannen van tabelkolommen te demonstreren: en laat zien dat lange tabelitems onverwachte gevolgen kunnen hebben voor de breedte van bepaalde kolommen — en dus voor de breedte van de tabel zelf. De vraag die we gaan behandelen is wat $$\mathrm\TeX$$ doet wanneer een bepaald tabelitem een aantal kolommen overspant maar ‘te breed is om te passen’. Zoals hierboven opgemerkt, $$\mathrm\TeX$$ past inderdaad een specifiek algoritme toe op dit probleem van het berekenen van kolombreedtes: de volgende voorbeelden zijn bedoeld om een ‘gevoel’ te ontwikkelen voor de werking van dat algoritme.

### Voorbeeldtabel 1

In dit voorbeeld gebruiken we `\multispan{2}` om kolommen 1 en 2 te overspannen met een item waarvan de tekst **Een tabelkop**:

![{{{alt}}}](/files/acd1dc86dfe6ab841a0dc44aeea87aed39bba2d1)

#### Waarnemingen

* De breedte van deze tabel is hetzelfde als die van de [referentietabel](#reference-table): $$327.71722\text{pt}$$.
* De breedte van het item dat kolommen 1 en 2 overspant is $$81.04953\text{pt}$$ wat minder is dan de totale breedte van de items in de kolommen die het overspant: $$52.56676\text{pt} + 57.06679\text{pt} = 109.63355\text{pt}$$

## Voorbeeldtabel 2

Net als in [Voorbeeldtabel 1](#example-table-1), gebruikt dit voorbeeld ook `\multispan{2}` om kolommen 1 en 2 te overspannen, maar hier gebruiken we een langer item waarvan de tekst **Een iets langere tabelkop**.

![{{{alt}}}](/files/6947cbdb60af7f05168f0a2776208689b427344b)

#### Waarnemingen

Als je dit voorbeeld vergelijkt met onze [referentietabel](#reference-table) kunnen we het volgende zien:

* De breedte van deze tabel is toegenomen van $$327.71722\text{pt}$$ om $$374.37032\text{pt}$$: in totaal $$46.6531\text{pt}$$.
* De breedte van het item dat kolommen 1 en 2 overspant ($$156.28664\text{pt}$$) is groter dan de totale breedte van de items in de kolommen die het overspant: $$52.56676\text{pt} + 57.06679\text{pt} = 109.63355\text{pt}$$. Dat verschil is $$156.28664\text{pt}-109.63355\text{pt} = 46.6531\text{pt}$$ wat hetzelfde bedrag is waarmee de tabelbreedte is toegenomen.
* $$\mathrm\TeX$$ heeft de breedte van kolom 2 aangepast om de extra benodigde ruimte te bieden. Later zullen we zien hoe $$\mathrm\TeX$$ de hoeveelheid berekent waarmee kolom 2 moet toenemen.
* Kolom 1 blijft onveranderd: de breedte ervan is niet beïnvloed door het item dat kolommen 1 en 2 overspant.

### Voorbeeldtabel 3

In dit voorbeeld gebruiken we `\multispan{3}` om kolommen 1 tot 3 te overspannen met een item waarvan de tekst hetzelfde is als [Voorbeeldtabel 2](#example-table-2): **Een iets langere tabelkop**.

![{{{alt}}}](/files/dcec330ed974d9dd2624dd0db3ff224d2cd15f2a)

#### Waarnemingen

* De breedte van deze tabel is hetzelfde als die van de [referentietabel](#reference-table): $$327.71722\text{pt}$$.
* De breedte van het item dat kolommen 1 tot 3 overspant ($$156.28664\text{pt}$$) is kleiner dan de totale breedte van de items in de drie kolommen die het overspant: $$52.56676\text{pt} + 57.06679\text{pt} + 59.03899\text{pt} = 168.67254\text{pt}$$.
* Geen van de kolombreedtes is beïnvloed door het item dat kolommen 1 tot 3 overspant.

Begin je een patroon te zien?

### Voorbeeldtabel 4

Net als bij [Voorbeeldtabel 3](#example-table-3), hier gebruiken we `\multispan{3}` om kolommen 1 tot 3 te overspannen, maar deze keer met een item waarvan de tekst aanzienlijk langer is: **Een aanzienlijk langere tabelkop die ver doorloopt**.

![{{{alt}}}](/files/9fdbfced37a17e99b074daf602462e64d1ebd646)

#### Waarnemingen

* Vergeleken met de [referentietabel](#reference-table), is de breedte van deze tabel toegenomen van $$327.71722\text{pt}$$ om $$465.95685\text{pt}$$: een toename van $$138.23963\text{pt}$$.
* De breedte van het item dat kolommen 1 tot 3 overspant is $$306.91216\text{pt}$$.
* De totale breedte van de items in de drie overspannen kolommen is $$52.56676\text{pt} + 57.06679\text{pt} + 59.03899\text{pt} = 168.67254\text{pt}$$.
* Het verschil in breedte tussen het lange overspannende item en de items in kolommen 1 tot 3 is $$306.91216\text{pt}-168.67254\text{pt}=138.23962\text{pt}$$. Hetzelfde bedrag (tot op 4 decimalen nauwkeurig!) waarmee de tabelbreedte is toegenomen.
* Alleen kolom 3 heeft een grotere breedte gekregen: noch kolom 1 noch kolom 2 zijn beïnvloed.

#### Er tekent zich een patroon af

Als we kijken naar [Voorbeeldtabel 2](#example-table-2) en [Voorbeeldtabel 4](#example-table-4) zien we dat het in beide gevallen de **laatste kolom in de overspanning is** waarvan de breedte is vergroot om ruimte te maken voor het lange item dat de kolommen overspande:

* In [Voorbeeldtabel 2](#example-table-2): Het lange item overspande kolommen 1 en 2. Kolom 2 werd ‘uitgerekt’.
* In [Voorbeeldtabel 4](#example-table-4): Het lange item overspande kolommen 1 tot 3. Kolom 3 werd ‘uitgerekt’.

#### De breedte van kolom 3: Tekent zich een algoritme af?

De volgende berekeningen geven een duidelijker beeld van wat $$\mathrm\TeX$$ doet. Dit is wat we weten:

* De breedte van het lange item dat kolommen 1 tot 3 overspant is $$306.91216\text{pt}$$.
* De totale breedte van de items in kolommen 1 en 2 is $$52.56676\text{pt} + 57.06679\text{pt} = 109.63355\text{pt}$$.

Wat is het verschil tussen die waarden? Dat is $$306.91216\text{pt}-109.63355\text{pt} = 197.2786\text{pt}$$ en dit is de breedte die voor kolom 3 wordt gebruikt: die komt rechtstreeks voort uit het algoritme dat wordt gebruikt door $$\mathrm\TeX$$.

### Voorbeeldtabel 5

Voordat we bij een ingewikkelder voorbeeld komen, nog één ‘eenvoudig’ voorbeeld. Deze tabel bevat hetzelfde lange item als [Voorbeeldtabel 4](#example-table-4): **Een aanzienlijk langere tabelkop die ver doorloopt**; deze keer gebruiken we echter `\multispan{6}` waardoor dat item de hele tabel kan overspannen. Zoals je kunt zien, heeft de resulterende tabel nog steeds dezelfde breedte als onze [referentietabel](#reference-table) ($$327.71722\text{pt}$$) wat betekent dat geen enkele kolom is beïnvloed door dit zeer lange item. Dat komt duidelijk omdat de breedte van het item ($$306.91216\text{pt}$$) kleiner is dan de totale breedte van alle items die het overspant: $$327.71722\text{pt}$$; d.w\.z. de breedte van de tabel.

![{{{alt}}}](/files/383c2f510999bed71c3eeaad2eda435046d68855)

### Voorbeeldtabel 6: Iets ingewikkelder

Hier bekijken we een reeks van drie voorbeeldtabellen (6(a)–6(c)) om het effect te laten zien van twee verschillende items die beide doorlopen tot kolom 5. [Voorbeeldtabel 6(a)](#example-table-6a) en [Voorbeeldtabel 6(b)](#example-table-6b) beide tonen een tabel met één enkel item dat meerdere kolommen overspant tot en met kolom 5. [Voorbeeldtabel 6(c)](#example-table-6c) combineert beide overspannende items in één tabel en stelt de vraag: welk item bepaalt eigenlijk de breedte van kolom 5, en waarom? Het antwoord brengt ons bij de kern van het algoritme dat wordt gebruikt door $$\mathrm\TeX$$.

#### Voorbeeldtabel 6(a)

![{{{alt}}}](/files/891f64a1752b27d5885d5d37a9653c65229346cb)

**Waarnemingen**

* Vergeleken met de [referentietabel](#reference-table), is de breedte van deze tabel toegenomen van $$327.71722\text{pt}$$ om $$371.11153\text{pt}$$: een toename van $$43.39431\text{pt}$$.
* De breedte van het item dat kolommen 3 tot 5 overspant is $$215.06683\text{pt}$$.
* De totale breedte van de items in kolommen 3 tot 5 is $$59.03899\text{pt} + 52.98344\text{pt} + 59.6501\text{pt} = 171.67253\text{pt}$$.
* Het verschil in breedte tussen de items in de overspannen kolommen 3 tot 5 en de breedte van het overspannende item is $$215.06683\text{pt}-171.67253\text{pt}=43.3943\text{pt}$$: het exacte bedrag (tot op 4 decimalen nauwkeurig!) waarmee de breedte van de tabel is toegenomen.

#### Voorbeeldtabel 6(b)

![{{{alt}}}](/files/c8f8c6840f2d54f329c0d0c4566cd1dd4db6d28d)

**Waarnemingen**

* Vergeleken met de [referentietabel](#reference-table), is de breedte van deze tabel toegenomen van $$327.71722\text{pt}$$ om $$353.3233\text{pt}$$: een toename van $$25.60608\text{pt}$$.
* De breedte van het item dat kolommen 1 tot 5 overspant is $$306.91216\text{pt}$$.
* De totale breedte van de items in kolommen 1 tot 5 is $$52.56676\text{pt} + 57.06679\text{pt} + 59.03899\text{pt} + 52.98344\text{pt} + 59.6501\text{pt} = 281.30608\text{pt}$$.
* Het verschil in breedte tussen de items in de overspannen kolommen 1 tot 5 en de breedte van het overspannende item is $$306.91216\text{pt}-281.30608\text{pt}=25.60608\text{pt}$$: **note** dit is *minder* dan de waarde berekend voor [Voorbeeld 6(a)](#example-table-6a), die was $$43.3943\text{pt}$$.

#### Voorbeeldtabel 6(c)

Hier combineren we de items in voorbeeldtabellen [6(a)](#example-table-6a) en [6(b)](#example-table-6b) tot één tabel: wat gebeurt er?

![{{{alt}}}](/files/4ba44591f058874e9fc342e8e97c2124078c2686)

**Waarneming**

* Vergeleken met de [referentietabel](#reference-table), is de breedte van deze tabel toegenomen van $$327.71722\text{pt}$$ om $$371.11153\text{pt}$$: een toename van $$43.39431\text{pt}$$. We merken op dat dit precies hetzelfde is als [Voorbeeldtabel 6(a)](#example-table-6a).

#### Wat is $$\mathrm\TeX$$ aan het doen?

Om de resultaten van $$\mathrm\TeX$$’s algoritme en besluitvormingsprocessen te begrijpen, merken we op dat dit item

![{{{alt}}}](/files/de107f768acc2695731fa9fda4bc088c39d1791b)

verder reikt dan de items die worden overspannen door $$25.60608\text{pt}$$; dit item

![{{{alt}}}](/files/4000a385b181672369cf0601df021c1d28436868)

reikt echter nog verder voorbij de overspannen items: met $$43.3943\text{pt}$$. Daardoor ‘wint’ dat item de race en wordt de breedte van kolom 5 verhoogd met de **maximale** van deze twee waarden ($$43.3943\text{pt}$$). De breedte van kolom 5 wordt nu $$59.6501\text{pt} + 43.3943\text{pt} = 103.0444\text{pt}$$ om plaats te bieden aan het item dat kolommen 3 tot 5 overspant. Onze beschrijving van de exacte ‘volgorde van gebeurtenissen’ is iets vereenvoudigd, maar de uitkomst is zoals we hebben beschreven.

## Wat meer complexiteit terugbrengen

Om de complexiteit van onze bespreking (tot nu toe) te beperken, hebben we relatief eenvoudige voorbeelden gebruikt om de principes van $$\mathrm\TeX$$’s algoritme te demonstreren; in het bijzonder stellen we `\tabskip=0pt`. In de praktijk zullen ‘echte’ tabellen waarschijnlijk veel items hebben die een reeks kolommen overspannen en zullen ze natuurlijk niet-nulwaarden hebben voor de `\tabskip` glue—een onderwerp dat we nu opnieuw bekijken.

### \tabskip-glue en breedtes van overspannen kolommen

Tabelontwerp vereist vaak het toevoegen van witruimte tussen kolommen en natuurlijk $$\mathrm\TeX$$ heeft deze mogelijkheid via een primitief commando genaamd `\tabskip`. Dit commando kan worden gebruikt om vaste of flexibele glue (ruimte) te plaatsen:

* vóór een tabel (d.w\.z. links van kolom 1);
* tussen één of meer kolommen;
* na de tabel (d.w\.z. rechts van de laatste kolom).

Hier is een voorbeeld om ons eraan te herinneren:

![{{{alt}}}](/files/03fc7e40d4fcaeda954e8f841a3c0624817c18dc)

### Hoe beïnvloedt \tabskip-glue de breedtes van overspannen kolommen?

De aanwezigheid van niet-nul `\tabskip` glue tussen kolommen biedt extra ruimte die overspannende items kunnen ‘absorberen’ voordat $$\mathrm\TeX$$ het moet overwegen de breedte van de laatste kolom in een overspanning te vergroten.

In ons volgende voorbeeld gebruiken we twee tabellen om de resultaten van het overspannen van twee kolommen te vergelijken. Het enige verschil tussen de tabellen is het gebruik van `\tabskip` glue.

* Het eerste voorbeeld gebruikt onze oorspronkelijke ‘referentietabel’ die, als je je herinnert, ingesteld heeft `\tabskip=0pt`.
* Het tweede voorbeeld gebruikt een aangepaste versie van onze [referentietabel](#reference-table) (hierboven geannoteerd) die `\tabskip=10pt` vóór en na de tabel heeft, maar belangrijker nog, het heeft ingesteld `\tabskip=20pt` tussen de kolommen.

Binnen de *aangepaste* referentietabel hebben de twee overspannen kolommen geen effect op de kolombreedtes (en tabelbreedte), maar ze beïnvloeden wel de breedte van kolom 2 (en tabelbreedte) in de *oorspronkelijke* [referentietabel](#reference-table).

### Oorspronkelijke referentietabel: \tabskip=0pt

Hier tonen we onze oorspronkelijke [referentietabel](#reference-table) samen met een tweede tabel (afgeleid van onze oorspronkelijke [referentietabel](#reference-table)) die een item heeft ‘**Test een langere tabelkop**’ dat kolommen 1 en 2 overspant. Heel duidelijk worden kolom 2 (van de tweede tabel in het diagram) en dus de hele tabel beide beïnvloed door de overspannen kolommen.

![{{{alt}}}](/files/85c6dd4f22bbb3ed0f6280f168f0ee41bd9cca63)

### Aangepaste referentietabel: \tabskip=20pt

Hier tonen we onze aangepaste referentietabel samen met een tweede tabel (afgeleid van onze aangepaste referentietabel) die ook een item heeft ‘**Test een langere tabelkop**’ dat kolommen 1 en 2 overspant. Heel duidelijk wordt binnen de tweede tabel in het diagram noch de breedte van kolom 2 noch die van de tabel beïnvloed door de overspannen kolommen. In dit geval heeft de aanwezigheid van `\tabskip` glue (`20pt`) tussen de kolommen geholpen om de ruimte te ‘absorberen’ die nodig is voor de tekst in het item dat kolommen 1 en 2 overspant:

![{{{alt}}}](/files/afa059713de69062be8094eedae6874a9026ced9)

## De essentie van $$\mathrm\TeX$$’s algoritme

Hopelijk heeft de reeks voorbeelden hierboven geholpen om een ‘gevoel’ te ontwikkelen voor wat $$\mathrm\TeX$$ doet om overspannen items te accommoderen en hoe $$\mathrm\TeX$$ zo nodig de breedte van de **laatste** kolom binnen elke reeks overspannen kolommen aanpast. Naast de breedte van items binnen afzonderlijke overspannen kolommen is de aanwezigheid van niet-nul `\tabskip` glue een belangrijke factor die $$\mathrm\TeX$$ in overweging neemt bij het beslissen of het kolombreedtes moet aanpassen. Het belangrijkste om te onthouden is dat $$\mathrm\TeX$$’s doel is om een geschikte breedte te berekenen voor de **laatste kolom** binnen elke reeks overspannen kolommen.

### Laatste tabelvoorbeeld: laatste kolommen in een overspannen reeks

In dit laatste voorbeeld gebruiken we opnieuw onze aangepaste referentietabel (met `\tabskip` (glue-waarden hierboven besproken) om een andere tabel af te leiden die verschillende kolommen bevat die door regels worden overspannen—we hebben regels gebruikt om de overspanningen beter zichtbaar te maken.

De twee tabellen zijn zorgvuldig uitgelijnd om te laten zien dat in de bovenste tabel geen kolommen vóór kolom 5 zijn beïnvloed door de overspannen kolommen. Het donkerdere groene gebied links van het diagram laat zien dat kolommen 1 tot en met 4 van beide tabellen nog steeds perfect uitlijnen. Rechts staat een lichter groen gearceerd gebied dat laat zien dat alleen kolommen 5 en 6 door de overspannen invoer zijn beïnvloed.

In de bovenste tabel zijn de overspanningen als volgt:

* kolommen 1 tot en met 5: overspannen door een $$400\text{pt}$$ regel;
* kolommen 3 tot en met 5: overspannen door een $$200\text{pt}$$ regel;
* kolommen 4 tot en met 6: overspannen door een $$250\text{pt}$$ regel.

![{{{alt}}}](/files/e2e4472c97c2429becc99ec3c8ae85fcce88779e)

Nogmaals, de uitleg is dat binnen een reeks overspannen kolommen alleen de breedte van de laatste kolom wordt aangepast (indien nodig): tussenliggende kolommen worden niet beïnvloed en dat betekent hier kolommen 1 tot en met 4—hoewel natuurlijk de breedte van kolommen 1 tot en met 4 (en de tussenliggende `\tabskip` glue) wordt meegewogen bij het berekenen van de aangepaste breedtes van kolommen 5 en 6.

### Een doorloop van $$\mathrm\TeX$$’s algoritme

We sluiten af met een *vereenvoudigde* doorloop van “$$\mathrm\TeX$$’s denkproces” terwijl het de breedtes van kolommen in overspannen invoer uitwerkt. Het beschrijven van $$\mathrm\TeX$$’s algoritmen is niet altijd eenvoudig, dus we gebruiken wat “vereenvoudigende artistieke vrijheid” om een overzicht te geven van wat er gebeurt. Lezers die geïnteresseerd zijn in alle rommelige details worden verwezen naar paragraaf 801 (pagina 336) van het gedrukte boek met $$\mathrm\TeX$$’s broncode [$$\mathrm\TeX\text{: The Program}$$](https://www.amazon.co.uk/Computers-Typesetting-Tex-Program-TEX/dp/0201134373).

Praktische tabellen worden vaak gemaakt met veel gebruik van de `\span` primitieve (bijv. binnen $$\mathrm\LaTeX$$ pakketten) om meerdere exemplaren van overspannen kolommen binnen de tabel te construeren. Om dit te beheren, houden de datastructuren (diep in $$\mathrm\TeX$$) informatie bij (zogenaamde *span-nodes*) die $$\mathrm\TeX$$ vertellen over de koppelingen (overspanningen) tussen tabelinvoer/kolommen. Duidelijk, $$\mathrm\TeX$$ moet zijn algoritmen op een systematische manier toepassen en zal de hele tabel moeten verwerken om zijn uiteindelijke berekeningen te maken—om alle kolombreedtes, de totale breedte van de tabel en, indien nodig, de hoeveelheid waarmee de flexibele glue die in de tabel wordt gebruikt moet uitrekken of krimpen, te bepalen. Het is niet echt verrassend dat $$\mathrm\TeX$$ kan de uiteindelijke tabelbreedte pas vertellen nadat het de `\halign{...}` opdracht volledig heeft verwerkt—het heeft echt heel veel werk te doen!

Het vertrekpunt voor berekeningen van kolombreedtes is kolom 1, omdat uiteraard niets kan overspannen vanaf de linkerkant van (en *over/in*) kolom 1. $$\mathrm\TeX$$ begint met het bepalen van de breedte van kolom 1 door vast te stellen welk element de maximale *natuurlijke breedte*. Laten we die maximale breedte $$w\_1$$is. Als er elementen zijn die van kolom 1 naar kolom 2 overspannen, laten we de breedte van dat element $$w\_{12}$$ (breedte van 1 naar 2). Daarnaast duiden we de `\tabskip` glue tussen kolommen 1 en 2 aan als $$t\_{1}$$—merk op dat we alleen de *natuurlijke breedte* breedte `\tabskip` van die glue beschouwen en voorlopig eventuele rek- of krimpcomponenten negeren die deze mogelijk heeft. Laat ook de maximale natuurlijke breedte van alle niet-overspannende elementen in kolom 2 gelijk zijn aan $$w\_2$$.

Het belangrijkste om op te merken is dat $$\mathrm\TeX$$ probeert de breedte van kolom 2 te berekenen door alleen die elementen te beschouwen waarbij de overspanning *begint* met kolom 1 begint en *eindigt* bij kolom 2. De belangrijkste overweging voor $$\mathrm\TeX$$ is de test $$\max(w\_{2}, w\_{12} - (w\_1+ t\_1))$$—er kunnen meerdere elementen zijn die kolommen 1 en 2 overspannen: sommige kunnen smal zijn (kleine $$w\_{12}$$), anderen erg breed (grote $$w\_{12}$$) dus $$\mathrm\TeX$$ zoekt naar degene met het grootste effect (vandaar de $$\max(\text{...})$$). Hier is de waarde van $$w\_{12} -(w\_1+ t\_1)$$ de hoeveelheid waarmee een element dat kolommen 1 en 2 overspant “overloopt” van kolom 1 naar kolom 2: merk op dat $$\mathrm\TeX$$ de breedte van kolom 1 gebruikt **en** het `\tabskip` glue ($$t\_{1}$$) tussen kolommen 1 en 2. Zodra $$\mathrm\TeX$$ heeft vastgesteld of eventuele overspanningen van kolom 1 naar 2 daadwerkelijk invloed hebben op de breedte van kolom 2, stelt het de breedte van kolom 2 in op de maximale waarde die het heeft bepaald (met behulp van de beschreven test). $$\mathrm\TeX$$ gaat verder met alle andere kolommen en voert soortgelijke tests uit.

En tot slot, voor de volledigheid citeren we hier de essentie van $$\mathrm\TeX$$’s algoritme voor het berekenen van kolombreedtes (overgenomen uit Knuths documentatie bij de broncode van $$\mathrm\TeX$$):

Laat $$w\_{ij}$$ de maximumwaarde zijn van de natuurlijke breedtes van alle elementen die kolommen $$i$$ tot en met $$j$$, inclusief. De uiteindelijke kolombreedtes worden gedefinieerd door de formule

$$\begin{equation\*} w\_j=\max\_{1\leq i\leq j}\biggl(w\_{ij}-\sum\_{i\leq k< j}(t\_k+w\_k)\biggr) \end{equation\*}$$

waar $$t\_k$$ is de natuurlijke breedte van de tabskip-glue tussen kolommen $$k$$ en $$k+1$$.

## Colofon: Overleaf gebruiken om tabellen als SVG-afbeeldingen te produceren

Alle $$\mathrm\TeX$$ tabellen die in dit artikel worden gepresenteerd zijn Scalable Vector Graphics (SVG)-bestanden die zijn geproduceerd op het Overleaf-platform. De annotaties (pijlen en groene vakken) werden toegevoegd door de SVG-afbeelding te openen in Inkscape—merk echter op dat de tekst van de annotaties was opgemaakt in $$\mathrm\TeX$$ als aanvullende tekst bij de tabel: alleen de pijlen en groene achtergronden werden in Inkscape toegevoegd. Als je wilt weten hoe dit is bereikt, lees dan verder.

De servers van Overleaf gebruiken de $$\mathrm\TeX \text{ Live}$$ distributie die, naast $$\mathrm\TeX$$op TeX gebaseerde zetmachines, een schat aan zeer nuttige $$\mathrm\TeX$$TeX-gerelateerde softwaretools en hulpprogramma's biedt. Daaronder bevindt zich een genaamd [`dvisvgm`](https://dvisvgm.de) dat, zoals de naam al aangeeft, $$\mathrm\TeX$$’s traditionele DVI (**D**e**V**ice **I**ndependent) uitvoerbestandsformaat naar SVG converteert. Onder de vele [opdrachtregelopties](https://dvisvgm.de/Manpage/) `dvisvgm` biedt een optie (`-n` of `--no-fonts`) die het opdracht geeft alle tekst om te zetten in *paden* wat betekent dat de tekst in SVG-afbeeldingen wordt getekend met lijnen en curven in plaats van echte lettertypen en glyphs. Dit kan de bestandsgrootte van de resulterende SVG-afbeelding vergroten, maar het zorgt ervoor dat de SVG-afbeeldingen uiterst draagbaar zijn en vrijwel zeker goed werken op elk apparaat.

### Dus... hoe is het gedaan?

In een [eerder artikel](https://www.overleaf.com/blog/510-using-luatex-to-run-tools-and-utilities-installed-on-overleafs-servers) Ik heb besproken hoe je kunt gebruiken $$\text{Lua}\mathrm\TeX$$ om de verschillende softwaretools en hulpprogramma's op de servers van Overleaf uit te voeren—het is een uiterst eenvoudige en handige techniek. Die techniek werd gebruikt om SVG-afbeeldingen van opgemaakte $$\mathrm\TeX$$ tabellen te genereren, als volgt. Vanuit het hoofd $$\mathrm\TeX$$ documentbestand werd de code om elke tabel op te maken (gemaakt met met behulp van `\halign`) werd weggeschreven naar een `.tex` bestand. Dit werd bereikt door de tabelcode in te sluiten tussen een paar opdrachten die ik noemde `\beginscoop` en `\endscoop`. Er zijn waarschijnlijk veel andere manieren om de gewenste resultaten te bereiken, maar hier zijn de macrodefinities die ik gebruikte:

```latex
\def\cc{\catcode`\#=12\relax}
\long\def\scoop#1\endscoop{\global\fulltoks={#1}\egroup}
\def\beginscoop{\global\advance\numfigs by1\relax\bgroup\cc\scoop}
```

Je gebruikt ze als volgt:

```latex
\beginscoop
\halign{...}
\endscoop
```

Merk op dat de `\endscoop` token dient slechts om het argument van de `\scoop` macro: $$\mathrm\TeX$$ gooit effectief het `\endscoop` token weg, dus we hoeven het eigenlijk niet te definiëren (bijvoorbeeld door `\def\endscoop{...}`).

De $$\mathrm\TeX$$ code in de `\halign{...}` wordt opgeslagen in een `toks` register met de naam `\fulltoks`. Een lastig punt waar ik tegenaan liep (met $$\text{Lua}\mathrm\TeX$$) was dat ik moest voorkomen dat `#` tekens binnen de `\halign{...}` preambule “verdubbeld” werden tot `##` wanneer ze naar een `.tex` bestand werden weggeschreven. Om dit te voorkomen moest ik tijdelijk de `\catcode`van `#` tekens op 12 zetten voordat ik de $$\mathrm\TeX$$ code (tokens) in het `\fulltoks` tokenregister opsloeg.

De volgende stap is om de tokens in `\fulltoks` als een $$\mathrm\TeX$$ bestand te schrijven—omdat ik $$\text{Lua}\mathrm\TeX$$ dit bleek *extreem* gemakkelijk dankzij $$\text{Lua}\mathrm\TeX$$’s prachtige Lua-API. Kort gezegd schreef ik een macro met de naam `\writefile{...}` die als parameter de naam neemt van een tokenregister waarvan je de tokens naar een bestand wilt schrijven (bijv., `\writefile{fulltoks}`). Binnen de `\writefile{...}` macro gebruikte ik de Lua-API om een tekstuele representatie van het `\fulltoks` tokenregister te verkrijgen:

```latex
\def\writefile#1{%
\directlua{
...
...
 local p=tex.toks["#1"]
...
...
}}
```

Hier is een schermafbeelding die nog iets meer van de `\writefile{...}` commando:

[![{{{alt}}}](/files/42161c2aed46d8e5cf746b8bcd52a7ca59a94f81)](https://www.filepicker.io/api/file/ngeDmgRStGWvG044RE1A)

De Lua-taal en de Lua-API die door $$\text{Lua}\mathrm\TeX$$ kunnen vaak vereenvoudigen $$\mathrm\TeX$$ programmeertaken, en het is vanwege deze nuttige en krachtige functies dat ik $$\text{Lua}\mathrm\TeX$$ sinds \~2009 gebruik—en een enorme fan blijf van deze werkelijk schitterende $$\mathrm\TeX$$ engine. Oké, de $$\text{Lua}\mathrm\TeX$$ reclameboodschap eindigt nu.

Nu we zo gemakkelijk de $$\mathrm\TeX$$ code opgeslagen in `\fulltoks` hebben, wordt die naar een bestand geschreven samen met wat aanvullende code om er een correct gevormd $$\mathrm\LaTeX$$ bestand van te maken. De volgende stappen zijn:

1. Verwerk het `.tex` bestand met onze tabel met $$\text{pdf}\mathrm\LaTeX$$ (in DVI-modus) zodat het de tabel opmaakt en een `.dvi` bestand genereert voor `dvisvgm` om te verwerken. Ja, je kunt $$\text{Lua}\mathrm\TeX$$ gebruiken om $$\text{pdf}\mathrm\LaTeX$$—nogmaals gebruikte ik de methode die in een [eerder artikel](/latex/nl/diepgaande-artikelen/52-using-luatex-to-run-tools-and-utilities-installed-on-overleaf-s-servers.md).
2. En ten slotte, voer `dvisvgm` uit om het `.dvi` bestand te verwerken en een SVG-afbeelding van de opgemaakte $$\mathrm\TeX$$ tabel te genereren.
3. Om de daadwerkelijke SVG-afbeeldingen te verkrijgen kun je een ZIP-bestand downloaden van Overleaf—zorg ervoor dat je de **Invoer- en uitvoerbestanden** optie.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/latex/nl/diepgaande-artikelen/47-tex-tables-how-tex-calculates-spanned-column-widths.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
