fumiama / go-docx

One of the most functional libraries to partially read and write .docx files (a.k.a. Microsoft Word documents or ECMA-376 Office Open XML) in Go.
GNU Affero General Public License v3.0
109 stars 14 forks source link

如何读写修改docx文件并且保存呢 #16

Closed huangchengwu closed 6 months ago

huangchengwu commented 9 months ago

如何读写修改docx文件并且保存呢 WriteTo 方法并不能保存修改

huangchengwu commented 9 months ago

2023/11/30 14:00:18 open _rels/: invalid argument 报错

huangchengwu commented 9 months ago

package main

import ( "log" "os"

"github.com/fumiama/go-docx"

)

func main() { readFile, err := os.OpenFile("测试表格.docx", os.O_RDWR|os.O_APPEND|os.O_CREATE, 0755)

if err != nil {
    log.Println(err)
}
fileinfo, err := readFile.Stat()
if err != nil {
    log.Println(err)

}
size := fileinfo.Size()
doc, err := docx.Parse(readFile, size)

if err != nil {
    log.Println(err)
}
defer readFile.Close()

for _, it := range doc.Document.Body.Items {

    switch o := it.(type) {

    case *docx.Paragraph: // printable

        o.Properties = nil
    case *docx.Table: // printable

        o.TableRows[0].TableCells[1].Paragraphs[0].AddText("ss").Shade("clear", "auto", "E7E6E6")

    }

}
// save to file
if err != nil {
    panic(err)
}
_, err = doc.WriteTo(readFile)
if err != nil {
    log.Println(err)
}
err = readFile.Close()
if err != nil {
    log.Println(err)

}

}

fumiama commented 9 months ago

不要用 os.OpenFile, os.O_RDWR|os.O_APPEND|os.O_CREATE 参数会打开文件并定位置最末尾, 所以无法解析出任何内容。你直接运行我的示例程序,在它的基础上修改即可。

huangchengwu commented 9 months ago

我的需求很简单就是打开旧的docx 进行修改后保存 ,但是我发现你的示例没有这个操作都是新建写入然后保存

fumiama commented 9 months ago

docx本质是zip,无法实现直接修改,都是要全部重写。你要真的要覆盖,就Close后用os.Create重新打开文件WriteTo。

huangchengwu commented 9 months ago

package main

import ( "fmt" "log" "os"

"github.com/fumiama/go-docx"

)

func DocAdd() { w := docx.NewA4() // add new paragraph para1 := w.AddParagraph() // add text para1.AddText("test").AddTab() para1.AddText("size").Size("44").AddTab() tbl2 := w.AddTableTwips([]int64{2333, 2333, 2333}, []int64{2333, 2333}).Justification("center") tbl2.TableRows[0].TableCells[0].Shade("clear", "auto", "E7E6E6")

f, err := os.Create("generated.docx")
// save to file
if err != nil {
    panic(err)
}
_, err = w.WriteTo(f)
if err != nil {
    panic(err)
}
err = f.Close()
if err != nil {
    panic(err)
}
log.Println(w.Document.Body.Items)

} func main() { readFile, err := os.OpenFile("测试表格.docx", os.O_RDWR, 0644)

if err != nil {
    log.Println(err)
}
fileinfo, err := readFile.Stat()
if err != nil {
    log.Println(err)

}
size := fileinfo.Size()
doc, err := docx.Parse(readFile, size)

if err != nil {
    log.Println(err)
}
defer readFile.Close()

for _, it := range doc.Document.Body.Items {

    switch o := it.(type) {

    case *docx.Paragraph: // printable

        o.Properties = nil
    case *docx.Table: // printable
        fmt.Println(o)
        o.TableRows[0].TableCells[1].Paragraphs[0].AddText("ss").Shade("clear", "auto", "E7E6E6")

        // for _, tr := range o.TableRows {
        //  for _, tc := range tr.TableCells {

        //      for _, p := range tc.Paragraphs {

        //          if p.String() == "活动名称" {
        //              fmt.Println("==add", o.TableRows[1].TableCells[1])
        //              p.AddText("add")
        //          }
        //          p.Properties = nil
        //      }
        //  }
        // }
    }
    fmt.Println(it)
}

// f, err := os.Create("generated.docx")
// newFile := docx.NewA4()

// para1 := newFile.AddParagraph()
// // add text
// para1.AddText("test").AddTab()

// para1.AddText("size").Size("44").AddTab()
// tbl2 := doc.AddTableTwips([]int64{2333, 2333, 2333}, []int64{2333, 2333}).Justification("end")
// tbl2.TableRows[0].TableCells[0].Shade("clear", "auto", "E7E6E6")

// tbl2.TableRows[0].TableCells[0].AddParagraph().AddText("test11").AddTab()
// tbl2.TableRows[0].TableCells[1].AddParagraph().AddText("test22").AddTab()
// tbl2.TableRows[1].TableCells[1].AddParagraph().AddText("test22").AddTab()
// tbl2.TableRows[2].TableCells[0].AddParagraph().Justification("center").AddText("test22").AddTab().Font("宋体", "宋体", "eastAsia").Bold()

// newFile.AppendFile(doc)

// _, err = io.Copy(f, newFile)
// if err != nil {
//  log.Println(err)
// }

}

不是很理解 是close后在打开在拷贝吗 ,这个是我新的例子拷贝数据过去建新的但是还是存在跟原先不一样的情况

fumiama commented 9 months ago

你是指就算直接读取后保存,也会和原文档不一样是吧,这是因为这个库并没有支持全部docx元素。

huangchengwu commented 9 months ago

![Uploading 1701325392770.jpg…]() ![Uploading 1701325392770.jpg…]()

huangchengwu commented 9 months ago

![Uploading 1701325392770.jpg…]()

huangchengwu commented 9 months ago

![Uploading 1701325392770.jpg…]()

huangchengwu commented 9 months ago

上传不了图片 就是两个表格一个短了一个还是原来的样子

huangchengwu commented 9 months ago

就是页边距没复制过来

huangchengwu commented 9 months ago

可以调整页边距吗

fumiama commented 9 months ago

不行。你可以尝试添加此功能或使用默认页边距。

huangchengwu commented 9 months ago

那我还要最后一个需求,

for _, it := range doc.Document.Body.Items {

    switch o := it.(type) {

    case *docx.Paragraph: // printable
        o.Justification("center")

        fmt.Println("==Paragraph", o)
        // o.Properties = nil
    case *docx.Table: // printable

        o.TableRows[0].TableCells[1].Paragraphs[0].AddText("ss").Shade("clear", "auto", "E7E6E6")

        // for _, tr := range o.TableRows {
        //  for _, tc := range tr.TableCells {

        //      for _, p := range tc.Paragraphs {

        //          if p.String() == "活动名称" {
        //              fmt.Println("==add", o.TableRows[1].TableCells[1])
        //              p.AddText("add")
        //          }
        //          p.Properties = nil
        //      }
        //  }
        // }
    }
    fmt.Println(it)
}

这里面 *docx.Paragraph 我可以替换掉这个字段吗 
fumiama commented 9 months ago

可以啊,doc.Document.Body.Items 你想换啥换啥

huangchengwu commented 9 months ago

创建一个对象然后替换到对应索引的Items 就可以了吗

fumiama commented 9 months ago

可以,你也可以直接改拿到的paragraph,办法很多。