来自Spreadsheetgear和Excel的RowHeight异常

时间:2014-06-09 21:47:40

标签: c# excel vba excel-vba spreadsheetgear

我正在使用Spreadsheetgear以编程方式制作excel,我有一个与行高有关的问题。

我在C#中有这个代码段

cells[0, 0].ColumnWidth = totalColumnWidth; // recalculated column width after some formatting logic
var x = cells[0, 0].RowHeight; // gives me 14.95
cells[0, 0].Formula = "A long long text goes here spanning multiple lines..."; // spanning say 10 rows in excel
x = cells[0, 0].RowHeight; // gives me 190.5

当我保存这个excel并在MS Excel中打开它时,我可以看到行高为210.

对于空的Excel工作表,我从电子表格中获得行高14.95,从excel获得15行。 我也分别得到8.09和8.43的列宽。

我的问题是 - 为什么这两个数字之间存在差异?在处理这些时,我应该考虑某种软糖因素吗?谢谢!

2 个答案:

答案 0 :(得分:1)

除非您明确指定某行的高度值(以磅为单位),否则将根据工作簿的默认字体高度自动确定行高(请参阅IWorkbook.Styles [“Normal”]。字体)。< / p>

相关地,列宽以“字符单位”测量。字符单位不是绝对的计量单位;它们还依赖于工作簿的默认字体。这就是为列宽指定值8的原因。 “字符单元”大致等于使用工作簿的默认字体的“0”字符的宽度。请注意,在此之上添加了一些填充,因此您的实际列宽仍将略宽于8个字符。

对于自动行高和列宽,SpreadsheetGear与Excel的单位不完全匹配,因为SpreadsheetGear依赖于GDI + / WPF / Silverlight图形库来测量字体的高度和“字符单位”值,而Excel使用本机GDI来测量这些值的东西。不幸的是,每个库计算相同给定文本的结果略有不同,因此您将在列宽和自动行高度上略有不同。除非SpreadsheetGear在与Excel完全相同的环境中运行(即使用GDI),否则这些差异是不可避免的。

在SpreadsheetGear中自动填充列时,通常会出现此问题。虽然具有AutoFitted文本的工作簿将在我们自己的WorkbookView控件中正常呈现,但将工作簿保存到磁盘然后在Excel中打开生成的工作簿通常会导致列太短。柱宽越宽,变得越明显。因此,在Excel中查看工作簿时,客户通常需要添加一个轻微的“软糖因子”来获得预期的结果。

行高可以手动设置,以磅为单位。因此,如果您不介意手动设置根本不会改变的行高,尽管有单元格的内容,您可以考虑明确地将行设置为适合Excel和SpreadsheetGear的高度。

实际上,在使用我们的WorkbookView控件时,由于我们使用了更可靠的字体指标,因此在很多情况下,您会发现SpreadsheetGear与Excel本身更为一致。即使在Excel本身内自动调整而不使用SpreadsheetGear,也可以通过保存然后在具有不同屏幕DPI(96/120 / etc ...)的机器上加载来发生列宽差异。另一个例子,尝试在Excel 2007/2010/2013中输入一个非常长的文本字符串到单元格中,自动调整文本,然后使用右下角的滑块工具放大或缩小,注意文本可能没有适合某些设置(它适合某些文本,但很少见)。 SpreadsheetGear中不会发生这种不一致的行为。

答案 1 :(得分:0)

我没有批评蒂姆的回答,我试图将其作为第一个答案。我同意他关于Excel不一致的评论,他对SpreadsheetGear的评论显然是具有说服力的。这个答案是额外的信息,如果你决定需要一个软糖因子,这可能是有用的。

在Excel中,如果将鼠标悬停在行边界上,您会看到行高为12.75 (17 pixels)19.5 (26 pixels)或类似内容。我尝试手动调整行高并更改默认字体和/或大小。我找不到points * 4/3 = pixels不为真的任何行高。

将鼠标悬停在列边界上会显示不同的值,例如8.43 (64 points)11.52 (86 pixels)。点和像素值之间的关系是不同的,但似乎仍然是固定的。下面的例程给出了从像素到点的转换,这些转换对于我尝试过的每个值都是正确的。例程是用VB.Net编写的,但如果你感兴趣的话,它将很容易转换为C#。

Private Shared Function pixelsToPoints(ByVal pixels As Integer) As Double

  ' Converts a column width in pixels to points.

  '  Pixels   Points
  '       0      0.0
  ' 0<=N<12      points1(N)
  '      12      1.0
  '      19      2.0
  '      26      3.0
  '   N>=12      (N - 12) Mod 7 + 1 + points2((N - 12) \ 7)  

  ' Point increments between pixel = 2 and pixels = 11 
  Dim points1() As Double = {0.0, 0.08, 0.17, 0.25, 0.33, 0.42, 0.5, 0.58, 0.67, 0.75, 0.83, 0.92}
  ' Point increments above pixels = 12 
  Dim points2() As Double = {0.0, 0.14, 0.29, 0.43, 0.57, 0.71, 0.86}

  Select Case pixels
    Case Is < 12
      Return points1(pixels)
      Exit Function
    Case Is >= 12
      Dim pixelsTemp As Integer = pixels - 12
      Dim pointsTemp As Double = 1.0
      pointsTemp += (pixelsTemp) \ 7 + points2(pixelsTemp Mod 7)
      Return pointsTemp
      Exit Function
  End Select

  Return 0.0      ' Required to avoid warning

End Function