【问题标题】:Compute column widths in a HTML-like manner (based on cell contents)以类似 HTML 的方式计算列宽(基于单元格内容)
【发布时间】:2011-03-04 08:50:34
【问题描述】:

我有一个数据网格,我想使用各种(而不是完美的)PHP 转换器/生成器将其导出为 RTF、PDF 等。

我最缺少的是HTML表格根据单元格中字符串的长度自动调整列宽(字符串包含换行符,这会使事情变得有点复杂,因为它们应该被保留)。

我需要一个算法,给定单元格的内容(纯文本)、表格的总宽度和字符的平均宽度,将返回每列的宽度。如果某些东西已经可用,我不想重新发明轮子。

当然,如果字体是可变宽度的,它就不可能是完美的,但近似值就可以了。或者它可能有一个可配置的表格,每个字符都有宽度。

任何提示将不胜感激。

【问题讨论】:

    标签: php algorithm html-table autosize column-width


    【解决方案1】:

    这不是一件容易的事。

    在PHPExcel中,当一个单元格设置为自动宽度时,我们使用gd库的imagettfbbox()函数

    // font size should really be supplied in pixels in GD2,
    // but since GD2 seems to assume 72dpi, pixels and points are the same
    $fontFile = self::getTrueTypeFontFileFromFont($font);
    $textBox = imagettfbbox($font->getSize(), $rotation, $fontFile, $text);
    
    // Get corners positions
    $lowerLeftCornerX  = $textBox[0];
    $lowerLeftCornerY  = $textBox[1];
    $lowerRightCornerX = $textBox[2];
    $lowerRightCornerY = $textBox[3];
    $upperRightCornerX = $textBox[4];
    $upperRightCornerY = $textBox[5];
    $upperLeftCornerX  = $textBox[6];
    $upperLeftCornerY  = $textBox[7];
    
    // Consider the rotation when calculating the width
    $textWidth = max($lowerRightCornerX - $upperLeftCornerX, $upperRightCornerX - $lowerLeftCornerX);
    
    return $textWidth;
    

    但它非常密集,尤其是在处理大型工作表时,因此我们还有一种替代(近似)方法

    // Calculate column width in pixels. We assume fixed glyph width. Result varies with font name and size.
    switch ($fontName) {
        case 'Calibri':
            // value 8.26 was found via interpolation by inspecting real Excel files with Calibri 11 font.
            $columnWidth = (int) (8.26 * PHPExcel_Shared_String::CountCharacters($columnText));
            $columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size
            break;
    
        case 'Arial':
            // value 7 was found via interpolation by inspecting real Excel files with Arial 10 font.
            $columnWidth = (int) (7 * PHPExcel_Shared_String::CountCharacters($columnText));
            $columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size
            break;
    
        case 'Verdana':
            // value 8 was found via interpolation by inspecting real Excel files with Verdana 10 font.
            $columnWidth = (int) (8 * PHPExcel_Shared_String::CountCharacters($columnText));
            $columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size
            break;
    
        default:
            // just assume Calibri
            $columnWidth = (int) (8.26 * PHPExcel_Shared_String::CountCharacters($columnText));
            $columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size
            break;
    }
    
    // Calculate approximate rotated column width
    if ($rotation !== 0) {
        if ($rotation == -165) {
            // stacked text
            $columnWidth = 4; // approximation
        } else {
            // rotated text
            $columnWidth = $columnWidth * cos(deg2rad($rotation))
                            + $fontSize * abs(sin(deg2rad($rotation))) / 5; // approximation
        }
    }
    
    // pixel width is an integer
    $columnWidth = (int) $columnWidth;
    return $columnWidth;
    

    【讨论】:

    • 嗨。我实际上正在使用 PHPExcel(我非常喜欢),但这不是我的问题的一部分,它可以很好地处理自动调整列(除了带有富文本的连接单元格)。我将从您的代码开始,并可能对其进行更新以处理换行符(CountCharacters 函数)和一些启发式方法来包装文本以保持列的总宽度小于页面的宽度(电子表格通常没有这个约束)。谢谢!
    猜你喜欢
    • 2021-03-16
    • 1970-01-01
    • 2015-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    • 2017-06-25
    相关资源
    最近更新 更多