Markdown复杂表格一键生成[合并 颜色 字体]基于Python【附完整代码】


当然此处的markdown指的是csdn的markdown

多样化、复杂化表格的需求

写在前面的话:

  当然,csdn的markdown编辑器已经有快捷的表格建立语法。

  但是很可惜的是,只能按固定格式创建,就是所创建的表格每一行的列数是固定的,相同的。如下
在这里插入图片描述
  大多数情况下,这种表格已经能满足一些需求。但有时候,我们需要做一些“合并单元格”,“颜色标注”来灵活使用表格,于是这种简单使用的语法,就不能满足了。

  要是耐心搜索的话,也能在csdn上搜寻到用markdown制作高级表格的方法——像写Html一样。【如下】

在这里插入图片描述
  要是码字速度够快,对html语法熟悉,那完全可以每次随手一码。
  不过要是能够有直接喂给数据,然后按要求生成表格数据的脚本,那岂不是快哉,快男的快,快的一批的快。


于是乎,通过一番观察思索,发现实现起来也不难

  • 这是一个较为复杂表格的代码,借此来分析

<table>
<tr>
	<td rowspan=1 colspan=1 align=center bgcolor=white>
		<font color=k size=4 face=YaHei>内容</font>
	</td>
	<td rowspan=1 colspan=2 align=center bgcolor=#f0f0f0>
		<font color=b size=4 face=YaHei>说明</font>
	</td>
</tr>
<tr>
	<td rowspan=3 colspan=1 align=center bgcolor=white>
		<font color=k size=5 face=YaHei>飞出个未来</font>
	</td>
	<td rowspan=1 colspan=1 align=left bgcolor=white>
		<font color=b size=4 face=楷体>人名</font>
	</td>
	<td rowspan=1 colspan=1 align=left bgcolor=white>
		<font color=orange size=4 face=楷体>翻译</font>
	</td>
</tr>
<tr>
	<td rowspan=1 colspan=1 align=left bgcolor=#f0f0f0>
		<font color=b size=4 face=楷体>Fry</font>
	</td>
	<td rowspan=1 colspan=1 align=left bgcolor=#f0f0f0>
		<font color=orange size=4 face=楷体>弗莱</font>
	</td>
</tr>
<tr>
	<td rowspan=1 colspan=1 align=left bgcolor=white>
		<font color=b size=4 face=楷体>Leela</font>
	</td>
	<td rowspan=1 colspan=1 align=left bgcolor=white>
		<font color=orange size=4 face=楷体>利拉</font>
	</td>
</tr>
<tr>
	<td rowspan=3 colspan=1 align=center bgcolor=white>
		<font color=k size=5 face=YaHei>马男</font>
	</td>
	<td rowspan=1 colspan=1 align=left bgcolor=#f0f0f0>
		<font color=b size=4 face=楷体>人名</font>
	</td>
	<td rowspan=1 colspan=1 align=left bgcolor=#f0f0f0>
		<font color=orange size=4 face=楷体>翻译</font>
	</td>
</tr>
<tr>
	<td rowspan=1 colspan=1 align=left bgcolor=white>
		<font color=b size=4 face=楷体>bojack</font>
	</td>
	<td rowspan=1 colspan=1 align=left bgcolor=white>
		<font color=orange size=4 face=楷体>波杰克</font>
	</td>
</tr>
<tr>
	<td rowspan=1 colspan=1 align=left bgcolor=#f0f0f0>
		<font color=b size=4 face=楷体>diane</font>
	</td>
	<td rowspan=1 colspan=1 align=left bgcolor=#f0f0f0>
		<font color=orange size=4 face=楷体>戴安</font>
	</td>
</tr>
</table>
内容 说明
飞出个未来 人名 翻译
Fry 弗莱
Leela 利拉
马男 人名 翻译
bojack 波杰克
diane 戴安

不难发现:

  • 整个表格的内容,都在一个 <table>。。。</table> 节点中。
  • 每一“行”表格的内容都在一个 <tr>。。。</tr> 节点中。
  • 每一格表格的内容都在一个 <td>。。。</td> 节点中。
  • 每格内容字体参数由 <font>。。。</font> 节点控制。
  • 表格的具体跨度(合并)由 <td>。。。</td> 节点中的 rowspancolspan 参数来控制
  • 一些参数说明如下
参数 说明
rowspan 行跨度 整数
colspan 列跨度 整数
align 对齐 left、center、right
bgcolor 背景颜色 颜色名[red、blue...]/十六进制[#f0f0f0]
color 字体颜色 颜色名[red、blue...]/十六进制[#f0f0f0]
size 字体大小 整数
face 字体 楷体、宋体、YaHei、仿宋。。。

构造模板,给入数据,一键生成!

思路说明:

1. 取最小单元:一格 作为模板

pt = f'''\t<td rowspan={rowspan} colspan={colspan} align={align} bgcolor={bg}>
\t\t<font color={fcolor} size={fsize} face={font}>{text}</font>
\t</td>
	<td rowspan=1 colspan=1 align=center bgcolor=yellow>
		<font color=0 size=0 face=0>没有内容</font>
	</td>
没有内容

2. 而后通过循环,逐一套入数据、参数,并将表格数据拼接

这里是最核心的地方。【各部分代码在最后】

  • 首先,对输入的数据作何约束,才方便处理?
      对于 表头(首行数据),通常需要它的跨度灵活,就是一格占多列。于是规定每一格内容最后,加上所占的列数【与总列数相符–总列数依据总数据判断】,同一行每列数据中文逗号隔开。
    如下:表头共两格,‘内容’格占一列,‘说明’格占两列【效果参考开头的表格】
内容1,说明2

于是希望从该行数据提取到如下信息

title = [
	['内容', 1], 
	['说明', 2']
	]

  对于 内容(详细数据),通常需要它的跨度灵活,就是一格占多行。于是规定每一个占多行的内容,其最后加上所占行数,而且之后行的该列数据为。同一行每列数据中文逗号隔开。
如下:‘飞出个未来’格占三行,其后两行该列数据为空【效果参考如下】

飞出个未来3,人名,翻译
,Fry,弗莱
,Leela,利拉
马男3,人名,翻译
,bojack,波杰克
,diane,戴安
飞出个未来 人名 翻译
Fry 弗莱
Leela 利拉
马男 人名 翻译
bojack 波杰克
diane 戴安

所期望从文本中提取的数据:

body = [
		['飞出个未来3', '人名', '翻译'],
		['', 'Fry', '胡莱'],
		['', 'Leela', '利拉'],
		['马男3', '人名', '翻译'],
		['', 'Bojack', '波杰克'],
		['', 'Diane', '戴安'],		
		]

  表头的列表很容易提取到信息,但是如上的就稍微绕了。抓住主要矛盾:获取特殊格的行跨度。如何判断是特殊格子呢?很简单,(当前格子内容不为空)and(下一行该位置内容为空),那么其列跨度就是内容之后的数字。【当然有想过直接通过循环之后的空格数来获取列跨度,但是觉得循环算法总给人费时的印象,哈哈,也可能是觉得数据里多写个数字,比写循环要偷懒的多。
  而其他参数,就不必包含在数据里了,可以固定化处理,实在想调整的话,倒腾代码吧,设计程序的时候留了后路,也不难实现!

从文本获取模板所需数据–代码:

def get_list(self, filepath):
    with open(filepath, 'r', encoding='utf8') as f:
        for line in f.readlines():
        	# 先分割数据
            texts = line.rstrip('\n').split(',')
            # 将第一行数据处理后存入 表头列表
            if not self.title:
                for tle in texts:
                    tl = [self.text.findall(tle)[-1], int(self.num.findall(tle)[-1])]
                    self.title.append(tl)
            else:
            	# 其余的存入内容列表
                self.datas.append(texts)

表头设计–代码:

def make_title(self, fsize=4, fcolor=['k', 'b', 'orange'],\
	font='YaHei', bg=['white', '#f0f0f0', 'snow', '#f0f0f0']):
    title = '<tr>\n{}\n</tr>'
    rowspan = 1
    align = 'center'
    lst = ''
    for i in range(len(self.title)):
        colspan = self.title[i][-1]
        text = self.title[i][0]
        if lst:
            lst += '\n'
        lst += self.one.format(
            rowspan, colspan, align, bg[i % len(bg)],
            fcolor[i % len(fcolor)], fsize, font, text
        )
    return title.format(lst)

表格设计–代码:

def make_body(self, align=['center', 'left', 'left'], bg=['white', '#f0f0f0'],
              fcolor=['k', 'b', 'orange'], fsize=[5, 4, 4, 4], font=['YaHei', '楷体', '楷体'],):
    allrow = len(self.datas)
    cols = len(self.datas[0])
    colspan = 1
    body = ''
    for i in range(allrow):
        fmt = '<tr>\n{}\n</tr>'
        lst = ''
        # 循环一行的每一列内容,以构造一行
        for j in range(cols):
            # 如果该行 j列有内容,进行操作
            if self.datas[i][j]:
                text = self.datas[i][j]
                rowspan = 1
                # 判断之前是否有加入内容单元,有的话换行
                if lst:
                    lst += '\n'
                else:
                    pass
                # 判断,从而获取 行跨度/纠正内容
                if i < allrow-1:
                    # 如果下一行同一位置内容为空,获取行跨度
                    if not self.datas[i+1][j]:
                        rowspan = int(self.num.findall(text)[-1])
                        # 纠正内容
                        text = self.text.findall(text)[0]
                if not j:
                    bgc = 'white'
                else:
                    bgc = bg[i % len(bg)]
                lst += self.one.format(
                    rowspan, colspan, align[j % len(align)], bgc,
                    fcolor[j % len(fcolor)], fsize[j % len(fsize)], font[j % len(font)], text
                    )
            else:
                continue
        if body:
            body += '\n'
        body += fmt.format(lst)
    return body

表格构建–代码:

def make_html(self, filepath):
    self.get_list(filepath)
    html = '<table>\n{}\n{}\n</table>'
    title = self.make_title()
    body = self.make_body()
    html = html.format(title, body)
    with open(f'{self.title[0][0]}.html', 'w', encoding='utf8') as f:
        f.write(html)
        f.close()
    print(html)

总代码

import re

class Markct():
    def __init__(self):
        self.title = []
        self.datas = []
        self.num = re.compile(r'\d+$')
        self.text = re.compile(r'.+[\D]')
        self.one = '\t<td rowspan={} colspan={} align={} bgcolor={}>' \
                 '\n\t\t<font color={} size={} face={}>{}</font>\n\t</td>'

    def get_list(self, filepath):
        with open(filepath, 'r', encoding='utf8') as f:
            for line in f.readlines():
                texts = line.rstrip('\n').split(',')
                if not self.title:
                    for tle in texts:
                        tl = [self.text.findall(tle)[-1], int(self.num.findall(tle)[-1])]
                        self.title.append(tl)
                else:
                    self.datas.append(texts)

    def make_html(self, filepath):
        self.get_list(filepath)
        html = '<table>\n{}\n{}\n</table>'
        title = self.make_title()
        body = self.make_body()
        html = html.format(title, body)
        with open(f'{self.title[0][0]}.html', 'w', encoding='utf8') as f:
            f.write(html)
            f.close()
        print(html)

    def make_body(self, align=['center', 'left', 'left'], bg=['white', '#f0f0f0'],
                  fcolor=['k', 'b', 'orange'], fsize=[5, 4, 4, 4], font=['YaHei', '楷体', '楷体'],):
        allrow = len(self.datas)
        cols = len(self.datas[0])
        colspan = 1
        body = ''
        for i in range(allrow):
            fmt = '<tr>\n{}\n</tr>'
            lst = ''
            # 循环一行的每一列内容,以构造一行
            for j in range(cols):
                # 如果该行 j列有内容,进行操作
                if self.datas[i][j]:
                    text = self.datas[i][j]
                    rowspan = 1
                    # 判断之前是否有加入内容单元,有的话换行
                    if lst:
                        lst += '\n'
                    else:
                        pass
                    # 判断,从而获取 行跨度/纠正内容
                    if i < allrow-1:
                        # 如果下一行同一位置内容为空,获取行跨度
                        if not self.datas[i+1][j]:
                            rowspan = int(self.num.findall(text)[-1])
                            # 纠正内容
                            text = self.text.findall(text)[0]
                    if not j:
                        bgc = 'white'
                    else:
                        bgc = bg[i % len(bg)]
                    lst += self.one.format(
                        rowspan, colspan, align[j % len(align)], bgc,
                        fcolor[j % len(fcolor)], fsize[j % len(fsize)], font[j % len(font)], text
                        )
                else:
                    continue
            if body:
                body += '\n'
            body += fmt.format(lst)
        return body

    def make_title(self, fsize=4, fcolor=['k', 'b', 'orange'], font='YaHei', bg=['white', '#f0f0f0', 'snow', '#f0f0f0']):
        title = '<tr>\n{}\n</tr>'
        rowspan = 1
        align = 'center'
        lst = ''
        for i in range(len(self.title)):
            colspan = self.title[i][-1]
            text = self.title[i][0]
            if lst:
                lst += '\n'
            lst += self.one.format(
                rowspan, colspan, align, bg[i % len(bg)],
                fcolor[i % len(fcolor)], fsize, font, text
            )
        return title.format(lst)

n = Markct()
n.make_html('data1.txt')
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛定谔的壳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值