file.go 3.6 KB
Newer Older
xurime's avatar
xurime 已提交
1
// Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
xurime's avatar
xurime 已提交
2 3 4 5
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
// Package excelize providing a set of functions that allow you to write to
xurime's avatar
xurime 已提交
6 7 8 9 10
// and read from XLSX / XLSM / XLTM files. Supports reading and writing
// spreadsheet documents generated by Microsoft Exce™ 2007 and later. Supports
// complex components by high compatibility, and provided streaming API for
// generating or reading data from a worksheet with huge amounts of data. This
// library needs Go version 1.10 or later.
xurime's avatar
xurime 已提交
11

xurime's avatar
xurime 已提交
12 13 14 15 16
package excelize

import (
	"archive/zip"
	"bytes"
17
	"errors"
J
Josh Fyne 已提交
18 19
	"fmt"
	"io"
xurime's avatar
xurime 已提交
20 21 22
	"os"
)

xurime's avatar
xurime 已提交
23
// NewFile provides a function to create new file by default template. For
24 25
// example:
//
26
//    xlsx := NewFile()
27
//
28
func NewFile() *File {
29 30 31 32 33 34 35 36 37 38
	file := make(map[string][]byte)
	file["_rels/.rels"] = []byte(XMLHeader + templateRels)
	file["docProps/app.xml"] = []byte(XMLHeader + templateDocpropsApp)
	file["docProps/core.xml"] = []byte(XMLHeader + templateDocpropsCore)
	file["xl/_rels/workbook.xml.rels"] = []byte(XMLHeader + templateWorkbookRels)
	file["xl/theme/theme1.xml"] = []byte(XMLHeader + templateTheme)
	file["xl/worksheets/sheet1.xml"] = []byte(XMLHeader + templateSheet)
	file["xl/styles.xml"] = []byte(XMLHeader + templateStyles)
	file["xl/workbook.xml"] = []byte(XMLHeader + templateWorkbook)
	file["[Content_Types].xml"] = []byte(XMLHeader + templateContentTypes)
39 40
	f := newFile()
	f.SheetCount, f.XLSX = 1, file
41 42
	f.CalcChain = f.calcChainReader()
	f.Comments = make(map[string]*xlsxComments)
43
	f.ContentTypes = f.contentTypesReader()
44
	f.Drawings = make(map[string]*xlsxWsDr)
45
	f.Styles = f.stylesReader()
46 47
	f.DecodeVMLDrawing = make(map[string]*decodeVmlDrawing)
	f.VMLDrawing = make(map[string]*vmlDrawing)
48
	f.WorkBook = f.workbookReader()
xurime's avatar
xurime 已提交
49 50
	f.Relationships = make(map[string]*xlsxRelationships)
	f.Relationships["xl/_rels/workbook.xml.rels"] = f.relsReader("xl/_rels/workbook.xml.rels")
xurime's avatar
xurime 已提交
51
	f.Sheet["xl/worksheets/sheet1.xml"], _ = f.workSheetReader("Sheet1")
52
	f.sheetMap["Sheet1"] = "xl/worksheets/sheet1.xml"
xurime's avatar
xurime 已提交
53
	f.Theme = f.themeReader()
54
	return f
55 56
}

xurime's avatar
xurime 已提交
57
// Save provides a function to override the xlsx file with origin path.
58
func (f *File) Save() error {
J
Josh Fyne 已提交
59
	if f.Path == "" {
xurime's avatar
xurime 已提交
60
		return fmt.Errorf("no path defined for file, consider File.WriteTo or File.Write")
61
	}
62
	return f.SaveAs(f.Path)
xurime's avatar
xurime 已提交
63 64
}

xurime's avatar
xurime 已提交
65 66
// SaveAs provides a function to create or update to an xlsx file at the
// provided path.
67
func (f *File) SaveAs(name string) error {
68 69 70
	if len(name) > FileNameLength {
		return errors.New("file name length exceeds maximum limit")
	}
J
Josh Fyne 已提交
71 72 73 74 75 76 77 78
	file, err := os.OpenFile(name, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666)
	if err != nil {
		return err
	}
	defer file.Close()
	return f.Write(file)
}

xurime's avatar
xurime 已提交
79
// Write provides a function to write to an io.Writer.
J
Josh Fyne 已提交
80
func (f *File) Write(w io.Writer) error {
81 82 83 84 85 86
	_, err := f.WriteTo(w)
	return err
}

// WriteTo implements io.WriterTo to write the file.
func (f *File) WriteTo(w io.Writer) (int64, error) {
87 88 89 90 91 92 93 94 95
	buf, err := f.WriteToBuffer()
	if err != nil {
		return 0, err
	}
	return buf.WriteTo(w)
}

// WriteToBuffer provides a function to get bytes.Buffer from the saved file.
func (f *File) WriteToBuffer() (*bytes.Buffer, error) {
xurime's avatar
xurime 已提交
96
	buf := new(bytes.Buffer)
J
Josh Fyne 已提交
97
	zw := zip.NewWriter(buf)
98 99
	f.calcChainWriter()
	f.commentsWriter()
xurime's avatar
xurime 已提交
100
	f.contentTypesWriter()
101
	f.drawingsWriter()
102
	f.vmlDrawingWriter()
103 104
	f.workBookWriter()
	f.workSheetWriter()
xurime's avatar
xurime 已提交
105
	f.relsWriter()
xurime's avatar
xurime 已提交
106
	f.sharedStringsWriter()
107
	f.styleSheetWriter()
108

109
	for path, content := range f.XLSX {
J
Josh Fyne 已提交
110
		fi, err := zw.Create(path)
xurime's avatar
xurime 已提交
111
		if err != nil {
Z
zaddok 已提交
112
			zw.Close()
113
			return buf, err
xurime's avatar
xurime 已提交
114
		}
115
		_, err = fi.Write(content)
xurime's avatar
xurime 已提交
116
		if err != nil {
Z
zaddok 已提交
117
			zw.Close()
118
			return buf, err
xurime's avatar
xurime 已提交
119 120
		}
	}
121
	return buf, zw.Close()
xurime's avatar
xurime 已提交
122
}