如何垂直添加单元格

本文关键字:添加 单元格 垂直 何垂直 | 更新日期: 2023-09-27 18:15:46

这里我们有一个需求。在表格中,我们需要垂直地添加单元格。例如,一个表可能是这样的:

Name Age   Name Age
Jim  11    Lily 9
Lucy 8     Tom  6
Lile 12
Leo  13

首先,它将添加第一列中的单元格,当第一列已满时,它将添加第二列中的单元格。所有的数据都来自字典。

是否有一个简单的方法来添加单元格垂直?否则,我必须水平添加单元格,而从字典中获取数据则是按照计算顺序来实现的。

如何垂直添加单元格

您要查找的是ColumnText类。

在iText网站上有很多例子,例如这个。

这些例子是用Java写的,但是"翻译"到c#应该很简单。

我只是想用一些特定于c#的代码来详细说明@Alexis-Pigeon的回答。(另外,c#版本的ittext似乎缺少ColumnText.START_COLUMN常量,该常量应该设置为零。)

下面的代码将文本从上到下,然后从左到右(而不是普通的表格从左到右,从上到下)放置到多个列中。它没有硬编码表的尺寸,而是根据文档的页边距、需要多少列以及列之间的行距来计算表的位置。后两者可以通过向上改变columnCountgutterWidth的性质来改变。

非常重要的是,这个将不会创建表格单元格从上到下,从左到右,以便所有内容完美排列。相反,这将绘制任意文本,当底部无法容纳它时,它将在下一列重新开始。这可能发生在段落中间。下面的代码恰好对齐得很好,但这是因为文本受到了控制。如果你把gutter50改为20,你会看到它是如何奇怪地分解的。

具体细节见代码注释

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();
        }
    }
}