chart, drawing: start adding chart & drawing support

- Created chart, drawing packages for the chart/drawing stuff common
  between document type
- Need to go back and clean up any drawing related document types after
This commit is contained in:
Todd 2017-09-03 16:47:46 -05:00
parent dc920417d0
commit 0dae44f002
11 changed files with 447 additions and 1 deletions

24
chart/axisdatasource.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 crt "baliance.com/gooxml/schema/schemas.openxmlformats.org/drawingml/2006/chart"
type AxisDataSource struct {
x *crt.CT_AxDataSource
}
func MakeAxisDataSource(x *crt.CT_AxDataSource) AxisDataSource {
return AxisDataSource{x}
}
func (a AxisDataSource) SetReference(s string) {
a.x.Choice = crt.NewCT_AxDataSourceChoice()
a.x.Choice.StrRef = crt.NewCT_StrRef()
a.x.Choice.StrRef.F = s
}

61
chart/datalabels.go Normal file
View File

@ -0,0 +1,61 @@
// 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"
crt "baliance.com/gooxml/schema/schemas.openxmlformats.org/drawingml/2006/chart"
)
type DataLabels struct {
x *crt.CT_DLbls
}
func MakeDataLabels(x *crt.CT_DLbls) DataLabels {
return DataLabels{x}
}
func (d DataLabels) ensureChoice() {
if d.x.Choice == nil {
d.x.Choice = crt.NewCT_DLblsChoice()
}
}
func (d DataLabels) SetShowLegendKey(b bool) {
d.ensureChoice()
d.x.Choice.ShowLegendKey = crt.NewCT_Boolean()
d.x.Choice.ShowLegendKey.ValAttr = gooxml.Bool(b)
}
func (d DataLabels) SetShowValue(b bool) {
d.ensureChoice()
d.x.Choice.ShowVal = crt.NewCT_Boolean()
d.x.Choice.ShowVal.ValAttr = gooxml.Bool(b)
}
func (d DataLabels) SetShowCategoryName(b bool) {
d.ensureChoice()
d.x.Choice.ShowCatName = crt.NewCT_Boolean()
d.x.Choice.ShowCatName.ValAttr = gooxml.Bool(b)
}
func (d DataLabels) SetShowSeriesName(b bool) {
d.ensureChoice()
d.x.Choice.ShowSerName = crt.NewCT_Boolean()
d.x.Choice.ShowSerName.ValAttr = gooxml.Bool(b)
}
func (d DataLabels) SetShowPercent(b bool) {
d.ensureChoice()
d.x.Choice.ShowPercent = crt.NewCT_Boolean()
d.x.Choice.ShowPercent.ValAttr = gooxml.Bool(b)
}
func (d DataLabels) SetShowLeaderLines(b bool) {
d.ensureChoice()
d.x.Choice.ShowLeaderLines = crt.NewCT_Boolean()
d.x.Choice.ShowLeaderLines.ValAttr = gooxml.Bool(b)
}

47
chart/marker.go Normal file
View File

@ -0,0 +1,47 @@
// 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 Marker struct {
x *crt.CT_Marker
}
func MakeMarker(x *crt.CT_Marker) Marker {
return Marker{x}
}
// X returns the inner wrapped XML type.
func (m Marker) X() *crt.CT_Marker {
return m.x
}
func (m Marker) SetSymbol(s crt.ST_MarkerStyle) {
if s == crt.ST_MarkerStyleUnset {
m.x.Symbol = nil
} else {
m.x.Symbol = crt.NewCT_MarkerStyle()
m.x.Symbol.ValAttr = s
}
}
func (m Marker) SetSize(sz uint8) {
m.x.Size = crt.NewCT_MarkerSize()
m.x.Size.ValAttr = &sz
}
func (m Marker) Properties() drawing.ShapeProperties {
if m.x.SpPr == nil {
m.x.SpPr = dml.NewCT_ShapeProperties()
}
return drawing.MakeShapeProperties(m.x.SpPr)
}

66
drawing/lineproperties.go Normal file
View File

@ -0,0 +1,66 @@
// 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 drawing
import (
"baliance.com/gooxml"
"baliance.com/gooxml/color"
"baliance.com/gooxml/measurement"
dml "baliance.com/gooxml/schema/schemas.openxmlformats.org/drawingml"
)
type LineProperties struct {
x *dml.CT_LineProperties
}
// X returns the inner wrapped XML type.
func (l LineProperties) X() *dml.CT_LineProperties {
return l.x
}
// SetWidth sets the line width, MS products treat zero as the minimum width
// that can be displayed.
func (l LineProperties) SetWidth(w measurement.Distance) {
// TODO: check these units, can't find documentation on them but this seems
// to be the right range
l.x.WAttr = gooxml.Int32(int32(w / measurement.EMU))
}
func (l LineProperties) SetSolidFill(c color.Color) {
l.x.NoFill = nil
l.x.GradFill = nil
l.x.PattFill = nil
l.x.SolidFill = dml.NewCT_SolidColorFillProperties()
l.x.SolidFill.SrgbClr = dml.NewCT_SRgbColor()
l.x.SolidFill.SrgbClr.ValAttr = *c.AsRGBAString()
}
// LineJoin is the type of line join
type LineJoin byte
// LineJoin types
const (
LineJoinRound LineJoin = iota
LineJoinBevel
LineJoinMiter
)
// SetJoin sets the line join style.
func (l LineProperties) SetJoin(e LineJoin) {
l.x.Round = nil
l.x.Miter = nil
l.x.Bevel = nil
switch e {
case LineJoinRound:
l.x.Round = dml.NewCT_LineJoinRound()
case LineJoinBevel:
l.x.Bevel = dml.NewCT_LineJoinBevel()
case LineJoinMiter:
l.x.Miter = dml.NewCT_LineJoinMiterProperties()
}
}

View File

@ -0,0 +1,40 @@
// 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 drawing
import (
"baliance.com/gooxml/color"
dml "baliance.com/gooxml/schema/schemas.openxmlformats.org/drawingml"
)
type ShapeProperties struct {
x *dml.CT_ShapeProperties
}
func MakeShapeProperties(x *dml.CT_ShapeProperties) ShapeProperties {
return ShapeProperties{x}
}
// X returns the inner wrapped XML type.
func (s ShapeProperties) X() *dml.CT_ShapeProperties {
return s.x
}
func (s ShapeProperties) SetSolidFill(c color.Color) {
s.x.SolidFill = dml.NewCT_SolidColorFillProperties()
s.x.SolidFill.SrgbClr = dml.NewCT_SRgbColor()
s.x.SolidFill.SrgbClr.ValAttr = *c.AsRGBAString()
}
func (s ShapeProperties) LineProperties() LineProperties {
if s.x.Ln == nil {
s.x.Ln = dml.NewCT_LineProperties()
}
return LineProperties{s.x.Ln}
}

View File

@ -39,7 +39,7 @@ func RelativeFilename(dt DocType, typ string, index int) string {
case StylesType:
return "styles.xml"
case ChartType:
return fmt.Sprintf("charts/chart%d.xml", index)
return fmt.Sprintf("../charts/chart%d.xml", index)
case DrawingType:
return fmt.Sprintf("drawings/drawing%d.xml", index)

28
spreadsheet/chart.go Normal file
View File

@ -0,0 +1,28 @@
// 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 spreadsheet
import crt "baliance.com/gooxml/schema/schemas.openxmlformats.org/drawingml/2006/chart"
type Chart struct {
x *crt.ChartSpace
}
// X returns the inner wrapped XML type.
func (c Chart) X() *crt.ChartSpace {
return c.x
}
func (c Chart) AddLineChart() LineChart {
chc := crt.NewCT_PlotAreaChoice()
c.x.Chart.PlotArea.Choice = append(c.x.Chart.PlotArea.Choice, chc)
chc.LineChart = crt.NewCT_LineChart()
chc.LineChart.Grouping = crt.NewCT_Grouping()
chc.LineChart.Grouping.ValAttr = crt.ST_GroupingStandard
return LineChart{chc.LineChart}
}

54
spreadsheet/drawing.go Normal file
View File

@ -0,0 +1,54 @@
// 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 spreadsheet
import (
"baliance.com/gooxml"
dml "baliance.com/gooxml/schema/schemas.openxmlformats.org/drawingml"
c "baliance.com/gooxml/schema/schemas.openxmlformats.org/drawingml/2006/chart"
crt "baliance.com/gooxml/schema/schemas.openxmlformats.org/drawingml/2006/chart"
sd "baliance.com/gooxml/schema/schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"
)
type Drawing struct {
wb *Workbook
x *sd.WsDr
}
// X returns the inner wrapped XML type.
func (d Drawing) X() *sd.WsDr {
return d.x
}
func (d Drawing) AddChart() Chart {
chart := crt.NewChartSpace()
d.wb.charts = append(d.wb.charts, chart)
var chartID string
// add relationship from drawing to the chart
for i, dr := range d.wb.drawings {
if dr == d.x {
fn := gooxml.RelativeFilename(gooxml.DocTypeSpreadsheet, gooxml.ChartType, len(d.wb.charts))
rel := d.wb.drawingRels[i].AddRelationship(fn, gooxml.ChartType)
chartID = rel.ID()
break
}
}
// maybe use a one cell anchor?
tca := sd.NewCT_TwoCellAnchor()
d.x.EG_Anchor = []*sd.EG_Anchor{&sd.EG_Anchor{TwoCellAnchor: tca}}
tca.Choice = &sd.EG_ObjectChoicesChoice{}
tca.Choice.GraphicFrame = sd.NewCT_GraphicalObjectFrame()
tca.Choice.GraphicFrame.Graphic = dml.NewGraphic()
tca.Choice.GraphicFrame.Graphic.GraphicData.UriAttr = "http://schemas.openxmlformats.org/drawingml/2006/chart"
c := c.NewChart()
c.IdAttr = chartID
tca.Choice.GraphicFrame.Graphic.GraphicData.Any = []gooxml.Any{c}
return Chart{chart}
}

36
spreadsheet/linechart.go Normal file
View File

@ -0,0 +1,36 @@
// 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 spreadsheet
import (
"baliance.com/gooxml/color"
"baliance.com/gooxml/drawing"
"baliance.com/gooxml/measurement"
crt "baliance.com/gooxml/schema/schemas.openxmlformats.org/drawingml/2006/chart"
)
type LineChart struct {
x *crt.CT_LineChart
}
// X returns the inner wrapped XML type.
func (c LineChart) X() *crt.CT_LineChart {
return c.x
}
func (c LineChart) AddSeries() LineChartSeries {
ser := crt.NewCT_LineSer()
c.x.Ser = append(c.x.Ser, ser)
ser.Idx.ValAttr = uint32(len(c.x.Ser))
ser.Order.ValAttr = uint32(len(c.x.Ser))
ls := LineChartSeries{ser}
ls.Properties().LineProperties().SetWidth(2 * measurement.Point)
ls.Properties().LineProperties().SetSolidFill(color.Green)
ls.Properties().LineProperties().SetJoin(drawing.LineJoinRound)
return ls
}

View File

@ -0,0 +1,81 @@
// 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 spreadsheet
import (
"baliance.com/gooxml/chart"
"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 LineChartSeries struct {
x *crt.CT_LineSer
}
// X returns the inner wrapped XML type.
func (c LineChartSeries) X() *crt.CT_LineSer {
return c.x
}
// Index returns the index of the series
func (c LineChartSeries) Index() uint32 {
return c.x.Idx.ValAttr
}
// SetIndex sets the index of the series
func (c LineChartSeries) SetIndex(idx uint32) {
c.x.Idx.ValAttr = idx
}
// Order returns the order of the series
func (c LineChartSeries) Order() uint32 {
return c.x.Order.ValAttr
}
// SetOrder sets the order of the series
func (c LineChartSeries) SetOrder(idx uint32) {
c.x.Order.ValAttr = idx
}
// SetText sets the series text
func (c LineChartSeries) SetText(s string) {
c.x.Tx = crt.NewCT_SerTx()
c.x.Tx.Choice.V = &s
}
// Properties returns the line chart series shape properties.
func (c LineChartSeries) Properties() drawing.ShapeProperties {
if c.x.SpPr == nil {
c.x.SpPr = dml.NewCT_ShapeProperties()
}
return drawing.MakeShapeProperties(c.x.SpPr)
}
// Marker returns the marker properties.
func (c LineChartSeries) Marker() chart.Marker {
if c.x.Marker == nil {
c.x.Marker = crt.NewCT_Marker()
}
return chart.MakeMarker(c.x.Marker)
}
// Labels returns the data label properties.
func (c LineChartSeries) Labels() chart.DataLabels {
if c.x.DLbls == nil {
c.x.DLbls = crt.NewCT_DLbls()
}
return chart.MakeDataLabels(c.x.DLbls)
}
func (c LineChartSeries) Axis() chart.AxisDataSource {
if c.x.Cat == nil {
c.x.Cat = crt.NewCT_AxDataSource()
}
return chart.MakeAxisDataSource(c.x.Cat)
}

View File

@ -295,3 +295,12 @@ func (wb *Workbook) onNewRelationship(decMap *zippkg.DecodeMap, target, typ stri
}
return nil
}
func (wb *Workbook) AddDrawing() Drawing {
drawing := sd.NewWsDr()
wb.drawings = append(wb.drawings, drawing)
fn := gooxml.AbsoluteFilename(gooxml.DocTypeSpreadsheet, gooxml.DrawingType, len(wb.drawings))
wb.ContentTypes.AddOverride(fn, gooxml.DrawingType)
wb.drawingRels = append(wb.drawingRels, common.NewRelationships())
return Drawing{wb, drawing}
}