summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--stream.go219
-rw-r--r--stream_test.go66
-rw-r--r--xmlTable.go1
-rw-r--r--xmlWorksheet.go180
4 files changed, 386 insertions, 80 deletions
diff --git a/stream.go b/stream.go
new file mode 100644
index 0000000..0d91ddd
--- /dev/null
+++ b/stream.go
@@ -0,0 +1,219 @@
+// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of
+// 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
+// and read from XLSX files. Support reads and writes XLSX file generated by
+// Microsoft Excelâ„¢ 2007 and later. Support save file without losing original
+// charts of XLSX. This library needs Go version 1.10 or later.
+
+package excelize
+
+import (
+ "bytes"
+ "encoding/xml"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "reflect"
+)
+
+// StreamWriter defined the type of stream writer.
+type StreamWriter struct {
+ tmpFile *os.File
+ File *File
+ Sheet string
+ SheetID int
+ SheetData bytes.Buffer
+}
+
+// NewStreamWriter return stream writer struct by given worksheet name for
+// generate new worksheet with large amounts of data. Note that after set
+// rows, you must call the 'Flush' method to end the streaming writing
+// process and ensure that the order of line numbers is ascending. For
+// example, set data for worksheet of size 102400 rows x 50 columns with
+// numbers:
+//
+// file := excelize.NewFile()
+// streamWriter, err := file.NewStreamWriter("Sheet1")
+// if err != nil {
+// panic(err)
+// }
+// for rowID := 1; rowID <= 102400; rowID++ {
+// row := make([]interface{}, 50)
+// for colID := 0; colID < 50; colID++ {
+// row[colID] = rand.Intn(640000)
+// }
+// cell, _ := excelize.CoordinatesToCellName(1, rowID)
+// if err := streamWriter.SetRow(cell, &row); err != nil {
+// panic(err)
+// }
+// }
+// if err := streamWriter.Flush(); err != nil {
+// panic(err)
+// }
+// if err := file.SaveAs("Book1.xlsx"); err != nil {
+// panic(err)
+// }
+//
+func (f *File) NewStreamWriter(sheet string) (*StreamWriter, error) {
+ sheetID := f.GetSheetIndex(sheet)
+ if sheetID == 0 {
+ return nil, fmt.Errorf("sheet %s is not exist", sheet)
+ }
+ rsw := &StreamWriter{
+ File: f,
+ Sheet: sheet,
+ SheetID: sheetID,
+ }
+ rsw.SheetData.WriteString("<sheetData>")
+ return rsw, nil
+}
+
+// SetRow writes an array to streaming row by given worksheet name, starting
+// coordinate and a pointer to array type 'slice'. Note that, cell settings
+// with styles are not supported currently and after set rows, you must call the
+// 'Flush' method to end the streaming writing process. The following
+// shows the supported data types:
+//
+// int
+// string
+//
+func (sw *StreamWriter) SetRow(axis string, slice interface{}) error {
+ col, row, err := CellNameToCoordinates(axis)
+ if err != nil {
+ return err
+ }
+ // Make sure 'slice' is a Ptr to Slice
+ v := reflect.ValueOf(slice)
+ if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Slice {
+ return errors.New("pointer to slice expected")
+ }
+ v = v.Elem()
+ sw.SheetData.WriteString(fmt.Sprintf(`<row r="%d">`, row))
+ for i := 0; i < v.Len(); i++ {
+ axis, err := CoordinatesToCellName(col+i, row)
+ if err != nil {
+ return err
+ }
+ switch val := v.Index(i).Interface().(type) {
+ case int:
+ sw.SheetData.WriteString(fmt.Sprintf(`<c r="%s"><v>%d</v></c>`, axis, val))
+ case string:
+ sw.SheetData.WriteString(sw.setCellStr(axis, val))
+ default:
+ sw.SheetData.WriteString(sw.setCellStr(axis, fmt.Sprint(val)))
+ }
+ }
+ sw.SheetData.WriteString(`</row>`)
+ // Try to use local storage
+ chunk := 1 << 24
+ if sw.SheetData.Len() >= chunk {
+ if sw.tmpFile == nil {
+ err := sw.createTmp()
+ if err != nil {
+ // can not use local storage
+ return nil
+ }
+ }
+ // use local storage
+ _, err := sw.tmpFile.Write(sw.SheetData.Bytes())
+ if err != nil {
+ return nil
+ }
+ sw.SheetData.Reset()
+ }
+ return err
+}
+
+// Flush ending the streaming writing process.
+func (sw *StreamWriter) Flush() error {
+ sw.SheetData.WriteString(`</sheetData>`)
+
+ ws, err := sw.File.workSheetReader(sw.Sheet)
+ if err != nil {
+ return err
+ }
+ sheetXML := fmt.Sprintf("xl/worksheets/sheet%d.xml", sw.SheetID)
+ delete(sw.File.Sheet, sheetXML)
+ delete(sw.File.checked, sheetXML)
+ var sheetDataByte []byte
+ if sw.tmpFile != nil {
+ // close the local storage file
+ if err = sw.tmpFile.Close(); err != nil {
+ return err
+ }
+
+ file, err := os.Open(sw.tmpFile.Name())
+ if err != nil {
+ return err
+ }
+
+ sheetDataByte, err = ioutil.ReadAll(file)
+ if err != nil {
+ return err
+ }
+
+ if err := file.Close(); err != nil {
+ return err
+ }
+
+ err = os.Remove(sw.tmpFile.Name())
+ if err != nil {
+ return err
+ }
+ }
+
+ sheetDataByte = append(sheetDataByte, sw.SheetData.Bytes()...)
+ replaceMap := map[string][]byte{
+ "XMLName": []byte{},
+ "SheetData": sheetDataByte,
+ }
+ sw.SheetData.Reset()
+ sw.File.XLSX[fmt.Sprintf("xl/worksheets/sheet%d.xml", sw.SheetID)] =
+ StreamMarshalSheet(ws, replaceMap)
+ return err
+}
+
+// createTmp creates a temporary file in the operating system default
+// temporary directory.
+func (sw *StreamWriter) createTmp() (err error) {
+ sw.tmpFile, err = ioutil.TempFile(os.TempDir(), "excelize-")
+ return err
+}
+
+// StreamMarshalSheet provides method to serialization worksheets by field as
+// streaming.
+func StreamMarshalSheet(ws *xlsxWorksheet, replaceMap map[string][]byte) []byte {
+ s := reflect.ValueOf(ws).Elem()
+ typeOfT := s.Type()
+ var marshalResult []byte
+ marshalResult = append(marshalResult, []byte(XMLHeader+`<worksheet`+templateNamespaceIDMap)...)
+ for i := 0; i < s.NumField(); i++ {
+ f := s.Field(i)
+ content, ok := replaceMap[typeOfT.Field(i).Name]
+ if ok {
+ marshalResult = append(marshalResult, content...)
+ continue
+ }
+ out, _ := xml.Marshal(f.Interface())
+ marshalResult = append(marshalResult, out...)
+ }
+ marshalResult = append(marshalResult, []byte(`</worksheet>`)...)
+ return marshalResult
+}
+
+// setCellStr provides a function to set string type value of a cell as
+// streaming. Total number of characters that a cell can contain 32767
+// characters.
+func (sw *StreamWriter) setCellStr(axis, value string) string {
+ if len(value) > 32767 {
+ value = value[0:32767]
+ }
+ // Leading and ending space(s) character detection.
+ if len(value) > 0 && (value[0] == 32 || value[len(value)-1] == 32) {
+ return fmt.Sprintf(`<c xml:space="preserve" r="%s" t="str"><v>%s</v></c>`, axis, value)
+ }
+ return fmt.Sprintf(`<c r="%s" t="str"><v>%s</v></c>`, axis, value)
+}
diff --git a/stream_test.go b/stream_test.go
new file mode 100644
index 0000000..97c55a7
--- /dev/null
+++ b/stream_test.go
@@ -0,0 +1,66 @@
+package excelize
+
+import (
+ "math/rand"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestStreamWriter(t *testing.T) {
+ file := NewFile()
+ streamWriter, err := file.NewStreamWriter("Sheet1")
+ assert.NoError(t, err)
+
+ // Test max characters in a cell.
+ row := make([]interface{}, 1)
+ row[0] = strings.Repeat("c", 32769)
+ assert.NoError(t, streamWriter.SetRow("A1", &row))
+
+ // Test leading and ending space(s) character characters in a cell.
+ row = make([]interface{}, 1)
+ row[0] = " characters"
+ assert.NoError(t, streamWriter.SetRow("A2", &row))
+
+ row = make([]interface{}, 1)
+ row[0] = []byte("Word")
+ assert.NoError(t, streamWriter.SetRow("A3", &row))
+
+ for rowID := 10; rowID <= 51200; rowID++ {
+ row := make([]interface{}, 50)
+ for colID := 0; colID < 50; colID++ {
+ row[colID] = rand.Intn(640000)
+ }
+ cell, _ := CoordinatesToCellName(1, rowID)
+ assert.NoError(t, streamWriter.SetRow(cell, &row))
+ }
+
+ err = streamWriter.Flush()
+ assert.NoError(t, err)
+ // Save xlsx file by the given path.
+ assert.NoError(t, file.SaveAs(filepath.Join("test", "TestStreamWriter.xlsx")))
+
+ // Test error exceptions
+ streamWriter, err = file.NewStreamWriter("SheetN")
+ assert.EqualError(t, err, "sheet SheetN is not exist")
+}
+
+func TestFlush(t *testing.T) {
+ // Test error exceptions
+ file := NewFile()
+ streamWriter, err := file.NewStreamWriter("Sheet1")
+ assert.NoError(t, err)
+ streamWriter.Sheet = "SheetN"
+ assert.EqualError(t, streamWriter.Flush(), "sheet SheetN is not exist")
+}
+
+func TestSetRow(t *testing.T) {
+ // Test error exceptions
+ file := NewFile()
+ streamWriter, err := file.NewStreamWriter("Sheet1")
+ assert.NoError(t, err)
+ assert.EqualError(t, streamWriter.SetRow("A", &[]interface{}{}), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
+ assert.EqualError(t, streamWriter.SetRow("A1", []interface{}{}), `pointer to slice expected`)
+}
diff --git a/xmlTable.go b/xmlTable.go
index ca4ce03..017bda1 100644
--- a/xmlTable.go
+++ b/xmlTable.go
@@ -44,6 +44,7 @@ type xlsxTable struct {
// applied column by column to a table of data in the worksheet. This collection
// expresses AutoFilter settings.
type xlsxAutoFilter struct {
+ XMLName xml.Name `xml:"autoFilter"`
Ref string `xml:"ref,attr"`
FilterColumn *xlsxFilterColumn `xml:"filterColumn"`
}
diff --git a/xmlWorksheet.go b/xmlWorksheet.go
index cb854cd..a071e4d 100644
--- a/xmlWorksheet.go
+++ b/xmlWorksheet.go
@@ -59,7 +59,8 @@ type xlsxWorksheet struct {
// xlsxDrawing change r:id to rid in the namespace.
type xlsxDrawing struct {
- RID string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
+ XMLName xml.Name `xml:"drawing"`
+ RID string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
}
// xlsxHeaderFooter directly maps the headerFooter element in the namespace
@@ -70,6 +71,7 @@ type xlsxDrawing struct {
// footers on the first page can differ from those on odd- and even-numbered
// pages. In the latter case, the first page is not considered an odd page.
type xlsxHeaderFooter struct {
+ XMLName xml.Name `xml:"headerFooter"`
AlignWithMargins bool `xml:"alignWithMargins,attr,omitempty"`
DifferentFirst bool `xml:"differentFirst,attr,omitempty"`
DifferentOddEven bool `xml:"differentOddEven,attr,omitempty"`
@@ -91,32 +93,33 @@ type xlsxHeaderFooter struct {
// each of the left section, center section and right section of a header and
// a footer.
type xlsxDrawingHF struct {
- Content string `xml:",chardata"`
+ Content string `xml:",innerxml"`
}
// xlsxPageSetUp directly maps the pageSetup element in the namespace
// http://schemas.openxmlformats.org/spreadsheetml/2006/main - Page setup
// settings for the worksheet.
type xlsxPageSetUp struct {
- BlackAndWhite bool `xml:"blackAndWhite,attr,omitempty"`
- CellComments string `xml:"cellComments,attr,omitempty"`
- Copies int `xml:"copies,attr,omitempty"`
- Draft bool `xml:"draft,attr,omitempty"`
- Errors string `xml:"errors,attr,omitempty"`
- FirstPageNumber int `xml:"firstPageNumber,attr,omitempty"`
- FitToHeight int `xml:"fitToHeight,attr,omitempty"`
- FitToWidth int `xml:"fitToWidth,attr,omitempty"`
- HorizontalDPI float32 `xml:"horizontalDpi,attr,omitempty"`
- RID string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
- Orientation string `xml:"orientation,attr,omitempty"`
- PageOrder string `xml:"pageOrder,attr,omitempty"`
- PaperHeight string `xml:"paperHeight,attr,omitempty"`
- PaperSize int `xml:"paperSize,attr,omitempty"`
- PaperWidth string `xml:"paperWidth,attr,omitempty"`
- Scale int `xml:"scale,attr,omitempty"`
- UseFirstPageNumber bool `xml:"useFirstPageNumber,attr,omitempty"`
- UsePrinterDefaults bool `xml:"usePrinterDefaults,attr,omitempty"`
- VerticalDPI float32 `xml:"verticalDpi,attr,omitempty"`
+ XMLName xml.Name `xml:"pageSetup"`
+ BlackAndWhite bool `xml:"blackAndWhite,attr,omitempty"`
+ CellComments string `xml:"cellComments,attr,omitempty"`
+ Copies int `xml:"copies,attr,omitempty"`
+ Draft bool `xml:"draft,attr,omitempty"`
+ Errors string `xml:"errors,attr,omitempty"`
+ FirstPageNumber int `xml:"firstPageNumber,attr,omitempty"`
+ FitToHeight int `xml:"fitToHeight,attr,omitempty"`
+ FitToWidth int `xml:"fitToWidth,attr,omitempty"`
+ HorizontalDPI float32 `xml:"horizontalDpi,attr,omitempty"`
+ RID string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
+ Orientation string `xml:"orientation,attr,omitempty"`
+ PageOrder string `xml:"pageOrder,attr,omitempty"`
+ PaperHeight string `xml:"paperHeight,attr,omitempty"`
+ PaperSize int `xml:"paperSize,attr,omitempty"`
+ PaperWidth string `xml:"paperWidth,attr,omitempty"`
+ Scale int `xml:"scale,attr,omitempty"`
+ UseFirstPageNumber bool `xml:"useFirstPageNumber,attr,omitempty"`
+ UsePrinterDefaults bool `xml:"usePrinterDefaults,attr,omitempty"`
+ VerticalDPI float32 `xml:"verticalDpi,attr,omitempty"`
}
// xlsxPrintOptions directly maps the printOptions element in the namespace
@@ -124,44 +127,48 @@ type xlsxPageSetUp struct {
// the sheet. Printer-specific settings are stored separately in the Printer
// Settings part.
type xlsxPrintOptions struct {
- GridLines bool `xml:"gridLines,attr,omitempty"`
- GridLinesSet bool `xml:"gridLinesSet,attr,omitempty"`
- Headings bool `xml:"headings,attr,omitempty"`
- HorizontalCentered bool `xml:"horizontalCentered,attr,omitempty"`
- VerticalCentered bool `xml:"verticalCentered,attr,omitempty"`
+ XMLName xml.Name `xml:"printOptions"`
+ GridLines bool `xml:"gridLines,attr,omitempty"`
+ GridLinesSet bool `xml:"gridLinesSet,attr,omitempty"`
+ Headings bool `xml:"headings,attr,omitempty"`
+ HorizontalCentered bool `xml:"horizontalCentered,attr,omitempty"`
+ VerticalCentered bool `xml:"verticalCentered,attr,omitempty"`
}
// xlsxPageMargins directly maps the pageMargins element in the namespace
// http://schemas.openxmlformats.org/spreadsheetml/2006/main - Page margins for
// a sheet or a custom sheet view.
type xlsxPageMargins struct {
- Bottom float64 `xml:"bottom,attr"`
- Footer float64 `xml:"footer,attr"`
- Header float64 `xml:"header,attr"`
- Left float64 `xml:"left,attr"`
- Right float64 `xml:"right,attr"`
- Top float64 `xml:"top,attr"`
+ XMLName xml.Name `xml:"pageMargins"`
+ Bottom float64 `xml:"bottom,attr"`
+ Footer float64 `xml:"footer,attr"`
+ Header float64 `xml:"header,attr"`
+ Left float64 `xml:"left,attr"`
+ Right float64 `xml:"right,attr"`
+ Top float64 `xml:"top,attr"`
}
// xlsxSheetFormatPr directly maps the sheetFormatPr element in the namespace
// http://schemas.openxmlformats.org/spreadsheetml/2006/main. This element
// specifies the sheet formatting properties.
type xlsxSheetFormatPr struct {
- BaseColWidth uint8 `xml:"baseColWidth,attr,omitempty"`
- DefaultColWidth float64 `xml:"defaultColWidth,attr,omitempty"`
- DefaultRowHeight float64 `xml:"defaultRowHeight,attr"`
- CustomHeight bool `xml:"customHeight,attr,omitempty"`
- ZeroHeight bool `xml:"zeroHeight,attr,omitempty"`
- ThickTop bool `xml:"thickTop,attr,omitempty"`
- ThickBottom bool `xml:"thickBottom,attr,omitempty"`
- OutlineLevelRow uint8 `xml:"outlineLevelRow,attr,omitempty"`
- OutlineLevelCol uint8 `xml:"outlineLevelCol,attr,omitempty"`
+ XMLName xml.Name `xml:"sheetFormatPr"`
+ BaseColWidth uint8 `xml:"baseColWidth,attr,omitempty"`
+ DefaultColWidth float64 `xml:"defaultColWidth,attr,omitempty"`
+ DefaultRowHeight float64 `xml:"defaultRowHeight,attr"`
+ CustomHeight bool `xml:"customHeight,attr,omitempty"`
+ ZeroHeight bool `xml:"zeroHeight,attr,omitempty"`
+ ThickTop bool `xml:"thickTop,attr,omitempty"`
+ ThickBottom bool `xml:"thickBottom,attr,omitempty"`
+ OutlineLevelRow uint8 `xml:"outlineLevelRow,attr,omitempty"`
+ OutlineLevelCol uint8 `xml:"outlineLevelCol,attr,omitempty"`
}
// xlsxSheetViews directly maps the sheetViews element in the namespace
// http://schemas.openxmlformats.org/spreadsheetml/2006/main - Worksheet views
// collection.
type xlsxSheetViews struct {
+ XMLName xml.Name `xml:"sheetViews"`
SheetView []xlsxSheetView `xml:"sheetView"`
}
@@ -263,7 +270,8 @@ type xlsxTabColor struct {
// http://schemas.openxmlformats.org/spreadsheetml/2006/main - currently I have
// not checked it for completeness - it does as much as I need.
type xlsxCols struct {
- Col []xlsxCol `xml:"col"`
+ XMLName xml.Name `xml:"cols"`
+ Col []xlsxCol `xml:"col"`
}
// xlsxCol directly maps the col (Column Width & Formatting). Defines column
@@ -289,7 +297,8 @@ type xlsxCol struct {
// When an entire column is formatted, only the first cell in that column is
// considered used.
type xlsxDimension struct {
- Ref string `xml:"ref,attr"`
+ XMLName xml.Name `xml:"dimension"`
+ Ref string `xml:"ref,attr"`
}
// xlsxSheetData directly maps the sheetData element in the namespace
@@ -322,6 +331,7 @@ type xlsxRow struct {
// xlsxCustomSheetViews directly maps the customSheetViews element. This is a
// collection of custom sheet views.
type xlsxCustomSheetViews struct {
+ XMLName xml.Name `xml:"customSheetViews"`
CustomSheetView []*xlsxCustomSheetView `xml:"customSheetView"`
}
@@ -384,13 +394,15 @@ type xlsxMergeCell struct {
// xlsxMergeCells directly maps the mergeCells element. This collection
// expresses all the merged cells in the sheet.
type xlsxMergeCells struct {
- Count int `xml:"count,attr,omitempty"`
- Cells []*xlsxMergeCell `xml:"mergeCell,omitempty"`
+ XMLName xml.Name `xml:"mergeCells"`
+ Count int `xml:"count,attr,omitempty"`
+ Cells []*xlsxMergeCell `xml:"mergeCell,omitempty"`
}
// xlsxDataValidations expresses all data validation information for cells in a
// sheet which have data validation features applied.
type xlsxDataValidations struct {
+ XMLName xml.Name `xml:"dataValidations"`
Count int `xml:"count,attr,omitempty"`
DisablePrompts bool `xml:"disablePrompts,attr,omitempty"`
XWindow int `xml:"xWindow,attr,omitempty"`
@@ -434,14 +446,15 @@ type DataValidation struct {
// str (String) | Cell containing a formula string.
//
type xlsxC struct {
- R string `xml:"r,attr"` // Cell ID, e.g. A1
- S int `xml:"s,attr,omitempty"` // Style reference.
- // Str string `xml:"str,attr,omitempty"` // Style reference.
- T string `xml:"t,attr,omitempty"` // Type.
- F *xlsxF `xml:"f,omitempty"` // Formula
- V string `xml:"v,omitempty"` // Value
- IS *xlsxSI `xml:"is"`
+ XMLName xml.Name `xml:"c"`
XMLSpace xml.Attr `xml:"space,attr,omitempty"`
+ R string `xml:"r,attr"` // Cell ID, e.g. A1
+ S int `xml:"s,attr,omitempty"` // Style reference.
+ // Str string `xml:"str,attr,omitempty"` // Style reference.
+ T string `xml:"t,attr,omitempty"` // Type.
+ F *xlsxF `xml:"f,omitempty"` // Formula
+ V string `xml:"v,omitempty"` // Value
+ IS *xlsxSI `xml:"is"`
}
func (c *xlsxC) hasValue() bool {
@@ -461,27 +474,28 @@ type xlsxF struct {
// xlsxSheetProtection collection expresses the sheet protection options to
// enforce when the sheet is protected.
type xlsxSheetProtection struct {
- AlgorithmName string `xml:"algorithmName,attr,omitempty"`
- Password string `xml:"password,attr,omitempty"`
- HashValue string `xml:"hashValue,attr,omitempty"`
- SaltValue string `xml:"saltValue,attr,omitempty"`
- SpinCount int `xml:"spinCount,attr,omitempty"`
- Sheet bool `xml:"sheet,attr"`
- Objects bool `xml:"objects,attr"`
- Scenarios bool `xml:"scenarios,attr"`
- FormatCells bool `xml:"formatCells,attr"`
- FormatColumns bool `xml:"formatColumns,attr"`
- FormatRows bool `xml:"formatRows,attr"`
- InsertColumns bool `xml:"insertColumns,attr"`
- InsertRows bool `xml:"insertRows,attr"`
- InsertHyperlinks bool `xml:"insertHyperlinks,attr"`
- DeleteColumns bool `xml:"deleteColumns,attr"`
- DeleteRows bool `xml:"deleteRows,attr"`
- SelectLockedCells bool `xml:"selectLockedCells,attr"`
- Sort bool `xml:"sort,attr"`
- AutoFilter bool `xml:"autoFilter,attr"`
- PivotTables bool `xml:"pivotTables,attr"`
- SelectUnlockedCells bool `xml:"selectUnlockedCells,attr"`
+ XMLName xml.Name `xml:"sheetProtection"`
+ AlgorithmName string `xml:"algorithmName,attr,omitempty"`
+ Password string `xml:"password,attr,omitempty"`
+ HashValue string `xml:"hashValue,attr,omitempty"`
+ SaltValue string `xml:"saltValue,attr,omitempty"`
+ SpinCount int `xml:"spinCount,attr,omitempty"`
+ Sheet bool `xml:"sheet,attr"`
+ Objects bool `xml:"objects,attr"`
+ Scenarios bool `xml:"scenarios,attr"`
+ FormatCells bool `xml:"formatCells,attr"`
+ FormatColumns bool `xml:"formatColumns,attr"`
+ FormatRows bool `xml:"formatRows,attr"`
+ InsertColumns bool `xml:"insertColumns,attr"`
+ InsertRows bool `xml:"insertRows,attr"`
+ InsertHyperlinks bool `xml:"insertHyperlinks,attr"`
+ DeleteColumns bool `xml:"deleteColumns,attr"`
+ DeleteRows bool `xml:"deleteRows,attr"`
+ SelectLockedCells bool `xml:"selectLockedCells,attr"`
+ Sort bool `xml:"sort,attr"`
+ AutoFilter bool `xml:"autoFilter,attr"`
+ PivotTables bool `xml:"pivotTables,attr"`
+ SelectUnlockedCells bool `xml:"selectUnlockedCells,attr"`
}
// xlsxPhoneticPr (Phonetic Properties) represents a collection of phonetic
@@ -492,9 +506,10 @@ type xlsxSheetProtection struct {
// every phonetic hint is expressed as a phonetic run (rPh), and these
// properties specify how to display that phonetic run.
type xlsxPhoneticPr struct {
- Alignment string `xml:"alignment,attr,omitempty"`
- FontID *int `xml:"fontId,attr"`
- Type string `xml:"type,attr,omitempty"`
+ XMLName xml.Name `xml:"phoneticPr"`
+ Alignment string `xml:"alignment,attr,omitempty"`
+ FontID *int `xml:"fontId,attr"`
+ Type string `xml:"type,attr,omitempty"`
}
// A Conditional Format is a format, such as cell shading or font color, that a
@@ -502,8 +517,9 @@ type xlsxPhoneticPr struct {
// condition is true. This collection expresses conditional formatting rules
// applied to a particular cell or range.
type xlsxConditionalFormatting struct {
- SQRef string `xml:"sqref,attr,omitempty"`
- CfRule []*xlsxCfRule `xml:"cfRule"`
+ XMLName xml.Name `xml:"conditionalFormatting"`
+ SQRef string `xml:"sqref,attr,omitempty"`
+ CfRule []*xlsxCfRule `xml:"cfRule"`
}
// xlsxCfRule (Conditional Formatting Rule) represents a description of a
@@ -568,6 +584,7 @@ type xlsxCfvo struct {
// be stored in a package as a relationship. Hyperlinks shall be identified by
// containing a target which specifies the destination of the given hyperlink.
type xlsxHyperlinks struct {
+ XMLName xml.Name `xml:"hyperlinks"`
Hyperlink []xlsxHyperlink `xml:"hyperlink"`
}
@@ -612,6 +629,7 @@ type xlsxHyperlink struct {
// </worksheet>
//
type xlsxTableParts struct {
+ XMLName xml.Name `xml:"tableParts"`
Count int `xml:"count,attr,omitempty"`
TableParts []*xlsxTablePart `xml:"tablePart"`
}
@@ -629,7 +647,8 @@ type xlsxTablePart struct {
// <picture r:id="rId1"/>
//
type xlsxPicture struct {
- RID string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
+ XMLName xml.Name `xml:"picture"`
+ RID string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
}
// xlsxLegacyDrawing directly maps the legacyDrawing element in the namespace
@@ -642,7 +661,8 @@ type xlsxPicture struct {
// can also be used to explain assumptions made in a formula or to call out
// something special about the cell.
type xlsxLegacyDrawing struct {
- RID string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
+ XMLName xml.Name `xml:"legacyDrawing"`
+ RID string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
}
type xlsxInnerXML struct {