2015-04-05 123 views
13

我想在Python的xlsxwriter中模拟Excel自动填充功能。根据这个URL,它不直接支持: http://xlsxwriter.readthedocs.io/worksheet.html在xslxwriter中模拟自动填充列

但是,它应该是相当简单的循环,通过在纸张上的每个小区确定的最大大小列,只是使用worksheet.set_column(行,列,宽度)来设置宽度。

是不让我只是写这个的并发症是:

  1. 该URL并不指定哪些单位是第三个参数set_column。
  2. 我找不到一种方法来测量我想要插入单元格的项目的宽度。
  3. xlsxwriter似乎没有读回特定单元格的方法。这意味着我需要在写入单元格时跟踪每个单元格的宽度。如果我可以循环遍历所有的单元格会更好,那样就可以编写一个通用的例程。
+1

试图设置自动宽度也不是那么简单。字形宽度取决于字体。而如果你写方程到单元格中呢?然后,根据写入的内容,您无法确定单元格的宽度。单位是任意的,这是真的,但有一个实际的定义!一个单位接近默认字体中一个字符的宽度。请参阅https://support.microsoft.com/en-us/kb/214123 – 2015-07-24 15:12:03

+0

有关xlwt的相关问题(对于XlsxWriter,总体方法将与此相同;尽管您可能需要Calibri 11而不是Arial 10的宽度) :http://stackoverflow.com/questions/6929115/python-xlwt-accessing-existing-cell-content-auto-adjust-column-width/23946840 – 2016-05-13 15:37:00

回答

2

我最近遇到了同样的问题,这就是我想出了:

r = 0 
c = 0 
for x in list: 
    worksheet.set_column('{0}:{0}'.format(chr(c + ord('A'))), len(str(x)) + 2) 
    worksheet.write(r, c, x) 
    c += 1 

在我的例子r将是你输出的行号,c将是列数你正在输出(均为0索引),并且x将是您想要在单元中的list的值。

'{0}:{0}'.format(chr(c + ord('A')))片采用列数设置并将其转换成由xlsxwriter接受列字母,因此,如果c = 0set_column会看到'A:A',如果c = 1那么它会看到'B:B',依此类推。

len(str(x)) + 2作品确定您尝试输出的字符串的长度,然后向其中添加2以确保excel单元足够宽,因为字符串的长度与单元格的宽度不完全相关。你可能想玩,而不是你添加2或可能更多取决于你的数据。

xlsxwriter接受的单位有点难以解释。当你在excel中时,你将鼠标悬停在可以改变列宽的地方,你会看到Width: 8.43 (64 pixels)。在这个例子中,它接受的单位是8.43,我认为它是厘米?但是,excel甚至不提供一个单位,至少不是明确的。

注意:我只对包含1行数据的excel文件试过这个答案。如果你将有多行,你需要有一种方法来确定哪一行将有'最长'的信息,并只应用于该行。但是,如果每列的大小大致相同,无论哪一行,那么这应该适合你。

祝你好运,我希望这有助于!

10

作为一般规则,您希望列的宽度稍大于列中最长字符串的大小。 1个xlsxwriter列的单位大约等于一个字符的宽度。因此,您可以通过将每列设置为该列中的最大字符数来模拟自动调整。

每个示例中,我倾向于在使用pandas数据框和xlsxwriter时使用下面的代码。

它首先找到索引的最大宽度,该索引始终是熊猫精通渲染数据帧的左列。然后,它将返回所有值的最大值和每个从左到右移动的其余列的列名称。

对于您使用的任何数据来说,修改此代码不应太难。

def get_col_widths(dataframe): 
    # First we find the maximum length of the index column 
    idx_max = max([len(str(s)) for s in dataframe.index.values] + [len(str(dataframe.index.name))]) 
    # Then, we concatenate this to the max of the lengths of column name and its values for each column, left to right 
    return [idx_max] + [max([len(str(s)) for s in dataframe[col].values] + [len(col)]) for col in dataframe.columns] 

for i, width in enumerate(get_col_widths(dataframe)): 
    worksheet.set_column(i, i, width) 
+0

什么是指标? – 2017-06-06 20:59:44

+0

对不起,指标是数据框的名称。为了清楚起见,更新了答案以说明数据框 – 2017-06-19 17:45:08

4

我同意科尔钻石。我需要做一些非常相似的事情,对我来说工作得很好。其中self.columns是我的专栏

def set_column_width(self): 
    length_list = [len(x) for x in self.columns] 
    for i, width in enumerate(length_list): 
     self.worksheet.set_column(i, i, width) 
1

的名单还有另一种解决方法,以模拟我发现Github site of xlsxwriter自动调整。我修改它返回水平文本(列宽)或90°旋转的文本(行高度)的近似大小:

from PIL import ImageFont 

def get_cell_size(value, font_name, font_size, dimension="width"): 
    """ value: cell content 
     font_name: The name of the font in the target cell 
     font_size: The size of the font in the target cell """ 
    font = ImageFont.truetype(font_name, size=font_size) 
    (size, h) = font.getsize(str(value)) 
    if dimension == "height": 
     return size * 0.92 # fit value experimentally determined 
    return size * 0.13  # fit value experimentally determined 

这并不解决粗体文字或其他格式元素可能影响文本尺寸。否则,它工作得很好。

要查找列宽度自动调整:

def get_col_width(data, font_name, font_size, min_width=1): 
    """ Assume 'data' to be an iterable (rows) of iterables (columns/cells) 
    Also, every cell is assumed to have the same font and font size. 
    Returns a list with the autofit-width per column """ 
    colwidth = [min_width for col in data[0]] 
    for x, row in enumerate(data): 
     for y, value in enumerate(row): 
      colwidth[y] = max(colwidth[y], get_cell_size(value, font_name, font_size)) 
    return colwidth