mirror of
https://github.com/fumiama/go-docx.git
synced 2026-06-19 09:00:31 +08:00
普适化 template
This commit is contained in:
@@ -17,7 +17,7 @@ func init() {
|
|||||||
func main() {
|
func main() {
|
||||||
fmt.Printf("Preparing new document to write at %s\n", *fileLocation)
|
fmt.Printf("Preparing new document to write at %s\n", *fileLocation)
|
||||||
|
|
||||||
w := docxlib.New()
|
w := docxlib.NewA4()
|
||||||
// add new paragraph
|
// add new paragraph
|
||||||
para1 := w.AddParagraph()
|
para1 := w.AddParagraph()
|
||||||
// add text
|
// add text
|
||||||
|
|||||||
12
docxlib.go
12
docxlib.go
@@ -5,6 +5,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -24,16 +25,21 @@ type Docx struct {
|
|||||||
rId uintptr
|
rId uintptr
|
||||||
imageId uintptr
|
imageId uintptr
|
||||||
|
|
||||||
|
template string
|
||||||
|
tmplfs fs.FS
|
||||||
|
tmpfslst []string
|
||||||
|
|
||||||
buf *bytes.Buffer
|
buf *bytes.Buffer
|
||||||
isbufempty bool
|
isbufempty bool
|
||||||
|
|
||||||
io.Reader
|
io.Reader
|
||||||
io.WriterTo
|
io.WriterTo
|
||||||
}
|
}
|
||||||
|
|
||||||
// New generates a new empty docx file that we can manipulate and
|
// NewA4 generates a new empty A4 docx file that we can manipulate and
|
||||||
// later on, save
|
// later on, save
|
||||||
func New() *Docx {
|
func NewA4() *Docx {
|
||||||
return newEmptyFile()
|
return newEmptyA4File()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse generates a new docx file in memory from a reader
|
// Parse generates a new docx file in memory from a reader
|
||||||
|
|||||||
13
empty.go
13
empty.go
@@ -5,7 +5,7 @@ import (
|
|||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newEmptyFile() *Docx {
|
func newEmptyA4File() *Docx {
|
||||||
docx := &Docx{
|
docx := &Docx{
|
||||||
Document: Document{
|
Document: Document{
|
||||||
XMLName: xml.Name{
|
XMLName: xml.Name{
|
||||||
@@ -45,7 +45,16 @@ func newEmptyFile() *Docx {
|
|||||||
media: make([]Media, 0, 64),
|
media: make([]Media, 0, 64),
|
||||||
mediaNameIdx: make(map[string]int, 64),
|
mediaNameIdx: make(map[string]int, 64),
|
||||||
rId: 3,
|
rId: 3,
|
||||||
buf: bytes.NewBuffer(make([]byte, 0, 1024*1024*4)),
|
template: "a4",
|
||||||
|
tmpfslst: []string{
|
||||||
|
"_rels/.rels",
|
||||||
|
"docProps/app.xml",
|
||||||
|
"docProps/core.xml",
|
||||||
|
"word/theme/theme1.xml",
|
||||||
|
"word/styles.xml",
|
||||||
|
"[Content_Types].xml",
|
||||||
|
},
|
||||||
|
buf: bytes.NewBuffer(make([]byte, 0, 1024*1024*4)),
|
||||||
}
|
}
|
||||||
docx.Document.file = docx
|
docx.Document.file = docx
|
||||||
return docx
|
return docx
|
||||||
|
|||||||
2
fs.go
2
fs.go
@@ -4,6 +4,6 @@ import "embed"
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
//go:embed xml
|
//go:embed xml
|
||||||
//go:embed xml/_rels/*
|
//go:embed xml/a4/_rels/*
|
||||||
TEMP_XML_FS embed.FS
|
TEMP_XML_FS embed.FS
|
||||||
)
|
)
|
||||||
|
|||||||
26
pack.go
26
pack.go
@@ -12,22 +12,24 @@ import (
|
|||||||
// and writes the relevant files. Some of them come from the empty_constants file,
|
// and writes the relevant files. Some of them come from the empty_constants file,
|
||||||
// others from the actual in-memory structure
|
// others from the actual in-memory structure
|
||||||
func (f *Docx) pack(zipWriter *zip.Writer) (err error) {
|
func (f *Docx) pack(zipWriter *zip.Writer) (err error) {
|
||||||
fileslst := []string{
|
|
||||||
"_rels/.rels",
|
|
||||||
"docProps/app.xml",
|
|
||||||
"docProps/core.xml",
|
|
||||||
"word/theme/theme1.xml",
|
|
||||||
"word/styles.xml",
|
|
||||||
"[Content_Types].xml",
|
|
||||||
}
|
|
||||||
files := make(map[string]io.Reader, 64)
|
files := make(map[string]io.Reader, 64)
|
||||||
|
|
||||||
for _, name := range fileslst {
|
if f.template != "" {
|
||||||
files[name], err = TEMP_XML_FS.Open("xml/" + name)
|
for _, name := range f.tmpfslst {
|
||||||
if err != nil {
|
files[name], err = TEMP_XML_FS.Open("xml/" + f.template + "/" + name)
|
||||||
return
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, name := range f.tmpfslst {
|
||||||
|
files[name], err = f.tmplfs.Open(name)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
files["word/_rels/document.xml.rels"] = marshaller{data: &f.DocRelation}
|
files["word/_rels/document.xml.rels"] = marshaller{data: &f.DocRelation}
|
||||||
files["word/document.xml"] = marshaller{data: f.Document}
|
files["word/document.xml"] = marshaller{data: f.Document}
|
||||||
|
|
||||||
|
|||||||
@@ -568,7 +568,7 @@ func TestUnmarshalDrawingStructure(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMarshalDrawingStructure(t *testing.T) {
|
func TestMarshalDrawingStructure(t *testing.T) {
|
||||||
w := New()
|
w := NewA4()
|
||||||
// add new paragraph
|
// add new paragraph
|
||||||
para1 := w.AddParagraph()
|
para1 := w.AddParagraph()
|
||||||
// add text
|
// add text
|
||||||
@@ -594,7 +594,7 @@ func TestMarshalDrawingStructure(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
w = New()
|
w = NewA4()
|
||||||
err = xml.NewDecoder(f).Decode(&w.Document)
|
err = xml.NewDecoder(f).Decode(&w.Document)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
20
unpack.go
20
unpack.go
@@ -16,23 +16,32 @@ import (
|
|||||||
func unpack(zipReader *zip.Reader) (docx *Docx, err error) {
|
func unpack(zipReader *zip.Reader) (docx *Docx, err error) {
|
||||||
docx = new(Docx)
|
docx = new(Docx)
|
||||||
docx.mediaNameIdx = make(map[string]int, 64)
|
docx.mediaNameIdx = make(map[string]int, 64)
|
||||||
|
docx.tmplfs = zipReader
|
||||||
|
docx.tmpfslst = make([]string, 0, 64)
|
||||||
for _, f := range zipReader.File {
|
for _, f := range zipReader.File {
|
||||||
if f.Name == "word/_rels/document.xml.rels" {
|
if f.Name == "word/_rels/document.xml.rels" {
|
||||||
err = docx.parseDocRelation(f)
|
err = docx.parseDocRelation(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
if f.Name == "word/document.xml" {
|
if f.Name == "word/document.xml" {
|
||||||
err = docx.parseDocument(f)
|
err = docx.parseDocument(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
err = docx.checkAndParseMedia(f)
|
if strings.HasPrefix(f.Name, MEDIA_FOLDER) {
|
||||||
if err != nil {
|
err = docx.parseMedia(f)
|
||||||
return
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
// fill remaining files into tmpfslst
|
||||||
|
docx.tmpfslst = append(docx.tmpfslst, f.Name)
|
||||||
}
|
}
|
||||||
docx.buf = bytes.NewBuffer(make([]byte, 0, 1024*1024*4))
|
docx.buf = bytes.NewBuffer(make([]byte, 0, 1024*1024*4))
|
||||||
return
|
return
|
||||||
@@ -72,10 +81,7 @@ func (f *Docx) parseDocRelation(file *zip.File) error {
|
|||||||
return xml.NewDecoder(zf).Decode(&f.DocRelation)
|
return xml.NewDecoder(zf).Decode(&f.DocRelation)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Docx) checkAndParseMedia(file *zip.File) error {
|
func (f *Docx) parseMedia(file *zip.File) error {
|
||||||
if !strings.HasPrefix(file.Name, MEDIA_FOLDER) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
name := file.Name[len(MEDIA_FOLDER):]
|
name := file.Name[len(MEDIA_FOLDER):]
|
||||||
zf, err := file.Open()
|
zf, err := file.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user