我需要找出一个算法来计算列宽的优化大小,如下所示:
所以给出以下数据:
'From' => '03/06/2014',
'To' => '03/06/2014',
'First Name' => 'John Doe',
'Status' => 'approved',
'Type' => 'PTO',
'Amount' => '8 Hours',
'Notes' => 'Oops! Who knew I would need one more day. This should be all I need over the next week to support my trip.'
如何计算最佳色谱柱宽度,以便“注释”列不会将其他宽度压缩到低于可接受的宽度?
更新:我目前知道网页的宽度&字体的宽度,所以我可以计算每列的最大宽度要求。它应该填充页面上的可用空间。但是,除非必要,否则我希望列不包装。像这样:
答案 0 :(得分:7)
一个简单的解决方案是为您的列分配属性;例如,您的Notes
列可能是flexible
。然后,您可以计算所有行上每列的最大宽度,为所有非灵活列设置该宽度,然后将剩余空间均匀分布(或者可能按其最大宽度加权)到灵活列。
但您也可以尝试使用一些简单的条件找出属性:
然后按照上述说明:计算所有非柔性列的宽度。检查是否有足够的空间;如果没有,也可以使可包装的柱子变得灵活。然后计算柔性单元格的宽度,按其最大宽度加权。
可能的伪代码算法如下。它可以自由地使用各种启发式方法,所以你应该把它当作一粒盐。您可以根据用例调整这些条件,但很难满足所有可能的情况。
function layout(table[], width, gutter, col[])
var maxw[col.length] # max. text width over all rows
var maxl[col.length] # max. width of longest word
var flex[col.length] # is column flexible?
var wrap[col.length] # can column be wrapped?
var colw[col.length] # final width of columns
foreach row in table:
for i = 0 to col.length:
cell = row[i]
maxw[i] = max(maxw[i], textwidth(cell))
if cell.find(" "):
maxl[i] = max(maxl[i], wordwidth(cell))
var left = width - (col.length - 1) * gutter
var avg = left / col.length
var nflex = 0
# determine whether columns should be flexible and assign
# width of non-flexible cells
for i = 0 to col.length:
flex[i] = (maxw[i] > 2 * avg) # ???
if flex[i]:
nflex++
else:
colw[i] = maxw[i]
left -= colw[i]
# if there is not enough space, make columns that could
# be word-wrapped flexible, too
if left < nflex * avg:
for i = 0 to col.length:
if !flex[i] and wrap[i]:
left += width[i]
colw[i] = 0
flex[i] = true
nflex += 1
# Calculate weights for flexible columns. The max width
# is capped at the page width to treat columns that have to
# be wrapped more or less equal
var tot = 0
for i = 0 to col.length:
if flex[i]:
maxw[i] = min(maxw[i], width) # ???
tot += maxw[i]
# Now assign the actual width for flexible columns. Make
# sure that it is at least as long as the longest word length
for i = 0 to col.length:
if flex[i]:
colw[i] = left * maxw[i] / tot
colw[i] = max(colw[i], maxl[i])
left -= colw[i]
return colw
答案 1 :(得分:1)
W3C在CSS 3 Tables Algorithms中发布了类似这样的东西的算法。
我在HTML4.1 specs中找到了一个我已成功使用并且实现起来非常简单的简单算法:
然后使用最小和最大单元格宽度来确定 列的相应最小和最大宽度。这些在 转,用于查找表的最小和最大宽度。 请注意,单元格可以包含嵌套表,但这并不复杂 代码显着。下一步是指定列宽 根据可用空间(即电流之间的空间) 左右边距)。
对于跨越多列的单元格,一种简单的方法包括 将最小/最大宽度均匀地分配给每个成分 列。稍微复杂的方法是使用最小/最大宽度 未扩展的单元格来衡量跨度宽度的分配方式。 实验表明,两种方法的混合可以提供良好的效果 各种表格的结果。
需要包含表格边框和单元间边距 指定列宽。有三种情况:
- 最小表格宽度等于或大于可用空间。在这种情况下,指定最小宽度并允许用户水平滚动。对于转换为盲文,有必要通过引用包含其全部内容的注释来替换单元格。按惯例,这些出现在表格之前。
- 最大表格宽度适合可用空间。在这种情况下,请将列设置为其最大宽度。
- 表的最大宽度大于可用空间,但最小表宽度较小。在这种情况下,找到可用空间和最小工作台宽度之间的差异,让我们称之为W.也可以调用D表格的最大和最小宽度之间的差异。
对于每列,设d为该列的最大和最小宽度之间的差异。现在将列的宽度设置为最小宽度加上D乘以D乘以D.这使得最小和最大宽度之间差异较大的列比差异较小的列宽。
答案 2 :(得分:0)
我使用带有14列表的ITextPDF遇到了与此类似的问题。数据是可变的,其中一些列可以包装,而其他列则不能。
我的解决方案是使用split(“”)找到每列中最大的单词。这减少了单词,日期或数字减半的几率。这是代码。抱歉,我没有时间将其编辑为更通用的格式,希望无论如何它都能帮到某人。
//This array will store the largest word found in each of the 14 columns
int[] maxStringLengthPerColumn = new int[14];
for(int i = 0; i < maxStringLengthPerColumn.length; i++)
maxStringLengthPerColumn[i]=0;
//for each row in table...
ArrayList<PdfPRow> rows = table.getRows();
for(int a = 0; a < rows.size(); a++){
//for each cell in row
PdfPCell[] cellsInRow = rows.get(a).getCells();
for(int b = 0; b < cellsInRow.length; b++){
//Split cell contents at " " and find longest word in each cell
String[] splitCell = cellsInRow[b].getPhrase().getContent().split(" ");
//find the longest string left after split
int largestStringSize = 0;
for(int c = 0; c < splitCell.length; c++){
if(splitCell[c].length()>largestStringSize){
largestStringSize=splitCell[c].length();
}
}
if(largestStringSize>maxStringLengthPerColumn[b]){
//I found that adding 4 to the value worked, change this number to fine tune.
maxStringLengthPerColumn[b] = largestStringSize + 4;
}
}
}
/*The pdf library can set width with just an array, you may need to
convert these values to something else depending on the application. For
example if you have a width of 800 pixels, the width of col1 would be
maxStringLengthPerColumn[0] / (sum of maxString0 - 13) * 800*/
table.setWidths(maxStringLengthPerColumn);