Aspose.Cells.Drawing.TextBox.CalculateTextSize 的原理是什么?为什么示例文件中文本框的文本已溢出,而CalculateTextSize缺小于文本框高度?

CalculateTextSizeTest.zip (86.1 KB)

public static void testHeight()
{

 // Create a new workbook and save with different DPI settings
 Workbook workbook = new Workbook("D:\\CalculateTextSizeTest.xlsm");
 Worksheet sheet = workbook.Worksheets["产品销售情况"];

 foreach (Shape shape in sheet.Shapes)
 {
     // 判断形状是否为文本框
     if (shape is Aspose.Cells.Drawing.TextBox)
     {
         Aspose.Cells.Drawing.TextBox textBox = (Aspose.Cells.Drawing.TextBox)shape;

         // 判断文本框的名称是否以"批注文本框"开头
         if (textBox.Name.StartsWith("批注文本框"))
         {
             // 获取文本框的高度
             double textBoxHeight = textBox.Height;

             Console.WriteLine("count" + textBox.TextBody.TextParagraphs.Count);


             Console.WriteLine(textBox.Text);

             int[] estimatedTextHeight = textBox.CalculateTextSize();
             Console.WriteLine(estimatedTextHeight[1]);

             // 检查是否溢出
             if (estimatedTextHeight[1] > textBoxHeight)
             {
                 throw new OverflowException(
                     $"{sheet.Name}在第{textBox.Top}行,第{textBox.Left}列的文本框内容溢出,请调整内容!"
                 );
             }

         }
     }
 }

}

@lingtian

CalculateTextSize 的工作原理
TextBox.CalculateTextSize() 在内部调用 Aspose.Cells 的文字排版引擎,根据文本的字体、字号、字符间距以及当前工作表的 DPI(默认 96)来计算 单行文本 所占的宽度和高度,返回 int[2][width, height])。

为什么示例中文本会溢出而返回的高度却小于文本框高度

从论坛的反馈可以看到:

  • 当文本中包含换行符(\r\n\n)时,CalculateTextSize() 只返回 默认单行高度,不再根据实际的多行布局进行累计。
  • 该问题在 8.9.x 及以后版本中仍然存在,属于 回归 bug(8.6.2 版本可以正确计算多行高度)。

因此,在您提供的 CalculateTextSizeTest.xlsm 中,文本框里的内容是多行的,实际占用的高度远大于单行高度;CalculateTextSize() 只给出了单行的高度值,导致判断为 “未溢出”,实际却已经超出文本框。

临时解决方案(不依赖 CalculateTextSize)

  1. 手动计算行高

    // 每行的高度 = 字体大小(pt) * 1.33(约等于像素) + 行间距(如果有)
    double lineHeight = textBox.Font.Size * 1.33;
    int lineCount = textBox.TextBody.TextParagraphs.Count;   // 或自行统计 \n 的数量 + 1
    double estimatedHeight = lineHeight * lineCount;
    
  2. 去掉换行符后再调用(仅在业务允许的情况下)

    string singleLine = textBox.Text.Replace("\r", "").Replace("\n", " ");
    textBox.Text = singleLine;
    int[] size = textBox.CalculateTextSize();   // 现在返回的高度会更接近实际
    
  3. 使用 AutoFit(如果只是想让文本框自适应)

    textBox.AutoFit = true;   // 让 Aspose.Cells 自动调整文本框大小
    
  4. 升级或等待修复

    • 确认使用的 Aspose.Cells 版本。如果是 8.9.x 系列,建议向 Aspose 官方提交 Bug 报告(附上示例文件和复现代码),并关注后续版本的修复说明。
    • 若可以接受使用更高的版本(如 23.x+),先在测试环境中验证是否已修复,再决定是否升级。

诊断信息建议提供给 Aspose 支持

项目 内容
Aspose.Cells 版本 例如 8.9.0、8.9.0.5、23.9 等
操作系统 & .NET 运行时 Windows 10, .NET Framework 4.8 / .NET 6 等
示例文件 CalculateTextSizeTest.xlsm(已上传)
复现代码 您提供的 testHeight() 方法
观察到的现象 多行文本实际溢出,CalculateTextSize()[1] 只返回单行高度
期望行为 返回累计的多行高度,或能够检测到溢出

提供上述信息后,Aspose 支持团队可以更快定位并在后续版本中修复此问题。祝您调试顺利!

@lingtian,

感谢提供模板Excel文件。

很抱歉,目前尚无精确的方法来确定确切的高度和宽度,因为文本方向、文本对齐方式以及是否启用了自动换行功能都会影响实际或原始值。无论如何,我使用您的示例文件和代码片段测试了您的场景/案例。发现当CalculateTextSize小于文本框高度时,文本确实如您所述发生了溢出现象。

我们需要对该问题进行深入评估。我们已在内部问题跟踪系统中创建了以下新工单,并将根据Free Support Policies中提到的条款提供修复。

问题ID:CELLSNET-59486

如果您需要优先支持服务以及直接访问我们的付费支持管理团队,可通过Paid Support Services获取相关支持。

@amjad.sahi
使用Microsoft.Office.Interop.Excel,以下代码可以比较准确的判断文本框中文字高度,供参考。

    internal static void CheckTextBoxOverllow(Excel.Worksheet sht, List<string> listErrors)
    {

        foreach (var txtBox in sht.Shapes.OfType<Excel.Shape>().Where(s => s.Name.StartsWith("批注文本框")))
        {

            //批注文本框内容的高度和批注文本框高度比较,需要剔除上下边缘的留边大小,使用TrimText方法,可以得到清除末尾空格回车字符,不清除头部,实现了忽略末尾多余的空白字符。
            var txtRangeTrim = txtBox.TextFrame2.TextRange.TrimText();
            if (!string.IsNullOrEmpty(txtRangeTrim.Text) &&
                Math.Floor(txtBox.Height - txtBox.TextFrame2.MarginTop - txtBox.TextFrame2.MarginBottom )  < txtBox.TextFrame2.TextRange.TrimText().BoundHeight)
            {
                var txtBoxRange = sht.Range[txtBox.TopLeftCell, txtBox.BottomRightCell];
                listErrors.Add($"工作表:{sht.Name},文本框位置:{txtBoxRange.Address[false, false]}");
            }
        }
    }

@lingtian
感谢你的反馈和提供的Microsoft.Office.Interop.Excel文字宽高计算信息。让我们详细调查和分析您的问题。一旦有任何更新,我们将及时通知你。