mirror of
https://github.com/unidoc/unioffice.git
synced 2025-04-27 13:48:54 +08:00
spreadsheet: add a multi chart example
This commit is contained in:
parent
b8bfe8129e
commit
5ee1459321
@ -28,9 +28,9 @@ func main() {
|
||||
|
||||
// Charts need to reside in a drawing
|
||||
dwng := ss.AddDrawing()
|
||||
chart := dwng.AddChart()
|
||||
chart, anc := dwng.AddChart()
|
||||
// make it a bit wider than the default
|
||||
dwng.BottomRight().SetCol(15)
|
||||
anc.BottomRight().SetCol(15)
|
||||
|
||||
lc := chart.AddBarChart()
|
||||
priceSeries := lc.AddSeries()
|
||||
|
@ -28,9 +28,9 @@ func main() {
|
||||
|
||||
// Charts need to reside in a drawing
|
||||
dwng := ss.AddDrawing()
|
||||
chart := dwng.AddChart()
|
||||
chart, anc := dwng.AddChart()
|
||||
// make it a bit wider than the default
|
||||
dwng.BottomRight().SetCol(15)
|
||||
anc.BottomRight().SetCol(15)
|
||||
|
||||
lc := chart.AddLineChart()
|
||||
priceSeries := lc.AddSeries()
|
||||
@ -57,9 +57,9 @@ func main() {
|
||||
va.SetCrosses(ca)
|
||||
|
||||
// add a title and legend
|
||||
// title := chart.AddTitle()
|
||||
// title.SetText("Items Sold")
|
||||
// chart.AddLegend()
|
||||
title := chart.AddTitle()
|
||||
title.SetText("Items Sold")
|
||||
chart.AddLegend()
|
||||
|
||||
// and finally add the chart to the sheet
|
||||
sheet.SetDrawing(dwng)
|
||||
|
101
_examples/spreadsheet/multiple-charts/main.go
Normal file
101
_examples/spreadsheet/multiple-charts/main.go
Normal file
@ -0,0 +1,101 @@
|
||||
// Copyright 2017 Baliance. All rights reserved.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"baliance.com/gooxml/chart"
|
||||
"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()
|
||||
chrt1, anc1 := dwng.AddChart()
|
||||
chrt2, anc2 := dwng.AddChart()
|
||||
addBarChart(chrt1)
|
||||
addLineChart(chrt2)
|
||||
anc1.SetWidth(9)
|
||||
anc1.MoveTo(5, 1)
|
||||
anc2.MoveTo(1, 23)
|
||||
|
||||
// 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("multiple-chart.xlsx")
|
||||
}
|
||||
|
||||
func addBarChart(chrt chart.Chart) {
|
||||
chrt.AddTitle().SetText("Bar Chart")
|
||||
lc := chrt.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 := chrt.AddCategoryAxis()
|
||||
va := chrt.AddValueAxis()
|
||||
lc.AddAxis(ca)
|
||||
lc.AddAxis(va)
|
||||
|
||||
ca.SetCrosses(va)
|
||||
va.SetCrosses(ca)
|
||||
}
|
||||
|
||||
func addLineChart(chrt chart.Chart) {
|
||||
chrt.AddTitle().SetText("Line Chart")
|
||||
lc := chrt.AddLineChart()
|
||||
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 := chrt.AddCategoryAxis()
|
||||
va := chrt.AddValueAxis()
|
||||
lc.AddAxis(ca)
|
||||
lc.AddAxis(va)
|
||||
|
||||
ca.SetCrosses(va)
|
||||
va.SetCrosses(ca)
|
||||
}
|
20
spreadsheet/anchor.go
Normal file
20
spreadsheet/anchor.go
Normal file
@ -0,0 +1,20 @@
|
||||
// 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
|
||||
|
||||
// Anchor is the interface implemented by anchors. It's modeled after the most
|
||||
// common anchor (Two cell variant with a from/to position), but will also be
|
||||
// used for one-cell anchors. In that case the only non-noop methods are
|
||||
// TopLeft() and MoveTo().
|
||||
type Anchor interface {
|
||||
BottomRight() CellMarker
|
||||
TopLeft() CellMarker
|
||||
MoveTo(col, row int32)
|
||||
SetWidth(w int32)
|
||||
SetHeight(h int32)
|
||||
}
|
@ -28,26 +28,12 @@ func (d Drawing) X() *sd.WsDr {
|
||||
}
|
||||
|
||||
func (d Drawing) InitializeDefaults() {
|
||||
d.x.TwoCellAnchor = sd.NewCT_TwoCellAnchor()
|
||||
d.x.TwoCellAnchor.EditAsAttr = sd.ST_EditAsOneCell
|
||||
|
||||
// provide a default size so its visible, if from/to are both 0,0 then the
|
||||
// chart won't show up.
|
||||
d.x.TwoCellAnchor.From.Col = 5
|
||||
d.x.TwoCellAnchor.From.Row = 0
|
||||
// Mac Excel requires the offsets be present
|
||||
d.x.TwoCellAnchor.From.ColOff.ST_CoordinateUnqualified = gooxml.Int64(0)
|
||||
d.x.TwoCellAnchor.From.RowOff.ST_CoordinateUnqualified = gooxml.Int64(0)
|
||||
d.x.TwoCellAnchor.To.Col = 10
|
||||
d.x.TwoCellAnchor.To.Row = 20
|
||||
d.x.TwoCellAnchor.To.ColOff.ST_CoordinateUnqualified = gooxml.Int64(0)
|
||||
d.x.TwoCellAnchor.To.RowOff.ST_CoordinateUnqualified = gooxml.Int64(0)
|
||||
}
|
||||
|
||||
func (d Drawing) AddChart() chart.Chart {
|
||||
func (d Drawing) AddChart() (chart.Chart, Anchor) {
|
||||
chartSpace := crt.NewChartSpace()
|
||||
d.wb.charts = append(d.wb.charts, chartSpace)
|
||||
chrt := chart.MakeChart(chartSpace)
|
||||
|
||||
fn := gooxml.AbsoluteFilename(gooxml.DocTypeSpreadsheet, gooxml.ChartContentType, len(d.wb.charts))
|
||||
d.wb.ContentTypes.AddOverride(fn, gooxml.ChartContentType)
|
||||
@ -63,60 +49,42 @@ func (d Drawing) AddChart() chart.Chart {
|
||||
}
|
||||
}
|
||||
|
||||
// maybe use a one cell anchor?
|
||||
if d.x.TwoCellAnchor == nil {
|
||||
d.InitializeDefaults()
|
||||
}
|
||||
d.x.TwoCellAnchor.Choice = &sd.EG_ObjectChoicesChoice{}
|
||||
d.x.TwoCellAnchor.Choice.GraphicFrame = sd.NewCT_GraphicalObjectFrame()
|
||||
tca := sd.NewCT_TwoCellAnchor()
|
||||
|
||||
d.x.EG_Anchor = append(d.x.EG_Anchor, &sd.EG_Anchor{TwoCellAnchor: tca})
|
||||
tca.EditAsAttr = sd.ST_EditAsOneCell
|
||||
|
||||
// provide a default size so its visible, if from/to are both 0,0 then the
|
||||
// chart won't show up.
|
||||
tca.From.Col = 5
|
||||
tca.From.Row = 0
|
||||
// Mac Excel requires the offsets be present
|
||||
tca.From.ColOff.ST_CoordinateUnqualified = gooxml.Int64(0)
|
||||
tca.From.RowOff.ST_CoordinateUnqualified = gooxml.Int64(0)
|
||||
tca.To.Col = 10
|
||||
tca.To.Row = 20
|
||||
tca.To.ColOff.ST_CoordinateUnqualified = gooxml.Int64(0)
|
||||
tca.To.RowOff.ST_CoordinateUnqualified = gooxml.Int64(0)
|
||||
|
||||
tca.Choice = &sd.EG_ObjectChoicesChoice{}
|
||||
tca.Choice.GraphicFrame = sd.NewCT_GraphicalObjectFrame()
|
||||
|
||||
// required by Mac Excel
|
||||
d.x.TwoCellAnchor.Choice.GraphicFrame.NvGraphicFramePr = sd.NewCT_GraphicalObjectFrameNonVisual()
|
||||
d.x.TwoCellAnchor.Choice.GraphicFrame.NvGraphicFramePr.CNvPr.IdAttr = 2
|
||||
d.x.TwoCellAnchor.Choice.GraphicFrame.NvGraphicFramePr.CNvPr.NameAttr = "Chart"
|
||||
tca.Choice.GraphicFrame.NvGraphicFramePr = sd.NewCT_GraphicalObjectFrameNonVisual()
|
||||
tca.Choice.GraphicFrame.NvGraphicFramePr.CNvPr.IdAttr = 2
|
||||
tca.Choice.GraphicFrame.NvGraphicFramePr.CNvPr.NameAttr = "Chart"
|
||||
|
||||
d.x.TwoCellAnchor.Choice.GraphicFrame.Graphic = dml.NewGraphic()
|
||||
d.x.TwoCellAnchor.Choice.GraphicFrame.Graphic.GraphicData.UriAttr = "http://schemas.openxmlformats.org/drawingml/2006/chart"
|
||||
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
|
||||
d.x.TwoCellAnchor.Choice.GraphicFrame.Graphic.GraphicData.Any = []gooxml.Any{c}
|
||||
tca.Choice.GraphicFrame.Graphic.GraphicData.Any = []gooxml.Any{c}
|
||||
|
||||
//chart.Chart.PlotVisOnly = crt.NewCT_Boolean()
|
||||
//chart.Chart.PlotVisOnly.ValAttr = gooxml.Bool(true)
|
||||
|
||||
chrt := chart.MakeChart(chartSpace)
|
||||
chrt.Properties().SetSolidFill(color.White)
|
||||
chrt.SetDisplayBlanksAs(crt.ST_DispBlanksAsGap)
|
||||
return chrt
|
||||
}
|
||||
|
||||
// TopLeft allows manipulating the top left position of the drawing.
|
||||
func (d Drawing) TopLeft() CellMarker {
|
||||
if d.x.TwoCellAnchor != nil {
|
||||
if d.x.TwoCellAnchor.From == nil {
|
||||
d.x.TwoCellAnchor.From = sd.NewCT_Marker()
|
||||
}
|
||||
return CellMarker{d.x.TwoCellAnchor.From}
|
||||
}
|
||||
if d.x.OneCellAnchor != nil {
|
||||
if d.x.OneCellAnchor.From == nil {
|
||||
d.x.OneCellAnchor.From = sd.NewCT_Marker()
|
||||
}
|
||||
return CellMarker{d.x.OneCellAnchor.From}
|
||||
}
|
||||
|
||||
// this will crash if used...
|
||||
return CellMarker{}
|
||||
}
|
||||
|
||||
// BottomRight allows manipulating the bottom right position of the drawing.
|
||||
func (d Drawing) BottomRight() CellMarker {
|
||||
if d.x.TwoCellAnchor != nil {
|
||||
if d.x.TwoCellAnchor.To == nil {
|
||||
d.x.TwoCellAnchor.To = sd.NewCT_Marker()
|
||||
}
|
||||
return CellMarker{d.x.TwoCellAnchor.To}
|
||||
}
|
||||
|
||||
// this will crash if used...
|
||||
return CellMarker{}
|
||||
return chrt, TwoCellAnchor{tca}
|
||||
}
|
||||
|
61
spreadsheet/twocellanchor.go
Normal file
61
spreadsheet/twocellanchor.go
Normal 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 spreadsheet
|
||||
|
||||
import (
|
||||
sd "baliance.com/gooxml/schema/schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"
|
||||
)
|
||||
|
||||
// TwoCellAnchor is an anchor that is attached from a top-left to a bottom-right
|
||||
// cell (from & to cells).
|
||||
type TwoCellAnchor struct {
|
||||
x *sd.CT_TwoCellAnchor
|
||||
}
|
||||
|
||||
// BottomRight returns the CellMaker for the bottom right corner of the anchor.
|
||||
func (t TwoCellAnchor) BottomRight() CellMarker {
|
||||
if t.x.To == nil {
|
||||
t.x.To = sd.NewCT_Marker()
|
||||
}
|
||||
return CellMarker{t.x.To}
|
||||
}
|
||||
|
||||
// TopLeft returns the CellMaker for the top left corner of the anchor.
|
||||
func (t TwoCellAnchor) TopLeft() CellMarker {
|
||||
if t.x.From == nil {
|
||||
t.x.From = sd.NewCT_Marker()
|
||||
}
|
||||
return CellMarker{t.x.From}
|
||||
}
|
||||
|
||||
// MoveTo repositions the anchor without changing the objects size.
|
||||
func (t TwoCellAnchor) MoveTo(col, row int32) {
|
||||
tl := t.TopLeft()
|
||||
br := t.BottomRight()
|
||||
w := br.Col() - tl.Col()
|
||||
h := br.Row() - tl.Row()
|
||||
|
||||
tl.SetCol(col)
|
||||
tl.SetRow(row)
|
||||
t.SetWidth(w)
|
||||
t.SetHeight(h)
|
||||
}
|
||||
|
||||
// SetWidth sets the height the anchored objet by moving the right hand side.
|
||||
func (t TwoCellAnchor) SetWidth(w int32) {
|
||||
tl := t.TopLeft()
|
||||
br := t.BottomRight()
|
||||
br.SetCol(tl.Col() + w)
|
||||
}
|
||||
|
||||
// SetHeight sets the height the anchored objet by moving the bottom.
|
||||
func (t TwoCellAnchor) SetHeight(h int32) {
|
||||
tl := t.TopLeft()
|
||||
br := t.BottomRight()
|
||||
br.SetRow(tl.Row() + h)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user