本代码价值:
终端生成的列表 通过TXT文本转换成docx文件
征文需求:
3月上海疫情隔离开启居家办公生涯。月底区教育局有一个“工具运用”的征文比赛,阿夏以《设计Python学具,开展大班幼儿学习活动的案例研究》为题,将已有的五个教学案例进行汇总。
第五项“数字加减法.py”的学具并不能立刻通过代码生成,需要借助“运行——保存为TXT——打开TXT——复制TXT内容——新建docx——黏贴TXT内容——分栏——放大字体、加粗——加框——添加页眉信息(X以内加减题,姓名、班级、学号、分数)”的方式。
1、不足之处:需手动制作word模板:
曾经阿夏觉得Python实现了题目批量,已节约了大量时间,因此愿意通过手动黏贴制作word模板。但是经过了5以内、10以内、20以内的模板制作,感觉也是比较费时间,人力操作依旧繁琐。
2、阶段体验:论文过程冗长无价值:
而在撰写文本经验的时候,阿夏也发自内心地认为“如果把这么多的制作过程写出来,图文占空间,根本无法体现编程的价值(高效)评审员估计要看晕了。”
因此,阿夏用了两天的时间,从网上搜索各种解题思路和实现代码,拼拼贴贴,反复测试。终于用繁琐的代码实现了“列示题TXT转docx”的初步结果。
3.宏观把控:“减负”背景下少触红线:
随后,阿夏把马先生设计的“加减法不重复题数代码“加上了”列示题TXT转docx”的程序,顺利获得了“X以内列示题(加法题、减法题、加减混合题)”的代码。
但是考虑到“减负”政策,如果直接演示“一年级的数学列示题”的设计和教学运用过程,也是有一定的降分风险(虽然班级里100%的孩子都在家练习过)”因此阿夏决定用大班主题教材上的《数字分合题》(相对安全)为教学目标,改良代码,制作“X以内数字分合题(分题)的不重复题数的代码”
代码演示:
0. 效果展示:生成一份带名称的docx文件(所有X以内不重复的减法题都在其中)(这里是分题,所以是减法)
1、拷贝代码,“X以内数字分合题-最大不重复数量.py”,py可以在盘的任意位置。生成的文件统一在VS打开的默认文件夹下,作者这里是D\test 下:
# -*- coding: utf-8 -*-
# 第1部分:题目库
print('----------------第一步开始:生成数学题----------------')
# -*- coding: utf-8 -*-
"""
@author: 马清新
@file: 阿夏修改(20以内加法题、20以内减法题、20以内加减法混合题(最大不重复算式值).py
@time: 2022/2/4 17.18
# 特别说明
1、选择“1.纯加法题。2.纯减法题。3.加减法混合题(请输入序号)”
2、分开计算,纯加法题数量+纯减法题数量=加减法混合题数量。
3、结果分别保存在相应的TXT内
4、可通过注释,选择题目是否有答案。
5、本题所有答案都是打乱模式 random.shuffle.如果是10以内加法、减法、加减法可以排序 sort
"""
import random
from re import X
import time
from async_generator import yield_
# 数字分合 总分结构,求分1 分2的数字
hao='数字分合(分)'
sumMax = int(input('请输入最大数字((≥0)):\n'))# 输入最大值
regNum = int(input('请输入需要的数量:\n'))# 输入需要的数量
# 生成1个列表,列表从0开始,到算术最大和结束,因为range函数包左不包右,因此如果要包括算式最大和,必须+1
# range函数从0开始,这样列表元素和列表索引一致,减轻算法的难度
numList = [x for x in range(0,sumMax+1)]# 建立整数列表,假设SUMMAX=20 sumMax+1等于21 但实际范围就是1-20,确保列表索引和列表元素一致
# resultList列表用于保存最后需求数量的合规算术式
resultList = []# 储存结果的列表
# 从列表第2个元素开始到列表最后一个元素进行循环遍历
for x in numList[0:]:# 0等于数字1
# 从列表第x个元素开始到列表最后一个元素进行循环遍历
for y in numList[x:]:
# 加法
if (x == y) and (x + y <= sumMax)and (y != 0): # X或Y两者一个或者两个都不能0。没有0+0,0-0
tempStr = ' '+str(x+y)+'\n' + ' / ' + ' \ '+'\n'+' __ ' + str(y)+'\n'
resultList.append((tempStr, (x+y)))
tempStr = ' '+str(x+y)+'\n' + ' / ' + ' \ '+'\n'+str(x)+' __' +'\n'
resultList.append((tempStr, (x+y)))
elif x + y <= sumMax and (y != 0):# 第一位或者第二位都不为0,也就是没有
tempStr = ' '+str(x+y)+'\n' + ' / ' + ' \ '+'\n'+'__ '+ str(y)+'\n'
resultList.append((tempStr, (x+y)))
tempStr = ' '+str(x+y)+'\n' + ' / ' + ' \ '+'\n'+str(x)+' __'+'\n'
resultList.append((tempStr, (x+y)))
elif y - x == 0 and(y == 0):#此段只有一个答案0+0=0,不需要的话,此段注释掉
tempStr = ' '+str(x+y)+'\n' + ' / ' + ' \ '+'\n'+str(x)+' __' +'\n'
resultList.append((tempStr, (y+x)))# 带答案的题目,如0+0=0,
selectList = []# 选择列表
if regNum > len(resultList):#如果(输入算式的数量)大于(结果列表的数量)#输入题数大于实际需求,就用shuffle洗牌,
print(f'您的需求大于最大算式生成数量!最大生成算式数量为{len(resultList)}') # 加了最大不重复算式统计值,如果输入的题数大于储存结果的列表的数量,列表加LEN
i = len(resultList)# i的数量等于储存结果的列表的数量
for _ in resultList:# 值在循环储存结果的列表内
selectList.append(_) #选择列表 需要添加循环储存结果列表的内容
random.shuffle(selectList) #shuffle 洗牌算法,把列表所有元素打乱,随机排列
# selectList.sort()#sort 正序排列,只有10以内的能排序,超过10就乱序
# selectList.sort(reverse=True) #从大到小 倒叙排列 5 + 0 = 5 4 + 1 = 5 ……
# selectList.shuffle()
for _ in selectList:
# 可选打印带答案的和不带答案啊8
# print(_[0])# 不带答案
print(f'{_[0]}{_[1]}')# 终端带答案,
else:#输入题数小于实际需求,代码自动随机抽取,不会排序,
i = regNum
selectList = random.sample(resultList,i)
for _ in selectList:
# 可选打印带答案的和不带答案啊
# print(_[0])# 不带答案
print(f'{_[0]}{_[1]}')# 终端带答案,
# 验证生成算式数量70
print(f'共生成不重复的纯加法算式的题目数量{len(selectList)}')# 选择列表的数量
print(f'纯加法最大不重复的算式的限制数量{len(resultList)}')# 结果列表的数量
str_title = '过渡.txt' # 保存带数字提示的题目
with open(str_title,'w',encoding='utf-8') as f:# 打开TXT文件
for a in selectList:# #循环查找答案的内容
f.write(str(a[0])+'\n')# 不带答案
# f.write(str(a[1])+'\n')#只有答案
# f.write(str(a[0])+str(a[1])+'\n')#有题目有答案 TXT里面是题目+答案,终端显示题目 无答案,因为上面选了(0)
f.close()# #关闭TXT
# elif sumMax<x + y <= sumMax+5:
# tempStr = ' '+str(x+y)+'\n' + ' / ' + ' \ '+'\n'+'__ '+' __' +'\n'+'\n'
# resultList.append((tempStr, (y+x)))# 带答案的题目,如0+0=0,
# tempStr = ' '+str(c)+'\n' + ' / ' + ' \ '+'\n'+'( ) ' + str(a)+'\n'+'\n'
# else:
# print('输入错误,请重新输入.')
print('----------------------第一步完成--------------------')
time.sleep(0.5)
print('----------------第二步开始:txt转换docx-------------')
# 第二部分: TXT转docx
from docx import Document
import os
# 作者:we1can https://www.bilibili.com/read/cv13745103 出处:bilibili
# 创建word并设置字体
document = Document()
paragraph = document.add_paragraph()
run = paragraph.add_run()
run.font.name = 'Times New Roman'
# 打开txt文件,并写入document中
f = open("过渡.txt","r",encoding='utf-8') # 注意编码类型
document._body.clear_content()# 删除docx里面的第一行 ,这是个空行,用strip无法删除
line = f.readline()
# line=line.strip('\n')# 删除一个数字题下面空行 也就是第三行
while line:
line=line.strip('\n')
document.add_paragraph(line)
line = f.readline()
# document.add_paragraph(line)
# line=line.strip('\n')
# line = f.readline()
# line=line.strip('\n')# 删除一个数字题下面空行 也就是第三行
f.close()
document.save(u'过渡.docx') # 保存文档
print('----------------------第二步完成--------------------')
time.sleep(0.5)
print('----------------第三步开始:docx格式调试------------')
'''https://www.cnblogs.com/wenshi-jj/p/15388808.html'''
# import docx# 导入docx模块
from docx import Document
from docx.shared import Pt
from docx.shared import RGBColor
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml.ns import qn
# 新建节 1页
# doc = docx.Document()# 新建一个空白文档,那么默认是只有一个节
# len(doc.sections)# 长度为1 默认是只有一个节
doc=Document('过渡.docx')
for paragraph in doc.paragraphs:
for run in paragraph.runs:
run.font.size = Pt(20) # 数字题目字体大小
run.font.bold = True #数字题目字体是否加粗
run.font.name = 'Arial' # 数字题英文时的字体
run.element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑') # 数字题中文时的字体
paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 设置数字题居中对齐
# paragraph.paragraph_format.line_spacing=0.8 #数字题的段行距
paragraph.paragraph_format.line_spacing = Pt(26) #数字题段间距
# 设置主要页边距
from docx.shared import Cm # 导入cm模块
doc.sections[0].top_margin = Cm(2.54)# sections[1]是第二节=第二页 上边距
doc.sections[0].bottom_margin = Cm(1)# sections[1]是第二节=第二页 下边距
doc.sections[0].left_margin = Cm(1) # sections[1]是第二节=第二页 左边距
doc.sections[0].right_margin = Cm(1)# sections[1]是第二节=第二页 右边距
# 设置其他页边距内容
doc.sections[0].gutter=Cm(0)# sections[1]是第二节=第二页 装订线 默认为0 左
doc.sections[0].header_distance=Cm(2)# sections[1]是第二节=第二页 页眉边距
doc.sections[0].footer_distance=Cm(1)# sections[1]是第二节=第二页 页脚边距
# 装订线还有一个位置属性,暂时未发现如何设置,默认为左,如果需求设置成右,可以建个模板docx文档导入。
# 设置纸张方向和大小 LANDSCAPE=横 PORTRAIT纵 默认信纸 纵
from docx.shared import Cm # 导入CM #
from docx.enum.section import WD_ORIENTATION # 导入纸张方向
doc.sections[0].page_height = Cm(21) # 设置A4纸的高度
doc.sections[0].page_width = Cm(29.7) # 设置A4纸的宽
doc.sections[0].orientation = WD_ORIENTATION.LANDSCAPE # 设置纸张方向为横向 L
# 设置分栏
from docx.oxml.ns import qn
doc.sections[0]._sectPr.xpath('./w:cols')[0].set(qn('w:num'), '6') #把第二节页设置为2栏
# doc.sections[0]._sectPr.xpath('./w:cols')[0].set(qn('w:distance'), '12')
# doc.sections[0]._sectPr.xpath_distance = Cm(21) 调证分栏间距?
# 设置页眉和页脚
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT# 导入文本居中 居左、居右
from docx.shared import Pt
header = doc.sections[0].header # 获取第一个节的页眉
# print('页眉中默认段落数:', len(header.paragraphs))
paragraph = header.paragraphs[0] # 获取页眉的第一个段落
# {}以内加法题'.format()
text=paragraph.add_run('{}以内{}-不重复题数-共{}题\n'
'姓名:______________学号:_______________班级:___________分数________ '.format(sumMax,hao,len(resultList))) # 添加页面内容
text.font.size = Pt(20) # 页眉字体大小
text.bold = True # 页眉字体是否加粗
text.font.name = 'Arial' # 控制是英文时的字体
text.element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑') # 控制是中文时的字体
paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 设置页眉居中对齐
paragraph.paragraph_format.line_spacing=1.5 #页眉中文字的段间距
# 设置页脚文字
footer = document.sections[0].footer # 获取第一个节的页脚
paragraph = footer.paragraphs[0] # 获取页脚的第一个段落
paragraph.add_run('')#添加内容
paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER#居中
# # 文字上下左右加边框 对导入的数学题加边框,控制答案的位置
# from docx.oxml import OxmlElement
# from docx.oxml.ns import qn
# #table = document.add_table(rows=1, cols=3)
# hdr_cells = table.rows[0].cells
# hdr_cells[0].text = 'Qty'
# set_cell_border(
# hdr_cells[0],
# top={"sz": 12, "val": "single", "color": "#000000", "space": "0"},
# bottom={"sz": 12, "val": "single", "color": "#000000", "space": "0"},
# left={"sz": 12, "val": "single", "color": "#000000", "space": "0"},
# right={"sz": 12, "val": "single", "color": "#000000", "space": "0"},
doc.save('%d以内%s-不重复题数-共%d题.docx' % (sumMax,str(hao),len(resultList))) # 保存文档
print('----------------------第三步完成--------------------')
time.sleep(0.5)
print('----------------第四步开始:删除过渡文件------------')
# 删除过渡文件
import os
path = '过渡.txt' # 文件路径
if os.path.exists(path): # 如果文件存在
# 删除文件,可使用以下两种方法。
os.remove(path)
#os.unlink(path)
path = '过渡.docx' # 文件路径
if os.path.exists(path): # 如果文件存在
# 删除文件,可使用以下两种方法。
os.remove(path)
#os.unlink(path)
print('----------------------第四步完成--------------------')
time.sleep(0.5)
print('---------------请到D盘test下查找生成word------------')
time.sleep(0.5)
'''
————————————————
版权声明:本文为CSDN博主「reasonsummer」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/reasonsummer/article/details/123781844
'''
基本参数都是调整过的,适合阿夏的电脑及生成的版本。其他电脑 不保证。
运行步骤:
1、VS 运行
每张A4上 3*6=18题
用同样的方法可以批量5以内、10以内分合题
3*6+5=23题
生成docx文件名也不同,便于区分,放在同一个文档里,打印方便。
也可以再增加代码,批量生成“5以内”“10以内”的28份,每份出现的题目顺序不一样的X以内分合题。(个别幼儿用20,50)
小结:
有了这个固定的TXT转docx模板,制作各类“数字题型”学具会变得更方便快捷。编程太有用了,值得花时间去写、去优化、去调整一个又一个受益终身的教学代码、办公代码!
后续:
目前没有破解的内容有“段落框架、页码、题目第一位数的排序、def函数体及EXE打包”
等下一次的比赛时估计才会逼着自己去研究吧。