【教学类-43-25】20241203 数独3宫格的所有可能-使用模版替换-用时少报错少(12套样式,空1格-空8格,每套510张,共6120小图)

前期做数独3宫格的所有排列,共有12套样式,空1格-空8格,每套510张,共6120小图

【教学类-43-24】20241127 数独3宫格的所有可能(12套样式,空1格-空8格,每套510张,共6120小图)-CSDN博客文章浏览阅读1.7k次,点赞41次,收藏30次。【教学类-43-24】20241127 数独3宫格的所有可能(12套样式,空1格-空8格,每套510张,共6120小图)https://blog.csdn.net/reasonsummer/article/details/144069290

代码用的是生成一个docx,转一个PDF,最后把所有的PDF合并,这种方式转化PDF容易报错(保存时间不够),就出现程序中断,及时顺利运行不报错,也要3个半小时。

所以我想了半天,想到一个新的思路

1、用12套的第一套生成510张图片+1个基础样式,获得共44张A4图纸

2、把44张图纸合并在一个word内(这样转PDF快一点,稳定不报错)

3、在一套3宫格的510张基础样式(一个word)基础上,对里面的数字进行替换,如果不是空,就清空原来的数字,换成新的数字,如果是空,就继续留空

4.生成12个合并word,每个里面有44张图纸,再把每个合并word转成每个PDF。

但是测试过程中,总是出现第一张基本样式表的“样式X”字样没有替换成“样式01、样式02……”

测试无数次后,发现原来要想替换文字,文字段落的字体格式、间距、大小、必须一样才行。

准备的word模版

代码展示






# 测试11*11格,2*2一共4套3*3 宫格
'''
目的:数独3宫格(1,2,3)有12套不同的基础模板,对每套题目进行空1=空8的不重复获取。
(12套样式,空1格-空8格,每套510张,共6120小图)
本代码先做样式1,获取基本样式510张,打印时44页,然后尝试用替换方式制作另外的11款
作者:阿夏
时间:2024年11月30日-12月4日


'''
import math,os,time
from itertools import permutations
import random
from win32com.client import constants, gencache
from win32com.client.gencache import EnsureDispatch
from docx import Document
from docx.shared import Pt, RGBColor
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT, WD_BREAK
from docx.oxml.ns import qn
from docxtpl import DocxTemplate
import pandas as pd
from docx2pdf import convert
from datetime import datetime


# 开始时间
start_time = datetime.now()

# 制作"单元格"# 几宫格
hsall=3
# int(input('3宫格数独=3\n'))
hs=hsall
# 内容太多了,容易报错,如果报错,就重新设置起始宫格数字1-8
start=1
# 第几套,第一套
sz=1


print('------第1步:制作单元格-------')

ll=['3'] # 如果输入345
mm=['34']# 3对应的套数是4*3套
gz=int(mm[0][0])*int(mm[0][1])
nn=['36']# 3对应的写入单元格的数字大小36磅 
# ll=['3','4','5','6','7','8','9'] # 如果输入345
# mm=['43','43','32','32','32','32','32']# 3对应的套数是4*3套
# nn=['36','24','36','24','24','24','24']# 3对应的写入单元格的数字大小36磅 
for r in range(len(ll)):
    if hsall ==int(ll[r]):
        # 底边几套.底边看有2份
        db=int(mm[r][0])
        # int(input('底边几套? 3\n'))
        # 侧边几套 侧边看也是2份
        print(db )        
        cb=int(mm[r][1])
        # int(input('侧边几套? 2\n'))
        print(cb)
        size=int(nn[r])
        print(size)        # 写入单元格数字的大小(撑满格子)

# 新建一个”装N份word和PDF“的临时文件夹
path=r'C:\Users\jg2yXRZ\OneDrive\桌面\数独所有可能'


# 新建“单独docx”输出文件夹
tencent=path+fr'\{hs}宫格'
os.makedirs(tencent,exist_ok=True)
tencent1=tencent+fr'\01_{hs}宫格_样式A_单独_X张A4_Y张小图'
os.makedirs(tencent1,exist_ok=True)
        

# 计算不同模板中的单元格坐标,放在bg里
# 棋盘格子数量,

# 如果正方形:底边2*侧边2,就是3*3宫格 2*2=4套,底边边格子数量就是3*2+1=7,侧边格子数量就是3*2+1=7,
# 如果长方形:底边3*侧边2,就是3*3宫格,3*2=6套 底边格子数量就是3*3+2=11,侧边格子数量就是3*2+1=7,
# if db==cb:
db_size = hs*db+db-1
cb_size=  hs*cb+cb-1
print('{}宫格排列底{}侧{}共{}套,底边格子数{}'.format(hs,db,cb,db*cb,db_size ))
print('{}宫格排列底{}侧{}共{}套,侧边格子数{}'.format(hs,db,cb,db*cb,cb_size ))

# 确定每个宫格的左上角坐标 00 04 40  44
bgszm=[]
for a in range(0,cb_size,hs+1):    # 0-11每隔4,写一个坐标  侧边y
    for b in range(0,db_size,hs+1):  # 0-11每隔4,写一个坐标  侧边x
        bgszm.append('{}{}'.format('%02d'%a,'%02d'%b))
print(bgszm)
# 3宫格排列底3侧2共6套,底边格子数11
# 3宫格排列底3侧2共6套,侧边格子数7
# ['0000', '0004', '0008', '0400', '0404', '0408']
    

# 转为元祖
start_coordinates = [(int(s[0:2]), int(s[2:4])) for s in bgszm]
cell_coordinates = []

# 推算每个起始格子后面的单元格数字
for start_coord in start_coordinates:
    i, j = start_coord
    subgrid_coordinates = []
    for x in range(hs):
        for y in range(hs):
            subgrid_coordinates.append((i + x, j + y))
    cell_coordinates.append(subgrid_coordinates)

# 打印结果(元祖样式)
bg=[]
for coordinates in cell_coordinates:
    # print(coordinates)     # [(4, 8), (4, 9), (4, 10), (5, 8), (5, 9), (5, 10), (6, 8), (6, 9), (6, 10)]
    for c in  coordinates:
        print(c)        # 元组 (1, 2) 样式
        s = ''.join(str(num).zfill(2) for num in c)   # zfill将元组 (1, 2) 转换为字符串 '0102' 特别是(5,10)这种必须转成2个数字0510
        print(str(s))        #  '12'
        bg.append(s)  #  '0102'
print(bg)
# 3列4行12个3*3格子
# ['0000', '0001', '0002', '0100', '0101', '0102', '0200', '0201', '0202', 
# '0004', '0005', '0006', '0104', '0105', '0106', '0204', '0205', '0206', 
# '0008', '0009', '0010', '0108', '0109', '0110', '0208', '0209', '0210', 
# '0400', '0401', '0402', '0500', '0501', '0502', '0600', '0601', '0602', 
# '0404', '0405', '0406', '0504', '0505', '0506', '0604', '0605', '0606', 
# '0408', '0409', '0410', '0508', '0509', '0510', '0608', '0609', '0610', 
# '0800', '0801', '0802', '0900', '0901', '0902', '1000', '1001', '1002', 
# '0804', '0805', '0806', '0904', '0905', '0906', '1004', '1005', '1006', 
# '0808', '0809', '0810', '0908', '0909', '0910', '1008', '1009', '1010', 
# '1200', '1201', '1202', '1300', '1301', '1302', '1400', '1401', '1402', 
# '1204', '1205', '1206', '1304', '1305', '1306', '1404', '1405', '1406', 
# '1208', '1209', '1210', '1308', '1309', '1310', '1408', '1409', '1410']

print('------第2步:制作3宫格的12套题的内容-------')

# 制作3宫格的12套题目(没有空格,只有基础模板)
lst=[]
for b in range(1,hs+1):
    lst.append(b)
print(lst)

permutations_list = list(permutations(lst))
numbers = [list(permutation) for permutation in permutations_list]
print(numbers)
# [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
# 6种组合


# 互相组合成3组
import itertools

# 计算排列数量并生成所有可能的排列
combinations2 = list(itertools.permutations(numbers, hs))
# 包含相似的

# 输出排列数量
print(len(combinations2))
# 120

# # 把所有数字都提取成元素
ll=[]
for o1 in combinations2:
    for o2 in o1:
        for o3 in o2:
            ll.append(o3)
            
print(ll)
print(len(ll))
# 1080

v=hs*hs
# 9个数字抽取一组
f=[]
for i in range(int(len(ll)/v)):
    f.append(ll[i*v:i*v+v])
# print(f)
# print(len(f))
#120条


# # # 遍历表格,把0、5、10相同的内容删除,横向的数字1234都正确了,现在只要排除竖向不对的

P=[]
z=[]
for k in f:  

    if int(k[0])!=int(k[3])!=int(k[6]) and int(k[0])+int(k[3])+int(k[6])==6 and\
          int(k[1])!=int(k[4])!=int(k[7]) and int(k[1])+int(k[4])+int(k[7])==6 and\
            int(k[2])!=int(k[5])!=int(k[8]) and int(k[2])+int(k[5])+int(k[8])==6 and\
                int(k[0])!=int(k[1])!=int(k[2]) and int(k[0])+int(k[1])+int(k[2])==6 and\
                    int(k[3])!=int(k[4])!=int(k[5]) and int(k[3])+int(k[4])+int(k[5])==6 and\
                        int(k[6])!=int(k[7])!=int(k[8]) and int(k[6])+int(k[7])+int(k[8])==6 :
        z.append(k)

print(z)
print(len(z))

# 12种基础样式
basis=[]
for hh in z:
    print(hh)
    basis.append(hh)
print(basis)
print(len(basis))    # 12种基础样式
# [1, 2, 3, 2, 3, 1, 3, 1, 2]
# [1, 2, 3, 3, 1, 2, 2, 3, 1]
# [1, 3, 2, 2, 1, 3, 3, 2, 1]
# [1, 3, 2, 3, 2, 1, 2, 1, 3]
# [2, 1, 3, 1, 3, 2, 3, 2, 1]
# [2, 1, 3, 3, 2, 1, 1, 3, 2]
# [2, 3, 1, 1, 2, 3, 3, 1, 2]
# [2, 3, 1, 3, 1, 2, 1, 2, 3]
# [3, 1, 2, 1, 2, 3, 2, 3, 1]
# [3, 1, 2, 2, 3, 1, 1, 2, 3]
# [3, 2, 1, 1, 3, 2, 2, 1, 3]
# [3, 2, 1, 2, 1, 3, 1, 3, 2]

# # # 12道题目



print('---------第3步,原始列表生成样式1,了解数量和空格位置----------')
# 读取每一款,假设任意缺1空、任意缺2空,任意缺三空
# 原始列表
import itertools
m=1

for a in  basis[:sz]:

    # 做每种的样式模版一页
    doc = Document(path+fr'\数独长方形({hs}宫格)合并版12标.docx'.format(hs))   

                # 获取第一段
    first_paragraph = doc.paragraphs[0]

    # 在段落中添加运行(run)
    run = first_paragraph.add_run(f"{hs}宫格数独_样式A_标准答案")

    # 设置字体为黑体
    # run.font.name = '等线 (中文正文)'
    # 设置字号为32磅
    run.font.size = Pt(20)
    run.font.bold = True

    # 设置段落居中对齐
    first_paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER  
    #    
    table = doc.tables[0]          # 表0,表2 写标题用的
    # 标题写入3、5单元格  
    for t in range(0,hs*hs):             # 0-5是最下面一行,用来写卡片数字
        pp=int(bg[t][0:2])     # 
        qq=int(bg[t][2:4])
        k=str(a[t])              # 提取list图案列表里面每个图形  t=索引数字
        # print(pp,qq,k)

        # 图案符号的字体、大小参数
        run=table.cell(pp,qq).paragraphs[0].add_run(k)    # 在单元格0,0(第1行第1列)输入第0个图图案
        run.font.name = '黑体'#输入时默认华文彩云字体
        # run.font.size = Pt(46)  #输入字体大小默认30号 换行(一页一份大卡片
        run.font.size = Pt(130) #是否加粗
        # run.font.color.rgb = RGBColor(150,150,150) #数字小,颜色深0-255
        run.font.color.rgb = RGBColor(50,50,50) #数字小,颜色深0-255
        run.bold=True
        # paragraph.paragraph_format.line_spacing = Pt(180) #数字段间距

        r = run._element
        r.rPr.rFonts.set(qn('w:eastAsia'), '黑体')#将输入语句中的中文部分字体变为华文行楷
        table.cell(pp,qq).paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER#居中  

            
    doc.save(path+fr'\数独{hs}宫格数独_样式A_空00基本样式.docx')#保存为XX学号的电话号码word     
    time.sleep(2)



    # 12张一页的样式
    n=0
    xx=0
    
    for x in range(start,hs*hs):
        # 如果报错,就从相应的宫格数字继续生成
        l1=[]
        # 使用 combinations 生成所有不重复的组合
        combinations = list(itertools.combinations(range(len(a)), x))
        # 1有9次,2有36次,,3有84次,4有84次,3有84次,3有84次,3有84次,3有84次,3有84次,3有84次

        # 打印组合及其索引,并将索引位置的内容变成 ''
        for comb in combinations:
            # 创建副本以避免修改原始列表
            modified_list = a[:]
            # 将组合中的索引位置内容替换为 ''
            for index in comb:
                modified_list[index] = ''
            
            # print(f"{modified_list}")
            # print(f"Combination: {[modified_list[i] for i in comb]}, Indices: {comb}")
            l1.append(modified_list)
        # 输出组合的数量
        # print(l)        
        print(f"{x}空有{len(l1)}种")
        # 1空有9种
        # 2空有36种
        # 3空有84种
        # 4空有126种
        # 5空有126种
        # 6空有84种
        # 7空有36种
        # 8空有9种
        # 9空有1种
        n+=len(combinations)
        # # 3宫格1套,511种,
        print(n)    
        # # 3宫格1套,12种图案,每种510,共6132种,
        # print(n*len(basis))
        
#     print(n*576)


        # 将嵌套列表转换为扁平列表
        flat_list = [item for sublist in l1 for item in sublist]
        # print(flat_list)
        print(len(flat_list))

            # 如果条数不满20条,只有一页
        if len(l1) <=gz:
            print(f"{len(l1)} 在范围 1页 内")
            kong = gz - len(l1)
            print(kong)
            Y = 1
            xx+=Y
        # 判断多页情况下,最后一页是否能够凑满20行,凑不满,补空
        else: 
            for z in range(gz, gz*gz, gz):
                if z < len(l1) <= z + gz:
                    # 出现过正好40条,只有两页,但出现了第3空页,少了小于等于z+2-
                    print(f"{len(l1)} 在范围 {z}-{z+gz} 内")
                    # 补多少的空格
                    kong = z + gz - len(l1)
                    print(kong)
                    # 有几页
                    Y = int((z + gz) / gz)
                    xx+=Y
         # 一个列表里面有7个空
        w = [''] * hs*hs
        # 需要14个这种7空的嵌套列表
        v = [w] * kong
        # print(v)

        #i 把实际的填写内容+补充的空格,凑满20的倍数页
        l=l1+v
        print(l)
        print(len(l))
        #  80  
        

        flat_list = [item for sublist in l for item in sublist]

        # 将扁平列表分割成每组12个元素的子列表
        grouped_list = [flat_list[i:i + gz*hs*hs] for i in range(0, len(flat_list),  gz*hs*hs)]
        print(grouped_list)    
        
        
        


        # 20:30-
        print('------第4步:写入docx,word表格正好12格子,写入1页12个-------')
        # 这里
        for z in range(len(grouped_list)):
            doc = Document(path+fr'\数独长方形({hs}宫格)合并版12.docx'.format(hs))   

                        # 获取第一段
            first_paragraph = doc.paragraphs[0]

            # 在段落中添加运行(run)
            run = first_paragraph.add_run(f"{hs}宫格数独_样式A_空{x:02}格{len(l1):03}种_第{z+1}/{len(grouped_list)}页")

            # 设置字体为黑体
            run.font.name = '黑体'
            # 设置字号为32磅
            run.font.size = Pt(20)
            run.font.bold = True

            # 设置段落居中对齐
            first_paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER  
            #    
            table = doc.tables[0]          # 表0,表2 写标题用的
            # 标题写入3、5单元格  
            for t in range(0,len(bg)):             # 0-5是最下面一行,用来写卡片数字
                pp=int(bg[t][0:2])     # 
                qq=int(bg[t][2:4])
                k=str(grouped_list[z][t])              # 提取list图案列表里面每个图形  t=索引数字
                # print(pp,qq,k)

                # 图案符号的字体、大小参数
                run=table.cell(pp,qq).paragraphs[0].add_run(k)    # 在单元格0,0(第1行第1列)输入第0个图图案
                run.font.name = '黑体'#输入时默认华文彩云字体
                # run.font.size = Pt(46)  #输入字体大小默认30号 换行(一页一份大卡片
                run.font.size = Pt(size) #是否加粗
                # run.font.color.rgb = RGBColor(150,150,150) #数字小,颜色深0-255
                run.font.color.rgb = RGBColor(50,50,50) #数字小,颜色深0-255
                run.bold=True
                # paragraph.paragraph_format.line_spacing = Pt(180) #数字段间距

                r = run._element
                r.rPr.rFonts.set(qn('w:eastAsia'), '黑体')#将输入语句中的中文部分字体变为华文行楷
                table.cell(pp,qq).paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER#居中  

                    
            doc.save(tencent1+fr'\{hs}宫格数独_样式A_空{x:02}有{len(l1):03}种_{z+1:02}.docx')#保存为XX学号的电话号码word     
            time.sleep(2)

print(f'共有{xx}张A4',f'共有{n}张小图')   
# 共有44张A4 共有510张小图 

xx=44
n=510

# print('---------第5步,将样式1的所有docx合并到一个docx内----------')

import os
from win32com import client
from docx import Document

# 设置路径
template_path = path+fr'\数独{hs}宫格数独_样式A_空00基本样式.docx'#保存为XX学号的电话号码word  
# template_path = path+r'\数独长方形(3宫格)合并版12空.docx'
# 添加在第一个基本样式文档里

# 合并docx的路径
n1=f'02_{hs}宫格_样式模版_合并_{xx}张A4_{n}张小图'
tencent2=tencent+fr'\{n1}'
os.makedirs(tencent2,exist_ok=True)


output_path = tencent2 + fr'\{n1}.docx' # 替换为你希望保存的文件路径word合并


# 打开Word应用程序
word = client.Dispatch("Word.Application")
word.Visible = False

# 打开模板文档
doc = word.Documents.Open(template_path)

# 获取最后一个段落
last_paragraph = doc.Paragraphs(doc.Paragraphs.Count)

# 遍历源文件夹中的所有Word文件
# 遍历源文件夹中的所有文件
# files = [f for f in os.listdir(tencent1) if f.endswith('.docx')]
# for filename in files[1:]:  # 跳过第一个文件
for filename in os.listdir(tencent1):
    # if filename.endswith('.docx'):
    file_path = os.path.join(tencent1, filename)
    temp_doc = word.Documents.Open(file_path)
    
    # 复制每个文档的内容到模板的最后
    first_para = temp_doc.Paragraphs(1)
    new_para = doc.Content.InsertAfter(first_para.Range.Text + "\n")
    
    # 复制表格到模板的最后
    for table in temp_doc.Tables:
        table.Range.Copy()
        last_paragraph.Range.Paste()
        doc.Content.InsertParagraphAfter()
        time.sleep(4)
        # 删除表格后的一个空行
        last_paragraph.Range.Delete()
    
    temp_doc.Close()

# 保存修改后的文档
doc.SaveAs(output_path)
doc.Close()
word.Quit()
time.sleep(10)

# print('---------第6步,将样式1一个docx转为一个PDF----------')
# from docx2pdf import convert
# # docx 文件另存为PDF文件
# inputFile = tencent2 + fr'\{n1}.docx' 
# outputFile = tencent2 + fr'\{n1}.pdf' 

# # # 先创建 不存在的 文件
# f1 = open(outputFile, 'w')
# f1.close()
# # 再转换往PDF中写入内容
# convert(inputFile, outputFile)
# # 转换 .docx 文件为 PDF

# time.sleep(5)


print('---------第7步,读取样式1合并docx,将数字分别替换。----------')

# # 读取docx的表格数量,制作9*12和数字的列表,分别替换到0000-1520的坐标里,如果是空就不要写入
from docx import Document

# 加载文档
doc1 = Document(output_path)
# 获取所有表格
tables1 = doc1.tables
# 打印表格数量
print(f'一共 {len(tables1)} 张表.')
1+44

li=['3','2','1','2','1','3','1','3','2']*12
print(len(li))

tencent3=tencent+fr'\03_{hs}宫格_样式{int(len(tables1)-1)}套_{xx}张A4_{n}张小图'
os.makedirs(tencent3,exist_ok=True)

basisall=[]
for f in basis :    # 从12条基础里分别替换,乘以12次
    ff=f*int(len(tables1))
    basisall.append(ff)
print(basisall)
print(len(basisall))


for g in range(len(basisall)):
    
    # 第一张基础样式表改数字
    
    table1 = doc1.tables[0]          # 从0+1表格开始
        # 标题写入3、5单元格  
    for t in range(len(bg[0:9])):             # 00,01,02,10,11,12,20,21,22
        pp=int(bg[0:9][t][0:2])     # 
        qq=int(bg[0:9][t][2:4])
        cell_content =table1.cell( pp, qq).text
    
        if cell_content !='':     
            table1.cell(pp, qq).text = ''             # 清空单元格原来的数字,
            k1=str(basis[g][t])             # 换成新的数字
            # print(pp,qq,k1)       

        # 图案符号的字体、大小参数
        run=table1.cell(pp,qq).paragraphs[0].add_run(k1)    # 在单元格0,0(第1行第1列)输入第0个图图案
    
        run.font.name = '黑体'#输入时默认华文彩云字体
        # run.font.size = Pt(46)  #输入字体大小默认30号 换行(一页一份大卡片
        run.font.size = Pt(130) #是否加粗
        # run.font.color.rgb = RGBColor(150,150,150) #数字小,颜色深0-255
        run.font.color.rgb = RGBColor(50,50,50) #数字小,颜色深0-255
        run.bold=True
        # paragraph.paragraph_format.line_spacing = Pt(180) #数字段间距

        r = run._element
        r.rPr.rFonts.set(qn('w:eastAsia'), '黑体')#将输入语句中的中文部分字体变为华文行楷
        table1.cell(pp,qq).paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER#居中

    # 第二到N张表改数字
    for bb in range(1,len(tables1)):
        table1 = doc1.tables[bb]          # 从0+1表格开始
            # 标题写入3、5单元格  
        for t in range(len(bg)):             # 0-5是最下面一行,用来写卡片数字
            pp=int(bg[t][0:2])     # 
            qq=int(bg[t][2:4])
            cell_content =table1.cell( pp, qq).text
        
            if cell_content !='':     
                table1.cell(pp, qq).text = ''             # 清空单元格原来的数字,
                k1=str(basisall[g][t])             # 换成新的数字
                # print(pp,qq,k1)
            else: # 如果是空,就继续空,或者跳过
                k1=''            
                table1.cell(pp, qq).text = k1 
                # print(pp,qq,k1)

            # 图案符号的字体、大小参数
            run=table1.cell(pp,qq).paragraphs[0].add_run(k1)    # 在单元格0,0(第1行第1列)输入第0个图图案
        
            run.font.name = '黑体'#输入时默认华文彩云字体
            # run.font.size = Pt(46)  #输入字体大小默认30号 换行(一页一份大卡片
            run.font.size = Pt(size) #是否加粗
            # run.font.color.rgb = RGBColor(150,150,150) #数字小,颜色深0-255
            run.font.color.rgb = RGBColor(50,50,50) #数字小,颜色深0-255
            run.bold=True
            # paragraph.paragraph_format.line_spacing = Pt(180) #数字段间距

            r = run._element
            r.rPr.rFonts.set(qn('w:eastAsia'), '黑体')#将输入语句中的中文部分字体变为华文行楷
            table1.cell(pp,qq).paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER#居中

         # 把样式01替换成样式XX 
    # 遍历每个段落
    for para in doc1.paragraphs:
        for run1 in para.runs: 
            if g==0:           
                t1='样式A'
                t2=f'样式{g+1:02}'
                if t1 in run1.text:
                    # 替换文本但保留格式
                    run1.text = run1.text.replace(t1, t2)
            else:
                t1=f'样式{g:02}'
            # t1=f'样式A'
                t2=f'样式{g+1:02}'
                if t1 in run1.text:
                    # 替换文本但保留格式
                    run1.text = run1.text.replace(t1, t2)
            
    doc1.save(tencent3+fr'\{hs}宫格数独_样式{g+1:02}_{xx}张A4_{n}张小图.docx')
    time.sleep(2)
    # 把第一页的样式的X改成01】02
    
    

print('---------第9步,把12个样式的docx转成12个PDF----------')
from docx2pdf import convert
for filename in os.listdir(tencent3):
    if filename.endswith('.docx'):
        docx_path = os.path.join(tencent3, filename)
        pdf_path = os.path.join(tencent3, filename.replace('.docx', '.pdf'))
        
        # 先创建不存在的PDF文件
        with open(pdf_path, 'wb') as f:
            pass
        
        # 转换并写入内容到PDF中
        convert(docx_path, pdf_path)
        time.sleep(20)

fin=f'{hs}宫格_样式{gz}套基本形_每套{n}张_共{gz*n}小张'
tencent4=tencent+fr'\04_{fin}'
os.makedirs(tencent4,exist_ok=True)

            
print('----------第4步:把12个PDF合并为一个打印用PDF------------')
        
# 多个PDF合并(CSDN博主「红色小小螃蟹」,https://blog.csdn.net/yangcunbiao/article/details/125248205)
import os
from PyPDF2 import PdfMerger

pdf_lst = [f for f in os.listdir(tencent3) if f.endswith('.pdf')]
pdf_lst = [os.path.join(tencent3, filename) for filename in pdf_lst]
pdf_lst.sort()
file_merger = PdfMerger()
for pdf in pdf_lst:
    print(pdf)
    file_merger.append(pdf)


file_merger.write(tencent4+fr'\{fin}.pdf')
time.sleep(60)

file_merger.close()
# doc.Close()


# 记录程序结束时间
end_time = datetime.now()

# 计算程序运行时间
elapsed_time = end_time - start_time

print(f"动物数独{hs}宫格程序开始时间:{start_time}")
print(f"动物数独{hs}宫格程序结束时间:{end_time}")

# 打印程序运行时间
print("程序运行时间:", elapsed_time)

制作一款3宫格空格的样式word,然后合并成一个word。根据这个基本word模版,替换数字,变出12款docx,转成12个PDF,所有PDF合并成一个PDF。

第1次:3宫格数独生成时间为:50分钟

第2次:3宫格数独生成时间为:32分钟

第3次:3宫格数独生成时间为:32分钟

为了防止保存时间不够,我都用了很长的停顿时间

具体生成流程:

1、生成3宫格所有的图片510张,合成44张A4

2、生成3宫格所有的图片510张,合成44张A4

一套是46张(第1张答案+44张图片+最后1张是空白)(应该也是要去掉,暂时去不掉)

模版里面的“样式A”后续用来替换套数01、02、03

3、在word里面替换数字,生成12套510张图片,所有的图片510张,合成44张A4

每一套样式都是46张

4、把12个PDF合成一个PDF,

46张*12套=552张

3宫格已经用了这么长时间,4宫格用时是几千倍,估计要把代码拆分开来做了,

同时还要想办法把最后的空白页的段落间距缩小到0.7磅

优化版本1:手动调整合并word最后的间距

程序运行到480行,就暂停了,然后打开

时间也很长,48分钟。

合并的pdf,变成540页=(1答案+44图纸)*12,没有空白了

样式1与样式2的连接处没有空白页

最后页页没有空白页,

尝试在代码里将合并word模版里面的最后一段段落间距变成0.7磅

最终代码






# 测试11*11格,2*2一共4套3*3 宫格
'''
目的:数独3宫格(1,2,3)有12套不同的基础模板,对每套题目进行空1=空8的不重复获取。
(12套样式,空1格-空8格,每套510张,共6120小图)
本代码先做样式1,获取基本样式510张,打印时44页,然后尝试用替换方式制作另外的11款
作者:阿夏
时间:2024年11月30日-12月4日


'''
import math,os,time
from itertools import permutations
import random
from win32com.client import constants, gencache
from win32com.client.gencache import EnsureDispatch
from docx import Document
from docx.shared import Pt, RGBColor
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT, WD_BREAK
from docx.oxml.ns import qn
from docxtpl import DocxTemplate
import pandas as pd
from docx2pdf import convert
from datetime import datetime


# 开始时间
start_time = datetime.now()

# 制作"单元格"# 几宫格
hsall=3
# int(input('3宫格数独=3\n'))
hs=hsall
# 内容太多了,容易报错,如果报错,就重新设置起始宫格数字1-8
start=1
# 第几套,第一套
sz=1


print('------第1步:制作单元格-------')

ll=['3'] # 如果输入345
mm=['34']# 3对应的套数是4*3套
gz=int(mm[0][0])*int(mm[0][1])
nn=['36']# 3对应的写入单元格的数字大小36磅 
# ll=['3','4','5','6','7','8','9'] # 如果输入345
# mm=['43','43','32','32','32','32','32']# 3对应的套数是4*3套
# nn=['36','24','36','24','24','24','24']# 3对应的写入单元格的数字大小36磅 
for r in range(len(ll)):
    if hsall ==int(ll[r]):
        # 底边几套.底边看有2份
        db=int(mm[r][0])
        # int(input('底边几套? 3\n'))
        # 侧边几套 侧边看也是2份
        print(db )        
        cb=int(mm[r][1])
        # int(input('侧边几套? 2\n'))
        print(cb)
        size=int(nn[r])
        print(size)        # 写入单元格数字的大小(撑满格子)

# 新建一个”装N份word和PDF“的临时文件夹
path=r'C:\Users\jg2yXRZ\OneDrive\桌面\数独所有可能'


# 新建“单独docx”输出文件夹
tencent=path+fr'\{hs}宫格'
os.makedirs(tencent,exist_ok=True)
tencent1=tencent+fr'\01_{hs}宫格_样式A_单独_X张A4_Y张小图'
os.makedirs(tencent1,exist_ok=True)
        

# 计算不同模板中的单元格坐标,放在bg里
# 棋盘格子数量,

# 如果正方形:底边2*侧边2,就是3*3宫格 2*2=4套,底边边格子数量就是3*2+1=7,侧边格子数量就是3*2+1=7,
# 如果长方形:底边3*侧边2,就是3*3宫格,3*2=6套 底边格子数量就是3*3+2=11,侧边格子数量就是3*2+1=7,
# if db==cb:
db_size = hs*db+db-1
cb_size=  hs*cb+cb-1
print('{}宫格排列底{}侧{}共{}套,底边格子数{}'.format(hs,db,cb,db*cb,db_size ))
print('{}宫格排列底{}侧{}共{}套,侧边格子数{}'.format(hs,db,cb,db*cb,cb_size ))

# 确定每个宫格的左上角坐标 00 04 40  44
bgszm=[]
for a in range(0,cb_size,hs+1):    # 0-11每隔4,写一个坐标  侧边y
    for b in range(0,db_size,hs+1):  # 0-11每隔4,写一个坐标  侧边x
        bgszm.append('{}{}'.format('%02d'%a,'%02d'%b))
print(bgszm)
# 3宫格排列底3侧2共6套,底边格子数11
# 3宫格排列底3侧2共6套,侧边格子数7
# ['0000', '0004', '0008', '0400', '0404', '0408']
    

# 转为元祖
start_coordinates = [(int(s[0:2]), int(s[2:4])) for s in bgszm]
cell_coordinates = []

# 推算每个起始格子后面的单元格数字
for start_coord in start_coordinates:
    i, j = start_coord
    subgrid_coordinates = []
    for x in range(hs):
        for y in range(hs):
            subgrid_coordinates.append((i + x, j + y))
    cell_coordinates.append(subgrid_coordinates)

# 打印结果(元祖样式)
bg=[]
for coordinates in cell_coordinates:
    # print(coordinates)     # [(4, 8), (4, 9), (4, 10), (5, 8), (5, 9), (5, 10), (6, 8), (6, 9), (6, 10)]
    for c in  coordinates:
        print(c)        # 元组 (1, 2) 样式
        s = ''.join(str(num).zfill(2) for num in c)   # zfill将元组 (1, 2) 转换为字符串 '0102' 特别是(5,10)这种必须转成2个数字0510
        print(str(s))        #  '12'
        bg.append(s)  #  '0102'
print(bg)
# 3列4行12个3*3格子
# ['0000', '0001', '0002', '0100', '0101', '0102', '0200', '0201', '0202', 
# '0004', '0005', '0006', '0104', '0105', '0106', '0204', '0205', '0206', 
# '0008', '0009', '0010', '0108', '0109', '0110', '0208', '0209', '0210', 
# '0400', '0401', '0402', '0500', '0501', '0502', '0600', '0601', '0602', 
# '0404', '0405', '0406', '0504', '0505', '0506', '0604', '0605', '0606', 
# '0408', '0409', '0410', '0508', '0509', '0510', '0608', '0609', '0610', 
# '0800', '0801', '0802', '0900', '0901', '0902', '1000', '1001', '1002', 
# '0804', '0805', '0806', '0904', '0905', '0906', '1004', '1005', '1006', 
# '0808', '0809', '0810', '0908', '0909', '0910', '1008', '1009', '1010', 
# '1200', '1201', '1202', '1300', '1301', '1302', '1400', '1401', '1402', 
# '1204', '1205', '1206', '1304', '1305', '1306', '1404', '1405', '1406', 
# '1208', '1209', '1210', '1308', '1309', '1310', '1408', '1409', '1410']

print('------第2步:制作3宫格的12套题的内容-------')

# 制作3宫格的12套题目(没有空格,只有基础模板)
lst=[]
for b in range(1,hs+1):
    lst.append(b)
print(lst)

permutations_list = list(permutations(lst))
numbers = [list(permutation) for permutation in permutations_list]
print(numbers)
# [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
# 6种组合


# 互相组合成3组
import itertools

# 计算排列数量并生成所有可能的排列
combinations2 = list(itertools.permutations(numbers, hs))
# 包含相似的

# 输出排列数量
print(len(combinations2))
# 120

# # 把所有数字都提取成元素
ll=[]
for o1 in combinations2:
    for o2 in o1:
        for o3 in o2:
            ll.append(o3)
            
print(ll)
print(len(ll))
# 1080

v=hs*hs
# 9个数字抽取一组
f=[]
for i in range(int(len(ll)/v)):
    f.append(ll[i*v:i*v+v])
# print(f)
# print(len(f))
#120条


# # # 遍历表格,把0、5、10相同的内容删除,横向的数字1234都正确了,现在只要排除竖向不对的

P=[]
z=[]
for k in f:  

    if int(k[0])!=int(k[3])!=int(k[6]) and int(k[0])+int(k[3])+int(k[6])==6 and\
          int(k[1])!=int(k[4])!=int(k[7]) and int(k[1])+int(k[4])+int(k[7])==6 and\
            int(k[2])!=int(k[5])!=int(k[8]) and int(k[2])+int(k[5])+int(k[8])==6 and\
                int(k[0])!=int(k[1])!=int(k[2]) and int(k[0])+int(k[1])+int(k[2])==6 and\
                    int(k[3])!=int(k[4])!=int(k[5]) and int(k[3])+int(k[4])+int(k[5])==6 and\
                        int(k[6])!=int(k[7])!=int(k[8]) and int(k[6])+int(k[7])+int(k[8])==6 :
        z.append(k)

print(z)
print(len(z))

# 12种基础样式
basis=[]
for hh in z:
    print(hh)
    basis.append(hh)
print(basis)
print(len(basis))    # 12种基础样式
# [1, 2, 3, 2, 3, 1, 3, 1, 2]
# [1, 2, 3, 3, 1, 2, 2, 3, 1]
# [1, 3, 2, 2, 1, 3, 3, 2, 1]
# [1, 3, 2, 3, 2, 1, 2, 1, 3]
# [2, 1, 3, 1, 3, 2, 3, 2, 1]
# [2, 1, 3, 3, 2, 1, 1, 3, 2]
# [2, 3, 1, 1, 2, 3, 3, 1, 2]
# [2, 3, 1, 3, 1, 2, 1, 2, 3]
# [3, 1, 2, 1, 2, 3, 2, 3, 1]
# [3, 1, 2, 2, 3, 1, 1, 2, 3]
# [3, 2, 1, 1, 3, 2, 2, 1, 3]
# [3, 2, 1, 2, 1, 3, 1, 3, 2]

# # # 12道题目



print('---------第3步,原始列表生成样式1,了解数量和空格位置----------')
# 读取每一款,假设任意缺1空、任意缺2空,任意缺三空
# 原始列表
import itertools
m=1

for a in  basis[:sz]:

    # 做每种的样式模版一页
    doc = Document(path+fr'\数独长方形({hs}宫格)合并版12标.docx'.format(hs))   

                # 获取第一段
    first_paragraph = doc.paragraphs[0]

    # 在段落中添加运行(run)
    run = first_paragraph.add_run(f"{hs}宫格数独_样式A_标准答案")

    # 设置字体为黑体
    # run.font.name = '等线 (中文正文)'
    # 设置字号为32磅
    run.font.size = Pt(20)
    run.font.bold = True

    # 设置段落居中对齐
    first_paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER  
    #    
    table = doc.tables[0]          # 表0,表2 写标题用的
    # 标题写入3、5单元格  
    for t in range(0,hs*hs):             # 0-5是最下面一行,用来写卡片数字
        pp=int(bg[t][0:2])     # 
        qq=int(bg[t][2:4])
        k=str(a[t])              # 提取list图案列表里面每个图形  t=索引数字
        # print(pp,qq,k)

        # 图案符号的字体、大小参数
        run=table.cell(pp,qq).paragraphs[0].add_run(k)    # 在单元格0,0(第1行第1列)输入第0个图图案
        run.font.name = '黑体'#输入时默认华文彩云字体
        # run.font.size = Pt(46)  #输入字体大小默认30号 换行(一页一份大卡片
        run.font.size = Pt(130) #是否加粗
        # run.font.color.rgb = RGBColor(150,150,150) #数字小,颜色深0-255
        run.font.color.rgb = RGBColor(50,50,50) #数字小,颜色深0-255
        run.bold=True
        # paragraph.paragraph_format.line_spacing = Pt(180) #数字段间距

        r = run._element
        r.rPr.rFonts.set(qn('w:eastAsia'), '黑体')#将输入语句中的中文部分字体变为华文行楷
        table.cell(pp,qq).paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER#居中  

            
    doc.save(path+fr'\数独{hs}宫格数独_样式A_空00基本样式.docx')#保存为XX学号的电话号码word     
    time.sleep(2)



    # 12张一页的样式
    n=0
    xx=0
    
    for x in range(start,hs*hs):
        # 如果报错,就从相应的宫格数字继续生成
        l1=[]
        # 使用 combinations 生成所有不重复的组合
        combinations = list(itertools.combinations(range(len(a)), x))
        # 1有9次,2有36次,,3有84次,4有84次,3有84次,3有84次,3有84次,3有84次,3有84次,3有84次

        # 打印组合及其索引,并将索引位置的内容变成 ''
        for comb in combinations:
            # 创建副本以避免修改原始列表
            modified_list = a[:]
            # 将组合中的索引位置内容替换为 ''
            for index in comb:
                modified_list[index] = ''
            
            # print(f"{modified_list}")
            # print(f"Combination: {[modified_list[i] for i in comb]}, Indices: {comb}")
            l1.append(modified_list)
        # 输出组合的数量
        # print(l)        
        print(f"{x}空有{len(l1)}种")
        # 1空有9种
        # 2空有36种
        # 3空有84种
        # 4空有126种
        # 5空有126种
        # 6空有84种
        # 7空有36种
        # 8空有9种
        # 9空有1种
        n+=len(combinations)
        # # 3宫格1套,511种,
        print(n)    
        # # 3宫格1套,12种图案,每种510,共6132种,
        # print(n*len(basis))
        
#     print(n*576)


        # 将嵌套列表转换为扁平列表
        flat_list = [item for sublist in l1 for item in sublist]
        # print(flat_list)
        print(len(flat_list))

            # 如果条数不满20条,只有一页
        if len(l1) <=gz:
            print(f"{len(l1)} 在范围 1页 内")
            kong = gz - len(l1)
            print(kong)
            Y = 1
            xx+=Y
        # 判断多页情况下,最后一页是否能够凑满20行,凑不满,补空
        else: 
            for z in range(gz, gz*gz, gz):
                if z < len(l1) <= z + gz:
                    # 出现过正好40条,只有两页,但出现了第3空页,少了小于等于z+2-
                    print(f"{len(l1)} 在范围 {z}-{z+gz} 内")
                    # 补多少的空格
                    kong = z + gz - len(l1)
                    print(kong)
                    # 有几页
                    Y = int((z + gz) / gz)
                    xx+=Y
         # 一个列表里面有7个空
        w = [''] * hs*hs
        # 需要14个这种7空的嵌套列表
        v = [w] * kong
        # print(v)

        #i 把实际的填写内容+补充的空格,凑满20的倍数页
        l=l1+v
        print(l)
        print(len(l))
        #  80  
        

        flat_list = [item for sublist in l for item in sublist]

        # 将扁平列表分割成每组12个元素的子列表
        grouped_list = [flat_list[i:i + gz*hs*hs] for i in range(0, len(flat_list),  gz*hs*hs)]
        print(grouped_list)    
        
        
        


        # 20:30-
        print('------第4步:写入docx,word表格正好12格子,写入1页12个-------')
        # 这里
        for z in range(len(grouped_list)):
            doc = Document(path+fr'\数独长方形({hs}宫格)合并版12.docx'.format(hs))   

                        # 获取第一段
            first_paragraph = doc.paragraphs[0]

            # 在段落中添加运行(run)
            run = first_paragraph.add_run(f"{hs}宫格数独_样式A_空{x:02}格{len(l1):03}种_第{z+1}/{len(grouped_list)}页")

            # 设置字体为黑体
            run.font.name = '黑体'
            # 设置字号为32磅
            run.font.size = Pt(20)
            run.font.bold = True

            # 设置段落居中对齐
            first_paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER  
            #    
            table = doc.tables[0]          # 表0,表2 写标题用的
            # 标题写入3、5单元格  
            for t in range(0,len(bg)):             # 0-5是最下面一行,用来写卡片数字
                pp=int(bg[t][0:2])     # 
                qq=int(bg[t][2:4])
                k=str(grouped_list[z][t])              # 提取list图案列表里面每个图形  t=索引数字
                # print(pp,qq,k)

                # 图案符号的字体、大小参数
                run=table.cell(pp,qq).paragraphs[0].add_run(k)    # 在单元格0,0(第1行第1列)输入第0个图图案
                run.font.name = '黑体'#输入时默认华文彩云字体
                # run.font.size = Pt(46)  #输入字体大小默认30号 换行(一页一份大卡片
                run.font.size = Pt(size) #是否加粗
                # run.font.color.rgb = RGBColor(150,150,150) #数字小,颜色深0-255
                run.font.color.rgb = RGBColor(50,50,50) #数字小,颜色深0-255
                run.bold=True
                # paragraph.paragraph_format.line_spacing = Pt(180) #数字段间距

                r = run._element
                r.rPr.rFonts.set(qn('w:eastAsia'), '黑体')#将输入语句中的中文部分字体变为华文行楷
                table.cell(pp,qq).paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER#居中  

                    
            doc.save(tencent1+fr'\{hs}宫格数独_样式A_空{x:02}有{len(l1):03}种_{z+1:02}.docx')#保存为XX学号的电话号码word     
            time.sleep(2)

print(f'共有{xx}张A4',f'共有{n}张小图')   
# 共有44张A4 共有510张小图 

xx=44
n=510

# print('---------第5步,将样式1的所有docx合并到一个docx内----------')

import os
from win32com import client
from docx import Document

# 设置路径
template_path = path+fr'\数独{hs}宫格数独_样式A_空00基本样式.docx'#保存为XX学号的电话号码word  
# template_path = path+r'\数独长方形(3宫格)合并版12空.docx'
# 添加在第一个基本样式文档里

# 合并docx的路径
n1=f'02_{hs}宫格_样式模版_合并_{xx}张A4_{n}张小图'
tencent2=tencent+fr'\{n1}'
os.makedirs(tencent2,exist_ok=True)


output_path = tencent2 + fr'\{n1}.docx' # 替换为你希望保存的文件路径word合并


# 打开Word应用程序
word = client.Dispatch("Word.Application")
word.Visible = False

# 打开模板文档
doc = word.Documents.Open(template_path)

# 获取最后一个段落
last_paragraph = doc.Paragraphs(doc.Paragraphs.Count)

# 遍历源文件夹中的所有Word文件
# 遍历源文件夹中的所有文件
# files = [f for f in os.listdir(tencent1) if f.endswith('.docx')]
# for filename in files[1:]:  # 跳过第一个文件
for filename in os.listdir(tencent1):
    # if filename.endswith('.docx'):
    file_path = os.path.join(tencent1, filename)
    temp_doc = word.Documents.Open(file_path)
    
    # 复制每个文档的内容到模板的最后
    first_para = temp_doc.Paragraphs(1)
    new_para = doc.Content.InsertAfter(first_para.Range.Text + "\n")
    
    # 复制表格到模板的最后
    for table in temp_doc.Tables:
        table.Range.Copy()
        last_paragraph.Range.Paste()
        doc.Content.InsertParagraphAfter()
        time.sleep(4)
        # 删除表格后的一个空行
        last_paragraph.Range.Delete()
    
    temp_doc.Close()

# 保存修改后的文档
doc.SaveAs(output_path)
doc.Close()
word.Quit()
time.sleep(10)


# 方法1,读取最后一段,把最后的段落的行距变成0.7磅
# 最后一段变成行距0.7
from docx import Document
from docx.shared import Pt

# 加载文档
doc = Document(output_path)

# 获取最后一个段落
last_paragraph = doc.paragraphs[-1]

# 设置行距为0.7磅
last_paragraph.paragraph_format.line_spacing = Pt(0.7)

# 保存文档
doc.save(output_path)

# # 方法2:手动删除模版里大大最后一个空格
# input("手动删除最后一个空白,间距0.7,按回车键继续...")

# print("程序开始运行...")



# print('---------第6步,将样式1一个docx转为一个PDF,这里不用,因为最后还是会转出12个样式doc和pdf----------')
# from docx2pdf import convert
# # docx 文件另存为PDF文件
# inputFile = tencent2 + fr'\{n1}.docx' 
# outputFile = tencent2 + fr'\{n1}.pdf' 

# # # 先创建 不存在的 文件
# f1 = open(outputFile, 'w')
# f1.close()
# # 再转换往PDF中写入内容
# convert(inputFile, outputFile)
# # 转换 .docx 文件为 PDF

# time.sleep(5)


print('---------第7步,读取样式1合并docx,将数字分别替换。----------')

# # 读取docx的表格数量,制作9*12和数字的列表,分别替换到0000-1520的坐标里,如果是空就不要写入
from docx import Document

# 加载文档
doc1 = Document(output_path)
# 获取所有表格
tables1 = doc1.tables
# 打印表格数量
print(f'一共 {len(tables1)} 张表.')
1+44

li=['3','2','1','2','1','3','1','3','2']*12
print(len(li))

tencent3=tencent+fr'\03_{hs}宫格_样式{int(len(tables1)-1)}套_{xx}张A4_{n}张小图'
os.makedirs(tencent3,exist_ok=True)

basisall=[]
for f in basis :    # 从12条基础里分别替换,乘以12次
    ff=f*int(len(tables1))
    basisall.append(ff)
print(basisall)
print(len(basisall))


for g in range(len(basisall)):
    
    # 第一张基础样式表改数字
    
    table1 = doc1.tables[0]          # 从0+1表格开始
        # 标题写入3、5单元格  
    for t in range(len(bg[0:9])):             # 00,01,02,10,11,12,20,21,22
        pp=int(bg[0:9][t][0:2])     # 
        qq=int(bg[0:9][t][2:4])
        cell_content =table1.cell( pp, qq).text
    
        if cell_content !='':     
            table1.cell(pp, qq).text = ''             # 清空单元格原来的数字,
            k1=str(basis[g][t])             # 换成新的数字
            # print(pp,qq,k1)       

        # 图案符号的字体、大小参数
        run=table1.cell(pp,qq).paragraphs[0].add_run(k1)    # 在单元格0,0(第1行第1列)输入第0个图图案
    
        run.font.name = '黑体'#输入时默认华文彩云字体
        # run.font.size = Pt(46)  #输入字体大小默认30号 换行(一页一份大卡片
        run.font.size = Pt(130) #是否加粗
        # run.font.color.rgb = RGBColor(150,150,150) #数字小,颜色深0-255
        run.font.color.rgb = RGBColor(50,50,50) #数字小,颜色深0-255
        run.bold=True
        # paragraph.paragraph_format.line_spacing = Pt(180) #数字段间距

        r = run._element
        r.rPr.rFonts.set(qn('w:eastAsia'), '黑体')#将输入语句中的中文部分字体变为华文行楷
        table1.cell(pp,qq).paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER#居中

    # 第二到N张表改数字
    for bb in range(1,len(tables1)):
        table1 = doc1.tables[bb]          # 从0+1表格开始
            # 标题写入3、5单元格  
        for t in range(len(bg)):             # 0-5是最下面一行,用来写卡片数字
            pp=int(bg[t][0:2])     # 
            qq=int(bg[t][2:4])
            cell_content =table1.cell( pp, qq).text
        
            if cell_content !='':     
                table1.cell(pp, qq).text = ''             # 清空单元格原来的数字,
                k1=str(basisall[g][t])             # 换成新的数字
                # print(pp,qq,k1)
            else: # 如果是空,就继续空,或者跳过
                k1=''            
                table1.cell(pp, qq).text = k1 
                # print(pp,qq,k1)

            # 图案符号的字体、大小参数
            run=table1.cell(pp,qq).paragraphs[0].add_run(k1)    # 在单元格0,0(第1行第1列)输入第0个图图案
        
            run.font.name = '黑体'#输入时默认华文彩云字体
            # run.font.size = Pt(46)  #输入字体大小默认30号 换行(一页一份大卡片
            run.font.size = Pt(size) #是否加粗
            # run.font.color.rgb = RGBColor(150,150,150) #数字小,颜色深0-255
            run.font.color.rgb = RGBColor(50,50,50) #数字小,颜色深0-255
            run.bold=True
            # paragraph.paragraph_format.line_spacing = Pt(180) #数字段间距

            r = run._element
            r.rPr.rFonts.set(qn('w:eastAsia'), '黑体')#将输入语句中的中文部分字体变为华文行楷
            table1.cell(pp,qq).paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER#居中

         # 把样式01替换成样式XX 
    # 遍历每个段落
    for para in doc1.paragraphs:
        for run1 in para.runs: 
            if g==0:           
                t1='样式A'
                t2=f'样式{g+1:02}'
                if t1 in run1.text:
                    # 替换文本但保留格式
                    run1.text = run1.text.replace(t1, t2)
            else:
                t1=f'样式{g:02}'
            # t1=f'样式A'
                t2=f'样式{g+1:02}'
                if t1 in run1.text:
                    # 替换文本但保留格式
                    run1.text = run1.text.replace(t1, t2)
            
    doc1.save(tencent3+fr'\{hs}宫格数独_样式{g+1:02}_{xx}张A4_{n}张小图.docx')
    time.sleep(2)
    # 把第一页的样式的X改成01】02
    
    

print('---------第9步,把12个样式的docx转成12个PDF----------')
from docx2pdf import convert
for filename in os.listdir(tencent3):
    if filename.endswith('.docx'):
        docx_path = os.path.join(tencent3, filename)
        pdf_path = os.path.join(tencent3, filename.replace('.docx', '.pdf'))
        
        # 先创建不存在的PDF文件
        with open(pdf_path, 'wb') as f:
            pass
        
        # 转换并写入内容到PDF中
        convert(docx_path, pdf_path)
        time.sleep(20)

fin=f'{hs}宫格_样式{gz}套基本形_每套{n}张_共{gz*n}小张'
tencent4=tencent+fr'\04_{fin}'
os.makedirs(tencent4,exist_ok=True)

            
print('----------第4步:把12个PDF合并为一个打印用PDF------------')
        
# 多个PDF合并(CSDN博主「红色小小螃蟹」,https://blog.csdn.net/yangcunbiao/article/details/125248205)
import os
from PyPDF2 import PdfMerger

pdf_lst = [f for f in os.listdir(tencent3) if f.endswith('.pdf')]
pdf_lst = [os.path.join(tencent3, filename) for filename in pdf_lst]
pdf_lst.sort()
file_merger = PdfMerger()
for pdf in pdf_lst:
    print(pdf)
    file_merger.append(pdf)


file_merger.write(tencent4+fr'\{fin}.pdf')
time.sleep(60)

file_merger.close()
# doc.Close()


# 记录程序结束时间
end_time = datetime.now()

# 计算程序运行时间
elapsed_time = end_time - start_time

print(f"动物数独{hs}宫格程序开始时间:{start_time}")
print(f"动物数独{hs}宫格程序结束时间:{end_time}")

# 打印程序运行时间
print("程序运行时间:", elapsed_time)

用时30分钟(实际不稳定,经常报错卡死,偶尔一次运行顺利)

最终效果:540页,(1+44)*12,没有空白页

总算全部成功了,如果打印全部540张纸(正反打印),需要270张,以一包A4纸80G为例,全部打印3宫格12套样式每套510张,需要半包250+20张纸,大约2.8CM厚的A4纸。也算是能够全部打印吧。

​​​​​​​

但是4宫格1套样式就是5468+1张,光是正反打印一套4宫格样式就需要5468/2/500=5.4约等于6包,打印厚度28.4336厘米,也就是一张竖版A4纸的厚度29CM,

​​​​​​​

再算上4宫格有576套,那么总高度824.5744厘米,也就是8.24米,已经没有打印的必要了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阿夏reasonsummer

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

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

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

打赏作者

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

抵扣说明:

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

余额充值