python操作word文档(python-docx)
写这篇博客源于博友的提问,将介绍如何使用python-docx操作word文档。python-docx不支持表格内文本水平居中,可以考虑使用itextpdf,生成pdf的表格然后在转回word。 itexpdf7支持的样式都比较灵活和多样。
1. 效果图
1.1 python-docx文档标题段落效果图
标题、段落可加粗,斜体,居中: 段落各种python-docx提供的默认style如下图:
1.2 python-docx 表格效果图
先使用5 * 5表格,然后在行中分别对某些cell在添加一个小的1*2的table实现 直接用5*9表格,标头部分列cell进行合并,效果图如下: python-docx不够灵活,没法居中等;但自带了比较多的样式: Light Shading如下: Light List样式如下: Light Grid如下: Medium Shading如下: Medium List如下: Dark List效果图如下: Colorful Shading效果图如下:
1.3 itextpdf7表格效果图
2. 安装
前提依赖:
- Python 2.6, 2.7, 3.3, or 3.4
- lxml >= 2.3.2
pip安装python-docx:
pip install python-docx
3. 源代码
3.1 python-docx文档标题段落源码
from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
document = Document()
for i in range(10):
document.add_heading('Heading, level ' + str(i), level=i)
p = document.add_paragraph('A plain paragraph having some ')
p.add_run('bold').bold = True
p.add_run(' and some ')
p.add_run('italic.').italic = True
print(p.style.font.size)
p.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
document.add_paragraph('Intense quote', style='Intense Quote')
document.add_paragraph(
'first item in unordered list', style='List Bullet'
)
document.add_paragraph(
'first item in ordered list', style='List Number'
)
styles = document.styles
for i, j in enumerate(styles):
if (not '_ParagraphStyle' in str(j)):
continue
print(i, str(j))
p1 = document.add_paragraph(str(i) + ' ' + str(j) + ' 居中字体', style=j)
p1.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
p2 = document.add_paragraph(str(i) + ' ' + str(j) + " 不居中~", style=j)
document.save('images/docx_header_paragraph.docx')
3.2 python-docx表格源码
from docx import Document
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
document = Document()
document.add_heading('Document Title', 0)
p = document.add_paragraph('A plain paragraph having some ')
p.add_run('bold').bold = True
p.add_run(' and some ')
p.add_run('italic.').italic = True
print(p.style.font.size)
p.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
document.add_heading('Heading, level 1', level=1)
document.add_paragraph('Intense quote', style='Intense Quote')
document.add_paragraph(
'first item in unordered list', style='List Bullet'
)
document.add_paragraph(
'first item in ordered list', style='List Number'
)
record_score = (
('学习目标-1', '', '', '21', '12.59', '', '', '21', '12.59'),
('学习目标-2', '', '', '16', '10.88', '14', '11.25', '30', '22.13'),
('学习目标-3', '17', '14.11', '', '', '32', '21.95', '49', '36.66')
)
styles = document.styles
table = document.add_table(rows=2, cols=5, style=styles['Table Grid'])
table.alignment = WD_TABLE_ALIGNMENT.CENTER
hdr_cells = table.rows[0].cells
hdr_cells[1].text = '2.1'
hdr_cells[2].text = '3.2'
hdr_cells[3].text = '7.4'
hdr_cells[4].text = '期末成绩'
hdr_cells = table.rows[1].cells
for i in range(5):
if (i == 0):
continue
t1 = hdr_cells[i].add_table(0, 2)
t1_cells = t1.add_row().cells
t1_cells[0].text = '分值'
t1_cells[1].text = '平均分'
for xxmb, l1, l2, l3, l4, l5, l6, l7, l8 in record_score:
row_cells = table.add_row().cells
l = [l1, l2, l3, l4, l5, l6, l7, l8]
for i in range(5):
if (i == 0):
row_cells[i].text = xxmb
continue
t2 = row_cells[i].add_table(0, 2)
t2_cells = t2.add_row().cells
t2_cells[0].text = l[(i - 1) * 2]
t2_cells[1].text = l[(i - 1) * 2 + 1]
p = document.add_paragraph('\n\n\n\n')
table = document.add_table(rows=2, cols=9, style=styles['Table Grid'])
print(table.style.font.size)
table.style.font.size = 80000
print(table.style.font.size)
table.alignment = WD_TABLE_ALIGNMENT.CENTER
hdr_cells = table.rows[0].cells
header = ['', '2.1', '3.2', '7.4', '期末成绩']
for i in range(5):
if (i == 0):
print(hdr_cells[i].width)
continue
tc = hdr_cells[i * 2 - 1].merge(hdr_cells[i * 2])
tc.text = header[i]
row_cells = table.rows[1].cells
for i in range(5):
if (i == 0):
continue
row_cells[i * 2 - 1].text = '分值'
row_cells[i * 2].text = '平均分'
for i, l in enumerate(record_score):
row_cells = table.add_row().cells
for j in range(9):
row_cells[j].text = l[j]
p = document.add_paragraph('\n\n\n\n')
for ii, style in enumerate(styles):
if (not '_TableStyle' in str(style)):
continue
p = document.add_paragraph('\n' + str(ii) + " " + str(style))
table = document.add_table(rows=2, cols=9, style=style)
table.alignment = WD_TABLE_ALIGNMENT.CENTER
hdr_cells = table.rows[0].cells
header = ['', '2.1', '3.2', '7.4', '期末成绩']
for i in range(5):
if (i == 0):
continue
tc = hdr_cells[i * 2 - 1].merge(hdr_cells[i * 2])
tc.text = header[i]
row_cells = table.rows[1].cells
for i in range(5):
if (i == 0):
continue
row_cells[i * 2 - 1].text = '分值'
row_cells[i * 2].text = '平均分'
for i, l in enumerate(record_score):
row_cells = table.add_row().cells
for j in range(9):
row_cells[j].text = l[j]
document.save('images/demo_merge_2.docx')
3.3 itextpdf 表格源码
package com.itextpdf.samples.sandbox.tables;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.properties.*;
import com.itextpdf.layout.renderer.CellRenderer;
import com.itextpdf.layout.renderer.DrawContext;
import com.itextpdf.layout.renderer.IRenderer;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class SimpleTable10_ {
public static final String DEST = "./target/sandbox/tables/simple_table10_.pdf";
public static void main(String[] args) throws Exception {
File file = new File(DEST);
file.getParentFile().mkdirs();
new SimpleTable10_().manipulatePdf(DEST);
}
protected void manipulatePdf(String dest) throws Exception {
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc);
Table table = new Table(UnitValue.createPercentArray(9)).useAllAvailableWidth();
table.setHorizontalAlignment(HorizontalAlignment.CENTER);
table.setVerticalAlignment(VerticalAlignment.MIDDLE);
String[] header = new String[]{"", "2.1", "3.2", "7.4", "期末成绩dd"};
for (int i = 0; i < 5; i++) {
if (i == 0) {
table.addCell("");
continue;
}
Cell cell0 = new Cell(1, 2);
cell0.setHeight(20);
cell0.setNextRenderer(new SimpleTable10_.PositionRenderer(cell0, 0.5f, 0.5f,
header[i], TextAlignment.CENTER));
table.addCell(cell0);
}
for (int i = 0; i < 5; i++) {
if (i == 0) {
table.addCell("");
continue;
}
Cell cell1 = new Cell();
cell1.setHeight(20);
cell1.setNextRenderer(new SimpleTable10_.PositionRenderer(cell1, 0.5f, 0.5f,
"分数grade", TextAlignment.CENTER));
table.addCell(cell1);
Cell cell2 = new Cell();
cell2.setHeight(20);
cell2.setNextRenderer(new SimpleTable10_.PositionRenderer(cell2, 0.5f, 0.5f,
"成绩score", TextAlignment.CENTER));
table.addCell(cell2);
}
Cell sn = new Cell(3, 1).add(new Paragraph("学习目标-1\n学习目标-2\n学习目标-3"));
table.addCell(sn);
List<String> stringList = new ArrayList<>();
stringList.add("\"\", \"\", \"21\", \"12.59\", \"\", \"\", \"21\", \"12.59\"," +
"\"\", \"\", \"16\", \"10.88\", \"14\", \"11.25\", \"20\", \"22.13\"," +
"\"17\", \"14.11\", \"\", \"\", \"32\", \"21.95\", \"49\", \"36.66\"");
String[] scores = stringList.get(0).split(",");
for (int i = 0; i < 24; i++) {
Cell cell7 = new Cell();
cell7.setHeight(20);
cell7.setNextRenderer(new SimpleTable10_.PositionRenderer(cell7, 0.5f, 0.5f,
scores[i].replaceAll("\"", ""), TextAlignment.CENTER));
table.addCell(cell7);
}
doc.add(table);
doc.close();
}
private static class PositionRenderer extends CellRenderer {
private String content;
private TextAlignment alignment;
private float wPct;
private float hPct;
public PositionRenderer(Cell modelElement, float wPct, float hPct,
String content, TextAlignment alignment) {
super(modelElement);
this.content = content;
this.alignment = alignment;
this.wPct = wPct;
this.hPct = hPct;
}
@Override
public IRenderer getNextRenderer() {
return new SimpleTable10_.PositionRenderer((Cell) modelElement, wPct, hPct, content, alignment);
}
@Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
drawContext.getCanvas().stroke();
UnitValue fontSizeUV = getPropertyAsUnitValue(Property.FONT_SIZE);
float x = getOccupiedAreaBBox().getX() + wPct * getOccupiedAreaBBox().getWidth();
float y = getOccupiedAreaBBox().getY() + hPct * (getOccupiedAreaBBox().getHeight()
- (fontSizeUV.isPointValue() ? fontSizeUV.getValue() : 12f) * 1.5f);
new Canvas(drawContext.getDocument().getFirstPage(), drawContext.getDocument().getDefaultPageSize())
.showTextAligned(content, x, y, alignment);
}
}
}
参考
|