
Hi folks,
we have a requirement for a PDF that we must draw a table with different columns counts and sizes. Our approach is to generate a defined number of cells in a row (18) and merge them appropriately as we need them. Find a test below.
void AddSecondTable(RadFixedPage page)
{
var blackBorder = new Border(1, new RgbColor(0, 0, 0));
var editor = new FixedContentEditor(page);
editor.Position.Translate(Unit.CmToDip(2), Unit.CmToDip(2));
var table = new Table
{
LayoutType = TableLayoutType.AutoFit,
DefaultCellProperties =
{
Padding = new Thickness(5, 5, 5, 5),
Borders = new TableCellBorders(blackBorder, blackBorder, blackBorder, blackBorder)
}
};
for (var rowIndex = 0; rowIndex < 10; rowIndex++)
{
var row = table.Rows.AddTableRow();
for (var cellIndex = 0; cellIndex < 18; cellIndex++)
{
var cell = row.Cells.AddTableCell();
cell.PreferredWidth = Unit.CmToDip(1);
var b = cell.Blocks.AddBlock();
b.InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, $"Cell: {cellIndex}");
}
var firstCell = row.Cells[0];
firstCell.ColumnSpan = 4;
}
editor.DrawTable(table, Unit.CmToDip(18));
}
We expect that the first cell be placed over the first four columns, but nothing happens at all. What do we miss here?
Further, we would expect that the next cell starts with cellIndex 4, as the first four (0-3) are “merged”.
1 Answer, 1 is accepted
Hello, Patrick,
Following the provided information, I have prepared a sample code snippet for your reference which I believe would be useful for understanding how the tables work in the PdfProcessing library:
RadFixedDocument fixedDocument = new RadFixedDocument();
RadFixedPage page = new RadFixedPage();
page.Size = new Size(1200, 800);
fixedDocument.Pages.Add(page);
Border blackBorder = new Border(1, new RgbColor(0, 0, 0));
FixedContentEditor editor = new FixedContentEditor(page);
editor.Position.Translate(Unit.CmToDip(2), Unit.CmToDip(2));
Table table = new Table
{
LayoutType = TableLayoutType.AutoFit,
DefaultCellProperties =
{
Padding = new Thickness(5, 5, 5, 5),
Borders = new TableCellBorders(blackBorder, blackBorder, blackBorder, blackBorder)
}
};
int colSpanValue = 4;
int columnSpanStartIndex = 2;
List<int> rowIndexWithMergedColumnsCollection = new List<int> { 0, 2, 3 };
int tableRowsCount = 5;
int tableColumnsCount = 10;
table.DefaultCellProperties.Background = new RgbColor(220, 220, 220);
for (var rowIndex = 0; rowIndex < tableRowsCount; rowIndex++)
{
Telerik.Windows.Documents.Fixed.Model.Editing.Tables.TableRow row = table.Rows.AddTableRow();
int colLimit = tableColumnsCount;
if (rowIndexWithMergedColumnsCollection.Contains(rowIndex))
{
//insert less text blocks when you have cells spanning among several columns
colLimit = tableColumnsCount - colSpanValue + 1;
}
for (var columnIndex = 0; columnIndex < colLimit; columnIndex++)
{
Telerik.Windows.Documents.Fixed.Model.Editing.Tables.TableCell cell = row.Cells.AddTableCell();
Block b = cell.Blocks.AddBlock();
string cellText = "Cell: " + rowIndex + "." + columnIndex;
if (columnSpanStartIndex<columnIndex && rowIndexWithMergedColumnsCollection.Contains(rowIndex))
{
cellText= "Cell: " + rowIndex + "." + (columnIndex+ colSpanValue-1);
}
b.InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, cellText);
if (rowIndexWithMergedColumnsCollection.Contains(rowIndex) && columnIndex == columnSpanStartIndex)
{
cell.RowSpan = 1;
cell.ColumnSpan = colSpanValue;
cell.Background = new RgbColor(255, 153, 0);
}
}
}
editor.DrawTable(table);
string outputFilePath = "sample.pdf";
File.Delete(outputFilePath);
PdfFormatProvider provider = new PdfFormatProvider();
using (Stream output = File.OpenWrite(outputFilePath))
{
provider.Export(fixedDocument, output);
}
Process.Start(new ProcessStartInfo() { FileName = outputFilePath, UseShellExecute = true });
I would like to pay attention to two important things:
1. The rows which contain cells with ColumnSpan should contain less text blocks, e.g. if ColumnSpan=4, you need to insert 4 text blocks less for this row. Hence, skip adding the text block for the cells participating in the ColumnSpan functionality, e.g. Cell: 0, 3 ; Cell: 0,4 ; Cell: 0, 5.
2. At least one row should contain the cells participating in the columnSpan for the other cells. If all rows contain cells which span the columns from index 2 to index 5, you wouldn't need the column span functionality. You will just need a wider column to fit the content.
It would be greatly appreciated if you can share with us what table exactly you need to build in the PDF document. Once we get better understanding of the precise case, we would be able to think about an appropriate solution and provide further assistance. Thank you in advance.
I am sharing with you another example which is more simplified for the sake of the example and understanding the idea behind the column spanning:
public static Telerik.Windows.Documents.Fixed.Model.Editing.Tables.Table GenerateSimpleTable()
{
Telerik.Windows.Documents.Fixed.Model.Editing.Tables.Table table = new Telerik.Windows.Documents.Fixed.Model.Editing.Tables.Table();
table.DefaultCellProperties.Background = new RgbColor(220, 220, 220);
string[][] tableValues = new string[][]
{
new string[] { "cell11", "cell12-cell23", "cell14" },
new string[] { "cell21", "cell24"},
new string[] { "cell31", "cell32", "cell33", "cell34"}
};
for (int rowIndex = 0; rowIndex < tableValues.Length; rowIndex++)
{
Telerik.Windows.Documents.Fixed.Model.Editing.Tables.TableRow row = table.Rows.AddTableRow();
string[] rowValues = tableValues[rowIndex];
for (int columnIndex = 0; columnIndex < rowValues.Length; columnIndex++)
{
Telerik.Windows.Documents.Fixed.Model.Editing.Tables.TableCell cell = row.Cells.AddTableCell();
Block block = new Block();
block.InsertText(tableValues[rowIndex][columnIndex]);
cell.Blocks.Add(block);
if (rowIndex == 0 && columnIndex == 1)
{
cell.RowSpan = 2;
cell.ColumnSpan = 2;
cell.Background = new RgbColor(255, 153, 0);
}
}
}
return table;
}
I hope you find this information helpful. Please, let me know if there is anything else I can assist you with.
Regards,
Dess | Tech Support Engineer, Principal
Progress Telerik
Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.
Thank you very much for your comprehensive answer.
To get a better idea of what we need is to look at the template below. As you can see, we have multiple rows with a different column layout and different row heights. Is this even possible with a Table?
Hi, Patrick,
For a better understanding, I have divided the table columns with the red lines:
This is the code snippet I prepared for achieving the below results:
private static Table GenerateClientTable()
{
Border blackBorder = new Border(1, new RgbColor(0, 0, 0));
Table table = new Table
{
LayoutType = TableLayoutType.AutoFit,
DefaultCellProperties =
{
Padding = new Thickness(5, 5, 5, 5),
Borders = new TableCellBorders(blackBorder, blackBorder, blackBorder, blackBorder)
}
};
TableRow row = table.Rows.AddTableRow();
TableCell cell = row.Cells.AddTableCell();
cell.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Truck-Reference");
cell.ColumnSpan = 5;
TableCell cell2 = row.Cells.AddTableCell();
cell2.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Date:");
cell2.ColumnSpan = 2;
TableRow row2 = table.Rows.AddTableRow();
TableCell cell3 = row2.Cells.AddTableCell();
cell3.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Appointment:");
cell3.ColumnSpan = 7;
TableRow row3 = table.Rows.AddTableRow();
TableCell cell4 = row3.Cells.AddTableCell();
cell4.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "CtrNr.:");
cell4.ColumnSpan = 2;
TableCell cell5 = row3.Cells.AddTableCell();
cell5.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Type:");
cell5.ColumnSpan = 2;
TableCell cell6 = row3.Cells.AddTableCell();
cell6.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Tara(kg):");
cell6.ColumnSpan = 2;
TableCell cell7 = row3.Cells.AddTableCell();
cell7.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Net(kg):");
cell7.ColumnSpan = 1;
TableRow row4 = table.Rows.AddTableRow();
TableCell cell8 = row4.Cells.AddTableCell();
cell8.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Content:");
cell8.ColumnSpan = 7;
TableRow row5 = table.Rows.AddTableRow();
TableCell cell9 = row5.Cells.AddTableCell();
cell9.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "License Truck:");
cell9.ColumnSpan = 3;
TableCell cell10 = row5.Cells.AddTableCell();
cell10.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Trailer:");
cell10.ColumnSpan = 4;
TableRow row6 = table.Rows.AddTableRow();
TableCell cell11 = row6.Cells.AddTableCell();
cell11.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Full Cont.:");
cell11.ColumnSpan = 7;
TableRow row7 = table.Rows.AddTableRow();
TableCell cell12 = row7.Cells.AddTableCell();
cell12.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Depot:");
cell12.ColumnSpan = 3;
TableCell cell13 = row7.Cells.AddTableCell();
cell13.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Available:");
cell13.ColumnSpan = 4;
TableRow row8 = table.Rows.AddTableRow();
TableCell cell14 = row8.Cells.AddTableCell();
cell14.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Loadingplace:");
cell14.ColumnSpan = 7;
TableRow row9 = table.Rows.AddTableRow();
TableCell cell15 = row9.Cells.AddTableCell();
cell15.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Reference:");
cell15.ColumnSpan = 3;
TableCell cell16 = row9.Cells.AddTableCell();
cell16.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Origin:");
cell16.ColumnSpan = 4;
TableRow row10 = table.Rows.AddTableRow();
TableCell cell17 = row10.Cells.AddTableCell();
cell17.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Info Driver:");
cell17.ColumnSpan = 7;
TableRow row11 = table.Rows.AddTableRow();
TableCell cell18 = row11.Cells.AddTableCell();
cell18.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Remarks:");
cell18.ColumnSpan = 7;
TableRow row12 = table.Rows.AddTableRow();
TableCell cell19 = row12.Cells.AddTableCell();
cell19.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Customs:");
cell19.ColumnSpan = 1;
TableCell cell20 = row12.Cells.AddTableCell();
cell20.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Procedure:");
cell20.ColumnSpan = 4;
TableCell cell21 = row12.Cells.AddTableCell();
cell21.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Info:");
cell21.ColumnSpan = 2;
TableRow row13 = table.Rows.AddTableRow();
TableCell cell22 = row13.Cells.AddTableCell();
cell22.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Arrical/Date/Time:");
cell22.ColumnSpan = 1;
TableCell cell23 = row13.Cells.AddTableCell();
cell23.Blocks.AddBlock().InsertText(new FontFamily("Helvetica"), FontStyles.Normal, FontWeights.Normal, "Date/Stamp/Signature:");
cell23.ColumnSpan = 6;
return table;
}
Feel free to further extend the sample code and manipulate it in a way to achieve the scenario you need to cover.
Hi Dess,
That looks pretty wonderful already, thank you!
Just one more question, how would we achieve a larger row height, like in our example in the previous comment on the last row?
Hi Patrick,
My name is Yoan and I am also from the Document Processing team. Dess is currently unavailable so I will be taking over for her for the time being.
Please accept my apologies for the inconvenience but currently, the library does not support setting the height of a table row. We already have a feature request about this functionality logged in our Feedback Portal - PdfProcessing: Implement option for setting height to table rows. If you are interested please feel free to cast your vote for it in order to increase its priority in our backlog and to subscribe so you get notified about potential status changes in the future.
As a workaround, I can suggest you use the same functionality provided by Dess and use multiple rows to make it look like one big row:
Let me know if you have any further questions or feedback. I remain at your disposal in the meantime.
Regards,
Yoan
Setting the ColumnSpan directly on the table (outside the for loop) generates something rather strange results.