From c922c32fb7571d3d40d3244e5635142bc390a3db Mon Sep 17 00:00:00 2001 From: xuri Date: Sat, 18 Jul 2020 15:15:16 +0800 Subject: support parse and generate XML element namespace dynamic, fix #651 --- cell.go | 1 + chart.go | 4 ++- col.go | 2 +- comment.go | 1 + drawing.go | 7 ++-- excelize.go | 14 ++++---- lib.go | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- picture.go | 5 +-- rows.go | 15 ++++++--- shape.go | 1 + sheet.go | 21 ++++++++---- sparkline.go | 2 +- stream.go | 2 +- styles.go | 4 +-- table.go | 26 +++++++++------ xmlDrawing.go | 10 ++++-- 16 files changed, 171 insertions(+), 45 deletions(-) diff --git a/cell.go b/cell.go index 0163c3b..3293d19 100644 --- a/cell.go +++ b/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, diff --git a/chart.go b/chart.go index b584c18..ae31f71 100644 --- a/chart.go +++ b/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 } diff --git a/col.go b/col.go index 472106f..5a8299e 100644 --- a/col.go +++ b/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 diff --git a/comment.go b/comment.go index 28140bf..8414b40 100644 --- a/comment.go +++ b/comment.go @@ -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" diff --git a/drawing.go b/drawing.go index 5e5bba9..ced747d 100644 --- a/drawing.go +++ b/drawing.go @@ -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), }, }, diff --git a/excelize.go b/excelize.go index bac569a..5cc88e9 100644 --- a/excelize.go +++ b/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 diff --git a/lib.go b/lib.go index 5d18064..6dcd97e 100644 --- a/lib.go +++ b/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 diff --git a/picture.go b/picture.go index c7f6e27..468cccd 100644 --- a/picture.go +++ b/picture.go @@ -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" diff --git a/rows.go b/rows.go index 535b010..320ba2f 100644 --- a/rows.go +++ b/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 diff --git a/shape.go b/shape.go index 3160616..0a5164b 100644 --- a/shape.go +++ b/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 { diff --git a/sheet.go b/sheet.go index 20bf7c7..31a36eb 100644 --- a/sheet.go +++ b/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) } diff --git a/sparkline.go b/sparkline.go index 9682db0..4004878 100644 --- a/sparkline.go +++ b/sparkline.go @@ -455,7 +455,7 @@ func (f *File) AddSparkline(sheet string, opt *SparklineOption) (err error) { } ws.ExtLst.Ext = string(extBytes) } - + f.addSheetNameSpace(sheet, NameSpaceSpreadSheetX14) return } diff --git a/stream.go b/stream.go index bdc0d26..ec1e65b 100644 --- a/stream.go +++ b/stream.go @@ -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, diff --git a/styles.go b/styles.go index 2ae1cd8..d7b1460 100644 --- a/styles.go +++ b/styles.go @@ -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)) } } diff --git a/table.go b/table.go index d59322c..e26bbe2 100644 --- a/table.go +++ b/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, diff --git a/xmlDrawing.go b/xmlDrawing.go index 9c7ef54..24df0fa 100644 --- a/xmlDrawing.go +++ b/xmlDrawing.go @@ -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" -- cgit v1.2.1