gofpdf
gofpdf copied to clipboard
Question: How to generate a table with cell word wrap?
Hi, I'm trying to create a table where each cell can be word wrap. How can I do that? I tried using MultiCell but it goes to the next line for each cell and CellFormat does not seem to support MultiCell.
Something like this.
Name | Description |
---|---|
John | John has a cat. John has a dog. |
Jane | Jane has a cat. |
This can be done with SplitLines()
. The limitation is that only one font and attribute per cell are supported.
For each row, you will need to loop through each column twice. The first time, call SplitLines()
to calculate each cell's height. The second time, use the maximum cell height from the previous loop as the
row height. Apply padding as needed to vertically center the text of cells that have a height less than the row height.
I've tried your suggestion and manage to get the max height but i couldn't word wrap using CellFormat like MultiCell
The example accompanying the documentation for SplitLines()
shows how each of the substrings (of type []byte) returned by SplitLines()
has to be passed to CellFormat()
individually. It's really SplitLines()
that determines where the wrap breaks are; after that the substrings are manually rendered.
I'll try to find some time tomorrow to augment the table example to demonstrate this.
Cool thanks
Demonstrated in 4491d0fe5997270270f8e4023786afd99251f604
Awesome. I'll have a go on your example. Thanks
Your example works. Thanks
Hi @jung-kurt, thank you for this awesome lib!
I think it would be awesome if the lib had that abstracted in a function or struct. It's a pretty common use case.
Thanks again! 😃
Thanks, @andreynering. I agree, an abstraction of word-wrapped table cells make sense. If it is done at the table level, then it could facilitate alternate row shading and page breaks with header rows. I'll reflect on various approaches and put something together in the days ahead.
I tried the approach it works fine with only one page. If the table is longer than one page and auto break is enabled the layout gets messed up. I'm working on a solution.
Thanks, @jacobfederer -- I look forward to seeing what you come up with.
hi @jung-kurt Can merge the cell's in the table? How would you do?
Can merge the cell's in the table? How would you do?
Tables in gofpdf are built up of individual cells. You can merge them manually with something like this:
package main
import (
"fmt"
"github.com/jung-kurt/gofpdf/v2"
)
func main() {
const (
colCount = 4
rowCount = 3
margin = 32.0
fontHt = 14.0 // point
)
pdf := gofpdf.New("L", "mm", "A4", "")
cellWd := (297 - margin - margin) / colCount
cellHt := pdf.PointToUnitConvert(fontHt) + 10.0
pdf.SetFont("Arial", "", fontHt)
pdf.AddPage()
pdf.SetXY(margin, margin)
for rowJ := 0; rowJ < rowCount; rowJ++ {
for colJ := 0; colJ < colCount; colJ++ {
pdf.SetXY(margin+float64(colJ)*cellWd, margin+float64(rowJ)*cellHt)
if rowJ == 1 && (colJ == 1 || colJ == 2) {
if colJ == 1 { // Merged cells
pdf.CellFormat(cellWd*2.0, cellHt, fmt.Sprintf("Merged cells"), "1", 0, "CM", false, 0, "")
}
} else {
pdf.CellFormat(cellWd, cellHt, fmt.Sprintf("Row %d, Col %d", rowJ, colJ), "1", 0, "CM", false, 0, "")
}
}
}
err := pdf.OutputFileAndClose("colmerge.pdf")
if err != nil {
fmt.Printf("%s\n", err)
}
}
very very Thankful
[image: Mailtrack] https://mailtrack.io?utm_source=gmail&utm_medium=signature&utm_campaign=signaturevirality5& Sender notified by Mailtrack https://mailtrack.io?utm_source=gmail&utm_medium=signature&utm_campaign=signaturevirality5& 27/03/19, 7:06:46 pm
On Sat, Mar 23, 2019 at 7:45 PM Kurt Jung [email protected] wrote:
Can merge the cell's in the table? How would you do?
Tables in gofpdf are built up of individual cells. You can merge them manually with something like this:
package main import ( "fmt"
"github.com/jung-kurt/gofpdf/v2" ) func main() { const ( colCount = 4 rowCount = 3 margin = 32.0 fontHt = 14.0 // point ) pdf := gofpdf.New("L", "mm", "A4", "") cellWd := (297 - margin - margin) / colCount cellHt := pdf.PointToUnitConvert(fontHt) + 10.0 pdf.SetFont("Arial", "", fontHt) pdf.AddPage() pdf.SetXY(margin, margin) for rowJ := 0; rowJ < rowCount; rowJ++ { for colJ := 0; colJ < colCount; colJ++ { pdf.SetXY(margin+float64(colJ)*cellWd, margin+float64(rowJ)cellHt) if rowJ == 1 && (colJ == 1 || colJ == 2) { if colJ == 1 { // Merged cells pdf.CellFormat(cellWd2.0, cellHt, fmt.Sprintf("Merged cells"), "1", 0, "CM", false, 0, "") } } else { pdf.CellFormat(cellWd, cellHt, fmt.Sprintf("Row %d, Col %d", rowJ, colJ), "1", 0, "CM", false, 0, "") } } } err := pdf.OutputFileAndClose("colmerge.pdf") if err != nil { fmt.Printf("%s\n", err) } }
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/jung-kurt/gofpdf/issues/129#issuecomment-475873331, or mute the thread https://github.com/notifications/unsubscribe-auth/Ad0bauryaJCz2ZehXL_Z4xYxAGEqGa_3ks5vZjcHgaJpZM4O_c_v .
But here we can't be merge corner cell. Like:- Merged cell Name: Class: Sub Mark1 Mark2 Mark3 SUB1 1 2 3 SUB2 4 5 6 SUB3 7 8 9
[image: Mailtrack] https://mailtrack.io?utm_source=gmail&utm_medium=signature&utm_campaign=signaturevirality5& Sender notified by Mailtrack https://mailtrack.io?utm_source=gmail&utm_medium=signature&utm_campaign=signaturevirality5& 27/03/19, 7:25:34 pm
On Wed, Mar 27, 2019 at 7:07 PM Dinesh kumar S [email protected] wrote:
very very Thankful
[image: Mailtrack] https://mailtrack.io?utm_source=gmail&utm_medium=signature&utm_campaign=signaturevirality5& Sender notified by Mailtrack https://mailtrack.io?utm_source=gmail&utm_medium=signature&utm_campaign=signaturevirality5& 27/03/19, 7:06:46 pm
On Sat, Mar 23, 2019 at 7:45 PM Kurt Jung [email protected] wrote:
Can merge the cell's in the table? How would you do?
Tables in gofpdf are built up of individual cells. You can merge them manually with something like this:
package main import ( "fmt"
"github.com/jung-kurt/gofpdf/v2" ) func main() { const ( colCount = 4 rowCount = 3 margin = 32.0 fontHt = 14.0 // point ) pdf := gofpdf.New("L", "mm", "A4", "") cellWd := (297 - margin - margin) / colCount cellHt := pdf.PointToUnitConvert(fontHt) + 10.0 pdf.SetFont("Arial", "", fontHt) pdf.AddPage() pdf.SetXY(margin, margin) for rowJ := 0; rowJ < rowCount; rowJ++ { for colJ := 0; colJ < colCount; colJ++ { pdf.SetXY(margin+float64(colJ)*cellWd, margin+float64(rowJ)cellHt) if rowJ == 1 && (colJ == 1 || colJ == 2) { if colJ == 1 { // Merged cells pdf.CellFormat(cellWd2.0, cellHt, fmt.Sprintf("Merged cells"), "1", 0, "CM", false, 0, "") } } else { pdf.CellFormat(cellWd, cellHt, fmt.Sprintf("Row %d, Col %d", rowJ, colJ), "1", 0, "CM", false, 0, "") } } } err := pdf.OutputFileAndClose("colmerge.pdf") if err != nil { fmt.Printf("%s\n", err) } }
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/jung-kurt/gofpdf/issues/129#issuecomment-475873331, or mute the thread https://github.com/notifications/unsubscribe-auth/Ad0bauryaJCz2ZehXL_Z4xYxAGEqGa_3ks5vZjcHgaJpZM4O_c_v .
Hi, Thank you... I got it!.... by the way package main
import ( "fmt"
"github.com/jung-kurt/gofpdf"
)
func main() { const ( colCount = 4 rowCount = 3 margin = 32.0 fontHt = 14.0 // point ) pdf := gofpdf.New("L", "mm", "A4", "") cellWd := (297 - margin - margin) / colCount cellHt := pdf.PointToUnitConvert(fontHt) + 10.0 pdf.SetFont("Arial", "", fontHt) pdf.AddPage() pdf.SetXY(margin, margin) for rowJ := 0; rowJ < rowCount; rowJ++ { for colJ := 0; colJ < colCount; colJ++ { pdf.SetXY(margin+float64(colJ)cellWd, margin+float64 (rowJ)cellHt) if (rowJ == 0 || rowJ == 1) && (colJ == 0 || colJ == 1) { if rowJ == 0 && colJ == 0 { pdf.CellFormat(cellWd2.0, cellHt2.0, fmt.Sprintf("Merged cells"), "1", 0, "CM", false, 0, "") } } else if (rowJ == 0 || rowJ == 1) && (colJ == 2 || colJ == 3) { if (rowJ == 0 || rowJ == 1) && colJ == 2 { pdf.CellFormat(cellWd*2.0, cellHt, fmt.Sprintf("Merged cells"), "1", 0, "CM", false, 0, "") } } else { pdf.CellFormat(cellWd, cellHt, fmt.Sprintf("Row %d, Col %d", rowJ, colJ), "1", 0, "CM", false, 0, "") } } } err := pdf.OutputFileAndClose("colmerge.pdf") if err != nil { fmt.Printf("%s\n", err) } }
Result:-
[image: Mailtrack] https://mailtrack.io?utm_source=gmail&utm_medium=signature&utm_campaign=signaturevirality5& Sender notified by Mailtrack https://mailtrack.io?utm_source=gmail&utm_medium=signature&utm_campaign=signaturevirality5& 27/03/19, 8:10:59 pm
On Wed, Mar 27, 2019 at 7:26 PM Dinesh kumar S [email protected] wrote:
But here we can't be merge corner cell. Like:- Merged cell Name: Class: Sub Mark1 Mark2 Mark3 SUB1 1 2 3 SUB2 4 5 6 SUB3 7 8 9
[image: Mailtrack] https://mailtrack.io?utm_source=gmail&utm_medium=signature&utm_campaign=signaturevirality5& Sender notified by Mailtrack https://mailtrack.io?utm_source=gmail&utm_medium=signature&utm_campaign=signaturevirality5& 27/03/19, 7:25:34 pm
On Wed, Mar 27, 2019 at 7:07 PM Dinesh kumar S [email protected] wrote:
very very Thankful
[image: Mailtrack] https://mailtrack.io?utm_source=gmail&utm_medium=signature&utm_campaign=signaturevirality5& Sender notified by Mailtrack https://mailtrack.io?utm_source=gmail&utm_medium=signature&utm_campaign=signaturevirality5& 27/03/19, 7:06:46 pm
On Sat, Mar 23, 2019 at 7:45 PM Kurt Jung [email protected] wrote:
Can merge the cell's in the table? How would you do?
Tables in gofpdf are built up of individual cells. You can merge them manually with something like this:
package main import ( "fmt"
"github.com/jung-kurt/gofpdf/v2" ) func main() { const ( colCount = 4 rowCount = 3 margin = 32.0 fontHt = 14.0 // point ) pdf := gofpdf.New("L", "mm", "A4", "") cellWd := (297 - margin - margin) / colCount cellHt := pdf.PointToUnitConvert(fontHt) + 10.0 pdf.SetFont("Arial", "", fontHt) pdf.AddPage() pdf.SetXY(margin, margin) for rowJ := 0; rowJ < rowCount; rowJ++ { for colJ := 0; colJ < colCount; colJ++ { pdf.SetXY(margin+float64(colJ)*cellWd, margin+float64(rowJ)cellHt) if rowJ == 1 && (colJ == 1 || colJ == 2) { if colJ == 1 { // Merged cells pdf.CellFormat(cellWd2.0, cellHt, fmt.Sprintf("Merged cells"), "1", 0, "CM", false, 0, "") } } else { pdf.CellFormat(cellWd, cellHt, fmt.Sprintf("Row %d, Col %d", rowJ, colJ), "1", 0, "CM", false, 0, "") } } } err := pdf.OutputFileAndClose("colmerge.pdf") if err != nil { fmt.Printf("%s\n", err) } }
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/jung-kurt/gofpdf/issues/129#issuecomment-475873331, or mute the thread https://github.com/notifications/unsubscribe-auth/Ad0bauryaJCz2ZehXL_Z4xYxAGEqGa_3ks5vZjcHgaJpZM4O_c_v .
Thank you... I got it!
Great!
hi @jung-kurt
One more question..!
If the table exists the 1-page alignment is missed... This is a bug or else need to configure anything?
like:
Sorry to bump this issue, but I ran into this too! The above was a complete dealbreaker, so I actually solved it a rather different way - by creating a writeRow() function. Do you think, if I flesh it out and fix it a little, this might be merged into the library?
type rowContents struct {
Contents string
ColumnWidthFraction float64
}
...
usablePageWidth = pageWidth - 2*margin
...
func writeRow(pdf *gofpdf.Fpdf, lineHeight int, contents ...rowContents) {
var maxHeight float64
for _, cellContent := range contents {
columnWidth := (cellContent.ColumnWidthFraction * usablePageWidth) - 2 // -2 for table margins
splitStrings := pdf.SplitText(cellContent.Contents, columnWidth)
if newHeight := float64(len(splitStrings)) * float64(lineHeight); newHeight > maxHeight {
maxHeight = newHeight
}
}
for _, cellContent := range contents {
pdf.CellFormat(cellContent.ColumnWidthFraction*usablePageWidth, maxHeight,
cellContent.Contents, "1", 0, "L", false, 0, "")
}
pdf.Ln(-1)
}
Do you think, if I flesh it out and fix it a little, this might be merged into the library?
Definitely! Thanks, @sk0g.
Of course, an example demonstrating it is always helpful.