Reputation: 593
Here we have a requirment. In a table, we need to add cells vertically. For example, a table may be like this.
Name Age Name Age
Jim 11 Lily 9
Lucy 8 Tom 6
Lile 12
Leo 13
Firstly, it will add cells in the first column, when the first column is full, it will then add cells in the second column. All the data is from a dictionary.
Is there a simply way to add cells vertically? Otherwise, I have to add cells horizontally, but get data from dictionary by calculated order to achieve this goal.
Upvotes: 3
Views: 423
Reputation: 55427
I just wanted to elaborate on @Alexis-Pigeon's answer with some code specific to C#. (Also, the C# port of iText appears to be missing the ColumnText.START_COLUMN
constant which should be set to zero.)
The code below will lay text out into multiple columns top to bottom and then left to right (instead of a normal table which it left to right, top to bottom). Instead of hard-coding the table's dimensions it also calculates the table's location based on the document's margins as well as how many columns are desired and the gutter between columns. The latter two can be changed by changing the columnCount
and gutterWidth
properties towards the top.
Very important, this will not create table cells top to bottom left to right so that everything lines up perfectly. Instead, this will draw arbitrary text and when it can't fit at the bottom it will start over in the next column. This could happen right in the middle of paragraph. The code below just happens to line up perfectly but that's because the text is controlled. If you change the gutter
from 50
to 20
you'll see how it breaks up weirdly.
See the code comments for specific details.
using (var fs = new FileStream(testFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, fs)) {
doc.Open();
//Number of columns to create
var columnCount = 4;
//Distance be columns
var gutterWidth = 20;
//Setup and calculate some helper variables
//The left-most edge
var tableLeft = doc.LeftMargin;
//The bottom-most edge
var tableBottom = doc.BottomMargin;
//The available width and height of the table taking into account the document's margins
var tableWidth = doc.PageSize.Width - (doc.LeftMargin + doc.RightMargin);
var tableHeight = doc.PageSize.Height - (doc.TopMargin + doc.BottomMargin);
//The width of a column taking into account the gutters (three columns have two gutters total)
var columnWidth = (tableWidth - (gutterWidth * (columnCount - 1))) / columnCount;
//Create an array of columns
var columns = new List<iTextSharp.text.Rectangle>();
//Create one rectangle per column
for (var i = 0; i < columnCount; i++) {
columns.Add(new iTextSharp.text.Rectangle(
tableLeft + (columnWidth * i) + (gutterWidth * i), //Left
tableBottom, //Bottom
tableLeft + (columnWidth * i) + (gutterWidth * i) + columnWidth, //Right
tableBottom + tableHeight //Top
)
);
}
//Create our column text object
var ct = new ColumnText(writer.DirectContent);
//Create and set some placeholder copy
for (var i = 0; i < 100; i++) {
ct.AddText(new Phrase(String.Format("This is cell {0}. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris lorem tortor, condimentum non urna congue, tincidunt viverra elit.", i)));
//Optional but helps to add spacing
ct.AddText(Chunk.NEWLINE);
ct.AddText(Chunk.NEWLINE);
}
//As we draw content below we'll loop through each column defined above
//This holds the current column index that we'll change in the loop
var currentColumnIndex = 0;
//Current status as returned from ct.go()
int status = 0; //START_COLUMN is defined in Java but is currently missing in .Net
//Loop until we've drawn everything
while (ColumnText.HasMoreText(status)) {
//Setup our column
ct.SetSimpleColumn(columns[currentColumnIndex]);
//To be honest, not quite sure how this is used but I think it is related to leading
ct.YLine = columns[currentColumnIndex].Top;
//This actually "draws" the text and will return either 0, NO_MORE_TEXT (1) or NO_MORE_COLUMN(2)
status = ct.Go();
//Increment our current column index
currentColumnIndex += 1;
//If we're out of columns
if (currentColumnIndex > (columns.Count - 1)) {
//Create a new page and reset to the first column
doc.NewPage();
currentColumnIndex = 0;
}
}
doc.Close();
}
}
}
Upvotes: 1
Reputation: 7512
What you are looking for is the ColumnText class.
There are many examples available on the iText website, for example this one.
These examples are in Java, but the "translation" to C# should be straightforward.
Upvotes: 1