excelize/sparkline.go
3zmx 50e23df865
ref #65, support _xlfn.ANCHORARRAY formula function (#1784)
- Initial formula array calculation support
- Update unit test and documentation
2024-01-18 15:31:43 +08:00

535 lines
23 KiB
Go

// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
// Package excelize providing a set of functions that allow you to write to and
// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
// Supports complex components by high compatibility, and provided streaming
// API for generating or reading data from a worksheet with huge amounts of
// data. This library needs Go version 1.18 or later.
package excelize
import (
"encoding/xml"
"io"
"sort"
"strings"
)
// sparklineGroupPresets defined the list of sparkline group to create
// x14:sparklineGroups element by given sparkline style ID.
var sparklineGroupPresets = []*xlsxX14SparklineGroup{
{
ColorSeries: &xlsxColor{Theme: intPtr(4), Tint: -0.499984740745262},
ColorNegative: &xlsxColor{Theme: intPtr(5)},
ColorMarkers: &xlsxColor{Theme: intPtr(4), Tint: -0.499984740745262},
ColorFirst: &xlsxColor{Theme: intPtr(4), Tint: 0.39997558519241921},
ColorLast: &xlsxColor{Theme: intPtr(4), Tint: 0.39997558519241921},
ColorHigh: &xlsxColor{Theme: intPtr(4)},
ColorLow: &xlsxColor{Theme: intPtr(4)},
}, // 0
{
ColorSeries: &xlsxColor{Theme: intPtr(4), Tint: -0.499984740745262},
ColorNegative: &xlsxColor{Theme: intPtr(5)},
ColorMarkers: &xlsxColor{Theme: intPtr(4), Tint: -0.499984740745262},
ColorFirst: &xlsxColor{Theme: intPtr(4), Tint: 0.39997558519241921},
ColorLast: &xlsxColor{Theme: intPtr(4), Tint: 0.39997558519241921},
ColorHigh: &xlsxColor{Theme: intPtr(4)},
ColorLow: &xlsxColor{Theme: intPtr(4)},
}, // 1
{
ColorSeries: &xlsxColor{Theme: intPtr(5), Tint: -0.499984740745262},
ColorNegative: &xlsxColor{Theme: intPtr(6)},
ColorMarkers: &xlsxColor{Theme: intPtr(5), Tint: -0.499984740745262},
ColorFirst: &xlsxColor{Theme: intPtr(5), Tint: 0.39997558519241921},
ColorLast: &xlsxColor{Theme: intPtr(5), Tint: 0.39997558519241921},
ColorHigh: &xlsxColor{Theme: intPtr(5)},
ColorLow: &xlsxColor{Theme: intPtr(5)},
}, // 2
{
ColorSeries: &xlsxColor{Theme: intPtr(6), Tint: -0.499984740745262},
ColorNegative: &xlsxColor{Theme: intPtr(7)},
ColorMarkers: &xlsxColor{Theme: intPtr(6), Tint: -0.499984740745262},
ColorFirst: &xlsxColor{Theme: intPtr(6), Tint: 0.39997558519241921},
ColorLast: &xlsxColor{Theme: intPtr(6), Tint: 0.39997558519241921},
ColorHigh: &xlsxColor{Theme: intPtr(6)},
ColorLow: &xlsxColor{Theme: intPtr(6)},
}, // 3
{
ColorSeries: &xlsxColor{Theme: intPtr(7), Tint: -0.499984740745262},
ColorNegative: &xlsxColor{Theme: intPtr(8)},
ColorMarkers: &xlsxColor{Theme: intPtr(7), Tint: -0.499984740745262},
ColorFirst: &xlsxColor{Theme: intPtr(7), Tint: 0.39997558519241921},
ColorLast: &xlsxColor{Theme: intPtr(7), Tint: 0.39997558519241921},
ColorHigh: &xlsxColor{Theme: intPtr(7)},
ColorLow: &xlsxColor{Theme: intPtr(7)},
}, // 4
{
ColorSeries: &xlsxColor{Theme: intPtr(8), Tint: -0.499984740745262},
ColorNegative: &xlsxColor{Theme: intPtr(9)},
ColorMarkers: &xlsxColor{Theme: intPtr(8), Tint: -0.499984740745262},
ColorFirst: &xlsxColor{Theme: intPtr(8), Tint: 0.39997558519241921},
ColorLast: &xlsxColor{Theme: intPtr(8), Tint: 0.39997558519241921},
ColorHigh: &xlsxColor{Theme: intPtr(8)},
ColorLow: &xlsxColor{Theme: intPtr(8)},
}, // 5
{
ColorSeries: &xlsxColor{Theme: intPtr(9), Tint: -0.499984740745262},
ColorNegative: &xlsxColor{Theme: intPtr(4)},
ColorMarkers: &xlsxColor{Theme: intPtr(9), Tint: -0.499984740745262},
ColorFirst: &xlsxColor{Theme: intPtr(9), Tint: 0.39997558519241921},
ColorLast: &xlsxColor{Theme: intPtr(9), Tint: 0.39997558519241921},
ColorHigh: &xlsxColor{Theme: intPtr(9)},
ColorLow: &xlsxColor{Theme: intPtr(9)},
}, // 6
{
ColorSeries: &xlsxColor{Theme: intPtr(4), Tint: -0.249977111117893},
ColorNegative: &xlsxColor{Theme: intPtr(5)},
ColorMarkers: &xlsxColor{Theme: intPtr(5), Tint: -0.249977111117893},
ColorFirst: &xlsxColor{Theme: intPtr(5), Tint: -0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(5), Tint: -0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(5)},
ColorLow: &xlsxColor{Theme: intPtr(5)},
}, // 7
{
ColorSeries: &xlsxColor{Theme: intPtr(5), Tint: -0.249977111117893},
ColorNegative: &xlsxColor{Theme: intPtr(6)},
ColorMarkers: &xlsxColor{Theme: intPtr(6), Tint: -0.249977111117893},
ColorFirst: &xlsxColor{Theme: intPtr(6), Tint: -0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(6), Tint: -0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(6), Tint: -0.249977111117893},
ColorLow: &xlsxColor{Theme: intPtr(6), Tint: -0.249977111117893},
}, // 8
{
ColorSeries: &xlsxColor{Theme: intPtr(6), Tint: -0.249977111117893},
ColorNegative: &xlsxColor{Theme: intPtr(7)},
ColorMarkers: &xlsxColor{Theme: intPtr(7), Tint: -0.249977111117893},
ColorFirst: &xlsxColor{Theme: intPtr(7), Tint: -0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(7), Tint: -0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(7), Tint: -0.249977111117893},
ColorLow: &xlsxColor{Theme: intPtr(7), Tint: -0.249977111117893},
}, // 9
{
ColorSeries: &xlsxColor{Theme: intPtr(7), Tint: -0.249977111117893},
ColorNegative: &xlsxColor{Theme: intPtr(8)},
ColorMarkers: &xlsxColor{Theme: intPtr(8), Tint: -0.249977111117893},
ColorFirst: &xlsxColor{Theme: intPtr(8), Tint: -0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(8), Tint: -0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(8), Tint: -0.249977111117893},
ColorLow: &xlsxColor{Theme: intPtr(8), Tint: -0.249977111117893},
}, // 10
{
ColorSeries: &xlsxColor{Theme: intPtr(8), Tint: -0.249977111117893},
ColorNegative: &xlsxColor{Theme: intPtr(9)},
ColorMarkers: &xlsxColor{Theme: intPtr(9), Tint: -0.249977111117893},
ColorFirst: &xlsxColor{Theme: intPtr(9), Tint: -0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(9), Tint: -0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(9), Tint: -0.249977111117893},
ColorLow: &xlsxColor{Theme: intPtr(9), Tint: -0.249977111117893},
}, // 11
{
ColorSeries: &xlsxColor{Theme: intPtr(9), Tint: -0.249977111117893},
ColorNegative: &xlsxColor{Theme: intPtr(4)},
ColorMarkers: &xlsxColor{Theme: intPtr(4), Tint: -0.249977111117893},
ColorFirst: &xlsxColor{Theme: intPtr(4), Tint: -0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(4), Tint: -0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(4), Tint: -0.249977111117893},
ColorLow: &xlsxColor{Theme: intPtr(4), Tint: -0.249977111117893},
}, // 12
{
ColorSeries: &xlsxColor{Theme: intPtr(4)},
ColorNegative: &xlsxColor{Theme: intPtr(5)},
ColorMarkers: &xlsxColor{Theme: intPtr(4), Tint: -0.249977111117893},
ColorFirst: &xlsxColor{Theme: intPtr(4), Tint: -0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(4), Tint: -0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(4), Tint: -0.249977111117893},
ColorLow: &xlsxColor{Theme: intPtr(4), Tint: -0.249977111117893},
}, // 13
{
ColorSeries: &xlsxColor{Theme: intPtr(5)},
ColorNegative: &xlsxColor{Theme: intPtr(6)},
ColorMarkers: &xlsxColor{Theme: intPtr(5), Tint: -0.249977111117893},
ColorFirst: &xlsxColor{Theme: intPtr(5), Tint: -0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(5), Tint: -0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(5), Tint: -0.249977111117893},
ColorLow: &xlsxColor{Theme: intPtr(5), Tint: -0.249977111117893},
}, // 14
{
ColorSeries: &xlsxColor{Theme: intPtr(6)},
ColorNegative: &xlsxColor{Theme: intPtr(7)},
ColorMarkers: &xlsxColor{Theme: intPtr(6), Tint: -0.249977111117893},
ColorFirst: &xlsxColor{Theme: intPtr(6), Tint: -0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(6), Tint: -0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(6), Tint: -0.249977111117893},
ColorLow: &xlsxColor{Theme: intPtr(6), Tint: -0.249977111117893},
}, // 15
{
ColorSeries: &xlsxColor{Theme: intPtr(7)},
ColorNegative: &xlsxColor{Theme: intPtr(8)},
ColorMarkers: &xlsxColor{Theme: intPtr(7), Tint: -0.249977111117893},
ColorFirst: &xlsxColor{Theme: intPtr(7), Tint: -0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(7), Tint: -0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(7), Tint: -0.249977111117893},
ColorLow: &xlsxColor{Theme: intPtr(7), Tint: -0.249977111117893},
}, // 16
{
ColorSeries: &xlsxColor{Theme: intPtr(8)},
ColorNegative: &xlsxColor{Theme: intPtr(9)},
ColorMarkers: &xlsxColor{Theme: intPtr(8), Tint: -0.249977111117893},
ColorFirst: &xlsxColor{Theme: intPtr(8), Tint: -0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(8), Tint: -0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(8), Tint: -0.249977111117893},
ColorLow: &xlsxColor{Theme: intPtr(8), Tint: -0.249977111117893},
}, // 17
{
ColorSeries: &xlsxColor{Theme: intPtr(9)},
ColorNegative: &xlsxColor{Theme: intPtr(4)},
ColorMarkers: &xlsxColor{Theme: intPtr(9), Tint: -0.249977111117893},
ColorFirst: &xlsxColor{Theme: intPtr(9), Tint: -0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(9), Tint: -0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(9), Tint: -0.249977111117893},
ColorLow: &xlsxColor{Theme: intPtr(9), Tint: -0.249977111117893},
}, // 18
{
ColorSeries: &xlsxColor{Theme: intPtr(4), Tint: 0.39997558519241921},
ColorNegative: &xlsxColor{Theme: intPtr(0), Tint: -0.499984740745262},
ColorMarkers: &xlsxColor{Theme: intPtr(4), Tint: 0.79998168889431442},
ColorFirst: &xlsxColor{Theme: intPtr(4), Tint: -0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(4), Tint: -0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(4), Tint: -0.499984740745262},
ColorLow: &xlsxColor{Theme: intPtr(4), Tint: -0.499984740745262},
}, // 19
{
ColorSeries: &xlsxColor{Theme: intPtr(5), Tint: 0.39997558519241921},
ColorNegative: &xlsxColor{Theme: intPtr(0), Tint: -0.499984740745262},
ColorMarkers: &xlsxColor{Theme: intPtr(5), Tint: 0.79998168889431442},
ColorFirst: &xlsxColor{Theme: intPtr(5), Tint: -0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(5), Tint: -0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(5), Tint: -0.499984740745262},
ColorLow: &xlsxColor{Theme: intPtr(5), Tint: -0.499984740745262},
}, // 20
{
ColorSeries: &xlsxColor{Theme: intPtr(6), Tint: 0.39997558519241921},
ColorNegative: &xlsxColor{Theme: intPtr(0), Tint: -0.499984740745262},
ColorMarkers: &xlsxColor{Theme: intPtr(6), Tint: 0.79998168889431442},
ColorFirst: &xlsxColor{Theme: intPtr(6), Tint: -0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(6), Tint: -0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(6), Tint: -0.499984740745262},
ColorLow: &xlsxColor{Theme: intPtr(6), Tint: -0.499984740745262},
}, // 21
{
ColorSeries: &xlsxColor{Theme: intPtr(7), Tint: 0.39997558519241921},
ColorNegative: &xlsxColor{Theme: intPtr(0), Tint: -0.499984740745262},
ColorMarkers: &xlsxColor{Theme: intPtr(7), Tint: 0.79998168889431442},
ColorFirst: &xlsxColor{Theme: intPtr(7), Tint: -0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(7), Tint: -0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(7), Tint: -0.499984740745262},
ColorLow: &xlsxColor{Theme: intPtr(7), Tint: -0.499984740745262},
}, // 22
{
ColorSeries: &xlsxColor{Theme: intPtr(8), Tint: 0.39997558519241921},
ColorNegative: &xlsxColor{Theme: intPtr(0), Tint: -0.499984740745262},
ColorMarkers: &xlsxColor{Theme: intPtr(8), Tint: 0.79998168889431442},
ColorFirst: &xlsxColor{Theme: intPtr(8), Tint: -0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(8), Tint: -0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(8), Tint: -0.499984740745262},
ColorLow: &xlsxColor{Theme: intPtr(8), Tint: -0.499984740745262},
}, // 23
{
ColorSeries: &xlsxColor{Theme: intPtr(9), Tint: 0.39997558519241921},
ColorNegative: &xlsxColor{Theme: intPtr(0), Tint: -0.499984740745262},
ColorMarkers: &xlsxColor{Theme: intPtr(9), Tint: 0.79998168889431442},
ColorFirst: &xlsxColor{Theme: intPtr(9), Tint: -0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(9), Tint: -0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(9), Tint: -0.499984740745262},
ColorLow: &xlsxColor{Theme: intPtr(9), Tint: -0.499984740745262},
}, // 24
{
ColorSeries: &xlsxColor{Theme: intPtr(1), Tint: 0.499984740745262},
ColorNegative: &xlsxColor{Theme: intPtr(1), Tint: 0.249977111117893},
ColorMarkers: &xlsxColor{Theme: intPtr(1), Tint: 0.249977111117893},
ColorFirst: &xlsxColor{Theme: intPtr(1), Tint: 0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(1), Tint: 0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(1), Tint: 0.249977111117893},
ColorLow: &xlsxColor{Theme: intPtr(1), Tint: 0.249977111117893},
}, // 25
{
ColorSeries: &xlsxColor{Theme: intPtr(1), Tint: 0.34998626667073579},
ColorNegative: &xlsxColor{Theme: intPtr(0), Tint: 0.249977111117893},
ColorMarkers: &xlsxColor{Theme: intPtr(0), Tint: 0.249977111117893},
ColorFirst: &xlsxColor{Theme: intPtr(0), Tint: 0.249977111117893},
ColorLast: &xlsxColor{Theme: intPtr(0), Tint: 0.249977111117893},
ColorHigh: &xlsxColor{Theme: intPtr(0), Tint: 0.249977111117893},
ColorLow: &xlsxColor{Theme: intPtr(0), Tint: 0.249977111117893},
}, // 26
{
ColorSeries: &xlsxColor{RGB: "FF323232"},
ColorNegative: &xlsxColor{RGB: "FFD00000"},
ColorMarkers: &xlsxColor{RGB: "FFD00000"},
ColorFirst: &xlsxColor{RGB: "FFD00000"},
ColorLast: &xlsxColor{RGB: "FFD00000"},
ColorHigh: &xlsxColor{RGB: "FFD00000"},
ColorLow: &xlsxColor{RGB: "FFD00000"},
}, // 27
{
ColorSeries: &xlsxColor{RGB: "FF000000"},
ColorNegative: &xlsxColor{RGB: "FF0070C0"},
ColorMarkers: &xlsxColor{RGB: "FF0070C0"},
ColorFirst: &xlsxColor{RGB: "FF0070C0"},
ColorLast: &xlsxColor{RGB: "FF0070C0"},
ColorHigh: &xlsxColor{RGB: "FF0070C0"},
ColorLow: &xlsxColor{RGB: "FF0070C0"},
}, // 28
{
ColorSeries: &xlsxColor{RGB: "FF376092"},
ColorNegative: &xlsxColor{RGB: "FFD00000"},
ColorMarkers: &xlsxColor{RGB: "FFD00000"},
ColorFirst: &xlsxColor{RGB: "FFD00000"},
ColorLast: &xlsxColor{RGB: "FFD00000"},
ColorHigh: &xlsxColor{RGB: "FFD00000"},
ColorLow: &xlsxColor{RGB: "FFD00000"},
}, // 29
{
ColorSeries: &xlsxColor{RGB: "FF0070C0"},
ColorNegative: &xlsxColor{RGB: "FF000000"},
ColorMarkers: &xlsxColor{RGB: "FF000000"},
ColorFirst: &xlsxColor{RGB: "FF000000"},
ColorLast: &xlsxColor{RGB: "FF000000"},
ColorHigh: &xlsxColor{RGB: "FF000000"},
ColorLow: &xlsxColor{RGB: "FF000000"},
}, // 30
{
ColorSeries: &xlsxColor{RGB: "FF5F5F5F"},
ColorNegative: &xlsxColor{RGB: "FFFFB620"},
ColorMarkers: &xlsxColor{RGB: "FFD70077"},
ColorFirst: &xlsxColor{RGB: "FF5687C2"},
ColorLast: &xlsxColor{RGB: "FF359CEB"},
ColorHigh: &xlsxColor{RGB: "FF56BE79"},
ColorLow: &xlsxColor{RGB: "FFFF5055"},
}, // 31
{
ColorSeries: &xlsxColor{RGB: "FF5687C2"},
ColorNegative: &xlsxColor{RGB: "FFFFB620"},
ColorMarkers: &xlsxColor{RGB: "FFD70077"},
ColorFirst: &xlsxColor{RGB: "FF777777"},
ColorLast: &xlsxColor{RGB: "FF359CEB"},
ColorHigh: &xlsxColor{RGB: "FF56BE79"},
ColorLow: &xlsxColor{RGB: "FFFF5055"},
}, // 32
{
ColorSeries: &xlsxColor{RGB: "FFC6EFCE"},
ColorNegative: &xlsxColor{RGB: "FFFFC7CE"},
ColorMarkers: &xlsxColor{RGB: "FF8CADD6"},
ColorFirst: &xlsxColor{RGB: "FFFFDC47"},
ColorLast: &xlsxColor{RGB: "FFFFEB9C"},
ColorHigh: &xlsxColor{RGB: "FF60D276"},
ColorLow: &xlsxColor{RGB: "FFFF5367"},
}, // 33
{
ColorSeries: &xlsxColor{RGB: "FF00B050"},
ColorNegative: &xlsxColor{RGB: "FFFF0000"},
ColorMarkers: &xlsxColor{RGB: "FF0070C0"},
ColorFirst: &xlsxColor{RGB: "FFFFC000"},
ColorLast: &xlsxColor{RGB: "FFFFC000"},
ColorHigh: &xlsxColor{RGB: "FF00B050"},
ColorLow: &xlsxColor{RGB: "FFFF0000"},
}, // 34
{
ColorSeries: &xlsxColor{Theme: intPtr(3)},
ColorNegative: &xlsxColor{Theme: intPtr(9)},
ColorMarkers: &xlsxColor{Theme: intPtr(8)},
ColorFirst: &xlsxColor{Theme: intPtr(4)},
ColorLast: &xlsxColor{Theme: intPtr(5)},
ColorHigh: &xlsxColor{Theme: intPtr(6)},
ColorLow: &xlsxColor{Theme: intPtr(7)},
}, // 35
{
ColorSeries: &xlsxColor{Theme: intPtr(1)},
ColorNegative: &xlsxColor{Theme: intPtr(9)},
ColorMarkers: &xlsxColor{Theme: intPtr(8)},
ColorFirst: &xlsxColor{Theme: intPtr(4)},
ColorLast: &xlsxColor{Theme: intPtr(5)},
ColorHigh: &xlsxColor{Theme: intPtr(6)},
ColorLow: &xlsxColor{Theme: intPtr(7)},
}, // 36
}
// AddSparkline provides a function to add sparklines to the worksheet by
// given formatting options. Sparklines are small charts that fit in a single
// cell and are used to show trends in data. Sparklines are a feature of Excel
// 2010 and later only. You can write them to an XLSX file that can be read by
// Excel 2007, but they won't be displayed. For example, add a grouped
// sparkline. Changes are applied to all three:
//
// err := f.AddSparkline("Sheet1", &excelize.SparklineOptions{
// Location: []string{"A1", "A2", "A3"},
// Range: []string{"Sheet2!A1:J1", "Sheet2!A2:J2", "Sheet2!A3:J3"},
// Markers: true,
// })
//
// The following shows the formatting options of sparkline supported by excelize:
//
// Parameter | Description
// -------------+--------------------------------------------
// Location | Required, must have the same number with 'Range' parameter
// Range | Required, must have the same number with 'Location' parameter
// Type | Enumeration value: line, column, win_loss
// Style | Value range: 0 - 35
// Hight | Toggle sparkline high points
// Low | Toggle sparkline low points
// First | Toggle sparkline first points
// Last | Toggle sparkline last points
// Negative | Toggle sparkline negative points
// Markers | Toggle sparkline markers
// Axis | Used to specify if show horizontal axis
// Reverse | Used to specify if enable plot data right-to-left
// SeriesColor | An RGB Color is specified as RRGGBB
func (f *File) AddSparkline(sheet string, opts *SparklineOptions) error {
var (
err error
ws *xlsxWorksheet
sparkType string
sparkTypes map[string]string
specifiedSparkTypes string
ok bool
group *xlsxX14SparklineGroup
groups *xlsxX14SparklineGroups
)
// parameter validation
if ws, err = f.parseFormatAddSparklineSet(sheet, opts); err != nil {
return err
}
// Handle the sparkline type
sparkType = "line"
sparkTypes = map[string]string{"line": "line", "column": "column", "win_loss": "stacked"}
if opts.Type != "" {
if specifiedSparkTypes, ok = sparkTypes[opts.Type]; !ok {
err = ErrSparklineType
return err
}
sparkType = specifiedSparkTypes
}
group = sparklineGroupPresets[opts.Style]
group.Type = sparkType
group.ColorAxis = &xlsxColor{RGB: "FF000000"}
group.DisplayEmptyCellsAs = "gap"
group.High = opts.High
group.Low = opts.Low
group.First = opts.First
group.Last = opts.Last
group.Negative = opts.Negative
group.DisplayXAxis = opts.Axis
group.Markers = opts.Markers
if opts.SeriesColor != "" {
group.ColorSeries = &xlsxColor{
RGB: getPaletteColor(opts.SeriesColor),
}
}
if opts.Reverse {
group.RightToLeft = opts.Reverse
}
f.addSparkline(opts, group)
if err = f.appendSparkline(ws, group, groups); err != nil {
return err
}
f.addSheetNameSpace(sheet, NameSpaceSpreadSheetX14)
return err
}
// parseFormatAddSparklineSet provides a function to validate sparkline
// properties.
func (f *File) parseFormatAddSparklineSet(sheet string, opts *SparklineOptions) (*xlsxWorksheet, error) {
ws, err := f.workSheetReader(sheet)
if err != nil {
return ws, err
}
if opts == nil {
return ws, ErrParameterRequired
}
if len(opts.Location) < 1 {
return ws, ErrSparklineLocation
}
if len(opts.Range) < 1 {
return ws, ErrSparklineRange
}
// The range and locations must match
if len(opts.Location) != len(opts.Range) {
return ws, ErrSparkline
}
if opts.Style < 0 || opts.Style > 35 {
return ws, ErrSparklineStyle
}
if ws.ExtLst == nil {
ws.ExtLst = &xlsxExtLst{}
}
return ws, err
}
// addSparkline provides a function to create a sparkline in a sparkline group
// by given properties.
func (f *File) addSparkline(opts *SparklineOptions, group *xlsxX14SparklineGroup) {
for idx, location := range opts.Location {
group.Sparklines.Sparkline = append(group.Sparklines.Sparkline, &xlsxX14Sparkline{
F: opts.Range[idx],
Sqref: location,
})
}
}
// appendSparkline provides a function to append sparkline to sparkline
// groups.
func (f *File) appendSparkline(ws *xlsxWorksheet, group *xlsxX14SparklineGroup, groups *xlsxX14SparklineGroups) error {
var (
err error
idx int
appendMode bool
decodeExtLst = new(decodeExtLst)
decodeSparklineGroups *decodeX14SparklineGroups
ext *xlsxExt
sparklineGroupsBytes, sparklineGroupBytes, extLstBytes []byte
)
sparklineGroupBytes, _ = xml.Marshal(group)
if ws.ExtLst != nil { // append mode ext
if err = f.xmlNewDecoder(strings.NewReader("<extLst>" + ws.ExtLst.Ext + "</extLst>")).
Decode(decodeExtLst); err != nil && err != io.EOF {
return err
}
for idx, ext = range decodeExtLst.Ext {
if ext.URI == ExtURISparklineGroups {
decodeSparklineGroups = new(decodeX14SparklineGroups)
if err = f.xmlNewDecoder(strings.NewReader(ext.Content)).
Decode(decodeSparklineGroups); err != nil && err != io.EOF {
return err
}
if groups == nil {
groups = &xlsxX14SparklineGroups{}
}
groups.XMLNSXM = NameSpaceSpreadSheetExcel2006Main.Value
groups.Content = decodeSparklineGroups.Content + string(sparklineGroupBytes)
sparklineGroupsBytes, _ = xml.Marshal(groups)
decodeExtLst.Ext[idx].Content = string(sparklineGroupsBytes)
appendMode = true
}
}
}
if !appendMode {
sparklineGroupsBytes, _ = xml.Marshal(&xlsxX14SparklineGroups{
XMLNSXM: NameSpaceSpreadSheetExcel2006Main.Value,
SparklineGroups: []*xlsxX14SparklineGroup{group},
})
decodeExtLst.Ext = append(decodeExtLst.Ext, &xlsxExt{
URI: ExtURISparklineGroups, Content: string(sparklineGroupsBytes),
})
}
sort.Slice(decodeExtLst.Ext, func(i, j int) bool {
return inStrSlice(worksheetExtURIPriority, decodeExtLst.Ext[i].URI, false) <
inStrSlice(worksheetExtURIPriority, decodeExtLst.Ext[j].URI, false)
})
extLstBytes, err = xml.Marshal(decodeExtLst)
ws.ExtLst = &xlsxExtLst{Ext: strings.TrimSuffix(strings.TrimPrefix(string(extLstBytes), "<extLst>"), "</extLst>")}
return err
}