在Go语言实际开发中,会遇到读取、写入或编辑docx格式文件等情况,目前使用比较多的第三方库有
源码:
- github.com/unidoc/unioffice
- github.com/carmel/gooxml
- github.com/nguyenthenguyen/docx
unidoc/unioffice 功能比较齐全,但是收费的,这里就不做介绍了。 carmel/gooxml: 这个库为unidoc/unioffice免费版,即1.4.0收费版,在双重许可证下提供的。在AGPLv3的条款下可以免费使用。虽然没有收费版功能多,但涵盖了大部分基本功能。 nguyenthenguyen/docx: 是一个简单的操作docx文件go语言库
示例
package main
import (
"fmt"
"github.com/carmel/gooxml/document"
"log"
"os"
"strconv"
)
func main() {
doc, err := document.Open("demo.docx")
if err != nil {
log.Fatalf("error opening document: %s", err)
return
}
//批注
for _, docfile := range doc.DocBase.ExtraFiles {
if docfile.ZipPath != "word/comments.xml" { //只处理word/comments.xml
continue
}
file, err := os.Open(docfile.DiskPath)
if err != nil {
continue
}
defer file.Close()
f, err := file.Stat()
if err != nil {
continue
}
size := f.Size()
var fileinfo []byte = make([]byte, size)
_, err = file.Read(fileinfo)
if err != nil {
continue
}
//实际应该解析<w:t>中的数据
fmt.Println(string(fileinfo))
}
//书签
for _, bookmark := range doc.Bookmarks() {
bookname := bookmark.Name()
if len(bookname) == 0 {
continue
}
fmt.Println(bookmark.Name())
}
//页眉
for _, head := range doc.Headers() {
var text string
for _, para := range head.Paragraphs() {
for _, run := range para.Runs() {
text += run.Text()
}
}
if len(text) == 0 {
continue
}
fmt.Println(text)
}
//页脚
for _, footer := range doc.Footers() {
for _, para := range footer.Paragraphs() {
var text string
for _, run := range para.Runs() {
text += run.Text()
}
if len(text) == 0 {
continue
}
fmt.Println(text)
}
}
//输出图片
//var fileBytes []byte
for k, img := range doc.Images { //返回文档内所有图片
fmt.Println("image:", k, img.Format(), img.Path(), img.Size())
}
//doc.Paragraphs()得到包含文档所有的段落的切片
for _, para := range doc.Paragraphs() {
var text string
//run为每个段落相同格式的文字组成的片段
for _, run := range para.Runs() {
text += run.Text()
//fmt.Println("粗体", run.Properties().IsBold(), run.Text()) //判断是否是粗体
//fmt.Println("粗体属性值", run.Properties().BoldValue(), run.Text())
// fmt.Println("斜体", run.Properties().IsItalic(), run.Text()) //判断是否是斜体
//fmt.Println("斜体属性值", run.Properties().ItalicValue(), run.Text())
}
if len(text) == 0 {
continue
}
//打印一段
fmt.Println(text)
}
//获取表格中的文本
for tId, table := range doc.Tables() {
for rowId, run := range table.Rows() {
for cellId, cell := range run.Cells() {
var text string
for _, para := range cell.Paragraphs() {
for _, run := range para.Runs() {
text += run.Text()
//fmt.Println("粗体", run.Properties().IsBold(), run.Text()) //判断是否是粗体
//fmt.Println("粗体属性值", run.Properties().BoldValue(), run.Text())
// fmt.Println("斜体", run.Properties().IsItalic(), run.Text()) //判断是否是斜体
//fmt.Println("斜体属性值", run.Properties().ItalicValue(), run.Text())
}
}
if len(text) == 0 {
continue
}
fmt.Println(text)
fmt.Println("table"+strconv.Itoa(tId), "行"+strconv.Itoa(rowId), "列"+strconv.Itoa(cellId))
}
}
}
}
示例
package main
import (
"github.com/carmel/gooxml/color"
"github.com/carmel/gooxml/common"
"github.com/carmel/gooxml/document"
"github.com/carmel/gooxml/measurement"
"github.com/carmel/gooxml/schema/soo/wml"
"log"
)
func main() {
doc := document.New()
para := doc.AddParagraph() // 新增段落
run := para.AddRun()
//设置段落
para.SetStyle("Title")
para.SetStyle("Heading1") // Heading1 Heading2 Heading3
para.Properties().SetFirstLineIndent(0.5 * measurement.Inch) // 段落添加首行缩进
// 换行处理,使用'\r'
run.AddText("这里是段落文字信息\n这里是第二行段落文字信息") // 添加文字信息
para.Properties().AddSection(wml.ST_SectionMarkNextPage) // 另起一页(用在AddText之后)
//设置字体样式
run.Properties().SetBold(true) // 是否加粗
run.Properties().SetFontFamily("Courier") // 字体
run.Properties().SetSize(15) // 字号
run.Properties().SetColor(color.Red) // 文字颜色
run.Properties().SetKerning(5) // 文字字距
run.Properties().SetCharacterSpacing(5) // 字符间距调整
run.Properties().SetHighlight(wml.ST_HighlightColorYellow) // 设置高亮
run.Properties().SetUnderline(wml.ST_UnderlineWavyDouble, color.Red) // 下划线
// 初始化图片信息
img1, err := common.ImageFromFile("demo.jpg")
if err != nil {
log.Fatalf("unable to create image: %s", err)
}
img1ref, err := doc.AddImage(img1)
if err != nil {
log.Fatalf("unable to add image to document: %s", err)
}
// 将图片添加到对应的段落
anchored, err := para.AddRun().AddDrawingAnchored(img1ref)
if err != nil {
log.Fatalf("unable to add anchored image: %s", err)
}
// 设置图片相关样式
anchored.SetName("图片名称")
anchored.SetSize(2*measurement.Inch, 2*measurement.Inch)
anchored.SetOrigin(wml.WdST_RelFromHPage, wml.WdST_RelFromVTopMargin)
anchored.SetHAlignment(wml.WdST_AlignHCenter)
anchored.SetYOffset(3 * measurement.Inch)
anchored.SetTextWrapSquare(wml.WdST_WrapTextBothSides)
//添加表格
table := doc.AddTable()
// width of the page
table.Properties().SetWidthPercent(100)
// with thick borers
borders := table.Properties().Borders()
borders.SetAll(wml.ST_BorderSingle, color.Auto, measurement.Zero)
row := table.AddRow()
row.AddCell().AddParagraph().AddRun().AddText("姓名")
row = table.AddRow()
row.AddCell().AddParagraph().AddRun().AddText("hello")
doc.SaveToFile("document.docx") // 保存文件路径,此处应为绝对路径
}
示例:
package main
import (
"fmt"
"github.com/nguyenthenguyen/docx"
)
func main() {
// Read from docx file
r, err := docx.ReadDocxFile("./demo.docx")
// Or read from memory
// r, err := docx.ReadDocxFromMemory(data io.ReaderAt, size int64)
// Or read from a filesystem object:
// r, err := docx.ReadDocxFromFS(file string, fs fs.FS)
if err != nil {
panic(err)
}
docx1 := r.Editable()
//获取内容
content:=docx1.GetContent()
fmt.Println(content)
r.Close()
}
示例:
package main
import (
"fmt"
"github.com/nguyenthenguyen/docx"
)
func main() {
r, err := docx.ReadDocxFile("./demo.docx")
if err != nil {
panic(err)
}
docx1 := r.Editable()
//替换内容
docx1.Replace("旧文字", "新文字", -1)
docx1.ReplaceLink("http://example.com/", "https://github.com/nguyenthenguyen/docx", 1)
//替换页头信息
docx1.ReplaceHeader("head", "页头")
//替换页尾信息
docx1.ReplaceFooter("第一页", "new footer")
//替换图片
//docx1.ReplaceImage("word/media/image1.png", "./new.png")
docx1.WriteToFile("./new_demo.docx")
r.Close()
}
https://pkg.go.dev/github.com/nguyenthenguyen/docx#section-readme https://www.cnblogs.com/xingzr/p/17370295.html
- 目录
- 上一节:
- 下一节: