> 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/da/dybtgaende-artikler/47-tex-tables-how-tex-calculates-spanned-column-widths.md).

# TeX-tabeller: Hvordan TeX beregner bredder af kolonner, der spænder over flere kolonner

## Målet med denne artikel

I denne artikel undersøger vi, hvordan $$\mathrm\TeX$$ beregner tabelkolonnebredder, når tabeller indeholder poster (f.eks. tabeloverskrifter), der spænder over flere kolonner (f.eks. ved at bruge $$\mathrm\TeX$$ primitiver `\omit` og `\span`). Ved at bruge en grundlæggende [“referencetabel”](#reference-table) som udgangspunkt opretter vi en række eksempler—afledt af den referencetabel—ved at ændre forskellige poster for at skabe kolonner, der spænder over flere kolonner. Ved at undersøge virkningen af disse ændringer kan vi begynde at udvikle en forståelse af den underliggende algoritme, som $$\mathrm\TeX$$ bruger til at beregne bredden af kolonner, der spændes over.

### Bruge $$\mathrm\TeX$$ ikke $$\mathrm\LaTeX$$

For at undersøge og forklare *hvordan* $$\mathrm\TeX$$ bestemmer bredden af kolonner, der spændes over, er det nødvendigt at afstå fra nogen af de vidunderlige $$\mathrm\LaTeX$$ tabelpakker og vende tilbage til grundlæggende, lavniveau- (primitive) tabeloprettelseskommandoer: nærmere bestemt, `\\halign{...}`, `\span` og `\omit`. [Eksisterende $$\mathrm\TeX$$/$$\mathrm\LaTeX$$ tabelpakker](https://ctan.org/topic/table) er naturligvis uundværlige produktivitetsværktøjer og tilbyder en rigdom af yderst nyttig funktionalitet, som gør det muligt for brugere hurtigt at fremstille et stort udvalg af tabelmateriale ved hjælp af $$\mathrm\LaTeX$$. Disse pakker leverer essentiel “makrostillads” bygget op omkring $$\mathrm\TeX$$’s lavniveauadfærd, og deres udviklere leverer meget velkomne abstraktioner og isoleringslag, som tager sig af de underliggende kompleksiteter. Mange af disse pakker er virkelig utrolige bedrifter inden for kompleks $$\mathrm\TeX$$ programmering: vi bør alle være taknemmelige for, at de findes for at skærme os fra at skulle bruge rå $$\mathrm\TeX$$!

Den egentlige algoritme, som $$\mathrm\TeX$$ bruger til at beregne bredderne af kolonner, der spændes over, er forklaret på side 245 i [$$\mathrm\TeX\text{book}$$](https://www.amazon.co.uk/TeXbook-Donald-E-Knuth/dp/0201134489) og, med yderligere detaljer, i afsnit 801 (side 336) i den trykte bog, der indeholder $$\mathrm\TeX$$’s kildekode [$$\mathrm\TeX\text{: The Program}$$](https://www.amazon.co.uk/Computers-Typesetting-Tex-Program-TEX/dp/0201134373). Men for mange mennesker (inklusive mig selv) er Knuths forklaringer til tider ganske kompakte og korte, og til tider kan de være svære at følge i detaljer: illustrerede eksempler er altid meget hjælpsomme.

### Ja, tabeller er komplekse

I afsnit 768 (side 322) af bogen [$$\mathrm\TeX\text{: The Program}$$](https://www.amazon.co.uk/Computers-Typesetting-Tex-Program-TEX/dp/0201134373), fremsætter Knuth en interessant bemærkning:

> “Det er næsten et mirakel, når `\halign` og `\valign` virker, fordi de går på tværs af så mange af kontrolstrukturerne i $$\mathrm\TeX$$.”

Derudover afsætter bind IV i den firebinds bogserie [$$\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) ikke færre end 180 sider (s. 199–379) til at skabe tabeller i $$\mathrm\TeX$$ via `\halign` og `\valign`.

Så det er sikkert at konstatere, at $$\mathrm\TeX$$ tabeller faktisk er “ret vanskelige”.

### Kolonnespænd: \\\omit, \\\span og \\\multispan

Som nævnt, for at undersøge $$\mathrm\TeX$$’s kolonnebreddeberegninger er vi nødt til at bruge “rå” $$\mathrm\TeX$$; det betyder en kombination af primitive kommandoer og en $$\text{Plain }\mathrm\TeX$$ makro kaldet `\\multispan`. Selv om vi ikke vil bruge disse kommandoer til direkte at illustrere vores eksempeltabeller (dvs. fuldt ud forklare al $$\mathrm\TeX$$ kode), er det værd at medtage en kort note, der forklarer dem:

* `\halign`: En af to $$\mathrm\TeX$$ primitive (kommandoer) til at oprette tabeller. Den anden er `\valign` men den bruges ikke lige så meget og vil ikke blive behandlet i denne artikel.
* `\omit`: En $$\mathrm\TeX$$ primitiv kommando, der instruerer $$\mathrm\TeX$$ til at ignorere en tabelposts præambelskabelon.
* `\span`: En $$\mathrm\TeX$$ primitiv kommando, der bruges til at kombinere to tilstødende tabelposter.
* `\\multispan{n}`: En almindelig $$\mathrm\TeX$$ makro til at spænde over `n` kolonner.

I bund og grund: for at spænde over kolonner $$\mathrm\TeX$$ ignorerer den passende mængde tabelpræambelskabeloner og kombinerer det krævede antal tabelposter til én enkelt post. `\\multispan{n}` virker ved at udvide sig til den sekvens af `\omit` og `\span` tokens, der kræves for at spænde over `n` kolonner. For eksempel, `\\multispan{3}` udvides til `\\omit\\span\\omit\\span\\omit`.

## Introduktion til vores “referencetabel”

Her er vores referencetabel efterfulgt af en annoteret version, som forklarer de elementer, der bruges i dens opbygning:

![{{{alt}}}](/files/1855a711c8f53f8306915492e3b42fe7e15625d5)

Ved at ændre vores referencetabel vil vi observere, hvad der sker med tabelbredden og bredden af de enkelte kolonner, når vi tilføjer poster, der spænder over forskellige kolonner. Denne referencetabel blev fremstillet i rå $$\mathrm\TeX$$ ved hjælp af `\\halign{...}` primitive sammen med en række brugerdefinerede makroer, der er nødvendige for at sætte tabellerne—vi vil ikke diskutere disse makroer, fordi de ikke er afgørende for at forstå eksemplerne og forklaringerne.

Her er en annoteret version af vores referencetabel for at forklare dens egenskaber:

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

Vores første sæt eksempeltabeller og den indledende referencetabel har alle sat `\\tabskip=0pt` således at $$\mathrm\TeX$$ ikke tilføjer noget mellemrum mellem vores kolonner: i praksis rører de alle hinanden. Grunden til at gøre dette er at forenkle den indledende diskussion og de efterfølgende beregninger—senere i artiklen genindfører vi ikke-nul `\tabskip` glue for at undersøge dens effekt på beregning af bredder for kolonner, der spændes over.

Som anført i noterne har vi tilføjet en lille smule mellemrum (5pt) i starten af alle ikke-spændende tabelposter (undtagen første række). Disse 5pt mellemrum udgør en del af den samlede bredde af alle ikke-spændende poster (undtagen første række) og blev kun tilføjet for at få tabellen til at se lidt mindre rodet ud.

### En kort bemærkning om tabelbredder

Den `\\halign{...}` kommandoen har tre former:

* `\\halign{...}`: sæt tabellen til den bredde, som $$\mathrm\TeX$$ beregner, baseret på posternes størrelse (og `\tabskip` glue);
* `\\halign to *width* {...}`: instruer $$\mathrm\TeX$$ til at sætte tabellen med en angivet `*bredde*`;
* `\\halign spread *amount*{...}`: juster den beregnede bredde med `*mængde*`.

Når $$\mathrm\TeX$$ sætter en tabel ved hjælp af `\\halign{...}` den er nødt til at læse hele tabellen ind i hukommelsen for at udføre de forskellige beregninger, der kræves for at sætte den. Derfor, medmindre du har angivet bredden ved hjælp af `\\halign to *width* {...}` kan du ikke kende den endelige bredde, før $$\mathrm\TeX$$ er færdig med at behandle (sætte) den. En måde at få bredden af en tabel produceret af `\\halign{...}` er først at sætte tabellen inde i en `\vbox{...}` (f.eks., `\\setbox0=\\vbox{\\halign{...}}`) og derefter f.eks. bruge `\\the\\wd0` for at få bredden.

### Ingen automatisk linjebrydning i tabelposter

Det er vigtigt at bemærke, at når $$\mathrm\TeX$$ sætter en tabel oprettet med `\\halign{...}` bliver tekst i tabelposter ikke automatisk underlagt linjebrydning: tabelposter sættes i *begrænset horisontal tilstand*—ligesom en `\hbox`. For at aktivere linjebrydning skal en tabelposts tekst være omsluttet af en `\vbox{...}` sammen med brug af en passende værdi for `\hsize` inden i den `\vbox{...}`. Bemærk dog, at tekst inden i en `\\noalign{...}` kommando (en $$\mathrm\TeX$$ primitive) brugt i en `\\halign{...}` er underlagt $$\mathrm\TeX$$’s linjebrydning. I praksis, og som navnet antyder, `\\noalign{...}` tillader $$\mathrm\TeX$$ at “undslippe” fra `\\halign{...}` og placere materiale mellem rækkerne i tabellen—typisk for at lave vandrette linjer mellem tabelrækker.

### Ikke tilladt: \\\halign{...} inde i \\\hbox{...}

Du kan ikke *direkte* sætte en `\\halign{...}` inde i en `\hbox{...}`. Hvis man forsøger at bruge `\\hbox{\\halign{...}}` vil det generere en ret forvirrende fejl:

```latex
! Missing } inserted.
<indsat tekst>
                }
<skal læses igen>
                   \halign
l.1 \\hbox{\\halign
```

#### En forklaring på denne fejl

På grund af den omsluttende `\hbox{...}` $$\mathrm\TeX$$ er i *begrænset horisontal tilstand*; derefter registrerer den `\\halign{...}` som er en *vertikal tilstand* kommando. For eksempel, hvis du bruger `\\halign{...}` inde i et afsnit, $$\mathrm\TeX$$ vil den afslutte afsnittet, behandle `\\halign{...}` og derefter fortsætte med resten af afsnittet.

Når den bruges inde i en `\hbox{...}`, den `\\halign{...}` udløser $$\mathrm\TeX$$ for at forsøge at undslippe tilbage til vertikal tilstand ved at forsøge at tvinge den aktuelle gruppe lukket: $$\mathrm\TeX$$ rapporterer en “`! Missing }`” og giver en fejl, fordi den tror, du har lavet en fejl i din brug af gruppering. Selv om en højre klammeparentes (`}`) måske ikke mangler i din $$\mathrm\TeX$$ kode, er fejlmeddelelsen et symptom på, at `\hbox{...}` “kommer i vejen” og $$\mathrm\TeX$$ foretager sit “bedste gæt” på den passende fremgangsmåde for at løse problemet.

## Eksempler på tabeller med kolonner, der spændes over

Den følgende række tabelgrafikker giver et udvalg af eksempler til at demonstrere virkningen af at spænde tabelkolonner over: hvilket viser, at lange tabelposter kan have uventede virkninger på bredden af bestemte kolonner—og dermed på selve tabellens bredde. Spørgsmålet, vi skal besvare, er hvad $$\mathrm\TeX$$ gør, når en bestemt tabelpost spænder over et antal kolonner, men den er “for bred til at passe”. Som nævnt ovenfor, $$\mathrm\TeX$$ anvender faktisk en specifik algoritme på dette problem med at beregne kolonnebredder: de følgende eksempler er designet til at hjælpe med at udvikle en “fornemmelse” for denne algoritmes virkemåde.

### Eksempelstabel 1

I dette eksempel bruger vi `\\multispan{2}` til at spænde over kolonnerne 1 og 2 med en post, hvis tekst er **En tabeloverskrift**:

![{{{alt}}}](/files/37565fbb2820bd022df998fcb9918bdff8730c45)

#### Observationer

* Bredden af denne tabel er den samme som [referencetabellen](#reference-table): $$327.71722\text{pt}$$.
* Bredden af posten, der spænder over kolonnerne 1 og 2, er $$81.04953\text{pt}$$ hvilket er mindre end den samlede bredde af posterne i de kolonner, den spænder over: $$52.56676\text{pt} + 57.06679\text{pt} = 109.63355\text{pt}$$

## Eksempelstabel 2

Som i [Eksempelstabel 1](#example-table-1)bruger dette eksempel også `\\multispan{2}` til at spænde over kolonnerne 1 og 2, men her bruger vi en længere post, hvis tekst er **En lidt længere tabeloverskrift**.

![{{{alt}}}](/files/426ad99aac507d94ab4787acad0fc46cad19402e)

#### Observationer

Hvis du sammenligner dette eksempel med vores [referencetabellen](#reference-table) kan vi se følgende:

* Bredden af denne tabel er steget fra $$327.71722\text{pt}$$ til $$374.37032\text{pt}$$: i alt $$46.6531\text{pt}$$.
* Bredden af posten, der spænder over kolonnerne 1 og 2 ($$156.28664\text{pt}$$) er større end den samlede bredde af posterne i de kolonner, den spænder over: $$52.56676\text{pt} + 57.06679\text{pt} = 109.63355\text{pt}$$. Denne forskel er $$156.28664\text{pt}-109.63355\text{pt} = 46.6531\text{pt}$$ hvilket er det samme beløb, som tabelbredden er steget med.
* $$\mathrm\TeX$$ har justeret bredden af kolonne 2 for at give den nødvendige ekstra plads. Senere vil vi se, hvordan $$\mathrm\TeX$$ beregner den mængde, som kolonne 2 skal øges med.
* Kolonne 1 er upåvirket: dens bredde er ikke blevet påvirket af posten, der spænder over kolonnerne 1 og 2.

### Eksempelstabel 3

I dette eksempel bruger vi `\\multispan{3}` til at spænde over kolonnerne 1 til 3 med en post, hvis tekst er den samme som [Eksempelstabel 2](#example-table-2): **En lidt længere tabeloverskrift**.

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

#### Observationer

* Bredden af denne tabel er den samme som [referencetabellen](#reference-table): $$327.71722\text{pt}$$.
* Bredden af posten, der spænder over kolonnerne 1 til 3 ($$156.28664\text{pt}$$) er mindre end den samlede bredde af posterne i de tre kolonner, den spænder over: $$52.56676\text{pt} + 57.06679\text{pt} + 59.03899\text{pt} = 168.67254\text{pt}$$.
* Ingen af kolonnebredderne er blevet påvirket af posten, der spænder over kolonnerne 1 til 3.

Begynder du at se et mønster dukke op?

### Eksempelstabel 4

Som med [Eksempelstabel 3](#example-table-3), bruger vi her `\\multispan{3}` til at spænde over kolonnerne 1 til 3, men denne gang med en post, hvis tekst er betydeligt længere: **En betydeligt længere tabeloverskrift, der strækker sig langt**.

![{{{alt}}}](/files/5a15a6f8728cae020d2788eb05996f40da4e6e5b)

#### Observationer

* Sammenlignet med [referencetabellen](#reference-table), er bredden af denne tabel steget fra $$327.71722\text{pt}$$ til $$465.95685\text{pt}$$: en stigning på $$138.23963\text{pt}$$.
* Bredden af posten, der spænder over kolonnerne 1 til 3, er $$306.91216\text{pt}$$.
* Den samlede bredde af posterne i de tre spændte kolonner er $$52.56676\text{pt} + 57.06679\text{pt} + 59.03899\text{pt} = 168.67254\text{pt}$$.
* Forskellen i bredde mellem den lange spænende post og posterne i kolonnerne 1 til 3 er $$306.91216\text{pt}-168.67254\text{pt}=138.23962\text{pt}$$. Det samme beløb (til 4 decimaler!) som tabelbredden er steget med.
* Kun kolonne 3 har fået øget sin bredde: hverken kolonne 1 eller kolonne 2 er påvirket.

#### Et mønster tegner sig

Hvis vi ser på [Eksempelstabel 2](#example-table-2) og [Eksempelstabel 4](#example-table-4) kan vi se, at det i begge tilfælde er den **sidste kolonne i spændet** hvis bredde blev øget for at gøre plads til den lange post, som spændte over kolonnerne:

* I [Eksempelstabel 2](#example-table-2): Den lange post spændte over kolonnerne 1 og 2. Kolonne 2 blev “strakt”.
* I [Eksempelstabel 4](#example-table-4): Den lange post spændte over kolonnerne 1 til 3. Kolonne 3 blev “strakt”.

#### Bredden af kolonne 3: Tegner der sig en algoritme?

De følgende beregninger giver en tydeligere indikation af, hvad $$\mathrm\TeX$$ gør. Her er, hvad vi ved:

* Bredden af den lange post, der spænder over kolonnerne 1 til 3, er $$306.91216\text{pt}$$.
* Den samlede bredde af posterne i kolonnerne 1 og 2 er $$52.56676\text{pt} + 57.06679\text{pt} = 109.63355\text{pt}$$.

Hvad er forskellen mellem disse værdier? Den er $$306.91216\text{pt}-109.63355\text{pt} = 197.2786\text{pt}$$ og dette er den bredde, der bruges til kolonne 3: den opstår direkte fra den algoritme, der bruges af $$\mathrm\TeX$$.

### Eksempelstabel 5

Før vi når til et mere kompliceret eksempel, er her endnu et “enkelt” eksempel. Denne tabel indeholder den samme lange post som [Eksempelstabel 4](#example-table-4): **En betydeligt længere tabeloverskrift, der strækker sig langt**; men denne gang bruger vi `\\multispan{6}` som gør det muligt for den post at spænde over hele tabellen. Som du kan se, har den resulterende tabel stadig samme bredde som vores [referencetabellen](#reference-table) ($$327.71722\text{pt}$$) hvilket betyder, at ingen kolonner er blevet påvirket af denne meget lange post. Det er klart, at dette skyldes, at bredden af posten ($$306.91216\text{pt}$$) er mindre end den samlede bredde af alle de poster, den spænder over: $$327.71722\text{pt}$$; dvs. tabellens bredde.

![{{{alt}}}](/files/753c0987a66af9b2d3bad687f0f27f4b2262fa2c)

### Eksempelstabel 6: Lidt mere kompliceret

Her ser vi på en serie af tre eksempeltabeller (6(a)–6(c)) for at vise virkningen af to forskellige poster, som begge spænder ind i kolonne 5. [Eksempelstabel 6(a)](#example-table-6a) og [Eksempelstabel 6(b)](#example-table-6b) viser hver en tabel, der indeholder en enkelt post, som spænder over flere kolonner op til kolonne 5. [Eksempelstabel 6(c)](#example-table-6c) kombinerer begge spændende poster i én enkelt tabel og stiller spørgsmålet: hvilken post bestemmer faktisk bredden af kolonne 5, og hvorfor? Svaret fører os til kernen af den algoritme, der bruges af $$\mathrm\TeX$$.

#### Eksempelstabel 6(a)

![{{{alt}}}](/files/005644fb029fa749730b6dc40e4139a32dd7ed0f)

**Observationer**

* Sammenlignet med [referencetabellen](#reference-table), er bredden af denne tabel steget fra $$327.71722\text{pt}$$ til $$371.11153\text{pt}$$: en stigning på $$43.39431\text{pt}$$.
* Bredden af posten, der spænder over kolonnerne 3 til 5, er $$215.06683\text{pt}$$.
* Den samlede bredde af posterne i kolonnerne 3 til 5 er $$59.03899\text{pt} + 52.98344\text{pt} + 59.6501\text{pt} = 171.67253\text{pt}$$.
* Forskellen i bredde mellem posterne, der er spændt over i kolonnerne 3 til 5, og bredden af den spændende post er $$215.06683\text{pt}-171.67253\text{pt}=43.3943\text{pt}$$: det nøjagtige beløb (til 4 decimaler!) som tabelbredden er steget med.

#### Eksempelstabel 6(b)

![{{{alt}}}](/files/68c702f9e05c9c23cc3fd182e0643737b032c022)

**Observationer**

* Sammenlignet med [referencetabellen](#reference-table), er bredden af denne tabel steget fra $$327.71722\text{pt}$$ til $$353.3233\text{pt}$$: en stigning på $$25.60608\text{pt}$$.
* Bredden af posten, der spænder over kolonnerne 1 til 5, er $$306.91216\text{pt}$$.
* Den samlede bredde af posterne i kolonnerne 1 til 5 er $$52.56676\text{pt} + 57.06679\text{pt} + 59.03899\text{pt} + 52.98344\text{pt} + 59.6501\text{pt} = 281.30608\text{pt}$$.
* Forskellen i bredde mellem posterne, der er spændt over i kolonnerne 1 til 5, og bredden af den spændende post er $$306.91216\text{pt}-281.30608\text{pt}=25.60608\text{pt}$$: **note** dette er *mindre* end den værdi, der blev beregnet for [Eksempel 6(a)](#example-table-6a), som var $$43.3943\text{pt}$$.

#### Eksempelstabel 6(c)

Her kombinerer vi posterne i eksempeltabellerne [6(a)](#example-table-6a) og [6(b)](#example-table-6b) til én enkelt tabel: hvad sker der?

![{{{alt}}}](/files/38b2ef2c861e36994794206600a0c09b25536cc5)

**Observation**

* Sammenlignet med [referencetabellen](#reference-table), er bredden af denne tabel steget fra $$327.71722\text{pt}$$ til $$371.11153\text{pt}$$: en stigning på $$43.39431\text{pt}$$. Vi bemærker, at dette er præcis det samme som [Eksempelstabel 6(a)](#example-table-6a).

#### Hvad er $$\mathrm\TeX$$ i gang med?

For at forstå resultaterne af $$\mathrm\TeX$$’s algoritme og beslutningsprocesser bemærker vi, at denne post

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

strækker sig ud over de poster, der bliver spændt over af $$25.60608\text{pt}$$; men denne post

![{{{alt}}}](/files/36f69d15772d11d4985a2c5c47bc547d7a31fcf1)

strækker sig endnu længere ud over de poster, der bliver spændt over: med $$43.3943\text{pt}$$. Derfor “vinder” denne post løbet, og kolonne 5 får øget sin bredde med den **maksimale** af disse to værdier ($$43.3943\text{pt}$$). Bredden af kolonne 5 bliver nu $$59.6501\text{pt} + 43.3943\text{pt} = 103.0444\text{pt}$$ for at rumme posten, der spænder over kolonnerne 3 til 5. Vores beskrivelse af den nøjagtige “rækkefølge af hændelser” er en smule forenklet, men resultatet er, som vi har beskrevet.

## Vi bringer lidt kompleksitet tilbage

For at minimere kompleksiteten i vores diskussioner (indtil nu) har vi brugt relativt simple eksempler til at demonstrere principperne i $$\mathrm\TeX$$’s algoritme; især satte vi `\\tabskip=0pt`. I praksis vil “virkelige” tabeller sandsynligvis have mange poster, der spænder over et udvalg af kolonner, og naturligvis vil de have ikke-nul værdier for `\tabskip` glue—et emne, vi nu vender tilbage til.

### \\\tabskip glue og spanned column widths

Tabeldesign kræver ofte tilføjelse af mellemrum mellem kolonner, og selvfølgelig, $$\mathrm\TeX$$ har denne mulighed gennem en primitiv kommando kaldet `\tabskip`. Denne kommando kan bruges til at indsætte fast eller fleksibelt glue (mellemrum):

* før en tabel (dvs. til venstre for kolonne 1);
* mellem én eller flere kolonner;
* efter tabellen (dvs. til højre for den sidste kolonne).

Her er et eksempel til at minde os selv om det:

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

### Hvordan påvirker \\\tabskip glue bredderne af kolonner, der spændes over?

Tilstedeværelsen af ikke-nul `\tabskip` glue mellem kolonner giver ekstra plads, som spændte poster kan “absorbere”, før $$\mathrm\TeX$$ behøver at overveje at øge bredden af den sidste kolonne i et spænd.

I vores næste eksempel bruger vi to tabeller til at sammenligne resultaterne af at spænde to kolonner over. Den eneste forskel mellem tabellerne er brugen af `\tabskip` glue.

* Det første eksempel bruger vores oprindelige “referencetabel”, som, hvis du husker, har sat `\\tabskip=0pt`.
* Det andet eksempel bruger en ændret version af vores [referencetabellen](#reference-table) (annoteret ovenfor), som har `\\tabskip=10pt` før og efter tabellen, men vigtigere er det, at den har sat `\\tabskip=20pt` mellem kolonnerne.

Inden for den *ændrede* referencetabel har de to spændte kolonner ingen effekt på kolonnebredderne (og tabelbredden), men de påvirker bredden af kolonne 2 (og tabelbredden) i den *oprindelige* [referencetabellen](#reference-table).

### Oprindelig referencetabel: \\\tabskip=0pt

Her viser vi vores oprindelige [referencetabellen](#reference-table) sammen med en anden tabel (afledt af vores oprindelige [referencetabellen](#reference-table)) som har en post “**Test en længere tabeloverskrift**” der spænder over kolonnerne 1 og 2. Helt klart er kolonne 2 (i den anden tabel i figuren) og dermed hele tabellen begge påvirket af de spændte kolonner.

![{{{alt}}}](/files/762c5db148d7bc369b95f239f1600e70f72ff045)

### Ændret referencetabel: \\\tabskip=20pt

Her viser vi vores ændrede referencetabel sammen med en anden tabel (afledt af vores ændrede referencetabel), som også har en post “**Test en længere tabeloverskrift**” der spænder over kolonnerne 1 og 2. Helt klart er hverken bredden af kolonne 2 eller tabellen i den anden tabel i figuren påvirket af de spændte kolonner. I dette tilfælde har tilstedeværelsen af `\tabskip` glue (`20pt`) mellem kolonnerne hjulpet med at “absorbere” den plads, som teksten i posten, der spænder over kolonnerne 1 og 2, kræver:

![{{{alt}}}](/files/06e78c5545f1ece98078b78b3d43c82253cdd9db)

## Kernen i $$\mathrm\TeX$$’s algoritme

Forhåbentlig har det udvalg af eksempler, der er givet ovenfor, hjulpet med at udvikle en “fornemmelse” for, hvad $$\mathrm\TeX$$ gør for at rumme spændte poster, og hvordan $$\mathrm\TeX$$ vil justere bredden af den **sidste** kolonne inden for hvert spænd af kolonner, der er spændt over, hvis nødvendigt. Ud over bredden af poster inden for de enkelte kolonner, der bliver spændt over, er tilstedeværelsen af ikke-nul `\tabskip` glue en vigtig faktor, som $$\mathrm\TeX$$ tager i betragtning, når den beslutter, om den har behov for at justere nogen kolonnebredder. Det vigtigste at huske er, at $$\mathrm\TeX$$’s mål er at beregne en passende bredde for den **sidste kolonne** inden for hvert interval af sammenspændte kolonner.

### Endeligt tabel-eksempel: sidste kolonner i et sammenspændt interval

I dette sidste eksempel bruger vi igen vores ændrede referenstabel (med `\tabskip` klæbeværdierne omtalt ovenfor) til at udlede en anden tabel, som indeholder forskellige kolonner, der er spændt over af regler—vi har brugt regler for at gøre spændene lettere at se.

De to tabeller er omhyggeligt justeret for at vise, at der i den øverste tabel ikke er nogen kolonner før kolonne 5, der er blevet påvirket af de sammenspændte kolonner. Det mørkere grønne område til venstre for diagrammet viser, at kolonne 1 til 4 i begge tabeller stadig flugter perfekt. Til højre er et lysere grønt skyggeområde, der viser, at kun kolonne 5 og 6 er blevet påvirket af de sammenspændte poster.

I den øverste tabel er spænderne som følger:

* kolonne 1 til 5: spændt over af en $$400\text{pt}$$ regel;
* kolonne 3 til 5: spændt over af en $$200\text{pt}$$ regel;
* kolonne 4 til 6: spændt over af en $$250\text{pt}$$ regel.

![{{{alt}}}](/files/036b62c9bcd4c0a6688e9bb02e02fc147f736386)

Forklaringen er igen, at inden for en række sammenspændte kolonner justeres kun bredden af den sidste kolonne (hvis nødvendigt): mellemliggende kolonner påvirkes ikke, og her betyder det kolonne 1 til 4—selvfølgelig under hensyntagen til bredden af kolonne 1 til 4 (og de mellemliggende `\tabskip` klæbemiddel) når de justerede bredder af kolonne 5 og 6 beregnes.

### En gennemgang af $$\mathrm\TeX$$’s algoritme

Vi afslutter med en *forenklet* gennemgang af “$$\mathrm\TeX$$’s tankeprocesser”, mens den beregner bredden af kolonner i sammenspændte poster. At beskrive $$\mathrm\TeX$$’s algoritmer er ikke altid ligetil, så vi vil tillade os lidt “forenklet kunstnerisk frihed” for at give et overblik over, hvad der sker. Læsere, der er interesserede i alle de rodet detaljer, henvises til afsnit 801 (side 336) i den trykte bog, der indeholder $$\mathrm\TeX$$’s kildekode [$$\mathrm\TeX\text{: The Program}$$](https://www.amazon.co.uk/Computers-Typesetting-Tex-Program-TEX/dp/0201134373).

Tabeller i den virkelige verden oprettes ofte med mange anvendelser af `\span` primitiven (f.eks. inde i $$\mathrm\LaTeX$$ pakker) til at konstruere flere forekomster af sammenspændte kolonner i tabellen. For at håndtere dette opretholder datastrukturerne (dybt inde i $$\mathrm\TeX$$) opretholder information (såkaldte *spændknuder*) som fortæller $$\mathrm\TeX$$ om forbindelserne (spændene) mellem tabelposter/kolonner. Det er klart, $$\mathrm\TeX$$ skal anvende sine algoritmer på systematisk vis og vil være nødt til at behandle hele tabellen for at foretage sine endelige beregninger—for at bestemme alle kolonnebredderne, tabellens samlede bredde og, om nødvendigt, den mængde, som de fleksible klæbemidler, der bruges i tabellen, skal strækkes eller krympe med. Det er ikke rigtig overraskende, at $$\mathrm\TeX$$ ikke kan fortælle dig den endelige tabelbredde, før den har behandlet `\\halign{...}` kommandoen fuldstændigt—den har virkelig meget arbejde at gøre!

Udgangspunktet for beregning af kolonnebredder er kolonne 1, fordi intet naturligvis kan spænde fra venstre for (og *hen over/i*) kolonne 1. $$\mathrm\TeX$$ begynder med at bestemme bredden af kolonne 1 ved at finde den post, der har den maksimale *naturlige bredde*. Lad os kalde den maksimale bredde $$w\_1$$og hvis der er poster, der spænder fra kolonne 1 til kolonne 2, så lad os kalde bredden af den post $$w\_{12}$$ (bredde fra 1 til 2). Derudover betegner vi `\tabskip` klæbemidlet mellem kolonne 1 og 2 som $$t\_{1}$$—bemærk, at vi kun betragter *naturlige bredde* af den pågældende `\tabskip` klæbemiddel og indtil videre ignorerer eventuelle stræk- eller krympekomponenter, det måtte have. Lad os også lade den maksimale naturlige bredde af alle poster i kolonne 2, der ikke spænder over flere kolonner, være $$w\_2$$.

Det vigtige at bemærke er, at $$\mathrm\TeX$$ forsøger at beregne bredden af kolonne 2 ved kun at betragte de poster, hvor spændet *begynder* med kolonne 1 og *slutter* ved kolonne 2. Det afgørende hensyn for $$\mathrm\TeX$$ er testen $$\max(w\_{2}, w\_{12} - (w\_1+ t\_1))$$—der kan være flere poster, der spænder over kolonne 1 og 2: nogle kan være smalle (lille $$w\_{12}$$), andre meget brede (stor $$w\_{12}$$) så $$\mathrm\TeX$$ leder efter den, der har den største effekt (deraf $$\max(\text{...})$$). Her er værdien af $$w\_{12} -(w\_1+ t\_1)$$ det beløb, som en post, der spænder over kolonne 1 og 2, “flyder over” fra kolonne 1 til kolonne 2: bemærk, at $$\mathrm\TeX$$ bruger bredden af kolonne 1 **og** den `\tabskip` glue ($$t\_{1}$$mellem kolonne 1 og 2. Når først $$\mathrm\TeX$$ har fastslået, om eventuelle spænd fra kolonne 1 til 2 faktisk påvirker bredden af kolonne 2, sætter den bredden af kolonne 2 til den maksimale værdi, den har fastlagt (ved brug af den beskrevne test). $$\mathrm\TeX$$ fortsætter den med at arbejde sig gennem alle de andre kolonner og udføre lignende tests.

Og endelig, for fuldstændighedens skyld, citerer vi her essensen af $$\mathrm\TeX$$’s algoritme til beregning af kolonnebredder (taget fra Knuths kildekodedokumentation til $$\mathrm\TeX$$):

Lad $$w\_{ij}$$ være maksimum af de naturlige bredder af alle poster, der spænder over kolonner $$i$$ til og med $$j$$, inklusive. De endelige kolonnebredder defineres ved formlen

$$\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\*}$$

hvor $$t\_k$$ er den naturlige bredde af tabskip-klæbemidlet mellem kolonnerne $$k$$ og $$k+1$$.

## Kolofon: Brug af Overleaf til at fremstille tabeller som SVG-grafik

Alle $$\mathrm\TeX$$ tabeller, der præsenteres i denne artikel, er Scalable Vector Graphics (SVG)-filer produceret på Overleaf-platformen. Anmærkningerne (pile og grønne bokse) blev tilføjet ved at åbne SVG-grafikken i Inkscape—bemærk dog, at anmærkningernes tekst blev sat op i $$\mathrm\TeX$$ som ekstra tekst til at ledsage tabellen: kun pilene og de grønne baggrunde blev tilføjet i Inkscape. Hvis du er interesseret i at vide, hvordan dette blev opnået, så læs videre.

Overleafs servere bruger $$\mathrm\TeX \text{ Live}$$ distribution, som ud over $$\mathrm\TeX$$-baserede satsmotorer leverer en lang række meget nyttige $$\mathrm\TeX$$-relaterede softwareværktøjer og hjælpeprogrammer. Blandt dem er et, der hedder [`dvisvgm`](https://dvisvgm.de) som, som navnet antyder, konverterer $$\mathrm\TeX$$’s traditionelle DVI (**D**e**V**ice **I**ndependent) outputfilformat til SVG. Blandt dets mange [kommandolinjeindstillinger](https://dvisvgm.de/Manpage/) `dvisvgm` findes der en indstilling (`-n` eller `--no-fonts`) som vil instruere det i at konvertere al tekst til *stier* hvilket betyder, at teksten i SVG-grafik tegnes ved hjælp af linjer og kurver snarere end egentlige skrifttyper og glyffer. Dette kan øge filstørrelsen på den resulterende SVG-grafik, men det sikrer, at SVG-grafikken er ekstremt portabel og næsten med sikkerhed fungerer godt på enhver enhed.

### Så... hvordan blev det gjort?

I en [tidligere artikel](https://www.overleaf.com/blog/510-using-luatex-to-run-tools-and-utilities-installed-on-overleafs-servers) drøftede jeg, hvordan du kan bruge $$\text{Lua}\mathrm\TeX$$ til at køre de forskellige softwareværktøjer og hjælpeprogrammer, der er installeret på Overleafs servere—det er en ekstremt nem og bekvem teknik. Den teknik blev brugt til at generere SVG-grafik af satte $$\mathrm\TeX$$ tabeller, som følger. Inde fra den primære $$\mathrm\TeX$$ dokumentfil blev koden til at sætte hver tabel (oprettet ved hjælp af using `\halign`) skrevet til en `.tex` fil. Dette blev opnået ved at omslutte tabelkoden i et par kommandoer, som jeg kaldte `\beginscoop` og `\endscoop`. Der er sandsynligvis mange andre måder at opnå de ønskede resultater på, men her er makrodefinitionerne, som jeg brugte:

```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}
```

Du bruger dem sådan her:

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

Bemærk, at `\endscoop` tokenet blot tjener til at afgrænse parameteren for `\scoop` makroen: $$\mathrm\TeX$$ effektivt kasserer `\endscoop` tokenet, så vi behøver faktisk ikke at definere det (f.eks. ved `\def\endscoop{...}`).

Den $$\mathrm\TeX$$ kode, der er indeholdt i `\\halign{...}` gemmes i en `toks` register kaldet `\fulltoks`. Et vanskeligt punkt, jeg stødte på (med $$\text{Lua}\mathrm\TeX$$) var behovet for at forhindre `#` tegn i `\\halign{...}` præamblen i at blive “fordoblet” til `##` når de skrives ud til en `.tex` fil. For at undgå dette måtte jeg midlertidigt sætte `\catcode`på `#` tegnene til 12, før jeg gemte $$\mathrm\TeX$$ koden (tokens) i `\fulltoks` token-registeret.

Næste skridt er at skrive de tokens, der er indeholdt i `\fulltoks` som en $$\mathrm\TeX$$ fil—for da jeg brugte $$\text{Lua}\mathrm\TeX$$ viste dette sig at være *ekstremt* let takket være $$\text{Lua}\mathrm\TeX$$’s vidunderlige Lua-API. Kort fortalt skrev jeg en makro kaldet `\writefile{...}` som som parameter tager navnet på et token-register, hvis tokens du vil skrive ud til en fil (f.eks., `\writefile{fulltoks}`). Inde i `\writefile{...}` makro brugte jeg Lua-API'et til at få en tekstlig repræsentation af `\fulltoks` token-registeret:

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

Her er et skærmbillede, der viser lidt mere af `\writefile{...}` kommandoen:

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

Lua-sproget og Lua-API'et, som leveres af $$\text{Lua}\mathrm\TeX$$ kan ofte forenkle $$\mathrm\TeX$$ programmeringsopgaver, og det er på grund af disse nyttige og kraftfulde funktioner, at jeg har brugt $$\text{Lua}\mathrm\TeX$$ siden \~2009—og fortsat er en stor fan af denne virkelig vidunderlige $$\mathrm\TeX$$ motor. OK, reklamen $$\text{Lua}\mathrm\TeX$$ slutter her.

Efter så let at have fået fat i $$\mathrm\TeX$$ koden gemt i `\fulltoks` skrives den ud til en fil sammen med noget ekstra kode for at gøre den til en korrekt formateret $$\mathrm\LaTeX$$ fil. De næste trin er:

1. Behandl `.tex` filen, der indeholder vores tabel, med $$\text{pdf}\mathrm\LaTeX$$ (i DVI-tilstand), så den sætter tabellen og genererer en `.dvi` fil til `dvisvgm` at behandle. Ja, du kan bruge $$\text{Lua}\mathrm\TeX$$ til at køre $$\text{pdf}\mathrm\LaTeX$$—endnu en gang brugte jeg metoden, der blev omtalt i en [tidligere artikel](/latex/da/dybtgaende-artikler/52-using-luatex-to-run-tools-and-utilities-installed-on-overleaf-s-servers.md).
2. Og endelig, kør `dvisvgm` til at behandle `.dvi` fil for at generere en SVG-grafik af den satte $$\mathrm\TeX$$ tabel.
3. For at få den egentlige SVG-grafik kan du downloade en ZIP-fil fra Overleaf—sørg for at vælge **Input- og outputfiler** valgmuligheden.


---

# 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/da/dybtgaende-artikler/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.
