[{"data":1,"prerenderedAt":1774},["ShallowReactive",2],{"blog-en-multi-page-table":3},{"id":4,"title":5,"author":6,"body":10,"date":1739,"description":1740,"draft":1741,"extension":1742,"howTo":1743,"image":1764,"meta":1765,"navigation":142,"path":1766,"seo":1767,"stem":1768,"tags":1769,"updated":1764,"__hash__":1773},"blog/blog/024.multi-page-table.md","How do I make a table span multiple pages?",{"name":7,"url":8,"avatar":9},"Taiki Noda","https://nadai.dev/en/about","https://nadai.dev/og-default.png",{"type":11,"value":12,"toc":1727},"minimark",[13,18,30,34,42,86,105,109,123,1136,1143,1147,1172,1175,1199,1203,1210,1408,1423,1427,1430,1552,1563,1567,1602,1606,1647,1651,1687,1691,1694,1711,1723],[14,15,17],"h2",{"id":16},"the-question-in-other-words","The question, in other words",[19,20,21,22,29],"p",{},"I have a report — invoice line items, a transaction log, a 300-row export — and it obviously won't fit on one A4 page. In a Go PDF library, what do I have to do to make the table flow onto page 2, page 3, and so on, with the header reappearing at the top each time? In ",[23,24,28],"a",{"href":25,"rel":26},"https://github.com/gpdf-dev/gpdf",[27],"nofollow","gpdf",", the answer is short.",[14,31,33],{"id":32},"tldr","TL;DR",[19,35,36,37,41],{},"Nothing. You write one ",[38,39,40],"code",{},"Table"," call, give it all your rows, and gpdf paginates it:",[43,44,49],"pre",{"className":45,"code":46,"language":47,"meta":48,"style":48},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","c.Table(header, rows) // rows has 300 entries — gpdf splits it across pages\n","go","",[38,50,51],{"__ignoreMap":48},[52,53,56,60,64,67,70,73,76,79,82],"span",{"class":54,"line":55},"line",1,[52,57,59],{"class":58},"sTEyZ","c",[52,61,63],{"class":62},"sMK4o",".",[52,65,40],{"class":66},"s2Zo4",[52,68,69],{"class":62},"(",[52,71,72],{"class":58},"header",[52,74,75],{"class":62},",",[52,77,78],{"class":58}," rows",[52,80,81],{"class":62},")",[52,83,85],{"class":84},"sHwdD"," // rows has 300 entries — gpdf splits it across pages\n",[19,87,88,89,91,92,96,97,100,101,104],{},"The body is split row by row across as many pages as it needs. The ",[38,90,72],{}," slice is ",[93,94,95],"strong",{},"re-emitted at the top of every continuation page"," automatically — same column widths, same styling. There is no ",[38,98,99],{},"PageBreak()"," method to call, no ",[38,102,103],{},"MaxRowsPerPage"," option, no row-counting loop. Overflow is the layout engine's job, not yours.",[14,106,108],{"id":107},"working-code","Working code",[19,110,111,112,115,116,119,120,63],{},"A complete program that produces a multi-page table. Save as ",[38,113,114],{},"main.go",", run ",[38,117,118],{},"go run .",", get ",[38,121,122],{},"report.pdf",[43,124,126],{"className":45,"code":125,"language":47,"meta":48,"style":48},"package main\n\nimport (\n    \"fmt\"\n    \"log\"\n    \"os\"\n\n    \"github.com/gpdf-dev/gpdf\"\n    \"github.com/gpdf-dev/gpdf/document\"\n    \"github.com/gpdf-dev/gpdf/pdf\"\n    \"github.com/gpdf-dev/gpdf/template\"\n)\n\nfunc main() {\n    doc := gpdf.NewDocument(\n        gpdf.WithPageSize(gpdf.A4),\n        gpdf.WithMargins(document.UniformEdges(document.Mm(20))),\n    )\n\n    brand := pdf.RGBHex(0x1A237E)\n\n    header := []string{\"Date\", \"Invoice #\", \"Customer\", \"Amount\"}\n    rows := make([][]string, 0, 200)\n    for i := 1; i \u003C= 200; i++ {\n        rows = append(rows, []string{\n            fmt.Sprintf(\"2026-%02d-%02d\", (i%6)+1, (i%28)+1),\n            fmt.Sprintf(\"INV-%05d\", 10000+i),\n            fmt.Sprintf(\"Customer #%d\", i),\n            fmt.Sprintf(\"$%d.00\", 100+i*7),\n        })\n    }\n\n    page := doc.AddPage()\n    page.AutoRow(func(r *template.RowBuilder) {\n        r.Col(12, func(c *template.ColBuilder) {\n            c.Text(\"2026 Invoice Ledger\", template.FontSize(18), template.Bold())\n            c.Spacer(document.Mm(4))\n\n            c.Table(header, rows,\n                template.ColumnWidths(20, 20, 40, 20),\n                template.TableHeaderStyle(\n                    template.TextColor(pdf.White),\n                    template.BgColor(brand),\n                ),\n            )\n        })\n    })\n\n    data, err := doc.Generate()\n    if err != nil {\n        log.Fatal(err)\n    }\n    if err := os.WriteFile(\"report.pdf\", data, 0o644); err != nil {\n        log.Fatal(err)\n    }\n}\n",[38,127,128,137,144,154,166,176,186,191,201,211,221,231,237,242,257,277,300,338,344,349,372,377,435,463,497,523,589,622,649,689,695,701,706,725,758,794,842,868,873,893,924,936,959,976,982,988,993,999,1004,1026,1042,1060,1065,1111,1126,1131],{"__ignoreMap":48},[52,129,130,133],{"class":54,"line":55},[52,131,132],{"class":62},"package",[52,134,136],{"class":135},"sBMFI"," main\n",[52,138,140],{"class":54,"line":139},2,[52,141,143],{"emptyLinePlaceholder":142},true,"\n",[52,145,147,151],{"class":54,"line":146},3,[52,148,150],{"class":149},"s7zQu","import",[52,152,153],{"class":62}," (\n",[52,155,157,160,163],{"class":54,"line":156},4,[52,158,159],{"class":62},"    \"",[52,161,162],{"class":135},"fmt",[52,164,165],{"class":62},"\"\n",[52,167,169,171,174],{"class":54,"line":168},5,[52,170,159],{"class":62},[52,172,173],{"class":135},"log",[52,175,165],{"class":62},[52,177,179,181,184],{"class":54,"line":178},6,[52,180,159],{"class":62},[52,182,183],{"class":135},"os",[52,185,165],{"class":62},[52,187,189],{"class":54,"line":188},7,[52,190,143],{"emptyLinePlaceholder":142},[52,192,194,196,199],{"class":54,"line":193},8,[52,195,159],{"class":62},[52,197,198],{"class":135},"github.com/gpdf-dev/gpdf",[52,200,165],{"class":62},[52,202,204,206,209],{"class":54,"line":203},9,[52,205,159],{"class":62},[52,207,208],{"class":135},"github.com/gpdf-dev/gpdf/document",[52,210,165],{"class":62},[52,212,214,216,219],{"class":54,"line":213},10,[52,215,159],{"class":62},[52,217,218],{"class":135},"github.com/gpdf-dev/gpdf/pdf",[52,220,165],{"class":62},[52,222,224,226,229],{"class":54,"line":223},11,[52,225,159],{"class":62},[52,227,228],{"class":135},"github.com/gpdf-dev/gpdf/template",[52,230,165],{"class":62},[52,232,234],{"class":54,"line":233},12,[52,235,236],{"class":62},")\n",[52,238,240],{"class":54,"line":239},13,[52,241,143],{"emptyLinePlaceholder":142},[52,243,245,248,251,254],{"class":54,"line":244},14,[52,246,247],{"class":62},"func",[52,249,250],{"class":66}," main",[52,252,253],{"class":62},"()",[52,255,256],{"class":62}," {\n",[52,258,260,263,266,269,271,274],{"class":54,"line":259},15,[52,261,262],{"class":58},"    doc ",[52,264,265],{"class":62},":=",[52,267,268],{"class":58}," gpdf",[52,270,63],{"class":62},[52,272,273],{"class":66},"NewDocument",[52,275,276],{"class":62},"(\n",[52,278,280,283,285,288,290,292,294,297],{"class":54,"line":279},16,[52,281,282],{"class":58},"        gpdf",[52,284,63],{"class":62},[52,286,287],{"class":66},"WithPageSize",[52,289,69],{"class":62},[52,291,28],{"class":58},[52,293,63],{"class":62},[52,295,296],{"class":58},"A4",[52,298,299],{"class":62},"),\n",[52,301,303,305,307,310,312,315,317,320,322,324,326,329,331,335],{"class":54,"line":302},17,[52,304,282],{"class":58},[52,306,63],{"class":62},[52,308,309],{"class":66},"WithMargins",[52,311,69],{"class":62},[52,313,314],{"class":58},"document",[52,316,63],{"class":62},[52,318,319],{"class":66},"UniformEdges",[52,321,69],{"class":62},[52,323,314],{"class":58},[52,325,63],{"class":62},[52,327,328],{"class":66},"Mm",[52,330,69],{"class":62},[52,332,334],{"class":333},"sbssI","20",[52,336,337],{"class":62},"))),\n",[52,339,341],{"class":54,"line":340},18,[52,342,343],{"class":62},"    )\n",[52,345,347],{"class":54,"line":346},19,[52,348,143],{"emptyLinePlaceholder":142},[52,350,352,355,357,360,362,365,367,370],{"class":54,"line":351},20,[52,353,354],{"class":58},"    brand ",[52,356,265],{"class":62},[52,358,359],{"class":58}," pdf",[52,361,63],{"class":62},[52,363,364],{"class":66},"RGBHex",[52,366,69],{"class":62},[52,368,369],{"class":333},"0x1A237E",[52,371,236],{"class":62},[52,373,375],{"class":54,"line":374},21,[52,376,143],{"emptyLinePlaceholder":142},[52,378,380,383,385,388,392,395,398,402,404,406,409,412,414,416,418,421,423,425,427,430,432],{"class":54,"line":379},22,[52,381,382],{"class":58},"    header ",[52,384,265],{"class":62},[52,386,387],{"class":62}," []",[52,389,391],{"class":390},"spNyl","string",[52,393,394],{"class":62},"{",[52,396,397],{"class":62},"\"",[52,399,401],{"class":400},"sfazB","Date",[52,403,397],{"class":62},[52,405,75],{"class":62},[52,407,408],{"class":62}," \"",[52,410,411],{"class":400},"Invoice #",[52,413,397],{"class":62},[52,415,75],{"class":62},[52,417,408],{"class":62},[52,419,420],{"class":400},"Customer",[52,422,397],{"class":62},[52,424,75],{"class":62},[52,426,408],{"class":62},[52,428,429],{"class":400},"Amount",[52,431,397],{"class":62},[52,433,434],{"class":62},"}\n",[52,436,438,441,443,446,449,451,453,456,458,461],{"class":54,"line":437},23,[52,439,440],{"class":58},"    rows ",[52,442,265],{"class":62},[52,444,445],{"class":66}," make",[52,447,448],{"class":62},"([][]",[52,450,391],{"class":390},[52,452,75],{"class":62},[52,454,455],{"class":333}," 0",[52,457,75],{"class":62},[52,459,460],{"class":333}," 200",[52,462,236],{"class":62},[52,464,466,469,472,474,477,480,482,485,487,489,492,495],{"class":54,"line":465},24,[52,467,468],{"class":149},"    for",[52,470,471],{"class":58}," i ",[52,473,265],{"class":62},[52,475,476],{"class":333}," 1",[52,478,479],{"class":62},";",[52,481,471],{"class":58},[52,483,484],{"class":62},"\u003C=",[52,486,460],{"class":333},[52,488,479],{"class":62},[52,490,491],{"class":58}," i",[52,493,494],{"class":62},"++",[52,496,256],{"class":62},[52,498,500,503,506,509,511,514,516,518,520],{"class":54,"line":499},25,[52,501,502],{"class":58},"        rows ",[52,504,505],{"class":62},"=",[52,507,508],{"class":66}," append",[52,510,69],{"class":62},[52,512,513],{"class":58},"rows",[52,515,75],{"class":62},[52,517,387],{"class":62},[52,519,391],{"class":390},[52,521,522],{"class":62},"{\n",[52,524,526,529,531,534,536,538,541,545,548,550,552,554,557,560,563,566,569,572,574,576,578,580,583,585,587],{"class":54,"line":525},26,[52,527,528],{"class":58},"            fmt",[52,530,63],{"class":62},[52,532,533],{"class":66},"Sprintf",[52,535,69],{"class":62},[52,537,397],{"class":62},[52,539,540],{"class":400},"2026-",[52,542,544],{"class":543},"swJcz","%02d",[52,546,547],{"class":400},"-",[52,549,544],{"class":543},[52,551,397],{"class":62},[52,553,75],{"class":62},[52,555,556],{"class":62}," (",[52,558,559],{"class":58},"i",[52,561,562],{"class":62},"%",[52,564,565],{"class":333},"6",[52,567,568],{"class":62},")+",[52,570,571],{"class":333},"1",[52,573,75],{"class":62},[52,575,556],{"class":62},[52,577,559],{"class":58},[52,579,562],{"class":62},[52,581,582],{"class":333},"28",[52,584,568],{"class":62},[52,586,571],{"class":333},[52,588,299],{"class":62},[52,590,592,594,596,598,600,602,605,608,610,612,615,618,620],{"class":54,"line":591},27,[52,593,528],{"class":58},[52,595,63],{"class":62},[52,597,533],{"class":66},[52,599,69],{"class":62},[52,601,397],{"class":62},[52,603,604],{"class":400},"INV-",[52,606,607],{"class":543},"%05d",[52,609,397],{"class":62},[52,611,75],{"class":62},[52,613,614],{"class":333}," 10000",[52,616,617],{"class":62},"+",[52,619,559],{"class":58},[52,621,299],{"class":62},[52,623,625,627,629,631,633,635,638,641,643,645,647],{"class":54,"line":624},28,[52,626,528],{"class":58},[52,628,63],{"class":62},[52,630,533],{"class":66},[52,632,69],{"class":62},[52,634,397],{"class":62},[52,636,637],{"class":400},"Customer #",[52,639,640],{"class":543},"%d",[52,642,397],{"class":62},[52,644,75],{"class":62},[52,646,491],{"class":58},[52,648,299],{"class":62},[52,650,652,654,656,658,660,662,665,667,670,672,674,677,679,681,684,687],{"class":54,"line":651},29,[52,653,528],{"class":58},[52,655,63],{"class":62},[52,657,533],{"class":66},[52,659,69],{"class":62},[52,661,397],{"class":62},[52,663,664],{"class":400},"$",[52,666,640],{"class":543},[52,668,669],{"class":400},".00",[52,671,397],{"class":62},[52,673,75],{"class":62},[52,675,676],{"class":333}," 100",[52,678,617],{"class":62},[52,680,559],{"class":58},[52,682,683],{"class":62},"*",[52,685,686],{"class":333},"7",[52,688,299],{"class":62},[52,690,692],{"class":54,"line":691},30,[52,693,694],{"class":62},"        })\n",[52,696,698],{"class":54,"line":697},31,[52,699,700],{"class":62},"    }\n",[52,702,704],{"class":54,"line":703},32,[52,705,143],{"emptyLinePlaceholder":142},[52,707,709,712,714,717,719,722],{"class":54,"line":708},33,[52,710,711],{"class":58},"    page ",[52,713,265],{"class":62},[52,715,716],{"class":58}," doc",[52,718,63],{"class":62},[52,720,721],{"class":66},"AddPage",[52,723,724],{"class":62},"()\n",[52,726,728,731,733,736,739,743,746,749,751,754,756],{"class":54,"line":727},34,[52,729,730],{"class":58},"    page",[52,732,63],{"class":62},[52,734,735],{"class":66},"AutoRow",[52,737,738],{"class":62},"(func(",[52,740,742],{"class":741},"sHdIc","r",[52,744,745],{"class":62}," *",[52,747,748],{"class":135},"template",[52,750,63],{"class":62},[52,752,753],{"class":135},"RowBuilder",[52,755,81],{"class":62},[52,757,256],{"class":62},[52,759,761,764,766,769,771,774,776,779,781,783,785,787,790,792],{"class":54,"line":760},35,[52,762,763],{"class":58},"        r",[52,765,63],{"class":62},[52,767,768],{"class":66},"Col",[52,770,69],{"class":62},[52,772,773],{"class":333},"12",[52,775,75],{"class":62},[52,777,778],{"class":62}," func(",[52,780,59],{"class":741},[52,782,745],{"class":62},[52,784,748],{"class":135},[52,786,63],{"class":62},[52,788,789],{"class":135},"ColBuilder",[52,791,81],{"class":62},[52,793,256],{"class":62},[52,795,797,800,802,805,807,809,812,814,816,819,821,824,826,829,832,834,836,839],{"class":54,"line":796},36,[52,798,799],{"class":58},"            c",[52,801,63],{"class":62},[52,803,804],{"class":66},"Text",[52,806,69],{"class":62},[52,808,397],{"class":62},[52,810,811],{"class":400},"2026 Invoice Ledger",[52,813,397],{"class":62},[52,815,75],{"class":62},[52,817,818],{"class":58}," template",[52,820,63],{"class":62},[52,822,823],{"class":66},"FontSize",[52,825,69],{"class":62},[52,827,828],{"class":333},"18",[52,830,831],{"class":62},"),",[52,833,818],{"class":58},[52,835,63],{"class":62},[52,837,838],{"class":66},"Bold",[52,840,841],{"class":62},"())\n",[52,843,845,847,849,852,854,856,858,860,862,865],{"class":54,"line":844},37,[52,846,799],{"class":58},[52,848,63],{"class":62},[52,850,851],{"class":66},"Spacer",[52,853,69],{"class":62},[52,855,314],{"class":58},[52,857,63],{"class":62},[52,859,328],{"class":66},[52,861,69],{"class":62},[52,863,864],{"class":333},"4",[52,866,867],{"class":62},"))\n",[52,869,871],{"class":54,"line":870},38,[52,872,143],{"emptyLinePlaceholder":142},[52,874,876,878,880,882,884,886,888,890],{"class":54,"line":875},39,[52,877,799],{"class":58},[52,879,63],{"class":62},[52,881,40],{"class":66},[52,883,69],{"class":62},[52,885,72],{"class":58},[52,887,75],{"class":62},[52,889,78],{"class":58},[52,891,892],{"class":62},",\n",[52,894,896,899,901,904,906,908,910,913,915,918,920,922],{"class":54,"line":895},40,[52,897,898],{"class":58},"                template",[52,900,63],{"class":62},[52,902,903],{"class":66},"ColumnWidths",[52,905,69],{"class":62},[52,907,334],{"class":333},[52,909,75],{"class":62},[52,911,912],{"class":333}," 20",[52,914,75],{"class":62},[52,916,917],{"class":333}," 40",[52,919,75],{"class":62},[52,921,912],{"class":333},[52,923,299],{"class":62},[52,925,927,929,931,934],{"class":54,"line":926},41,[52,928,898],{"class":58},[52,930,63],{"class":62},[52,932,933],{"class":66},"TableHeaderStyle",[52,935,276],{"class":62},[52,937,939,942,944,947,949,952,954,957],{"class":54,"line":938},42,[52,940,941],{"class":58},"                    template",[52,943,63],{"class":62},[52,945,946],{"class":66},"TextColor",[52,948,69],{"class":62},[52,950,951],{"class":58},"pdf",[52,953,63],{"class":62},[52,955,956],{"class":58},"White",[52,958,299],{"class":62},[52,960,962,964,966,969,971,974],{"class":54,"line":961},43,[52,963,941],{"class":58},[52,965,63],{"class":62},[52,967,968],{"class":66},"BgColor",[52,970,69],{"class":62},[52,972,973],{"class":58},"brand",[52,975,299],{"class":62},[52,977,979],{"class":54,"line":978},44,[52,980,981],{"class":62},"                ),\n",[52,983,985],{"class":54,"line":984},45,[52,986,987],{"class":62},"            )\n",[52,989,991],{"class":54,"line":990},46,[52,992,694],{"class":62},[52,994,996],{"class":54,"line":995},47,[52,997,998],{"class":62},"    })\n",[52,1000,1002],{"class":54,"line":1001},48,[52,1003,143],{"emptyLinePlaceholder":142},[52,1005,1007,1010,1012,1015,1017,1019,1021,1024],{"class":54,"line":1006},49,[52,1008,1009],{"class":58},"    data",[52,1011,75],{"class":62},[52,1013,1014],{"class":58}," err ",[52,1016,265],{"class":62},[52,1018,716],{"class":58},[52,1020,63],{"class":62},[52,1022,1023],{"class":66},"Generate",[52,1025,724],{"class":62},[52,1027,1029,1032,1034,1037,1040],{"class":54,"line":1028},50,[52,1030,1031],{"class":149},"    if",[52,1033,1014],{"class":58},[52,1035,1036],{"class":62},"!=",[52,1038,1039],{"class":62}," nil",[52,1041,256],{"class":62},[52,1043,1045,1048,1050,1053,1055,1058],{"class":54,"line":1044},51,[52,1046,1047],{"class":58},"        log",[52,1049,63],{"class":62},[52,1051,1052],{"class":66},"Fatal",[52,1054,69],{"class":62},[52,1056,1057],{"class":58},"err",[52,1059,236],{"class":62},[52,1061,1063],{"class":54,"line":1062},52,[52,1064,700],{"class":62},[52,1066,1068,1070,1072,1074,1077,1079,1082,1084,1086,1088,1090,1092,1095,1097,1100,1103,1105,1107,1109],{"class":54,"line":1067},53,[52,1069,1031],{"class":149},[52,1071,1014],{"class":58},[52,1073,265],{"class":62},[52,1075,1076],{"class":58}," os",[52,1078,63],{"class":62},[52,1080,1081],{"class":66},"WriteFile",[52,1083,69],{"class":62},[52,1085,397],{"class":62},[52,1087,122],{"class":400},[52,1089,397],{"class":62},[52,1091,75],{"class":62},[52,1093,1094],{"class":58}," data",[52,1096,75],{"class":62},[52,1098,1099],{"class":333}," 0o644",[52,1101,1102],{"class":62},");",[52,1104,1014],{"class":58},[52,1106,1036],{"class":62},[52,1108,1039],{"class":62},[52,1110,256],{"class":62},[52,1112,1114,1116,1118,1120,1122,1124],{"class":54,"line":1113},54,[52,1115,1047],{"class":58},[52,1117,63],{"class":62},[52,1119,1052],{"class":66},[52,1121,69],{"class":62},[52,1123,1057],{"class":58},[52,1125,236],{"class":62},[52,1127,1129],{"class":54,"line":1128},55,[52,1130,700],{"class":62},[52,1132,1134],{"class":54,"line":1133},56,[52,1135,434],{"class":62},[19,1137,1138,1139,1142],{},"200 rows on A4 lands on roughly eight pages. On every one of them the dark-blue header sits at the top; the body picks up exactly where the previous page stopped. The only thing in that code that hints at \"multi-page\" is the ",[38,1140,1141],{},"200"," in the loop bound.",[14,1144,1146],{"id":1145},"how-it-works","How it works",[19,1148,1149,1150,1154,1155,1158,1159,1165,1166,1171],{},"Worth understanding so you trust it. When the layout engine lays out the table, it measures body rows in order and adds them to the current page until the next row would exceed the available height. The rows that didn't fit become an ",[1151,1152,1153],"em",{},"overflow table"," — a new ",[38,1156,1157],{},"*document.Table"," carrying the ",[93,1160,1161,1162],{},"same ",[38,1163,1164],{},"Header",", the ",[93,1167,1161,1168],{},[38,1169,1170],{},"Footer",", and the leftover body rows. gpdf flushes the laid-out part to the page, opens the next page, and feeds the overflow table back into the layout engine with the new page's height. Repeat until there's nothing left over.",[19,1173,1174],{},"Two things fall out of that design:",[1176,1177,1178,1189],"ul",{},[1179,1180,1181,1188],"li",{},[93,1182,1183,1184,1187],{},"The header repeats because it lives in ",[38,1185,1186],{},"tbl.Header",", not in your loop."," The overflow table reuses the same slice, so it re-renders identically on every page. You get this for free.",[1179,1190,1191,1194,1195,1198],{},[93,1192,1193],{},"There's no \"header doesn't fit\" edge case."," The engine reserves space for the header ",[1151,1196,1197],{},"before"," measuring how many body rows fit. If a page can't hold the header plus at least one body row, the whole table is pushed to the next page instead of being split awkwardly.",[14,1200,1202],{"id":1201},"footers-that-repeat-too","Footers that repeat too",[19,1204,1205,1206,1209],{},"If you want a totals row (or a \"page summary\") that also appears at the bottom of every page, that's ",[38,1207,1208],{},"document.Table.Footer"," — available when you build the table at the document layer instead of through the builder:",[43,1211,1213],{"className":45,"code":1212,"language":47,"meta":48,"style":48},"import \"github.com/gpdf-dev/gpdf/document\"\n\ntbl := &document.Table{\n    Columns: []document.TableColumn{\n        {Width: document.Pct(20)}, {Width: document.Pct(20)},\n        {Width: document.Auto},    {Width: document.Pct(20)},\n    },\n    Header: headerRows, // []document.TableRow\n    Body:   bodyRows,\n    Footer: []document.TableRow{footerRow},\n}\n",[38,1214,1215,1225,1229,1247,1266,1311,1348,1353,1368,1380,1404],{"__ignoreMap":48},[52,1216,1217,1219,1221,1223],{"class":54,"line":55},[52,1218,150],{"class":149},[52,1220,408],{"class":62},[52,1222,208],{"class":135},[52,1224,165],{"class":62},[52,1226,1227],{"class":54,"line":139},[52,1228,143],{"emptyLinePlaceholder":142},[52,1230,1231,1234,1236,1239,1241,1243,1245],{"class":54,"line":146},[52,1232,1233],{"class":58},"tbl ",[52,1235,265],{"class":62},[52,1237,1238],{"class":62}," &",[52,1240,314],{"class":135},[52,1242,63],{"class":62},[52,1244,40],{"class":135},[52,1246,522],{"class":62},[52,1248,1249,1252,1255,1257,1259,1261,1264],{"class":54,"line":156},[52,1250,1251],{"class":58},"    Columns",[52,1253,1254],{"class":62},":",[52,1256,387],{"class":62},[52,1258,314],{"class":135},[52,1260,63],{"class":62},[52,1262,1263],{"class":135},"TableColumn",[52,1265,522],{"class":62},[52,1267,1268,1271,1274,1276,1279,1281,1284,1286,1288,1291,1294,1296,1298,1300,1302,1304,1306,1308],{"class":54,"line":168},[52,1269,1270],{"class":62},"        {",[52,1272,1273],{"class":58},"Width",[52,1275,1254],{"class":62},[52,1277,1278],{"class":58}," document",[52,1280,63],{"class":62},[52,1282,1283],{"class":66},"Pct",[52,1285,69],{"class":62},[52,1287,334],{"class":333},[52,1289,1290],{"class":62},")},",[52,1292,1293],{"class":62}," {",[52,1295,1273],{"class":58},[52,1297,1254],{"class":62},[52,1299,1278],{"class":58},[52,1301,63],{"class":62},[52,1303,1283],{"class":66},[52,1305,69],{"class":62},[52,1307,334],{"class":333},[52,1309,1310],{"class":62},")},\n",[52,1312,1313,1315,1317,1319,1321,1323,1326,1329,1332,1334,1336,1338,1340,1342,1344,1346],{"class":54,"line":178},[52,1314,1270],{"class":62},[52,1316,1273],{"class":58},[52,1318,1254],{"class":62},[52,1320,1278],{"class":58},[52,1322,63],{"class":62},[52,1324,1325],{"class":58},"Auto",[52,1327,1328],{"class":62},"},",[52,1330,1331],{"class":62},"    {",[52,1333,1273],{"class":58},[52,1335,1254],{"class":62},[52,1337,1278],{"class":58},[52,1339,63],{"class":62},[52,1341,1283],{"class":66},[52,1343,69],{"class":62},[52,1345,334],{"class":333},[52,1347,1310],{"class":62},[52,1349,1350],{"class":54,"line":188},[52,1351,1352],{"class":62},"    },\n",[52,1354,1355,1358,1360,1363,1365],{"class":54,"line":193},[52,1356,1357],{"class":58},"    Header",[52,1359,1254],{"class":62},[52,1361,1362],{"class":58}," headerRows",[52,1364,75],{"class":62},[52,1366,1367],{"class":84}," // []document.TableRow\n",[52,1369,1370,1373,1375,1378],{"class":54,"line":203},[52,1371,1372],{"class":58},"    Body",[52,1374,1254],{"class":62},[52,1376,1377],{"class":58},"   bodyRows",[52,1379,892],{"class":62},[52,1381,1382,1385,1387,1389,1391,1393,1396,1398,1401],{"class":54,"line":213},[52,1383,1384],{"class":58},"    Footer",[52,1386,1254],{"class":62},[52,1388,387],{"class":62},[52,1390,314],{"class":135},[52,1392,63],{"class":62},[52,1394,1395],{"class":135},"TableRow",[52,1397,394],{"class":62},[52,1399,1400],{"class":58},"footerRow",[52,1402,1403],{"class":62},"},\n",[52,1405,1406],{"class":54,"line":223},[52,1407,434],{"class":62},[19,1409,1410,1411,1413,1414,1417,1418,1422],{},"The ",[38,1412,1170],{}," slice repeats on every continuation page, same mechanism as the header. The builder's ",[38,1415,1416],{},"c.Table(...)"," doesn't expose a footer because most short tables don't need one — when you do, you've left the common-case zone, and ",[23,1419,1421],{"href":1420},"/blog/tables-in-go-pdfs","the deep-dive on tables"," walks through the document layer.",[14,1424,1426],{"id":1425},"forcing-the-table-to-start-on-a-fresh-page","Forcing the table to start on a fresh page",[19,1428,1429],{},"There's no per-table \"begin on a new page\" option. You do it at the page level — add a page before the row that holds the table:",[43,1431,1433],{"className":45,"code":1432,"language":47,"meta":48,"style":48},"doc.AddPage() // the table below starts at the top of this page\npage2 := doc.AddPage()\npage2.AutoRow(func(r *template.RowBuilder) {\n    r.Col(12, func(c *template.ColBuilder) {\n        c.Table(header, rows /* , opts... */)\n    })\n})\n",[38,1434,1435,1449,1464,1489,1520,1543,1547],{"__ignoreMap":48},[52,1436,1437,1440,1442,1444,1446],{"class":54,"line":55},[52,1438,1439],{"class":58},"doc",[52,1441,63],{"class":62},[52,1443,721],{"class":66},[52,1445,253],{"class":62},[52,1447,1448],{"class":84}," // the table below starts at the top of this page\n",[52,1450,1451,1454,1456,1458,1460,1462],{"class":54,"line":139},[52,1452,1453],{"class":58},"page2 ",[52,1455,265],{"class":62},[52,1457,716],{"class":58},[52,1459,63],{"class":62},[52,1461,721],{"class":66},[52,1463,724],{"class":62},[52,1465,1466,1469,1471,1473,1475,1477,1479,1481,1483,1485,1487],{"class":54,"line":146},[52,1467,1468],{"class":58},"page2",[52,1470,63],{"class":62},[52,1472,735],{"class":66},[52,1474,738],{"class":62},[52,1476,742],{"class":741},[52,1478,745],{"class":62},[52,1480,748],{"class":135},[52,1482,63],{"class":62},[52,1484,753],{"class":135},[52,1486,81],{"class":62},[52,1488,256],{"class":62},[52,1490,1491,1494,1496,1498,1500,1502,1504,1506,1508,1510,1512,1514,1516,1518],{"class":54,"line":156},[52,1492,1493],{"class":58},"    r",[52,1495,63],{"class":62},[52,1497,768],{"class":66},[52,1499,69],{"class":62},[52,1501,773],{"class":333},[52,1503,75],{"class":62},[52,1505,778],{"class":62},[52,1507,59],{"class":741},[52,1509,745],{"class":62},[52,1511,748],{"class":135},[52,1513,63],{"class":62},[52,1515,789],{"class":135},[52,1517,81],{"class":62},[52,1519,256],{"class":62},[52,1521,1522,1525,1527,1529,1531,1533,1535,1538,1541],{"class":54,"line":168},[52,1523,1524],{"class":58},"        c",[52,1526,63],{"class":62},[52,1528,40],{"class":66},[52,1530,69],{"class":62},[52,1532,72],{"class":58},[52,1534,75],{"class":62},[52,1536,1537],{"class":58}," rows ",[52,1539,1540],{"class":84},"/* , opts... */",[52,1542,236],{"class":62},[52,1544,1545],{"class":54,"line":178},[52,1546,998],{"class":62},[52,1548,1549],{"class":54,"line":188},[52,1550,1551],{"class":62},"})\n",[19,1553,1554,1555,1558,1559,1562],{},"That's the only \"page break\" control you need for tables, because the table's ",[1151,1556,1557],{},"internal"," breaks are handled for you and the ",[1151,1560,1561],{},"external"," one is just \"where does this block start.\"",[14,1564,1566],{"id":1565},"what-you-dont-get","What you don't get",[1176,1568,1569,1575,1592],{},[1179,1570,1571,1574],{},[93,1572,1573],{},"\"Keep these rows together.\""," Every body row is split-eligible. There's no annotation that says \"row group 4–7 must stay on one page.\" It's a known gap. If an invoice line item plus its sub-rows really must not be torn across a page, the workaround is to start a fresh page before that group, or build the table at the document layer and insert your own break hints.",[1179,1576,1577,1580,1581,1583,1584,1587,1588,1591],{},[93,1578,1579],{},"A footer on the last page only."," ",[38,1582,1208],{}," repeats on ",[1151,1585,1586],{},"every"," page by design (per-page column totals are the common case). For a one-shot grand total at the document end, append it as a separate block ",[1151,1589,1590],{},"after"," the table, not inside it.",[1179,1593,1594,1597,1598,1601],{},[93,1595,1596],{},"Page-of-N in the table itself."," \"Page 3 of 8\" belongs in the document footer, not the table. See ",[23,1599,1600],{"href":1420},"page numbers, headers, and footers"," for where that lives.",[14,1603,1605],{"id":1604},"mistakes-that-cost-ten-minutes","Mistakes that cost ten minutes",[1176,1607,1608,1618,1632,1641],{},[1179,1609,1610,1617],{},[93,1611,1612,1613,1616],{},"Looking for a ",[38,1614,1615],{},"PageBreak"," option."," There isn't one and you don't want one — if you're calling it manually you've already lost. Just feed all the rows.",[1179,1619,1620,1623,1624,1627,1628,1631],{},[93,1621,1622],{},"Splitting your data into per-page chunks yourself."," People do ",[38,1625,1626],{},"rows[0:40]"," on page 1, ",[38,1629,1630],{},"rows[40:80]"," on page 2… Don't. You'll get the row math wrong, the last page will be short, and the header styling will drift. Hand gpdf the whole slice.",[1179,1633,1634,1637,1638,1640],{},[93,1635,1636],{},"Expecting the header on page 1 only."," Some libraries do that. gpdf repeats it on ",[1151,1639,1586],{}," page, which is what you want for a report someone prints and flips through.",[1179,1642,1643,1646],{},[93,1644,1645],{},"A 6 MB CJK font on a 150-page table."," The font is subset to the glyphs actually used, so this is fine — the output stays small. But if you somehow disabled subsetting, a long table is where it bites. Leave subsetting on (it's the default).",[14,1648,1650],{"id":1649},"related-recipes","Related recipes",[1176,1652,1653,1663,1673,1680],{},[1179,1654,1655,1658,1659,1662],{},[23,1656,1657],{"href":1420},"Tables in Go PDFs: column widths, striped rows, page breaks"," — the long form, including ",[38,1660,1661],{},"document.Table"," and footers.",[1179,1664,1665,1669,1670,1672],{},[23,1666,1668],{"href":1667},"/blog/table-column-widths","How do I set custom column widths for a table?"," — ",[38,1671,903],{}," corner cases.",[1179,1674,1675,1679],{},[23,1676,1678],{"href":1677},"/blog/zebra-striped-table-rows","How do I create striped (zebra) table rows?"," — and how stripes stay consistent across a page break.",[1179,1681,1682,1686],{},[23,1683,1685],{"href":1684},"/blog/invoice-pdf-go-under-50-lines","Generate an invoice PDF in Go in under 50 lines"," — a real document with a table that paginates.",[14,1688,1690],{"id":1689},"try-gpdf","Try gpdf",[19,1692,1693],{},"gpdf is a Go library for generating PDFs. MIT licensed, zero external dependencies, native CJK support.",[43,1695,1699],{"className":1696,"code":1697,"language":1698,"meta":48,"style":48},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","go get github.com/gpdf-dev/gpdf\n","bash",[38,1700,1701],{"__ignoreMap":48},[52,1702,1703,1705,1708],{"class":54,"line":55},[52,1704,47],{"class":135},[52,1706,1707],{"class":400}," get",[52,1709,1710],{"class":400}," github.com/gpdf-dev/gpdf\n",[19,1712,1713,1717,1718],{},[23,1714,1716],{"href":25,"rel":1715},[27],"⭐ Star on GitHub"," · ",[23,1719,1722],{"href":1720,"rel":1721},"https://gpdf.dev/docs/quickstart",[27],"Read the docs",[1724,1725,1726],"style",{},"html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":48,"searchDepth":139,"depth":139,"links":1728},[1729,1730,1731,1732,1733,1734,1735,1736,1737,1738],{"id":16,"depth":139,"text":17},{"id":32,"depth":139,"text":33},{"id":107,"depth":139,"text":108},{"id":1145,"depth":139,"text":1146},{"id":1201,"depth":139,"text":1202},{"id":1425,"depth":139,"text":1426},{"id":1565,"depth":139,"text":1566},{"id":1604,"depth":139,"text":1605},{"id":1649,"depth":139,"text":1650},{"id":1689,"depth":139,"text":1690},"2026-05-12","You don't do anything. Feed gpdf a table with more rows than fit, and it paginates the body and repeats the header on every page automatically.",false,"md",{"name":1744,"totalTime":1745,"tools":1746,"steps":1748},"Render a table that spans multiple pages in gpdf with a repeating header","PT10M",[1747,198],"Go 1.22+",[1749,1752,1755,1758,1761],{"name":1750,"text":1751},"Build one Table call inside a Col","Inside page.AutoRow → r.Col(12, ...), call c.Table(header, rows). Header is []string, rows is [][]string. Don't loop, don't count rows, don't call any page-break method.",{"name":1753,"text":1754},"Feed it more rows than fit on a page","Append as many body rows as your data has. When the body overflows the current page, gpdf's layout engine produces an overflow table with the remaining rows and continues it on the next page.",{"name":1756,"text":1757},"Let gpdf repeat the header","The Header slice is carried into every continuation page automatically — same styling, same column widths. There is no option to enable this; it's the default behavior.",{"name":1759,"text":1760},"Use document.Table.Footer for per-page totals","Drop to &document.Table{Header, Body, Footer} when you want a footer row (column totals, page label) that also repeats at the bottom of every page.",{"name":1762,"text":1763},"Call doc.AddPage() before the table to force a fresh start","If you need the table to begin at the top of a new page rather than flowing from wherever the previous content ended, add a page first. There is no per-table 'start on new page' option.",null,{},"/blog/multi-page-table",{"title":5,"description":1740},"blog/024.multi-page-table",[1770,1771,1772],"recipe","tutorial","templates","vRfwQm6lGJqUQrzATuPVisSxnHKH4KSxlInxh8H99EY",1779199010120]