Python编程快速上手——Excel表格创建乘法表案例分析
前言「用 Python 生成乘法表」是很多人写的第一个循环练习但把它写进 Excel 表格难度就上了一个台阶——因为它从「在终端里打印几行字符串」变成了「操作一个真实的文件格式」。这个转变里有几个新手最容易卡住的地方行列号从 1 还是从 0 开始打印出来的对齐和 Excel 里的对齐是不是一回事为什么保存之后打开是空的本文把它当成一个完整的小案例来拆先讲清楚乘法表在数据结构上到底是什么再用不依赖任何第三方库的写法在终端里把它做出来最后平移思路写进 xlsx 文件。这样安排是因为前者可以完整验证后者只是把「输出到哪里」换了个出口。需要说明写 xlsx 要用第三方库本机没有安装因此相关代码是按官方文档逐行推演的骨架具体参数与返回值以对应库的官方文档为准。一、先看结构乘法表只是一个二维数组很多教程一上来就讲单元格反而让人看不清重点。把乘法表抽象出来它非常简单概念在本例中的含义行被乘数从 1 到 N列乘数从 1 到 N单元格两个数的乘积可选的首行首列表头用于标出乘数所以「生成乘法表」只是生成一个 N×N 的二维数据外加一层表头。数据本身与输出格式无关输出到终端、CSV、xlsx 只是出口不同。先把这个二维数据构造出来后面就是搬运工作。二、纯标准库版先在终端里把它打印出来这一步不需要任何第三方库可以完整跑通。重点是先把数据结构和循环边界写对。# 适用于 Python 3.8# 仅用标准库无需安装第三方包def build_table(n):返回一个 n 行 n 列的乘法表元素是乘积。table []for i in range(1, n 1): # range 右端不包含所以要 1row []for j in range(1, n 1):row.append(i * j)table.append(row)return tabledef print_table(table):把二维表按等宽对齐打印出来。n len(table)# 先算每个数字需要的最大宽度保证对齐width len(str(n * n))# 表头行第一列留空后面依次是 1..nheader * width | .join(str(j).rjust(width) for j in range(1, n 1))print(header)print(- * len(header))for i, row in enumerate(table, start1):cells .join(str(v).rjust(width) for v in row)print(str(i).rjust(width) | cells)table build_table(9)print_table(table)# 顺手校验一下数据结构本身print(行数:, len(table))print(列数:, len(table[0]))print(对角线元素:, [table[k][k] for k in range(len(table))])这段代码有两个值得留意的细节。第一个是range(1, n 1)。Python 的range右端是开区间range(1, 10)只会给出 1 到 9。想要 9×9 的表循环必须写成range(1, 10)用变量时就是range(1, n 1)。这是新手最常犯的边界错误写进去的表会悄悄少一行一列。第二个是对齐是靠字符串宽度撑出来的rjust(width)把数字右对齐到统一的宽度。这只是显示层的技巧和 Excel 里的「单元格对齐」完全是两回事——后者是文件里存的格式属性前者只是终端输出。三、写进 xlsx把二维表搬进单元格理解了数据与格式分离换成 xlsx 就很自然了。写 xlsx 需要第三方库这里以 openpyxl 为例# 适用于 Python 3.8# 需要先安装pip install openpyxl# 具体参数与返回值以 openpyxl 官方文档为准from openpyxl import Workbookfrom openpyxl.styles import Alignment, FontN 9wb Workbook()ws wb.activews.title 乘法表# 写表头从 B1 开始横向写 1..N从 A2 开始纵向写 1..Nws.cell(row1, column1, value×)for j in range(1, N 1):ws.cell(row1, columnj 1, valuej) # 第 j 列对应乘数 jws.cell(rowj 1, column1, valuej) # 第 j 行对应被乘数 j# 写乘积行列号都比数据大 1因为有个表头for i in range(1, N 1):for j in range(1, N 1):ws.cell(rowi 1, columnj 1, valuei * j)# 表头加粗for col in range(1, N 2):ws.cell(row1, columncol).font Font(boldTrue)for row in range(1, N 2):ws.cell(rowrow, column1).font Font(boldTrue)# 全部居中让表看起来整齐center Alignment(horizontalcenter, verticalcenter)for row in ws.iter_rows(min_row1, max_rowN 1, min_col1, max_colN 1):for cell in row:cell.alignment center# 固定列宽避免数字挤在一起for col in range(1, N 2):ws.column_dimensions[ws.cell(row1, columncol).column_letter].width 6# 最后一次性保存wb.save(乘法表.xlsx)print(已写出 乘法表.xlsx)这段骨架里有几个关键改名点对照着理解终端版xlsx 版说明print(...)ws.cell(row, column, value)输出位置从终端换成单元格字符串rjust对齐Alignment(horizontalcenter)对齐在 Excel 里是单元格属性手动算widthcolumn_dimensions[...].width列宽由工作表统一控制无wb.save(...)文件必须显式落盘最后一条是新手最大的坑终端版的输出是即时可见的xlsx 版不写save就什么都没有。程序正常退出、没有任何报错但文件根本没生成这是最让人困惑的一种「失败」。四、让表格更像表格几个提升可读性的动作真正的办公表格还需要一些额外处理。这些都属于「格式」层不影响数据正确性但会显著影响可用性冻结首行首列。滚动时表头始终可见长表尤其需要。加边框。乘法表本身是密排数字画上网格线后阅读体验完全不同。表头加底色。用填充色把表头与数据区分开。设置打印区域。明确告诉 Excel 只打印这张表。这些动作里有一部分可以直接说清单元格的对齐、字体、边框是通过把样式对象赋值给cell.alignment、cell.font、cell.border、cell.fill这些属性完成的冻结窗格是工作表的freeze_panes属性打印区域是工作表的print_area属性取值形如A1:J10的区域字符串或区域列表。下面是在前面骨架基础上补上这几项的样子# 适用于 Python 3.8# 需要先安装pip install openpyxl# 具体参数与返回值以 openpyxl 官方文档为准from openpyxl import Workbookfrom openpyxl.styles import Alignment, Border, Font, PatternFill, SideN 9wb Workbook()ws wb.activews.title 乘法表ws.cell(row1, column1, value×)for j in range(1, N 1):ws.cell(row1, columnj 1, valuej)ws.cell(rowj 1, column1, valuej)for i in range(1, N 1):for j in range(1, N 1):ws.cell(rowi 1, columnj 1, valuei * j)# 表头加底色与加粗header_fill PatternFill(fill_typesolid, start_colorFFD9E1F2)bold Font(boldTrue)for col in range(1, N 2):cell ws.cell(row1, columncol)cell.font boldcell.fill header_fillfor row in range(1, N 2):ws.cell(rowrow, column1).font bold# 给所有表格区域画细边框thin Side(stylethin, colorFF999999)box Border(leftthin, rightthin, topthin, bottomthin)center Alignment(horizontalcenter, verticalcenter)for row in ws.iter_rows(min_row1, max_rowN 1, min_col1, max_colN 1):for cell in row:cell.border boxcell.alignment center# 冻结首行与首列B2 表示冻结在 B2 左上方的行列ws.freeze_panes B2# 显式指定打印区域ws.print_area fA1:{ws.cell(row1, columnN 1).column_letter}{N 1}wb.save(乘法表.xlsx)print(已写出 乘法表.xlsx)freeze_panes的取值是一个单元格地址含义是「冻结这个地址左边和上边的行列」。写B2就是冻结第 1 行与第 A 列滚动时表头始终留在视野里——这正是乘法表这种密排数据最需要的效果。样式对象各字段可接受的具体取值颜色是AARRGGBB形式的字符串还是别的写法、边框线型有哪些枚举请以 openpyxl 官方文档为准不要凭印象拼。常见坑点range少写一个 1表小了一圈❌for i in range(1, 9)以为是 9×9实际只得到 8×8。 ✅ 想清楚要几个数range(1, n 1)才是 1 到 n。写完了却忘了保存❌ 代码一路跑完没有任何报错打开目录却找不到文件——因为漏了wb.save(...)。 ✅ 记住工作簿对象只是在内存里必须显式保存到磁盘保存后可以打印一句提示确认走到了这一步。把行列号当成从 0 开始❌ws.cell(row0, column0, value1)想写左上角实际不合法。 ✅ xlsx 的行列号从 1 开始左上角是row1, column1。在有表头的情况下忘了偏移❌ 算出乘积直接写到rowi, columnj把第一行第一列的表头覆盖掉了。 ✅ 有表头时统一加 1 偏移写成rowi 1, columnj 1并在循环外围想清楚表头占了多少行列。用 write_only 模式却按坐标写入❌ 为了「性能好」开Workbook(write_onlyTrue)然后继续用ws.cell(row, column)定位。 ✅ 写模式只能用append()逐行追加且新工作簿必须先用create_sheet()建表。Windows 上手写路径的反斜杠被吃掉了❌wb.save(C:\tables\乘法表.xlsx)里的\t被当成制表符路径乱掉。 ✅ 用原始字符串rC:\tables\乘法表.xlsx或者用 pathlib 拼接路径、使用正斜杠避免手工转义的问题。以为终端对齐和 Excel 对齐是一回事❌ 在终端里靠rjust排得整整齐齐就以为写进 xlsx 也会自动对齐。 ✅ 明白前者是文本排版技巧、后者是单元格格式属性xlsx 里的对齐需要显式设置。总结环节要点数据结构先构造二维数组与输出格式无关循环边界range(1, n 1)右端不包含单元格坐标行列都从 1 开始有表头要整体偏移对齐与列宽属于格式层需要显式设置落盘必须调用保存否则文件不存在这个小案例的价值不在乘法表本身而在于它把「数据结构 → 输出格式」这条链路暴露得很清楚。先把数据算对再考虑往哪里写、写成什么样至于写文件那一端的库其具体类名、参数与返回值请以官方文档为准。