获取单元格占用的行数Itextsharp

时间:2017-04-28 14:43:59

标签: c# pdf itext

大家。

我想知道是否有一种方法可以准确地获取某个单元格占用的行。

目前我正在使用ff这样做。功能:

private int GetRowLines(string content, float maxFloatPerRow)
{
    if (string.IsNullOrEmpty(content))
        content = string.Empty;

    float noteFwidth = BaseFont.GetWidthPoint(content, cellFont.Size);

    int nextRowLines = 0;
    var test = noteFwidth / maxFloatPerRow;
    nextRowLines = (int)Math.Ceiling(test);

    return nextRowLines == 0 ? 1 : nextRowLines;
}

唯一的问题是我需要提供maxFloatPerRow,这只能通过反复试验来完成。

  
      
  1. 我想要测试的特定单元格中生成了大量"i"的pdf。
  2.   
  3. 然后我将该单元格上的所有内容复制为1行(这将是该单元格的一行中的最大字符数。)
  4.   
  5. 获取"每行最大内容的浮动宽度"使用BaseFont.GetWidthPoint方法。
  6.   

但是,我想创建一个实用程序方法,它将为我提供内容占用的行数,前提是标题的Fwidth,内容的字体和内容本身。如果需要,可以提供更多。

根据评论

编辑

我正在使用itext v.3.1.7.0而我正在创建一个pdf,而不是编辑现有的。

我希望你们有分享的东西。感谢。

2 个答案:

答案 0 :(得分:3)

有几种选择。我只描述两个最简单的解决方案的高级别点

方法1

使用pdf2Data(它是一个iText7附加组件),它能够将pdf文档转换为xml数据(给定文档匹配的模板)。这个附加组件仅适用于iText7,因此需要一些迁移工作。

方法2

  1. 使用EventListener从目标页面收集所有线条绘制事件。
  2. 获得所有线条渲染信息后,将其聚类,将线条放在同一个簇中,当且仅当它们以大约90度角相交时
  3. 检查每个群集,包含特定阈值线的群集可以被视为一个表
  4. 对所有水平线进行垂直投影,这会告诉您有多少行(总共在整个表格中)
  5. 对所有垂直线进行水平投影,这会告诉您有多少列(总共在整个表格中)
  6. 现在您已拥有每个单元格的边界,您可以对表格中的每个子坐标范围重复步骤4和5,以确切了解该坐标范围内的行数/列数。

答案 1 :(得分:2)

经过几天的实验,这是我到目前为止的解决方法,这似乎足够准确:

    /// <summary>
    /// Gets number of rows this cell occupies.
    /// </summary>
    /// <param name="headerFwidths">The fwidths of the headers of the table this cell belongs to</param>
    /// <param name="index">The column index of the cell to check</param>
    /// <param name="cCell">The cell to check</param>
    /// <returns>int the number of rows</returns>
    public int GetRowLines(float[] headerFwidths, int index, CellValue cCell) {
        float tableWidth = Document.GetRight(Document.LeftMargin);
        float lPad = cCell.PaddingLeft != null ? cCell.PaddingLeft.Value : 2f;
        float rPad = cCell.PaddingRight != null ? cCell.PaddingRight.Value : 2f;
        float maxFloatPerRow = ((tableWidth / headerFwidths.Sum()) * headerFwidths[index]) - (lPad + rPad);
        string content = string.IsNullOrEmpty(cCell.Title) ? string.Empty : cCell.Title;

        int rowLines = 0;
        float cellFontWidth = BaseFont.GetWidthPoint(content, cCell.CellFont.Size);
        rowLines = (int)Math.Ceiling(cellFontWidth / maxFloatPerRow);
        return rowLines == 0 ? 1 : rowLines;
    }

所以这是它的工作原理:

首先,您获得表标题的float[] fWidths,因为单元格基本上遵循其标题的fwidth

然后,使用Document.GetRight(Document.LeftMargin)获得文档的宽度。

下一步,是要检查CellValue的填充。

注意CellValue是我们的自定义类,它派生自PdfPCell类iTextSharp。

因此,使用表格宽度,单元格填充和标题宽度,我们可以估计maxFloatPerRow

float maxFloatPerRow = ((tableWidth / headerFwidths.Sum()) * headerFwidths[index]) - (lPad + rPad);

我们可以使用cellFontWidth获取单元格BaseFont.GetWidthPoint的浮点值。

最后,我们将cellFontWidthmaxFloatPerRow分开,得到单元格占用的行数。

这可能不是100%准确,但到目前为止这适用于我们的情况。

我希望这可以帮助任何与我情况相同的人。 (我接受这个作为答案。但是如果你有更好的答案,请随时发帖。如果证明更好,我会乐意接受你的答案。)