OSDN Git Service

Improve compatibility, fix workbook's rels ID calc error
authorxuri <xuri.me@gmail.com>
Sun, 22 Dec 2019 16:07:40 +0000 (00:07 +0800)
committerxuri <xuri.me@gmail.com>
Sun, 22 Dec 2019 16:07:40 +0000 (00:07 +0800)
17 files changed:
adjust.go
cell.go
cellmerged.go
chart.go
comment.go
excelize.go
excelize_test.go
lib.go
shape.go
sheet.go
stream_test.go
styles.go
styles_test.go
table.go
xmlChart.go
xmlPivotTable.go
xmlWorksheet.go

index bb583f1..c15d4b4 100644 (file)
--- a/adjust.go
+++ b/adjust.go
@@ -53,7 +53,7 @@ func (f *File) adjustHelper(sheet string, dir adjustDirection, num, offset int)
                return err
        }
        checkSheet(xlsx)
-       checkRow(xlsx)
+       _ = checkRow(xlsx)
 
        if xlsx.MergeCells != nil && len(xlsx.MergeCells.Cells) == 0 {
                xlsx.MergeCells = nil
diff --git a/cell.go b/cell.go
index ad4bcdb..e59a659 100644 (file)
--- a/cell.go
+++ b/cell.go
@@ -395,7 +395,7 @@ func (f *File) SetCellHyperLink(sheet, axis, link, linkType string) error {
                linkData = xlsxHyperlink{
                        Ref: axis,
                }
-               sheetPath, _ := f.sheetMap[trimSheetName(sheet)]
+               sheetPath := f.sheetMap[trimSheetName(sheet)]
                sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetPath, "xl/worksheets/") + ".rels"
                rID := f.addRels(sheetRels, SourceRelationshipHyperLink, link, linkType)
                linkData.RID = "rId" + strconv.Itoa(rID)
index 968a28a..5bea0bc 100644 (file)
@@ -129,8 +129,6 @@ func (f *File) UnmergeCell(sheet string, hcell, vcell string) error {
        if rect1[3] < rect1[1] {
                rect1[1], rect1[3] = rect1[3], rect1[1]
        }
-       hcell, _ = CoordinatesToCellName(rect1[0], rect1[1])
-       vcell, _ = CoordinatesToCellName(rect1[2], rect1[3])
 
        // return nil since no MergeCells in the sheet
        if xlsx.MergeCells == nil {
index bf8155a..5a42c5b 100644 (file)
--- a/chart.go
+++ b/chart.go
@@ -726,8 +726,7 @@ func (f *File) prepareDrawing(xlsx *xlsxWorksheet, drawingID int, sheet, drawing
                drawingXML = strings.Replace(sheetRelationshipsDrawingXML, "..", "xl", -1)
        } else {
                // Add first picture for given sheet.
-               sheetPath, _ := f.sheetMap[trimSheetName(sheet)]
-               sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetPath, "xl/worksheets/") + ".rels"
+               sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(f.sheetMap[trimSheetName(sheet)], "xl/worksheets/") + ".rels"
                rID := f.addRels(sheetRels, SourceRelationshipDrawingML, sheetRelationshipsDrawingXML, "")
                f.addSheetDrawing(sheet, rID)
        }
@@ -743,9 +742,9 @@ func (f *File) addChart(formatSet *formatChart) {
                XMLNSa:         NameSpaceDrawingML,
                XMLNSr:         SourceRelationship,
                XMLNSc16r2:     SourceRelationshipChart201506,
-               Date1904:       &attrValBool{Val: false},
-               Lang:           &attrValString{Val: "en-US"},
-               RoundedCorners: &attrValBool{Val: false},
+               Date1904:       &attrValBool{Val: boolPtr(false)},
+               Lang:           &attrValString{Val: stringPtr("en-US")},
+               RoundedCorners: &attrValBool{Val: boolPtr(false)},
                Chart: cChart{
                        Title: &cTitle{
                                Tx: cTx{
@@ -761,10 +760,10 @@ func (f *File) addChart(formatSet *formatChart) {
                                                                                SchemeClr: &aSchemeClr{
                                                                                        Val: "tx1",
                                                                                        LumMod: &attrValInt{
-                                                                                               Val: 65000,
+                                                                                               Val: intPtr(65000),
                                                                                        },
                                                                                        LumOff: &attrValInt{
-                                                                                               Val: 35000,
+                                                                                               Val: intPtr(35000),
                                                                                        },
                                                                                },
                                                                        },
@@ -806,29 +805,29 @@ func (f *File) addChart(formatSet *formatChart) {
                                },
                        },
                        View3D: &cView3D{
-                               RotX:        &attrValInt{Val: chartView3DRotX[formatSet.Type]},
-                               RotY:        &attrValInt{Val: chartView3DRotY[formatSet.Type]},
-                               Perspective: &attrValInt{Val: chartView3DPerspective[formatSet.Type]},
-                               RAngAx:      &attrValInt{Val: chartView3DRAngAx[formatSet.Type]},
+                               RotX:        &attrValInt{Val: intPtr(chartView3DRotX[formatSet.Type])},
+                               RotY:        &attrValInt{Val: intPtr(chartView3DRotY[formatSet.Type])},
+                               Perspective: &attrValInt{Val: intPtr(chartView3DPerspective[formatSet.Type])},
+                               RAngAx:      &attrValInt{Val: intPtr(chartView3DRAngAx[formatSet.Type])},
                        },
                        Floor: &cThicknessSpPr{
-                               Thickness: &attrValInt{Val: 0},
+                               Thickness: &attrValInt{Val: intPtr(0)},
                        },
                        SideWall: &cThicknessSpPr{
-                               Thickness: &attrValInt{Val: 0},
+                               Thickness: &attrValInt{Val: intPtr(0)},
                        },
                        BackWall: &cThicknessSpPr{
-                               Thickness: &attrValInt{Val: 0},
+                               Thickness: &attrValInt{Val: intPtr(0)},
                        },
                        PlotArea: &cPlotArea{},
                        Legend: &cLegend{
-                               LegendPos: &attrValString{Val: chartLegendPosition[formatSet.Legend.Position]},
-                               Overlay:   &attrValBool{Val: false},
+                               LegendPos: &attrValString{Val: stringPtr(chartLegendPosition[formatSet.Legend.Position])},
+                               Overlay:   &attrValBool{Val: boolPtr(false)},
                        },
 
-                       PlotVisOnly:      &attrValBool{Val: false},
-                       DispBlanksAs:     &attrValString{Val: formatSet.ShowBlanksAs},
-                       ShowDLblsOverMax: &attrValBool{Val: false},
+                       PlotVisOnly:      &attrValBool{Val: boolPtr(false)},
+                       DispBlanksAs:     &attrValString{Val: stringPtr(formatSet.ShowBlanksAs)},
+                       ShowDLblsOverMax: &attrValBool{Val: boolPtr(false)},
                },
                SpPr: &cSpPr{
                        SolidFill: &aSolidFill{
@@ -842,10 +841,10 @@ func (f *File) addChart(formatSet *formatChart) {
                                SolidFill: &aSolidFill{
                                        SchemeClr: &aSchemeClr{Val: "tx1",
                                                LumMod: &attrValInt{
-                                                       Val: 15000,
+                                                       Val: intPtr(15000),
                                                },
                                                LumOff: &attrValInt{
-                                                       Val: 85000,
+                                                       Val: intPtr(85000),
                                                },
                                        },
                                },
@@ -928,31 +927,31 @@ func (f *File) addChart(formatSet *formatChart) {
 func (f *File) drawBaseChart(formatSet *formatChart) *cPlotArea {
        c := cCharts{
                BarDir: &attrValString{
-                       Val: "col",
+                       Val: stringPtr("col"),
                },
                Grouping: &attrValString{
-                       Val: "clustered",
+                       Val: stringPtr("clustered"),
                },
                VaryColors: &attrValBool{
-                       Val: true,
+                       Val: boolPtr(true),
                },
                Ser:   f.drawChartSeries(formatSet),
                Shape: f.drawChartShape(formatSet),
                DLbls: f.drawChartDLbls(formatSet),
                AxID: []*attrValInt{
-                       {Val: 754001152},
-                       {Val: 753999904},
+                       {Val: intPtr(754001152)},
+                       {Val: intPtr(753999904)},
                },
-               Overlap: &attrValInt{Val: 100},
+               Overlap: &attrValInt{Val: intPtr(100)},
        }
        var ok bool
-       if c.BarDir.Val, ok = plotAreaChartBarDir[formatSet.Type]; !ok {
+       if *c.BarDir.Val, ok = plotAreaChartBarDir[formatSet.Type]; !ok {
                c.BarDir = nil
        }
-       if c.Grouping.Val, ok = plotAreaChartGrouping[formatSet.Type]; !ok {
+       if *c.Grouping.Val, ok = plotAreaChartGrouping[formatSet.Type]; !ok {
                c.Grouping = nil
        }
-       if c.Overlap.Val, ok = plotAreaChartOverlap[formatSet.Type]; !ok {
+       if *c.Overlap.Val, ok = plotAreaChartOverlap[formatSet.Type]; !ok {
                c.Overlap = nil
        }
        catAx := f.drawPlotAreaCatAx(formatSet)
@@ -1178,10 +1177,10 @@ func (f *File) drawDoughnutChart(formatSet *formatChart) *cPlotArea {
        return &cPlotArea{
                DoughnutChart: &cCharts{
                        VaryColors: &attrValBool{
-                               Val: true,
+                               Val: boolPtr(true),
                        },
                        Ser:      f.drawChartSeries(formatSet),
-                       HoleSize: &attrValInt{Val: 75},
+                       HoleSize: &attrValInt{Val: intPtr(75)},
                },
        }
 }
@@ -1192,19 +1191,19 @@ func (f *File) drawLineChart(formatSet *formatChart) *cPlotArea {
        return &cPlotArea{
                LineChart: &cCharts{
                        Grouping: &attrValString{
-                               Val: plotAreaChartGrouping[formatSet.Type],
+                               Val: stringPtr(plotAreaChartGrouping[formatSet.Type]),
                        },
                        VaryColors: &attrValBool{
-                               Val: false,
+                               Val: boolPtr(false),
                        },
                        Ser:   f.drawChartSeries(formatSet),
                        DLbls: f.drawChartDLbls(formatSet),
                        Smooth: &attrValBool{
-                               Val: false,
+                               Val: boolPtr(false),
                        },
                        AxID: []*attrValInt{
-                               {Val: 754001152},
-                               {Val: 753999904},
+                               {Val: intPtr(754001152)},
+                               {Val: intPtr(753999904)},
                        },
                },
                CatAx: f.drawPlotAreaCatAx(formatSet),
@@ -1218,7 +1217,7 @@ func (f *File) drawPieChart(formatSet *formatChart) *cPlotArea {
        return &cPlotArea{
                PieChart: &cCharts{
                        VaryColors: &attrValBool{
-                               Val: true,
+                               Val: boolPtr(true),
                        },
                        Ser: f.drawChartSeries(formatSet),
                },
@@ -1231,7 +1230,7 @@ func (f *File) drawPie3DChart(formatSet *formatChart) *cPlotArea {
        return &cPlotArea{
                Pie3DChart: &cCharts{
                        VaryColors: &attrValBool{
-                               Val: true,
+                               Val: boolPtr(true),
                        },
                        Ser: f.drawChartSeries(formatSet),
                },
@@ -1244,16 +1243,16 @@ func (f *File) drawRadarChart(formatSet *formatChart) *cPlotArea {
        return &cPlotArea{
                RadarChart: &cCharts{
                        RadarStyle: &attrValString{
-                               Val: "marker",
+                               Val: stringPtr("marker"),
                        },
                        VaryColors: &attrValBool{
-                               Val: false,
+                               Val: boolPtr(false),
                        },
                        Ser:   f.drawChartSeries(formatSet),
                        DLbls: f.drawChartDLbls(formatSet),
                        AxID: []*attrValInt{
-                               {Val: 754001152},
-                               {Val: 753999904},
+                               {Val: intPtr(754001152)},
+                               {Val: intPtr(753999904)},
                        },
                },
                CatAx: f.drawPlotAreaCatAx(formatSet),
@@ -1267,16 +1266,16 @@ func (f *File) drawScatterChart(formatSet *formatChart) *cPlotArea {
        return &cPlotArea{
                ScatterChart: &cCharts{
                        ScatterStyle: &attrValString{
-                               Val: "smoothMarker", // line,lineMarker,marker,none,smooth,smoothMarker
+                               Val: stringPtr("smoothMarker"), // line,lineMarker,marker,none,smooth,smoothMarker
                        },
                        VaryColors: &attrValBool{
-                               Val: false,
+                               Val: boolPtr(false),
                        },
                        Ser:   f.drawChartSeries(formatSet),
                        DLbls: f.drawChartDLbls(formatSet),
                        AxID: []*attrValInt{
-                               {Val: 754001152},
-                               {Val: 753999904},
+                               {Val: intPtr(754001152)},
+                               {Val: intPtr(753999904)},
                        },
                },
                CatAx: f.drawPlotAreaCatAx(formatSet),
@@ -1291,9 +1290,9 @@ func (f *File) drawSurface3DChart(formatSet *formatChart) *cPlotArea {
                Surface3DChart: &cCharts{
                        Ser: f.drawChartSeries(formatSet),
                        AxID: []*attrValInt{
-                               {Val: 754001152},
-                               {Val: 753999904},
-                               {Val: 832256642},
+                               {Val: intPtr(754001152)},
+                               {Val: intPtr(753999904)},
+                               {Val: intPtr(832256642)},
                        },
                },
                CatAx: f.drawPlotAreaCatAx(formatSet),
@@ -1301,7 +1300,7 @@ func (f *File) drawSurface3DChart(formatSet *formatChart) *cPlotArea {
                SerAx: f.drawPlotAreaSerAx(formatSet),
        }
        if formatSet.Type == WireframeSurface3D {
-               plotArea.Surface3DChart.Wireframe = &attrValBool{Val: true}
+               plotArea.Surface3DChart.Wireframe = &attrValBool{Val: boolPtr(true)}
        }
        return plotArea
 }
@@ -1313,9 +1312,9 @@ func (f *File) drawSurfaceChart(formatSet *formatChart) *cPlotArea {
                SurfaceChart: &cCharts{
                        Ser: f.drawChartSeries(formatSet),
                        AxID: []*attrValInt{
-                               {Val: 754001152},
-                               {Val: 753999904},
-                               {Val: 832256642},
+                               {Val: intPtr(754001152)},
+                               {Val: intPtr(753999904)},
+                               {Val: intPtr(832256642)},
                        },
                },
                CatAx: f.drawPlotAreaCatAx(formatSet),
@@ -1323,7 +1322,7 @@ func (f *File) drawSurfaceChart(formatSet *formatChart) *cPlotArea {
                SerAx: f.drawPlotAreaSerAx(formatSet),
        }
        if formatSet.Type == WireframeContour {
-               plotArea.SurfaceChart.Wireframe = &attrValBool{Val: true}
+               plotArea.SurfaceChart.Wireframe = &attrValBool{Val: boolPtr(true)}
        }
        return plotArea
 }
@@ -1355,7 +1354,7 @@ func (f *File) drawChartShape(formatSet *formatChart) *attrValString {
                Col3DCylinderPercentStacked: "cylinder",
        }
        if shape, ok := shapes[formatSet.Type]; ok {
-               return &attrValString{Val: shape}
+               return &attrValString{Val: stringPtr(shape)}
        }
        return nil
 }
@@ -1366,8 +1365,8 @@ func (f *File) drawChartSeries(formatSet *formatChart) *[]cSer {
        ser := []cSer{}
        for k := range formatSet.Series {
                ser = append(ser, cSer{
-                       IDx:   &attrValInt{Val: k},
-                       Order: &attrValInt{Val: k},
+                       IDx:   &attrValInt{Val: intPtr(k)},
+                       Order: &attrValInt{Val: intPtr(k)},
                        Tx: &cTx{
                                StrRef: &cStrRef{
                                        F: formatSet.Series[k].Name,
@@ -1416,8 +1415,8 @@ func (f *File) drawChartSeriesSpPr(i int, formatSet *formatChart) *cSpPr {
 // data index and format sets.
 func (f *File) drawChartSeriesDPt(i int, formatSet *formatChart) []*cDPt {
        dpt := []*cDPt{{
-               IDx:      &attrValInt{Val: i},
-               Bubble3D: &attrValBool{Val: false},
+               IDx:      &attrValInt{Val: intPtr(i)},
+               Bubble3D: &attrValBool{Val: boolPtr(false)},
                SpPr: &cSpPr{
                        SolidFill: &aSolidFill{
                                SchemeClr: &aSchemeClr{Val: "accent" + strconv.Itoa(i+1)},
@@ -1475,8 +1474,8 @@ func (f *File) drawChartSeriesVal(v formatChartSeries, formatSet *formatChart) *
 // given data index and format sets.
 func (f *File) drawChartSeriesMarker(i int, formatSet *formatChart) *cMarker {
        marker := &cMarker{
-               Symbol: &attrValString{Val: "circle"},
-               Size:   &attrValInt{Val: 5},
+               Symbol: &attrValString{Val: stringPtr("circle")},
+               Size:   &attrValInt{Val: intPtr(5)},
        }
        if i < 6 {
                marker.SpPr = &cSpPr{
@@ -1542,20 +1541,20 @@ func (f *File) drawCharSeriesBubble3D(formatSet *formatChart) *attrValBool {
        if _, ok := map[string]bool{Bubble3D: true}[formatSet.Type]; !ok {
                return nil
        }
-       return &attrValBool{Val: true}
+       return &attrValBool{Val: boolPtr(true)}
 }
 
 // drawChartDLbls provides a function to draw the c:dLbls element by given
 // format sets.
 func (f *File) drawChartDLbls(formatSet *formatChart) *cDLbls {
        return &cDLbls{
-               ShowLegendKey:   &attrValBool{Val: formatSet.Legend.ShowLegendKey},
-               ShowVal:         &attrValBool{Val: formatSet.Plotarea.ShowVal},
-               ShowCatName:     &attrValBool{Val: formatSet.Plotarea.ShowCatName},
-               ShowSerName:     &attrValBool{Val: formatSet.Plotarea.ShowSerName},
-               ShowBubbleSize:  &attrValBool{Val: formatSet.Plotarea.ShowBubbleSize},
-               ShowPercent:     &attrValBool{Val: formatSet.Plotarea.ShowPercent},
-               ShowLeaderLines: &attrValBool{Val: formatSet.Plotarea.ShowLeaderLines},
+               ShowLegendKey:   &attrValBool{Val: boolPtr(formatSet.Legend.ShowLegendKey)},
+               ShowVal:         &attrValBool{Val: boolPtr(formatSet.Plotarea.ShowVal)},
+               ShowCatName:     &attrValBool{Val: boolPtr(formatSet.Plotarea.ShowCatName)},
+               ShowSerName:     &attrValBool{Val: boolPtr(formatSet.Plotarea.ShowSerName)},
+               ShowBubbleSize:  &attrValBool{Val: boolPtr(formatSet.Plotarea.ShowBubbleSize)},
+               ShowPercent:     &attrValBool{Val: boolPtr(formatSet.Plotarea.ShowPercent)},
+               ShowLeaderLines: &attrValBool{Val: boolPtr(formatSet.Plotarea.ShowLeaderLines)},
        }
 }
 
@@ -1572,8 +1571,8 @@ func (f *File) drawChartSeriesDLbls(formatSet *formatChart) *cDLbls {
 
 // drawPlotAreaCatAx provides a function to draw the c:catAx element.
 func (f *File) drawPlotAreaCatAx(formatSet *formatChart) []*cAxs {
-       min := &attrValFloat{Val: formatSet.XAxis.Minimum}
-       max := &attrValFloat{Val: formatSet.XAxis.Maximum}
+       min := &attrValFloat{Val: float64Ptr(formatSet.XAxis.Minimum)}
+       max := &attrValFloat{Val: float64Ptr(formatSet.XAxis.Maximum)}
        if formatSet.XAxis.Minimum == 0 {
                min = nil
        }
@@ -1582,29 +1581,29 @@ func (f *File) drawPlotAreaCatAx(formatSet *formatChart) []*cAxs {
        }
        axs := []*cAxs{
                {
-                       AxID: &attrValInt{Val: 754001152},
+                       AxID: &attrValInt{Val: intPtr(754001152)},
                        Scaling: &cScaling{
-                               Orientation: &attrValString{Val: orientation[formatSet.XAxis.ReverseOrder]},
+                               Orientation: &attrValString{Val: stringPtr(orientation[formatSet.XAxis.ReverseOrder])},
                                Max:         max,
                                Min:         min,
                        },
-                       Delete: &attrValBool{Val: false},
-                       AxPos:  &attrValString{Val: catAxPos[formatSet.XAxis.ReverseOrder]},
+                       Delete: &attrValBool{Val: boolPtr(false)},
+                       AxPos:  &attrValString{Val: stringPtr(catAxPos[formatSet.XAxis.ReverseOrder])},
                        NumFmt: &cNumFmt{
                                FormatCode:   "General",
                                SourceLinked: true,
                        },
-                       MajorTickMark: &attrValString{Val: "none"},
-                       MinorTickMark: &attrValString{Val: "none"},
-                       TickLblPos:    &attrValString{Val: "nextTo"},
+                       MajorTickMark: &attrValString{Val: stringPtr("none")},
+                       MinorTickMark: &attrValString{Val: stringPtr("none")},
+                       TickLblPos:    &attrValString{Val: stringPtr("nextTo")},
                        SpPr:          f.drawPlotAreaSpPr(),
                        TxPr:          f.drawPlotAreaTxPr(),
-                       CrossAx:       &attrValInt{Val: 753999904},
-                       Crosses:       &attrValString{Val: "autoZero"},
-                       Auto:          &attrValBool{Val: true},
-                       LblAlgn:       &attrValString{Val: "ctr"},
-                       LblOffset:     &attrValInt{Val: 100},
-                       NoMultiLvlLbl: &attrValBool{Val: false},
+                       CrossAx:       &attrValInt{Val: intPtr(753999904)},
+                       Crosses:       &attrValString{Val: stringPtr("autoZero")},
+                       Auto:          &attrValBool{Val: boolPtr(true)},
+                       LblAlgn:       &attrValString{Val: stringPtr("ctr")},
+                       LblOffset:     &attrValInt{Val: intPtr(100)},
+                       NoMultiLvlLbl: &attrValBool{Val: boolPtr(false)},
                },
        }
        if formatSet.XAxis.MajorGridlines {
@@ -1618,8 +1617,8 @@ func (f *File) drawPlotAreaCatAx(formatSet *formatChart) []*cAxs {
 
 // drawPlotAreaValAx provides a function to draw the c:valAx element.
 func (f *File) drawPlotAreaValAx(formatSet *formatChart) []*cAxs {
-       min := &attrValFloat{Val: formatSet.YAxis.Minimum}
-       max := &attrValFloat{Val: formatSet.YAxis.Maximum}
+       min := &attrValFloat{Val: float64Ptr(formatSet.YAxis.Minimum)}
+       max := &attrValFloat{Val: float64Ptr(formatSet.YAxis.Maximum)}
        if formatSet.YAxis.Minimum == 0 {
                min = nil
        }
@@ -1628,26 +1627,26 @@ func (f *File) drawPlotAreaValAx(formatSet *formatChart) []*cAxs {
        }
        axs := []*cAxs{
                {
-                       AxID: &attrValInt{Val: 753999904},
+                       AxID: &attrValInt{Val: intPtr(753999904)},
                        Scaling: &cScaling{
-                               Orientation: &attrValString{Val: orientation[formatSet.YAxis.ReverseOrder]},
+                               Orientation: &attrValString{Val: stringPtr(orientation[formatSet.YAxis.ReverseOrder])},
                                Max:         max,
                                Min:         min,
                        },
-                       Delete: &attrValBool{Val: false},
-                       AxPos:  &attrValString{Val: valAxPos[formatSet.YAxis.ReverseOrder]},
+                       Delete: &attrValBool{Val: boolPtr(false)},
+                       AxPos:  &attrValString{Val: stringPtr(valAxPos[formatSet.YAxis.ReverseOrder])},
                        NumFmt: &cNumFmt{
                                FormatCode:   chartValAxNumFmtFormatCode[formatSet.Type],
                                SourceLinked: true,
                        },
-                       MajorTickMark: &attrValString{Val: "none"},
-                       MinorTickMark: &attrValString{Val: "none"},
-                       TickLblPos:    &attrValString{Val: "nextTo"},
+                       MajorTickMark: &attrValString{Val: stringPtr("none")},
+                       MinorTickMark: &attrValString{Val: stringPtr("none")},
+                       TickLblPos:    &attrValString{Val: stringPtr("nextTo")},
                        SpPr:          f.drawPlotAreaSpPr(),
                        TxPr:          f.drawPlotAreaTxPr(),
-                       CrossAx:       &attrValInt{Val: 754001152},
-                       Crosses:       &attrValString{Val: "autoZero"},
-                       CrossBetween:  &attrValString{Val: chartValAxCrossBetween[formatSet.Type]},
+                       CrossAx:       &attrValInt{Val: intPtr(754001152)},
+                       Crosses:       &attrValString{Val: stringPtr("autoZero")},
+                       CrossBetween:  &attrValString{Val: stringPtr(chartValAxCrossBetween[formatSet.Type])},
                },
        }
        if formatSet.YAxis.MajorGridlines {
@@ -1657,15 +1656,15 @@ func (f *File) drawPlotAreaValAx(formatSet *formatChart) []*cAxs {
                axs[0].MinorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()}
        }
        if pos, ok := valTickLblPos[formatSet.Type]; ok {
-               axs[0].TickLblPos.Val = pos
+               axs[0].TickLblPos.Val = stringPtr(pos)
        }
        return axs
 }
 
 // drawPlotAreaSerAx provides a function to draw the c:serAx element.
 func (f *File) drawPlotAreaSerAx(formatSet *formatChart) []*cAxs {
-       min := &attrValFloat{Val: formatSet.YAxis.Minimum}
-       max := &attrValFloat{Val: formatSet.YAxis.Maximum}
+       min := &attrValFloat{Val: float64Ptr(formatSet.YAxis.Minimum)}
+       max := &attrValFloat{Val: float64Ptr(formatSet.YAxis.Maximum)}
        if formatSet.YAxis.Minimum == 0 {
                min = nil
        }
@@ -1674,18 +1673,18 @@ func (f *File) drawPlotAreaSerAx(formatSet *formatChart) []*cAxs {
        }
        return []*cAxs{
                {
-                       AxID: &attrValInt{Val: 832256642},
+                       AxID: &attrValInt{Val: intPtr(832256642)},
                        Scaling: &cScaling{
-                               Orientation: &attrValString{Val: orientation[formatSet.YAxis.ReverseOrder]},
+                               Orientation: &attrValString{Val: stringPtr(orientation[formatSet.YAxis.ReverseOrder])},
                                Max:         max,
                                Min:         min,
                        },
-                       Delete:     &attrValBool{Val: false},
-                       AxPos:      &attrValString{Val: catAxPos[formatSet.XAxis.ReverseOrder]},
-                       TickLblPos: &attrValString{Val: "nextTo"},
+                       Delete:     &attrValBool{Val: boolPtr(false)},
+                       AxPos:      &attrValString{Val: stringPtr(catAxPos[formatSet.XAxis.ReverseOrder])},
+                       TickLblPos: &attrValString{Val: stringPtr("nextTo")},
                        SpPr:       f.drawPlotAreaSpPr(),
                        TxPr:       f.drawPlotAreaTxPr(),
-                       CrossAx:    &attrValInt{Val: 753999904},
+                       CrossAx:    &attrValInt{Val: intPtr(753999904)},
                },
        }
 }
@@ -1701,8 +1700,8 @@ func (f *File) drawPlotAreaSpPr() *cSpPr {
                        SolidFill: &aSolidFill{
                                SchemeClr: &aSchemeClr{
                                        Val:    "tx1",
-                                       LumMod: &attrValInt{Val: 15000},
-                                       LumOff: &attrValInt{Val: 85000},
+                                       LumMod: &attrValInt{Val: intPtr(15000)},
+                                       LumOff: &attrValInt{Val: intPtr(85000)},
                                },
                        },
                },
@@ -1734,8 +1733,8 @@ func (f *File) drawPlotAreaTxPr() *cTxPr {
                                        SolidFill: &aSolidFill{
                                                SchemeClr: &aSchemeClr{
                                                        Val:    "tx1",
-                                                       LumMod: &attrValInt{Val: 15000},
-                                                       LumOff: &attrValInt{Val: 85000},
+                                                       LumMod: &attrValInt{Val: intPtr(15000)},
+                                                       LumOff: &attrValInt{Val: intPtr(85000)},
                                                },
                                        },
                                        Latin: &aLatin{Typeface: "+mn-lt"},
index 99630c9..486a035 100644 (file)
@@ -101,8 +101,7 @@ func (f *File) AddComment(sheet, cell, format string) error {
                drawingVML = strings.Replace(sheetRelationshipsDrawingVML, "..", "xl", -1)
        } else {
                // Add first comment for given sheet.
-               sheetPath, _ := f.sheetMap[trimSheetName(sheet)]
-               sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetPath, "xl/worksheets/") + ".rels"
+               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.addSheetLegacyDrawing(sheet, rID)
@@ -256,23 +255,23 @@ func (f *File) addComment(commentsXML, cell string, formatSet *formatComment) {
                                {
                                        RPr: &xlsxRPr{
                                                B:  " ",
-                                               Sz: &attrValFloat{Val: 9},
+                                               Sz: &attrValFloat{Val: float64Ptr(9)},
                                                Color: &xlsxColor{
                                                        Indexed: 81,
                                                },
-                                               RFont:  &attrValString{Val: defaultFont},
-                                               Family: &attrValInt{Val: 2},
+                                               RFont:  &attrValString{Val: stringPtr(defaultFont)},
+                                               Family: &attrValInt{Val: intPtr(2)},
                                        },
                                        T: a,
                                },
                                {
                                        RPr: &xlsxRPr{
-                                               Sz: &attrValFloat{Val: 9},
+                                               Sz: &attrValFloat{Val: float64Ptr(9)},
                                                Color: &xlsxColor{
                                                        Indexed: 81,
                                                },
-                                               RFont:  &attrValString{Val: defaultFont},
-                                               Family: &attrValInt{Val: 2},
+                                               RFont:  &attrValString{Val: stringPtr(defaultFont)},
+                                               Family: &attrValInt{Val: intPtr(2)},
                                        },
                                        T: t,
                                },
index a2e20ff..135028c 100644 (file)
@@ -203,11 +203,17 @@ func checkSheet(xlsx *xlsxWorksheet) {
 // relationship type, target and target mode.
 func (f *File) addRels(relPath, relType, target, targetMode string) int {
        rels := f.relsReader(relPath)
-       rID := 0
        if rels == nil {
                rels = &xlsxRelationships{}
        }
-       rID = len(rels.Relationships) + 1
+       var rID int
+       for _, rel := range rels.Relationships {
+               ID, _ := strconv.Atoi(strings.TrimPrefix(rel.ID, "rId"))
+               if ID > rID {
+                       rID = ID
+               }
+       }
+       rID++
        var ID bytes.Buffer
        ID.WriteString("rId")
        ID.WriteString(strconv.Itoa(rID))
index 6929a4f..1d6ed24 100644 (file)
@@ -48,7 +48,7 @@ func TestOpenFile(t *testing.T) {
        assert.EqualError(t, f.SetCellDefault("Sheet2", "A", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64)),
                `cannot convert cell "A" to coordinates: invalid cell name "A"`)
 
-       f.SetCellInt("Sheet2", "A1", 100)
+       assert.NoError(t, f.SetCellInt("Sheet2", "A1", 100))
 
        // Test set cell integer value with illegal row number.
        assert.EqualError(t, f.SetCellInt("Sheet2", "A", 100), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
@@ -80,8 +80,10 @@ func TestOpenFile(t *testing.T) {
        _, err = f.GetCellFormula("Sheet1", "B")
        assert.EqualError(t, err, `cannot convert cell "B" to coordinates: invalid cell name "B"`)
        // Test get shared cell formula
-       f.GetCellFormula("Sheet2", "H11")
-       f.GetCellFormula("Sheet2", "I11")
+       _, err = f.GetCellFormula("Sheet2", "H11")
+       assert.NoError(t, err)
+       _, err = f.GetCellFormula("Sheet2", "I11")
+       assert.NoError(t, err)
        getSharedForumula(&xlsxWorksheet{}, "")
 
        // Test read cell value with given illegal rows number.
@@ -91,10 +93,14 @@ func TestOpenFile(t *testing.T) {
        assert.EqualError(t, err, `cannot convert cell "A" to coordinates: invalid cell name "A"`)
 
        // Test read cell value with given lowercase column number.
-       f.GetCellValue("Sheet2", "a5")
-       f.GetCellValue("Sheet2", "C11")
-       f.GetCellValue("Sheet2", "D11")
-       f.GetCellValue("Sheet2", "D12")
+       _, err = f.GetCellValue("Sheet2", "a5")
+       assert.NoError(t, err)
+       _, err = f.GetCellValue("Sheet2", "C11")
+       assert.NoError(t, err)
+       _, err = f.GetCellValue("Sheet2", "D11")
+       assert.NoError(t, err)
+       _, err = f.GetCellValue("Sheet2", "D12")
+       assert.NoError(t, err)
        // Test SetCellValue function.
        assert.NoError(t, f.SetCellValue("Sheet2", "F1", " Hello"))
        assert.NoError(t, f.SetCellValue("Sheet2", "G1", []byte("World")))
@@ -147,7 +153,8 @@ func TestOpenFile(t *testing.T) {
        // Test completion column.
        f.SetCellValue("Sheet2", "M2", nil)
        // Test read cell value with given axis large than exists row.
-       f.GetCellValue("Sheet2", "E231")
+       _, err = f.GetCellValue("Sheet2", "E231")
+       assert.NoError(t, err)
        // Test get active worksheet of XLSX and get worksheet name of XLSX by given worksheet index.
        f.GetSheetName(f.GetActiveSheetIndex())
        // Test get worksheet index of XLSX by given worksheet name.
@@ -302,13 +309,10 @@ func TestSetCellHyperLink(t *testing.T) {
 
        assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellHyperLink.xlsx")))
 
-       file := NewFile()
-       for row := 1; row <= 65530; row++ {
-               cell, err := CoordinatesToCellName(1, row)
-               assert.NoError(t, err)
-               assert.NoError(t, file.SetCellHyperLink("Sheet1", cell, "https://github.com/360EntSecGroup-Skylar/excelize", "External"))
-       }
-       assert.EqualError(t, file.SetCellHyperLink("Sheet1", "A65531", "https://github.com/360EntSecGroup-Skylar/excelize", "External"), "over maximum limit hyperlinks in a worksheet")
+       f = NewFile()
+       f.workSheetReader("Sheet1")
+       f.Sheet["xl/worksheets/sheet1.xml"].Hyperlinks = &xlsxHyperlinks{Hyperlink: make([]xlsxHyperlink, 65530)}
+       assert.EqualError(t, f.SetCellHyperLink("Sheet1", "A65531", "https://github.com/360EntSecGroup-Skylar/excelize", "External"), "over maximum limit hyperlinks in a worksheet")
 
        f = NewFile()
        f.workSheetReader("Sheet1")
@@ -1013,6 +1017,8 @@ func TestSetActiveSheet(t *testing.T) {
        f.WorkBook.BookViews = &xlsxBookViews{WorkBookView: []xlsxWorkBookView{}}
        f.Sheet["xl/worksheets/sheet1.xml"].SheetViews = &xlsxSheetViews{SheetView: []xlsxSheetView{}}
        f.SetActiveSheet(1)
+       f.Sheet["xl/worksheets/sheet1.xml"].SheetViews = nil
+       f.SetActiveSheet(1)
 }
 
 func TestSetSheetVisible(t *testing.T) {
diff --git a/lib.go b/lib.go
index edac98a..86f8d16 100644 (file)
--- a/lib.go
+++ b/lib.go
@@ -198,6 +198,15 @@ func CoordinatesToCellName(col, row int) (string, error) {
 // boolPtr returns a pointer to a bool with the given value.
 func boolPtr(b bool) *bool { return &b }
 
+// intPtr returns a pointer to a int with the given value.
+func intPtr(i int) *int { return &i }
+
+// float64Ptr returns a pofloat64er to a float64 with the given value.
+func float64Ptr(f float64) *float64 { return &f }
+
+// stringPtr returns a pointer to a string with the given value.
+func stringPtr(s string) *string { return &s }
+
 // defaultTrue returns true if b is nil, or the pointed value.
 func defaultTrue(b *bool) bool {
        if b == nil {
index f284e43..2ea66ea 100644 (file)
--- a/shape.go
+++ b/shape.go
@@ -275,8 +275,7 @@ func (f *File) AddShape(sheet, cell, format string) error {
                drawingXML = strings.Replace(sheetRelationshipsDrawingXML, "..", "xl", -1)
        } else {
                // Add first shape for given sheet.
-               name, _ := f.sheetMap[trimSheetName(sheet)]
-               sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(name, "xl/worksheets/") + ".rels"
+               sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(f.sheetMap[trimSheetName(sheet)], "xl/worksheets/") + ".rels"
                rID := f.addRels(sheetRels, SourceRelationshipDrawingML, sheetRelationshipsDrawingXML, "")
                f.addSheetDrawing(sheet, rID)
        }
@@ -362,7 +361,7 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *format
                        FontRef: &aFontRef{
                                Idx: "minor",
                                SchemeClr: &attrValString{
-                                       Val: "tx1",
+                                       Val: stringPtr("tx1"),
                                },
                        },
                },
@@ -422,7 +421,7 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *format
                if len(srgbClr) == 6 {
                        paragraph.R.RPr.SolidFill = &aSolidFill{
                                SrgbClr: &attrValString{
-                                       Val: srgbClr,
+                                       Val: stringPtr(srgbClr),
                                },
                        }
                }
@@ -454,7 +453,7 @@ func setShapeRef(color string, i int) *aRef {
        return &aRef{
                Idx: i,
                SrgbClr: &attrValString{
-                       Val: strings.Replace(strings.ToUpper(color), "#", "", -1),
+                       Val: stringPtr(strings.Replace(strings.ToUpper(color), "#", "", -1)),
                },
        }
 }
index 7412fce..954de5b 100644 (file)
--- a/sheet.go
+++ b/sheet.go
@@ -249,6 +249,11 @@ func (f *File) SetActiveSheet(index int) {
        }
        for idx, name := range f.GetSheetMap() {
                xlsx, _ := f.workSheetReader(name)
+               if xlsx.SheetViews == nil {
+                       xlsx.SheetViews = &xlsxSheetViews{
+                               SheetView: []xlsxSheetView{{WorkbookViewID: 0}},
+                       }
+               }
                if len(xlsx.SheetViews.SheetView) > 0 {
                        xlsx.SheetViews.SheetView[0].TabSelected = false
                }
@@ -305,11 +310,15 @@ func (f *File) SetSheetName(oldName, newName string) {
 // string.
 func (f *File) GetSheetName(index int) string {
        wb := f.workbookReader()
-       realIdx := index - 1 // sheets are 1 based index, but we're checking against an array
-       if wb == nil || realIdx < 0 || realIdx >= len(wb.Sheets.Sheet) {
+       if wb == nil || index < 1 {
                return ""
        }
-       return wb.Sheets.Sheet[realIdx].Name
+       for _, sheet := range wb.Sheets.Sheet {
+               if index == sheet.SheetID {
+                       return sheet.Name
+               }
+       }
+       return ""
 }
 
 // GetSheetIndex provides a function to get worksheet index of XLSX by given
@@ -342,8 +351,8 @@ func (f *File) GetSheetMap() map[int]string {
        wb := f.workbookReader()
        sheetMap := map[int]string{}
        if wb != nil {
-               for i, sheet := range wb.Sheets.Sheet {
-                       sheetMap[i+1] = sheet.Name
+               for _, sheet := range wb.Sheets.Sheet {
+                       sheetMap[sheet.SheetID] = sheet.Name
                }
        }
        return sheetMap
@@ -384,8 +393,7 @@ func (f *File) SetSheetBackground(sheet, picture string) error {
        }
        file, _ := ioutil.ReadFile(picture)
        name := f.addMedia(file, ext)
-       sheetPath, _ := f.sheetMap[trimSheetName(sheet)]
-       sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetPath, "xl/worksheets/") + ".rels"
+       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.setContentTypePartImageExtensions()
index 8371a4e..4482bd1 100644 (file)
@@ -42,7 +42,7 @@ func TestStreamWriter(t *testing.T) {
        assert.NoError(t, file.SaveAs(filepath.Join("test", "TestStreamWriter.xlsx")))
 
        // Test error exceptions
-       streamWriter, err = file.NewStreamWriter("SheetN")
+       _, err = file.NewStreamWriter("SheetN")
        assert.EqualError(t, err, "sheet SheetN is not exist")
 }
 
index fa0507e..56c7196 100644 (file)
--- a/styles.go
+++ b/styles.go
@@ -1957,13 +1957,13 @@ func (f *File) NewConditionalStyle(style string) (int, error) {
 // Documents generated by excelize start with Calibri.
 func (f *File) GetDefaultFont() string {
        font := f.readDefaultFont()
-       return font.Name.Val
+       return *font.Name.Val
 }
 
 // SetDefaultFont changes the default font in the workbook.
 func (f *File) SetDefaultFont(fontName string) {
        font := f.readDefaultFont()
-       font.Name.Val = fontName
+       font.Name.Val = stringPtr(fontName)
        s := f.stylesReader()
        s.Fonts.Font[0] = font
        custom := true
@@ -1987,10 +1987,10 @@ func (f *File) setFont(formatStyle *formatStyle) *xlsxFont {
                formatStyle.Font.Color = "#000000"
        }
        fnt := xlsxFont{
-               Sz:     &attrValFloat{Val: formatStyle.Font.Size},
+               Sz:     &attrValFloat{Val: float64Ptr(formatStyle.Font.Size)},
                Color:  &xlsxColor{RGB: getPaletteColor(formatStyle.Font.Color)},
-               Name:   &attrValString{Val: formatStyle.Font.Family},
-               Family: &attrValInt{Val: 2},
+               Name:   &attrValString{Val: stringPtr(formatStyle.Font.Family)},
+               Family: &attrValInt{Val: intPtr(2)},
        }
        if formatStyle.Font.Bold {
                fnt.B = &formatStyle.Font.Bold
@@ -1998,8 +1998,8 @@ func (f *File) setFont(formatStyle *formatStyle) *xlsxFont {
        if formatStyle.Font.Italic {
                fnt.I = &formatStyle.Font.Italic
        }
-       if fnt.Name.Val == "" {
-               fnt.Name.Val = f.GetDefaultFont()
+       if *fnt.Name.Val == "" {
+               *fnt.Name.Val = f.GetDefaultFont()
        }
        if formatStyle.Font.Strike {
                strike := true
@@ -2007,7 +2007,7 @@ func (f *File) setFont(formatStyle *formatStyle) *xlsxFont {
        }
        val, ok := fontUnderlineType[formatStyle.Font.Underline]
        if ok {
-               fnt.U = &attrValString{Val: val}
+               fnt.U = &attrValString{Val: stringPtr(val)}
        }
        return &fnt
 }
index 36a78ed..e6faccb 100644 (file)
@@ -175,7 +175,7 @@ func TestNewStyle(t *testing.T) {
        styles := f.stylesReader()
        fontID := styles.CellXfs.Xf[styleID].FontID
        font := styles.Fonts.Font[fontID]
-       assert.Contains(t, font.Name.Val, "Times New Roman", "Stored font should contain font name")
+       assert.Contains(t, *font.Name.Val, "Times New Roman", "Stored font should contain font name")
        assert.Equal(t, 2, styles.CellXfs.Count, "Should have 2 styles")
 }
 
index d26f8fd..c5a704c 100644 (file)
--- a/table.go
+++ b/table.go
@@ -77,8 +77,7 @@ func (f *File) AddTable(sheet, hcell, vcell, format string) error {
        sheetRelationshipsTableXML := "../tables/table" + strconv.Itoa(tableID) + ".xml"
        tableXML := strings.Replace(sheetRelationshipsTableXML, "..", "xl", -1)
        // Add first table for given sheet.
-       sheetPath, _ := f.sheetMap[trimSheetName(sheet)]
-       sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetPath, "xl/worksheets/") + ".rels"
+       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)
index a02da2a..84c1a3b 100644 (file)
@@ -141,25 +141,25 @@ type aSchemeClr struct {
 // attrValInt directly maps the val element with integer data type as an
 // attribute。
 type attrValInt struct {
-       Val int `xml:"val,attr"`
+       Val *int `xml:"val,attr"`
 }
 
 // attrValFloat directly maps the val element with float64 data type as an
 // attribute。
 type attrValFloat struct {
-       Val float64 `xml:"val,attr"`
+       Val *float64 `xml:"val,attr"`
 }
 
 // attrValBool directly maps the val element with boolean data type as an
 // attribute。
 type attrValBool struct {
-       Val bool `xml:"val,attr"`
+       Val *bool `xml:"val,attr"`
 }
 
 // attrValString directly maps the val element with string data type as an
 // attribute。
 type attrValString struct {
-       Val string `xml:"val,attr"`
+       Val *string `xml:"val,attr"`
 }
 
 // aCs directly maps the a:cs element.
index 0549c5e..6e1dfb8 100644 (file)
@@ -187,7 +187,7 @@ type xlsxItem struct {
        F  bool   `xml:"f,attr,omitempty"`
        M  bool   `xml:"m,attr,omitempty"`
        C  bool   `xml:"c,attr,omitempty"`
-       X  int    `xml:"x,attr,omitempty,omitempty"`
+       X  int    `xml:"x,attr,omitempty"`
        D  bool   `xml:"d,attr,omitempty"`
        E  bool   `xml:"e,attr,omitempty"`
 }
index 8f39adf..57fd43f 100644 (file)
@@ -27,7 +27,7 @@ type xlsxWorksheet struct {
        ProtectedRanges       *xlsxInnerXML                `xml:"protectedRanges"`
        Scenarios             *xlsxInnerXML                `xml:"scenarios"`
        AutoFilter            *xlsxAutoFilter              `xml:"autoFilter"`
-       SortState             *xlsxInnerXML                `xml:"sortState"`
+       SortState             *xlsxSortState               `xml:"sortState"`
        DataConsolidate       *xlsxInnerXML                `xml:"dataConsolidate"`
        CustomSheetViews      *xlsxCustomSheetViews        `xml:"customSheetViews"`
        MergeCells            *xlsxMergeCells              `xml:"mergeCells"`
@@ -47,7 +47,7 @@ type xlsxWorksheet struct {
        SmartTags             *xlsxInnerXML                `xml:"smartTags"`
        Drawing               *xlsxDrawing                 `xml:"drawing"`
        LegacyDrawing         *xlsxLegacyDrawing           `xml:"legacyDrawing"`
-       LegacyDrawingHF       *xlsxInnerXML                `xml:"legacyDrawingHF"`
+       LegacyDrawingHF       *xlsxLegacyDrawingHF         `xml:"legacyDrawingHF"`
        DrawingHF             *xlsxDrawingHF               `xml:"drawingHF"`
        Picture               *xlsxPicture                 `xml:"picture"`
        OleObjects            *xlsxInnerXML                `xml:"oleObjects"`
@@ -328,6 +328,16 @@ type xlsxRow struct {
        C            []xlsxC `xml:"c"`
 }
 
+// xlsxSortState directly maps the sortState element. This collection
+// preserves the AutoFilter sort state.
+type xlsxSortState struct {
+       ColumnSort    bool   `xml:"columnSort,attr,omitempty"`
+       CaseSensitive bool   `xml:"caseSensitive,attr,omitempty"`
+       SortMethod    string `xml:"sortMethod,attr,omitempty"`
+       Ref           string `xml:"ref,attr"`
+       Content       string `xml:",innerxml"`
+}
+
 // xlsxCustomSheetViews directly maps the customSheetViews element. This is a
 // collection of custom sheet views.
 type xlsxCustomSheetViews struct {
@@ -424,7 +434,7 @@ type DataValidation struct {
        ShowErrorMessage bool    `xml:"showErrorMessage,attr,omitempty"`
        ShowInputMessage bool    `xml:"showInputMessage,attr,omitempty"`
        Sqref            string  `xml:"sqref,attr"`
-       Type             string  `xml:"type,attr"`
+       Type             string  `xml:"type,attr,omitempty"`
        Formula1         string  `xml:",innerxml"`
        Formula2         string  `xml:",innerxml"`
 }
@@ -448,7 +458,7 @@ type DataValidation struct {
 type xlsxC struct {
        XMLName  xml.Name `xml:"c"`
        XMLSpace xml.Attr `xml:"space,attr,omitempty"`
-       R        string   `xml:"r,attr"`           // Cell ID, e.g. A1
+       R        string   `xml:"r,attr,omitempty"` // 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.
@@ -665,6 +675,14 @@ type xlsxLegacyDrawing struct {
        RID     string   `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
 }
 
+// xlsxLegacyDrawingHF specifies the explicit relationship to the part
+// containing the VML defining pictures rendered in the header / footer of the
+// sheet.
+type xlsxLegacyDrawingHF struct {
+       XMLName xml.Name `xml:"legacyDrawingHF"`
+       RID     string   `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
+}
+
 type xlsxInnerXML struct {
        Content string `xml:",innerxml"`
 }