spreadsheet: add bar chart support

This commit is contained in:
Todd 2017-09-04 16:01:26 -05:00
parent 817869647c
commit 03fa89c7ee
6 changed files with 192 additions and 17 deletions

View File

@ -0,0 +1,71 @@
// Copyright 2017 Baliance. All rights reserved.
package main
import (
"fmt"
"log"
"baliance.com/gooxml/spreadsheet"
)
func main() {
ss := spreadsheet.New()
sheet := ss.AddSheet()
// Create all of our data
row := sheet.AddRow()
row.AddCell().SetString("Item")
row.AddCell().SetString("Price")
row.AddCell().SetString("# Sold")
row.AddCell().SetString("Total")
for r := 0; r < 5; r++ {
row := sheet.AddRow()
row.AddCell().SetString(fmt.Sprintf("Product %d", r+1))
row.AddCell().SetNumber(1.23 * float64(r+1))
row.AddCell().SetNumber(float64(r%3 + 1))
row.AddCell().SetFormulaRaw(fmt.Sprintf("C%d*B%d", r+2, r+2))
}
// Charts need to reside in a drawing
dwng := ss.AddDrawing()
chart := dwng.AddChart()
// make it a bit wider than the default
dwng.BottomRight().SetCol(15)
lc := chart.AddBarChart()
priceSeries := lc.AddSeries()
priceSeries.SetText("Price")
// Set a category axis reference on the first series to pull the product names
priceSeries.CategoryAxis().SetReference(`'Sheet 1'!A2:A6`)
priceSeries.Values().SetReference(`'Sheet 1'!B2:B6`)
soldSeries := lc.AddSeries()
soldSeries.SetText("Sold")
soldSeries.Values().SetReference(`'Sheet 1'!C2:C6`)
totalSeries := lc.AddSeries()
totalSeries.SetText("Total")
totalSeries.Values().SetReference(`'Sheet 1'!D2:D6`)
// the line chart accepts up to two axes
ca := chart.AddCategoryAxis()
va := chart.AddValueAxis()
lc.AddAxis(ca)
lc.AddAxis(va)
ca.SetCrosses(va)
va.SetCrosses(ca)
// add a title and legend
title := chart.AddTitle()
title.SetText("Items Sold")
chart.AddLegend()
// and finally add the chart to the sheet
sheet.SetDrawing(dwng)
if err := ss.Validate(); err != nil {
log.Fatalf("error validating sheet: %s", err)
}
ss.SaveToFile("bar-chart.xlsx")
}

View File

@ -7,10 +7,13 @@
package chart
import crt "baliance.com/gooxml/schema/schemas.openxmlformats.org/drawingml/2006/chart"
import (
crt "baliance.com/gooxml/schema/schemas.openxmlformats.org/drawingml/2006/chart"
)
// BarChart is a 2D bar chart.
type BarChart struct {
chartBase
x *crt.CT_BarChart
}
@ -18,3 +21,33 @@ type BarChart struct {
func (c BarChart) X() *crt.CT_BarChart {
return c.x
}
// InitializeDefaults the bar chart to its defaults
func (c BarChart) InitializeDefaults() {
c.SetDirection(crt.ST_BarDirCol)
}
// SetDirection changes the direction of the bar chart (bar or column).
func (c BarChart) SetDirection(d crt.ST_BarDir) {
c.x.BarDir.ValAttr = d
}
// AddSeries adds a default series to a bar chart.
func (c BarChart) AddSeries() BarChartSeries {
clr := c.nextColor(len(c.x.Ser))
ser := crt.NewCT_BarSer()
c.x.Ser = append(c.x.Ser, ser)
ser.Idx.ValAttr = uint32(len(c.x.Ser) - 1)
ser.Order.ValAttr = uint32(len(c.x.Ser) - 1)
bs := BarChartSeries{ser}
bs.InitializeDefaults()
bs.Properties().SetSolidFill(clr)
return bs
}
func (c BarChart) AddAxis(axis Axis) {
axisID := crt.NewCT_UnsignedInt()
axisID.ValAttr = axis.AxisID()
c.x.AxId = append(c.x.AxId, axisID)
}

55
chart/barchartseries.go Normal file
View File

@ -0,0 +1,55 @@
// Copyright 2017 Baliance. All rights reserved.
//
// Use of this source code is governed by the terms of the Affero GNU General
// Public License version 3.0 as published by the Free Software Foundation and
// appearing in the file LICENSE included in the packaging of this file. A
// commercial license can be purchased by contacting sales@baliance.com.
package chart
import (
"baliance.com/gooxml/drawing"
dml "baliance.com/gooxml/schema/schemas.openxmlformats.org/drawingml"
crt "baliance.com/gooxml/schema/schemas.openxmlformats.org/drawingml/2006/chart"
)
type BarChartSeries struct {
x *crt.CT_BarSer
}
// X returns the inner wrapped XML type.
func (c BarChartSeries) X() *crt.CT_BarSer {
return c.x
}
// InitializeDefaults initializes a bar chart series to the default values.
func (c BarChartSeries) InitializeDefaults() {
}
// SetText sets the series text
func (c BarChartSeries) SetText(s string) {
c.x.Tx = crt.NewCT_SerTx()
c.x.Tx.Choice.V = &s
}
func (c BarChartSeries) CategoryAxis() AxisDataSource {
if c.x.Cat == nil {
c.x.Cat = crt.NewCT_AxDataSource()
}
return MakeAxisDataSource(c.x.Cat)
}
func (c BarChartSeries) Values() NumberDataSource {
if c.x.Val == nil {
c.x.Val = crt.NewCT_NumDataSource()
}
return MakeNumberDataSource(c.x.Val)
}
// Properties returns the bar chart series shape properties.
func (c BarChartSeries) Properties() drawing.ShapeProperties {
if c.x.SpPr == nil {
c.x.SpPr = dml.NewCT_ShapeProperties()
}
return drawing.MakeShapeProperties(c.x.SpPr)
}

View File

@ -43,7 +43,7 @@ func (c Chart) AddLineChart() LineChart {
// TODO: needed?
chc.LineChart.Marker = crt.NewCT_Boolean()
chc.LineChart.Marker.ValAttr = gooxml.Bool(true)
return LineChart{chc.LineChart}
return LineChart{x: chc.LineChart}
}
// AddBarChart adds a new bar chart to a chart.
@ -54,7 +54,9 @@ func (c Chart) AddBarChart() BarChart {
chc.BarChart.Grouping = crt.NewCT_BarGrouping()
chc.BarChart.Grouping.ValAttr = crt.ST_BarGroupingStandard
return BarChart{chc.BarChart}
b := BarChart{x: chc.BarChart}
b.InitializeDefaults()
return b
}
func (c Chart) Properties() drawing.ShapeProperties {

24
chart/chartbase.go Normal file
View File

@ -0,0 +1,24 @@
// Copyright 2017 Baliance. All rights reserved.
//
// Use of this source code is governed by the terms of the Affero GNU General
// Public License version 3.0 as published by the Free Software Foundation and
// appearing in the file LICENSE included in the packaging of this file. A
// commercial license can be purchased by contacting sales@baliance.com.
package chart
import "baliance.com/gooxml/color"
var defaultColors = []color.Color{color.RGB(0x33, 0x66, 0xcc), color.RGB(0xDC, 0x39, 0x12), color.RGB(0xFF, 0x99, 0x00),
color.RGB(0x10, 0x96, 0x18), color.RGB(0x99, 0x00, 0x99), color.RGB(0x3B, 0x3E, 0xAC), color.RGB(0x00, 0x99, 0xC6),
color.RGB(0xDD, 0x44, 0x77), color.RGB(0x66, 0xAA, 0x00), color.RGB(0xB8, 0x2E, 0x2E), color.RGB(0x31, 0x63, 0x95),
color.RGB(0x99, 0x44, 0x99), color.RGB(0x22, 0xAA, 0x99), color.RGB(0xAA, 0xAA, 0x11), color.RGB(0x66, 0x33, 0xCC),
color.RGB(0xE6, 0x73, 0x00), color.RGB(0x8B, 0x07, 0x07), color.RGB(0x32, 0x92, 0x62), color.RGB(0x55, 0x74, 0xA6),
color.RGB(0x3B, 0x3E, 0xAC)}
type chartBase struct {
}
func (c chartBase) nextColor(idx int) color.Color {
return defaultColors[idx%len(defaultColors)]
}

View File

@ -8,11 +8,11 @@
package chart
import (
"baliance.com/gooxml/color"
crt "baliance.com/gooxml/schema/schemas.openxmlformats.org/drawingml/2006/chart"
)
type LineChart struct {
chartBase
x *crt.CT_LineChart
}
@ -21,20 +21,9 @@ func (c LineChart) X() *crt.CT_LineChart {
return c.x
}
var colors = []color.Color{color.RGB(0x33, 0x66, 0xcc), color.RGB(0xDC, 0x39, 0x12), color.RGB(0xFF, 0x99, 0x00),
color.RGB(0x10, 0x96, 0x18), color.RGB(0x99, 0x00, 0x99), color.RGB(0x3B, 0x3E, 0xAC), color.RGB(0x00, 0x99, 0xC6),
color.RGB(0xDD, 0x44, 0x77), color.RGB(0x66, 0xAA, 0x00), color.RGB(0xB8, 0x2E, 0x2E), color.RGB(0x31, 0x63, 0x95),
color.RGB(0x99, 0x44, 0x99), color.RGB(0x22, 0xAA, 0x99), color.RGB(0xAA, 0xAA, 0x11), color.RGB(0x66, 0x33, 0xCC),
color.RGB(0xE6, 0x73, 0x00), color.RGB(0x8B, 0x07, 0x07), color.RGB(0x32, 0x92, 0x62), color.RGB(0x55, 0x74, 0xA6),
color.RGB(0x3B, 0x3E, 0xAC)}
func (c LineChart) nextColor() color.Color {
idx := len(c.x.Ser)
return colors[idx%len(colors)]
}
// AddSeries adds a default series to a line chart.
func (c LineChart) AddSeries() LineChartSeries {
color := c.nextColor()
color := c.nextColor(len(c.x.Ser))
ser := crt.NewCT_LineSer()
c.x.Ser = append(c.x.Ser, ser)
ser.Idx.ValAttr = uint32(len(c.x.Ser) - 1)
@ -46,6 +35,7 @@ func (c LineChart) AddSeries() LineChartSeries {
return ls
}
// AddAxis adds an axis to a line chart.
func (c LineChart) AddAxis(axis Axis) {
axisID := crt.NewCT_UnsignedInt()
axisID.ValAttr = axis.AxisID()