Skip to content

Commit 6afc468

Browse files
committed
Resolve qax-os#451, support create chart sheet
1 parent a75c6f6 commit 6afc468

11 files changed

+239
-79
lines changed

LICENSE

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
BSD 3-Clause License
22

33
Copyright (c) 2016-2020, 360 Enterprise Security Group, Endpoint Security, Inc.
4-
Copyright (c) 2011-2017, Geoffrey J. Teale
54
All rights reserved.
65

76
Redistribution and use in source and binary forms, with or without

chart.go

+68
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ package excelize
1111

1212
import (
1313
"encoding/json"
14+
"encoding/xml"
1415
"errors"
16+
"fmt"
1517
"strconv"
1618
"strings"
1719
)
@@ -768,6 +770,72 @@ func (f *File) AddChart(sheet, cell, format string, combo ...string) error {
768770
return err
769771
}
770772

773+
// AddChartSheet provides the method to create a chartsheet by given chart
774+
// format set (such as offset, scale, aspect ratio setting and print settings)
775+
// and properties set. In Excel a chartsheet is a worksheet that only contains
776+
// a chart.
777+
func (f *File) AddChartSheet(sheet, format string, combo ...string) error {
778+
// Check if the worksheet already exists
779+
if f.GetSheetIndex(sheet) != 0 {
780+
return errors.New("already existing name worksheet")
781+
}
782+
formatSet, err := parseFormatChartSet(format)
783+
if err != nil {
784+
return err
785+
}
786+
comboCharts := []*formatChart{}
787+
for _, comboFormat := range combo {
788+
comboChart, err := parseFormatChartSet(comboFormat)
789+
if err != nil {
790+
return err
791+
}
792+
if _, ok := chartValAxNumFmtFormatCode[comboChart.Type]; !ok {
793+
return errors.New("unsupported chart type " + comboChart.Type)
794+
}
795+
comboCharts = append(comboCharts, comboChart)
796+
}
797+
if _, ok := chartValAxNumFmtFormatCode[formatSet.Type]; !ok {
798+
return errors.New("unsupported chart type " + formatSet.Type)
799+
}
800+
cs := xlsxChartsheet{
801+
SheetViews: []*xlsxChartsheetViews{{
802+
SheetView: []*xlsxChartsheetView{{ZoomScaleAttr: 100, ZoomToFitAttr: true}}},
803+
},
804+
}
805+
wb := f.workbookReader()
806+
sheetID := 0
807+
for _, v := range wb.Sheets.Sheet {
808+
if v.SheetID > sheetID {
809+
sheetID = v.SheetID
810+
}
811+
}
812+
sheetID++
813+
path := "xl/chartsheets/sheet" + strconv.Itoa(sheetID) + ".xml"
814+
f.sheetMap[trimSheetName(sheet)] = path
815+
f.Sheet[path] = nil
816+
drawingID := f.countDrawings() + 1
817+
chartID := f.countCharts() + 1
818+
drawingXML := "xl/drawings/drawing" + strconv.Itoa(drawingID) + ".xml"
819+
drawingID, drawingXML = f.prepareChartSheetDrawing(&cs, drawingID, sheet, drawingXML)
820+
drawingRels := "xl/drawings/_rels/drawing" + strconv.Itoa(drawingID) + ".xml.rels"
821+
drawingRID := f.addRels(drawingRels, SourceRelationshipChart, "../charts/chart"+strconv.Itoa(chartID)+".xml", "")
822+
err = f.addSheetDrawingChart(sheet, drawingXML, formatSet.Dimension.Width, formatSet.Dimension.Height, drawingRID, &formatSet.Format)
823+
if err != nil {
824+
return err
825+
}
826+
f.addChart(formatSet, comboCharts)
827+
f.addContentTypePart(chartID, "chart")
828+
f.addContentTypePart(sheetID, "chartsheet")
829+
f.addContentTypePart(drawingID, "drawings")
830+
// Update xl/_rels/workbook.xml.rels
831+
rID := f.addRels("xl/_rels/workbook.xml.rels", SourceRelationshipChartsheet, fmt.Sprintf("chartsheets/sheet%d.xml", sheetID), "")
832+
// Update xl/workbook.xml
833+
f.setWorkbook(sheet, sheetID, rID)
834+
v, _ := xml.Marshal(cs)
835+
f.saveFileList(path, replaceRelationshipsBytes(replaceWorkSheetsRelationshipsNameSpaceBytes(v)))
836+
return err
837+
}
838+
771839
// DeleteChart provides a function to delete chart in XLSX by given worksheet
772840
// and cell name.
773841
func (f *File) DeleteChart(sheet, cell string) (err error) {

chart_test.go

+21-2
Original file line numberDiff line numberDiff line change
@@ -200,12 +200,31 @@ func TestAddChart(t *testing.T) {
200200
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddChart.xlsx")))
201201
// Test with unsupported chart type
202202
assert.EqualError(t, f.AddChart("Sheet2", "BD32", `{"type":"unknown","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"},{"name":"Sheet1!$A$33","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$33:$D$33"},{"name":"Sheet1!$A$34","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$34:$D$34"},{"name":"Sheet1!$A$35","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$35:$D$35"},{"name":"Sheet1!$A$36","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$36:$D$36"},{"name":"Sheet1!$A$37","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$37:$D$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Bubble 3D Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`), "unsupported chart type unknown")
203-
// Test add combo chart with invalid format set.
203+
// Test add combo chart with invalid format set
204204
assert.EqualError(t, f.AddChart("Sheet2", "BD32", `{"type":"col","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"},{"name":"Sheet1!$A$33","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$33:$D$33"},{"name":"Sheet1!$A$34","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$34:$D$34"},{"name":"Sheet1!$A$35","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$35:$D$35"},{"name":"Sheet1!$A$36","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$36:$D$36"},{"name":"Sheet1!$A$37","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$37:$D$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"2D Column Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`, ""), "unexpected end of JSON input")
205-
// Test add combo chart with unsupported chart type.
205+
// Test add combo chart with unsupported chart type
206206
assert.EqualError(t, f.AddChart("Sheet2", "BD64", `{"type":"barOfPie","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$A$30:$D$37","values":"Sheet1!$B$30:$B$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Bar of Pie Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero","x_axis":{"major_grid_lines":true},"y_axis":{"major_grid_lines":true}}`, `{"type":"unknown","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$A$30:$D$37","values":"Sheet1!$B$30:$B$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Bar of Pie Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero","x_axis":{"major_grid_lines":true},"y_axis":{"major_grid_lines":true}}`), "unsupported chart type unknown")
207207
}
208208

209+
func TestAddChartSheet(t *testing.T) {
210+
categories := map[string]string{"A2": "Small", "A3": "Normal", "A4": "Large", "B1": "Apple", "C1": "Orange", "D1": "Pear"}
211+
values := map[string]int{"B2": 2, "C2": 3, "D2": 3, "B3": 5, "C3": 2, "D3": 4, "B4": 6, "C4": 7, "D4": 8}
212+
f := NewFile()
213+
for k, v := range categories {
214+
assert.NoError(t, f.SetCellValue("Sheet1", k, v))
215+
}
216+
for k, v := range values {
217+
assert.NoError(t, f.SetCellValue("Sheet1", k, v))
218+
}
219+
assert.NoError(t, f.AddChartSheet("Chart1", `{"type":"col3DClustered","series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"title":{"name":"Fruit 3D Clustered Column Chart"}}`))
220+
221+
assert.EqualError(t, f.AddChartSheet("Sheet1", `{"type":"col3DClustered","series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"title":{"name":"Fruit 3D Clustered Column Chart"}}`), "already existing name worksheet")
222+
// Test with unsupported chart type
223+
assert.EqualError(t, f.AddChartSheet("Chart2", `{"type":"unknown","series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"title":{"name":"Fruit 3D Clustered Column Chart"}}`), "unsupported chart type unknown")
224+
225+
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddChartSheet.xlsx")))
226+
}
227+
209228
func TestDeleteChart(t *testing.T) {
210229
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
211230
assert.NoError(t, err)

drawing.go

+63
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,26 @@ func (f *File) prepareDrawing(xlsx *xlsxWorksheet, drawingID int, sheet, drawing
3838
return drawingID, drawingXML
3939
}
4040

41+
// prepareChartSheetDrawing provides a function to prepare drawing ID and XML
42+
// by given drawingID, worksheet name and default drawingXML.
43+
func (f *File) prepareChartSheetDrawing(xlsx *xlsxChartsheet, drawingID int, sheet, drawingXML string) (int, string) {
44+
sheetRelationshipsDrawingXML := "../drawings/drawing" + strconv.Itoa(drawingID) + ".xml"
45+
if xlsx.Drawing != nil {
46+
// The worksheet already has a picture or chart relationships, use the relationships drawing ../drawings/drawing%d.xml.
47+
sheetRelationshipsDrawingXML = f.getSheetRelationshipsTargetByID(sheet, xlsx.Drawing.RID)
48+
drawingID, _ = strconv.Atoi(strings.TrimSuffix(strings.TrimPrefix(sheetRelationshipsDrawingXML, "../drawings/drawing"), ".xml"))
49+
drawingXML = strings.Replace(sheetRelationshipsDrawingXML, "..", "xl", -1)
50+
} else {
51+
// Add first picture for given sheet.
52+
sheetRels := "xl/chartsheets/_rels/" + strings.TrimPrefix(f.sheetMap[trimSheetName(sheet)], "xl/chartsheets/") + ".rels"
53+
rID := f.addRels(sheetRels, SourceRelationshipDrawingML, sheetRelationshipsDrawingXML, "")
54+
xlsx.Drawing = &xlsxDrawing{
55+
RID: "rId" + strconv.Itoa(rID),
56+
}
57+
}
58+
return drawingID, drawingXML
59+
}
60+
4161
// addChart provides a function to create chart as xl/charts/chart%d.xml by
4262
// given format sets.
4363
func (f *File) addChart(formatSet *formatChart, comboCharts []*formatChart) {
@@ -1209,6 +1229,49 @@ func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rI
12091229
return err
12101230
}
12111231

1232+
// addSheetDrawingChart provides a function to add chart graphic frame for
1233+
// chartsheet by given sheet, drawingXML, width, height, relationship index
1234+
// and format sets.
1235+
func (f *File) addSheetDrawingChart(sheet, drawingXML string, width, height, rID int, formatSet *formatPicture) (err error) {
1236+
width = int(float64(width) * formatSet.XScale)
1237+
height = int(float64(height) * formatSet.YScale)
1238+
1239+
content, cNvPrID := f.drawingParser(drawingXML)
1240+
absoluteAnchor := xdrCellAnchor{
1241+
EditAs: formatSet.Positioning,
1242+
Pos: &xlsxPoint2D{},
1243+
Ext: &xlsxExt{},
1244+
}
1245+
1246+
graphicFrame := xlsxGraphicFrame{
1247+
NvGraphicFramePr: xlsxNvGraphicFramePr{
1248+
CNvPr: &xlsxCNvPr{
1249+
ID: cNvPrID,
1250+
Name: "Chart " + strconv.Itoa(cNvPrID),
1251+
},
1252+
},
1253+
Graphic: &xlsxGraphic{
1254+
GraphicData: &xlsxGraphicData{
1255+
URI: NameSpaceDrawingMLChart,
1256+
Chart: &xlsxChart{
1257+
C: NameSpaceDrawingMLChart,
1258+
R: SourceRelationship,
1259+
RID: "rId" + strconv.Itoa(rID),
1260+
},
1261+
},
1262+
},
1263+
}
1264+
graphic, _ := xml.Marshal(graphicFrame)
1265+
absoluteAnchor.GraphicFrame = string(graphic)
1266+
absoluteAnchor.ClientData = &xdrClientData{
1267+
FLocksWithSheet: formatSet.FLocksWithSheet,
1268+
FPrintsWithSheet: formatSet.FPrintsWithSheet,
1269+
}
1270+
content.AbsoluteAnchor = append(content.AbsoluteAnchor, &absoluteAnchor)
1271+
f.Drawings[drawingXML] = content
1272+
return err
1273+
}
1274+
12121275
// deleteDrawing provides a function to delete chart graphic frame by given by
12131276
// given coordinates and graphic type.
12141277
func (f *File) deleteDrawing(col, row int, drawingXML, drawingType string) (err error) {

excelize.go

+6-17
Original file line numberDiff line numberDiff line change
@@ -228,21 +228,10 @@ func (f *File) addRels(relPath, relType, target, targetMode string) int {
228228
}
229229

230230
// replaceWorkSheetsRelationshipsNameSpaceBytes provides a function to replace
231-
// xl/worksheets/sheet%d.xml XML tags to self-closing for compatible Microsoft
232-
// Office Excel 2007.
233-
func replaceWorkSheetsRelationshipsNameSpaceBytes(workbookMarshal []byte) []byte {
234-
var oldXmlns = []byte(`<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`)
235-
var newXmlns = []byte(`<worksheet` + templateNamespaceIDMap)
236-
workbookMarshal = bytes.Replace(workbookMarshal, oldXmlns, newXmlns, -1)
237-
return workbookMarshal
238-
}
239-
240-
// replaceStyleRelationshipsNameSpaceBytes provides a function to replace
241-
// xl/styles.xml XML tags to self-closing for compatible Microsoft Office
242-
// Excel 2007.
243-
func replaceStyleRelationshipsNameSpaceBytes(contentMarshal []byte) []byte {
244-
var oldXmlns = []byte(`<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`)
245-
var newXmlns = []byte(`<styleSheet` + templateNamespaceIDMap)
231+
// XML tags to self-closing for compatible Microsoft Office Excel 2007.
232+
func replaceWorkSheetsRelationshipsNameSpaceBytes(contentMarshal []byte) []byte {
233+
var oldXmlns = []byte(` xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`)
234+
var newXmlns = []byte(templateNamespaceIDMap)
246235
contentMarshal = bytes.Replace(contentMarshal, oldXmlns, newXmlns, -1)
247236
return contentMarshal
248237
}
@@ -354,13 +343,13 @@ func (f *File) setContentTypePartVBAProjectExtensions() {
354343
}
355344
for idx, o := range content.Overrides {
356345
if o.PartName == "/xl/workbook.xml" {
357-
content.Overrides[idx].ContentType = "application/vnd.ms-excel.sheet.macroEnabled.main+xml"
346+
content.Overrides[idx].ContentType = ContentTypeMacro
358347
}
359348
}
360349
if !ok {
361350
content.Defaults = append(content.Defaults, xlsxDefault{
362351
Extension: "bin",
363-
ContentType: "application/vnd.ms-office.vbaProject",
352+
ContentType: ContentTypeVBA,
364353
})
365354
}
366355
}

picture.go

+9-7
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ func (f *File) setContentTypePartVMLExtensions() {
354354
if !vml {
355355
content.Defaults = append(content.Defaults, xlsxDefault{
356356
Extension: "vml",
357-
ContentType: "application/vnd.openxmlformats-officedocument.vmlDrawing",
357+
ContentType: ContentTypeVML,
358358
})
359359
}
360360
}
@@ -368,19 +368,21 @@ func (f *File) addContentTypePart(index int, contentType string) {
368368
}
369369
partNames := map[string]string{
370370
"chart": "/xl/charts/chart" + strconv.Itoa(index) + ".xml",
371+
"chartsheet": "/xl/chartsheets/sheet" + strconv.Itoa(index) + ".xml",
371372
"comments": "/xl/comments" + strconv.Itoa(index) + ".xml",
372373
"drawings": "/xl/drawings/drawing" + strconv.Itoa(index) + ".xml",
373374
"table": "/xl/tables/table" + strconv.Itoa(index) + ".xml",
374375
"pivotTable": "/xl/pivotTables/pivotTable" + strconv.Itoa(index) + ".xml",
375376
"pivotCache": "/xl/pivotCache/pivotCacheDefinition" + strconv.Itoa(index) + ".xml",
376377
}
377378
contentTypes := map[string]string{
378-
"chart": "application/vnd.openxmlformats-officedocument.drawingml.chart+xml",
379-
"comments": "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml",
380-
"drawings": "application/vnd.openxmlformats-officedocument.drawing+xml",
381-
"table": "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml",
382-
"pivotTable": "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml",
383-
"pivotCache": "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml",
379+
"chart": ContentTypeDrawingML,
380+
"chartsheet": ContentTypeSpreadSheetMLChartsheet,
381+
"comments": ContentTypeSpreadSheetMLComments,
382+
"drawings": ContentTypeDrawing,
383+
"table": ContentTypeSpreadSheetMLTable,
384+
"pivotTable": ContentTypeSpreadSheetMLPivotTable,
385+
"pivotCache": ContentTypeSpreadSheetMLPivotCacheDefinition,
384386
}
385387
s, ok := setContentType[contentType]
386388
if ok {

sheet.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func (f *File) NewSheet(name string) int {
5050
// Update docProps/app.xml
5151
f.setAppXML()
5252
// Update [Content_Types].xml
53-
f.setContentTypes(sheetID)
53+
f.setContentTypes("/xl/worksheets/sheet"+strconv.Itoa(sheetID)+".xml", ContentTypeSpreadSheetMLWorksheet)
5454
// Create new sheet /xl/worksheets/sheet%d.xml
5555
f.setSheet(sheetID, name)
5656
// Update xl/_rels/workbook.xml.rels
@@ -151,11 +151,11 @@ func trimCell(column []xlsxC) []xlsxC {
151151

152152
// setContentTypes provides a function to read and update property of contents
153153
// type of XLSX.
154-
func (f *File) setContentTypes(index int) {
154+
func (f *File) setContentTypes(partName, contentType string) {
155155
content := f.contentTypesReader()
156156
content.Overrides = append(content.Overrides, xlsxOverride{
157-
PartName: "/xl/worksheets/sheet" + strconv.Itoa(index) + ".xml",
158-
ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
157+
PartName: partName,
158+
ContentType: contentType,
159159
})
160160
}
161161

@@ -336,8 +336,8 @@ func (f *File) GetSheetIndex(name string) int {
336336
return 0
337337
}
338338

339-
// GetSheetMap provides a function to get worksheet name and index map of XLSX.
340-
// For example:
339+
// GetSheetMap provides a function to get worksheet and chartsheet name and
340+
// index map of XLSX. For example:
341341
//
342342
// f, err := excelize.OpenFile("Book1.xlsx")
343343
// if err != nil {
@@ -358,8 +358,8 @@ func (f *File) GetSheetMap() map[int]string {
358358
return sheetMap
359359
}
360360

361-
// getSheetMap provides a function to get worksheet name and XML file path map
362-
// of XLSX.
361+
// getSheetMap provides a function to get worksheet and chartsheet name and
362+
// XML file path map of XLSX.
363363
func (f *File) getSheetMap() map[string]string {
364364
content := f.workbookReader()
365365
rels := f.relsReader("xl/_rels/workbook.xml.rels")

styles.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,7 @@ func (f *File) stylesReader() *xlsxStyleSheet {
10181018
func (f *File) styleSheetWriter() {
10191019
if f.Styles != nil {
10201020
output, _ := xml.Marshal(f.Styles)
1021-
f.saveFileList("xl/styles.xml", replaceStyleRelationshipsNameSpaceBytes(output))
1021+
f.saveFileList("xl/styles.xml", replaceWorkSheetsRelationshipsNameSpaceBytes(output))
10221022
}
10231023
}
10241024

xmlChartSheet.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ type xlsxChartsheet struct {
2424
PageMargins *xlsxPageMargins `xml:"pageMargins"`
2525
PageSetup []*xlsxPageSetUp `xml:"pageSetup"`
2626
HeaderFooter *xlsxHeaderFooter `xml:"headerFooter"`
27-
Drawing []*xlsxDrawing `xml:"drawing"`
27+
Drawing *xlsxDrawing `xml:"drawing"`
2828
DrawingHF []*xlsxDrawingHF `xml:"drawingHF"`
2929
Picture []*xlsxPicture `xml:"picture"`
3030
WebPublishItems []*xlsxInnerXML `xml:"webPublishItems"`

0 commit comments

Comments
 (0)