6

有没有办法从对象(Python/Ruby/Java/C#)生成表?

我想以编程方式创建一个简单的表。我有一些对象,我想将一些属性映射到标题并将集合映射到行。

为什么要降价?因为我想稍后手动编辑该文档。现在,整个过程是这样的:

  • 报告引擎在 C# 中
  • 有从中生成 DOCX 的对象(有中间 XML 或类似的东西)
  • 几乎总是我必须做一些小的修复,我必须在 MS Word 中打开那个 docx 文档
  • 要求开发团队修复每一个错误是很麻烦的,因为他们根本没有时间立即修复,我必须等待下一个版本。

我发现如果我能得到 Markdown 文档,我可以轻松地编辑它,插入一些变量并使用 pandoc 用给定的数据替换这些变量。但要获得 Markdown,我必须知道开发人员如何在 Markdown 中生成表格。

4

3 回答 3

12

我需要做几乎相同的事情来生成 Doxygen Markdown 表,所以我想我会分享。我已经在 Python 2.7 和 3.3 中成功运行了示例代码,尽管我不能声称我已经对其进行了严格的测试。

# Generates tables for Doxygen flavored Markdown.  See the Doxygen
# documentation for details:
#   http://www.doxygen.nl/manual/markdown.html#md_tables

# Translation dictionaries for table alignment
left_rule = {'<': ':', '^': ':', '>': '-'}
right_rule = {'<': '-', '^': ':', '>': ':'}

def evalute_field(record, field_spec):
    """
    Evalute a field of a record using the type of the field_spec as a guide.
    """
    if type(field_spec) is int:
        return str(record[field_spec])
    elif type(field_spec) is str:
        return str(getattr(record, field_spec))
    else:
        return str(field_spec(record))

def table(file, records, fields, headings, alignment = None):
    """
    Generate a Doxygen-flavor Markdown table from records.

    file -- Any object with a 'write' method that takes a single string
        parameter.
    records -- Iterable.  Rows will be generated from this.
    fields -- List of fields for each row.  Each entry may be an integer,
        string or a function.  If the entry is an integer, it is assumed to be
        an index of each record.  If the entry is a string, it is assumed to be
        a field of each record.  If the entry is a function, it is called with
        the record and its return value is taken as the value of the field.
    headings -- List of column headings.
    alignment - List of pairs alignment characters.  The first of the pair
        specifies the alignment of the header, (Doxygen won't respect this, but
        it might look good, the second specifies the alignment of the cells in
        the column.

        Possible alignment characters are:
            '<' = Left align (default for cells)
            '>' = Right align
            '^' = Center (default for column headings)
    """

    num_columns = len(fields)
    assert len(headings) == num_columns

    # Compute the table cell data
    columns = [[] for i in range(num_columns)]
    for record in records:
        for i, field in enumerate(fields):
            columns[i].append(evalute_field(record, field))

    # Fill out any missing alignment characters.
    extended_align = alignment if alignment != None else []
    if len(extended_align) > num_columns:
        extended_align = extended_align[0:num_columns]
    elif len(extended_align) < num_columns:
        extended_align += [('^', '<')
                           for i in range[num_columns-len(extended_align)]]

    heading_align, cell_align = [x for x in zip(*extended_align)]

    field_widths = [len(max(column, key=len)) if len(column) > 0 else 0
                    for column in columns]
    heading_widths = [max(len(head), 2) for head in headings]
    column_widths = [max(x) for x in zip(field_widths, heading_widths)]

    _ = ' | '.join(['{:' + a + str(w) + '}'
                    for a, w in zip(heading_align, column_widths)])
    heading_template = '| ' + _ + ' |'
    _ = ' | '.join(['{:' + a + str(w) + '}'
                    for a, w in zip(cell_align, column_widths)])
    row_template = '| ' + _ + ' |'

    _ = ' | '.join([left_rule[a] + '-'*(w-2) + right_rule[a]
                    for a, w in zip(cell_align, column_widths)])
    ruling = '| ' + _ + ' |'

    file.write(heading_template.format(*headings).rstrip() + '\n')
    file.write(ruling.rstrip() + '\n')
    for row in zip(*columns):
        file.write(row_template.format(*row).rstrip() + '\n')

这是一个简单的测试用例:

import sys

sys.stdout.write('State Capitals (source: Wikipedia)\n\n')

headings = ['State', 'Abrev.', 'Capital', 'Capital since', 'Population',
            'Largest Population?']

data = [('Alabama', 'AL', '1819', 'Montgomery', '1846', 155.4, False,
         205764),
        ('Alaska', 'AK', '1959', 'Juneau', '1906', 2716.7, False, 31275),
        ('Arizona', 'AZ', '1912', 'Phoenix', '1889',474.9, True, 1445632),
        ('Arkansas', 'AR', '1836', 'Little Rock', '1821', 116.2, True,
         193524)]

fields = [0, 1, 3, 4, 7, lambda rec: 'Yes' if rec[6] else 'No']

align = [('^', '<'), ('^', '^'), ('^', '<'), ('^', '^'), ('^', '>'),
         ('^','^')]

table(sys.stdout, data, fields, headings, align)

给出这个输出:

State Capitals (source: Wikipedia)

|  State   | Abrev. |   Capital   | Capital since | Population | Largest Population? |
| :------- | :----: | :---------- | :-----------: | ---------: | :-----------------: |
| Alabama  |   AL   | Montgomery  |     1846      |     205764 |         No          |
| Alaska   |   AK   | Juneau      |     1906      |      31275 |         No          |
| Arizona  |   AZ   | Phoenix     |     1889      |    1445632 |         Yes         |
| Arkansas |   AR   | Little Rock |     1821      |     193524 |         Yes         |

Doxygen 将其呈现为:

样本

于 2013-03-16T05:29:08.977 回答
1

我需要为最近的一个项目以编程方式生成 Markdown,所以我构建了一个库并将其发布在 GitHub 上。希望您会发现它很有用。

该项目称为MarkdownLog,它是一个轻量级(即最小依赖项)、可移植的 .NET 库 (PCL),可以从 .NET 数据结构(如集合和字典)生成 Markdown。我使用它来记录内部程序数据结构以进行诊断,但它也应该满足您的需求。

以下是从集合构建 Markdown 表的方式:

var data = new[]
{
    new{Year = 1991, Album = "Out of Time", Songs=11, Rating = "* * * *"},
    new{Year = 1992, Album = "Automatic for the People", Songs=12, Rating = "* * * * *"},
    new{Year = 1994, Album = "Monster", Songs=12, Rating = "* * *"}
};

Console.Write(data.ToMarkdownTable());

// Produces:
//
//     Year | Album                    | Songs | Rating   
//     ----:| ------------------------ | -----:| --------- 
//     1991 | Out of Time              |    11 | * * * *  
//     1992 | Automatic for the People |    12 | * * * * *
//     1994 | Monster                  |    12 | * * *    

请注意,当使用 GitHub 风格的 Markdown 解析器解析此输出时,它将生成一个 HTML 表格。

默认情况下,列根据其数据类型对齐(数字右对齐,字符串左对齐),标题名称由对象的属性名称生成。如果这不是您想要的,那么有许多覆盖可以让您更好地控制输出。

内置支持所有标准 Markdown 元素GFM 表格。我还添加了一些我需要的额外元素类型(条形图、iOS UITableView),它们以代码块的形式实现,因此它们仍然符合 Markdown 标准。

我最近才将代码上传到 GitHub,所以文档现在是基本的。话虽如此,项目中有大量的单元测试,应该可以演示它是如何工作的。

我很感激自从提出这个问题以来已经有一段时间了,但我希望这个项目对某人有用。

于 2014-07-08T17:33:56.093 回答
0

使用 Apache Freemarker 通过 Java 代码呈现 HTML,然后将其转换为 Markdown。这是将 HTML 表格转移到 markdown 的地方。

Flexmark-java 将 HTML 表格转换为 Markdown

于 2021-07-26T11:36:38.810 回答