How to format a String resulting in a two-column display?

Tags: tablestabsmonospaced fontiText 7

I'm trying to print in PDF two columns of information that contain some strings that the user inputs. This is my code so far:

string s = "";
int width = 60 - name.Count(Char.IsWhiteSpace);                                                                  
s = s + string.Format("{0,-" + width +"}", "Name: " + name);
s = s + string.Format("{0,15}","AAA: ");
p1.Add(s);
document.Add(p1);
 
string p = "";
int width = 60 - surname.Count(Char.IsWhiteSpace);                                                                 
p = p + string.Format("{0,-"+ width +"}", "Surname: " + surname);
p = p + string.Format("{0,15}","BBB: ");
p2.Add(p);
document.Add(p2);
 
string r = ""; 
int width = 60 - school.Count(Char.IsWhiteSpace);                                                       
r = r + string.Format("{0,-"+ width +"}", "School: " + school);
r = r + string.Format("{0,15}","CCC: ");
p3.Add(r);
document.Add(p3);
If the user enters, for example, "John Edward Jr." for name, "Pascal Einstein W. Alfi" for surname and "St. John" for school, then the expected output is something like this:

Name: John Edward Jr.________________AAA:
Surname: Pascal Einstein W. Alfi_______BBB:
School: St. John___________________CCC:
I suppose the spaces in every string name, surname and school are the problem. How can I deal with this?

EXPECTED OUTPUT:

Name: John Edward Jr.__________________AAA:
Surname: Pascal Einstein W. Alfi_______BBB:
School: St. John_______________________CCC:
EDIT:

int width = 60 - name.Count(Char.IsWhiteSpace);
Question posted on StackOverflow on Dec 27, 2015 by PeMaCN

Suppose that we want to render this data in tabular format:

public static final String[][] DATA = {
    {"John Edward Jr.", "AAA"},
    {"Pascal Einstein W. Alfi", "BBB"},
    {"St. John", "CCC"}
};

There are three ways to achieve this using iText.

Solution #1: use a table

Please take a look at the SimpleTable13 example:

protected void manipulatePdf(String dest) throws Exception {
    PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
    Document doc = new Document(pdfDoc);
    Table table = new Table(new float[]{5, 1});
    table.setWidthPercent(50);
    table.setTextAlignment(TextAlignment.LEFT);
    table.addCell(new Cell().add("Name: " + DATA[0][0]).setBorder(Border.NO_BORDER));
    table.addCell(new Cell().add(DATA[0][1]).setBorder(Border.NO_BORDER));
    table.addCell(new Cell().add("Surname: " + DATA[1][0]).setBorder(Border.NO_BORDER));
    table.addCell(new Cell().add(DATA[1][1]).setBorder(Border.NO_BORDER));
    table.addCell(new Cell().add("School: " + DATA[2][0]).setBorder(Border.NO_BORDER));
    table.addCell(new Cell().add(DATA[1][1]).setBorder(Border.NO_BORDER));
    doc.add(table);
    doc.close();
}

We create a table with 2 columns and we add 6 cells. This will result in a table with 2 columns and 3 rows. As we removed the border and as we told the table that the first column should be 5 times as wide as the second column, the result looks like this:

Using a PdfPTable
Using a PdfPTable

Advantage: should there be too much text in one of the cells, then the content will automatically wrap and the size of the table will adapt to accommodate the content.

Note that we use Table and Cell classes in iText 7, not PdfPTable and PdfPCell.

Solution #2: use tabs

Please take a look at the TableTab example:

protected void manipulatePdf(String dest) throws Exception {
    PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
    Document doc = new Document(pdfDoc);
    doc.add(createParagraphWithTab("Name: ", DATA[0][0], DATA[0][1]));
    doc.add(createParagraphWithTab("Surname: ", DATA[1][0], DATA[1][1]));
    doc.add(createParagraphWithTab("School: ", DATA[2][0], DATA[2][1]));
    doc.close();
}
 
public Paragraph createParagraphWithTab(String key, String value1, String value2) {
    Paragraph p = new Paragraph();
    p.addTabStops(new TabStop(200f, TabAlignment.LEFT));
    p.add(key);
    p.add(value1);
    p.add(new Tab());
    p.add(value2);
    return p;
}

In this example, we create a paragraph for which we define tabs of 200 user units. Now when we add a new Tab(), the content will jump to that position. The result looks like this:

Using tabs
Using tabs

Disadvantage: when there is too much text in the first column, that text will run into the second column, and a tab will be added at the next 200 user units (could be on the same line, could be on the next line).

Solution #3: use spaces and a monospaced font

This is what you're doing, except that you don't use a monospaced font which doesn't give you the result you want.

Please take a look at the TableSpace example:

protected void manipulatePdf(String dest) throws Exception {
    PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
    Document doc = new Document(pdfDoc);
    PdfFont font = PdfFontFactory.createFont(FONT, PdfEncodings.CP1250, true);
    doc.add(createParagraphWithSpaces(font, String.format("%s: %s", "Name", DATA[0][0]), DATA[0][1]));
    doc.add(createParagraphWithSpaces(font, String.format("%s: %s", "Surname", DATA[1][0]), DATA[1][1]));
    doc.add(createParagraphWithSpaces(font, String.format("%s: %s", "School", DATA[2][0]), DATA[2][1]));
    doc.close();
}
 
public Paragraph createParagraphWithSpaces(PdfFont font, String value1, String value2) {
    Paragraph p = new Paragraph();
    p.setFont(font);
    p.add(String.format("%-35s", value1));
    p.add(value2);
    return p;
}

Now we format the first String so that it always measures 35 characters. The result looks like this:

Using spaces
Using spaces

Disadvantages: if the text in the first column needs more than 35 characters, it will run through the second column and the text of the second column will be glued to it. You also see that I needed to use a different font. I use PTMono-Regular. Usually, text in a monospaced font takes more space than text in a proportional font.

Click this link if you want to see how to answer this question in iText 5.