> 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/pl/artykuly-szczegolowe/47-tex-tables-how-tex-calculates-spanned-column-widths.md).

# Tabele TeX-a: Jak TeX oblicza szerokości kolumn obejmujących wiele kolumn

## Celem tego artykułu

W tym artykule badamy, jak $$\mathrm\TeX$$ oblicza szerokości kolumn tabeli, gdy tabele zawierają wpisy (np. nagłówki tabeli) obejmujące wiele kolumn (np. przy użyciu $$\mathrm\TeX$$ prymitywów `\omit` i `\span`). Korzystając z podstawowej [„referencyjnej” tabeli](#reference-table) jako punktu wyjścia, tworzymy szereg przykładów — wyprowadzonych z tej tabeli referencyjnej — poprzez modyfikowanie różnych wpisów w celu utworzenia kolumn obejmujących wiele komórek. Badając wpływ tych zmian, możemy zacząć rozwijać rozumienie podstawowego algorytmu, którego $$\mathrm\TeX$$ używa do obliczania szerokości kolumn obejmujących wiele komórek.

### Korzystanie z $$\mathrm\TeX$$ nie $$\mathrm\LaTeX$$

Aby zbadać i wyjaśnić *jak* $$\mathrm\TeX$$ decyduje o szerokości kolumn obejmujących wiele komórek, należy zrezygnować z wszelkich cudownych $$\mathrm\LaTeX$$ pakietów do tworzenia tabel i wrócić do fundamentalnych, niskopoziomowych (pierwotnych) poleceń do tworzenia tabel: w szczególności `\halign{...}`, `\span` i `\omit`. [Istniejące $$\mathrm\TeX$$/$$\mathrm\LaTeX$$ pakiety do tworzenia tabel](https://ctan.org/topic/table) są oczywiście niezbędnymi narzędziami zwiększającymi produktywność i oferują bogactwo niezwykle użytecznych funkcji, które umożliwiają użytkownikom szybkie tworzenie szerokiej gamy materiałów tabelarycznych przy użyciu $$\mathrm\LaTeX$$. Pakiety te dostarczają niezbędnego „szkieletu makr” zbudowanego wokół $$\mathrm\TeX$$niskopoziomowego zachowania i ich twórcy zapewniają bardzo mile widziane abstrakcje oraz warstwy izolacji, które dbają o leżące u podstaw złożoności. Wiele z tych pakietów to naprawdę niesamowite osiągnięcia złożonego $$\mathrm\TeX$$ programowania: wszyscy powinniśmy być wdzięczni, że istnieją, by chronić nas przed koniecznością używania surowego $$\mathrm\TeX$$!

Rzeczywisty algorytm, którego $$\mathrm\TeX$$ używa do obliczania szerokości kolumn obejmujących wiele komórek, jest wyjaśniony na stronie 245 [$$\mathrm\TeX\text{book}$$](https://www.amazon.co.uk/TeXbook-Donald-E-Knuth/dp/0201134489) a z dalszymi szczegółami w sekcji 801 (strona 336) drukowanej książki zawierającej $$\mathrm\TeX$$kod źródłowy [$$\mathrm\TeX\text{: The Program}$$](https://www.amazon.co.uk/Computers-Typesetting-Tex-Program-TEX/dp/0201134373). Jednak dla wielu osób (w tym dla mnie) wyjaśnienia Knutha są czasem dość zwięzłe i skondensowane, a niekiedy trudno je szczegółowo śledzić: przykładowe ilustracje są zawsze bardzo pomocne.

### Tak, tabele są złożone

W sekcji 768 (strona 322) książki [$$\mathrm\TeX\text{: The Program}$$](https://www.amazon.co.uk/Computers-Typesetting-Tex-Program-TEX/dp/0201134373)Knuth zamieszcza interesujący komentarz:

> „To chyba cud, gdy `\halign` i `\valign` działa, ponieważ przecina tak wiele struktur sterujących $$\mathrm\TeX$$.”

Ponadto, tom IV czterotomowej serii książkowej [$$\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) poświęca nie mniej niż 180 stron (s. 199–379) tworzeniu tabel w $$\mathrm\TeX$$ za pomocą `\halign` i `\valign`.

Można więc śmiało zauważyć, że $$\mathrm\TeX$$ tabele są rzeczywiście „dość trudne” do opanowania.

### Kolumny obejmujące wiele komórek: \omit, \span i \multispan

Jak wspomniano, aby zbadać $$\mathrm\TeX$$obliczenia szerokości kolumn wykonywane przez $$\mathrm\TeX$$musimy użyć „surowego” $$\text{Plain }\mathrm\TeX$$ ; oznacza to połączenie poleceń pierwotnych i jednego `makra o nazwie`. Chociaż nie będziemy używać tych poleceń do bezpośredniego ilustrowania naszych przykładowych tabel (tj. do pełnego wyjaśniania całego $$\mathrm\TeX$$ kodu), warto zamieścić krótką notatkę wyjaśniającą je:

* `\halign` : Jedno z dwóch $$\mathrm\TeX$$ poleceń pierwotnych (komend) do tworzenia tabel. Drugim jest `\valign` ale nie jest ono tak powszechnie używane i nie będzie omawiane w tym artykule.
* `\omit` : $$\mathrm\TeX$$ polecenie pierwotne (komenda), które nakazuje $$\mathrm\TeX$$ zignorować szablon wstępu wpisu tabeli.
* `\span` : $$\mathrm\TeX$$ polecenie pierwotne (komenda) używane do łączenia dwóch sąsiadujących wpisów tabeli.
* `\multispan{n}` : zwykłe $$\mathrm\TeX$$ makro do obejmowania `n` kolumn.

W istocie, aby objąć kolumny $$\mathrm\TeX$$ ignoruje odpowiednią liczbę szablonów wstępu tabeli i łączy wymaganą liczbę wpisów tabeli w jeden wpis. `\multispan{n}` działa, rozwijając się do sekwencji `\omit` i `\span` tokenów potrzebnych do objęcia `n` kolumn. Na przykład `\multispan{3}` rozwija się do `\omit\span\omit\span\omit`.

## Wprowadzenie naszej „referencyjnej” tabeli

Oto nasza tabela referencyjna, a następnie wersja z adnotacjami, która wyjaśnia elementy użyte w jej konstrukcji:

![{{{alt}}}](/files/885786eec33dc7d64eaaba193ec7976b723b5bcd)

Modyfikując naszą tabelę referencyjną, zaobserwujemy, co dzieje się z szerokością tabeli oraz szerokością poszczególnych kolumn, gdy dodajemy wpisy obejmujące różne kolumny. Ta tabela referencyjna została przygotowana w surowym $$\mathrm\TeX$$ z użyciem `\halign{...}` polecenia pierwotnego wraz z szeregiem własnych makr potrzebnych do składania tabel — nie będziemy omawiać tych makr, ponieważ nie są one niezbędne do zrozumienia przykładów i objaśnień.

Oto wersja naszej tabeli referencyjnej z adnotacjami, wyjaśniająca jej cechy:

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

Nasze pierwsze zestawy przykładowych tabel oraz początkowa tabela referencyjna mają ustawione `\tabskip=0pt` tak, że $$\mathrm\TeX$$ nie dodaje żadnej przestrzeni między naszymi kolumnami: w praktyce wszystkie się stykają. Powodem tego jest uproszczenie początkowej dyskusji i dalszych obliczeń — później w artykule ponownie wprowadzamy niezerowe `\tabskip` wypełnienie, aby zbadać jego wpływ na obliczanie szerokości kolumn obejmujących wiele komórek.

Jak zauważono w adnotacjach, dodaliśmy niewielką ilość białej przestrzeni (5pt) na początku wszystkich niewyciąganych wpisów tabeli (z wyjątkiem pierwszego wiersza). Te 5pt białej przestrzeni stanowią część całkowitej szerokości wszystkich niewyciąganych wpisów (z wyjątkiem pierwszego wiersza) i zostały dodane tylko po to, by tabela wyglądała nieco mniej przeładowana.

### Krótka uwaga o szerokości tabel

Ta `\halign{...}` polecenie ma trzy postacie:

* `\halign{...}`: ustaw tabelę na dowolną szerokość, jaką $$\mathrm\TeX$$ oblicza na podstawie rozmiaru wpisów (i `\tabskip` wypełnienia);
* `\halign to *width* {...}`: nakazuje $$\mathrm\TeX$$ skład tabeli do określonej `*szerokości*`;
* `\halign spread *amount*{...}`: dostosuj obliczoną szerokość o `*kwotę*`.

Gdy $$\mathrm\TeX$$ składa tabelę używając `\halign{...}` musi wczytać całą tabelę do pamięci, aby wykonać różne obliczenia wymagane do jej złożenia. W konsekwencji, chyba że określono szerokość za pomocą `\halign to *width* {...}` nie można poznać końcowej szerokości, dopóki $$\mathrm\TeX$$ nie zakończy przetwarzania (składania) tabeli. Jednym ze sposobów uzyskania szerokości tabeli utworzonej przez `\halign{...}` jest najpierw złożenie tabeli wewnątrz `\vbox{...}` (np. `\setbox0=\vbox{\halign{...}}`) a następnie, na przykład, użycie `\the\wd0` do uzyskania szerokości.

### Brak automatycznego łamania wierszy we wpisach tabeli

Ważne jest, aby zauważyć, że gdy $$\mathrm\TeX$$ składa tabelę utworzoną za pomocą `\halign{...}` dowolny tekst wewnątrz wpisów tabeli nie podlega automatycznie łamaniu wierszy: wpisy tabeli są składane w *ograniczonym trybie poziomym*— podobnie jak `\hbox`. Aby włączyć łamanie wierszy, tekst wpisu tabeli musi zostać ujęty w `\vbox{...}` wraz z użyciem odpowiedniej wartości dla `\hsize` wewnątrz tego `\vbox{...}`. Zwróć jednak uwagę, że tekst wewnątrz `\noalign{...}` polecenia ( $$\mathrm\TeX$$ polecenie pierwotne) używanego w `\halign{...}` podlega łamaniu wierszy przez $$\mathrm\TeX$$W praktyce, jak sugeruje sama nazwa, `\noalign{...}` pozwala $$\mathrm\TeX$$ „uciec” z `\halign{...}` i umieścić materiał między wierszami tabeli — zazwyczaj po to, by tworzyć poziome linie między wierszami tabeli.

### Niedozwolone: \halign{...} wewnątrz \hbox{...}

Nie można *bezpośrednie* złożyć `\halign{...}` wewnątrz `\hbox{...}`. Próba użycia `\hbox{\halign{...}}` spowoduje dość mylący błąd:

```latex
! Wstawiono brakujący }.
<wstawiony tekst>
                }
<do ponownego odczytania>
                   \halign
l.1 \hbox{\halign
```

#### Wyjaśnienie tego błędu

Z powodu otaczającego `\hbox{...}` $$\mathrm\TeX$$ znajduje się w *ograniczonym trybie poziomym*; następnie wykrywa `\halign{...}` który jest *poleceniem trybu pionowego.* Na przykład jeśli użyjesz `\halign{...}` w obrębie akapitu, $$\mathrm\TeX$$ zakończy akapit, przetworzy `\halign{...}` a następnie przejdzie do reszty akapitu.

Gdy jest używane wewnątrz `\hbox{...}`, a `\halign{...}` wyzwala $$\mathrm\TeX$$ próbę powrotu do trybu pionowego przez próbę wymuszenia zamknięcia bieżącej grupy: $$\mathrm\TeX$$ zwraca „`! Missing }`” i zgłasza błąd, ponieważ myśli, że popełniłeś błąd w użyciu grupowania. Chociaż brakujący nawias klamrowy prawy (`}`) może nie być brakujący w twoim $$\mathrm\TeX$$ kodzie, komunikat o błędzie jest objawem `\hbox{...}` „wtrącania się” i $$\mathrm\TeX$$ podejmowania „najlepszego domysłu” co do odpowiedniego sposobu rozwiązania problemu.

## Przykłady tabel z kolumnami obejmującymi wiele komórek

Poniższy ciąg grafik tabelarycznych przedstawia szereg przykładów demonstrujących wpływ obejmowania kolumn tabeli: pokazując, że długie wpisy tabeli mogą dawać nieoczekiwane rezultaty dla szerokości niektórych kolumn — a w konsekwencji także dla szerokości samej tabeli. Pytanie, na które zamierzamy odpowiedzieć, brzmi: co robi $$\mathrm\TeX$$ gdy określony wpis tabeli obejmuje kilka kolumn, ale jest „za szeroki, by się zmieścić”. Jak wspomniano wyżej, $$\mathrm\TeX$$ rzeczywiście stosuje do tego problemu obliczania szerokości kolumn określony algorytm: poniższe przykłady mają pomóc wyrobić „wyczucie” działania tego algorytmu.

### Przykładowa tabela 1

W tym przykładzie używamy `\multispan{2}` do objęcia kolumn 1 i 2 wpisem, którego tekst brzmi **Nagłówek tabeli**:

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

#### Obserwacje

* Szerokość tej tabeli jest taka sama jak szerokość [tabeli referencyjnej](#reference-table): $$327.71722\text{pt}$$.
* Szerokość wpisu obejmującego kolumny 1 i 2 wynosi $$81.04953\text{pt}$$ co jest mniejsze od łącznej szerokości wpisów w kolumnach, które obejmuje: $$52.56676\text{pt} + 57.06679\text{pt} = 109.63355\text{pt}$$

## Przykładowa tabela 2

Jak w [Przykładowa tabela 1](#example-table-1)ten przykład również używa `\multispan{2}` do objęcia kolumn 1 i 2, ale tutaj używamy dłuższego wpisu o tekście **Nieco dłuższy nagłówek tabeli**.

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

#### Obserwacje

Jeśli porównamy ten przykład z naszym [tabeli referencyjnej](#reference-table) możemy zobaczyć następujące rzeczy:

* Szerokość tej tabeli wzrosła z $$327.71722\text{pt}$$ na $$374.37032\text{pt}$$: łącznie o $$46.6531\text{pt}$$.
* Szerokość wpisu obejmującego kolumny 1 i 2 ($$156.28664\text{pt}$$) jest większa niż łączna szerokość wpisów w kolumnach, które obejmuje: $$52.56676\text{pt} + 57.06679\text{pt} = 109.63355\text{pt}$$. Ta różnica wynosi $$156.28664\text{pt}-109.63355\text{pt} = 46.6531\text{pt}$$ co jest taką samą wartością, o jaką wzrosła szerokość tabeli.
* $$\mathrm\TeX$$ dostosował szerokość kolumny 2, aby zapewnić dodatkowe potrzebne miejsce. Później zobaczymy, jak $$\mathrm\TeX$$ oblicza kwotę, o jaką kolumna 2 musi się zwiększyć.
* Kolumna 1 pozostaje bez zmian: jej szerokość nie została zmieniona przez wpis obejmujący kolumny 1 i 2.

### Przykładowa tabela 3

W tym przykładzie używamy `\multispan{3}` do objęcia kolumn 1 do 3 wpisem, którego tekst jest taki sam jak [Przykładowa tabela 2](#example-table-2): **Nieco dłuższy nagłówek tabeli**.

![{{{alt}}}](/files/510759ac2703283119a64bc3cf5d26b7b5827d39)

#### Obserwacje

* Szerokość tej tabeli jest taka sama jak szerokość [tabeli referencyjnej](#reference-table): $$327.71722\text{pt}$$.
* Szerokość wpisu obejmującego kolumny 1 do 3 ($$156.28664\text{pt}$$) jest mniejsza niż łączna szerokość wpisów w trzech kolumnach, które obejmuje: $$52.56676\text{pt} + 57.06679\text{pt} + 59.03899\text{pt} = 168.67254\text{pt}$$.
* Żadna z szerokości kolumn nie została zmieniona przez wpis obejmujący kolumny 1 do 3.

Czy zaczynasz dostrzegać wyłaniający się wzorzec?

### Przykładowa tabela 4

Podobnie jak w [Przykładowa tabela 3](#example-table-3), tutaj również używamy `\multispan{3}` do objęcia kolumn 1 do 3, ale tym razem z wpisem o tekście znacznie dłuższym: **Znacznie dłuższy nagłówek tabeli, który rozciąga się bardzo daleko**.

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

#### Obserwacje

* W porównaniu z [tabeli referencyjnej](#reference-table), szerokość tej tabeli wzrosła z $$327.71722\text{pt}$$ na $$465.95685\text{pt}$$: o $$138.23963\text{pt}$$.
* Szerokość wpisu obejmującego kolumny 1 do 3 wynosi $$306.91216\text{pt}$$.
* Łączna szerokość wpisów w trzech objętych kolumnach wynosi $$52.56676\text{pt} + 57.06679\text{pt} + 59.03899\text{pt} = 168.67254\text{pt}$$.
* Różnica szerokości między długim wpisem obejmującym a wpisami w kolumnach 1 do 3 wynosi $$306.91216\text{pt}-168.67254\text{pt}=138.23962\text{pt}$$. Taka sama wartość (do 4 miejsc po przecinku!), o jaką wzrosła szerokość tabeli.
* Tylko szerokość kolumny 3 wzrosła: ani kolumna 1, ani kolumna 2 nie zostały zmienione.

#### Wyłania się wzorzec

Jeśli spojrzymy na [Przykładowa tabela 2](#example-table-2) i [Przykładowa tabela 4](#example-table-4) możemy zobaczyć, że w obu przypadkach jest to **ostatnia kolumna w zakresie objęcia** której szerokość została zwiększona, aby zrobić miejsce dla długiego wpisu obejmującego kolumny:

* W [Przykładowa tabela 2](#example-table-2): Długi wpis obejmował kolumny 1 i 2. Kolumna 2 stała się „rozciągnięta”.
* W [Przykładowa tabela 4](#example-table-4): Długi wpis obejmował kolumny 1 do 3. Kolumna 3 stała się „rozciągnięta”.

#### Szerokość kolumny 3: Wyłania się algorytm?

Poniższe obliczenia dają jaśniejszy obraz tego, co $$\mathrm\TeX$$ robi. Oto, co wiemy:

* Szerokość długiego wpisu obejmującego kolumny 1 do 3 wynosi $$306.91216\text{pt}$$.
* Łączna szerokość wpisów w kolumnach 1 i 2 wynosi $$52.56676\text{pt} + 57.06679\text{pt} = 109.63355\text{pt}$$.

Jaka jest różnica między tymi wartościami? To $$306.91216\text{pt}-109.63355\text{pt} = 197.2786\text{pt}$$ i jest to szerokość użyta dla kolumny 3: wynika ona bezpośrednio z algorytmu używanego przez $$\mathrm\TeX$$.

### Przykładowa tabela 5

Zanim przejdziemy do bardziej skomplikowanego przykładu, oto jeszcze jeden „prosty” przykład. Ta tabela zawiera ten sam długi wpis co [Przykładowa tabela 4](#example-table-4): **Znacznie dłuższy nagłówek tabeli, który rozciąga się bardzo daleko**; jednak tym razem używamy `\multispan{6}` co pozwala temu wpisowi objąć całą tabelę. Jak widać, otrzymana tabela nadal ma taką samą szerokość jak nasza [tabeli referencyjnej](#reference-table) ($$327.71722\text{pt}$$) co oznacza, że żadne kolumny nie zostały zmienione przez ten bardzo długi wpis. Oczywiście dzieje się tak dlatego, że szerokość wpisu ($$306.91216\text{pt}$$) jest mniejsza od łącznej szerokości wszystkich wpisów, które obejmuje: $$327.71722\text{pt}$$; tj. szerokość tabeli.

![{{{alt}}}](/files/708f6a200a18d262842d66e89aada91b86a842e6)

### Przykładowa tabela 6: Nieco bardziej skomplikowana

Tutaj przyglądamy się serii trzech przykładowych tabel (6(a)–6(c)), aby pokazać wpływ dwóch różnych wpisów, z których oba obejmują kolumnę 5. [Przykładowa tabela 6(a)](#example-table-6a) i [Przykładowa tabela 6(b)](#example-table-6b) każda pokazuje tabelę zawierającą pojedynczy wpis, który obejmuje kilka kolumn aż do kolumny 5. [Przykładowa tabela 6(c)](#example-table-6c) łączy oba wpisy obejmujące w jedną tabelę i stawia pytanie: który wpis faktycznie określa szerokość kolumny 5 i dlaczego? Odpowiedź prowadzi nas do istoty algorytmu używanego przez $$\mathrm\TeX$$.

#### Przykładowa tabela 6(a)

![{{{alt}}}](/files/382e428651c1b938d515bd7473708178553bad34)

**Obserwacje**

* W porównaniu z [tabeli referencyjnej](#reference-table), szerokość tej tabeli wzrosła z $$327.71722\text{pt}$$ na $$371.11153\text{pt}$$: o $$43.39431\text{pt}$$.
* Szerokość wpisu obejmującego kolumny 3 do 5 wynosi $$215.06683\text{pt}$$.
* Łączna szerokość wpisów w kolumnach 3 do 5 wynosi $$59.03899\text{pt} + 52.98344\text{pt} + 59.6501\text{pt} = 171.67253\text{pt}$$.
* Różnica szerokości między wpisami obejmowanymi w kolumnach 3 do 5 a szerokością wpisu obejmującego wynosi $$215.06683\text{pt}-171.67253\text{pt}=43.3943\text{pt}$$: dokładną wartość (do 4 miejsc po przecinku!), o jaką wzrosła szerokość tabeli.

#### Przykładowa tabela 6(b)

![{{{alt}}}](/files/2896b9ef243f4c4788a9acc3e5484f4384946463)

**Obserwacje**

* W porównaniu z [tabeli referencyjnej](#reference-table), szerokość tej tabeli wzrosła z $$327.71722\text{pt}$$ na $$353.3233\text{pt}$$: o $$25.60608\text{pt}$$.
* Szerokość wpisu obejmującego kolumny 1 do 5 wynosi $$306.91216\text{pt}$$.
* Łączna szerokość wpisów w kolumnach 1 do 5 wynosi $$52.56676\text{pt} + 57.06679\text{pt} + 59.03899\text{pt} + 52.98344\text{pt} + 59.6501\text{pt} = 281.30608\text{pt}$$.
* Różnica szerokości między wpisami obejmowanymi w kolumnach 1 do 5 a szerokością wpisu obejmującego wynosi $$306.91216\text{pt}-281.30608\text{pt}=25.60608\text{pt}$$: **note** to jest *mniej* niż wartość obliczona dla [Przykład 6(a)](#example-table-6a), która wynosiła $$43.3943\text{pt}$$.

#### Przykładowa tabela 6(c)

Tutaj łączymy wpisy z przykładowych tabel [6(a)](#example-table-6a) i [6(b)](#example-table-6b) w jedną tabelę: co się dzieje?

![{{{alt}}}](/files/4604e7ef7f6cb83b471dbac3f922e12eb0a23f9c)

**Obserwacja**

* W porównaniu z [tabeli referencyjnej](#reference-table), szerokość tej tabeli wzrosła z $$327.71722\text{pt}$$ na $$371.11153\text{pt}$$: o $$43.39431\text{pt}$$. Zauważamy, że jest to dokładnie to samo co [Przykładowa tabela 6(a)](#example-table-6a).

#### Co $$\mathrm\TeX$$ robi?

Aby zrozumieć wyniki algorytmu i procesów decyzyjnych $$\mathrm\TeX$$zauważamy, że ten wpis

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

wykracza poza wpisy obejmowane przez $$25.60608\text{pt}$$; jednak ten wpis

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

wykracza jeszcze dalej poza wpisy obejmowane: o $$43.3943\text{pt}$$. Zatem ten wpis „wygrywa wyścig” i szerokość kolumny 5 zostaje zwiększona o **maksimum** z tych dwóch wartości ($$43.3943\text{pt}$$). Szerokość kolumny 5 staje się teraz $$59.6501\text{pt} + 43.3943\text{pt} = 103.0444\text{pt}$$ aby pomieścić wpis obejmujący kolumny 3 do 5. Nasz opis dokładnej „sekwencji zdarzeń” jest nieco uproszczony, ale wynik jest taki, jak opisaliśmy.

## Przywracanie nieco złożoności

Aby zminimalizować złożoność naszych dotychczasowych rozważań, używaliśmy stosunkowo prostych przykładów do zilustrowania zasad algorytmu $$\mathrm\TeX$$; w szczególności ustawiliśmy `\tabskip=0pt`. W praktyce tabele „z życia wzięte” prawdopodobnie będą zawierały wiele wpisów obejmujących zakres kolumn i oczywiście będą miały niezerowe wartości dla `\tabskip` wypełnienia — temat, do którego teraz wrócimy.

### wypełnienie \tabskip i szerokości kolumn obejmujących wiele komórek

Projektowanie tabel często wymaga dodawania białej przestrzeni między kolumnami i oczywiście $$\mathrm\TeX$$ ma do tego funkcję poprzez polecenie pierwotne o nazwie `\tabskip`. To polecenie może służyć do wstawiania stałego lub elastycznego wypełnienia (odstępu):

* przed tabelą (tj. po lewej stronie kolumny 1);
* między jedną lub wieloma kolumnami;
* po tabeli (tj. po prawej stronie ostatniej kolumny).

Oto przykład, by sobie to przypomnieć:

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

### Jak wypełnienie \tabskip wpływa na szerokości kolumn obejmujących wiele komórek?

Obecność niezerowego `\tabskip` wypełnienia między kolumnami zapewnia dodatkową przestrzeń, którą wpisy obejmujące mogą „pochłonąć”, zanim $$\mathrm\TeX$$ trzeba zacznie myśleć o zwiększaniu szerokości ostatniej kolumny w zakresie objęcia.

W naszym następnym przykładzie użyjemy dwóch tabel, aby porównać wyniki obejmowania dwóch kolumn. Jedyną różnicą między tabelami jest użycie `\tabskip` wypełnienia.

* Pierwszy przykład używa naszej oryginalnej „referencyjnej” tabeli, która, jak pamiętasz, ma ustawione `\tabskip=0pt`.
* Drugi przykład używa zmodyfikowanej wersji naszej [tabeli referencyjnej](#reference-table) (z adnotacjami powyżej), która ma `\tabskip=10pt` przed i po tabeli, ale co ważniejsze, ma ustawione `\tabskip=20pt` między kolumnami.

W obrębie *zmodyfikowanej* tabeli referencyjnej te dwie objęte kolumny nie wpływają na szerokości kolumn (ani na szerokość tabeli), ale wpływają na szerokość kolumny 2 (i szerokość tabeli) w *oryginalnej* [tabeli referencyjnej](#reference-table).

### Oryginalna tabela referencyjna: \tabskip=0pt

Tutaj pokazujemy naszą oryginalną [tabeli referencyjnej](#reference-table) razem z drugą tabelą (wyprowadzoną z naszej oryginalnej [tabeli referencyjnej](#reference-table)) która ma wpis „**Przetestuj dłuższy nagłówek tabeli**” obejmujący kolumny 1 i 2. Całkiem wyraźnie, kolumna 2 (drugiej tabeli na diagramie), a więc i cała tabela, są objęte wpływem obejmowanych kolumn.

![{{{alt}}}](/files/727bf71f3b96bcbb4c385e6870a1a9343c65401a)

### Zmodyfikowana tabela referencyjna: \tabskip=20pt

Tutaj pokazujemy naszą zmodyfikowaną tabelę referencyjną razem z drugą tabelą (wyprowadzoną z naszej zmodyfikowanej tabeli referencyjnej), która również ma wpis „**Przetestuj dłuższy nagłówek tabeli**” obejmujący kolumny 1 i 2. Całkiem wyraźnie, w drugiej tabeli na diagramie ani szerokość kolumny 2, ani szerokość tabeli nie są objęte wpływem obejmowanych kolumn. W tym przypadku obecność `\tabskip` wypełnienia (`20pt`) między kolumnami pomogła „pochłonąć” przestrzeń wymaganą przez tekst we wpisie obejmującym kolumny 1 i 2:

![{{{alt}}}](/files/5265058d04a60c589b5f71254e27a8711b5ab3a5)

## Istota $$\mathrm\TeX$$algorytmu

Mam nadzieję, że przedstawiony powyżej zakres przykładów pomógł wyrobić „wyczucie”, co $$\mathrm\TeX$$ robi, aby uwzględnić wpisy obejmujące wiele komórek, i jak $$\mathrm\TeX$$ w razie potrzeby dostosuje szerokość **ostatniej** kolumny w każdym zakresie kolumn objętych. Oprócz szerokości wpisów w poszczególnych obejmowanych kolumnach, obecność niezerowego `\tabskip` wypełnienia jest ważnym czynnikiem, który $$\mathrm\TeX$$ bierze pod uwagę przy decydowaniu, czy trzeba dostosować jakąkolwiek szerokość kolumn. Najważniejszą rzeczą do zapamiętania jest to, że $$\mathrm\TeX$$celem jest obliczenie odpowiedniej szerokości dla **ostatnia kolumna** w obrębie każdego zakresu rozpiętych kolumn.

### Ostatni przykład tabeli: ostatnie kolumny w rozpiętym zakresie

W tym ostatnim przykładzie ponownie używamy naszej zmodyfikowanej tabeli referencyjnej (z `\tabskip` omówionymi powyżej wartościami odstępów), aby wyprowadzić kolejną tabelę zawierającą różne kolumny rozpięte przez reguły — użyliśmy reguł, aby rozpięcia były łatwiejsze do zauważenia.

Obie tabele zostały starannie wyrównane, aby pokazać, że w górnej tabeli rozpięte kolumny nie wpłynęły na żadne kolumny poprzedzające kolumnę 5. Ciemniejszy zielony obszar po lewej stronie diagramu pokazuje, że kolumny od 1 do 4 obu tabel nadal są idealnie wyrównane. Po prawej stronie znajduje się jaśniejszy zielony zacieniony obszar, pokazujący, że tylko kolumny 5 i 6 zostały dotknięte przez rozpięte wpisy.

W górnej tabeli rozpięcia są następujące:

* kolumny od 1 do 5: rozpięte przez $$400\text{pt}$$ regułę;
* kolumny od 3 do 5: rozpięte przez $$200\text{pt}$$ regułę;
* kolumny od 4 do 6: rozpięte przez $$250\text{pt}$$ regułę.

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

Ponownie wyjaśnienie jest takie, że w serii rozpiętych kolumn dostosowywana jest tylko szerokość ostatniej kolumny (jeśli jest to wymagane): kolumny pośrednie pozostają bez zmian, co w tym przypadku oznacza kolumny od 1 do 4 — chociaż oczywiście szerokość kolumn od 1 do 4 (oraz pośredni `\tabskip` odstęp) jest brana pod uwagę podczas obliczania dostosowanych szerokości kolumn 5 i 6.

### Przegląd $$\mathrm\TeX$$algorytmu

Zakończymy *uproszczonym* omówieniem „$$\mathrm\TeX$$procesów myślowych” podczas obliczania szerokości kolumn w rozpiętych wpisach. Opisanie $$\mathrm\TeX$$algorytmów nie zawsze jest proste, dlatego zastosujemy pewną „artystyczną licencję upraszczającą”, aby przedstawić przegląd tego, co się dzieje. Czytelników zainteresowanych wszystkimi zawiłymi szczegółami odsyłamy do sekcji 801 (strona 336) drukowanej książki zawierającej $$\mathrm\TeX$$kod źródłowy [$$\mathrm\TeX\text{: The Program}$$](https://www.amazon.co.uk/Computers-Typesetting-Tex-Program-TEX/dp/0201134373).

Tabele w rzeczywistych zastosowaniach są często tworzone z wielokrotnym użyciem `\span` prymitywu (np. wewnątrz pakietów $$\mathrm\LaTeX$$ ) w celu skonstruowania wielu wystąpień rozpiętych kolumn w tabeli. Aby tym zarządzać, struktury danych (głęboko wewnątrz $$\mathrm\TeX$$) przechowują informacje (tak zwane *węzły rozpięcia*), które informują $$\mathrm\TeX$$ o powiązaniach (rozpięciach) między wpisami/kolumnami tabeli. Oczywiście, $$\mathrm\TeX$$ musi stosować swoje algorytmy w sposób systematyczny i będzie musiał przetworzyć całą tabelę, aby wykonać ostateczne obliczenia — określić wszystkie szerokości kolumn, całkowitą szerokość tabeli oraz, jeśli to konieczne, wielkość, o jaką elastyczne odstępy użyte w tabeli muszą się rozciągnąć lub skurczyć. Nie jest szczególnie zaskakujące, że $$\mathrm\TeX$$ nie może podać ostatecznej szerokości tabeli, dopóki całkowicie nie przetworzy polecenia `\halign{...}` — naprawdę ma mnóstwo pracy do wykonania!

Punktem wyjścia do obliczeń szerokości kolumn jest kolumna 1, ponieważ oczywiście nic nie może rozciągać się z lewej strony (ani *przez/do*) kolumny 1. $$\mathrm\TeX$$ zaczyna od określenia szerokości kolumny 1 poprzez ustalenie, który wpis ma maksymalną *naturalną szerokość*. Nazwijmy tę maksymalną szerokość $$w\_1$$a jeśli istnieją wpisy rozpięte od kolumny 1 do kolumny 2, nazwijmy szerokość takiego wpisu $$w\_{12}$$ (szerokość od 1 do 2). Ponadto oznaczymy `\tabskip` odstęp między kolumnami 1 i 2 jako $$t\_{1}$$— zwróć uwagę, że rozważamy jedynie *naturalną szerokość* tego `\tabskip` odstępu i na razie ignorujemy wszelkie składniki rozciągania lub kurczenia, które może posiadać. Niech również maksymalna naturalna szerokość wszystkich nierozpiętych wpisów w kolumnie 2 będzie $$w\_2$$.

Kluczową kwestią, którą należy zauważyć, jest to, że $$\mathrm\TeX$$ próbuje obliczyć szerokość kolumny 2, rozważając tylko te wpisy, w których rozpięcie *zaczyna się* od kolumny 1 i *kończy się* na kolumnie 2. Kluczową kwestią dla $$\mathrm\TeX$$ jest test $$\max(w\_{2}, w\_{12} - (w\_1+ t\_1))$$— może istnieć wiele wpisów rozpiętych na kolumny 1 i 2: niektóre mogą być wąskie (małe $$w\_{12}$$), inne bardzo szerokie (duże $$w\_{12}$$), więc $$\mathrm\TeX$$ szuka tego, który ma największy wpływ (stąd $$\max(\text{...})$$). W tym przypadku wartość $$w\_{12} -(w\_1+ t\_1)$$ to wielkość, o którą wpis rozpięty na kolumny 1 i 2 „przelewa się” z kolumny 1 do kolumny 2: zauważ, że $$\mathrm\TeX$$ używa szerokości kolumny 1 **i** stronie `\tabskip` wypełnienia ($$t\_{1}$$) między kolumnami 1 i 2. Gdy $$\mathrm\TeX$$ ustali, czy jakiekolwiek rozpięcia od kolumny 1 do 2 wpływają na szerokość kolumny 2, ustawia szerokość kolumny 2 na maksymalną ustaloną wartość (korzystając z opisanego testu). $$\mathrm\TeX$$ kontynuuje przechodzenie przez wszystkie pozostałe kolumny, wykonując podobne testy.

I na koniec, tylko dla kompletności, przytaczamy tutaj istotę $$\mathrm\TeX$$algorytmu obliczania szerokości kolumn (zaczerpniętego z dokumentacji kodu źródłowego Knutha dla $$\mathrm\TeX$$):

Niech $$w\_{ij}$$ będzie maksimum naturalnych szerokości wszystkich wpisów rozpiętych na kolumny $$i$$ do $$j$$, włącznie. Ostateczne szerokości kolumn są określone wzorem

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

gdzie $$t\_k$$ jest naturalną szerokością odstępu tabskip między kolumnami $$k$$ i $$k+1$$.

## Stopka: używanie Overleaf do tworzenia tabel jako grafik SVG

Wszystkie $$\mathrm\TeX$$ tabele przedstawione w tym artykule są plikami Scalable Vector Graphics (SVG) utworzonymi na platformie Overleaf. Adnotacje (strzałki i zielone pola) dodano przez otwarcie grafiki SVG w Inkscape — należy jednak zauważyć, że tekst adnotacji został złożony w $$\mathrm\TeX$$ jako dodatkowy tekst towarzyszący tabeli: w Inkscape dodano tylko strzałki i zielone tła. Jeśli chcesz dowiedzieć się, jak to osiągnięto, czytaj dalej.

Serwery Overleaf używają dystrybucji $$\mathrm\TeX \text{ Live}$$ która oprócz $$\mathrm\TeX$$-opartych silników składu zapewnia bogactwo bardzo użytecznych $$\mathrm\TeX$$-powiązanych narzędzi programowych i narzędzi pomocniczych. Jednym z nich jest program o nazwie [`dvisvgm`](https://dvisvgm.de) który, jak sugeruje jego nazwa, konwertuje $$\mathrm\TeX$$tradycyjny format pliku wyjściowego DVI (**D**e**V**niezależny od urządzenia **I**) na SVG. Wśród jego wielu [opcji wiersza poleceń](https://dvisvgm.de/Manpage/) `dvisvgm` udostępnia opcję (`-n` lub `--no-fonts`), która nakaże mu przekonwertować cały tekst na *ścieżki* co oznacza, że tekst w grafikach SVG jest rysowany za pomocą linii i krzywych, a nie rzeczywistych czcionek i glifów. Może to zwiększyć rozmiar wynikowego pliku SVG, ale zapewnia, że grafiki SVG są wyjątkowo przenośne i niemal na pewno będą dobrze działać na każdym urządzeniu.

### A więc... jak to zrobiono?

W [poprzednim artykule](https://www.overleaf.com/blog/510-using-luatex-to-run-tools-and-utilities-installed-on-overleafs-servers) omówiłem, jak można użyć $$\text{Lua}\mathrm\TeX$$ do uruchamiania różnych narzędzi programowych i narzędzi pomocniczych zainstalowanych na serwerach Overleaf — jest to niezwykle łatwa i wygodna technika. Technikę tę wykorzystano do wygenerowania grafik SVG złożonych $$\mathrm\TeX$$ tabel w następujący sposób. Z głównego $$\mathrm\TeX$$ pliku dokumentu kod do złożenia każdej tabeli (utworzonej przy użyciu `\halign`) został zapisany do pliku `.tex` . Osiągnięto to przez ujęcie kodu tabeli w parę poleceń, które nazwałem `\beginscoop` i `\endscoop`. Prawdopodobnie istnieje wiele innych sposobów osiągnięcia pożądanych rezultatów, ale oto definicje makr, których użyłem:

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

Używa się ich tak:

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

Zauważ, że token `\endscoop` służy jedynie do ograniczenia parametru `\scoop` makra: $$\mathrm\TeX$$ faktycznie odrzuca token `\endscoop` więc nie musimy go w rzeczywistości definiować (np. przez `\def\endscoop{...}`).

Ta $$\mathrm\TeX$$ kod zawarty w `\halign{...}` jest zapisywany w `toks` rejestrze o nazwie `\fulltoks`. Jednym z trudnych problemów, na który natrafiłem (w przypadku $$\text{Lua}\mathrm\TeX$$), było zapobieżenie temu, aby znaki `#` wewnątrz `\halign{...}` preambuły były „podwajane” do `##` podczas zapisywania do pliku `.tex` . Aby tego uniknąć, musiałem tymczasowo ustawić znaki `\catcode`o wartości `#` na 12 przed zapisaniem $$\mathrm\TeX$$ kodu (tokenów) w `\fulltoks` rejestrze tokenów.

Następnym krokiem jest zapisanie tokenów zawartych w `\fulltoks` jako pliku $$\mathrm\TeX$$ — ponieważ używałem $$\text{Lua}\mathrm\TeX$$ okazało się to *skrajnie* łatwe dzięki znakomitemu API Lua $$\text{Lua}\mathrm\TeX$$. Krótko mówiąc, napisałem makro o nazwie `\writefile{...}` które jako parametr przyjmuje nazwę rejestru tokenów, których tokeny chcesz zapisać do pliku (np. `\writefile{fulltoks}`). Wewnątrz makra `\writefile{...}` użyłem API Lua, aby uzyskać tekstową reprezentację `\fulltoks` rejestru tokenów:

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

Oto zrzut ekranu pokazujący nieco więcej `\writefile{...}` polecenia:

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

Język Lua oraz API Lua zapewniane przez $$\text{Lua}\mathrm\TeX$$ mogą często uprościć $$\mathrm\TeX$$ zadania programistyczne i to właśnie dzięki tym użytecznym i potężnym funkcjom używam $$\text{Lua}\mathrm\TeX$$ od około 2009 roku — i nadal jestem wielkim fanem tego naprawdę wspaniałego $$\mathrm\TeX$$ silnika. Dobrze, reklama $$\text{Lua}\mathrm\TeX$$ dobiega teraz końca.

Po tak łatwym uzyskaniu $$\mathrm\TeX$$ kodu przechowywanego w `\fulltoks` jest on zapisywany do pliku wraz z dodatkowym kodem, aby utworzyć poprawnie sformowany plik $$\mathrm\LaTeX$$ . Następne kroki są następujące:

1. Przetwórz `.tex` plik zawierający naszą tabelę za pomocą $$\text{pdf}\mathrm\LaTeX$$ (w trybie DVI), aby złożyć tabelę i wygenerować plik `.dvi` do przetworzenia przez `dvisvgm` . Tak, możesz użyć $$\text{Lua}\mathrm\TeX$$ do uruchomienia $$\text{pdf}\mathrm\LaTeX$$— ponownie użyłem metody omówionej w [poprzednim artykule](/latex/pl/artykuly-szczegolowe/52-using-luatex-to-run-tools-and-utilities-installed-on-overleaf-s-servers.md).
2. I na koniec uruchom `dvisvgm` aby przetworzyć `.dvi` plik i wygenerować grafikę SVG złożonej $$\mathrm\TeX$$ tabeli.
3. Aby uzyskać rzeczywiste grafiki SVG, możesz pobrać plik ZIP z Overleaf — pamiętaj, aby wybrać **Pliki wejściowe i wyjściowe** .


---

# 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/pl/artykuly-szczegolowe/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.
