Skip to content

Latest commit

 

History

History
415 lines (286 loc) · 10.5 KB

README-zh_CN.md

File metadata and controls

415 lines (286 loc) · 10.5 KB

警告: 当前代码库已完全 废弃 ,具有全新接口的下一代正在大力开发中(尚未上传)。

minidocx

License Documentation Status GitHub code size in bytes GitHub last commit

English | 简体中文

minidocx 是一个跨平台且易于使用的 C++ 库,用于从零开始创建 Microsoft Word 文档 (.docx)。它被设计为足够精简和小巧。因此,你只需要将几个文件与你项目的其他源文件一同编译即可。

环境要求

要构建 minidocx,你需要一个支持 C++ 11 的编译器和下列两个第三方库:

已在下列平台测试通过:

  • CMake 3.21
  • Visual Studio 14 2015 / Visual Studio 16 2019 / GCC 8.2+
  • Windows 7/10 / Ubuntu 18.04 / Kylin-Desktop V10-SP1

参考文献

要处理 .docx 文档,你至少要了解下列 3 个概念:

  • Paragraph 段落,具有相同段落格式的文本
  • Run 富文本,段落中具有相同字体格式的文本
  • Section 分节,具有相同页面设置的一个或多个页面

更多信息见 此网站

示例

下面是一个使用 minidocx 创建 .docx 文件的示例。

#include "minidocx.hpp"

using namespace docx;

int main()
{
  Document doc;

  auto p1 = doc.AppendParagraph("Hello, World!", 12, "Times New Roman");
  auto p2 = doc.AppendParagraph(u8"你好,世界!", 14, u8"宋体");
  auto p3 = doc.AppendParagraph(u8"Hello, 世界!", 16, "Times New Roman", u8"宋体");

  auto p4 = doc.AppendParagraph();
  p4.SetAlignment(Paragraph::Alignment::Centered);

  auto p4r1 = p4.AppendRun("Sample text here...", 12, "Arial");
  p4r1.AppendLineBreak();
  p4r1.SetCharacterSpacing(Pt2Twip(2));

  auto p4r2 = p4.AppendRun("And another line of sample text here...");
  p4r2.SetFontSize(14);
  p4r2.SetFont("Times New Roman");
  p4r2.SetFontColor("FF0000");
  p4r2.SetFontStyle(Run::Bold | Run::Italic);

  doc.Save("basic.docx");
  return 0;
}

更多示例见 examples 文件夹。

构建命令

git clone [email protected]:totravel/minidocx.git
cd minidocx

# Windows
cmake -S . -B build -DBUILD_EXAMPLES=ON -DWITH_STATIC_CRT=OFF
cmake --build build -j4 --config Release
cmake --install build --prefix install --config Release

# Linux
cmake -S . -B build -DBUILD_EXAMPLES=ON -DWITH_STATIC_CRT=OFF -DCMAKE_BUILD_TYPE=Release
cmake --build build -j4
cmake --install build --prefix install

指南

使用 minidocx 的程序只需包含头文件 minidocx.hpp。minidocx 提供的类和函数都定义在命名空间 docx 中。

#include "minidocx.hpp"

using namespace docx;

下文将介绍常用 API。如需了解所有 API,请查阅头文件。

单位

文档的基本单位是缇(Twip),它等于磅的二十分之一。minidocx 提供了一些辅助函数用于单位换算:

int Pt2Twip(const double pt);       // points to twip
double Twip2Pt(const int twip);     // twip to points

int Inch2Twip(const double inch);   // inches to twip
double Twip2Inch(const int twip);   // twip to inches

int MM2Twip(const int mm);          // mm to twip
int Twip2MM(const int twip);        // twip to mm

int CM2Twip(const double cm);       // cm to twip
double Twip2CM(const int twip);     // twip to cm

double Inch2Pt(const double inch);  // inches to points
double Pt2Inch(const double pt);    // points to inches

double MM2Inch(const int mm);       // mm to inches
int Inch2MM(const double inch);     // inches to mm

double CM2Inch(const double cm);    // cm to inches
double Inch2CM(const double inch);  // inches to cm

有关单位转换的更多信息,请参阅 Lars Corneliussen 的博文

文档

Document 表示一个 Microsoft Word 文档。

Document doc;

保存文档的内容:

doc.Save("a.docx");

段落

Paragraph 表示一个段落。有多种方法可以新建段落:

auto p1 = doc.AppendParagraph();         // 在文档结尾追加新段落
auto p3 = doc.InsertParagraphAfter(p1);  // 在 p1 之后插入新段落
auto p2 = doc.InsertParagraphBefore(p3); // 在 p3 之前插入新段落

下列方法用于遍历文档的段落:

auto p1 = doc.FirstParagraph();
auto p3 = doc.LastParagraph();
auto p2 = p3.Prev(); // 还可以用 Next() 方法

段落可以被移除:

doc.RemoveParagraph(p3); // 移除 p3

可以检查两个 Paragraph 对象是否是同一个段落:

if (p1 == p2) {
  std::cout << "They're the same paragraph\n";
}

富文本

向一个段落添加富文本:

auto p4 = doc.AppendParagraph();
auto p4r1 = p4.AppendRun("Hello, World!");
auto p4r2 = p4.AppendRun(u8"你好,世界!");
auto p4r3 = p4.AppendRun(u8"你好,World!");

可以在新建段落的同时添加富文本:

auto p5 = doc.AppendParagraph("Hello, World!");
// is equivalent to:
auto p5 = doc.AppendParagraph();
auto p5r1 = p5.AppendRun("Hello, World!");

添加富文本时可以指定字号和字体(西文和中文字体可以分别设置):

auto p5r2 = p5.AppendRun("Hello, World!", 12, "Times New Roman");

字号以磅为单位。

可以创建空的富文本。富文本在创建之后都可以继续添加更多文本。

auto p5r3 = p5.AppendRun();
p5r3.AppendText("Hello, World!");
p5r3.AppendText(u8"你好,世界!");
p5r3.AppendText(u8"你好,World!");

可以获取富文本包含的文本:

auto text = p5r3.GetText(); // "Hello, World!你好,世界!你好,World!"

设置字体格式:

p5r3.SetFontSize(14);
p5r3.SetFont("Times New Roman");
p5r3.SetFontColor("FF0000");
p5r3.SetFontStyle(Run::Bold | Run::Italic); // 加粗、倾斜
                                            // 还可以用下划线 Run::Underline 和删除线 Run::Strikethrough
p5r3.SetCharacterSpacing(Pt2Twip(2));

要以磅为单位指定字间距,可用辅助函数 Pt2Twip()

下列方法用于遍历段落的富文本:

auto p4r1 = p4.FirstRun(); // 没有 LastRun() 方法
auto p4r2 = p4r1.Next(); // 没有 Prev() 方法

富文本可以被移除:

p4r2.Remove();

换行

可以添加换行符到富文本中:

auto r = p.AppendRun();
r.AppendText("This is");
r.AppendLineBreak();
r.AppendText("a simple sentence.");

分页

分页符是特殊的富文本,只能通过调用 AppendPageBreak() 函数将分页符添加到段落中。

auto r = p.AppendPageBreak();

制表符

你可以用 AppendTabs() 方法插入一个或多个制表符。

auto r = doc.AppendParagraph().AppendRun();
r.AppendText(u8"甲方:");
r.AppendTabs(4);
r.AppendText(u8"乙方:");

分节

任何文档都至少包含一个分节且不可删除。

新建分节需要插入分节符。分节符需要插入到某个段落中:

p3.InsertSectionBreak();

包含分节符的段落将成为分节的最后一个段落。

可以检查一个段落是否包含分节符:

if (p3.HasSectionBreak()) {
  std::cout << "p3 是这一节的最后一个段落\n";
}

段落中的分节符可以被移除:

p3.RemoveSectionBreak();

Section 表示一个分节。下列方法用于遍历文档的分节:

auto s1 = doc.FirstSection();
auto s2 = s1.Next(); // 还可以用 Prev() 方法

下列方法用于遍历分节的段落:

auto p1 = s1.FirstParagraph();

可以检查两个 Section 对象是否是同一分节:

if (s1 == s2) {
  std::cout << "They're the same Section\n";
}

可以设置分节的页面格式:

s1.SetPageSize(MM2Twip(297), MM2Twip(420));        // 纸张大小为 A3
s1.SetPageOrient(Section::Orientation::Landscape); // 纸张方向为横向

页码

底部居中的页码可以用 SetPageNumber() 方法添加,用 RemovePageNumber() 方法移除:

s1.SetPageNumber(docx::Section::PageNumberFormat::Decimal);         // 1, 2, 3, ...
s1.SetPageNumber(docx::Section::PageNumberFormat::NumberInDash, 3); // -3-, -4-, -5-, ...
s1.RemovePageNumber();

表格

要插入表格,可以用 Document 类的 AppendTable() 方法。比如,插入一个 2 行 3 列的表格:

auto tbl = doc.AppendTable(2, 3);

每个单元格都已经包含一个段落。

tbl.GetCell(0, 0).FirstParagraph().AppendRun("AAA");
tbl.GetCell(0, 1).FirstParagraph().AppendRun("BBB");
tbl.GetCell(0, 2).FirstParagraph().AppendRun("CCC");

tbl.GetCell(1, 0).FirstParagraph().AppendRun("DDD");
tbl.GetCell(1, 1).FirstParagraph().AppendRun("EEE");
AAA BBB CCC
DDD EEE

可以设置边框的样式、宽度(磅)和颜色(十六进制):

tbl.SetTopBorders(Table::BorderStyle::Single, 1, "FF0000");      // 单直线, 1 磅, 红色
tbl.SetBottomBorders(Table::BorderStyle::Dotted, 2, "00FF00");   // 点虚线, 2 磅, 绿色
tbl.SetLeftBorders(Table::BorderStyle::Dashed, 3, "0000FF");     // 短划线, 3 磅, 蓝色
tbl.SetRightBorders(Table::BorderStyle::DotDash, 0.5, "FFFF00"); // 点划线, 1/2 磅,黄色
tbl.SetInsideHBorders(Table::BorderStyle::Double, 1, "FF00FF");  // 双直线, 1 磅, 紫色

合并单元格

可以合并相邻且具有相同行数或列数的单元格:

auto c00 = tbl.GetCell(0, 0);
auto c01 = tbl.GetCell(0, 1);
if (tbl.MergeCells(c00, c01)) {
  std::cout << "c00 c01 merged\n";
}

图文框

图文框类似于文本框,但比文本框简单。图文框是特殊的段落,可以 Document::AppendTextFrame() 方法添加。

auto frame = doc.AppendTextFrame(CM2Twip(4), CM2Twip(5));
frame.AppendRun("This is the text frame paragraph.");

设置图文框的位置:

frame.SetPositionX(TextFrame::Position::Left, TextFrame::Anchor::Page);   // 相对于页面
frame.SetPositionY(TextFrame::Position::Top,  TextFrame::Anchor::Margin); // 相对于页边距

设置文本环绕:

frame.SetTextWrapping(TextFrame::Wrapping::Around);

反馈

有任何疑问,可随时在 此处 提问。

许可

根据 MIT 许可条款,任何人都可以免费使用这个库(参见 License.md)。