forked from p30928647/excelize
support parse and generate XML element namespace dynamic, fix #651
This commit is contained in:
parent
820a314cfb
commit
c922c32fb7
1
cell.go
1
cell.go
|
@ -490,6 +490,7 @@ func (f *File) SetCellHyperLink(sheet, axis, link, linkType string) error {
|
|||
sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetPath, "xl/worksheets/") + ".rels"
|
||||
rID := f.addRels(sheetRels, SourceRelationshipHyperLink, link, linkType)
|
||||
linkData.RID = "rId" + strconv.Itoa(rID)
|
||||
f.addSheetNameSpace(sheet, SourceRelationship)
|
||||
case "Location":
|
||||
linkData = xlsxHyperlink{
|
||||
Ref: axis,
|
||||
|
|
4
chart.go
4
chart.go
|
@ -755,6 +755,7 @@ func (f *File) AddChart(sheet, cell, format string, combo ...string) error {
|
|||
f.addChart(formatSet, comboCharts)
|
||||
f.addContentTypePart(chartID, "chart")
|
||||
f.addContentTypePart(drawingID, "drawings")
|
||||
f.addSheetNameSpace(sheet, SourceRelationship)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -804,7 +805,8 @@ func (f *File) AddChartSheet(sheet, format string, combo ...string) error {
|
|||
// Update xl/workbook.xml
|
||||
f.setWorkbook(sheet, sheetID, rID)
|
||||
chartsheet, _ := xml.Marshal(cs)
|
||||
f.saveFileList(path, replaceRelationshipsBytes(replaceRelationshipsNameSpaceBytes(chartsheet)))
|
||||
f.addSheetNameSpace(sheet, NameSpaceSpreadSheet)
|
||||
f.saveFileList(path, replaceRelationshipsBytes(f.replaceNameSpaceBytes(path, chartsheet)))
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
2
col.go
2
col.go
|
@ -159,7 +159,7 @@ func (f *File) Cols(sheet string) (*Cols, error) {
|
|||
}
|
||||
if f.Sheet[name] != nil {
|
||||
output, _ := xml.Marshal(f.Sheet[name])
|
||||
f.saveFileList(name, replaceRelationshipsNameSpaceBytes(output))
|
||||
f.saveFileList(name, f.replaceNameSpaceBytes(name, output))
|
||||
}
|
||||
var (
|
||||
inElement string
|
||||
|
|
|
@ -109,6 +109,7 @@ func (f *File) AddComment(sheet, cell, format string) error {
|
|||
sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(f.sheetMap[trimSheetName(sheet)], "xl/worksheets/") + ".rels"
|
||||
rID := f.addRels(sheetRels, SourceRelationshipDrawingVML, sheetRelationshipsDrawingVML, "")
|
||||
f.addRels(sheetRels, SourceRelationshipComments, sheetRelationshipsComments, "")
|
||||
f.addSheetNameSpace(sheet, SourceRelationship)
|
||||
f.addSheetLegacyDrawing(sheet, rID)
|
||||
}
|
||||
commentsXML := "xl/comments" + strconv.Itoa(commentID) + ".xml"
|
||||
|
|
|
@ -47,6 +47,7 @@ func (f *File) prepareChartSheetDrawing(xlsx *xlsxChartsheet, drawingID int, she
|
|||
// Only allow one chart in a chartsheet.
|
||||
sheetRels := "xl/chartsheets/_rels/" + strings.TrimPrefix(f.sheetMap[trimSheetName(sheet)], "xl/chartsheets/") + ".rels"
|
||||
rID := f.addRels(sheetRels, SourceRelationshipDrawingML, sheetRelationshipsDrawingXML, "")
|
||||
f.addSheetNameSpace(sheet, SourceRelationship)
|
||||
xlsx.Drawing = &xlsxDrawing{
|
||||
RID: "rId" + strconv.Itoa(rID),
|
||||
}
|
||||
|
@ -60,7 +61,7 @@ func (f *File) addChart(formatSet *formatChart, comboCharts []*formatChart) {
|
|||
xlsxChartSpace := xlsxChartSpace{
|
||||
XMLNSc: NameSpaceDrawingMLChart,
|
||||
XMLNSa: NameSpaceDrawingML,
|
||||
XMLNSr: SourceRelationship,
|
||||
XMLNSr: SourceRelationship.Value,
|
||||
XMLNSc16r2: SourceRelationshipChart201506,
|
||||
Date1904: &attrValBool{Val: boolPtr(false)},
|
||||
Lang: &attrValString{Val: stringPtr("en-US")},
|
||||
|
@ -1212,7 +1213,7 @@ func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rI
|
|||
URI: NameSpaceDrawingMLChart,
|
||||
Chart: &xlsxChart{
|
||||
C: NameSpaceDrawingMLChart,
|
||||
R: SourceRelationship,
|
||||
R: SourceRelationship.Value,
|
||||
RID: "rId" + strconv.Itoa(rID),
|
||||
},
|
||||
},
|
||||
|
@ -1252,7 +1253,7 @@ func (f *File) addSheetDrawingChart(drawingXML string, rID int, formatSet *forma
|
|||
URI: NameSpaceDrawingMLChart,
|
||||
Chart: &xlsxChart{
|
||||
C: NameSpaceDrawingMLChart,
|
||||
R: SourceRelationship,
|
||||
R: SourceRelationship.Value,
|
||||
RID: "rId" + strconv.Itoa(rID),
|
||||
},
|
||||
},
|
||||
|
|
14
excelize.go
14
excelize.go
|
@ -30,6 +30,7 @@ import (
|
|||
|
||||
// File define a populated spreadsheet file struct.
|
||||
type File struct {
|
||||
xmlAttr map[string][]xml.Attr
|
||||
checked map[string]bool
|
||||
sheetMap map[string]string
|
||||
CalcChain *xlsxCalcChain
|
||||
|
@ -72,6 +73,7 @@ func OpenFile(filename string) (*File, error) {
|
|||
// newFile is object builder
|
||||
func newFile() *File {
|
||||
return &File{
|
||||
xmlAttr: make(map[string][]xml.Attr),
|
||||
checked: make(map[string]bool),
|
||||
sheetMap: make(map[string]string),
|
||||
Comments: make(map[string]*xlsxComments),
|
||||
|
@ -166,6 +168,10 @@ func (f *File) workSheetReader(sheet string) (xlsx *xlsxWorksheet, err error) {
|
|||
return
|
||||
}
|
||||
xlsx = new(xlsxWorksheet)
|
||||
if _, ok := f.xmlAttr[name]; !ok {
|
||||
d := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(name))))
|
||||
f.xmlAttr[name] = append(f.xmlAttr[name], getRootElement(d)...)
|
||||
}
|
||||
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(name)))).
|
||||
Decode(xlsx); err != nil && err != io.EOF {
|
||||
err = fmt.Errorf("xml decode error: %s", err)
|
||||
|
@ -254,14 +260,6 @@ func (f *File) addRels(relPath, relType, target, targetMode string) int {
|
|||
return rID
|
||||
}
|
||||
|
||||
// replaceRelationshipsNameSpaceBytes provides a function to replace
|
||||
// XML tags to self-closing for compatible Microsoft Office Excel 2007.
|
||||
func replaceRelationshipsNameSpaceBytes(contentMarshal []byte) []byte {
|
||||
var oldXmlns = stringToBytes(` xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`)
|
||||
var newXmlns = []byte(templateNamespaceIDMap)
|
||||
return bytesReplace(contentMarshal, oldXmlns, newXmlns, -1)
|
||||
}
|
||||
|
||||
// UpdateLinkedValue fix linked values within a spreadsheet are not updating in
|
||||
// Office Excel 2007 and 2010. This function will be remove value tag when met a
|
||||
// cell have a linked value. Reference
|
||||
|
|
101
lib.go
101
lib.go
|
@ -15,6 +15,7 @@ import (
|
|||
"archive/zip"
|
||||
"bytes"
|
||||
"container/list"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
|
@ -243,11 +244,11 @@ func parseFormatSet(formatSet string) []byte {
|
|||
// Transitional namespaces.
|
||||
func namespaceStrictToTransitional(content []byte) []byte {
|
||||
var namespaceTranslationDic = map[string]string{
|
||||
StrictSourceRelationship: SourceRelationship,
|
||||
StrictSourceRelationship: SourceRelationship.Value,
|
||||
StrictSourceRelationshipChart: SourceRelationshipChart,
|
||||
StrictSourceRelationshipComments: SourceRelationshipComments,
|
||||
StrictSourceRelationshipImage: SourceRelationshipImage,
|
||||
StrictNameSpaceSpreadSheet: NameSpaceSpreadSheet,
|
||||
StrictNameSpaceSpreadSheet: NameSpaceSpreadSheet.Value,
|
||||
}
|
||||
for s, n := range namespaceTranslationDic {
|
||||
content = bytesReplace(content, stringToBytes(s), stringToBytes(n), -1)
|
||||
|
@ -319,6 +320,102 @@ func genSheetPasswd(plaintext string) string {
|
|||
return strings.ToUpper(strconv.FormatInt(password, 16))
|
||||
}
|
||||
|
||||
// getRootElement extract root element attributes by given XML decoder.
|
||||
func getRootElement(d *xml.Decoder) []xml.Attr {
|
||||
tokenIdx := 0
|
||||
for {
|
||||
token, _ := d.Token()
|
||||
if token == nil {
|
||||
break
|
||||
}
|
||||
switch startElement := token.(type) {
|
||||
case xml.StartElement:
|
||||
tokenIdx++
|
||||
if tokenIdx == 1 {
|
||||
return startElement.Attr
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// genXMLNamespace generate serialized XML attributes with a multi namespace
|
||||
// by given element attributes.
|
||||
func genXMLNamespace(attr []xml.Attr) string {
|
||||
var rootElement string
|
||||
for _, v := range attr {
|
||||
if lastSpace := getXMLNamespace(v.Name.Space, attr); lastSpace != "" {
|
||||
rootElement += fmt.Sprintf("%s:%s=\"%s\" ", lastSpace, v.Name.Local, v.Value)
|
||||
continue
|
||||
}
|
||||
rootElement += fmt.Sprintf("%s=\"%s\" ", v.Name.Local, v.Value)
|
||||
}
|
||||
return strings.TrimSpace(rootElement) + ">"
|
||||
}
|
||||
|
||||
// getXMLNamespace extract XML namespace from specified element name and attributes.
|
||||
func getXMLNamespace(space string, attr []xml.Attr) string {
|
||||
for _, attribute := range attr {
|
||||
if attribute.Value == space {
|
||||
return attribute.Name.Local
|
||||
}
|
||||
}
|
||||
return space
|
||||
}
|
||||
|
||||
// replaceNameSpaceBytes provides a function to replace the XML root element
|
||||
// attribute by the given component part path and XML content.
|
||||
func (f *File) replaceNameSpaceBytes(path string, contentMarshal []byte) []byte {
|
||||
var oldXmlns = stringToBytes(`xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`)
|
||||
var newXmlns = []byte(templateNamespaceIDMap)
|
||||
if attr, ok := f.xmlAttr[path]; ok {
|
||||
newXmlns = []byte(genXMLNamespace(attr))
|
||||
}
|
||||
return bytesReplace(contentMarshal, oldXmlns, newXmlns, -1)
|
||||
}
|
||||
|
||||
// addNameSpaces provides a function to add a XML attribute by the given
|
||||
// component part path.
|
||||
func (f *File) addNameSpaces(path string, ns xml.Attr) {
|
||||
exist := false
|
||||
mc := false
|
||||
ignore := false
|
||||
if attr, ok := f.xmlAttr[path]; ok {
|
||||
for _, attribute := range attr {
|
||||
if attribute.Name.Local == ns.Name.Local && attribute.Name.Space == ns.Name.Space {
|
||||
exist = true
|
||||
}
|
||||
if attribute.Name.Local == "Ignorable" && attribute.Name.Space == "mc" {
|
||||
ignore = true
|
||||
}
|
||||
if attribute.Name.Local == "mc" && attribute.Name.Space == "xmlns" {
|
||||
mc = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if !exist {
|
||||
f.xmlAttr[path] = append(f.xmlAttr[path], ns)
|
||||
if !mc {
|
||||
f.xmlAttr[path] = append(f.xmlAttr[path], xml.Attr{
|
||||
Name: xml.Name{Local: "mc", Space: "xmlns"},
|
||||
Value: SourceRelationshipCompatibility,
|
||||
})
|
||||
}
|
||||
if !ignore {
|
||||
f.xmlAttr[path] = append(f.xmlAttr[path], xml.Attr{
|
||||
Name: xml.Name{Local: "Ignorable", Space: "mc"},
|
||||
Value: ns.Name.Local,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// addSheetNameSpace add XML attribute for worksheet.
|
||||
func (f *File) addSheetNameSpace(sheet string, ns xml.Attr) {
|
||||
name, _ := f.sheetMap[trimSheetName(sheet)]
|
||||
f.addNameSpaces(name, ns)
|
||||
}
|
||||
|
||||
// Stack defined an abstract data type that serves as a collection of elements.
|
||||
type Stack struct {
|
||||
list *list.List
|
||||
|
|
|
@ -168,6 +168,7 @@ func (f *File) AddPictureFromBytes(sheet, cell, format, name, extension string,
|
|||
return err
|
||||
}
|
||||
f.addContentTypePart(drawingID, "drawings")
|
||||
f.addSheetNameSpace(sheet, SourceRelationship)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -279,11 +280,11 @@ func (f *File) addDrawingPicture(sheet, drawingXML, cell, file string, width, he
|
|||
pic.NvPicPr.CNvPr.Name = "Picture " + strconv.Itoa(cNvPrID)
|
||||
if hyperlinkRID != 0 {
|
||||
pic.NvPicPr.CNvPr.HlinkClick = &xlsxHlinkClick{
|
||||
R: SourceRelationship,
|
||||
R: SourceRelationship.Value,
|
||||
RID: "rId" + strconv.Itoa(hyperlinkRID),
|
||||
}
|
||||
}
|
||||
pic.BlipFill.Blip.R = SourceRelationship
|
||||
pic.BlipFill.Blip.R = SourceRelationship.Value
|
||||
pic.BlipFill.Blip.Embed = "rId" + strconv.Itoa(rID)
|
||||
pic.SpPr.PrstGeom.Prst = "rect"
|
||||
|
||||
|
|
15
rows.go
15
rows.go
|
@ -121,11 +121,8 @@ func (rows *Rows) Columns() ([]string, error) {
|
|||
}
|
||||
}
|
||||
blank := cellCol - len(columns)
|
||||
for i := 1; i < blank; i++ {
|
||||
columns = append(columns, "")
|
||||
}
|
||||
val, _ := colCell.getValueFrom(rows.f, d)
|
||||
columns = append(columns, val)
|
||||
columns = append(appendSpace(blank, columns), val)
|
||||
}
|
||||
case xml.EndElement:
|
||||
inElement = startElement.Name.Local
|
||||
|
@ -137,6 +134,14 @@ func (rows *Rows) Columns() ([]string, error) {
|
|||
return columns, err
|
||||
}
|
||||
|
||||
// appendSpace append blank characters to slice by given length and source slice.
|
||||
func appendSpace(l int, s []string) []string {
|
||||
for i := 1; i < l; i++ {
|
||||
s = append(s, "")
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// ErrSheetNotExist defines an error of sheet is not exist
|
||||
type ErrSheetNotExist struct {
|
||||
SheetName string
|
||||
|
@ -173,7 +178,7 @@ func (f *File) Rows(sheet string) (*Rows, error) {
|
|||
if f.Sheet[name] != nil {
|
||||
// flush data
|
||||
output, _ := xml.Marshal(f.Sheet[name])
|
||||
f.saveFileList(name, replaceRelationshipsNameSpaceBytes(output))
|
||||
f.saveFileList(name, f.replaceNameSpaceBytes(name, output))
|
||||
}
|
||||
var (
|
||||
err error
|
||||
|
|
1
shape.go
1
shape.go
|
@ -280,6 +280,7 @@ func (f *File) AddShape(sheet, cell, format string) error {
|
|||
sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(f.sheetMap[trimSheetName(sheet)], "xl/worksheets/") + ".rels"
|
||||
rID := f.addRels(sheetRels, SourceRelationshipDrawingML, sheetRelationshipsDrawingXML, "")
|
||||
f.addSheetDrawing(sheet, rID)
|
||||
f.addSheetNameSpace(sheet, SourceRelationship)
|
||||
}
|
||||
err = f.addDrawingShape(sheet, drawingXML, cell, formatSet)
|
||||
if err != nil {
|
||||
|
|
21
sheet.go
21
sheet.go
|
@ -92,15 +92,18 @@ func (f *File) contentTypesWriter() {
|
|||
// structure after deserialization.
|
||||
func (f *File) workbookReader() *xlsxWorkbook {
|
||||
var err error
|
||||
|
||||
if f.WorkBook == nil {
|
||||
f.WorkBook = new(xlsxWorkbook)
|
||||
if _, ok := f.xmlAttr["xl/workbook.xml"]; !ok {
|
||||
d := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML("xl/workbook.xml"))))
|
||||
f.xmlAttr["xl/workbook.xml"] = append(f.xmlAttr["xl/workbook.xml"], getRootElement(d)...)
|
||||
f.addNameSpaces("xl/workbook.xml", SourceRelationship)
|
||||
}
|
||||
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML("xl/workbook.xml")))).
|
||||
Decode(f.WorkBook); err != nil && err != io.EOF {
|
||||
log.Printf("xml decode error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
return f.WorkBook
|
||||
}
|
||||
|
||||
|
@ -109,7 +112,7 @@ func (f *File) workbookReader() *xlsxWorkbook {
|
|||
func (f *File) workBookWriter() {
|
||||
if f.WorkBook != nil {
|
||||
output, _ := xml.Marshal(f.WorkBook)
|
||||
f.saveFileList("xl/workbook.xml", replaceRelationshipsBytes(replaceRelationshipsNameSpaceBytes(output)))
|
||||
f.saveFileList("xl/workbook.xml", replaceRelationshipsBytes(f.replaceNameSpaceBytes("xl/workbook.xml", output)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,7 +125,7 @@ func (f *File) workSheetWriter() {
|
|||
f.Sheet[p].SheetData.Row[k].C = trimCell(v.C)
|
||||
}
|
||||
output, _ := xml.Marshal(sheet)
|
||||
f.saveFileList(p, replaceRelationshipsBytes(replaceRelationshipsNameSpaceBytes(output)))
|
||||
f.saveFileList(p, replaceRelationshipsBytes(f.replaceNameSpaceBytes(p, output)))
|
||||
ok := f.checked[p]
|
||||
if ok {
|
||||
delete(f.Sheet, p)
|
||||
|
@ -173,6 +176,7 @@ func (f *File) setSheet(index int, name string) {
|
|||
path := "xl/worksheets/sheet" + strconv.Itoa(index) + ".xml"
|
||||
f.sheetMap[trimSheetName(name)] = path
|
||||
f.Sheet[path] = &xlsx
|
||||
f.xmlAttr[path] = append(f.xmlAttr[path], NameSpaceSpreadSheet)
|
||||
}
|
||||
|
||||
// setWorkbook update workbook property of the spreadsheet. Maximum 31
|
||||
|
@ -193,7 +197,7 @@ func (f *File) relsWriter() {
|
|||
if rel != nil {
|
||||
output, _ := xml.Marshal(rel)
|
||||
if strings.HasPrefix(path, "xl/worksheets/sheet/rels/sheet") {
|
||||
output = replaceRelationshipsNameSpaceBytes(output)
|
||||
output = f.replaceNameSpaceBytes(path, output)
|
||||
}
|
||||
f.saveFileList(path, replaceRelationshipsBytes(output))
|
||||
}
|
||||
|
@ -440,6 +444,7 @@ func (f *File) SetSheetBackground(sheet, picture string) error {
|
|||
sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(f.sheetMap[trimSheetName(sheet)], "xl/worksheets/") + ".rels"
|
||||
rID := f.addRels(sheetRels, SourceRelationshipImage, strings.Replace(name, "xl", "..", 1), "")
|
||||
f.addSheetPicture(sheet, rID)
|
||||
f.addSheetNameSpace(sheet, SourceRelationship)
|
||||
f.setContentTypePartImageExtensions()
|
||||
return err
|
||||
}
|
||||
|
@ -479,6 +484,7 @@ func (f *File) DeleteSheet(name string) {
|
|||
delete(f.XLSX, rels)
|
||||
delete(f.Relationships, rels)
|
||||
delete(f.Sheet, sheetXML)
|
||||
delete(f.xmlAttr, sheetXML)
|
||||
f.SheetCount--
|
||||
}
|
||||
}
|
||||
|
@ -557,6 +563,9 @@ func (f *File) copySheet(from, to int) error {
|
|||
if ok {
|
||||
f.XLSX[toRels] = f.XLSX[fromRels]
|
||||
}
|
||||
fromSheetXMLPath, _ := f.sheetMap[trimSheetName(fromSheet)]
|
||||
fromSheetAttr, _ := f.xmlAttr[fromSheetXMLPath]
|
||||
f.xmlAttr[path] = fromSheetAttr
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -779,7 +788,7 @@ func (f *File) SearchSheet(sheet, value string, reg ...bool) ([]string, error) {
|
|||
if f.Sheet[name] != nil {
|
||||
// flush data
|
||||
output, _ := xml.Marshal(f.Sheet[name])
|
||||
f.saveFileList(name, replaceRelationshipsNameSpaceBytes(output))
|
||||
f.saveFileList(name, f.replaceNameSpaceBytes(name, output))
|
||||
}
|
||||
return f.searchSheet(name, value, regSearch)
|
||||
}
|
||||
|
|
|
@ -455,7 +455,7 @@ func (f *File) AddSparkline(sheet string, opt *SparklineOption) (err error) {
|
|||
}
|
||||
ws.ExtLst.Ext = string(extBytes)
|
||||
}
|
||||
|
||||
f.addSheetNameSpace(sheet, NameSpaceSpreadSheetX14)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ func (sw *StreamWriter) AddTable(hcell, vcell, format string) error {
|
|||
}
|
||||
|
||||
table := xlsxTable{
|
||||
XMLNS: NameSpaceSpreadSheet,
|
||||
XMLNS: NameSpaceSpreadSheet.Value,
|
||||
ID: tableID,
|
||||
Name: name,
|
||||
DisplayName: name,
|
||||
|
|
|
@ -1022,7 +1022,7 @@ func (f *File) stylesReader() *xlsxStyleSheet {
|
|||
func (f *File) styleSheetWriter() {
|
||||
if f.Styles != nil {
|
||||
output, _ := xml.Marshal(f.Styles)
|
||||
f.saveFileList("xl/styles.xml", replaceRelationshipsNameSpaceBytes(output))
|
||||
f.saveFileList("xl/styles.xml", f.replaceNameSpaceBytes("xl/styles.xml", output))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1031,7 +1031,7 @@ func (f *File) styleSheetWriter() {
|
|||
func (f *File) sharedStringsWriter() {
|
||||
if f.SharedStrings != nil {
|
||||
output, _ := xml.Marshal(f.SharedStrings)
|
||||
f.saveFileList("xl/sharedStrings.xml", replaceRelationshipsNameSpaceBytes(output))
|
||||
f.saveFileList("xl/sharedStrings.xml", f.replaceNameSpaceBytes("xl/sharedStrings.xml", output))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
26
table.go
26
table.go
|
@ -83,9 +83,11 @@ func (f *File) AddTable(sheet, hcell, vcell, format string) error {
|
|||
// Add first table for given sheet.
|
||||
sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(f.sheetMap[trimSheetName(sheet)], "xl/worksheets/") + ".rels"
|
||||
rID := f.addRels(sheetRels, SourceRelationshipTable, sheetRelationshipsTableXML, "")
|
||||
f.addSheetTable(sheet, rID)
|
||||
err = f.addTable(sheet, tableXML, hcol, hrow, vcol, vrow, tableID, formatSet)
|
||||
if err != nil {
|
||||
if err = f.addSheetTable(sheet, rID); err != nil {
|
||||
return err
|
||||
}
|
||||
f.addSheetNameSpace(sheet, SourceRelationship)
|
||||
if err = f.addTable(sheet, tableXML, hcol, hrow, vcol, vrow, tableID, formatSet); err != nil {
|
||||
return err
|
||||
}
|
||||
f.addContentTypePart(tableID, "table")
|
||||
|
@ -106,16 +108,20 @@ func (f *File) countTables() int {
|
|||
|
||||
// addSheetTable provides a function to add tablePart element to
|
||||
// xl/worksheets/sheet%d.xml by given worksheet name and relationship index.
|
||||
func (f *File) addSheetTable(sheet string, rID int) {
|
||||
xlsx, _ := f.workSheetReader(sheet)
|
||||
func (f *File) addSheetTable(sheet string, rID int) error {
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
table := &xlsxTablePart{
|
||||
RID: "rId" + strconv.Itoa(rID),
|
||||
}
|
||||
if xlsx.TableParts == nil {
|
||||
xlsx.TableParts = &xlsxTableParts{}
|
||||
if ws.TableParts == nil {
|
||||
ws.TableParts = &xlsxTableParts{}
|
||||
}
|
||||
xlsx.TableParts.Count++
|
||||
xlsx.TableParts.TableParts = append(xlsx.TableParts.TableParts, table)
|
||||
ws.TableParts.Count++
|
||||
ws.TableParts.TableParts = append(ws.TableParts.TableParts, table)
|
||||
return err
|
||||
}
|
||||
|
||||
// addTable provides a function to add table by given worksheet name,
|
||||
|
@ -159,7 +165,7 @@ func (f *File) addTable(sheet, tableXML string, x1, y1, x2, y2, i int, formatSet
|
|||
name = "Table" + strconv.Itoa(i)
|
||||
}
|
||||
t := xlsxTable{
|
||||
XMLNS: NameSpaceSpreadSheet,
|
||||
XMLNS: NameSpaceSpreadSheet.Value,
|
||||
ID: i,
|
||||
Name: name,
|
||||
DisplayName: name,
|
||||
|
|
|
@ -13,9 +13,15 @@ package excelize
|
|||
|
||||
import "encoding/xml"
|
||||
|
||||
// Source relationship and namespace.
|
||||
var (
|
||||
SourceRelationship = xml.Attr{Name: xml.Name{Local: "r", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/officeDocument/2006/relationships"}
|
||||
NameSpaceSpreadSheet = xml.Attr{Name: xml.Name{Local: "xmlns"}, Value: "http://schemas.openxmlformats.org/spreadsheetml/2006/main"}
|
||||
NameSpaceSpreadSheetX14 = xml.Attr{Name: xml.Name{Local: "x14", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"}
|
||||
)
|
||||
|
||||
// Source relationship and namespace.
|
||||
const (
|
||||
SourceRelationship = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
|
||||
SourceRelationshipChart = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart"
|
||||
SourceRelationshipComments = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"
|
||||
SourceRelationshipImage = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
|
||||
|
@ -37,8 +43,6 @@ const (
|
|||
NameSpaceDrawingML = "http://schemas.openxmlformats.org/drawingml/2006/main"
|
||||
NameSpaceDrawingMLChart = "http://schemas.openxmlformats.org/drawingml/2006/chart"
|
||||
NameSpaceDrawingMLSpreadSheet = "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"
|
||||
NameSpaceSpreadSheet = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
|
||||
NameSpaceSpreadSheetX14 = "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"
|
||||
NameSpaceSpreadSheetX15 = "http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"
|
||||
NameSpaceSpreadSheetExcel2006Main = "http://schemas.microsoft.com/office/excel/2006/main"
|
||||
NameSpaceMacExcel2008Main = "http://schemas.microsoft.com/office/mac/excel/2008/main"
|
||||
|
|
Loading…
Reference in New Issue