[{"data":1,"prerenderedAt":3449},["ShallowReactive",2],{"blog-es-tables-in-go-pdfs":3},{"id":4,"title":5,"author":6,"body":10,"date":3411,"description":3412,"draft":3413,"extension":3414,"howTo":3415,"image":3439,"meta":3440,"navigation":484,"path":3441,"seo":3442,"stem":3443,"tags":3444,"updated":3439,"__hash__":3448},"blogEs/es/blog/022.tables-in-go-pdfs.md","Tablas en PDFs con Go: anchos, rayas zebra, saltos de página",{"name":7,"url":8,"avatar":9},"Taiki Noda","https://nadai.dev/en/about","https://nadai.dev/og-default.png",{"type":11,"value":12,"toc":3394},"minimark",[13,18,26,184,203,206,210,224,227,261,264,268,271,333,340,443,449,453,467,1579,1582,1598,1602,1612,1630,1636,1642,1681,1688,1719,1727,1731,1758,1768,1786,1789,1810,1822,1826,1829,1839,1865,1868,1889,1892,1899,1903,1908,2347,2384,2393,2403,2408,2412,2415,2476,2492,2498,2501,2695,2698,2702,2705,2842,2851,2864,2868,2871,3170,3173,3181,3185,3190,3213,3218,3242,3247,3250,3255,3267,3272,3278,3286,3293,3297,3304,3311,3314,3318,3321,3338,3350,3354,3390],[14,15,17],"h2",{"id":16},"tldr","TL;DR",[19,20,21,25],"p",{},[22,23,24],"strong",{},"Las tablas son la parte de la generación de PDFs que arruina los fines de semana."," Anchos de columna que no suman, headers que desaparecen en la página 2, rayas dibujadas con un bucle de filas que tiene un off-by-one. gpdf colapsa todo eso en una sola llamada:",[27,28,33],"pre",{"className":29,"code":30,"language":31,"meta":32,"style":32},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","c.Table(header, rows,\n    template.ColumnWidths(40, 15, 20, 25),\n    template.TableHeaderStyle(template.TextColor(pdf.White), template.BgColor(brand)),\n    template.TableStripe(pdf.RGBHex(0xF5F5F5)),\n)\n","go","",[34,35,36,68,103,152,178],"code",{"__ignoreMap":32},[37,38,41,45,49,53,56,59,62,65],"span",{"class":39,"line":40},"line",1,[37,42,44],{"class":43},"sTEyZ","c",[37,46,48],{"class":47},"sMK4o",".",[37,50,52],{"class":51},"s2Zo4","Table",[37,54,55],{"class":47},"(",[37,57,58],{"class":43},"header",[37,60,61],{"class":47},",",[37,63,64],{"class":43}," rows",[37,66,67],{"class":47},",\n",[37,69,71,74,76,79,81,85,87,90,92,95,97,100],{"class":39,"line":70},2,[37,72,73],{"class":43},"    template",[37,75,48],{"class":47},[37,77,78],{"class":51},"ColumnWidths",[37,80,55],{"class":47},[37,82,84],{"class":83},"sbssI","40",[37,86,61],{"class":47},[37,88,89],{"class":83}," 15",[37,91,61],{"class":47},[37,93,94],{"class":83}," 20",[37,96,61],{"class":47},[37,98,99],{"class":83}," 25",[37,101,102],{"class":47},"),\n",[37,104,106,108,110,113,115,118,120,123,125,128,130,133,136,139,141,144,146,149],{"class":39,"line":105},3,[37,107,73],{"class":43},[37,109,48],{"class":47},[37,111,112],{"class":51},"TableHeaderStyle",[37,114,55],{"class":47},[37,116,117],{"class":43},"template",[37,119,48],{"class":47},[37,121,122],{"class":51},"TextColor",[37,124,55],{"class":47},[37,126,127],{"class":43},"pdf",[37,129,48],{"class":47},[37,131,132],{"class":43},"White",[37,134,135],{"class":47},"),",[37,137,138],{"class":43}," template",[37,140,48],{"class":47},[37,142,143],{"class":51},"BgColor",[37,145,55],{"class":47},[37,147,148],{"class":43},"brand",[37,150,151],{"class":47},")),\n",[37,153,155,157,159,162,164,166,168,171,173,176],{"class":39,"line":154},4,[37,156,73],{"class":43},[37,158,48],{"class":47},[37,160,161],{"class":51},"TableStripe",[37,163,55],{"class":47},[37,165,127],{"class":43},[37,167,48],{"class":47},[37,169,170],{"class":51},"RGBHex",[37,172,55],{"class":47},[37,174,175],{"class":83},"0xF5F5F5",[37,177,151],{"class":47},[37,179,181],{"class":39,"line":180},5,[37,182,183],{"class":47},")\n",[19,185,186,187,190,191,194,195,198,199,202],{},"Eso resuelve anchos, rayas y ",[22,188,189],{},"repetición automática del encabezado en cada salto de página",". Sin bucle de filas. Sin opción ",[34,192,193],{},"PageBreak",". El motor de layout detecta cuando la tabla no entra y reemite el slice ",[34,196,197],{},"Header"," arriba de la siguiente página. Para colspan, rowspan o un footer que también se repita, bajas un nivel a ",[34,200,201],{},"document.Table"," — los mismos bloques con más control.",[19,204,205],{},"Este artículo explica por qué esos son los tres ejes que importan, qué hace gpdf con cada uno, y dónde la abstracción se detiene a propósito.",[14,207,209],{"id":208},"por-qué-este-artículo","Por qué este artículo",[19,211,212,219,220,223],{},[213,214,218],"a",{"href":215,"rel":216},"https://github.com/gpdf-dev/gpdf",[217],"nofollow","gpdf"," es una librería Go para generar PDFs. MIT, cero dependencias, una página renderiza en ~13 µs. La API de tablas es pequeña — ocho constructores ",[34,221,222],{},"TableOption"," — pero la presión de diseño sobre ella es enorme: la mayoría de los proyectos PDF en Go se atascan en las tablas.",[19,225,226],{},"Los tres puntos donde una tabla se rompe en el mundo de PDF en Go:",[228,229,230,245,251],"ol",{},[231,232,233,236,237,240,241,244],"li",{},[22,234,235],{},"Anchos de columna."," La web tiene CSS ",[34,238,239],{},"\u003Ccol>"," y ",[34,242,243],{},"colgroup",". PDF no tiene nada. O calculas cada ancho en puntos a mano, o aceptas lo que la librería te dé — normalmente partes iguales.",[231,246,247,250],{},[22,248,249],{},"Rayas zebra."," Quieres que cada fila alterna del cuerpo se tinte de gris para legibilidad. La mayoría de las librerías de bajo nivel te obliga a escribir el bucle y rastrear paridad — la fuente de la mitad de los bugs de renderizado de tablas.",[231,252,253,256,257,260],{},[22,254,255],{},"Saltos de página."," Un reporte de 200 filas no entra en una hoja A4. La librería tiene que (a) cortar el cuerpo en algún sitio razonable, (b) cerrar la página, (c) abrir una nueva, y (d) ",[22,258,259],{},"reemitir el header en la nueva página"," para que el lector sepa qué columna está mirando. Olvida cualquiera de estos y la tabla es inutilizable.",[19,262,263],{},"Este artículo recorre cómo gpdf resuelve cada uno y qué compromisos tiene el diseño. Si solo quieres recetas copy-paste, los enlaces al final apuntan a las recetas por opción. Esto es la versión larga para quien quiere saber si puede confiar en la API antes de comprometer un estado de cuenta mensual de diez mil filas.",[14,265,267],{"id":266},"la-forma-de-la-api","La forma de la API",[19,269,270],{},"Hay un único punto de entrada en la capa builder:",[27,272,274],{"className":29,"code":273,"language":31,"meta":32,"style":32},"func (c *ColBuilder) Table(header []string, rows [][]string, opts ...TableOption)\n",[34,275,276],{"__ignoreMap":32},[37,277,278,281,284,288,291,295,298,301,303,305,308,312,314,316,319,321,323,326,329,331],{"class":39,"line":40},[37,279,280],{"class":47},"func",[37,282,283],{"class":47}," (",[37,285,287],{"class":286},"sHdIc","c ",[37,289,290],{"class":47},"*",[37,292,294],{"class":293},"sBMFI","ColBuilder",[37,296,297],{"class":47},")",[37,299,300],{"class":51}," Table",[37,302,55],{"class":47},[37,304,58],{"class":286},[37,306,307],{"class":47}," []",[37,309,311],{"class":310},"spNyl","string",[37,313,61],{"class":47},[37,315,64],{"class":286},[37,317,318],{"class":47}," [][]",[37,320,311],{"class":310},[37,322,61],{"class":47},[37,324,325],{"class":286}," opts",[37,327,328],{"class":47}," ...",[37,330,222],{"class":293},[37,332,183],{"class":47},[19,334,335,336,339],{},"Header es un slice de strings, rows es un slice de slices de strings, y el variádico ",[34,337,338],{},"opts"," configura todo lo demás. Existen ocho constructores de opciones:",[341,342,343,356],"table",{},[344,345,346],"thead",{},[347,348,349,353],"tr",{},[350,351,352],"th",{},"Opción",[350,354,355],{},"Qué controla",[357,358,359,370,380,390,400,410,420,433],"tbody",{},[347,360,361,367],{},[362,363,364],"td",{},[34,365,366],{},"ColumnWidths(...float64)",[362,368,369],{},"Anchos por columna como porcentaje del Col padre",[347,371,372,377],{},[362,373,374],{},[34,375,376],{},"TableHeaderStyle(...TextOption)",[362,378,379],{},"Color de fondo y de texto del header",[347,381,382,387],{},[362,383,384],{},[34,385,386],{},"TableStripe(pdf.Color)",[362,388,389],{},"Color de fondo para filas alternas del cuerpo",[347,391,392,397],{},[362,393,394],{},[34,395,396],{},"TableCellVAlign(document.VerticalAlign)",[362,398,399],{},"Alineación vertical de celdas (top/middle/bottom)",[347,401,402,407],{},[362,403,404],{},[34,405,406],{},"WithTableBorder(BorderSpec)",[362,408,409],{},"Marco exterior de toda la tabla",[347,411,412,417],{},[362,413,414],{},[34,415,416],{},"WithTableCellBorder(BorderSpec)",[362,418,419],{},"Mismo borde alrededor de cada celda — la cuadrícula",[347,421,422,427],{},[362,423,424],{},[34,425,426],{},"WithTableBorderCollapse(bool)",[362,428,429,430],{},"Semántica de CSS ",[34,431,432],{},"border-collapse: collapse",[347,434,435,440],{},[362,436,437],{},[34,438,439],{},"WithTableBackground(pdf.Color)",[362,441,442],{},"Relleno detrás de toda la tabla",[19,444,445,446,448],{},"Esa es toda la superficie. Lo que se construye con el builder se construye con estos ocho. Cualquier cosa más allá — colspan, rowspan, footer, anchos fijos en pt — es una llamada a ",[34,447,201],{},". Llegamos ahí.",[14,450,452],{"id":451},"código-que-funciona-un-libro-mayor-de-seis-meses","Código que funciona: un libro mayor de seis meses",[19,454,455,456,459,460,463,464,48],{},"Programa completo y ejecutable. Guarda como ",[34,457,458],{},"main.go",", ejecuta ",[34,461,462],{},"go run .",", obtén ",[34,465,466],{},"ledger.pdf",[27,468,470],{"className":29,"code":469,"language":31,"meta":32,"style":32},"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    stripe := pdf.RGBHex(0xF5F5F5)\n    hairline := template.Border(\n        template.BorderWidth(document.Pt(0.5)),\n        template.BorderColor(pdf.Gray(0.85)),\n    )\n\n    header := []string{\"Fecha\", \"Factura #\", \"Cliente\", \"Importe\"}\n    rows := make([][]string, 0, 120)\n    for i := 1; i \u003C= 120; 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(\"Cliente #%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(\"Libro mayor S1 2026\", 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                template.TableStripe(stripe),\n                template.WithTableCellBorder(hairline),\n            )\n        })\n    })\n\n    data, err := doc.Generate()\n    if err != nil {\n        log.Fatal(err)\n    }\n    if err := os.WriteFile(\"ledger.pdf\", data, 0o644); err != nil {\n        log.Fatal(err)\n    }\n}\n",[34,471,472,480,486,495,506,515,525,530,540,550,560,570,575,580,594,614,636,673,679,684,706,726,743,770,796,801,806,861,889,923,949,1014,1047,1074,1113,1119,1125,1130,1149,1180,1215,1261,1287,1292,1311,1340,1351,1371,1386,1392,1408,1425,1431,1436,1442,1447,1469,1485,1503,1508,1554,1569,1574],{"__ignoreMap":32},[37,473,474,477],{"class":39,"line":40},[37,475,476],{"class":47},"package",[37,478,479],{"class":293}," main\n",[37,481,482],{"class":39,"line":70},[37,483,485],{"emptyLinePlaceholder":484},true,"\n",[37,487,488,492],{"class":39,"line":105},[37,489,491],{"class":490},"s7zQu","import",[37,493,494],{"class":47}," (\n",[37,496,497,500,503],{"class":39,"line":154},[37,498,499],{"class":47},"    \"",[37,501,502],{"class":293},"fmt",[37,504,505],{"class":47},"\"\n",[37,507,508,510,513],{"class":39,"line":180},[37,509,499],{"class":47},[37,511,512],{"class":293},"log",[37,514,505],{"class":47},[37,516,518,520,523],{"class":39,"line":517},6,[37,519,499],{"class":47},[37,521,522],{"class":293},"os",[37,524,505],{"class":47},[37,526,528],{"class":39,"line":527},7,[37,529,485],{"emptyLinePlaceholder":484},[37,531,533,535,538],{"class":39,"line":532},8,[37,534,499],{"class":47},[37,536,537],{"class":293},"github.com/gpdf-dev/gpdf",[37,539,505],{"class":47},[37,541,543,545,548],{"class":39,"line":542},9,[37,544,499],{"class":47},[37,546,547],{"class":293},"github.com/gpdf-dev/gpdf/document",[37,549,505],{"class":47},[37,551,553,555,558],{"class":39,"line":552},10,[37,554,499],{"class":47},[37,556,557],{"class":293},"github.com/gpdf-dev/gpdf/pdf",[37,559,505],{"class":47},[37,561,563,565,568],{"class":39,"line":562},11,[37,564,499],{"class":47},[37,566,567],{"class":293},"github.com/gpdf-dev/gpdf/template",[37,569,505],{"class":47},[37,571,573],{"class":39,"line":572},12,[37,574,183],{"class":47},[37,576,578],{"class":39,"line":577},13,[37,579,485],{"emptyLinePlaceholder":484},[37,581,583,585,588,591],{"class":39,"line":582},14,[37,584,280],{"class":47},[37,586,587],{"class":51}," main",[37,589,590],{"class":47},"()",[37,592,593],{"class":47}," {\n",[37,595,597,600,603,606,608,611],{"class":39,"line":596},15,[37,598,599],{"class":43},"    doc ",[37,601,602],{"class":47},":=",[37,604,605],{"class":43}," gpdf",[37,607,48],{"class":47},[37,609,610],{"class":51},"NewDocument",[37,612,613],{"class":47},"(\n",[37,615,617,620,622,625,627,629,631,634],{"class":39,"line":616},16,[37,618,619],{"class":43},"        gpdf",[37,621,48],{"class":47},[37,623,624],{"class":51},"WithPageSize",[37,626,55],{"class":47},[37,628,218],{"class":43},[37,630,48],{"class":47},[37,632,633],{"class":43},"A4",[37,635,102],{"class":47},[37,637,639,641,643,646,648,651,653,656,658,660,662,665,667,670],{"class":39,"line":638},17,[37,640,619],{"class":43},[37,642,48],{"class":47},[37,644,645],{"class":51},"WithMargins",[37,647,55],{"class":47},[37,649,650],{"class":43},"document",[37,652,48],{"class":47},[37,654,655],{"class":51},"UniformEdges",[37,657,55],{"class":47},[37,659,650],{"class":43},[37,661,48],{"class":47},[37,663,664],{"class":51},"Mm",[37,666,55],{"class":47},[37,668,669],{"class":83},"20",[37,671,672],{"class":47},"))),\n",[37,674,676],{"class":39,"line":675},18,[37,677,678],{"class":47},"    )\n",[37,680,682],{"class":39,"line":681},19,[37,683,485],{"emptyLinePlaceholder":484},[37,685,687,690,692,695,697,699,701,704],{"class":39,"line":686},20,[37,688,689],{"class":43},"    brand ",[37,691,602],{"class":47},[37,693,694],{"class":43}," pdf",[37,696,48],{"class":47},[37,698,170],{"class":51},[37,700,55],{"class":47},[37,702,703],{"class":83},"0x1A237E",[37,705,183],{"class":47},[37,707,709,712,714,716,718,720,722,724],{"class":39,"line":708},21,[37,710,711],{"class":43},"    stripe ",[37,713,602],{"class":47},[37,715,694],{"class":43},[37,717,48],{"class":47},[37,719,170],{"class":51},[37,721,55],{"class":47},[37,723,175],{"class":83},[37,725,183],{"class":47},[37,727,729,732,734,736,738,741],{"class":39,"line":728},22,[37,730,731],{"class":43},"    hairline ",[37,733,602],{"class":47},[37,735,138],{"class":43},[37,737,48],{"class":47},[37,739,740],{"class":51},"Border",[37,742,613],{"class":47},[37,744,746,749,751,754,756,758,760,763,765,768],{"class":39,"line":745},23,[37,747,748],{"class":43},"        template",[37,750,48],{"class":47},[37,752,753],{"class":51},"BorderWidth",[37,755,55],{"class":47},[37,757,650],{"class":43},[37,759,48],{"class":47},[37,761,762],{"class":51},"Pt",[37,764,55],{"class":47},[37,766,767],{"class":83},"0.5",[37,769,151],{"class":47},[37,771,773,775,777,780,782,784,786,789,791,794],{"class":39,"line":772},24,[37,774,748],{"class":43},[37,776,48],{"class":47},[37,778,779],{"class":51},"BorderColor",[37,781,55],{"class":47},[37,783,127],{"class":43},[37,785,48],{"class":47},[37,787,788],{"class":51},"Gray",[37,790,55],{"class":47},[37,792,793],{"class":83},"0.85",[37,795,151],{"class":47},[37,797,799],{"class":39,"line":798},25,[37,800,678],{"class":47},[37,802,804],{"class":39,"line":803},26,[37,805,485],{"emptyLinePlaceholder":484},[37,807,809,812,814,816,818,821,824,828,830,832,835,838,840,842,844,847,849,851,853,856,858],{"class":39,"line":808},27,[37,810,811],{"class":43},"    header ",[37,813,602],{"class":47},[37,815,307],{"class":47},[37,817,311],{"class":310},[37,819,820],{"class":47},"{",[37,822,823],{"class":47},"\"",[37,825,827],{"class":826},"sfazB","Fecha",[37,829,823],{"class":47},[37,831,61],{"class":47},[37,833,834],{"class":47}," \"",[37,836,837],{"class":826},"Factura #",[37,839,823],{"class":47},[37,841,61],{"class":47},[37,843,834],{"class":47},[37,845,846],{"class":826},"Cliente",[37,848,823],{"class":47},[37,850,61],{"class":47},[37,852,834],{"class":47},[37,854,855],{"class":826},"Importe",[37,857,823],{"class":47},[37,859,860],{"class":47},"}\n",[37,862,864,867,869,872,875,877,879,882,884,887],{"class":39,"line":863},28,[37,865,866],{"class":43},"    rows ",[37,868,602],{"class":47},[37,870,871],{"class":51}," make",[37,873,874],{"class":47},"([][]",[37,876,311],{"class":310},[37,878,61],{"class":47},[37,880,881],{"class":83}," 0",[37,883,61],{"class":47},[37,885,886],{"class":83}," 120",[37,888,183],{"class":47},[37,890,892,895,898,900,903,906,908,911,913,915,918,921],{"class":39,"line":891},29,[37,893,894],{"class":490},"    for",[37,896,897],{"class":43}," i ",[37,899,602],{"class":47},[37,901,902],{"class":83}," 1",[37,904,905],{"class":47},";",[37,907,897],{"class":43},[37,909,910],{"class":47},"\u003C=",[37,912,886],{"class":83},[37,914,905],{"class":47},[37,916,917],{"class":43}," i",[37,919,920],{"class":47},"++",[37,922,593],{"class":47},[37,924,926,929,932,935,937,940,942,944,946],{"class":39,"line":925},30,[37,927,928],{"class":43},"        rows ",[37,930,931],{"class":47},"=",[37,933,934],{"class":51}," append",[37,936,55],{"class":47},[37,938,939],{"class":43},"rows",[37,941,61],{"class":47},[37,943,307],{"class":47},[37,945,311],{"class":310},[37,947,948],{"class":47},"{\n",[37,950,952,955,957,960,962,964,967,971,974,976,978,980,982,985,988,991,994,997,999,1001,1003,1005,1008,1010,1012],{"class":39,"line":951},31,[37,953,954],{"class":43},"            fmt",[37,956,48],{"class":47},[37,958,959],{"class":51},"Sprintf",[37,961,55],{"class":47},[37,963,823],{"class":47},[37,965,966],{"class":826},"2026-",[37,968,970],{"class":969},"swJcz","%02d",[37,972,973],{"class":826},"-",[37,975,970],{"class":969},[37,977,823],{"class":47},[37,979,61],{"class":47},[37,981,283],{"class":47},[37,983,984],{"class":43},"i",[37,986,987],{"class":47},"%",[37,989,990],{"class":83},"6",[37,992,993],{"class":47},")+",[37,995,996],{"class":83},"1",[37,998,61],{"class":47},[37,1000,283],{"class":47},[37,1002,984],{"class":43},[37,1004,987],{"class":47},[37,1006,1007],{"class":83},"28",[37,1009,993],{"class":47},[37,1011,996],{"class":83},[37,1013,102],{"class":47},[37,1015,1017,1019,1021,1023,1025,1027,1030,1033,1035,1037,1040,1043,1045],{"class":39,"line":1016},32,[37,1018,954],{"class":43},[37,1020,48],{"class":47},[37,1022,959],{"class":51},[37,1024,55],{"class":47},[37,1026,823],{"class":47},[37,1028,1029],{"class":826},"INV-",[37,1031,1032],{"class":969},"%05d",[37,1034,823],{"class":47},[37,1036,61],{"class":47},[37,1038,1039],{"class":83}," 10000",[37,1041,1042],{"class":47},"+",[37,1044,984],{"class":43},[37,1046,102],{"class":47},[37,1048,1050,1052,1054,1056,1058,1060,1063,1066,1068,1070,1072],{"class":39,"line":1049},33,[37,1051,954],{"class":43},[37,1053,48],{"class":47},[37,1055,959],{"class":51},[37,1057,55],{"class":47},[37,1059,823],{"class":47},[37,1061,1062],{"class":826},"Cliente #",[37,1064,1065],{"class":969},"%d",[37,1067,823],{"class":47},[37,1069,61],{"class":47},[37,1071,917],{"class":43},[37,1073,102],{"class":47},[37,1075,1077,1079,1081,1083,1085,1087,1090,1092,1095,1097,1099,1102,1104,1106,1108,1111],{"class":39,"line":1076},34,[37,1078,954],{"class":43},[37,1080,48],{"class":47},[37,1082,959],{"class":51},[37,1084,55],{"class":47},[37,1086,823],{"class":47},[37,1088,1089],{"class":826},"€",[37,1091,1065],{"class":969},[37,1093,1094],{"class":826},".00",[37,1096,823],{"class":47},[37,1098,61],{"class":47},[37,1100,1101],{"class":83}," 100",[37,1103,1042],{"class":47},[37,1105,984],{"class":43},[37,1107,290],{"class":47},[37,1109,1110],{"class":83},"7",[37,1112,102],{"class":47},[37,1114,1116],{"class":39,"line":1115},35,[37,1117,1118],{"class":47},"        })\n",[37,1120,1122],{"class":39,"line":1121},36,[37,1123,1124],{"class":47},"    }\n",[37,1126,1128],{"class":39,"line":1127},37,[37,1129,485],{"emptyLinePlaceholder":484},[37,1131,1133,1136,1138,1141,1143,1146],{"class":39,"line":1132},38,[37,1134,1135],{"class":43},"    page ",[37,1137,602],{"class":47},[37,1139,1140],{"class":43}," doc",[37,1142,48],{"class":47},[37,1144,1145],{"class":51},"AddPage",[37,1147,1148],{"class":47},"()\n",[37,1150,1152,1155,1157,1160,1163,1166,1169,1171,1173,1176,1178],{"class":39,"line":1151},39,[37,1153,1154],{"class":43},"    page",[37,1156,48],{"class":47},[37,1158,1159],{"class":51},"AutoRow",[37,1161,1162],{"class":47},"(func(",[37,1164,1165],{"class":286},"r",[37,1167,1168],{"class":47}," *",[37,1170,117],{"class":293},[37,1172,48],{"class":47},[37,1174,1175],{"class":293},"RowBuilder",[37,1177,297],{"class":47},[37,1179,593],{"class":47},[37,1181,1183,1186,1188,1191,1193,1196,1198,1201,1203,1205,1207,1209,1211,1213],{"class":39,"line":1182},40,[37,1184,1185],{"class":43},"        r",[37,1187,48],{"class":47},[37,1189,1190],{"class":51},"Col",[37,1192,55],{"class":47},[37,1194,1195],{"class":83},"12",[37,1197,61],{"class":47},[37,1199,1200],{"class":47}," func(",[37,1202,44],{"class":286},[37,1204,1168],{"class":47},[37,1206,117],{"class":293},[37,1208,48],{"class":47},[37,1210,294],{"class":293},[37,1212,297],{"class":47},[37,1214,593],{"class":47},[37,1216,1218,1221,1223,1226,1228,1230,1233,1235,1237,1239,1241,1244,1246,1249,1251,1253,1255,1258],{"class":39,"line":1217},41,[37,1219,1220],{"class":43},"            c",[37,1222,48],{"class":47},[37,1224,1225],{"class":51},"Text",[37,1227,55],{"class":47},[37,1229,823],{"class":47},[37,1231,1232],{"class":826},"Libro mayor S1 2026",[37,1234,823],{"class":47},[37,1236,61],{"class":47},[37,1238,138],{"class":43},[37,1240,48],{"class":47},[37,1242,1243],{"class":51},"FontSize",[37,1245,55],{"class":47},[37,1247,1248],{"class":83},"18",[37,1250,135],{"class":47},[37,1252,138],{"class":43},[37,1254,48],{"class":47},[37,1256,1257],{"class":51},"Bold",[37,1259,1260],{"class":47},"())\n",[37,1262,1264,1266,1268,1271,1273,1275,1277,1279,1281,1284],{"class":39,"line":1263},42,[37,1265,1220],{"class":43},[37,1267,48],{"class":47},[37,1269,1270],{"class":51},"Spacer",[37,1272,55],{"class":47},[37,1274,650],{"class":43},[37,1276,48],{"class":47},[37,1278,664],{"class":51},[37,1280,55],{"class":47},[37,1282,1283],{"class":83},"4",[37,1285,1286],{"class":47},"))\n",[37,1288,1290],{"class":39,"line":1289},43,[37,1291,485],{"emptyLinePlaceholder":484},[37,1293,1295,1297,1299,1301,1303,1305,1307,1309],{"class":39,"line":1294},44,[37,1296,1220],{"class":43},[37,1298,48],{"class":47},[37,1300,52],{"class":51},[37,1302,55],{"class":47},[37,1304,58],{"class":43},[37,1306,61],{"class":47},[37,1308,64],{"class":43},[37,1310,67],{"class":47},[37,1312,1314,1317,1319,1321,1323,1325,1327,1329,1331,1334,1336,1338],{"class":39,"line":1313},45,[37,1315,1316],{"class":43},"                template",[37,1318,48],{"class":47},[37,1320,78],{"class":51},[37,1322,55],{"class":47},[37,1324,669],{"class":83},[37,1326,61],{"class":47},[37,1328,94],{"class":83},[37,1330,61],{"class":47},[37,1332,1333],{"class":83}," 40",[37,1335,61],{"class":47},[37,1337,94],{"class":83},[37,1339,102],{"class":47},[37,1341,1343,1345,1347,1349],{"class":39,"line":1342},46,[37,1344,1316],{"class":43},[37,1346,48],{"class":47},[37,1348,112],{"class":51},[37,1350,613],{"class":47},[37,1352,1354,1357,1359,1361,1363,1365,1367,1369],{"class":39,"line":1353},47,[37,1355,1356],{"class":43},"                    template",[37,1358,48],{"class":47},[37,1360,122],{"class":51},[37,1362,55],{"class":47},[37,1364,127],{"class":43},[37,1366,48],{"class":47},[37,1368,132],{"class":43},[37,1370,102],{"class":47},[37,1372,1374,1376,1378,1380,1382,1384],{"class":39,"line":1373},48,[37,1375,1356],{"class":43},[37,1377,48],{"class":47},[37,1379,143],{"class":51},[37,1381,55],{"class":47},[37,1383,148],{"class":43},[37,1385,102],{"class":47},[37,1387,1389],{"class":39,"line":1388},49,[37,1390,1391],{"class":47},"                ),\n",[37,1393,1395,1397,1399,1401,1403,1406],{"class":39,"line":1394},50,[37,1396,1316],{"class":43},[37,1398,48],{"class":47},[37,1400,161],{"class":51},[37,1402,55],{"class":47},[37,1404,1405],{"class":43},"stripe",[37,1407,102],{"class":47},[37,1409,1411,1413,1415,1418,1420,1423],{"class":39,"line":1410},51,[37,1412,1316],{"class":43},[37,1414,48],{"class":47},[37,1416,1417],{"class":51},"WithTableCellBorder",[37,1419,55],{"class":47},[37,1421,1422],{"class":43},"hairline",[37,1424,102],{"class":47},[37,1426,1428],{"class":39,"line":1427},52,[37,1429,1430],{"class":47},"            )\n",[37,1432,1434],{"class":39,"line":1433},53,[37,1435,1118],{"class":47},[37,1437,1439],{"class":39,"line":1438},54,[37,1440,1441],{"class":47},"    })\n",[37,1443,1445],{"class":39,"line":1444},55,[37,1446,485],{"emptyLinePlaceholder":484},[37,1448,1450,1453,1455,1458,1460,1462,1464,1467],{"class":39,"line":1449},56,[37,1451,1452],{"class":43},"    data",[37,1454,61],{"class":47},[37,1456,1457],{"class":43}," err ",[37,1459,602],{"class":47},[37,1461,1140],{"class":43},[37,1463,48],{"class":47},[37,1465,1466],{"class":51},"Generate",[37,1468,1148],{"class":47},[37,1470,1472,1475,1477,1480,1483],{"class":39,"line":1471},57,[37,1473,1474],{"class":490},"    if",[37,1476,1457],{"class":43},[37,1478,1479],{"class":47},"!=",[37,1481,1482],{"class":47}," nil",[37,1484,593],{"class":47},[37,1486,1488,1491,1493,1496,1498,1501],{"class":39,"line":1487},58,[37,1489,1490],{"class":43},"        log",[37,1492,48],{"class":47},[37,1494,1495],{"class":51},"Fatal",[37,1497,55],{"class":47},[37,1499,1500],{"class":43},"err",[37,1502,183],{"class":47},[37,1504,1506],{"class":39,"line":1505},59,[37,1507,1124],{"class":47},[37,1509,1511,1513,1515,1517,1520,1522,1525,1527,1529,1531,1533,1535,1538,1540,1543,1546,1548,1550,1552],{"class":39,"line":1510},60,[37,1512,1474],{"class":490},[37,1514,1457],{"class":43},[37,1516,602],{"class":47},[37,1518,1519],{"class":43}," os",[37,1521,48],{"class":47},[37,1523,1524],{"class":51},"WriteFile",[37,1526,55],{"class":47},[37,1528,823],{"class":47},[37,1530,466],{"class":826},[37,1532,823],{"class":47},[37,1534,61],{"class":47},[37,1536,1537],{"class":43}," data",[37,1539,61],{"class":47},[37,1541,1542],{"class":83}," 0o644",[37,1544,1545],{"class":47},");",[37,1547,1457],{"class":43},[37,1549,1479],{"class":47},[37,1551,1482],{"class":47},[37,1553,593],{"class":47},[37,1555,1557,1559,1561,1563,1565,1567],{"class":39,"line":1556},61,[37,1558,1490],{"class":43},[37,1560,48],{"class":47},[37,1562,1495],{"class":51},[37,1564,55],{"class":47},[37,1566,1500],{"class":43},[37,1568,183],{"class":47},[37,1570,1572],{"class":39,"line":1571},62,[37,1573,1124],{"class":47},[37,1575,1577],{"class":39,"line":1576},63,[37,1578,860],{"class":47},[19,1580,1581],{},"120 filas en A4 ocupan unas cinco páginas. En cada página el header azul oscuro reaparece arriba, el cuerpo continúa donde se cortó, las rayas grises alternas mantienen la consistencia entre saltos. No tienes que tocar nada de eso.",[19,1583,1584,1585,1589,1590,1593,1594,1597],{},"Lo que hay que mirar de este snippet es lo que ",[1586,1587,1588],"em",{},"no"," tiene: no hay bucle de filas, ni contador de página, ni ",[34,1591,1592],{},"if i == lastRowOnPage"," manual, ni ",[34,1595,1596],{},"PageBreak()",", ni reemisión de header. Las cuatro líneas de opciones declaran cómo se ve la tabla; el motor decide cuándo y dónde cortar.",[14,1599,1601],{"id":1600},"anchos-de-columna-de-qué-son-porcentajes","Anchos de columna: de qué son porcentajes",[19,1603,1604,1607,1608,1611],{},[34,1605,1606],{},"ColumnWidths(40, 15, 20, 25)"," se parece a CSS ",[34,1609,1610],{},"\u003Ccol width=\"40%\">",". Casi. Con tres bordes filosos.",[19,1613,1614,1617,1618,1621,1622,1625,1626,1629],{},[22,1615,1616],{},"El porcentaje es del Col padre, no de la página."," Un ",[34,1619,1620],{},"r.Col(6, ...)"," ocupa la mitad del ancho de contenido de la fila. Una tabla dentro con ",[34,1623,1624],{},"ColumnWidths(50, 50)"," produce dos columnas al ",[22,1627,1628],{},"25% del ancho de la fila",", no 50%. Los porcentajes son locales al sitio donde vive la tabla. Si mueves una tabla de una fila a ancho completo a un layout en paralelo, la llamada a la opción no cambia.",[19,1631,1632,1635],{},[22,1633,1634],{},"Sin normalización."," Si tus anchos suman 90, queda 10% de espacio vacío a la derecha. Si suman 110, la columna más derecha desborda al padre y se mete en la página. gpdf confía en tu aritmética. Sin warning — y no debería: corregir automáticamente lo que escribiste es peor que el bug.",[19,1637,1638,1641],{},[22,1639,1640],{},"Los faltantes al final se autodistribuyen."," Pasar menos anchos que columnas hace que las columnas restantes compartan el resto en partes iguales:",[27,1643,1645],{"className":29,"code":1644,"language":31,"meta":32,"style":32},"// Tabla de cinco columnas, tres anchos dados.\ntemplate.ColumnWidths(40, 10, 20)\n// → 40% / 10% / 20% / 15% / 15%   (30% repartido entre las dos finales)\n",[34,1646,1647,1653,1676],{"__ignoreMap":32},[37,1648,1649],{"class":39,"line":40},[37,1650,1652],{"class":1651},"sHwdD","// Tabla de cinco columnas, tres anchos dados.\n",[37,1654,1655,1657,1659,1661,1663,1665,1667,1670,1672,1674],{"class":39,"line":70},[37,1656,117],{"class":43},[37,1658,48],{"class":47},[37,1660,78],{"class":51},[37,1662,55],{"class":47},[37,1664,84],{"class":83},[37,1666,61],{"class":47},[37,1668,1669],{"class":83}," 10",[37,1671,61],{"class":47},[37,1673,94],{"class":83},[37,1675,183],{"class":47},[37,1677,1678],{"class":39,"line":105},[37,1679,1680],{"class":1651},"// → 40% / 10% / 20% / 15% / 15%   (30% repartido entre las dos finales)\n",[19,1682,1683,1684,1687],{},"Truco útil para \"me importan estos anchos específicos; el resto que se acomode\". Pasar ",[34,1685,1686],{},"0"," explícito también marca la columna como auto:",[27,1689,1691],{"className":29,"code":1690,"language":31,"meta":32,"style":32},"template.ColumnWidths(0, 30, 30) // → 40% / 30% / 30% en una tabla de 3 columnas\n",[34,1692,1693],{"__ignoreMap":32},[37,1694,1695,1697,1699,1701,1703,1705,1707,1710,1712,1714,1716],{"class":39,"line":40},[37,1696,117],{"class":43},[37,1698,48],{"class":47},[37,1700,78],{"class":51},[37,1702,55],{"class":47},[37,1704,1686],{"class":83},[37,1706,61],{"class":47},[37,1708,1709],{"class":83}," 30",[37,1711,61],{"class":47},[37,1713,1709],{"class":83},[37,1715,297],{"class":47},[37,1717,1718],{"class":1651}," // → 40% / 30% / 30% en una tabla de 3 columnas\n",[19,1720,1721,1722,1726],{},"Para los detalles de las esquinas, ver la ",[213,1723,1725],{"href":1724},"/es/blog/table-column-widths","receta de anchos de columna",". Resumen: los porcentajes cubren el 95% de los layouts, y cuando no, bajas una capa. Descrito más adelante.",[14,1728,1730],{"id":1729},"rayas-el-bucle-de-filas-que-no-escribes","Rayas: el bucle de filas que no escribes",[27,1732,1734],{"className":29,"code":1733,"language":31,"meta":32,"style":32},"template.TableStripe(pdf.RGBHex(0xF5F5F5))\n",[34,1735,1736],{"__ignoreMap":32},[37,1737,1738,1740,1742,1744,1746,1748,1750,1752,1754,1756],{"class":39,"line":40},[37,1739,117],{"class":43},[37,1741,48],{"class":47},[37,1743,161],{"class":51},[37,1745,55],{"class":47},[37,1747,127],{"class":43},[37,1749,48],{"class":47},[37,1751,170],{"class":51},[37,1753,55],{"class":47},[37,1755,175],{"class":83},[37,1757,1286],{"class":47},[19,1759,1760,1761,1763,1764,1767],{},"Eso es todo. gpdf recorre las filas del cuerpo con un índice ",[34,1762,984],{}," desde 0 y tinta las que cumplen ",[34,1765,1766],{},"i % 2 == 1",". El header es su propio slice y no cuenta, así que la primera fila del cuerpo queda limpia y la segunda con sombra — convención Bootstrap.",[19,1769,1770,1771,240,1774,1777,1778,1781,1782,1785],{},"Por qué existe la opción: en ",[34,1772,1773],{},"gofpdf",[34,1775,1776],{},"gopdf"," escribes el bucle, llamas ",[34,1779,1780],{},"SetFillColor"," por fila e invocas ",[34,1783,1784],{},"CellFormat"," con el flag de relleno. Son ocho o diez líneas y la tasa de off-by-one es lo bastante alta para tener un set propio de respuestas en StackOverflow. Meterlo en una sola opción hace desaparecer la clase de bug.",[19,1787,1788],{},"Las restricciones son deliberadas:",[1790,1791,1792,1798,1804],"ul",{},[231,1793,1794,1797],{},[22,1795,1796],{},"Un solo color de raya, no dos."," Sin \"alternar entre azul y gris\". La página ya es blanca, así que la fila sin raya es automáticamente blanca. Pedir un ciclo de tres colores es pedirle al lector pensar más, y las rayas zebra son para lo opuesto.",[231,1799,1800,1803],{},[22,1801,1802],{},"No hay forma de invertir la paridad."," La primera fila del cuerpo siempre limpia, la segunda siempre sombreada. Si realmente lo quieres invertido, pon una fila vacía al inicio. Pero nadie quiere eso de verdad.",[231,1805,1806,1809],{},[22,1807,1808],{},"Las rayas cruzan saltos de página correctamente."," La fila 14 sigue siendo paridad-14 cuando aterriza en la página 2. El motor lleva el índice a través del corte.",[19,1811,1812,1813,1817,1818,1821],{},"Para elección de color y variantes en tema oscuro, la ",[213,1814,1816],{"href":1815},"/es/blog/zebra-striped-table-rows","receta de rayas zebra"," tiene la discusión de paleta. Para este post, el punto es que una propiedad de la ",[1586,1819,1820],{},"tabla"," (la alternancia) se configura al nivel de la llamada de tabla, no por fila.",[14,1823,1825],{"id":1824},"saltos-de-página-la-parte-que-de-verdad-cuesta","Saltos de página: la parte que de verdad cuesta",[19,1827,1828],{},"Aquí es donde la mayoría de las historias de PDF en Go se caen, y donde el diseño de gpdf rinde más.",[19,1830,1831,1832,1838],{},"Versión simple: ",[22,1833,1834,1835,1837],{},"escribe una tabla con más filas de las que entran en una página y gpdf la pagina por ti. El slice ",[34,1836,197],{}," se repite arriba de cada página de continuación."," Ninguna opción para activarlo. Ningún método que llamar. Es el comportamiento por defecto del motor.",[19,1840,1841,1842,1845,1846,1849,1850,1853,1854,1856,1857,1860,1861,1864],{},"Versión real, más interesante. El motor de layout (",[34,1843,1844],{},"document/layout/block.go",") maquina la tabla con la altura disponible. Cuando el cuerpo no entra, el resultado incluye un campo ",[34,1847,1848],{},"Overflow"," — un nuevo ",[34,1851,1852],{},"*document.Table"," con el mismo ",[34,1855,197],{},", el mismo ",[34,1858,1859],{},"Footer"," y las filas ",[1586,1862,1863],{},"restantes",". El sistema de página vuelca lo que entró a la página actual, abre la siguiente y mete la tabla overflow de vuelta al motor con la nueva altura disponible. Repite hasta que el overflow esté vacío.",[19,1866,1867],{},"Dos consecuencias del diseño:",[228,1869,1870,1883],{},[231,1871,1872,1879,1880,1882],{},[22,1873,1874,1875,1878],{},"El header vive en ",[34,1876,1877],{},"tbl.Header",", no en el bucle."," Como la tabla overflow reusa el mismo slice ",[34,1881,197],{},", el header se repite automáticamente en cada página de continuación. Mismo estilo, mismos anchos, todo igual.",[231,1884,1885,1888],{},[22,1886,1887],{},"No hay caso límite \"el header no entra en esta página\"."," El motor reserva el espacio del header antes de medir cuántas filas del cuerpo entran. Si la página no aguanta el header más al menos una fila, la tabla entera pasa a la siguiente página.",[19,1890,1891],{},"Footers — cuando los usas en la capa documento — funcionan igual: se llevan en cada página de continuación automáticamente.",[19,1893,1894,1895,1898],{},"Lo que no obtienes: una anotación \"mantén este grupo de filas junto\", supresión de salto en una fila específica o \"empieza esta tabla en una página nueva\". Las primeras dos son TODO. La tercera la haces a nivel página — ",[34,1896,1897],{},"doc.AddPage()"," antes de la fila que contiene la tabla.",[14,1900,1902],{"id":1901},"cuando-se-te-queda-chica-la-api-builder","Cuando se te queda chica la API builder",[19,1904,1905,1906,48],{},"El builder es bueno para los casos comunes. Cuando necesitas combinación de celdas, anchos en pt fijos, un footer que se repita o cualquier cosa que mezcle tipos de contenido por celda, bajas a ",[34,1907,201],{},[27,1909,1911],{"className":29,"code":1910,"language":31,"meta":32,"style":32},"import (\n    \"github.com/gpdf-dev/gpdf/document\"\n)\n\nfooter := document.TableRow{\n    Cells: []document.TableCell{\n        {\n            Content: []document.DocumentNode{\n                &document.Text{Content: \"Total\", TextStyle: document.DefaultStyle()},\n            },\n            ColSpan: 3, // ← combina las tres primeras columnas\n            RowSpan: 1,\n        },\n        {\n            Content: []document.DocumentNode{\n                &document.Text{Content: \"€48,720.00\", TextStyle: document.DefaultStyle()},\n            },\n            ColSpan: 1,\n            RowSpan: 1,\n        },\n    },\n}\n\ntbl := &document.Table{\n    Columns: []document.TableColumn{\n        {Width: document.Pct(20)},\n        {Width: document.Pct(20)},\n        {Width: document.Auto},\n        {Width: document.Pt(80)}, // 80pt fijos sin importar el ancho de página\n    },\n    Header: /* ... */,\n    Body:   /* ... */,\n    Footer: []document.TableRow{footer},\n}\n",[34,1912,1913,1919,1927,1931,1935,1952,1971,1976,1994,2036,2041,2056,2067,2072,2076,2092,2129,2133,2143,2153,2157,2162,2166,2170,2188,2206,2230,2250,2268,2293,2297,2309,2321,2343],{"__ignoreMap":32},[37,1914,1915,1917],{"class":39,"line":40},[37,1916,491],{"class":490},[37,1918,494],{"class":47},[37,1920,1921,1923,1925],{"class":39,"line":70},[37,1922,499],{"class":47},[37,1924,547],{"class":293},[37,1926,505],{"class":47},[37,1928,1929],{"class":39,"line":105},[37,1930,183],{"class":47},[37,1932,1933],{"class":39,"line":154},[37,1934,485],{"emptyLinePlaceholder":484},[37,1936,1937,1940,1942,1945,1947,1950],{"class":39,"line":180},[37,1938,1939],{"class":43},"footer ",[37,1941,602],{"class":47},[37,1943,1944],{"class":293}," document",[37,1946,48],{"class":47},[37,1948,1949],{"class":293},"TableRow",[37,1951,948],{"class":47},[37,1953,1954,1957,1960,1962,1964,1966,1969],{"class":39,"line":517},[37,1955,1956],{"class":43},"    Cells",[37,1958,1959],{"class":47},":",[37,1961,307],{"class":47},[37,1963,650],{"class":293},[37,1965,48],{"class":47},[37,1967,1968],{"class":293},"TableCell",[37,1970,948],{"class":47},[37,1972,1973],{"class":39,"line":527},[37,1974,1975],{"class":47},"        {\n",[37,1977,1978,1981,1983,1985,1987,1989,1992],{"class":39,"line":532},[37,1979,1980],{"class":43},"            Content",[37,1982,1959],{"class":47},[37,1984,307],{"class":47},[37,1986,650],{"class":293},[37,1988,48],{"class":47},[37,1990,1991],{"class":293},"DocumentNode",[37,1993,948],{"class":47},[37,1995,1996,1999,2001,2003,2005,2007,2010,2012,2014,2017,2019,2021,2024,2026,2028,2030,2033],{"class":39,"line":542},[37,1997,1998],{"class":47},"                &",[37,2000,650],{"class":293},[37,2002,48],{"class":47},[37,2004,1225],{"class":293},[37,2006,820],{"class":47},[37,2008,2009],{"class":43},"Content",[37,2011,1959],{"class":47},[37,2013,834],{"class":47},[37,2015,2016],{"class":826},"Total",[37,2018,823],{"class":47},[37,2020,61],{"class":47},[37,2022,2023],{"class":43}," TextStyle",[37,2025,1959],{"class":47},[37,2027,1944],{"class":43},[37,2029,48],{"class":47},[37,2031,2032],{"class":51},"DefaultStyle",[37,2034,2035],{"class":47},"()},\n",[37,2037,2038],{"class":39,"line":552},[37,2039,2040],{"class":47},"            },\n",[37,2042,2043,2046,2048,2051,2053],{"class":39,"line":562},[37,2044,2045],{"class":43},"            ColSpan",[37,2047,1959],{"class":47},[37,2049,2050],{"class":83}," 3",[37,2052,61],{"class":47},[37,2054,2055],{"class":1651}," // ← combina las tres primeras columnas\n",[37,2057,2058,2061,2063,2065],{"class":39,"line":572},[37,2059,2060],{"class":43},"            RowSpan",[37,2062,1959],{"class":47},[37,2064,902],{"class":83},[37,2066,67],{"class":47},[37,2068,2069],{"class":39,"line":577},[37,2070,2071],{"class":47},"        },\n",[37,2073,2074],{"class":39,"line":582},[37,2075,1975],{"class":47},[37,2077,2078,2080,2082,2084,2086,2088,2090],{"class":39,"line":596},[37,2079,1980],{"class":43},[37,2081,1959],{"class":47},[37,2083,307],{"class":47},[37,2085,650],{"class":293},[37,2087,48],{"class":47},[37,2089,1991],{"class":293},[37,2091,948],{"class":47},[37,2093,2094,2096,2098,2100,2102,2104,2106,2108,2110,2113,2115,2117,2119,2121,2123,2125,2127],{"class":39,"line":616},[37,2095,1998],{"class":47},[37,2097,650],{"class":293},[37,2099,48],{"class":47},[37,2101,1225],{"class":293},[37,2103,820],{"class":47},[37,2105,2009],{"class":43},[37,2107,1959],{"class":47},[37,2109,834],{"class":47},[37,2111,2112],{"class":826},"€48,720.00",[37,2114,823],{"class":47},[37,2116,61],{"class":47},[37,2118,2023],{"class":43},[37,2120,1959],{"class":47},[37,2122,1944],{"class":43},[37,2124,48],{"class":47},[37,2126,2032],{"class":51},[37,2128,2035],{"class":47},[37,2130,2131],{"class":39,"line":638},[37,2132,2040],{"class":47},[37,2134,2135,2137,2139,2141],{"class":39,"line":675},[37,2136,2045],{"class":43},[37,2138,1959],{"class":47},[37,2140,902],{"class":83},[37,2142,67],{"class":47},[37,2144,2145,2147,2149,2151],{"class":39,"line":681},[37,2146,2060],{"class":43},[37,2148,1959],{"class":47},[37,2150,902],{"class":83},[37,2152,67],{"class":47},[37,2154,2155],{"class":39,"line":686},[37,2156,2071],{"class":47},[37,2158,2159],{"class":39,"line":708},[37,2160,2161],{"class":47},"    },\n",[37,2163,2164],{"class":39,"line":728},[37,2165,860],{"class":47},[37,2167,2168],{"class":39,"line":745},[37,2169,485],{"emptyLinePlaceholder":484},[37,2171,2172,2175,2177,2180,2182,2184,2186],{"class":39,"line":772},[37,2173,2174],{"class":43},"tbl ",[37,2176,602],{"class":47},[37,2178,2179],{"class":47}," &",[37,2181,650],{"class":293},[37,2183,48],{"class":47},[37,2185,52],{"class":293},[37,2187,948],{"class":47},[37,2189,2190,2193,2195,2197,2199,2201,2204],{"class":39,"line":798},[37,2191,2192],{"class":43},"    Columns",[37,2194,1959],{"class":47},[37,2196,307],{"class":47},[37,2198,650],{"class":293},[37,2200,48],{"class":47},[37,2202,2203],{"class":293},"TableColumn",[37,2205,948],{"class":47},[37,2207,2208,2211,2214,2216,2218,2220,2223,2225,2227],{"class":39,"line":803},[37,2209,2210],{"class":47},"        {",[37,2212,2213],{"class":43},"Width",[37,2215,1959],{"class":47},[37,2217,1944],{"class":43},[37,2219,48],{"class":47},[37,2221,2222],{"class":51},"Pct",[37,2224,55],{"class":47},[37,2226,669],{"class":83},[37,2228,2229],{"class":47},")},\n",[37,2231,2232,2234,2236,2238,2240,2242,2244,2246,2248],{"class":39,"line":808},[37,2233,2210],{"class":47},[37,2235,2213],{"class":43},[37,2237,1959],{"class":47},[37,2239,1944],{"class":43},[37,2241,48],{"class":47},[37,2243,2222],{"class":51},[37,2245,55],{"class":47},[37,2247,669],{"class":83},[37,2249,2229],{"class":47},[37,2251,2252,2254,2256,2258,2260,2262,2265],{"class":39,"line":863},[37,2253,2210],{"class":47},[37,2255,2213],{"class":43},[37,2257,1959],{"class":47},[37,2259,1944],{"class":43},[37,2261,48],{"class":47},[37,2263,2264],{"class":43},"Auto",[37,2266,2267],{"class":47},"},\n",[37,2269,2270,2272,2274,2276,2278,2280,2282,2284,2287,2290],{"class":39,"line":891},[37,2271,2210],{"class":47},[37,2273,2213],{"class":43},[37,2275,1959],{"class":47},[37,2277,1944],{"class":43},[37,2279,48],{"class":47},[37,2281,762],{"class":51},[37,2283,55],{"class":47},[37,2285,2286],{"class":83},"80",[37,2288,2289],{"class":47},")},",[37,2291,2292],{"class":1651}," // 80pt fijos sin importar el ancho de página\n",[37,2294,2295],{"class":39,"line":925},[37,2296,2161],{"class":47},[37,2298,2299,2302,2304,2307],{"class":39,"line":951},[37,2300,2301],{"class":43},"    Header",[37,2303,1959],{"class":47},[37,2305,2306],{"class":1651}," /* ... */",[37,2308,67],{"class":47},[37,2310,2311,2314,2316,2319],{"class":39,"line":1016},[37,2312,2313],{"class":43},"    Body",[37,2315,1959],{"class":47},[37,2317,2318],{"class":1651},"   /* ... */",[37,2320,67],{"class":47},[37,2322,2323,2326,2328,2330,2332,2334,2336,2338,2341],{"class":39,"line":1049},[37,2324,2325],{"class":43},"    Footer",[37,2327,1959],{"class":47},[37,2329,307],{"class":47},[37,2331,650],{"class":293},[37,2333,48],{"class":47},[37,2335,1949],{"class":293},[37,2337,820],{"class":47},[37,2339,2340],{"class":43},"footer",[37,2342,2267],{"class":47},[37,2344,2345],{"class":39,"line":1076},[37,2346,860],{"class":47},[19,2348,2349,2350,2353,2354,2357,2358,2360,2361,2360,2363,2360,2366,2360,2369,2360,2372,2374,2375,2377,2378,2380,2381,2383],{},"Notar varias cosas. ",[34,2351,2352],{},"TableColumn.Width"," es un ",[34,2355,2356],{},"document.Value"," — ",[34,2359,762],{},", ",[34,2362,664],{},[34,2364,2365],{},"Cm",[34,2367,2368],{},"In",[34,2370,2371],{},"Em",[34,2373,2222],{}," o el especial ",[34,2376,2264],{},". Los puedes mezclar en una tabla. Las columnas ",[34,2379,2264],{}," comparten lo que queda después de restar las fijas y las en porcentaje. Más cerca del elemento ",[34,2382,239],{}," de CSS que del modelo solo-porcentaje del builder.",[19,2385,2386,240,2389,2392],{},[34,2387,2388],{},"TableCell.ColSpan",[34,2390,2391],{},"RowSpan"," son enteros, por defecto 1. El ejemplo es el footer clásico de factura: tres columnas del header se combinan para \"Total\" y la cuarta lleva la suma.",[19,2394,2395,2398,2399,2402],{},[34,2396,2397],{},"document.Table.Footer"," es ",[34,2400,2401],{},"[]TableRow"," que se repite en cada página, igual que el header. La API builder no la expone porque la mayoría de tablas cortas no la necesitan — cuando la necesitas, ya saliste de la zona \"caso común\".",[19,2404,2405,2406,48],{},"Este es el patrón general de gpdf: el builder de alto nivel cubre el 90% con ergonomía, y la capa documento está justo al lado para el otro 10%. No son librerías separadas. Puedes mezclar filas hechas con builder y a mano en el mismo documento. El builder es solo un constructor del mismo nodo ",[34,2407,201],{},[14,2409,2411],{"id":2410},"bordes-y-el-modelo-de-caja","Bordes y el modelo de caja",[19,2413,2414],{},"Tres opciones de borde, tres trabajos diferentes:",[27,2416,2418],{"className":29,"code":2417,"language":31,"meta":32,"style":32},"template.WithTableBorder(spec)         // marco exterior alrededor de toda la tabla\ntemplate.WithTableCellBorder(spec)     // mismo borde alrededor de cada celda\ntemplate.WithTableBorderCollapse(true) // fusionar bordes adyacentes\n",[34,2419,2420,2439,2456],{"__ignoreMap":32},[37,2421,2422,2424,2426,2429,2431,2434,2436],{"class":39,"line":40},[37,2423,117],{"class":43},[37,2425,48],{"class":47},[37,2427,2428],{"class":51},"WithTableBorder",[37,2430,55],{"class":47},[37,2432,2433],{"class":43},"spec",[37,2435,297],{"class":47},[37,2437,2438],{"class":1651},"         // marco exterior alrededor de toda la tabla\n",[37,2440,2441,2443,2445,2447,2449,2451,2453],{"class":39,"line":70},[37,2442,117],{"class":43},[37,2444,48],{"class":47},[37,2446,1417],{"class":51},[37,2448,55],{"class":47},[37,2450,2433],{"class":43},[37,2452,297],{"class":47},[37,2454,2455],{"class":1651},"     // mismo borde alrededor de cada celda\n",[37,2457,2458,2460,2462,2465,2467,2471,2473],{"class":39,"line":105},[37,2459,117],{"class":43},[37,2461,48],{"class":47},[37,2463,2464],{"class":51},"WithTableBorderCollapse",[37,2466,55],{"class":47},[37,2468,2470],{"class":2469},"sfNiH","true",[37,2472,297],{"class":47},[37,2474,2475],{"class":1651}," // fusionar bordes adyacentes\n",[19,2477,2478,2479,2481,2482,2484,2485,2488,2489,48],{},"Por defecto, sin bordes. Añade ",[34,2480,2428],{}," para un marco. Añade ",[34,2483,1417],{}," para dibujar el mismo borde en cada celda — el look de cuadrícula. Ambos juntos = marco alrededor de cuadrícula. El ",[34,2486,2487],{},"BorderSpec"," se construye con ",[34,2490,2491],{},"template.Border(template.BorderWidth(...), template.BorderColor(...))",[19,2493,2494,2497],{},[34,2495,2496],{},"WithTableBorderCollapse(true)"," es el equivalente CSS: bordes adyacentes se fusionan en una sola línea (en vez de dibujarse dos veces, una por cada celda). En cuadrículas hairline donde el borde importa visualmente, collapse se ve más limpio. En bordes gruesos donde quieres el doble grosor a propósito, déjalo apagado. Por defecto, separados.",[19,2499,2500],{},"Combinación útil: bordes hairline en celdas + rayas suaves:",[27,2502,2504],{"className":29,"code":2503,"language":31,"meta":32,"style":32},"c.Table(header, rows,\n    template.ColumnWidths(40, 20, 15, 25),\n    template.TableHeaderStyle(template.TextColor(pdf.White), template.BgColor(brand)),\n    template.TableStripe(pdf.RGBHex(0xF5F5F5)),\n    template.WithTableCellBorder(template.Border(\n        template.BorderWidth(document.Pt(0.5)),\n        template.BorderColor(pdf.Gray(0.85)),\n    )),\n    template.WithTableBorderCollapse(true),\n)\n",[34,2505,2506,2524,2550,2588,2610,2628,2650,2672,2677,2691],{"__ignoreMap":32},[37,2507,2508,2510,2512,2514,2516,2518,2520,2522],{"class":39,"line":40},[37,2509,44],{"class":43},[37,2511,48],{"class":47},[37,2513,52],{"class":51},[37,2515,55],{"class":47},[37,2517,58],{"class":43},[37,2519,61],{"class":47},[37,2521,64],{"class":43},[37,2523,67],{"class":47},[37,2525,2526,2528,2530,2532,2534,2536,2538,2540,2542,2544,2546,2548],{"class":39,"line":70},[37,2527,73],{"class":43},[37,2529,48],{"class":47},[37,2531,78],{"class":51},[37,2533,55],{"class":47},[37,2535,84],{"class":83},[37,2537,61],{"class":47},[37,2539,94],{"class":83},[37,2541,61],{"class":47},[37,2543,89],{"class":83},[37,2545,61],{"class":47},[37,2547,99],{"class":83},[37,2549,102],{"class":47},[37,2551,2552,2554,2556,2558,2560,2562,2564,2566,2568,2570,2572,2574,2576,2578,2580,2582,2584,2586],{"class":39,"line":105},[37,2553,73],{"class":43},[37,2555,48],{"class":47},[37,2557,112],{"class":51},[37,2559,55],{"class":47},[37,2561,117],{"class":43},[37,2563,48],{"class":47},[37,2565,122],{"class":51},[37,2567,55],{"class":47},[37,2569,127],{"class":43},[37,2571,48],{"class":47},[37,2573,132],{"class":43},[37,2575,135],{"class":47},[37,2577,138],{"class":43},[37,2579,48],{"class":47},[37,2581,143],{"class":51},[37,2583,55],{"class":47},[37,2585,148],{"class":43},[37,2587,151],{"class":47},[37,2589,2590,2592,2594,2596,2598,2600,2602,2604,2606,2608],{"class":39,"line":154},[37,2591,73],{"class":43},[37,2593,48],{"class":47},[37,2595,161],{"class":51},[37,2597,55],{"class":47},[37,2599,127],{"class":43},[37,2601,48],{"class":47},[37,2603,170],{"class":51},[37,2605,55],{"class":47},[37,2607,175],{"class":83},[37,2609,151],{"class":47},[37,2611,2612,2614,2616,2618,2620,2622,2624,2626],{"class":39,"line":180},[37,2613,73],{"class":43},[37,2615,48],{"class":47},[37,2617,1417],{"class":51},[37,2619,55],{"class":47},[37,2621,117],{"class":43},[37,2623,48],{"class":47},[37,2625,740],{"class":51},[37,2627,613],{"class":47},[37,2629,2630,2632,2634,2636,2638,2640,2642,2644,2646,2648],{"class":39,"line":517},[37,2631,748],{"class":43},[37,2633,48],{"class":47},[37,2635,753],{"class":51},[37,2637,55],{"class":47},[37,2639,650],{"class":43},[37,2641,48],{"class":47},[37,2643,762],{"class":51},[37,2645,55],{"class":47},[37,2647,767],{"class":83},[37,2649,151],{"class":47},[37,2651,2652,2654,2656,2658,2660,2662,2664,2666,2668,2670],{"class":39,"line":527},[37,2653,748],{"class":43},[37,2655,48],{"class":47},[37,2657,779],{"class":51},[37,2659,55],{"class":47},[37,2661,127],{"class":43},[37,2663,48],{"class":47},[37,2665,788],{"class":51},[37,2667,55],{"class":47},[37,2669,793],{"class":83},[37,2671,151],{"class":47},[37,2673,2674],{"class":39,"line":532},[37,2675,2676],{"class":47},"    )),\n",[37,2678,2679,2681,2683,2685,2687,2689],{"class":39,"line":542},[37,2680,73],{"class":43},[37,2682,48],{"class":47},[37,2684,2464],{"class":51},[37,2686,55],{"class":47},[37,2688,2470],{"class":2469},[37,2690,102],{"class":47},[37,2692,2693],{"class":39,"line":552},[37,2694,183],{"class":47},[19,2696,2697],{},"El look al que aterriza la vista previa de impresión de cualquier hoja de cálculo de un contable, deliberadamente. Es el default correcto para cualquier documento financiero — facturas, estados de cuenta, libros, reportes de gastos.",[14,2699,2701],{"id":2700},"comparación-con-las-alternativas","Comparación con las alternativas",[19,2703,2704],{},"Para contexto, esto cuesta la misma tabla multipágina con rayas en las librerías que gpdf suele reemplazar:",[341,2706,2707,2726],{},[344,2708,2709],{},[347,2710,2711,2714,2717,2720,2723],{},[350,2712,2713],{},"Librería",[350,2715,2716],{},"Líneas para la tabla",[350,2718,2719],{},"Repetición de header al saltar página",[350,2721,2722],{},"Rayas",[350,2724,2725],{},"Notas",[357,2727,2728,2754,2776,2791,2807,2826],{},[347,2729,2730,2734,2739,2744,2751],{},[362,2731,2732],{},[22,2733,218],{},[362,2735,2736],{},[22,2737,2738],{},"~10",[362,2740,2741],{},[22,2742,2743],{},"automático",[362,2745,2746],{},[22,2747,2748],{},[34,2749,2750],{},"TableStripe(...)",[362,2752,2753],{},"Builder y bajo nivel disponibles",[347,2755,2756,2759,2762,2768,2773],{},[362,2757,2758],{},"jung-kurt/gofpdf (archivado 2021)",[362,2760,2761],{},"40–60",[362,2763,2764,2765,2767],{},"manual: rastrear Y, llamar ",[34,2766,1145],{},", reemitir header",[362,2769,2770,2771],{},"bucle manual con ",[34,2772,1780],{},[362,2774,2775],{},"Fundacional, sin mantenimiento",[347,2777,2778,2781,2783,2786,2788],{},[362,2779,2780],{},"go-pdf/fpdf (archivado 2025)",[362,2782,2761],{},[362,2784,2785],{},"igual",[362,2787,2785],{},[362,2789,2790],{},"Era fork de gofpdf, mismo modelo",[347,2792,2793,2796,2799,2802,2804],{},[362,2794,2795],{},"signintech/gopdf",[362,2797,2798],{},"50–80",[362,2800,2801],{},"manual",[362,2803,2801],{},[362,2805,2806],{},"Aún más bajo nivel",[347,2808,2809,2812,2815,2817,2823],{},[362,2810,2811],{},"johnfercher/maroto v2",[362,2813,2814],{},"~15",[362,2816,2743],{},[362,2818,2819,2822],{},[34,2820,2821],{},"WithBackgroundColor"," por fila a mano",[362,2824,2825],{},"Sobre gofpdf; API agradable pero hereda dependencias",[347,2827,2828,2831,2834,2836,2839],{},[362,2829,2830],{},"unidoc/unipdf",[362,2832,2833],{},"~12",[362,2835,2743],{},[362,2837,2838],{},"helper de estilo de fila",[362,2840,2841],{},"Licencia comercial requerida",[19,2843,2844,2845,2847,2848,2850],{},"Comparando solo líneas de builder, la diferencia se aprieta. La diferencia real aparece al mes 6 de uso, cuando los requisitos derivan — una nueva columna necesita otra alineación, el reporte tiene que ir en japonés, el cliente quiere el conteo de filas en el footer. Con ",[34,2846,1773],{}," o ",[34,2849,1776],{},", cada deriva pide tocar el bucle de filas. Con gpdf, la lista de opciones crece y el cuerpo del código no cambia.",[19,2852,2853,2854,2858,2859,2863],{},"Para benchmarks — las cifras µs por tabla — ver ",[213,2855,2857],{"href":2856},"/es/blog/why-gpdf-is-faster","por qué gpdf es más rápido",". Para el showdown más amplio entre librerías, ",[213,2860,2862],{"href":2861},"/es/blog/go-pdf-library-showdown-2026","el showdown de 2026"," va columna por columna.",[14,2865,2867],{"id":2866},"cjk-en-tablas","CJK en tablas",[19,2869,2870],{},"Algo invisible en la tabla comparativa de arriba: gpdf renderiza glifos CJK nativamente. No hay un \"modo japonés\" para tablas — registras la fuente una vez y la tabla la usa para todo.",[27,2872,2874],{"className":29,"code":2873,"language":31,"meta":32,"style":32},"ttf, _ := os.ReadFile(\"NotoSansJP-Regular.ttf\")\ndoc := gpdf.NewDocument(\n    gpdf.WithPageSize(gpdf.A4),\n    gpdf.WithFont(\"NotoSansJP\", ttf),\n    gpdf.WithDefaultFont(\"NotoSansJP\"),\n)\n\nc.Table(\n    []string{\"日付\", \"請求書番号\", \"顧客名\", \"金額\"},\n    [][]string{\n        {\"2026-04-01\", \"INV-10001\", \"株式会社サンプル\", \"￥120,000\"},\n        {\"2026-04-02\", \"INV-10002\", \"山田商店\", \"￥38,500\"},\n    },\n    template.ColumnWidths(20, 20, 40, 20),\n)\n",[34,2875,2876,2906,2921,2940,2965,2984,2988,2992,3002,3047,3056,3096,3136,3140,3166],{"__ignoreMap":32},[37,2877,2878,2881,2883,2886,2888,2890,2892,2895,2897,2899,2902,2904],{"class":39,"line":40},[37,2879,2880],{"class":43},"ttf",[37,2882,61],{"class":47},[37,2884,2885],{"class":43}," _ ",[37,2887,602],{"class":47},[37,2889,1519],{"class":43},[37,2891,48],{"class":47},[37,2893,2894],{"class":51},"ReadFile",[37,2896,55],{"class":47},[37,2898,823],{"class":47},[37,2900,2901],{"class":826},"NotoSansJP-Regular.ttf",[37,2903,823],{"class":47},[37,2905,183],{"class":47},[37,2907,2908,2911,2913,2915,2917,2919],{"class":39,"line":70},[37,2909,2910],{"class":43},"doc ",[37,2912,602],{"class":47},[37,2914,605],{"class":43},[37,2916,48],{"class":47},[37,2918,610],{"class":51},[37,2920,613],{"class":47},[37,2922,2923,2926,2928,2930,2932,2934,2936,2938],{"class":39,"line":105},[37,2924,2925],{"class":43},"    gpdf",[37,2927,48],{"class":47},[37,2929,624],{"class":51},[37,2931,55],{"class":47},[37,2933,218],{"class":43},[37,2935,48],{"class":47},[37,2937,633],{"class":43},[37,2939,102],{"class":47},[37,2941,2942,2944,2946,2949,2951,2953,2956,2958,2960,2963],{"class":39,"line":154},[37,2943,2925],{"class":43},[37,2945,48],{"class":47},[37,2947,2948],{"class":51},"WithFont",[37,2950,55],{"class":47},[37,2952,823],{"class":47},[37,2954,2955],{"class":826},"NotoSansJP",[37,2957,823],{"class":47},[37,2959,61],{"class":47},[37,2961,2962],{"class":43}," ttf",[37,2964,102],{"class":47},[37,2966,2967,2969,2971,2974,2976,2978,2980,2982],{"class":39,"line":180},[37,2968,2925],{"class":43},[37,2970,48],{"class":47},[37,2972,2973],{"class":51},"WithDefaultFont",[37,2975,55],{"class":47},[37,2977,823],{"class":47},[37,2979,2955],{"class":826},[37,2981,823],{"class":47},[37,2983,102],{"class":47},[37,2985,2986],{"class":39,"line":517},[37,2987,183],{"class":47},[37,2989,2990],{"class":39,"line":527},[37,2991,485],{"emptyLinePlaceholder":484},[37,2993,2994,2996,2998,3000],{"class":39,"line":532},[37,2995,44],{"class":43},[37,2997,48],{"class":47},[37,2999,52],{"class":51},[37,3001,613],{"class":47},[37,3003,3004,3007,3009,3011,3013,3016,3018,3020,3022,3025,3027,3029,3031,3034,3036,3038,3040,3043,3045],{"class":39,"line":542},[37,3005,3006],{"class":47},"    []",[37,3008,311],{"class":310},[37,3010,820],{"class":47},[37,3012,823],{"class":47},[37,3014,3015],{"class":826},"日付",[37,3017,823],{"class":47},[37,3019,61],{"class":47},[37,3021,834],{"class":47},[37,3023,3024],{"class":826},"請求書番号",[37,3026,823],{"class":47},[37,3028,61],{"class":47},[37,3030,834],{"class":47},[37,3032,3033],{"class":826},"顧客名",[37,3035,823],{"class":47},[37,3037,61],{"class":47},[37,3039,834],{"class":47},[37,3041,3042],{"class":826},"金額",[37,3044,823],{"class":47},[37,3046,2267],{"class":47},[37,3048,3049,3052,3054],{"class":39,"line":552},[37,3050,3051],{"class":47},"    [][]",[37,3053,311],{"class":310},[37,3055,948],{"class":47},[37,3057,3058,3060,3062,3065,3067,3069,3071,3074,3076,3078,3080,3083,3085,3087,3089,3092,3094],{"class":39,"line":562},[37,3059,2210],{"class":47},[37,3061,823],{"class":47},[37,3063,3064],{"class":826},"2026-04-01",[37,3066,823],{"class":47},[37,3068,61],{"class":47},[37,3070,834],{"class":47},[37,3072,3073],{"class":826},"INV-10001",[37,3075,823],{"class":47},[37,3077,61],{"class":47},[37,3079,834],{"class":47},[37,3081,3082],{"class":826},"株式会社サンプル",[37,3084,823],{"class":47},[37,3086,61],{"class":47},[37,3088,834],{"class":47},[37,3090,3091],{"class":826},"￥120,000",[37,3093,823],{"class":47},[37,3095,2267],{"class":47},[37,3097,3098,3100,3102,3105,3107,3109,3111,3114,3116,3118,3120,3123,3125,3127,3129,3132,3134],{"class":39,"line":572},[37,3099,2210],{"class":47},[37,3101,823],{"class":47},[37,3103,3104],{"class":826},"2026-04-02",[37,3106,823],{"class":47},[37,3108,61],{"class":47},[37,3110,834],{"class":47},[37,3112,3113],{"class":826},"INV-10002",[37,3115,823],{"class":47},[37,3117,61],{"class":47},[37,3119,834],{"class":47},[37,3121,3122],{"class":826},"山田商店",[37,3124,823],{"class":47},[37,3126,61],{"class":47},[37,3128,834],{"class":47},[37,3130,3131],{"class":826},"￥38,500",[37,3133,823],{"class":47},[37,3135,2267],{"class":47},[37,3137,3138],{"class":39,"line":577},[37,3139,2161],{"class":47},[37,3141,3142,3144,3146,3148,3150,3152,3154,3156,3158,3160,3162,3164],{"class":39,"line":582},[37,3143,73],{"class":43},[37,3145,48],{"class":47},[37,3147,78],{"class":51},[37,3149,55],{"class":47},[37,3151,669],{"class":83},[37,3153,61],{"class":47},[37,3155,94],{"class":83},[37,3157,61],{"class":47},[37,3159,1333],{"class":83},[37,3161,61],{"class":47},[37,3163,94],{"class":83},[37,3165,102],{"class":47},[37,3167,3168],{"class":39,"line":596},[37,3169,183],{"class":47},[19,3171,3172],{},"Header en japonés, cuerpo en japonés, anchos siguen siendo porcentajes, repetición de header en saltos sigue funcionando. La fuente se subseta a solo los glifos que el documento usa, así que el PDF resultante es pequeño aun con Noto Sans JP completa disponible — unos 50 KB para una página versus los 6 MB del archivo de fuente sin subsetear.",[19,3174,3175,3176,3180],{},"Para el setup de la fuente, ",[213,3177,3179],{"href":3178},"/es/blog/embed-japanese-font","embedir una fuente TrueType japonesa"," es la receta. El punto aquí es que nada en la API de tabla cambia cuando los datos son CJK.",[14,3182,3184],{"id":3183},"preguntas-frecuentes","Preguntas frecuentes",[19,3186,3187],{},[22,3188,3189],{},"P: ¿gpdf soporta estilo por fila?",[19,3191,3192,3193,3196,3197,3200,3201,3203,3204,3206,3207,3210,3211,48],{},"No en la API builder. El builder toma ",[34,3194,3195],{},"[][]string"," para el cuerpo, lo que significa que cada celda comparte el mismo ",[34,3198,3199],{},"Style"," derivado de la columna. Para estilizar filas individuales, construye la tabla en la capa ",[34,3202,201],{}," donde cada ",[34,3205,1968],{}," lleva su propio ",[34,3208,3209],{},"CellStyle",". El patrón es directo; solo te cuesta la conveniencia de la forma ",[34,3212,3195],{},[19,3214,3215],{},[22,3216,3217],{},"P: ¿Puedo poner imágenes u otras tablas dentro de una celda?",[19,3219,3220,3221,3223,3224,2398,3227,3230,3231,2360,3234,3237,3238,3241],{},"Sí, en la capa ",[34,3222,201],{},". ",[34,3225,3226],{},"TableCell.Content",[34,3228,3229],{},"[]DocumentNode",", que acepta cualquier nodo — ",[34,3232,3233],{},"*Text",[34,3235,3236],{},"*Image",", incluso otra ",[34,3239,3240],{},"*Table",". La API builder basada en strings no lo expone por ser un borde más afilado de lo que la mayoría quiere, pero el modelo subyacente lo soporta.",[19,3243,3244],{},[22,3245,3246],{},"P: ¿Cómo decide gpdf dónde partir el cuerpo entre páginas?",[19,3248,3249],{},"Fila por fila. El motor mide cada fila del cuerpo en orden y la añade a la página actual hasta que la siguiente excedería la altura disponible. Esa fila se vuelve la primera de la tabla overflow. Aún no hay anotación \"mantén estas filas juntas\" — toda fila es divisible. Para líneas de factura donde necesitas un grupo lógico en una página, deberías abrir página manualmente antes del grupo o caer a la capa documento para insertar pistas de salto.",[19,3251,3252],{},[22,3253,3254],{},"P: ¿Cuál es la tabla más grande que gpdf puede renderizar?",[19,3256,3257,3258,3261,3262,3264,3265,48],{},"Probamos con 10,000 filas en A4. Pagina correctamente, el header se repite en cada página, el PDF resultante tiene ~150 páginas y unos cientos de KB. El cuello de botella no es el layout de tabla — es el shaping de texto del contenido de la celda, que es ",[34,3259,3260],{},"O(filas × columnas)",". Si necesitas 100,000+ filas, escribe a disco en chunks (varias llamadas a ",[34,3263,1466],{}," por ~10k filas) o alimenta runs pre-shaped en la capa ",[34,3266,201],{},[19,3268,3269],{},[22,3270,3271],{},"P: ¿Puedo hacer que el footer aparezca solo en la última página?",[19,3273,3274,3275,3277],{},"No de forma nativa. ",[34,3276,2397],{}," se repite en cada página por diseño — es el caso común (totales por página). Si necesitas un resumen único al final del documento, añádelo como bloque de filas separado tras la tabla, no dentro.",[19,3279,3280],{},[22,3281,3282,3283,3285],{},"P: ¿",[34,3284,1417],{}," afecta también al header?",[19,3287,3288,3289,3292],{},"Sí. Los bordes de celda aplican uniformemente a header y cuerpo. Si quieres un borde distinto en el header (por ejemplo, borde inferior más grueso bajo la fila del header), constrúyelo en la capa documento y aplica ",[34,3290,3291],{},"CellStyle.Border"," por celda allí.",[14,3294,3296],{"id":3295},"la-forma-del-diseño","La forma del diseño",[19,3298,3299,3300,3303],{},"Si hay una sola cosa que llevarse: ",[22,3301,3302],{},"la API de tablas de gpdf es pequeña porque la mayoría de los problemas de tabla son los mismos tres problemas."," Anchos, rayas, saltos de página. Lo demás es long tail. Poner los casos comunes en el builder y el long tail en la capa documento es el trato — tienes tablas de cinco líneas para lo cotidiano y no pagas la abstracción cuando necesitas algo que el builder no expresa.",[19,3305,3306,3307,3310],{},"El costo es honesto: no hay atajo ",[34,3308,3309],{},"setRowStyle(i, ...)"," y no lo habrá. Si quieres estilizar la fila 4 distinto de la 5, cruzaste una línea de complejidad que el builder no intenta manejar. Baja una capa. La frontera es clara y estable.",[19,3312,3313],{},"Eso es el artículo entero. Veinte minutos de lectura para una parte de la API que vale la pena entender bien una vez y luego no pensar más.",[14,3315,3317],{"id":3316},"prueba-gpdf","Prueba gpdf",[19,3319,3320],{},"gpdf es una librería Go para generar PDFs. Licencia MIT, cero dependencias externas, soporte CJK nativo.",[27,3322,3326],{"className":3323,"code":3324,"language":3325,"meta":32,"style":32},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","go get github.com/gpdf-dev/gpdf\n","bash",[34,3327,3328],{"__ignoreMap":32},[37,3329,3330,3332,3335],{"class":39,"line":40},[37,3331,31],{"class":293},[37,3333,3334],{"class":826}," get",[37,3336,3337],{"class":826}," github.com/gpdf-dev/gpdf\n",[19,3339,3340,3344,3345],{},[213,3341,3343],{"href":215,"rel":3342},[217],"⭐ Star en GitHub"," · ",[213,3346,3349],{"href":3347,"rel":3348},"https://gpdf.dev/es/docs/quickstart",[217],"Lee la documentación",[14,3351,3353],{"id":3352},"lectura-relacionada","Lectura relacionada",[1790,3355,3356,3364,3370,3377,3384],{},[231,3357,3358,3361,3362],{},[213,3359,3360],{"href":1724},"¿Cómo establezco anchos de columna en una tabla gpdf?"," — los detalles de ",[34,3363,78],{},[231,3365,3366,3369],{},[213,3367,3368],{"href":1815},"¿Cómo hago filas con rayas zebra?"," — elección de color y temas oscuros",[231,3371,3372,3376],{},[213,3373,3375],{"href":3374},"/es/blog/bootstrap-grid-thinking-for-pdf","Pensar Bootstrap para PDF: la cuadrícula de 12 columnas de gpdf"," — qué Col padre resuelve los porcentajes",[231,3378,3379,3383],{},[213,3380,3382],{"href":3381},"/es/blog/invoice-pdf-go-under-50-lines","Genera un PDF de factura en Go en menos de 50 líneas"," — una tabla del mundo real dentro de un documento completo",[231,3385,3386,3389],{},[213,3387,3388],{"href":2856},"Por qué gpdf es más rápido que gofpdf, gopdf y Maroto"," — los µs detrás de la tabla comparativa",[3391,3392,3393],"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 .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}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 .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}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}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 .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 .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 pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":32,"searchDepth":70,"depth":70,"links":3395},[3396,3397,3398,3399,3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410],{"id":16,"depth":70,"text":17},{"id":208,"depth":70,"text":209},{"id":266,"depth":70,"text":267},{"id":451,"depth":70,"text":452},{"id":1600,"depth":70,"text":1601},{"id":1729,"depth":70,"text":1730},{"id":1824,"depth":70,"text":1825},{"id":1901,"depth":70,"text":1902},{"id":2410,"depth":70,"text":2411},{"id":2700,"depth":70,"text":2701},{"id":2866,"depth":70,"text":2867},{"id":3183,"depth":70,"text":3184},{"id":3295,"depth":70,"text":3296},{"id":3316,"depth":70,"text":3317},{"id":3352,"depth":70,"text":3353},"2026-05-07","Las tablas son la parte más difícil de un PDF en Go. gpdf colapsa anchos, rayas y la repetición del encabezado en cada página dentro de una sola llamada.",false,"md",{"name":3416,"totalTime":3417,"tools":3418,"steps":3420},"Renderizar una tabla multipágina en Go con anchos de columna, rayas y encabezado repetido usando gpdf","PT20M",[3419,537],"Go 1.22+",[3421,3424,3427,3430,3433,3436],{"name":3422,"text":3423},"Instalar gpdf","Ejecuta go get github.com/gpdf-dev/gpdf en un módulo Go 1.22+. La librería core no tiene dependencias externas; con esta línea basta.",{"name":3425,"text":3426},"Construir una sola llamada Table dentro de un Col","Dentro de page.AutoRow → r.Col(12, ...), llama c.Table(header, rows). El header es []string, rows es [][]string. Sin opciones las columnas se reparten igual.",{"name":3428,"text":3429},"Definir anchos por columna en porcentajes","Pasa template.ColumnWidths(40, 15, 20, 25). Cada valor es porcentaje del ancho del Col padre. Los valores faltantes al final se autodistribuyen.",{"name":3431,"text":3432},"Estilizar el encabezado y añadir rayas","Añade template.TableHeaderStyle(template.TextColor(pdf.White), template.BgColor(brand)) y template.TableStripe(pdf.RGBHex(0xF5F5F5)). Las rayas aplican solo al cuerpo, no al header.",{"name":3434,"text":3435},"Deja que gpdf pagine. El header se repite automáticamente","Dale tantas filas que excedan una página. gpdf parte el cuerpo entre páginas y reemite la sección Header al inicio de cada página de continuación. Sin opción PageBreak ni conteo manual.",{"name":3437,"text":3438},"Baja a document.Table cuando necesites ColSpan, RowSpan, anchos fijos o un footer","Construye &document.Table{Columns, Header, Body, Footer} directamente cuando necesites celdas combinadas, columnas en pt fijas o un footer que se repita en todas las páginas. La API builder no expone esto a propósito.",null,{},"/es/blog/tables-in-go-pdfs",{"title":5,"description":3412},"es/blog/022.tables-in-go-pdfs",[3445,3446,3447],"tutorial","templates","comparison","rsyW8-iwCCNBVEVTYxgHaZ39H6SYRMEz85Ar8UNJ2EU",1779199041408]