forked from p30928647/excelize
This closes #1358, made a refactor with breaking changes, see details:
This made a refactor with breaking changes: Motivation and Context When I decided to add set horizontal centered support for this library to resolve #1358, the reason I made this huge breaking change was: - There are too many exported types for set sheet view, properties, and format properties, although a function using the functional options pattern can be optimized by returning an anonymous function, these types or property set or get function has no binding categorization, so I change these functions like `SetAppProps` to accept a pointer of options structure. - Users can not easily find out which properties should be in the `SetSheetPrOptions` or `SetSheetFormatPr` categories - Nested properties cannot proceed modify easily Introduce 5 new export data types: `HeaderFooterOptions`, `PageLayoutMarginsOptions`, `PageLayoutOptions`, `SheetPropsOptions`, and `ViewOptions` Rename 4 exported data types: - Rename `PivotTableOption` to `PivotTableOptions` - Rename `FormatHeaderFooter` to `HeaderFooterOptions` - Rename `FormatSheetProtection` to `SheetProtectionOptions` - Rename `SparklineOption` to `SparklineOptions` Remove 54 exported types: `AutoPageBreaks`, `BaseColWidth`, `BlackAndWhite`, `CodeName`, `CustomHeight`, `Date1904`, `DefaultColWidth`, `DefaultGridColor`, `DefaultRowHeight`, `EnableFormatConditionsCalculation`, `FilterPrivacy`, `FirstPageNumber`, `FitToHeight`, `FitToPage`, `FitToWidth`, `OutlineSummaryBelow`, `PageLayoutOption`, `PageLayoutOptionPtr`, `PageLayoutOrientation`, `PageLayoutPaperSize`, `PageLayoutScale`, `PageMarginBottom`, `PageMarginFooter`, `PageMarginHeader`, `PageMarginLeft`, `PageMarginRight`, `PageMarginsOptions`, `PageMarginsOptionsPtr`, `PageMarginTop`, `Published`, `RightToLeft`, `SheetFormatPrOptions`, `SheetFormatPrOptionsPtr`, `SheetPrOption`, `SheetPrOptionPtr`, `SheetViewOption`, `SheetViewOptionPtr`, `ShowFormulas`, `ShowGridLines`, `ShowRowColHeaders`, `ShowRuler`, `ShowZeros`, `TabColorIndexed`, `TabColorRGB`, `TabColorTheme`, `TabColorTint`, `ThickBottom`, `ThickTop`, `TopLeftCell`, `View`, `WorkbookPrOption`, `WorkbookPrOptionPtr`, `ZeroHeight` and `ZoomScale` Remove 2 exported constants: `OrientationPortrait` and `OrientationLandscape` Change 8 functions: - Change the `func (f *File) SetPageLayout(sheet string, opts ...PageLayoutOption) error` to `func (f *File) SetPageLayout(sheet string, opts *PageLayoutOptions) error` - Change the `func (f *File) GetPageLayout(sheet string, opts ...PageLayoutOptionPtr) error` to `func (f *File) GetPageLayout(sheet string) (PageLayoutOptions, error)` - Change the `func (f *File) SetPageMargins(sheet string, opts ...PageMarginsOptions) error` to `func (f *File) SetPageMargins(sheet string, opts *PageLayoutMarginsOptions) error` - Change the `func (f *File) GetPageMargins(sheet string, opts ...PageMarginsOptionsPtr) error` to `func (f *File) GetPageMargins(sheet string) (PageLayoutMarginsOptions, error)` - Change the `func (f *File) SetSheetViewOptions(sheet string, viewIndex int, opts ...SheetViewOption) error` to `func (f *File) SetSheetView(sheet string, viewIndex int, opts *ViewOptions) error` - Change the `func (f *File) GetSheetViewOptions(sheet string, viewIndex int, opts ...SheetViewOptionPtr) error` to `func (f *File) GetSheetView(sheet string, viewIndex int) (ViewOptions, error)` - Change the `func (f *File) SetWorkbookPrOptions(opts ...WorkbookPrOption) error` to `func (f *File) SetWorkbookProps(opts *WorkbookPropsOptions) error` - Change the `func (f *File) GetWorkbookPrOptions(opts ...WorkbookPrOptionPtr) error` to `func (f *File) GetWorkbookProps() (WorkbookPropsOptions, error)` Introduce new function to instead of existing functions: - New function `func (f *File) SetSheetProps(sheet string, opts *SheetPropsOptions) error` instead of `func (f *File) SetSheetPrOptions(sheet string, opts ...SheetPrOption) error` and `func (f *File) SetSheetFormatPr(sheet string, opts ...SheetFormatPrOption
This commit is contained in:
parent
efcf599dfe
commit
53a495563a
64
chart.go
64
chart.go
|
@ -469,30 +469,30 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
// parseFormatChartSet provides a function to parse the format settings of the
|
||||
// parseChartOptions provides a function to parse the format settings of the
|
||||
// chart with default value.
|
||||
func parseFormatChartSet(formatSet string) (*formatChart, error) {
|
||||
format := formatChart{
|
||||
Dimension: formatChartDimension{
|
||||
func parseChartOptions(opts string) (*chartOptions, error) {
|
||||
options := chartOptions{
|
||||
Dimension: chartDimensionOptions{
|
||||
Width: 480,
|
||||
Height: 290,
|
||||
},
|
||||
Format: formatPicture{
|
||||
Format: pictureOptions{
|
||||
FPrintsWithSheet: true,
|
||||
XScale: 1,
|
||||
YScale: 1,
|
||||
},
|
||||
Legend: formatChartLegend{
|
||||
Legend: chartLegendOptions{
|
||||
Position: "bottom",
|
||||
},
|
||||
Title: formatChartTitle{
|
||||
Title: chartTitleOptions{
|
||||
Name: " ",
|
||||
},
|
||||
VaryColors: true,
|
||||
ShowBlanksAs: "gap",
|
||||
}
|
||||
err := json.Unmarshal([]byte(formatSet), &format)
|
||||
return &format, err
|
||||
err := json.Unmarshal([]byte(opts), &options)
|
||||
return &options, err
|
||||
}
|
||||
|
||||
// AddChart provides the method to add chart in a sheet by given chart format
|
||||
|
@ -881,13 +881,13 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) {
|
|||
// fmt.Println(err)
|
||||
// }
|
||||
// }
|
||||
func (f *File) AddChart(sheet, cell, format string, combo ...string) error {
|
||||
func (f *File) AddChart(sheet, cell, opts string, combo ...string) error {
|
||||
// Read sheet data.
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
formatSet, comboCharts, err := f.getFormatChart(format, combo)
|
||||
options, comboCharts, err := f.getChartOptions(opts, combo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -898,11 +898,11 @@ func (f *File) AddChart(sheet, cell, format string, combo ...string) error {
|
|||
drawingID, drawingXML = f.prepareDrawing(ws, drawingID, sheet, drawingXML)
|
||||
drawingRels := "xl/drawings/_rels/drawing" + strconv.Itoa(drawingID) + ".xml.rels"
|
||||
drawingRID := f.addRels(drawingRels, SourceRelationshipChart, "../charts/chart"+strconv.Itoa(chartID)+".xml", "")
|
||||
err = f.addDrawingChart(sheet, drawingXML, cell, formatSet.Dimension.Width, formatSet.Dimension.Height, drawingRID, &formatSet.Format)
|
||||
err = f.addDrawingChart(sheet, drawingXML, cell, options.Dimension.Width, options.Dimension.Height, drawingRID, &options.Format)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.addChart(formatSet, comboCharts)
|
||||
f.addChart(options, comboCharts)
|
||||
f.addContentTypePart(chartID, "chart")
|
||||
f.addContentTypePart(drawingID, "drawings")
|
||||
f.addSheetNameSpace(sheet, SourceRelationship)
|
||||
|
@ -913,12 +913,12 @@ func (f *File) AddChart(sheet, cell, format string, combo ...string) error {
|
|||
// format set (such as offset, scale, aspect ratio setting and print settings)
|
||||
// and properties set. In Excel a chartsheet is a worksheet that only contains
|
||||
// a chart.
|
||||
func (f *File) AddChartSheet(sheet, format string, combo ...string) error {
|
||||
func (f *File) AddChartSheet(sheet, opts string, combo ...string) error {
|
||||
// Check if the worksheet already exists
|
||||
if f.GetSheetIndex(sheet) != -1 {
|
||||
return ErrExistsWorksheet
|
||||
}
|
||||
formatSet, comboCharts, err := f.getFormatChart(format, combo)
|
||||
options, comboCharts, err := f.getChartOptions(opts, combo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -945,8 +945,8 @@ func (f *File) AddChartSheet(sheet, format string, combo ...string) error {
|
|||
f.prepareChartSheetDrawing(&cs, drawingID, sheet)
|
||||
drawingRels := "xl/drawings/_rels/drawing" + strconv.Itoa(drawingID) + ".xml.rels"
|
||||
drawingRID := f.addRels(drawingRels, SourceRelationshipChart, "../charts/chart"+strconv.Itoa(chartID)+".xml", "")
|
||||
f.addSheetDrawingChart(drawingXML, drawingRID, &formatSet.Format)
|
||||
f.addChart(formatSet, comboCharts)
|
||||
f.addSheetDrawingChart(drawingXML, drawingRID, &options.Format)
|
||||
f.addChart(options, comboCharts)
|
||||
f.addContentTypePart(chartID, "chart")
|
||||
f.addContentTypePart(sheetID, "chartsheet")
|
||||
f.addContentTypePart(drawingID, "drawings")
|
||||
|
@ -960,45 +960,45 @@ func (f *File) AddChartSheet(sheet, format string, combo ...string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// getFormatChart provides a function to check format set of the chart and
|
||||
// getChartOptions provides a function to check format set of the chart and
|
||||
// create chart format.
|
||||
func (f *File) getFormatChart(format string, combo []string) (*formatChart, []*formatChart, error) {
|
||||
var comboCharts []*formatChart
|
||||
formatSet, err := parseFormatChartSet(format)
|
||||
func (f *File) getChartOptions(opts string, combo []string) (*chartOptions, []*chartOptions, error) {
|
||||
var comboCharts []*chartOptions
|
||||
options, err := parseChartOptions(opts)
|
||||
if err != nil {
|
||||
return formatSet, comboCharts, err
|
||||
return options, comboCharts, err
|
||||
}
|
||||
for _, comboFormat := range combo {
|
||||
comboChart, err := parseFormatChartSet(comboFormat)
|
||||
comboChart, err := parseChartOptions(comboFormat)
|
||||
if err != nil {
|
||||
return formatSet, comboCharts, err
|
||||
return options, comboCharts, err
|
||||
}
|
||||
if _, ok := chartValAxNumFmtFormatCode[comboChart.Type]; !ok {
|
||||
return formatSet, comboCharts, newUnsupportedChartType(comboChart.Type)
|
||||
return options, comboCharts, newUnsupportedChartType(comboChart.Type)
|
||||
}
|
||||
comboCharts = append(comboCharts, comboChart)
|
||||
}
|
||||
if _, ok := chartValAxNumFmtFormatCode[formatSet.Type]; !ok {
|
||||
return formatSet, comboCharts, newUnsupportedChartType(formatSet.Type)
|
||||
if _, ok := chartValAxNumFmtFormatCode[options.Type]; !ok {
|
||||
return options, comboCharts, newUnsupportedChartType(options.Type)
|
||||
}
|
||||
return formatSet, comboCharts, err
|
||||
return options, comboCharts, err
|
||||
}
|
||||
|
||||
// DeleteChart provides a function to delete chart in spreadsheet by given
|
||||
// worksheet name and cell reference.
|
||||
func (f *File) DeleteChart(sheet, cell string) (err error) {
|
||||
func (f *File) DeleteChart(sheet, cell string) error {
|
||||
col, row, err := CellNameToCoordinates(cell)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
col--
|
||||
row--
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if ws.Drawing == nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
drawingXML := strings.ReplaceAll(f.getSheetRelationshipsTargetByID(sheet, ws.Drawing.RID), "..", "xl")
|
||||
return f.deleteDrawing(col, row, drawingXML, "Chart")
|
||||
|
|
41
comment.go
41
comment.go
|
@ -23,15 +23,15 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// parseFormatCommentsSet provides a function to parse the format settings of
|
||||
// parseCommentOptions provides a function to parse the format settings of
|
||||
// the comment with default value.
|
||||
func parseFormatCommentsSet(formatSet string) (*formatComment, error) {
|
||||
format := formatComment{
|
||||
func parseCommentOptions(opts string) (*commentOptions, error) {
|
||||
options := commentOptions{
|
||||
Author: "Author:",
|
||||
Text: " ",
|
||||
}
|
||||
err := json.Unmarshal([]byte(formatSet), &format)
|
||||
return &format, err
|
||||
err := json.Unmarshal([]byte(opts), &options)
|
||||
return &options, err
|
||||
}
|
||||
|
||||
// GetComments retrieves all comments and returns a map of worksheet name to
|
||||
|
@ -93,8 +93,8 @@ func (f *File) getSheetComments(sheetFile string) string {
|
|||
// comment in Sheet1!$A$30:
|
||||
//
|
||||
// err := f.AddComment("Sheet1", "A30", `{"author":"Excelize: ","text":"This is a comment."}`)
|
||||
func (f *File) AddComment(sheet, cell, format string) error {
|
||||
formatSet, err := parseFormatCommentsSet(format)
|
||||
func (f *File) AddComment(sheet, cell, opts string) error {
|
||||
options, err := parseCommentOptions(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -123,19 +123,19 @@ func (f *File) AddComment(sheet, cell, format string) error {
|
|||
}
|
||||
commentsXML := "xl/comments" + strconv.Itoa(commentID) + ".xml"
|
||||
var colCount int
|
||||
for i, l := range strings.Split(formatSet.Text, "\n") {
|
||||
for i, l := range strings.Split(options.Text, "\n") {
|
||||
if ll := len(l); ll > colCount {
|
||||
if i == 0 {
|
||||
ll += len(formatSet.Author)
|
||||
ll += len(options.Author)
|
||||
}
|
||||
colCount = ll
|
||||
}
|
||||
}
|
||||
err = f.addDrawingVML(commentID, drawingVML, cell, strings.Count(formatSet.Text, "\n")+1, colCount)
|
||||
err = f.addDrawingVML(commentID, drawingVML, cell, strings.Count(options.Text, "\n")+1, colCount)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.addComment(commentsXML, cell, formatSet)
|
||||
f.addComment(commentsXML, cell, options)
|
||||
f.addContentTypePart(commentID, "comments")
|
||||
return err
|
||||
}
|
||||
|
@ -144,11 +144,12 @@ func (f *File) AddComment(sheet, cell, format string) error {
|
|||
// worksheet name. For example, delete the comment in Sheet1!$A$30:
|
||||
//
|
||||
// err := f.DeleteComment("Sheet1", "A30")
|
||||
func (f *File) DeleteComment(sheet, cell string) (err error) {
|
||||
func (f *File) DeleteComment(sheet, cell string) error {
|
||||
var err error
|
||||
sheetXMLPath, ok := f.getSheetXMLPath(sheet)
|
||||
if !ok {
|
||||
err = newNoExistSheetError(sheet)
|
||||
return
|
||||
return err
|
||||
}
|
||||
commentsXML := f.getSheetComments(filepath.Base(sheetXMLPath))
|
||||
if !strings.HasPrefix(commentsXML, "/") {
|
||||
|
@ -173,7 +174,7 @@ func (f *File) DeleteComment(sheet, cell string) (err error) {
|
|||
}
|
||||
f.Comments[commentsXML] = comments
|
||||
}
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
// addDrawingVML provides a function to create comment as
|
||||
|
@ -279,9 +280,9 @@ func (f *File) addDrawingVML(commentID int, drawingVML, cell string, lineCount,
|
|||
|
||||
// addComment provides a function to create chart as xl/comments%d.xml by
|
||||
// given cell and format sets.
|
||||
func (f *File) addComment(commentsXML, cell string, formatSet *formatComment) {
|
||||
a := formatSet.Author
|
||||
t := formatSet.Text
|
||||
func (f *File) addComment(commentsXML, cell string, opts *commentOptions) {
|
||||
a := opts.Author
|
||||
t := opts.Text
|
||||
if len(a) > MaxFieldLength {
|
||||
a = a[:MaxFieldLength]
|
||||
}
|
||||
|
@ -291,10 +292,10 @@ func (f *File) addComment(commentsXML, cell string, formatSet *formatComment) {
|
|||
comments := f.commentsReader(commentsXML)
|
||||
authorID := 0
|
||||
if comments == nil {
|
||||
comments = &xlsxComments{Authors: xlsxAuthor{Author: []string{formatSet.Author}}}
|
||||
comments = &xlsxComments{Authors: xlsxAuthor{Author: []string{opts.Author}}}
|
||||
}
|
||||
if inStrSlice(comments.Authors.Author, formatSet.Author, true) == -1 {
|
||||
comments.Authors.Author = append(comments.Authors.Author, formatSet.Author)
|
||||
if inStrSlice(comments.Authors.Author, opts.Author, true) == -1 {
|
||||
comments.Authors.Author = append(comments.Authors.Author, opts.Author)
|
||||
authorID = len(comments.Authors.Author) - 1
|
||||
}
|
||||
defaultFont := f.GetDefaultFont()
|
||||
|
|
32
docProps.go
32
docProps.go
|
@ -64,19 +64,20 @@ import (
|
|||
// HyperlinksChanged: true,
|
||||
// AppVersion: "16.0000",
|
||||
// })
|
||||
func (f *File) SetAppProps(appProperties *AppProperties) (err error) {
|
||||
func (f *File) SetAppProps(appProperties *AppProperties) error {
|
||||
var (
|
||||
app *xlsxProperties
|
||||
fields []string
|
||||
output []byte
|
||||
immutable, mutable reflect.Value
|
||||
err error
|
||||
field string
|
||||
fields []string
|
||||
immutable, mutable reflect.Value
|
||||
output []byte
|
||||
)
|
||||
app = new(xlsxProperties)
|
||||
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathDocPropsApp)))).
|
||||
Decode(app); err != nil && err != io.EOF {
|
||||
err = newDecodeXMLError(err)
|
||||
return
|
||||
return err
|
||||
}
|
||||
fields = []string{"Application", "ScaleCrop", "DocSecurity", "Company", "LinksUpToDate", "HyperlinksChanged", "AppVersion"}
|
||||
immutable, mutable = reflect.ValueOf(*appProperties), reflect.ValueOf(app).Elem()
|
||||
|
@ -94,7 +95,7 @@ func (f *File) SetAppProps(appProperties *AppProperties) (err error) {
|
|||
app.Vt = NameSpaceDocumentPropertiesVariantTypes.Value
|
||||
output, err = xml.Marshal(app)
|
||||
f.saveFileList(defaultXMLPathDocPropsApp, output)
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
// GetAppProps provides a function to get document application properties.
|
||||
|
@ -167,23 +168,24 @@ func (f *File) GetAppProps() (ret *AppProperties, err error) {
|
|||
// Language: "en-US",
|
||||
// Version: "1.0.0",
|
||||
// })
|
||||
func (f *File) SetDocProps(docProperties *DocProperties) (err error) {
|
||||
func (f *File) SetDocProps(docProperties *DocProperties) error {
|
||||
var (
|
||||
core *decodeCoreProperties
|
||||
newProps *xlsxCoreProperties
|
||||
fields []string
|
||||
output []byte
|
||||
immutable, mutable reflect.Value
|
||||
err error
|
||||
field, val string
|
||||
fields []string
|
||||
immutable, mutable reflect.Value
|
||||
newProps *xlsxCoreProperties
|
||||
output []byte
|
||||
)
|
||||
|
||||
core = new(decodeCoreProperties)
|
||||
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathDocPropsCore)))).
|
||||
Decode(core); err != nil && err != io.EOF {
|
||||
err = newDecodeXMLError(err)
|
||||
return
|
||||
return err
|
||||
}
|
||||
newProps, err = &xlsxCoreProperties{
|
||||
newProps = &xlsxCoreProperties{
|
||||
Dc: NameSpaceDublinCore,
|
||||
Dcterms: NameSpaceDublinCoreTerms,
|
||||
Dcmitype: NameSpaceDublinCoreMetadataInitiative,
|
||||
|
@ -200,7 +202,7 @@ func (f *File) SetDocProps(docProperties *DocProperties) (err error) {
|
|||
ContentStatus: core.ContentStatus,
|
||||
Category: core.Category,
|
||||
Version: core.Version,
|
||||
}, nil
|
||||
}
|
||||
if core.Created != nil {
|
||||
newProps.Created = &xlsxDcTerms{Type: core.Created.Type, Text: core.Created.Text}
|
||||
}
|
||||
|
@ -226,7 +228,7 @@ func (f *File) SetDocProps(docProperties *DocProperties) (err error) {
|
|||
output, err = xml.Marshal(newProps)
|
||||
f.saveFileList(defaultXMLPathDocPropsCore, output)
|
||||
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
// GetDocProps provides a function to get document core properties.
|
||||
|
|
347
drawing.go
347
drawing.go
|
@ -56,7 +56,7 @@ func (f *File) prepareChartSheetDrawing(cs *xlsxChartsheet, drawingID int, sheet
|
|||
|
||||
// addChart provides a function to create chart as xl/charts/chart%d.xml by
|
||||
// given format sets.
|
||||
func (f *File) addChart(formatSet *formatChart, comboCharts []*formatChart) {
|
||||
func (f *File) addChart(opts *chartOptions, comboCharts []*chartOptions) {
|
||||
count := f.countCharts()
|
||||
xlsxChartSpace := xlsxChartSpace{
|
||||
XMLNSa: NameSpaceDrawingML.Value,
|
||||
|
@ -101,7 +101,7 @@ func (f *File) addChart(formatSet *formatChart, comboCharts []*formatChart) {
|
|||
Lang: "en-US",
|
||||
AltLang: "en-US",
|
||||
},
|
||||
T: formatSet.Title.Name,
|
||||
T: opts.Title.Name,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -124,10 +124,10 @@ func (f *File) addChart(formatSet *formatChart, comboCharts []*formatChart) {
|
|||
Overlay: &attrValBool{Val: boolPtr(false)},
|
||||
},
|
||||
View3D: &cView3D{
|
||||
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])},
|
||||
RotX: &attrValInt{Val: intPtr(chartView3DRotX[opts.Type])},
|
||||
RotY: &attrValInt{Val: intPtr(chartView3DRotY[opts.Type])},
|
||||
Perspective: &attrValInt{Val: intPtr(chartView3DPerspective[opts.Type])},
|
||||
RAngAx: &attrValInt{Val: intPtr(chartView3DRAngAx[opts.Type])},
|
||||
},
|
||||
Floor: &cThicknessSpPr{
|
||||
Thickness: &attrValInt{Val: intPtr(0)},
|
||||
|
@ -140,12 +140,12 @@ func (f *File) addChart(formatSet *formatChart, comboCharts []*formatChart) {
|
|||
},
|
||||
PlotArea: &cPlotArea{},
|
||||
Legend: &cLegend{
|
||||
LegendPos: &attrValString{Val: stringPtr(chartLegendPosition[formatSet.Legend.Position])},
|
||||
LegendPos: &attrValString{Val: stringPtr(chartLegendPosition[opts.Legend.Position])},
|
||||
Overlay: &attrValBool{Val: boolPtr(false)},
|
||||
},
|
||||
|
||||
PlotVisOnly: &attrValBool{Val: boolPtr(false)},
|
||||
DispBlanksAs: &attrValString{Val: stringPtr(formatSet.ShowBlanksAs)},
|
||||
DispBlanksAs: &attrValString{Val: stringPtr(opts.ShowBlanksAs)},
|
||||
ShowDLblsOverMax: &attrValBool{Val: boolPtr(false)},
|
||||
},
|
||||
SpPr: &cSpPr{
|
||||
|
@ -181,7 +181,7 @@ func (f *File) addChart(formatSet *formatChart, comboCharts []*formatChart) {
|
|||
},
|
||||
},
|
||||
}
|
||||
plotAreaFunc := map[string]func(*formatChart) *cPlotArea{
|
||||
plotAreaFunc := map[string]func(*chartOptions) *cPlotArea{
|
||||
Area: f.drawBaseChart,
|
||||
AreaStacked: f.drawBaseChart,
|
||||
AreaPercentStacked: f.drawBaseChart,
|
||||
|
@ -237,7 +237,7 @@ func (f *File) addChart(formatSet *formatChart, comboCharts []*formatChart) {
|
|||
Bubble: f.drawBaseChart,
|
||||
Bubble3D: f.drawBaseChart,
|
||||
}
|
||||
if formatSet.Legend.None {
|
||||
if opts.Legend.None {
|
||||
xlsxChartSpace.Chart.Legend = nil
|
||||
}
|
||||
addChart := func(c, p *cPlotArea) {
|
||||
|
@ -250,8 +250,8 @@ func (f *File) addChart(formatSet *formatChart, comboCharts []*formatChart) {
|
|||
immutable.FieldByName(mutable.Type().Field(i).Name).Set(field)
|
||||
}
|
||||
}
|
||||
addChart(xlsxChartSpace.Chart.PlotArea, plotAreaFunc[formatSet.Type](formatSet))
|
||||
order := len(formatSet.Series)
|
||||
addChart(xlsxChartSpace.Chart.PlotArea, plotAreaFunc[opts.Type](opts))
|
||||
order := len(opts.Series)
|
||||
for idx := range comboCharts {
|
||||
comboCharts[idx].order = order
|
||||
addChart(xlsxChartSpace.Chart.PlotArea, plotAreaFunc[comboCharts[idx].Type](comboCharts[idx]))
|
||||
|
@ -264,7 +264,7 @@ func (f *File) addChart(formatSet *formatChart, comboCharts []*formatChart) {
|
|||
|
||||
// drawBaseChart provides a function to draw the c:plotArea element for bar,
|
||||
// and column series charts by given format sets.
|
||||
func (f *File) drawBaseChart(formatSet *formatChart) *cPlotArea {
|
||||
func (f *File) drawBaseChart(opts *chartOptions) *cPlotArea {
|
||||
c := cCharts{
|
||||
BarDir: &attrValString{
|
||||
Val: stringPtr("col"),
|
||||
|
@ -273,11 +273,11 @@ func (f *File) drawBaseChart(formatSet *formatChart) *cPlotArea {
|
|||
Val: stringPtr("clustered"),
|
||||
},
|
||||
VaryColors: &attrValBool{
|
||||
Val: boolPtr(formatSet.VaryColors),
|
||||
Val: boolPtr(opts.VaryColors),
|
||||
},
|
||||
Ser: f.drawChartSeries(formatSet),
|
||||
Shape: f.drawChartShape(formatSet),
|
||||
DLbls: f.drawChartDLbls(formatSet),
|
||||
Ser: f.drawChartSeries(opts),
|
||||
Shape: f.drawChartShape(opts),
|
||||
DLbls: f.drawChartDLbls(opts),
|
||||
AxID: []*attrValInt{
|
||||
{Val: intPtr(754001152)},
|
||||
{Val: intPtr(753999904)},
|
||||
|
@ -285,17 +285,17 @@ func (f *File) drawBaseChart(formatSet *formatChart) *cPlotArea {
|
|||
Overlap: &attrValInt{Val: intPtr(100)},
|
||||
}
|
||||
var ok bool
|
||||
if *c.BarDir.Val, ok = plotAreaChartBarDir[formatSet.Type]; !ok {
|
||||
if *c.BarDir.Val, ok = plotAreaChartBarDir[opts.Type]; !ok {
|
||||
c.BarDir = nil
|
||||
}
|
||||
if *c.Grouping.Val, ok = plotAreaChartGrouping[formatSet.Type]; !ok {
|
||||
if *c.Grouping.Val, ok = plotAreaChartGrouping[opts.Type]; !ok {
|
||||
c.Grouping = nil
|
||||
}
|
||||
if *c.Overlap.Val, ok = plotAreaChartOverlap[formatSet.Type]; !ok {
|
||||
if *c.Overlap.Val, ok = plotAreaChartOverlap[opts.Type]; !ok {
|
||||
c.Overlap = nil
|
||||
}
|
||||
catAx := f.drawPlotAreaCatAx(formatSet)
|
||||
valAx := f.drawPlotAreaValAx(formatSet)
|
||||
catAx := f.drawPlotAreaCatAx(opts)
|
||||
valAx := f.drawPlotAreaValAx(opts)
|
||||
charts := map[string]*cPlotArea{
|
||||
"area": {
|
||||
AreaChart: &c,
|
||||
|
@ -508,23 +508,23 @@ func (f *File) drawBaseChart(formatSet *formatChart) *cPlotArea {
|
|||
ValAx: valAx,
|
||||
},
|
||||
}
|
||||
return charts[formatSet.Type]
|
||||
return charts[opts.Type]
|
||||
}
|
||||
|
||||
// drawDoughnutChart provides a function to draw the c:plotArea element for
|
||||
// doughnut chart by given format sets.
|
||||
func (f *File) drawDoughnutChart(formatSet *formatChart) *cPlotArea {
|
||||
func (f *File) drawDoughnutChart(opts *chartOptions) *cPlotArea {
|
||||
holeSize := 75
|
||||
if formatSet.HoleSize > 0 && formatSet.HoleSize <= 90 {
|
||||
holeSize = formatSet.HoleSize
|
||||
if opts.HoleSize > 0 && opts.HoleSize <= 90 {
|
||||
holeSize = opts.HoleSize
|
||||
}
|
||||
|
||||
return &cPlotArea{
|
||||
DoughnutChart: &cCharts{
|
||||
VaryColors: &attrValBool{
|
||||
Val: boolPtr(formatSet.VaryColors),
|
||||
Val: boolPtr(opts.VaryColors),
|
||||
},
|
||||
Ser: f.drawChartSeries(formatSet),
|
||||
Ser: f.drawChartSeries(opts),
|
||||
HoleSize: &attrValInt{Val: intPtr(holeSize)},
|
||||
},
|
||||
}
|
||||
|
@ -532,65 +532,65 @@ func (f *File) drawDoughnutChart(formatSet *formatChart) *cPlotArea {
|
|||
|
||||
// drawLineChart provides a function to draw the c:plotArea element for line
|
||||
// chart by given format sets.
|
||||
func (f *File) drawLineChart(formatSet *formatChart) *cPlotArea {
|
||||
func (f *File) drawLineChart(opts *chartOptions) *cPlotArea {
|
||||
return &cPlotArea{
|
||||
LineChart: &cCharts{
|
||||
Grouping: &attrValString{
|
||||
Val: stringPtr(plotAreaChartGrouping[formatSet.Type]),
|
||||
Val: stringPtr(plotAreaChartGrouping[opts.Type]),
|
||||
},
|
||||
VaryColors: &attrValBool{
|
||||
Val: boolPtr(false),
|
||||
},
|
||||
Ser: f.drawChartSeries(formatSet),
|
||||
DLbls: f.drawChartDLbls(formatSet),
|
||||
Ser: f.drawChartSeries(opts),
|
||||
DLbls: f.drawChartDLbls(opts),
|
||||
AxID: []*attrValInt{
|
||||
{Val: intPtr(754001152)},
|
||||
{Val: intPtr(753999904)},
|
||||
},
|
||||
},
|
||||
CatAx: f.drawPlotAreaCatAx(formatSet),
|
||||
ValAx: f.drawPlotAreaValAx(formatSet),
|
||||
CatAx: f.drawPlotAreaCatAx(opts),
|
||||
ValAx: f.drawPlotAreaValAx(opts),
|
||||
}
|
||||
}
|
||||
|
||||
// drawPieChart provides a function to draw the c:plotArea element for pie
|
||||
// chart by given format sets.
|
||||
func (f *File) drawPieChart(formatSet *formatChart) *cPlotArea {
|
||||
func (f *File) drawPieChart(opts *chartOptions) *cPlotArea {
|
||||
return &cPlotArea{
|
||||
PieChart: &cCharts{
|
||||
VaryColors: &attrValBool{
|
||||
Val: boolPtr(formatSet.VaryColors),
|
||||
Val: boolPtr(opts.VaryColors),
|
||||
},
|
||||
Ser: f.drawChartSeries(formatSet),
|
||||
Ser: f.drawChartSeries(opts),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// drawPie3DChart provides a function to draw the c:plotArea element for 3D
|
||||
// pie chart by given format sets.
|
||||
func (f *File) drawPie3DChart(formatSet *formatChart) *cPlotArea {
|
||||
func (f *File) drawPie3DChart(opts *chartOptions) *cPlotArea {
|
||||
return &cPlotArea{
|
||||
Pie3DChart: &cCharts{
|
||||
VaryColors: &attrValBool{
|
||||
Val: boolPtr(formatSet.VaryColors),
|
||||
Val: boolPtr(opts.VaryColors),
|
||||
},
|
||||
Ser: f.drawChartSeries(formatSet),
|
||||
Ser: f.drawChartSeries(opts),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// drawPieOfPieChart provides a function to draw the c:plotArea element for
|
||||
// pie chart by given format sets.
|
||||
func (f *File) drawPieOfPieChart(formatSet *formatChart) *cPlotArea {
|
||||
func (f *File) drawPieOfPieChart(opts *chartOptions) *cPlotArea {
|
||||
return &cPlotArea{
|
||||
OfPieChart: &cCharts{
|
||||
OfPieType: &attrValString{
|
||||
Val: stringPtr("pie"),
|
||||
},
|
||||
VaryColors: &attrValBool{
|
||||
Val: boolPtr(formatSet.VaryColors),
|
||||
Val: boolPtr(opts.VaryColors),
|
||||
},
|
||||
Ser: f.drawChartSeries(formatSet),
|
||||
Ser: f.drawChartSeries(opts),
|
||||
SerLines: &attrValString{},
|
||||
},
|
||||
}
|
||||
|
@ -598,16 +598,16 @@ func (f *File) drawPieOfPieChart(formatSet *formatChart) *cPlotArea {
|
|||
|
||||
// drawBarOfPieChart provides a function to draw the c:plotArea element for
|
||||
// pie chart by given format sets.
|
||||
func (f *File) drawBarOfPieChart(formatSet *formatChart) *cPlotArea {
|
||||
func (f *File) drawBarOfPieChart(opts *chartOptions) *cPlotArea {
|
||||
return &cPlotArea{
|
||||
OfPieChart: &cCharts{
|
||||
OfPieType: &attrValString{
|
||||
Val: stringPtr("bar"),
|
||||
},
|
||||
VaryColors: &attrValBool{
|
||||
Val: boolPtr(formatSet.VaryColors),
|
||||
Val: boolPtr(opts.VaryColors),
|
||||
},
|
||||
Ser: f.drawChartSeries(formatSet),
|
||||
Ser: f.drawChartSeries(opts),
|
||||
SerLines: &attrValString{},
|
||||
},
|
||||
}
|
||||
|
@ -615,7 +615,7 @@ func (f *File) drawBarOfPieChart(formatSet *formatChart) *cPlotArea {
|
|||
|
||||
// drawRadarChart provides a function to draw the c:plotArea element for radar
|
||||
// chart by given format sets.
|
||||
func (f *File) drawRadarChart(formatSet *formatChart) *cPlotArea {
|
||||
func (f *File) drawRadarChart(opts *chartOptions) *cPlotArea {
|
||||
return &cPlotArea{
|
||||
RadarChart: &cCharts{
|
||||
RadarStyle: &attrValString{
|
||||
|
@ -624,21 +624,21 @@ func (f *File) drawRadarChart(formatSet *formatChart) *cPlotArea {
|
|||
VaryColors: &attrValBool{
|
||||
Val: boolPtr(false),
|
||||
},
|
||||
Ser: f.drawChartSeries(formatSet),
|
||||
DLbls: f.drawChartDLbls(formatSet),
|
||||
Ser: f.drawChartSeries(opts),
|
||||
DLbls: f.drawChartDLbls(opts),
|
||||
AxID: []*attrValInt{
|
||||
{Val: intPtr(754001152)},
|
||||
{Val: intPtr(753999904)},
|
||||
},
|
||||
},
|
||||
CatAx: f.drawPlotAreaCatAx(formatSet),
|
||||
ValAx: f.drawPlotAreaValAx(formatSet),
|
||||
CatAx: f.drawPlotAreaCatAx(opts),
|
||||
ValAx: f.drawPlotAreaValAx(opts),
|
||||
}
|
||||
}
|
||||
|
||||
// drawScatterChart provides a function to draw the c:plotArea element for
|
||||
// scatter chart by given format sets.
|
||||
func (f *File) drawScatterChart(formatSet *formatChart) *cPlotArea {
|
||||
func (f *File) drawScatterChart(opts *chartOptions) *cPlotArea {
|
||||
return &cPlotArea{
|
||||
ScatterChart: &cCharts{
|
||||
ScatterStyle: &attrValString{
|
||||
|
@ -647,35 +647,35 @@ func (f *File) drawScatterChart(formatSet *formatChart) *cPlotArea {
|
|||
VaryColors: &attrValBool{
|
||||
Val: boolPtr(false),
|
||||
},
|
||||
Ser: f.drawChartSeries(formatSet),
|
||||
DLbls: f.drawChartDLbls(formatSet),
|
||||
Ser: f.drawChartSeries(opts),
|
||||
DLbls: f.drawChartDLbls(opts),
|
||||
AxID: []*attrValInt{
|
||||
{Val: intPtr(754001152)},
|
||||
{Val: intPtr(753999904)},
|
||||
},
|
||||
},
|
||||
CatAx: f.drawPlotAreaCatAx(formatSet),
|
||||
ValAx: f.drawPlotAreaValAx(formatSet),
|
||||
CatAx: f.drawPlotAreaCatAx(opts),
|
||||
ValAx: f.drawPlotAreaValAx(opts),
|
||||
}
|
||||
}
|
||||
|
||||
// drawSurface3DChart provides a function to draw the c:surface3DChart element by
|
||||
// given format sets.
|
||||
func (f *File) drawSurface3DChart(formatSet *formatChart) *cPlotArea {
|
||||
func (f *File) drawSurface3DChart(opts *chartOptions) *cPlotArea {
|
||||
plotArea := &cPlotArea{
|
||||
Surface3DChart: &cCharts{
|
||||
Ser: f.drawChartSeries(formatSet),
|
||||
Ser: f.drawChartSeries(opts),
|
||||
AxID: []*attrValInt{
|
||||
{Val: intPtr(754001152)},
|
||||
{Val: intPtr(753999904)},
|
||||
{Val: intPtr(832256642)},
|
||||
},
|
||||
},
|
||||
CatAx: f.drawPlotAreaCatAx(formatSet),
|
||||
ValAx: f.drawPlotAreaValAx(formatSet),
|
||||
SerAx: f.drawPlotAreaSerAx(formatSet),
|
||||
CatAx: f.drawPlotAreaCatAx(opts),
|
||||
ValAx: f.drawPlotAreaValAx(opts),
|
||||
SerAx: f.drawPlotAreaSerAx(opts),
|
||||
}
|
||||
if formatSet.Type == WireframeSurface3D {
|
||||
if opts.Type == WireframeSurface3D {
|
||||
plotArea.Surface3DChart.Wireframe = &attrValBool{Val: boolPtr(true)}
|
||||
}
|
||||
return plotArea
|
||||
|
@ -683,21 +683,21 @@ func (f *File) drawSurface3DChart(formatSet *formatChart) *cPlotArea {
|
|||
|
||||
// drawSurfaceChart provides a function to draw the c:surfaceChart element by
|
||||
// given format sets.
|
||||
func (f *File) drawSurfaceChart(formatSet *formatChart) *cPlotArea {
|
||||
func (f *File) drawSurfaceChart(opts *chartOptions) *cPlotArea {
|
||||
plotArea := &cPlotArea{
|
||||
SurfaceChart: &cCharts{
|
||||
Ser: f.drawChartSeries(formatSet),
|
||||
Ser: f.drawChartSeries(opts),
|
||||
AxID: []*attrValInt{
|
||||
{Val: intPtr(754001152)},
|
||||
{Val: intPtr(753999904)},
|
||||
{Val: intPtr(832256642)},
|
||||
},
|
||||
},
|
||||
CatAx: f.drawPlotAreaCatAx(formatSet),
|
||||
ValAx: f.drawPlotAreaValAx(formatSet),
|
||||
SerAx: f.drawPlotAreaSerAx(formatSet),
|
||||
CatAx: f.drawPlotAreaCatAx(opts),
|
||||
ValAx: f.drawPlotAreaValAx(opts),
|
||||
SerAx: f.drawPlotAreaSerAx(opts),
|
||||
}
|
||||
if formatSet.Type == WireframeContour {
|
||||
if opts.Type == WireframeContour {
|
||||
plotArea.SurfaceChart.Wireframe = &attrValBool{Val: boolPtr(true)}
|
||||
}
|
||||
return plotArea
|
||||
|
@ -705,7 +705,7 @@ func (f *File) drawSurfaceChart(formatSet *formatChart) *cPlotArea {
|
|||
|
||||
// drawChartShape provides a function to draw the c:shape element by given
|
||||
// format sets.
|
||||
func (f *File) drawChartShape(formatSet *formatChart) *attrValString {
|
||||
func (f *File) drawChartShape(opts *chartOptions) *attrValString {
|
||||
shapes := map[string]string{
|
||||
Bar3DConeClustered: "cone",
|
||||
Bar3DConeStacked: "cone",
|
||||
|
@ -729,7 +729,7 @@ func (f *File) drawChartShape(formatSet *formatChart) *attrValString {
|
|||
Col3DCylinderStacked: "cylinder",
|
||||
Col3DCylinderPercentStacked: "cylinder",
|
||||
}
|
||||
if shape, ok := shapes[formatSet.Type]; ok {
|
||||
if shape, ok := shapes[opts.Type]; ok {
|
||||
return &attrValString{Val: stringPtr(shape)}
|
||||
}
|
||||
return nil
|
||||
|
@ -737,29 +737,29 @@ func (f *File) drawChartShape(formatSet *formatChart) *attrValString {
|
|||
|
||||
// drawChartSeries provides a function to draw the c:ser element by given
|
||||
// format sets.
|
||||
func (f *File) drawChartSeries(formatSet *formatChart) *[]cSer {
|
||||
func (f *File) drawChartSeries(opts *chartOptions) *[]cSer {
|
||||
var ser []cSer
|
||||
for k := range formatSet.Series {
|
||||
for k := range opts.Series {
|
||||
ser = append(ser, cSer{
|
||||
IDx: &attrValInt{Val: intPtr(k + formatSet.order)},
|
||||
Order: &attrValInt{Val: intPtr(k + formatSet.order)},
|
||||
IDx: &attrValInt{Val: intPtr(k + opts.order)},
|
||||
Order: &attrValInt{Val: intPtr(k + opts.order)},
|
||||
Tx: &cTx{
|
||||
StrRef: &cStrRef{
|
||||
F: formatSet.Series[k].Name,
|
||||
F: opts.Series[k].Name,
|
||||
},
|
||||
},
|
||||
SpPr: f.drawChartSeriesSpPr(k, formatSet),
|
||||
Marker: f.drawChartSeriesMarker(k, formatSet),
|
||||
DPt: f.drawChartSeriesDPt(k, formatSet),
|
||||
DLbls: f.drawChartSeriesDLbls(formatSet),
|
||||
SpPr: f.drawChartSeriesSpPr(k, opts),
|
||||
Marker: f.drawChartSeriesMarker(k, opts),
|
||||
DPt: f.drawChartSeriesDPt(k, opts),
|
||||
DLbls: f.drawChartSeriesDLbls(opts),
|
||||
InvertIfNegative: &attrValBool{Val: boolPtr(false)},
|
||||
Cat: f.drawChartSeriesCat(formatSet.Series[k], formatSet),
|
||||
Smooth: &attrValBool{Val: boolPtr(formatSet.Series[k].Line.Smooth)},
|
||||
Val: f.drawChartSeriesVal(formatSet.Series[k], formatSet),
|
||||
XVal: f.drawChartSeriesXVal(formatSet.Series[k], formatSet),
|
||||
YVal: f.drawChartSeriesYVal(formatSet.Series[k], formatSet),
|
||||
BubbleSize: f.drawCharSeriesBubbleSize(formatSet.Series[k], formatSet),
|
||||
Bubble3D: f.drawCharSeriesBubble3D(formatSet),
|
||||
Cat: f.drawChartSeriesCat(opts.Series[k], opts),
|
||||
Smooth: &attrValBool{Val: boolPtr(opts.Series[k].Line.Smooth)},
|
||||
Val: f.drawChartSeriesVal(opts.Series[k], opts),
|
||||
XVal: f.drawChartSeriesXVal(opts.Series[k], opts),
|
||||
YVal: f.drawChartSeriesYVal(opts.Series[k], opts),
|
||||
BubbleSize: f.drawCharSeriesBubbleSize(opts.Series[k], opts),
|
||||
Bubble3D: f.drawCharSeriesBubble3D(opts),
|
||||
})
|
||||
}
|
||||
return &ser
|
||||
|
@ -767,15 +767,15 @@ func (f *File) drawChartSeries(formatSet *formatChart) *[]cSer {
|
|||
|
||||
// drawChartSeriesSpPr provides a function to draw the c:spPr element by given
|
||||
// format sets.
|
||||
func (f *File) drawChartSeriesSpPr(i int, formatSet *formatChart) *cSpPr {
|
||||
func (f *File) drawChartSeriesSpPr(i int, opts *chartOptions) *cSpPr {
|
||||
var srgbClr *attrValString
|
||||
var schemeClr *aSchemeClr
|
||||
|
||||
if color := stringPtr(formatSet.Series[i].Line.Color); *color != "" {
|
||||
if color := stringPtr(opts.Series[i].Line.Color); *color != "" {
|
||||
*color = strings.TrimPrefix(*color, "#")
|
||||
srgbClr = &attrValString{Val: color}
|
||||
} else {
|
||||
schemeClr = &aSchemeClr{Val: "accent" + strconv.Itoa((formatSet.order+i)%6+1)}
|
||||
schemeClr = &aSchemeClr{Val: "accent" + strconv.Itoa((opts.order+i)%6+1)}
|
||||
}
|
||||
|
||||
spPrScatter := &cSpPr{
|
||||
|
@ -786,7 +786,7 @@ func (f *File) drawChartSeriesSpPr(i int, formatSet *formatChart) *cSpPr {
|
|||
}
|
||||
spPrLine := &cSpPr{
|
||||
Ln: &aLn{
|
||||
W: f.ptToEMUs(formatSet.Series[i].Line.Width),
|
||||
W: f.ptToEMUs(opts.Series[i].Line.Width),
|
||||
Cap: "rnd", // rnd, sq, flat
|
||||
SolidFill: &aSolidFill{
|
||||
SchemeClr: schemeClr,
|
||||
|
@ -795,12 +795,12 @@ func (f *File) drawChartSeriesSpPr(i int, formatSet *formatChart) *cSpPr {
|
|||
},
|
||||
}
|
||||
chartSeriesSpPr := map[string]*cSpPr{Line: spPrLine, Scatter: spPrScatter}
|
||||
return chartSeriesSpPr[formatSet.Type]
|
||||
return chartSeriesSpPr[opts.Type]
|
||||
}
|
||||
|
||||
// drawChartSeriesDPt provides a function to draw the c:dPt element by given
|
||||
// data index and format sets.
|
||||
func (f *File) drawChartSeriesDPt(i int, formatSet *formatChart) []*cDPt {
|
||||
func (f *File) drawChartSeriesDPt(i int, opts *chartOptions) []*cDPt {
|
||||
dpt := []*cDPt{{
|
||||
IDx: &attrValInt{Val: intPtr(i)},
|
||||
Bubble3D: &attrValBool{Val: boolPtr(false)},
|
||||
|
@ -824,19 +824,19 @@ func (f *File) drawChartSeriesDPt(i int, formatSet *formatChart) []*cDPt {
|
|||
},
|
||||
}}
|
||||
chartSeriesDPt := map[string][]*cDPt{Pie: dpt, Pie3D: dpt}
|
||||
return chartSeriesDPt[formatSet.Type]
|
||||
return chartSeriesDPt[opts.Type]
|
||||
}
|
||||
|
||||
// drawChartSeriesCat provides a function to draw the c:cat element by given
|
||||
// chart series and format sets.
|
||||
func (f *File) drawChartSeriesCat(v formatChartSeries, formatSet *formatChart) *cCat {
|
||||
func (f *File) drawChartSeriesCat(v chartSeriesOptions, opts *chartOptions) *cCat {
|
||||
cat := &cCat{
|
||||
StrRef: &cStrRef{
|
||||
F: v.Categories,
|
||||
},
|
||||
}
|
||||
chartSeriesCat := map[string]*cCat{Scatter: nil, Bubble: nil, Bubble3D: nil}
|
||||
if _, ok := chartSeriesCat[formatSet.Type]; ok || v.Categories == "" {
|
||||
if _, ok := chartSeriesCat[opts.Type]; ok || v.Categories == "" {
|
||||
return nil
|
||||
}
|
||||
return cat
|
||||
|
@ -844,14 +844,14 @@ func (f *File) drawChartSeriesCat(v formatChartSeries, formatSet *formatChart) *
|
|||
|
||||
// drawChartSeriesVal provides a function to draw the c:val element by given
|
||||
// chart series and format sets.
|
||||
func (f *File) drawChartSeriesVal(v formatChartSeries, formatSet *formatChart) *cVal {
|
||||
func (f *File) drawChartSeriesVal(v chartSeriesOptions, opts *chartOptions) *cVal {
|
||||
val := &cVal{
|
||||
NumRef: &cNumRef{
|
||||
F: v.Values,
|
||||
},
|
||||
}
|
||||
chartSeriesVal := map[string]*cVal{Scatter: nil, Bubble: nil, Bubble3D: nil}
|
||||
if _, ok := chartSeriesVal[formatSet.Type]; ok {
|
||||
if _, ok := chartSeriesVal[opts.Type]; ok {
|
||||
return nil
|
||||
}
|
||||
return val
|
||||
|
@ -859,16 +859,16 @@ func (f *File) drawChartSeriesVal(v formatChartSeries, formatSet *formatChart) *
|
|||
|
||||
// drawChartSeriesMarker provides a function to draw the c:marker element by
|
||||
// given data index and format sets.
|
||||
func (f *File) drawChartSeriesMarker(i int, formatSet *formatChart) *cMarker {
|
||||
func (f *File) drawChartSeriesMarker(i int, opts *chartOptions) *cMarker {
|
||||
defaultSymbol := map[string]*attrValString{Scatter: {Val: stringPtr("circle")}}
|
||||
marker := &cMarker{
|
||||
Symbol: defaultSymbol[formatSet.Type],
|
||||
Symbol: defaultSymbol[opts.Type],
|
||||
Size: &attrValInt{Val: intPtr(5)},
|
||||
}
|
||||
if symbol := stringPtr(formatSet.Series[i].Marker.Symbol); *symbol != "" {
|
||||
if symbol := stringPtr(opts.Series[i].Marker.Symbol); *symbol != "" {
|
||||
marker.Symbol = &attrValString{Val: symbol}
|
||||
}
|
||||
if size := intPtr(formatSet.Series[i].Marker.Size); *size != 0 {
|
||||
if size := intPtr(opts.Series[i].Marker.Size); *size != 0 {
|
||||
marker.Size = &attrValInt{Val: size}
|
||||
}
|
||||
if i < 6 {
|
||||
|
@ -889,37 +889,37 @@ func (f *File) drawChartSeriesMarker(i int, formatSet *formatChart) *cMarker {
|
|||
}
|
||||
}
|
||||
chartSeriesMarker := map[string]*cMarker{Scatter: marker, Line: marker}
|
||||
return chartSeriesMarker[formatSet.Type]
|
||||
return chartSeriesMarker[opts.Type]
|
||||
}
|
||||
|
||||
// drawChartSeriesXVal provides a function to draw the c:xVal element by given
|
||||
// chart series and format sets.
|
||||
func (f *File) drawChartSeriesXVal(v formatChartSeries, formatSet *formatChart) *cCat {
|
||||
func (f *File) drawChartSeriesXVal(v chartSeriesOptions, opts *chartOptions) *cCat {
|
||||
cat := &cCat{
|
||||
StrRef: &cStrRef{
|
||||
F: v.Categories,
|
||||
},
|
||||
}
|
||||
chartSeriesXVal := map[string]*cCat{Scatter: cat}
|
||||
return chartSeriesXVal[formatSet.Type]
|
||||
return chartSeriesXVal[opts.Type]
|
||||
}
|
||||
|
||||
// drawChartSeriesYVal provides a function to draw the c:yVal element by given
|
||||
// chart series and format sets.
|
||||
func (f *File) drawChartSeriesYVal(v formatChartSeries, formatSet *formatChart) *cVal {
|
||||
func (f *File) drawChartSeriesYVal(v chartSeriesOptions, opts *chartOptions) *cVal {
|
||||
val := &cVal{
|
||||
NumRef: &cNumRef{
|
||||
F: v.Values,
|
||||
},
|
||||
}
|
||||
chartSeriesYVal := map[string]*cVal{Scatter: val, Bubble: val, Bubble3D: val}
|
||||
return chartSeriesYVal[formatSet.Type]
|
||||
return chartSeriesYVal[opts.Type]
|
||||
}
|
||||
|
||||
// drawCharSeriesBubbleSize provides a function to draw the c:bubbleSize
|
||||
// element by given chart series and format sets.
|
||||
func (f *File) drawCharSeriesBubbleSize(v formatChartSeries, formatSet *formatChart) *cVal {
|
||||
if _, ok := map[string]bool{Bubble: true, Bubble3D: true}[formatSet.Type]; !ok {
|
||||
func (f *File) drawCharSeriesBubbleSize(v chartSeriesOptions, opts *chartOptions) *cVal {
|
||||
if _, ok := map[string]bool{Bubble: true, Bubble3D: true}[opts.Type]; !ok {
|
||||
return nil
|
||||
}
|
||||
return &cVal{
|
||||
|
@ -931,8 +931,8 @@ func (f *File) drawCharSeriesBubbleSize(v formatChartSeries, formatSet *formatCh
|
|||
|
||||
// drawCharSeriesBubble3D provides a function to draw the c:bubble3D element
|
||||
// by given format sets.
|
||||
func (f *File) drawCharSeriesBubble3D(formatSet *formatChart) *attrValBool {
|
||||
if _, ok := map[string]bool{Bubble3D: true}[formatSet.Type]; !ok {
|
||||
func (f *File) drawCharSeriesBubble3D(opts *chartOptions) *attrValBool {
|
||||
if _, ok := map[string]bool{Bubble3D: true}[opts.Type]; !ok {
|
||||
return nil
|
||||
}
|
||||
return &attrValBool{Val: boolPtr(true)}
|
||||
|
@ -940,51 +940,51 @@ func (f *File) drawCharSeriesBubble3D(formatSet *formatChart) *attrValBool {
|
|||
|
||||
// drawChartDLbls provides a function to draw the c:dLbls element by given
|
||||
// format sets.
|
||||
func (f *File) drawChartDLbls(formatSet *formatChart) *cDLbls {
|
||||
func (f *File) drawChartDLbls(opts *chartOptions) *cDLbls {
|
||||
return &cDLbls{
|
||||
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)},
|
||||
ShowLegendKey: &attrValBool{Val: boolPtr(opts.Legend.ShowLegendKey)},
|
||||
ShowVal: &attrValBool{Val: boolPtr(opts.Plotarea.ShowVal)},
|
||||
ShowCatName: &attrValBool{Val: boolPtr(opts.Plotarea.ShowCatName)},
|
||||
ShowSerName: &attrValBool{Val: boolPtr(opts.Plotarea.ShowSerName)},
|
||||
ShowBubbleSize: &attrValBool{Val: boolPtr(opts.Plotarea.ShowBubbleSize)},
|
||||
ShowPercent: &attrValBool{Val: boolPtr(opts.Plotarea.ShowPercent)},
|
||||
ShowLeaderLines: &attrValBool{Val: boolPtr(opts.Plotarea.ShowLeaderLines)},
|
||||
}
|
||||
}
|
||||
|
||||
// drawChartSeriesDLbls provides a function to draw the c:dLbls element by
|
||||
// given format sets.
|
||||
func (f *File) drawChartSeriesDLbls(formatSet *formatChart) *cDLbls {
|
||||
dLbls := f.drawChartDLbls(formatSet)
|
||||
func (f *File) drawChartSeriesDLbls(opts *chartOptions) *cDLbls {
|
||||
dLbls := f.drawChartDLbls(opts)
|
||||
chartSeriesDLbls := map[string]*cDLbls{
|
||||
Scatter: nil, Surface3D: nil, WireframeSurface3D: nil, Contour: nil, WireframeContour: nil, Bubble: nil, Bubble3D: nil,
|
||||
}
|
||||
if _, ok := chartSeriesDLbls[formatSet.Type]; ok {
|
||||
if _, ok := chartSeriesDLbls[opts.Type]; ok {
|
||||
return nil
|
||||
}
|
||||
return dLbls
|
||||
}
|
||||
|
||||
// drawPlotAreaCatAx provides a function to draw the c:catAx element.
|
||||
func (f *File) drawPlotAreaCatAx(formatSet *formatChart) []*cAxs {
|
||||
max := &attrValFloat{Val: formatSet.XAxis.Maximum}
|
||||
min := &attrValFloat{Val: formatSet.XAxis.Minimum}
|
||||
if formatSet.XAxis.Maximum == nil {
|
||||
func (f *File) drawPlotAreaCatAx(opts *chartOptions) []*cAxs {
|
||||
max := &attrValFloat{Val: opts.XAxis.Maximum}
|
||||
min := &attrValFloat{Val: opts.XAxis.Minimum}
|
||||
if opts.XAxis.Maximum == nil {
|
||||
max = nil
|
||||
}
|
||||
if formatSet.XAxis.Minimum == nil {
|
||||
if opts.XAxis.Minimum == nil {
|
||||
min = nil
|
||||
}
|
||||
axs := []*cAxs{
|
||||
{
|
||||
AxID: &attrValInt{Val: intPtr(754001152)},
|
||||
Scaling: &cScaling{
|
||||
Orientation: &attrValString{Val: stringPtr(orientation[formatSet.XAxis.ReverseOrder])},
|
||||
Orientation: &attrValString{Val: stringPtr(orientation[opts.XAxis.ReverseOrder])},
|
||||
Max: max,
|
||||
Min: min,
|
||||
},
|
||||
Delete: &attrValBool{Val: boolPtr(formatSet.XAxis.None)},
|
||||
AxPos: &attrValString{Val: stringPtr(catAxPos[formatSet.XAxis.ReverseOrder])},
|
||||
Delete: &attrValBool{Val: boolPtr(opts.XAxis.None)},
|
||||
AxPos: &attrValString{Val: stringPtr(catAxPos[opts.XAxis.ReverseOrder])},
|
||||
NumFmt: &cNumFmt{
|
||||
FormatCode: "General",
|
||||
SourceLinked: true,
|
||||
|
@ -1002,45 +1002,45 @@ func (f *File) drawPlotAreaCatAx(formatSet *formatChart) []*cAxs {
|
|||
NoMultiLvlLbl: &attrValBool{Val: boolPtr(false)},
|
||||
},
|
||||
}
|
||||
if formatSet.XAxis.MajorGridlines {
|
||||
if opts.XAxis.MajorGridlines {
|
||||
axs[0].MajorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()}
|
||||
}
|
||||
if formatSet.XAxis.MinorGridlines {
|
||||
if opts.XAxis.MinorGridlines {
|
||||
axs[0].MinorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()}
|
||||
}
|
||||
if formatSet.XAxis.TickLabelSkip != 0 {
|
||||
axs[0].TickLblSkip = &attrValInt{Val: intPtr(formatSet.XAxis.TickLabelSkip)}
|
||||
if opts.XAxis.TickLabelSkip != 0 {
|
||||
axs[0].TickLblSkip = &attrValInt{Val: intPtr(opts.XAxis.TickLabelSkip)}
|
||||
}
|
||||
return axs
|
||||
}
|
||||
|
||||
// drawPlotAreaValAx provides a function to draw the c:valAx element.
|
||||
func (f *File) drawPlotAreaValAx(formatSet *formatChart) []*cAxs {
|
||||
max := &attrValFloat{Val: formatSet.YAxis.Maximum}
|
||||
min := &attrValFloat{Val: formatSet.YAxis.Minimum}
|
||||
if formatSet.YAxis.Maximum == nil {
|
||||
func (f *File) drawPlotAreaValAx(opts *chartOptions) []*cAxs {
|
||||
max := &attrValFloat{Val: opts.YAxis.Maximum}
|
||||
min := &attrValFloat{Val: opts.YAxis.Minimum}
|
||||
if opts.YAxis.Maximum == nil {
|
||||
max = nil
|
||||
}
|
||||
if formatSet.YAxis.Minimum == nil {
|
||||
if opts.YAxis.Minimum == nil {
|
||||
min = nil
|
||||
}
|
||||
var logBase *attrValFloat
|
||||
if formatSet.YAxis.LogBase >= 2 && formatSet.YAxis.LogBase <= 1000 {
|
||||
logBase = &attrValFloat{Val: float64Ptr(formatSet.YAxis.LogBase)}
|
||||
if opts.YAxis.LogBase >= 2 && opts.YAxis.LogBase <= 1000 {
|
||||
logBase = &attrValFloat{Val: float64Ptr(opts.YAxis.LogBase)}
|
||||
}
|
||||
axs := []*cAxs{
|
||||
{
|
||||
AxID: &attrValInt{Val: intPtr(753999904)},
|
||||
Scaling: &cScaling{
|
||||
LogBase: logBase,
|
||||
Orientation: &attrValString{Val: stringPtr(orientation[formatSet.YAxis.ReverseOrder])},
|
||||
Orientation: &attrValString{Val: stringPtr(orientation[opts.YAxis.ReverseOrder])},
|
||||
Max: max,
|
||||
Min: min,
|
||||
},
|
||||
Delete: &attrValBool{Val: boolPtr(formatSet.YAxis.None)},
|
||||
AxPos: &attrValString{Val: stringPtr(valAxPos[formatSet.YAxis.ReverseOrder])},
|
||||
Delete: &attrValBool{Val: boolPtr(opts.YAxis.None)},
|
||||
AxPos: &attrValString{Val: stringPtr(valAxPos[opts.YAxis.ReverseOrder])},
|
||||
NumFmt: &cNumFmt{
|
||||
FormatCode: chartValAxNumFmtFormatCode[formatSet.Type],
|
||||
FormatCode: chartValAxNumFmtFormatCode[opts.Type],
|
||||
SourceLinked: true,
|
||||
},
|
||||
MajorTickMark: &attrValString{Val: stringPtr("none")},
|
||||
|
@ -1050,44 +1050,44 @@ func (f *File) drawPlotAreaValAx(formatSet *formatChart) []*cAxs {
|
|||
TxPr: f.drawPlotAreaTxPr(),
|
||||
CrossAx: &attrValInt{Val: intPtr(754001152)},
|
||||
Crosses: &attrValString{Val: stringPtr("autoZero")},
|
||||
CrossBetween: &attrValString{Val: stringPtr(chartValAxCrossBetween[formatSet.Type])},
|
||||
CrossBetween: &attrValString{Val: stringPtr(chartValAxCrossBetween[opts.Type])},
|
||||
},
|
||||
}
|
||||
if formatSet.YAxis.MajorGridlines {
|
||||
if opts.YAxis.MajorGridlines {
|
||||
axs[0].MajorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()}
|
||||
}
|
||||
if formatSet.YAxis.MinorGridlines {
|
||||
if opts.YAxis.MinorGridlines {
|
||||
axs[0].MinorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()}
|
||||
}
|
||||
if pos, ok := valTickLblPos[formatSet.Type]; ok {
|
||||
if pos, ok := valTickLblPos[opts.Type]; ok {
|
||||
axs[0].TickLblPos.Val = stringPtr(pos)
|
||||
}
|
||||
if formatSet.YAxis.MajorUnit != 0 {
|
||||
axs[0].MajorUnit = &attrValFloat{Val: float64Ptr(formatSet.YAxis.MajorUnit)}
|
||||
if opts.YAxis.MajorUnit != 0 {
|
||||
axs[0].MajorUnit = &attrValFloat{Val: float64Ptr(opts.YAxis.MajorUnit)}
|
||||
}
|
||||
return axs
|
||||
}
|
||||
|
||||
// drawPlotAreaSerAx provides a function to draw the c:serAx element.
|
||||
func (f *File) drawPlotAreaSerAx(formatSet *formatChart) []*cAxs {
|
||||
max := &attrValFloat{Val: formatSet.YAxis.Maximum}
|
||||
min := &attrValFloat{Val: formatSet.YAxis.Minimum}
|
||||
if formatSet.YAxis.Maximum == nil {
|
||||
func (f *File) drawPlotAreaSerAx(opts *chartOptions) []*cAxs {
|
||||
max := &attrValFloat{Val: opts.YAxis.Maximum}
|
||||
min := &attrValFloat{Val: opts.YAxis.Minimum}
|
||||
if opts.YAxis.Maximum == nil {
|
||||
max = nil
|
||||
}
|
||||
if formatSet.YAxis.Minimum == nil {
|
||||
if opts.YAxis.Minimum == nil {
|
||||
min = nil
|
||||
}
|
||||
return []*cAxs{
|
||||
{
|
||||
AxID: &attrValInt{Val: intPtr(832256642)},
|
||||
Scaling: &cScaling{
|
||||
Orientation: &attrValString{Val: stringPtr(orientation[formatSet.YAxis.ReverseOrder])},
|
||||
Orientation: &attrValString{Val: stringPtr(orientation[opts.YAxis.ReverseOrder])},
|
||||
Max: max,
|
||||
Min: min,
|
||||
},
|
||||
Delete: &attrValBool{Val: boolPtr(formatSet.YAxis.None)},
|
||||
AxPos: &attrValString{Val: stringPtr(catAxPos[formatSet.XAxis.ReverseOrder])},
|
||||
Delete: &attrValBool{Val: boolPtr(opts.YAxis.None)},
|
||||
AxPos: &attrValString{Val: stringPtr(catAxPos[opts.XAxis.ReverseOrder])},
|
||||
TickLblPos: &attrValString{Val: stringPtr("nextTo")},
|
||||
SpPr: f.drawPlotAreaSpPr(),
|
||||
TxPr: f.drawPlotAreaTxPr(),
|
||||
|
@ -1207,7 +1207,7 @@ func (f *File) drawingParser(path string) (*xlsxWsDr, int) {
|
|||
|
||||
// addDrawingChart provides a function to add chart graphic frame by given
|
||||
// sheet, drawingXML, cell, width, height, relationship index and format sets.
|
||||
func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rID int, formatSet *formatPicture) error {
|
||||
func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rID int, opts *pictureOptions) error {
|
||||
col, row, err := CellNameToCoordinates(cell)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1215,17 +1215,17 @@ func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rI
|
|||
colIdx := col - 1
|
||||
rowIdx := row - 1
|
||||
|
||||
width = int(float64(width) * formatSet.XScale)
|
||||
height = int(float64(height) * formatSet.YScale)
|
||||
colStart, rowStart, colEnd, rowEnd, x2, y2 := f.positionObjectPixels(sheet, colIdx, rowIdx, formatSet.OffsetX, formatSet.OffsetY, width, height)
|
||||
width = int(float64(width) * opts.XScale)
|
||||
height = int(float64(height) * opts.YScale)
|
||||
colStart, rowStart, colEnd, rowEnd, x2, y2 := f.positionObjectPixels(sheet, colIdx, rowIdx, opts.OffsetX, opts.OffsetY, width, height)
|
||||
content, cNvPrID := f.drawingParser(drawingXML)
|
||||
twoCellAnchor := xdrCellAnchor{}
|
||||
twoCellAnchor.EditAs = formatSet.Positioning
|
||||
twoCellAnchor.EditAs = opts.Positioning
|
||||
from := xlsxFrom{}
|
||||
from.Col = colStart
|
||||
from.ColOff = formatSet.OffsetX * EMU
|
||||
from.ColOff = opts.OffsetX * EMU
|
||||
from.Row = rowStart
|
||||
from.RowOff = formatSet.OffsetY * EMU
|
||||
from.RowOff = opts.OffsetY * EMU
|
||||
to := xlsxTo{}
|
||||
to.Col = colEnd
|
||||
to.ColOff = x2 * EMU
|
||||
|
@ -1255,8 +1255,8 @@ func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rI
|
|||
graphic, _ := xml.Marshal(graphicFrame)
|
||||
twoCellAnchor.GraphicFrame = string(graphic)
|
||||
twoCellAnchor.ClientData = &xdrClientData{
|
||||
FLocksWithSheet: formatSet.FLocksWithSheet,
|
||||
FPrintsWithSheet: formatSet.FPrintsWithSheet,
|
||||
FLocksWithSheet: opts.FLocksWithSheet,
|
||||
FPrintsWithSheet: opts.FPrintsWithSheet,
|
||||
}
|
||||
content.TwoCellAnchor = append(content.TwoCellAnchor, &twoCellAnchor)
|
||||
f.Drawings.Store(drawingXML, content)
|
||||
|
@ -1266,10 +1266,10 @@ func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rI
|
|||
// addSheetDrawingChart provides a function to add chart graphic frame for
|
||||
// chartsheet by given sheet, drawingXML, width, height, relationship index
|
||||
// and format sets.
|
||||
func (f *File) addSheetDrawingChart(drawingXML string, rID int, formatSet *formatPicture) {
|
||||
func (f *File) addSheetDrawingChart(drawingXML string, rID int, opts *pictureOptions) {
|
||||
content, cNvPrID := f.drawingParser(drawingXML)
|
||||
absoluteAnchor := xdrCellAnchor{
|
||||
EditAs: formatSet.Positioning,
|
||||
EditAs: opts.Positioning,
|
||||
Pos: &xlsxPoint2D{},
|
||||
Ext: &xlsxExt{},
|
||||
}
|
||||
|
@ -1295,8 +1295,8 @@ func (f *File) addSheetDrawingChart(drawingXML string, rID int, formatSet *forma
|
|||
graphic, _ := xml.Marshal(graphicFrame)
|
||||
absoluteAnchor.GraphicFrame = string(graphic)
|
||||
absoluteAnchor.ClientData = &xdrClientData{
|
||||
FLocksWithSheet: formatSet.FLocksWithSheet,
|
||||
FPrintsWithSheet: formatSet.FPrintsWithSheet,
|
||||
FLocksWithSheet: opts.FLocksWithSheet,
|
||||
FPrintsWithSheet: opts.FPrintsWithSheet,
|
||||
}
|
||||
content.AbsoluteAnchor = append(content.AbsoluteAnchor, &absoluteAnchor)
|
||||
f.Drawings.Store(drawingXML, content)
|
||||
|
@ -1304,8 +1304,9 @@ func (f *File) addSheetDrawingChart(drawingXML string, rID int, formatSet *forma
|
|||
|
||||
// deleteDrawing provides a function to delete chart graphic frame by given by
|
||||
// given coordinates and graphic type.
|
||||
func (f *File) deleteDrawing(col, row int, drawingXML, drawingType string) (err error) {
|
||||
func (f *File) deleteDrawing(col, row int, drawingXML, drawingType string) error {
|
||||
var (
|
||||
err error
|
||||
wsDr *xlsxWsDr
|
||||
deTwoCellAnchor *decodeTwoCellAnchor
|
||||
)
|
||||
|
@ -1331,7 +1332,7 @@ func (f *File) deleteDrawing(col, row int, drawingXML, drawingType string) (err
|
|||
if err = f.xmlNewDecoder(strings.NewReader("<decodeTwoCellAnchor>" + wsDr.TwoCellAnchor[idx].GraphicFrame + "</decodeTwoCellAnchor>")).
|
||||
Decode(deTwoCellAnchor); err != nil && err != io.EOF {
|
||||
err = newDecodeXMLError(err)
|
||||
return
|
||||
return err
|
||||
}
|
||||
if err = nil; deTwoCellAnchor.From != nil && decodeTwoCellAnchorFuncs[drawingType](deTwoCellAnchor) {
|
||||
if deTwoCellAnchor.From.Col == col && deTwoCellAnchor.From.Row == row {
|
||||
|
|
|
@ -319,13 +319,13 @@ func TestNewFile(t *testing.T) {
|
|||
t.FailNow()
|
||||
}
|
||||
|
||||
// Test add picture to worksheet without formatset.
|
||||
// Test add picture to worksheet without options.
|
||||
err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), "")
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// Test add picture to worksheet with invalid formatset.
|
||||
// Test add picture to worksheet with invalid options.
|
||||
err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), `{`)
|
||||
if !assert.Error(t, err) {
|
||||
t.FailNow()
|
||||
|
@ -1021,12 +1021,6 @@ func TestRelsWriter(t *testing.T) {
|
|||
f.relsWriter()
|
||||
}
|
||||
|
||||
func TestGetSheetView(t *testing.T) {
|
||||
f := NewFile()
|
||||
_, err := f.getSheetView("SheetN", 0)
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
}
|
||||
|
||||
func TestConditionalFormat(t *testing.T) {
|
||||
f := NewFile()
|
||||
sheet1 := f.GetSheetName(0)
|
||||
|
@ -1228,7 +1222,7 @@ func TestProtectSheet(t *testing.T) {
|
|||
sheetName := f.GetSheetName(0)
|
||||
assert.NoError(t, f.ProtectSheet(sheetName, nil))
|
||||
// Test protect worksheet with XOR hash algorithm
|
||||
assert.NoError(t, f.ProtectSheet(sheetName, &FormatSheetProtection{
|
||||
assert.NoError(t, f.ProtectSheet(sheetName, &SheetProtectionOptions{
|
||||
Password: "password",
|
||||
EditScenarios: false,
|
||||
}))
|
||||
|
@ -1237,7 +1231,7 @@ func TestProtectSheet(t *testing.T) {
|
|||
assert.Equal(t, "83AF", ws.SheetProtection.Password)
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestProtectSheet.xlsx")))
|
||||
// Test protect worksheet with SHA-512 hash algorithm
|
||||
assert.NoError(t, f.ProtectSheet(sheetName, &FormatSheetProtection{
|
||||
assert.NoError(t, f.ProtectSheet(sheetName, &SheetProtectionOptions{
|
||||
AlgorithmName: "SHA-512",
|
||||
Password: "password",
|
||||
}))
|
||||
|
@ -1251,15 +1245,15 @@ func TestProtectSheet(t *testing.T) {
|
|||
// Test remove sheet protection with password verification
|
||||
assert.NoError(t, f.UnprotectSheet(sheetName, "password"))
|
||||
// Test protect worksheet with empty password
|
||||
assert.NoError(t, f.ProtectSheet(sheetName, &FormatSheetProtection{}))
|
||||
assert.NoError(t, f.ProtectSheet(sheetName, &SheetProtectionOptions{}))
|
||||
assert.Equal(t, "", ws.SheetProtection.Password)
|
||||
// Test protect worksheet with password exceeds the limit length
|
||||
assert.EqualError(t, f.ProtectSheet(sheetName, &FormatSheetProtection{
|
||||
assert.EqualError(t, f.ProtectSheet(sheetName, &SheetProtectionOptions{
|
||||
AlgorithmName: "MD4",
|
||||
Password: strings.Repeat("s", MaxFieldLength+1),
|
||||
}), ErrPasswordLengthInvalid.Error())
|
||||
// Test protect worksheet with unsupported hash algorithm
|
||||
assert.EqualError(t, f.ProtectSheet(sheetName, &FormatSheetProtection{
|
||||
assert.EqualError(t, f.ProtectSheet(sheetName, &SheetProtectionOptions{
|
||||
AlgorithmName: "RIPEMD-160",
|
||||
Password: "password",
|
||||
}), ErrUnsupportedHashAlgorithm.Error())
|
||||
|
@ -1282,13 +1276,13 @@ func TestUnprotectSheet(t *testing.T) {
|
|||
|
||||
f = NewFile()
|
||||
sheetName := f.GetSheetName(0)
|
||||
assert.NoError(t, f.ProtectSheet(sheetName, &FormatSheetProtection{Password: "password"}))
|
||||
assert.NoError(t, f.ProtectSheet(sheetName, &SheetProtectionOptions{Password: "password"}))
|
||||
// Test remove sheet protection with an incorrect password
|
||||
assert.EqualError(t, f.UnprotectSheet(sheetName, "wrongPassword"), ErrUnprotectSheetPassword.Error())
|
||||
// Test remove sheet protection with password verification
|
||||
assert.NoError(t, f.UnprotectSheet(sheetName, "password"))
|
||||
// Test with invalid salt value
|
||||
assert.NoError(t, f.ProtectSheet(sheetName, &FormatSheetProtection{
|
||||
assert.NoError(t, f.ProtectSheet(sheetName, &SheetProtectionOptions{
|
||||
AlgorithmName: "SHA-512",
|
||||
Password: "password",
|
||||
}))
|
||||
|
@ -1309,7 +1303,7 @@ func TestSetDefaultTimeStyle(t *testing.T) {
|
|||
|
||||
func TestAddVBAProject(t *testing.T) {
|
||||
f := NewFile()
|
||||
assert.NoError(t, f.SetSheetPrOptions("Sheet1", CodeName("Sheet1")))
|
||||
assert.NoError(t, f.SetSheetProps("Sheet1", &SheetPropsOptions{CodeName: stringPtr("Sheet1")}))
|
||||
assert.EqualError(t, f.AddVBAProject("macros.bin"), "stat macros.bin: no such file or directory")
|
||||
assert.EqualError(t, f.AddVBAProject(filepath.Join("test", "Book1.xlsx")), ErrAddVBAProject.Error())
|
||||
assert.NoError(t, f.AddVBAProject(filepath.Join("test", "vbaProject.bin")))
|
||||
|
|
19
lib.go
19
lib.go
|
@ -422,20 +422,15 @@ func boolPtr(b bool) *bool { return &b }
|
|||
// intPtr returns a pointer to an int with the given value.
|
||||
func intPtr(i int) *int { return &i }
|
||||
|
||||
// uintPtr returns a pointer to an int with the given value.
|
||||
func uintPtr(i uint) *uint { return &i }
|
||||
|
||||
// float64Ptr returns a pointer 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 {
|
||||
return true
|
||||
}
|
||||
return *b
|
||||
}
|
||||
|
||||
// MarshalXML convert the boolean data type to literal values 0 or 1 on
|
||||
// serialization.
|
||||
func (avb attrValBool) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
|
||||
|
@ -499,11 +494,11 @@ func (avb *attrValBool) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
|
|||
return nil
|
||||
}
|
||||
|
||||
// parseFormatSet provides a method to convert format string to []byte and
|
||||
// fallbackOptions provides a method to convert format string to []byte and
|
||||
// handle empty string.
|
||||
func parseFormatSet(formatSet string) []byte {
|
||||
if formatSet != "" {
|
||||
return []byte(formatSet)
|
||||
func fallbackOptions(opts string) []byte {
|
||||
if opts != "" {
|
||||
return []byte(opts)
|
||||
}
|
||||
return []byte("{}")
|
||||
}
|
||||
|
|
60
picture.go
60
picture.go
|
@ -25,15 +25,15 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// parseFormatPictureSet provides a function to parse the format settings of
|
||||
// parsePictureOptions provides a function to parse the format settings of
|
||||
// the picture with default value.
|
||||
func parseFormatPictureSet(formatSet string) (*formatPicture, error) {
|
||||
format := formatPicture{
|
||||
func parsePictureOptions(opts string) (*pictureOptions, error) {
|
||||
format := pictureOptions{
|
||||
FPrintsWithSheet: true,
|
||||
XScale: 1,
|
||||
YScale: 1,
|
||||
}
|
||||
err := json.Unmarshal(parseFormatSet(formatSet), &format)
|
||||
err := json.Unmarshal(fallbackOptions(opts), &format)
|
||||
return &format, err
|
||||
}
|
||||
|
||||
|
@ -148,14 +148,14 @@ func (f *File) AddPicture(sheet, cell, picture, format string) error {
|
|||
// fmt.Println(err)
|
||||
// }
|
||||
// }
|
||||
func (f *File) AddPictureFromBytes(sheet, cell, format, name, extension string, file []byte) error {
|
||||
func (f *File) AddPictureFromBytes(sheet, cell, opts, name, extension string, file []byte) error {
|
||||
var drawingHyperlinkRID int
|
||||
var hyperlinkType string
|
||||
ext, ok := supportedImageTypes[extension]
|
||||
if !ok {
|
||||
return ErrImgExt
|
||||
}
|
||||
formatSet, err := parseFormatPictureSet(format)
|
||||
options, err := parsePictureOptions(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -177,14 +177,14 @@ func (f *File) AddPictureFromBytes(sheet, cell, format, name, extension string,
|
|||
mediaStr := ".." + strings.TrimPrefix(f.addMedia(file, ext), "xl")
|
||||
drawingRID := f.addRels(drawingRels, SourceRelationshipImage, mediaStr, hyperlinkType)
|
||||
// Add picture with hyperlink.
|
||||
if formatSet.Hyperlink != "" && formatSet.HyperlinkType != "" {
|
||||
if formatSet.HyperlinkType == "External" {
|
||||
hyperlinkType = formatSet.HyperlinkType
|
||||
if options.Hyperlink != "" && options.HyperlinkType != "" {
|
||||
if options.HyperlinkType == "External" {
|
||||
hyperlinkType = options.HyperlinkType
|
||||
}
|
||||
drawingHyperlinkRID = f.addRels(drawingRels, SourceRelationshipHyperLink, formatSet.Hyperlink, hyperlinkType)
|
||||
drawingHyperlinkRID = f.addRels(drawingRels, SourceRelationshipHyperLink, options.Hyperlink, hyperlinkType)
|
||||
}
|
||||
ws.Unlock()
|
||||
err = f.addDrawingPicture(sheet, drawingXML, cell, name, img.Width, img.Height, drawingRID, drawingHyperlinkRID, formatSet)
|
||||
err = f.addDrawingPicture(sheet, drawingXML, cell, name, img.Width, img.Height, drawingRID, drawingHyperlinkRID, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -264,31 +264,31 @@ func (f *File) countDrawings() (count int) {
|
|||
// addDrawingPicture provides a function to add picture by given sheet,
|
||||
// drawingXML, cell, file name, width, height relationship index and format
|
||||
// sets.
|
||||
func (f *File) addDrawingPicture(sheet, drawingXML, cell, file string, width, height, rID, hyperlinkRID int, formatSet *formatPicture) error {
|
||||
func (f *File) addDrawingPicture(sheet, drawingXML, cell, file string, width, height, rID, hyperlinkRID int, opts *pictureOptions) error {
|
||||
col, row, err := CellNameToCoordinates(cell)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if formatSet.Autofit {
|
||||
width, height, col, row, err = f.drawingResize(sheet, cell, float64(width), float64(height), formatSet)
|
||||
if opts.Autofit {
|
||||
width, height, col, row, err = f.drawingResize(sheet, cell, float64(width), float64(height), opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
width = int(float64(width) * formatSet.XScale)
|
||||
height = int(float64(height) * formatSet.YScale)
|
||||
width = int(float64(width) * opts.XScale)
|
||||
height = int(float64(height) * opts.YScale)
|
||||
}
|
||||
col--
|
||||
row--
|
||||
colStart, rowStart, colEnd, rowEnd, x2, y2 := f.positionObjectPixels(sheet, col, row, formatSet.OffsetX, formatSet.OffsetY, width, height)
|
||||
colStart, rowStart, colEnd, rowEnd, x2, y2 := f.positionObjectPixels(sheet, col, row, opts.OffsetX, opts.OffsetY, width, height)
|
||||
content, cNvPrID := f.drawingParser(drawingXML)
|
||||
twoCellAnchor := xdrCellAnchor{}
|
||||
twoCellAnchor.EditAs = formatSet.Positioning
|
||||
twoCellAnchor.EditAs = opts.Positioning
|
||||
from := xlsxFrom{}
|
||||
from.Col = colStart
|
||||
from.ColOff = formatSet.OffsetX * EMU
|
||||
from.ColOff = opts.OffsetX * EMU
|
||||
from.Row = rowStart
|
||||
from.RowOff = formatSet.OffsetY * EMU
|
||||
from.RowOff = opts.OffsetY * EMU
|
||||
to := xlsxTo{}
|
||||
to.Col = colEnd
|
||||
to.ColOff = x2 * EMU
|
||||
|
@ -297,7 +297,7 @@ func (f *File) addDrawingPicture(sheet, drawingXML, cell, file string, width, he
|
|||
twoCellAnchor.From = &from
|
||||
twoCellAnchor.To = &to
|
||||
pic := xlsxPic{}
|
||||
pic.NvPicPr.CNvPicPr.PicLocks.NoChangeAspect = formatSet.NoChangeAspect
|
||||
pic.NvPicPr.CNvPicPr.PicLocks.NoChangeAspect = opts.NoChangeAspect
|
||||
pic.NvPicPr.CNvPr.ID = cNvPrID
|
||||
pic.NvPicPr.CNvPr.Descr = file
|
||||
pic.NvPicPr.CNvPr.Name = "Picture " + strconv.Itoa(cNvPrID)
|
||||
|
@ -313,8 +313,8 @@ func (f *File) addDrawingPicture(sheet, drawingXML, cell, file string, width, he
|
|||
|
||||
twoCellAnchor.Pic = &pic
|
||||
twoCellAnchor.ClientData = &xdrClientData{
|
||||
FLocksWithSheet: formatSet.FLocksWithSheet,
|
||||
FPrintsWithSheet: formatSet.FPrintsWithSheet,
|
||||
FLocksWithSheet: opts.FLocksWithSheet,
|
||||
FPrintsWithSheet: opts.FPrintsWithSheet,
|
||||
}
|
||||
content.Lock()
|
||||
defer content.Unlock()
|
||||
|
@ -514,19 +514,19 @@ func (f *File) GetPicture(sheet, cell string) (string, []byte, error) {
|
|||
// DeletePicture provides a function to delete charts in spreadsheet by given
|
||||
// worksheet name and cell reference. Note that the image file won't be deleted
|
||||
// from the document currently.
|
||||
func (f *File) DeletePicture(sheet, cell string) (err error) {
|
||||
func (f *File) DeletePicture(sheet, cell string) error {
|
||||
col, row, err := CellNameToCoordinates(cell)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
col--
|
||||
row--
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if ws.Drawing == nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
drawingXML := strings.ReplaceAll(f.getSheetRelationshipsTargetByID(sheet, ws.Drawing.RID), "..", "xl")
|
||||
return f.deleteDrawing(col, row, drawingXML, "Pic")
|
||||
|
@ -636,7 +636,7 @@ func (f *File) drawingsWriter() {
|
|||
}
|
||||
|
||||
// drawingResize calculate the height and width after resizing.
|
||||
func (f *File) drawingResize(sheet, cell string, width, height float64, formatSet *formatPicture) (w, h, c, r int, err error) {
|
||||
func (f *File) drawingResize(sheet, cell string, width, height float64, opts *pictureOptions) (w, h, c, r int, err error) {
|
||||
var mergeCells []MergeCell
|
||||
mergeCells, err = f.GetMergeCells(sheet)
|
||||
if err != nil {
|
||||
|
@ -678,7 +678,7 @@ func (f *File) drawingResize(sheet, cell string, width, height float64, formatSe
|
|||
asp := float64(cellHeight) / height
|
||||
height, width = float64(cellHeight), width*asp
|
||||
}
|
||||
width, height = width-float64(formatSet.OffsetX), height-float64(formatSet.OffsetY)
|
||||
w, h = int(width*formatSet.XScale), int(height*formatSet.YScale)
|
||||
width, height = width-float64(opts.OffsetX), height-float64(opts.OffsetY)
|
||||
w, h = int(width*opts.XScale), int(height*opts.YScale)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -18,14 +18,14 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// PivotTableOption directly maps the format settings of the pivot table.
|
||||
// PivotTableOptions directly maps the format settings of the pivot table.
|
||||
//
|
||||
// PivotTableStyleName: The built-in pivot table style names
|
||||
//
|
||||
// PivotStyleLight1 - PivotStyleLight28
|
||||
// PivotStyleMedium1 - PivotStyleMedium28
|
||||
// PivotStyleDark1 - PivotStyleDark28
|
||||
type PivotTableOption struct {
|
||||
type PivotTableOptions struct {
|
||||
pivotTableSheetName string
|
||||
DataRange string `json:"data_range"`
|
||||
PivotTableRange string `json:"pivot_table_range"`
|
||||
|
@ -81,9 +81,9 @@ type PivotTableField struct {
|
|||
// options. Note that the same fields can not in Columns, Rows and Filter
|
||||
// fields at the same time.
|
||||
//
|
||||
// For example, create a pivot table on the Sheet1!$G$2:$M$34 range reference
|
||||
// with the region Sheet1!$A$1:$E$31 as the data source, summarize by sum for
|
||||
// sales:
|
||||
// For example, create a pivot table on the range reference Sheet1!$G$2:$M$34
|
||||
// with the range reference Sheet1!$A$1:$E$31 as the data source, summarize by
|
||||
// sum for sales:
|
||||
//
|
||||
// package main
|
||||
//
|
||||
|
@ -129,7 +129,7 @@ type PivotTableField struct {
|
|||
// fmt.Println(err)
|
||||
// }
|
||||
// }
|
||||
func (f *File) AddPivotTable(opts *PivotTableOption) error {
|
||||
func (f *File) AddPivotTable(opts *PivotTableOptions) error {
|
||||
// parameter validation
|
||||
_, pivotTableSheetPath, err := f.parseFormatPivotTableSet(opts)
|
||||
if err != nil {
|
||||
|
@ -168,7 +168,7 @@ func (f *File) AddPivotTable(opts *PivotTableOption) error {
|
|||
|
||||
// parseFormatPivotTableSet provides a function to validate pivot table
|
||||
// properties.
|
||||
func (f *File) parseFormatPivotTableSet(opts *PivotTableOption) (*xlsxWorksheet, string, error) {
|
||||
func (f *File) parseFormatPivotTableSet(opts *PivotTableOptions) (*xlsxWorksheet, string, error) {
|
||||
if opts == nil {
|
||||
return nil, "", ErrParameterRequired
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ func (f *File) adjustRange(rangeStr string) (string, []int, error) {
|
|||
|
||||
// getPivotFieldsOrder provides a function to get order list of pivot table
|
||||
// fields.
|
||||
func (f *File) getPivotFieldsOrder(opts *PivotTableOption) ([]string, error) {
|
||||
func (f *File) getPivotFieldsOrder(opts *PivotTableOptions) ([]string, error) {
|
||||
var order []string
|
||||
dataRange := f.getDefinedNameRefTo(opts.DataRange, opts.pivotTableSheetName)
|
||||
if dataRange == "" {
|
||||
|
@ -250,7 +250,7 @@ func (f *File) getPivotFieldsOrder(opts *PivotTableOption) ([]string, error) {
|
|||
}
|
||||
|
||||
// addPivotCache provides a function to create a pivot cache by given properties.
|
||||
func (f *File) addPivotCache(pivotCacheXML string, opts *PivotTableOption) error {
|
||||
func (f *File) addPivotCache(pivotCacheXML string, opts *PivotTableOptions) error {
|
||||
// validate data range
|
||||
definedNameRef := true
|
||||
dataRange := f.getDefinedNameRefTo(opts.DataRange, opts.pivotTableSheetName)
|
||||
|
@ -312,7 +312,7 @@ func (f *File) addPivotCache(pivotCacheXML string, opts *PivotTableOption) error
|
|||
|
||||
// addPivotTable provides a function to create a pivot table by given pivot
|
||||
// table ID and properties.
|
||||
func (f *File) addPivotTable(cacheID, pivotTableID int, pivotTableXML string, opts *PivotTableOption) error {
|
||||
func (f *File) addPivotTable(cacheID, pivotTableID int, pivotTableXML string, opts *PivotTableOptions) error {
|
||||
// validate pivot table range
|
||||
_, coordinates, err := f.adjustRange(opts.PivotTableRange)
|
||||
if err != nil {
|
||||
|
@ -391,7 +391,7 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, pivotTableXML string, op
|
|||
|
||||
// addPivotRowFields provides a method to add row fields for pivot table by
|
||||
// given pivot table options.
|
||||
func (f *File) addPivotRowFields(pt *xlsxPivotTableDefinition, opts *PivotTableOption) error {
|
||||
func (f *File) addPivotRowFields(pt *xlsxPivotTableDefinition, opts *PivotTableOptions) error {
|
||||
// row fields
|
||||
rowFieldsIndex, err := f.getPivotFieldsIndex(opts.Rows, opts)
|
||||
if err != nil {
|
||||
|
@ -415,7 +415,7 @@ func (f *File) addPivotRowFields(pt *xlsxPivotTableDefinition, opts *PivotTableO
|
|||
|
||||
// addPivotPageFields provides a method to add page fields for pivot table by
|
||||
// given pivot table options.
|
||||
func (f *File) addPivotPageFields(pt *xlsxPivotTableDefinition, opts *PivotTableOption) error {
|
||||
func (f *File) addPivotPageFields(pt *xlsxPivotTableDefinition, opts *PivotTableOptions) error {
|
||||
// page fields
|
||||
pageFieldsIndex, err := f.getPivotFieldsIndex(opts.Filter, opts)
|
||||
if err != nil {
|
||||
|
@ -441,7 +441,7 @@ func (f *File) addPivotPageFields(pt *xlsxPivotTableDefinition, opts *PivotTable
|
|||
|
||||
// addPivotDataFields provides a method to add data fields for pivot table by
|
||||
// given pivot table options.
|
||||
func (f *File) addPivotDataFields(pt *xlsxPivotTableDefinition, opts *PivotTableOption) error {
|
||||
func (f *File) addPivotDataFields(pt *xlsxPivotTableDefinition, opts *PivotTableOptions) error {
|
||||
// data fields
|
||||
dataFieldsIndex, err := f.getPivotFieldsIndex(opts.Data, opts)
|
||||
if err != nil {
|
||||
|
@ -481,7 +481,7 @@ func inPivotTableField(a []PivotTableField, x string) int {
|
|||
|
||||
// addPivotColFields create pivot column fields by given pivot table
|
||||
// definition and option.
|
||||
func (f *File) addPivotColFields(pt *xlsxPivotTableDefinition, opts *PivotTableOption) error {
|
||||
func (f *File) addPivotColFields(pt *xlsxPivotTableDefinition, opts *PivotTableOptions) error {
|
||||
if len(opts.Columns) == 0 {
|
||||
if len(opts.Data) <= 1 {
|
||||
return nil
|
||||
|
@ -522,7 +522,7 @@ func (f *File) addPivotColFields(pt *xlsxPivotTableDefinition, opts *PivotTableO
|
|||
|
||||
// addPivotFields create pivot fields based on the column order of the first
|
||||
// row in the data region by given pivot table definition and option.
|
||||
func (f *File) addPivotFields(pt *xlsxPivotTableDefinition, opts *PivotTableOption) error {
|
||||
func (f *File) addPivotFields(pt *xlsxPivotTableDefinition, opts *PivotTableOptions) error {
|
||||
order, err := f.getPivotFieldsOrder(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -627,7 +627,7 @@ func (f *File) countPivotCache() int {
|
|||
|
||||
// getPivotFieldsIndex convert the column of the first row in the data region
|
||||
// to a sequential index by given fields and pivot option.
|
||||
func (f *File) getPivotFieldsIndex(fields []PivotTableField, opts *PivotTableOption) ([]int, error) {
|
||||
func (f *File) getPivotFieldsIndex(fields []PivotTableField, opts *PivotTableOptions) ([]int, error) {
|
||||
var pivotFieldsIndex []int
|
||||
orders, err := f.getPivotFieldsOrder(opts)
|
||||
if err != nil {
|
||||
|
|
|
@ -25,7 +25,7 @@ func TestAddPivotTable(t *testing.T) {
|
|||
assert.NoError(t, f.SetCellValue("Sheet1", fmt.Sprintf("D%d", row), rand.Intn(5000)))
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", fmt.Sprintf("E%d", row), region[rand.Intn(4)]))
|
||||
}
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOption{
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOptions{
|
||||
DataRange: "Sheet1!$A$1:$E$31",
|
||||
PivotTableRange: "Sheet1!$G$2:$M$34",
|
||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||
|
@ -41,7 +41,7 @@ func TestAddPivotTable(t *testing.T) {
|
|||
ShowError: true,
|
||||
}))
|
||||
// Use different order of coordinate tests
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOption{
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOptions{
|
||||
DataRange: "Sheet1!$A$1:$E$31",
|
||||
PivotTableRange: "Sheet1!$U$34:$O$2",
|
||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||
|
@ -55,7 +55,7 @@ func TestAddPivotTable(t *testing.T) {
|
|||
ShowLastColumn: true,
|
||||
}))
|
||||
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOption{
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOptions{
|
||||
DataRange: "Sheet1!$A$1:$E$31",
|
||||
PivotTableRange: "Sheet1!$W$2:$AC$34",
|
||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||
|
@ -68,7 +68,7 @@ func TestAddPivotTable(t *testing.T) {
|
|||
ShowColHeaders: true,
|
||||
ShowLastColumn: true,
|
||||
}))
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOption{
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOptions{
|
||||
DataRange: "Sheet1!$A$1:$E$31",
|
||||
PivotTableRange: "Sheet1!$G$37:$W$50",
|
||||
Rows: []PivotTableField{{Data: "Month"}},
|
||||
|
@ -81,7 +81,7 @@ func TestAddPivotTable(t *testing.T) {
|
|||
ShowColHeaders: true,
|
||||
ShowLastColumn: true,
|
||||
}))
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOption{
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOptions{
|
||||
DataRange: "Sheet1!$A$1:$E$31",
|
||||
PivotTableRange: "Sheet1!$AE$2:$AG$33",
|
||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||
|
@ -94,7 +94,7 @@ func TestAddPivotTable(t *testing.T) {
|
|||
ShowLastColumn: true,
|
||||
}))
|
||||
// Create pivot table with empty subtotal field name and specified style
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOption{
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOptions{
|
||||
DataRange: "Sheet1!$A$1:$E$31",
|
||||
PivotTableRange: "Sheet1!$AJ$2:$AP1$35",
|
||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||
|
@ -110,7 +110,7 @@ func TestAddPivotTable(t *testing.T) {
|
|||
PivotTableStyleName: "PivotStyleLight19",
|
||||
}))
|
||||
f.NewSheet("Sheet2")
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOption{
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOptions{
|
||||
DataRange: "Sheet1!$A$1:$E$31",
|
||||
PivotTableRange: "Sheet2!$A$1:$AR$15",
|
||||
Rows: []PivotTableField{{Data: "Month"}},
|
||||
|
@ -123,7 +123,7 @@ func TestAddPivotTable(t *testing.T) {
|
|||
ShowColHeaders: true,
|
||||
ShowLastColumn: true,
|
||||
}))
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOption{
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOptions{
|
||||
DataRange: "Sheet1!$A$1:$E$31",
|
||||
PivotTableRange: "Sheet2!$A$18:$AR$54",
|
||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Type"}},
|
||||
|
@ -143,7 +143,7 @@ func TestAddPivotTable(t *testing.T) {
|
|||
Comment: "Pivot Table Data Range",
|
||||
Scope: "Sheet2",
|
||||
}))
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOption{
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOptions{
|
||||
DataRange: "dataRange",
|
||||
PivotTableRange: "Sheet2!$A$57:$AJ$91",
|
||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||
|
@ -160,7 +160,7 @@ func TestAddPivotTable(t *testing.T) {
|
|||
// Test empty pivot table options
|
||||
assert.EqualError(t, f.AddPivotTable(nil), ErrParameterRequired.Error())
|
||||
// Test invalid data range
|
||||
assert.EqualError(t, f.AddPivotTable(&PivotTableOption{
|
||||
assert.EqualError(t, f.AddPivotTable(&PivotTableOptions{
|
||||
DataRange: "Sheet1!$A$1:$A$1",
|
||||
PivotTableRange: "Sheet1!$U$34:$O$2",
|
||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||
|
@ -168,7 +168,7 @@ func TestAddPivotTable(t *testing.T) {
|
|||
Data: []PivotTableField{{Data: "Sales"}},
|
||||
}), `parameter 'DataRange' parsing error: parameter is invalid`)
|
||||
// Test the data range of the worksheet that is not declared
|
||||
assert.EqualError(t, f.AddPivotTable(&PivotTableOption{
|
||||
assert.EqualError(t, f.AddPivotTable(&PivotTableOptions{
|
||||
DataRange: "$A$1:$E$31",
|
||||
PivotTableRange: "Sheet1!$U$34:$O$2",
|
||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||
|
@ -176,7 +176,7 @@ func TestAddPivotTable(t *testing.T) {
|
|||
Data: []PivotTableField{{Data: "Sales"}},
|
||||
}), `parameter 'DataRange' parsing error: parameter is invalid`)
|
||||
// Test the worksheet declared in the data range does not exist
|
||||
assert.EqualError(t, f.AddPivotTable(&PivotTableOption{
|
||||
assert.EqualError(t, f.AddPivotTable(&PivotTableOptions{
|
||||
DataRange: "SheetN!$A$1:$E$31",
|
||||
PivotTableRange: "Sheet1!$U$34:$O$2",
|
||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||
|
@ -184,7 +184,7 @@ func TestAddPivotTable(t *testing.T) {
|
|||
Data: []PivotTableField{{Data: "Sales"}},
|
||||
}), "sheet SheetN does not exist")
|
||||
// Test the pivot table range of the worksheet that is not declared
|
||||
assert.EqualError(t, f.AddPivotTable(&PivotTableOption{
|
||||
assert.EqualError(t, f.AddPivotTable(&PivotTableOptions{
|
||||
DataRange: "Sheet1!$A$1:$E$31",
|
||||
PivotTableRange: "$U$34:$O$2",
|
||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||
|
@ -192,7 +192,7 @@ func TestAddPivotTable(t *testing.T) {
|
|||
Data: []PivotTableField{{Data: "Sales"}},
|
||||
}), `parameter 'PivotTableRange' parsing error: parameter is invalid`)
|
||||
// Test the worksheet declared in the pivot table range does not exist
|
||||
assert.EqualError(t, f.AddPivotTable(&PivotTableOption{
|
||||
assert.EqualError(t, f.AddPivotTable(&PivotTableOptions{
|
||||
DataRange: "Sheet1!$A$1:$E$31",
|
||||
PivotTableRange: "SheetN!$U$34:$O$2",
|
||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||
|
@ -200,7 +200,7 @@ func TestAddPivotTable(t *testing.T) {
|
|||
Data: []PivotTableField{{Data: "Sales"}},
|
||||
}), "sheet SheetN does not exist")
|
||||
// Test not exists worksheet in data range
|
||||
assert.EqualError(t, f.AddPivotTable(&PivotTableOption{
|
||||
assert.EqualError(t, f.AddPivotTable(&PivotTableOptions{
|
||||
DataRange: "SheetN!$A$1:$E$31",
|
||||
PivotTableRange: "Sheet1!$U$34:$O$2",
|
||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||
|
@ -208,7 +208,7 @@ func TestAddPivotTable(t *testing.T) {
|
|||
Data: []PivotTableField{{Data: "Sales"}},
|
||||
}), "sheet SheetN does not exist")
|
||||
// Test invalid row number in data range
|
||||
assert.EqualError(t, f.AddPivotTable(&PivotTableOption{
|
||||
assert.EqualError(t, f.AddPivotTable(&PivotTableOptions{
|
||||
DataRange: "Sheet1!$A$0:$E$31",
|
||||
PivotTableRange: "Sheet1!$U$34:$O$2",
|
||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||
|
@ -217,7 +217,7 @@ func TestAddPivotTable(t *testing.T) {
|
|||
}), `parameter 'DataRange' parsing error: cannot convert cell "A0" to coordinates: invalid cell name "A0"`)
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddPivotTable1.xlsx")))
|
||||
// Test with field names that exceed the length limit and invalid subtotal
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOption{
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOptions{
|
||||
DataRange: "Sheet1!$A$1:$E$31",
|
||||
PivotTableRange: "Sheet1!$G$2:$M$34",
|
||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||
|
@ -232,12 +232,12 @@ func TestAddPivotTable(t *testing.T) {
|
|||
_, _, err = f.adjustRange("sheet1!")
|
||||
assert.EqualError(t, err, "parameter is invalid")
|
||||
// Test get pivot fields order with empty data range
|
||||
_, err = f.getPivotFieldsOrder(&PivotTableOption{})
|
||||
_, err = f.getPivotFieldsOrder(&PivotTableOptions{})
|
||||
assert.EqualError(t, err, `parameter 'DataRange' parsing error: parameter is required`)
|
||||
// Test add pivot cache with empty data range
|
||||
assert.EqualError(t, f.addPivotCache("", &PivotTableOption{}), "parameter 'DataRange' parsing error: parameter is required")
|
||||
assert.EqualError(t, f.addPivotCache("", &PivotTableOptions{}), "parameter 'DataRange' parsing error: parameter is required")
|
||||
// Test add pivot cache with invalid data range
|
||||
assert.EqualError(t, f.addPivotCache("", &PivotTableOption{
|
||||
assert.EqualError(t, f.addPivotCache("", &PivotTableOptions{
|
||||
DataRange: "$A$1:$E$31",
|
||||
PivotTableRange: "Sheet1!$U$34:$O$2",
|
||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||
|
@ -245,11 +245,11 @@ func TestAddPivotTable(t *testing.T) {
|
|||
Data: []PivotTableField{{Data: "Sales"}},
|
||||
}), "parameter 'DataRange' parsing error: parameter is invalid")
|
||||
// Test add pivot table with empty options
|
||||
assert.EqualError(t, f.addPivotTable(0, 0, "", &PivotTableOption{}), "parameter 'PivotTableRange' parsing error: parameter is required")
|
||||
assert.EqualError(t, f.addPivotTable(0, 0, "", &PivotTableOptions{}), "parameter 'PivotTableRange' parsing error: parameter is required")
|
||||
// Test add pivot table with invalid data range
|
||||
assert.EqualError(t, f.addPivotTable(0, 0, "", &PivotTableOption{}), "parameter 'PivotTableRange' parsing error: parameter is required")
|
||||
assert.EqualError(t, f.addPivotTable(0, 0, "", &PivotTableOptions{}), "parameter 'PivotTableRange' parsing error: parameter is required")
|
||||
// Test add pivot fields with empty data range
|
||||
assert.EqualError(t, f.addPivotFields(nil, &PivotTableOption{
|
||||
assert.EqualError(t, f.addPivotFields(nil, &PivotTableOptions{
|
||||
DataRange: "$A$1:$E$31",
|
||||
PivotTableRange: "Sheet1!$U$34:$O$2",
|
||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||
|
@ -257,14 +257,14 @@ func TestAddPivotTable(t *testing.T) {
|
|||
Data: []PivotTableField{{Data: "Sales"}},
|
||||
}), `parameter 'DataRange' parsing error: parameter is invalid`)
|
||||
// Test get pivot fields index with empty data range
|
||||
_, err = f.getPivotFieldsIndex([]PivotTableField{}, &PivotTableOption{})
|
||||
_, err = f.getPivotFieldsIndex([]PivotTableField{}, &PivotTableOptions{})
|
||||
assert.EqualError(t, err, `parameter 'DataRange' parsing error: parameter is required`)
|
||||
}
|
||||
|
||||
func TestAddPivotRowFields(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test invalid data range
|
||||
assert.EqualError(t, f.addPivotRowFields(&xlsxPivotTableDefinition{}, &PivotTableOption{
|
||||
assert.EqualError(t, f.addPivotRowFields(&xlsxPivotTableDefinition{}, &PivotTableOptions{
|
||||
DataRange: "Sheet1!$A$1:$A$1",
|
||||
}), `parameter 'DataRange' parsing error: parameter is invalid`)
|
||||
}
|
||||
|
@ -272,7 +272,7 @@ func TestAddPivotRowFields(t *testing.T) {
|
|||
func TestAddPivotPageFields(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test invalid data range
|
||||
assert.EqualError(t, f.addPivotPageFields(&xlsxPivotTableDefinition{}, &PivotTableOption{
|
||||
assert.EqualError(t, f.addPivotPageFields(&xlsxPivotTableDefinition{}, &PivotTableOptions{
|
||||
DataRange: "Sheet1!$A$1:$A$1",
|
||||
}), `parameter 'DataRange' parsing error: parameter is invalid`)
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ func TestAddPivotPageFields(t *testing.T) {
|
|||
func TestAddPivotDataFields(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test invalid data range
|
||||
assert.EqualError(t, f.addPivotDataFields(&xlsxPivotTableDefinition{}, &PivotTableOption{
|
||||
assert.EqualError(t, f.addPivotDataFields(&xlsxPivotTableDefinition{}, &PivotTableOptions{
|
||||
DataRange: "Sheet1!$A$1:$A$1",
|
||||
}), `parameter 'DataRange' parsing error: parameter is invalid`)
|
||||
}
|
||||
|
@ -288,7 +288,7 @@ func TestAddPivotDataFields(t *testing.T) {
|
|||
func TestAddPivotColFields(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test invalid data range
|
||||
assert.EqualError(t, f.addPivotColFields(&xlsxPivotTableDefinition{}, &PivotTableOption{
|
||||
assert.EqualError(t, f.addPivotColFields(&xlsxPivotTableDefinition{}, &PivotTableOptions{
|
||||
DataRange: "Sheet1!$A$1:$A$1",
|
||||
Columns: []PivotTableField{{Data: "Type", DefaultSubtotal: true}},
|
||||
}), `parameter 'DataRange' parsing error: parameter is invalid`)
|
||||
|
@ -297,7 +297,7 @@ func TestAddPivotColFields(t *testing.T) {
|
|||
func TestGetPivotFieldsOrder(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test get pivot fields order with not exist worksheet
|
||||
_, err := f.getPivotFieldsOrder(&PivotTableOption{DataRange: "SheetN!$A$1:$E$31"})
|
||||
_, err := f.getPivotFieldsOrder(&PivotTableOptions{DataRange: "SheetN!$A$1:$E$31"})
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
}
|
||||
|
||||
|
|
|
@ -165,10 +165,10 @@ func TestRowHeight(t *testing.T) {
|
|||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
|
||||
// Test get row height with custom default row height.
|
||||
assert.NoError(t, f.SetSheetFormatPr(sheet1,
|
||||
DefaultRowHeight(30.0),
|
||||
CustomHeight(true),
|
||||
))
|
||||
assert.NoError(t, f.SetSheetProps(sheet1, &SheetPropsOptions{
|
||||
DefaultRowHeight: float64Ptr(30.0),
|
||||
CustomHeight: boolPtr(true),
|
||||
}))
|
||||
height, err = f.GetRowHeight(sheet1, 100)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 30.0, height)
|
||||
|
|
58
shape.go
58
shape.go
|
@ -17,21 +17,21 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// parseFormatShapeSet provides a function to parse the format settings of the
|
||||
// parseShapeOptions provides a function to parse the format settings of the
|
||||
// shape with default value.
|
||||
func parseFormatShapeSet(formatSet string) (*formatShape, error) {
|
||||
format := formatShape{
|
||||
func parseShapeOptions(opts string) (*shapeOptions, error) {
|
||||
options := shapeOptions{
|
||||
Width: 160,
|
||||
Height: 160,
|
||||
Format: formatPicture{
|
||||
Format: pictureOptions{
|
||||
FPrintsWithSheet: true,
|
||||
XScale: 1,
|
||||
YScale: 1,
|
||||
},
|
||||
Line: formatLine{Width: 1},
|
||||
Line: lineOptions{Width: 1},
|
||||
}
|
||||
err := json.Unmarshal([]byte(formatSet), &format)
|
||||
return &format, err
|
||||
err := json.Unmarshal([]byte(opts), &options)
|
||||
return &options, err
|
||||
}
|
||||
|
||||
// AddShape provides the method to add shape in a sheet by given worksheet
|
||||
|
@ -277,8 +277,8 @@ func parseFormatShapeSet(formatSet string) (*formatShape, error) {
|
|||
// wavy
|
||||
// wavyHeavy
|
||||
// wavyDbl
|
||||
func (f *File) AddShape(sheet, cell, format string) error {
|
||||
formatSet, err := parseFormatShapeSet(format)
|
||||
func (f *File) AddShape(sheet, cell, opts string) error {
|
||||
options, err := parseShapeOptions(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -305,7 +305,7 @@ func (f *File) AddShape(sheet, cell, format string) error {
|
|||
f.addSheetDrawing(sheet, rID)
|
||||
f.addSheetNameSpace(sheet, SourceRelationship)
|
||||
}
|
||||
err = f.addDrawingShape(sheet, drawingXML, cell, formatSet)
|
||||
err = f.addDrawingShape(sheet, drawingXML, cell, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -315,7 +315,7 @@ func (f *File) AddShape(sheet, cell, format string) error {
|
|||
|
||||
// addDrawingShape provides a function to add preset geometry by given sheet,
|
||||
// drawingXMLand format sets.
|
||||
func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *formatShape) error {
|
||||
func (f *File) addDrawingShape(sheet, drawingXML, cell string, opts *shapeOptions) error {
|
||||
fromCol, fromRow, err := CellNameToCoordinates(cell)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -344,19 +344,19 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *format
|
|||
"wavyDbl": true,
|
||||
}
|
||||
|
||||
width := int(float64(formatSet.Width) * formatSet.Format.XScale)
|
||||
height := int(float64(formatSet.Height) * formatSet.Format.YScale)
|
||||
width := int(float64(opts.Width) * opts.Format.XScale)
|
||||
height := int(float64(opts.Height) * opts.Format.YScale)
|
||||
|
||||
colStart, rowStart, colEnd, rowEnd, x2, y2 := f.positionObjectPixels(sheet, colIdx, rowIdx, formatSet.Format.OffsetX, formatSet.Format.OffsetY,
|
||||
colStart, rowStart, colEnd, rowEnd, x2, y2 := f.positionObjectPixels(sheet, colIdx, rowIdx, opts.Format.OffsetX, opts.Format.OffsetY,
|
||||
width, height)
|
||||
content, cNvPrID := f.drawingParser(drawingXML)
|
||||
twoCellAnchor := xdrCellAnchor{}
|
||||
twoCellAnchor.EditAs = formatSet.Format.Positioning
|
||||
twoCellAnchor.EditAs = opts.Format.Positioning
|
||||
from := xlsxFrom{}
|
||||
from.Col = colStart
|
||||
from.ColOff = formatSet.Format.OffsetX * EMU
|
||||
from.ColOff = opts.Format.OffsetX * EMU
|
||||
from.Row = rowStart
|
||||
from.RowOff = formatSet.Format.OffsetY * EMU
|
||||
from.RowOff = opts.Format.OffsetY * EMU
|
||||
to := xlsxTo{}
|
||||
to.Col = colEnd
|
||||
to.ColOff = x2 * EMU
|
||||
|
@ -365,7 +365,7 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *format
|
|||
twoCellAnchor.From = &from
|
||||
twoCellAnchor.To = &to
|
||||
shape := xdrSp{
|
||||
Macro: formatSet.Macro,
|
||||
Macro: opts.Macro,
|
||||
NvSpPr: &xdrNvSpPr{
|
||||
CNvPr: &xlsxCNvPr{
|
||||
ID: cNvPrID,
|
||||
|
@ -377,13 +377,13 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *format
|
|||
},
|
||||
SpPr: &xlsxSpPr{
|
||||
PrstGeom: xlsxPrstGeom{
|
||||
Prst: formatSet.Type,
|
||||
Prst: opts.Type,
|
||||
},
|
||||
},
|
||||
Style: &xdrStyle{
|
||||
LnRef: setShapeRef(formatSet.Color.Line, 2),
|
||||
FillRef: setShapeRef(formatSet.Color.Fill, 1),
|
||||
EffectRef: setShapeRef(formatSet.Color.Effect, 0),
|
||||
LnRef: setShapeRef(opts.Color.Line, 2),
|
||||
FillRef: setShapeRef(opts.Color.Fill, 1),
|
||||
EffectRef: setShapeRef(opts.Color.Effect, 0),
|
||||
FontRef: &aFontRef{
|
||||
Idx: "minor",
|
||||
SchemeClr: &attrValString{
|
||||
|
@ -401,13 +401,13 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *format
|
|||
},
|
||||
},
|
||||
}
|
||||
if formatSet.Line.Width != 1 {
|
||||
if opts.Line.Width != 1 {
|
||||
shape.SpPr.Ln = xlsxLineProperties{
|
||||
W: f.ptToEMUs(formatSet.Line.Width),
|
||||
W: f.ptToEMUs(opts.Line.Width),
|
||||
}
|
||||
}
|
||||
if len(formatSet.Paragraph) < 1 {
|
||||
formatSet.Paragraph = []formatShapeParagraph{
|
||||
if len(opts.Paragraph) < 1 {
|
||||
opts.Paragraph = []shapeParagraphOptions{
|
||||
{
|
||||
Font: Font{
|
||||
Bold: false,
|
||||
|
@ -421,7 +421,7 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *format
|
|||
},
|
||||
}
|
||||
}
|
||||
for _, p := range formatSet.Paragraph {
|
||||
for _, p := range opts.Paragraph {
|
||||
u := p.Font.Underline
|
||||
_, ok := textUnderlineType[u]
|
||||
if !ok {
|
||||
|
@ -460,8 +460,8 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *format
|
|||
}
|
||||
twoCellAnchor.Sp = &shape
|
||||
twoCellAnchor.ClientData = &xdrClientData{
|
||||
FLocksWithSheet: formatSet.Format.FLocksWithSheet,
|
||||
FPrintsWithSheet: formatSet.Format.FPrintsWithSheet,
|
||||
FLocksWithSheet: opts.Format.FLocksWithSheet,
|
||||
FPrintsWithSheet: opts.Format.FPrintsWithSheet,
|
||||
}
|
||||
content.TwoCellAnchor = append(content.TwoCellAnchor, &twoCellAnchor)
|
||||
f.Drawings.Store(drawingXML, content)
|
||||
|
|
328
sheet.go
328
sheet.go
|
@ -38,10 +38,10 @@ import (
|
|||
// Note that when creating a new workbook, the default worksheet named
|
||||
// `Sheet1` will be created.
|
||||
func (f *File) NewSheet(sheet string) int {
|
||||
// Check if the worksheet already exists
|
||||
if trimSheetName(sheet) == "" {
|
||||
return -1
|
||||
}
|
||||
// Check if the worksheet already exists
|
||||
index := f.GetSheetIndex(sheet)
|
||||
if index != -1 {
|
||||
return index
|
||||
|
@ -675,10 +675,10 @@ func (f *File) SetSheetVisible(sheet string, visible bool) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// parseFormatPanesSet provides a function to parse the panes settings.
|
||||
func parseFormatPanesSet(formatSet string) (*formatPanes, error) {
|
||||
format := formatPanes{}
|
||||
err := json.Unmarshal([]byte(formatSet), &format)
|
||||
// parsePanesOptions provides a function to parse the panes settings.
|
||||
func parsePanesOptions(opts string) (*panesOptions, error) {
|
||||
format := panesOptions{}
|
||||
err := json.Unmarshal([]byte(opts), &format)
|
||||
return &format, err
|
||||
}
|
||||
|
||||
|
@ -767,7 +767,7 @@ func parseFormatPanesSet(formatSet string) (*formatPanes, error) {
|
|||
//
|
||||
// f.SetPanes("Sheet1", `{"freeze":false,"split":false}`)
|
||||
func (f *File) SetPanes(sheet, panes string) error {
|
||||
fs, _ := parseFormatPanesSet(panes)
|
||||
fs, _ := parsePanesOptions(panes)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1021,7 +1021,7 @@ func attrValToBool(name string, attrs []xml.Attr) (val bool, err error) {
|
|||
// |
|
||||
// &R | Right section
|
||||
// |
|
||||
// &S | Strikethrough text format
|
||||
// &S | Strike through text format
|
||||
// |
|
||||
// &T | Current time
|
||||
// |
|
||||
|
@ -1068,7 +1068,7 @@ func attrValToBool(name string, attrs []xml.Attr) (val bool, err error) {
|
|||
// that same page
|
||||
//
|
||||
// - No footer on the first page
|
||||
func (f *File) SetHeaderFooter(sheet string, settings *FormatHeaderFooter) error {
|
||||
func (f *File) SetHeaderFooter(sheet string, settings *HeaderFooterOptions) error {
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1113,13 +1113,13 @@ func (f *File) SetHeaderFooter(sheet string, settings *FormatHeaderFooter) error
|
|||
// Password: "password",
|
||||
// EditScenarios: false,
|
||||
// })
|
||||
func (f *File) ProtectSheet(sheet string, settings *FormatSheetProtection) error {
|
||||
func (f *File) ProtectSheet(sheet string, settings *SheetProtectionOptions) error {
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if settings == nil {
|
||||
settings = &FormatSheetProtection{
|
||||
settings = &SheetProtectionOptions{
|
||||
EditObjects: true,
|
||||
EditScenarios: true,
|
||||
SelectLockedCells: true,
|
||||
|
@ -1213,173 +1213,8 @@ func trimSheetName(name string) string {
|
|||
return name
|
||||
}
|
||||
|
||||
// PageLayoutOption is an option of a page layout of a worksheet. See
|
||||
// SetPageLayout().
|
||||
type PageLayoutOption interface {
|
||||
setPageLayout(layout *xlsxPageSetUp)
|
||||
}
|
||||
|
||||
// PageLayoutOptionPtr is a writable PageLayoutOption. See GetPageLayout().
|
||||
type PageLayoutOptionPtr interface {
|
||||
PageLayoutOption
|
||||
getPageLayout(layout *xlsxPageSetUp)
|
||||
}
|
||||
|
||||
type (
|
||||
// BlackAndWhite specified print black and white.
|
||||
BlackAndWhite bool
|
||||
// FirstPageNumber specified the first printed page number. If no value is
|
||||
// specified, then 'automatic' is assumed.
|
||||
FirstPageNumber uint
|
||||
// PageLayoutOrientation defines the orientation of page layout for a
|
||||
// worksheet.
|
||||
PageLayoutOrientation string
|
||||
// PageLayoutPaperSize defines the paper size of the worksheet.
|
||||
PageLayoutPaperSize int
|
||||
// FitToHeight specified the number of vertical pages to fit on.
|
||||
FitToHeight int
|
||||
// FitToWidth specified the number of horizontal pages to fit on.
|
||||
FitToWidth int
|
||||
// PageLayoutScale defines the print scaling. This attribute is restricted
|
||||
// to value ranging from 10 (10%) to 400 (400%). This setting is
|
||||
// overridden when fitToWidth and/or fitToHeight are in use.
|
||||
PageLayoutScale uint
|
||||
)
|
||||
|
||||
const (
|
||||
// OrientationPortrait indicates page layout orientation id portrait.
|
||||
OrientationPortrait = "portrait"
|
||||
// OrientationLandscape indicates page layout orientation id landscape.
|
||||
OrientationLandscape = "landscape"
|
||||
)
|
||||
|
||||
// setPageLayout provides a method to set the print black and white for the
|
||||
// worksheet.
|
||||
func (p BlackAndWhite) setPageLayout(ps *xlsxPageSetUp) {
|
||||
ps.BlackAndWhite = bool(p)
|
||||
}
|
||||
|
||||
// getPageLayout provides a method to get the print black and white for the
|
||||
// worksheet.
|
||||
func (p *BlackAndWhite) getPageLayout(ps *xlsxPageSetUp) {
|
||||
if ps == nil {
|
||||
*p = false
|
||||
return
|
||||
}
|
||||
*p = BlackAndWhite(ps.BlackAndWhite)
|
||||
}
|
||||
|
||||
// setPageLayout provides a method to set the first printed page number for
|
||||
// the worksheet.
|
||||
func (p FirstPageNumber) setPageLayout(ps *xlsxPageSetUp) {
|
||||
if 0 < int(p) {
|
||||
ps.FirstPageNumber = strconv.Itoa(int(p))
|
||||
ps.UseFirstPageNumber = true
|
||||
}
|
||||
}
|
||||
|
||||
// getPageLayout provides a method to get the first printed page number for
|
||||
// the worksheet.
|
||||
func (p *FirstPageNumber) getPageLayout(ps *xlsxPageSetUp) {
|
||||
if ps != nil && ps.UseFirstPageNumber {
|
||||
if number, _ := strconv.Atoi(ps.FirstPageNumber); number != 0 {
|
||||
*p = FirstPageNumber(number)
|
||||
return
|
||||
}
|
||||
}
|
||||
*p = 1
|
||||
}
|
||||
|
||||
// setPageLayout provides a method to set the orientation for the worksheet.
|
||||
func (o PageLayoutOrientation) setPageLayout(ps *xlsxPageSetUp) {
|
||||
ps.Orientation = string(o)
|
||||
}
|
||||
|
||||
// getPageLayout provides a method to get the orientation for the worksheet.
|
||||
func (o *PageLayoutOrientation) getPageLayout(ps *xlsxPageSetUp) {
|
||||
// Excel default: portrait
|
||||
if ps == nil || ps.Orientation == "" {
|
||||
*o = OrientationPortrait
|
||||
return
|
||||
}
|
||||
*o = PageLayoutOrientation(ps.Orientation)
|
||||
}
|
||||
|
||||
// setPageLayout provides a method to set the paper size for the worksheet.
|
||||
func (p PageLayoutPaperSize) setPageLayout(ps *xlsxPageSetUp) {
|
||||
ps.PaperSize = intPtr(int(p))
|
||||
}
|
||||
|
||||
// getPageLayout provides a method to get the paper size for the worksheet.
|
||||
func (p *PageLayoutPaperSize) getPageLayout(ps *xlsxPageSetUp) {
|
||||
// Excel default: 1
|
||||
if ps == nil || ps.PaperSize == nil {
|
||||
*p = 1
|
||||
return
|
||||
}
|
||||
*p = PageLayoutPaperSize(*ps.PaperSize)
|
||||
}
|
||||
|
||||
// setPageLayout provides a method to set the fit to height for the worksheet.
|
||||
func (p FitToHeight) setPageLayout(ps *xlsxPageSetUp) {
|
||||
if int(p) > 0 {
|
||||
ps.FitToHeight = intPtr(int(p))
|
||||
}
|
||||
}
|
||||
|
||||
// getPageLayout provides a method to get the fit to height for the worksheet.
|
||||
func (p *FitToHeight) getPageLayout(ps *xlsxPageSetUp) {
|
||||
if ps == nil || ps.FitToHeight == nil {
|
||||
*p = 1
|
||||
return
|
||||
}
|
||||
*p = FitToHeight(*ps.FitToHeight)
|
||||
}
|
||||
|
||||
// setPageLayout provides a method to set the fit to width for the worksheet.
|
||||
func (p FitToWidth) setPageLayout(ps *xlsxPageSetUp) {
|
||||
if int(p) > 0 {
|
||||
ps.FitToWidth = intPtr(int(p))
|
||||
}
|
||||
}
|
||||
|
||||
// getPageLayout provides a method to get the fit to width for the worksheet.
|
||||
func (p *FitToWidth) getPageLayout(ps *xlsxPageSetUp) {
|
||||
if ps == nil || ps.FitToWidth == nil {
|
||||
*p = 1
|
||||
return
|
||||
}
|
||||
*p = FitToWidth(*ps.FitToWidth)
|
||||
}
|
||||
|
||||
// setPageLayout provides a method to set the scale for the worksheet.
|
||||
func (p PageLayoutScale) setPageLayout(ps *xlsxPageSetUp) {
|
||||
if 10 <= int(p) && int(p) <= 400 {
|
||||
ps.Scale = int(p)
|
||||
}
|
||||
}
|
||||
|
||||
// getPageLayout provides a method to get the scale for the worksheet.
|
||||
func (p *PageLayoutScale) getPageLayout(ps *xlsxPageSetUp) {
|
||||
if ps == nil || ps.Scale < 10 || ps.Scale > 400 {
|
||||
*p = 100
|
||||
return
|
||||
}
|
||||
*p = PageLayoutScale(ps.Scale)
|
||||
}
|
||||
|
||||
// SetPageLayout provides a function to sets worksheet page layout.
|
||||
//
|
||||
// Available options:
|
||||
//
|
||||
// BlackAndWhite(bool)
|
||||
// FirstPageNumber(uint)
|
||||
// PageLayoutOrientation(string)
|
||||
// PageLayoutPaperSize(int)
|
||||
// FitToHeight(int)
|
||||
// FitToWidth(int)
|
||||
// PageLayoutScale(uint)
|
||||
//
|
||||
// The following shows the paper size sorted by excelize index number:
|
||||
//
|
||||
// Index | Paper Size
|
||||
|
@ -1500,42 +1335,93 @@ func (p *PageLayoutScale) getPageLayout(ps *xlsxPageSetUp) {
|
|||
// 116 | PRC Envelope #8 Rotated (309 mm x 120 mm)
|
||||
// 117 | PRC Envelope #9 Rotated (324 mm x 229 mm)
|
||||
// 118 | PRC Envelope #10 Rotated (458 mm x 324 mm)
|
||||
func (f *File) SetPageLayout(sheet string, opts ...PageLayoutOption) error {
|
||||
s, err := f.workSheetReader(sheet)
|
||||
func (f *File) SetPageLayout(sheet string, opts *PageLayoutOptions) error {
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ps := s.PageSetUp
|
||||
if ps == nil {
|
||||
ps = new(xlsxPageSetUp)
|
||||
s.PageSetUp = ps
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt.setPageLayout(ps)
|
||||
if opts == nil {
|
||||
return err
|
||||
}
|
||||
ws.setPageSetUp(opts)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetPageLayout provides a function to gets worksheet page layout.
|
||||
//
|
||||
// Available options:
|
||||
//
|
||||
// PageLayoutOrientation(string)
|
||||
// PageLayoutPaperSize(int)
|
||||
// FitToHeight(int)
|
||||
// FitToWidth(int)
|
||||
func (f *File) GetPageLayout(sheet string, opts ...PageLayoutOptionPtr) error {
|
||||
s, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
// newPageSetUp initialize page setup settings for the worksheet if which not
|
||||
// exist.
|
||||
func (ws *xlsxWorksheet) newPageSetUp() {
|
||||
if ws.PageSetUp == nil {
|
||||
ws.PageSetUp = new(xlsxPageSetUp)
|
||||
}
|
||||
ps := s.PageSetUp
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt.getPageLayout(ps)
|
||||
// setPageSetUp set page setup settings for the worksheet by given options.
|
||||
func (ws *xlsxWorksheet) setPageSetUp(opts *PageLayoutOptions) {
|
||||
if opts.Size != nil {
|
||||
ws.newPageSetUp()
|
||||
ws.PageSetUp.PaperSize = opts.Size
|
||||
}
|
||||
return err
|
||||
if opts.Orientation != nil && (*opts.Orientation == "portrait" || *opts.Orientation == "landscape") {
|
||||
ws.newPageSetUp()
|
||||
ws.PageSetUp.Orientation = *opts.Orientation
|
||||
}
|
||||
if opts.FirstPageNumber != nil && *opts.FirstPageNumber > 0 {
|
||||
ws.newPageSetUp()
|
||||
ws.PageSetUp.FirstPageNumber = strconv.Itoa(int(*opts.FirstPageNumber))
|
||||
ws.PageSetUp.UseFirstPageNumber = true
|
||||
}
|
||||
if opts.AdjustTo != nil && 10 <= *opts.AdjustTo && *opts.AdjustTo <= 400 {
|
||||
ws.newPageSetUp()
|
||||
ws.PageSetUp.Scale = int(*opts.AdjustTo)
|
||||
}
|
||||
if opts.FitToHeight != nil {
|
||||
ws.newPageSetUp()
|
||||
ws.PageSetUp.FitToHeight = opts.FitToHeight
|
||||
}
|
||||
if opts.FitToWidth != nil {
|
||||
ws.newPageSetUp()
|
||||
ws.PageSetUp.FitToWidth = opts.FitToWidth
|
||||
}
|
||||
if opts.BlackAndWhite != nil {
|
||||
ws.newPageSetUp()
|
||||
ws.PageSetUp.BlackAndWhite = *opts.BlackAndWhite
|
||||
}
|
||||
}
|
||||
|
||||
// GetPageLayout provides a function to gets worksheet page layout.
|
||||
func (f *File) GetPageLayout(sheet string) (PageLayoutOptions, error) {
|
||||
opts := PageLayoutOptions{
|
||||
Size: intPtr(0),
|
||||
Orientation: stringPtr("portrait"),
|
||||
FirstPageNumber: uintPtr(1),
|
||||
AdjustTo: uintPtr(100),
|
||||
}
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return opts, err
|
||||
}
|
||||
if ws.PageSetUp != nil {
|
||||
if ws.PageSetUp.PaperSize != nil {
|
||||
opts.Size = ws.PageSetUp.PaperSize
|
||||
}
|
||||
if ws.PageSetUp.Orientation != "" {
|
||||
opts.Orientation = stringPtr(ws.PageSetUp.Orientation)
|
||||
}
|
||||
if num, _ := strconv.Atoi(ws.PageSetUp.FirstPageNumber); num != 0 {
|
||||
opts.FirstPageNumber = uintPtr(uint(num))
|
||||
}
|
||||
if ws.PageSetUp.Scale >= 10 && ws.PageSetUp.Scale <= 400 {
|
||||
opts.AdjustTo = uintPtr(uint(ws.PageSetUp.Scale))
|
||||
}
|
||||
if ws.PageSetUp.FitToHeight != nil {
|
||||
opts.FitToHeight = ws.PageSetUp.FitToHeight
|
||||
}
|
||||
if ws.PageSetUp.FitToWidth != nil {
|
||||
opts.FitToWidth = ws.PageSetUp.FitToWidth
|
||||
}
|
||||
opts.BlackAndWhite = boolPtr(ws.PageSetUp.BlackAndWhite)
|
||||
}
|
||||
return opts, err
|
||||
}
|
||||
|
||||
// SetDefinedName provides a function to set the defined names of the workbook
|
||||
|
@ -1690,20 +1576,23 @@ func (f *File) UngroupSheets() error {
|
|||
// ends and where begins the next one by given worksheet name and cell reference, so the
|
||||
// content before the page break will be printed on one page and after the
|
||||
// page break on another.
|
||||
func (f *File) InsertPageBreak(sheet, cell string) (err error) {
|
||||
var ws *xlsxWorksheet
|
||||
var row, col int
|
||||
func (f *File) InsertPageBreak(sheet, cell string) error {
|
||||
var (
|
||||
ws *xlsxWorksheet
|
||||
row, col int
|
||||
err error
|
||||
)
|
||||
rowBrk, colBrk := -1, -1
|
||||
if ws, err = f.workSheetReader(sheet); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if col, row, err = CellNameToCoordinates(cell); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
col--
|
||||
row--
|
||||
if col == row && col == 0 {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if ws.RowBreaks == nil {
|
||||
ws.RowBreaks = &xlsxBreaks{}
|
||||
|
@ -1741,24 +1630,27 @@ func (f *File) InsertPageBreak(sheet, cell string) (err error) {
|
|||
}
|
||||
ws.RowBreaks.Count = len(ws.RowBreaks.Brk)
|
||||
ws.ColBreaks.Count = len(ws.ColBreaks.Brk)
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
// RemovePageBreak remove a page break by given worksheet name and cell
|
||||
// reference.
|
||||
func (f *File) RemovePageBreak(sheet, cell string) (err error) {
|
||||
var ws *xlsxWorksheet
|
||||
var row, col int
|
||||
func (f *File) RemovePageBreak(sheet, cell string) error {
|
||||
var (
|
||||
ws *xlsxWorksheet
|
||||
row, col int
|
||||
err error
|
||||
)
|
||||
if ws, err = f.workSheetReader(sheet); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if col, row, err = CellNameToCoordinates(cell); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
col--
|
||||
row--
|
||||
if col == row && col == 0 {
|
||||
return
|
||||
return err
|
||||
}
|
||||
removeBrk := func(ID int, brks []*xlsxBrk) []*xlsxBrk {
|
||||
for i, brk := range brks {
|
||||
|
@ -1769,7 +1661,7 @@ func (f *File) RemovePageBreak(sheet, cell string) (err error) {
|
|||
return brks
|
||||
}
|
||||
if ws.RowBreaks == nil || ws.ColBreaks == nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
rowBrks := len(ws.RowBreaks.Brk)
|
||||
colBrks := len(ws.ColBreaks.Brk)
|
||||
|
@ -1780,20 +1672,20 @@ func (f *File) RemovePageBreak(sheet, cell string) (err error) {
|
|||
ws.ColBreaks.Count = len(ws.ColBreaks.Brk)
|
||||
ws.RowBreaks.ManualBreakCount--
|
||||
ws.ColBreaks.ManualBreakCount--
|
||||
return
|
||||
return err
|
||||
}
|
||||
if rowBrks > 0 && rowBrks > colBrks {
|
||||
ws.RowBreaks.Brk = removeBrk(row, ws.RowBreaks.Brk)
|
||||
ws.RowBreaks.Count = len(ws.RowBreaks.Brk)
|
||||
ws.RowBreaks.ManualBreakCount--
|
||||
return
|
||||
return err
|
||||
}
|
||||
if colBrks > 0 && colBrks > rowBrks {
|
||||
ws.ColBreaks.Brk = removeBrk(col, ws.ColBreaks.Brk)
|
||||
ws.ColBreaks.Count = len(ws.ColBreaks.Brk)
|
||||
ws.ColBreaks.ManualBreakCount--
|
||||
}
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
// relsReader provides a function to get the pointer to the structure
|
||||
|
|
159
sheet_test.go
159
sheet_test.go
|
@ -8,78 +8,9 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/mohae/deepcopy"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func ExampleFile_SetPageLayout() {
|
||||
f := NewFile()
|
||||
if err := f.SetPageLayout(
|
||||
"Sheet1",
|
||||
BlackAndWhite(true),
|
||||
FirstPageNumber(2),
|
||||
PageLayoutOrientation(OrientationLandscape),
|
||||
PageLayoutPaperSize(10),
|
||||
FitToHeight(2),
|
||||
FitToWidth(2),
|
||||
PageLayoutScale(50),
|
||||
); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
// Output:
|
||||
}
|
||||
|
||||
func ExampleFile_GetPageLayout() {
|
||||
f := NewFile()
|
||||
var (
|
||||
blackAndWhite BlackAndWhite
|
||||
firstPageNumber FirstPageNumber
|
||||
orientation PageLayoutOrientation
|
||||
paperSize PageLayoutPaperSize
|
||||
fitToHeight FitToHeight
|
||||
fitToWidth FitToWidth
|
||||
scale PageLayoutScale
|
||||
)
|
||||
if err := f.GetPageLayout("Sheet1", &blackAndWhite); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err := f.GetPageLayout("Sheet1", &firstPageNumber); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err := f.GetPageLayout("Sheet1", &orientation); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err := f.GetPageLayout("Sheet1", &paperSize); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err := f.GetPageLayout("Sheet1", &fitToHeight); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err := f.GetPageLayout("Sheet1", &fitToWidth); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err := f.GetPageLayout("Sheet1", &scale); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println("Defaults:")
|
||||
fmt.Printf("- print black and white: %t\n", blackAndWhite)
|
||||
fmt.Printf("- page number for first printed page: %d\n", firstPageNumber)
|
||||
fmt.Printf("- orientation: %q\n", orientation)
|
||||
fmt.Printf("- paper size: %d\n", paperSize)
|
||||
fmt.Printf("- fit to height: %d\n", fitToHeight)
|
||||
fmt.Printf("- fit to width: %d\n", fitToWidth)
|
||||
fmt.Printf("- scale: %d\n", scale)
|
||||
// Output:
|
||||
// Defaults:
|
||||
// - print black and white: false
|
||||
// - page number for first printed page: 1
|
||||
// - orientation: "portrait"
|
||||
// - paper size: 1
|
||||
// - fit to height: 1
|
||||
// - fit to width: 1
|
||||
// - scale: 100
|
||||
}
|
||||
|
||||
func TestNewSheet(t *testing.T) {
|
||||
f := NewFile()
|
||||
f.NewSheet("Sheet2")
|
||||
|
@ -114,68 +45,6 @@ func TestSetPane(t *testing.T) {
|
|||
assert.NoError(t, f.SetPanes("Sheet1", `{"freeze":true,"split":false,"x_split":1,"y_split":0,"top_left_cell":"B1","active_pane":"topRight","panes":[{"sqref":"K16","active_cell":"K16","pane":"topRight"}]}`))
|
||||
}
|
||||
|
||||
func TestPageLayoutOption(t *testing.T) {
|
||||
const sheet = "Sheet1"
|
||||
|
||||
testData := []struct {
|
||||
container PageLayoutOptionPtr
|
||||
nonDefault PageLayoutOption
|
||||
}{
|
||||
{new(BlackAndWhite), BlackAndWhite(true)},
|
||||
{new(FirstPageNumber), FirstPageNumber(2)},
|
||||
{new(PageLayoutOrientation), PageLayoutOrientation(OrientationLandscape)},
|
||||
{new(PageLayoutPaperSize), PageLayoutPaperSize(10)},
|
||||
{new(FitToHeight), FitToHeight(2)},
|
||||
{new(FitToWidth), FitToWidth(2)},
|
||||
{new(PageLayoutScale), PageLayoutScale(50)},
|
||||
}
|
||||
|
||||
for i, test := range testData {
|
||||
t.Run(fmt.Sprintf("TestData%d", i), func(t *testing.T) {
|
||||
opts := test.nonDefault
|
||||
t.Logf("option %T", opts)
|
||||
|
||||
def := deepcopy.Copy(test.container).(PageLayoutOptionPtr)
|
||||
val1 := deepcopy.Copy(def).(PageLayoutOptionPtr)
|
||||
val2 := deepcopy.Copy(def).(PageLayoutOptionPtr)
|
||||
|
||||
f := NewFile()
|
||||
// Get the default value
|
||||
assert.NoError(t, f.GetPageLayout(sheet, def), opts)
|
||||
// Get again and check
|
||||
assert.NoError(t, f.GetPageLayout(sheet, val1), opts)
|
||||
if !assert.Equal(t, val1, def, opts) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Set the same value
|
||||
assert.NoError(t, f.SetPageLayout(sheet, val1), opts)
|
||||
// Get again and check
|
||||
assert.NoError(t, f.GetPageLayout(sheet, val1), opts)
|
||||
if !assert.Equal(t, val1, def, "%T: value should not have changed", opts) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Set a different value
|
||||
assert.NoError(t, f.SetPageLayout(sheet, test.nonDefault), opts)
|
||||
assert.NoError(t, f.GetPageLayout(sheet, val1), opts)
|
||||
// Get again and compare
|
||||
assert.NoError(t, f.GetPageLayout(sheet, val2), opts)
|
||||
if !assert.Equal(t, val1, val2, "%T: value should not have changed", opts) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Value should not be the same as the default
|
||||
if !assert.NotEqual(t, def, val1, "%T: value should have changed from default", opts) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Restore the default value
|
||||
assert.NoError(t, f.SetPageLayout(sheet, def), opts)
|
||||
assert.NoError(t, f.GetPageLayout(sheet, val1), opts)
|
||||
if !assert.Equal(t, def, val1) {
|
||||
t.FailNow()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSearchSheet(t *testing.T) {
|
||||
f, err := OpenFile(filepath.Join("test", "SharedStrings.xlsx"))
|
||||
if !assert.NoError(t, err) {
|
||||
|
@ -226,14 +95,32 @@ func TestSearchSheet(t *testing.T) {
|
|||
|
||||
func TestSetPageLayout(t *testing.T) {
|
||||
f := NewFile()
|
||||
assert.NoError(t, f.SetPageLayout("Sheet1", nil))
|
||||
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
|
||||
assert.True(t, ok)
|
||||
ws.(*xlsxWorksheet).PageSetUp = nil
|
||||
expected := PageLayoutOptions{
|
||||
Size: intPtr(1),
|
||||
Orientation: stringPtr("landscape"),
|
||||
FirstPageNumber: uintPtr(1),
|
||||
AdjustTo: uintPtr(120),
|
||||
FitToHeight: intPtr(2),
|
||||
FitToWidth: intPtr(2),
|
||||
BlackAndWhite: boolPtr(true),
|
||||
}
|
||||
assert.NoError(t, f.SetPageLayout("Sheet1", &expected))
|
||||
opts, err := f.GetPageLayout("Sheet1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, opts)
|
||||
// Test set page layout on not exists worksheet.
|
||||
assert.EqualError(t, f.SetPageLayout("SheetN"), "sheet SheetN does not exist")
|
||||
assert.EqualError(t, f.SetPageLayout("SheetN", nil), "sheet SheetN does not exist")
|
||||
}
|
||||
|
||||
func TestGetPageLayout(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test get page layout on not exists worksheet.
|
||||
assert.EqualError(t, f.GetPageLayout("SheetN"), "sheet SheetN does not exist")
|
||||
_, err := f.GetPageLayout("SheetN")
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
}
|
||||
|
||||
func TestSetHeaderFooter(t *testing.T) {
|
||||
|
@ -242,20 +129,20 @@ func TestSetHeaderFooter(t *testing.T) {
|
|||
// Test set header and footer on not exists worksheet.
|
||||
assert.EqualError(t, f.SetHeaderFooter("SheetN", nil), "sheet SheetN does not exist")
|
||||
// Test set header and footer with illegal setting.
|
||||
assert.EqualError(t, f.SetHeaderFooter("Sheet1", &FormatHeaderFooter{
|
||||
assert.EqualError(t, f.SetHeaderFooter("Sheet1", &HeaderFooterOptions{
|
||||
OddHeader: strings.Repeat("c", MaxFieldLength+1),
|
||||
}), newFieldLengthError("OddHeader").Error())
|
||||
|
||||
assert.NoError(t, f.SetHeaderFooter("Sheet1", nil))
|
||||
text := strings.Repeat("一", MaxFieldLength)
|
||||
assert.NoError(t, f.SetHeaderFooter("Sheet1", &FormatHeaderFooter{
|
||||
assert.NoError(t, f.SetHeaderFooter("Sheet1", &HeaderFooterOptions{
|
||||
OddHeader: text,
|
||||
OddFooter: text,
|
||||
EvenHeader: text,
|
||||
EvenFooter: text,
|
||||
FirstHeader: text,
|
||||
}))
|
||||
assert.NoError(t, f.SetHeaderFooter("Sheet1", &FormatHeaderFooter{
|
||||
assert.NoError(t, f.SetHeaderFooter("Sheet1", &HeaderFooterOptions{
|
||||
DifferentFirst: true,
|
||||
DifferentOddEven: true,
|
||||
OddHeader: "&R&P",
|
||||
|
|
844
sheetpr.go
844
sheetpr.go
|
@ -11,647 +11,249 @@
|
|||
|
||||
package excelize
|
||||
|
||||
import "strings"
|
||||
|
||||
// SheetPrOption is an option of a view of a worksheet. See SetSheetPrOptions().
|
||||
type SheetPrOption interface {
|
||||
setSheetPrOption(view *xlsxSheetPr)
|
||||
}
|
||||
|
||||
// SheetPrOptionPtr is a writable SheetPrOption. See GetSheetPrOptions().
|
||||
type SheetPrOptionPtr interface {
|
||||
SheetPrOption
|
||||
getSheetPrOption(view *xlsxSheetPr)
|
||||
}
|
||||
|
||||
type (
|
||||
// CodeName is an option used for SheetPrOption and WorkbookPrOption
|
||||
CodeName string
|
||||
// EnableFormatConditionsCalculation is a SheetPrOption
|
||||
EnableFormatConditionsCalculation bool
|
||||
// Published is a SheetPrOption
|
||||
Published bool
|
||||
// FitToPage is a SheetPrOption
|
||||
FitToPage bool
|
||||
// TabColorIndexed is a TabColor option, within SheetPrOption
|
||||
TabColorIndexed int
|
||||
// TabColorRGB is a TabColor option, within SheetPrOption
|
||||
TabColorRGB string
|
||||
// TabColorTheme is a TabColor option, within SheetPrOption
|
||||
TabColorTheme int
|
||||
// TabColorTint is a TabColor option, within SheetPrOption
|
||||
TabColorTint float64
|
||||
// AutoPageBreaks is a SheetPrOption
|
||||
AutoPageBreaks bool
|
||||
// OutlineSummaryBelow is an outlinePr, within SheetPr option
|
||||
OutlineSummaryBelow bool
|
||||
)
|
||||
|
||||
// setSheetPrOption implements the SheetPrOption interface.
|
||||
func (o OutlineSummaryBelow) setSheetPrOption(pr *xlsxSheetPr) {
|
||||
if pr.OutlinePr == nil {
|
||||
pr.OutlinePr = new(xlsxOutlinePr)
|
||||
}
|
||||
pr.OutlinePr.SummaryBelow = bool(o)
|
||||
}
|
||||
|
||||
// getSheetPrOption implements the SheetPrOptionPtr interface.
|
||||
func (o *OutlineSummaryBelow) getSheetPrOption(pr *xlsxSheetPr) {
|
||||
// Excel default: true
|
||||
if pr == nil || pr.OutlinePr == nil {
|
||||
*o = true
|
||||
return
|
||||
}
|
||||
*o = OutlineSummaryBelow(defaultTrue(&pr.OutlinePr.SummaryBelow))
|
||||
}
|
||||
|
||||
// setSheetPrOption implements the SheetPrOption interface and specifies a
|
||||
// stable name of the sheet.
|
||||
func (o CodeName) setSheetPrOption(pr *xlsxSheetPr) {
|
||||
pr.CodeName = string(o)
|
||||
}
|
||||
|
||||
// getSheetPrOption implements the SheetPrOptionPtr interface and get the
|
||||
// stable name of the sheet.
|
||||
func (o *CodeName) getSheetPrOption(pr *xlsxSheetPr) {
|
||||
if pr == nil {
|
||||
*o = ""
|
||||
return
|
||||
}
|
||||
*o = CodeName(pr.CodeName)
|
||||
}
|
||||
|
||||
// setSheetPrOption implements the SheetPrOption interface and flag indicating
|
||||
// whether the conditional formatting calculations shall be evaluated.
|
||||
func (o EnableFormatConditionsCalculation) setSheetPrOption(pr *xlsxSheetPr) {
|
||||
pr.EnableFormatConditionsCalculation = boolPtr(bool(o))
|
||||
}
|
||||
|
||||
// getSheetPrOption implements the SheetPrOptionPtr interface and get the
|
||||
// settings of whether the conditional formatting calculations shall be
|
||||
// evaluated.
|
||||
func (o *EnableFormatConditionsCalculation) getSheetPrOption(pr *xlsxSheetPr) {
|
||||
if pr == nil {
|
||||
*o = true
|
||||
return
|
||||
}
|
||||
*o = EnableFormatConditionsCalculation(defaultTrue(pr.EnableFormatConditionsCalculation))
|
||||
}
|
||||
|
||||
// setSheetPrOption implements the SheetPrOption interface and flag indicating
|
||||
// whether the worksheet is published.
|
||||
func (o Published) setSheetPrOption(pr *xlsxSheetPr) {
|
||||
pr.Published = boolPtr(bool(o))
|
||||
}
|
||||
|
||||
// getSheetPrOption implements the SheetPrOptionPtr interface and get the
|
||||
// settings of whether the worksheet is published.
|
||||
func (o *Published) getSheetPrOption(pr *xlsxSheetPr) {
|
||||
if pr == nil {
|
||||
*o = true
|
||||
return
|
||||
}
|
||||
*o = Published(defaultTrue(pr.Published))
|
||||
}
|
||||
|
||||
// setSheetPrOption implements the SheetPrOption interface.
|
||||
func (o FitToPage) setSheetPrOption(pr *xlsxSheetPr) {
|
||||
if pr.PageSetUpPr == nil {
|
||||
if !o {
|
||||
return
|
||||
}
|
||||
pr.PageSetUpPr = new(xlsxPageSetUpPr)
|
||||
}
|
||||
pr.PageSetUpPr.FitToPage = bool(o)
|
||||
}
|
||||
|
||||
// getSheetPrOption implements the SheetPrOptionPtr interface.
|
||||
func (o *FitToPage) getSheetPrOption(pr *xlsxSheetPr) {
|
||||
// Excel default: false
|
||||
if pr == nil || pr.PageSetUpPr == nil {
|
||||
*o = false
|
||||
return
|
||||
}
|
||||
*o = FitToPage(pr.PageSetUpPr.FitToPage)
|
||||
}
|
||||
|
||||
// setSheetPrOption implements the SheetPrOption interface and sets the
|
||||
// TabColor Indexed.
|
||||
func (o TabColorIndexed) setSheetPrOption(pr *xlsxSheetPr) {
|
||||
if pr.TabColor == nil {
|
||||
pr.TabColor = new(xlsxTabColor)
|
||||
}
|
||||
pr.TabColor.Indexed = int(o)
|
||||
}
|
||||
|
||||
// getSheetPrOption implements the SheetPrOptionPtr interface and gets the
|
||||
// TabColor Indexed. Defaults to -1 if no indexed has been set.
|
||||
func (o *TabColorIndexed) getSheetPrOption(pr *xlsxSheetPr) {
|
||||
if pr == nil || pr.TabColor == nil {
|
||||
*o = TabColorIndexed(ColorMappingTypeUnset)
|
||||
return
|
||||
}
|
||||
*o = TabColorIndexed(pr.TabColor.Indexed)
|
||||
}
|
||||
|
||||
// setSheetPrOption implements the SheetPrOption interface and specifies a
|
||||
// stable name of the sheet.
|
||||
func (o TabColorRGB) setSheetPrOption(pr *xlsxSheetPr) {
|
||||
if pr.TabColor == nil {
|
||||
if string(o) == "" {
|
||||
return
|
||||
}
|
||||
pr.TabColor = new(xlsxTabColor)
|
||||
}
|
||||
pr.TabColor.RGB = getPaletteColor(string(o))
|
||||
}
|
||||
|
||||
// getSheetPrOption implements the SheetPrOptionPtr interface and get the
|
||||
// stable name of the sheet.
|
||||
func (o *TabColorRGB) getSheetPrOption(pr *xlsxSheetPr) {
|
||||
if pr == nil || pr.TabColor == nil {
|
||||
*o = ""
|
||||
return
|
||||
}
|
||||
*o = TabColorRGB(strings.TrimPrefix(pr.TabColor.RGB, "FF"))
|
||||
}
|
||||
|
||||
// setSheetPrOption implements the SheetPrOption interface and sets the
|
||||
// TabColor Theme. Warning: it does not create a clrScheme!
|
||||
func (o TabColorTheme) setSheetPrOption(pr *xlsxSheetPr) {
|
||||
if pr.TabColor == nil {
|
||||
pr.TabColor = new(xlsxTabColor)
|
||||
}
|
||||
pr.TabColor.Theme = int(o)
|
||||
}
|
||||
|
||||
// getSheetPrOption implements the SheetPrOptionPtr interface and gets the
|
||||
// TabColor Theme. Defaults to -1 if no theme has been set.
|
||||
func (o *TabColorTheme) getSheetPrOption(pr *xlsxSheetPr) {
|
||||
if pr == nil || pr.TabColor == nil {
|
||||
*o = TabColorTheme(ColorMappingTypeUnset)
|
||||
return
|
||||
}
|
||||
*o = TabColorTheme(pr.TabColor.Theme)
|
||||
}
|
||||
|
||||
// setSheetPrOption implements the SheetPrOption interface and sets the
|
||||
// TabColor Tint.
|
||||
func (o TabColorTint) setSheetPrOption(pr *xlsxSheetPr) {
|
||||
if pr.TabColor == nil {
|
||||
pr.TabColor = new(xlsxTabColor)
|
||||
}
|
||||
pr.TabColor.Tint = float64(o)
|
||||
}
|
||||
|
||||
// getSheetPrOption implements the SheetPrOptionPtr interface and gets the
|
||||
// TabColor Tint. Defaults to 0.0 if no tint has been set.
|
||||
func (o *TabColorTint) getSheetPrOption(pr *xlsxSheetPr) {
|
||||
if pr == nil || pr.TabColor == nil {
|
||||
*o = 0.0
|
||||
return
|
||||
}
|
||||
*o = TabColorTint(pr.TabColor.Tint)
|
||||
}
|
||||
|
||||
// setSheetPrOption implements the SheetPrOption interface.
|
||||
func (o AutoPageBreaks) setSheetPrOption(pr *xlsxSheetPr) {
|
||||
if pr.PageSetUpPr == nil {
|
||||
if !o {
|
||||
return
|
||||
}
|
||||
pr.PageSetUpPr = new(xlsxPageSetUpPr)
|
||||
}
|
||||
pr.PageSetUpPr.AutoPageBreaks = bool(o)
|
||||
}
|
||||
|
||||
// getSheetPrOption implements the SheetPrOptionPtr interface.
|
||||
func (o *AutoPageBreaks) getSheetPrOption(pr *xlsxSheetPr) {
|
||||
// Excel default: false
|
||||
if pr == nil || pr.PageSetUpPr == nil {
|
||||
*o = false
|
||||
return
|
||||
}
|
||||
*o = AutoPageBreaks(pr.PageSetUpPr.AutoPageBreaks)
|
||||
}
|
||||
|
||||
// SetSheetPrOptions provides a function to sets worksheet properties.
|
||||
//
|
||||
// Available options:
|
||||
//
|
||||
// CodeName(string)
|
||||
// EnableFormatConditionsCalculation(bool)
|
||||
// Published(bool)
|
||||
// FitToPage(bool)
|
||||
// TabColorIndexed(int)
|
||||
// TabColorRGB(string)
|
||||
// TabColorTheme(int)
|
||||
// TabColorTint(float64)
|
||||
// AutoPageBreaks(bool)
|
||||
// OutlineSummaryBelow(bool)
|
||||
func (f *File) SetSheetPrOptions(sheet string, opts ...SheetPrOption) error {
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pr := ws.SheetPr
|
||||
if pr == nil {
|
||||
pr = new(xlsxSheetPr)
|
||||
ws.SheetPr = pr
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt.setSheetPrOption(pr)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// GetSheetPrOptions provides a function to gets worksheet properties.
|
||||
//
|
||||
// Available options:
|
||||
//
|
||||
// CodeName(string)
|
||||
// EnableFormatConditionsCalculation(bool)
|
||||
// Published(bool)
|
||||
// FitToPage(bool)
|
||||
// TabColorIndexed(int)
|
||||
// TabColorRGB(string)
|
||||
// TabColorTheme(int)
|
||||
// TabColorTint(float64)
|
||||
// AutoPageBreaks(bool)
|
||||
// OutlineSummaryBelow(bool)
|
||||
func (f *File) GetSheetPrOptions(sheet string, opts ...SheetPrOptionPtr) error {
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pr := ws.SheetPr
|
||||
|
||||
for _, opt := range opts {
|
||||
opt.getSheetPrOption(pr)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type (
|
||||
// PageMarginBottom specifies the bottom margin for the page.
|
||||
PageMarginBottom float64
|
||||
// PageMarginFooter specifies the footer margin for the page.
|
||||
PageMarginFooter float64
|
||||
// PageMarginHeader specifies the header margin for the page.
|
||||
PageMarginHeader float64
|
||||
// PageMarginLeft specifies the left margin for the page.
|
||||
PageMarginLeft float64
|
||||
// PageMarginRight specifies the right margin for the page.
|
||||
PageMarginRight float64
|
||||
// PageMarginTop specifies the top margin for the page.
|
||||
PageMarginTop float64
|
||||
)
|
||||
|
||||
// setPageMargins provides a method to set the bottom margin for the worksheet.
|
||||
func (p PageMarginBottom) setPageMargins(pm *xlsxPageMargins) {
|
||||
pm.Bottom = float64(p)
|
||||
}
|
||||
|
||||
// setPageMargins provides a method to get the bottom margin for the worksheet.
|
||||
func (p *PageMarginBottom) getPageMargins(pm *xlsxPageMargins) {
|
||||
// Excel default: 0.75
|
||||
if pm == nil || pm.Bottom == 0 {
|
||||
*p = 0.75
|
||||
return
|
||||
}
|
||||
*p = PageMarginBottom(pm.Bottom)
|
||||
}
|
||||
|
||||
// setPageMargins provides a method to set the footer margin for the worksheet.
|
||||
func (p PageMarginFooter) setPageMargins(pm *xlsxPageMargins) {
|
||||
pm.Footer = float64(p)
|
||||
}
|
||||
|
||||
// setPageMargins provides a method to get the footer margin for the worksheet.
|
||||
func (p *PageMarginFooter) getPageMargins(pm *xlsxPageMargins) {
|
||||
// Excel default: 0.3
|
||||
if pm == nil || pm.Footer == 0 {
|
||||
*p = 0.3
|
||||
return
|
||||
}
|
||||
*p = PageMarginFooter(pm.Footer)
|
||||
}
|
||||
|
||||
// setPageMargins provides a method to set the header margin for the worksheet.
|
||||
func (p PageMarginHeader) setPageMargins(pm *xlsxPageMargins) {
|
||||
pm.Header = float64(p)
|
||||
}
|
||||
|
||||
// setPageMargins provides a method to get the header margin for the worksheet.
|
||||
func (p *PageMarginHeader) getPageMargins(pm *xlsxPageMargins) {
|
||||
// Excel default: 0.3
|
||||
if pm == nil || pm.Header == 0 {
|
||||
*p = 0.3
|
||||
return
|
||||
}
|
||||
*p = PageMarginHeader(pm.Header)
|
||||
}
|
||||
|
||||
// setPageMargins provides a method to set the left margin for the worksheet.
|
||||
func (p PageMarginLeft) setPageMargins(pm *xlsxPageMargins) {
|
||||
pm.Left = float64(p)
|
||||
}
|
||||
|
||||
// setPageMargins provides a method to get the left margin for the worksheet.
|
||||
func (p *PageMarginLeft) getPageMargins(pm *xlsxPageMargins) {
|
||||
// Excel default: 0.7
|
||||
if pm == nil || pm.Left == 0 {
|
||||
*p = 0.7
|
||||
return
|
||||
}
|
||||
*p = PageMarginLeft(pm.Left)
|
||||
}
|
||||
|
||||
// setPageMargins provides a method to set the right margin for the worksheet.
|
||||
func (p PageMarginRight) setPageMargins(pm *xlsxPageMargins) {
|
||||
pm.Right = float64(p)
|
||||
}
|
||||
|
||||
// setPageMargins provides a method to get the right margin for the worksheet.
|
||||
func (p *PageMarginRight) getPageMargins(pm *xlsxPageMargins) {
|
||||
// Excel default: 0.7
|
||||
if pm == nil || pm.Right == 0 {
|
||||
*p = 0.7
|
||||
return
|
||||
}
|
||||
*p = PageMarginRight(pm.Right)
|
||||
}
|
||||
|
||||
// setPageMargins provides a method to set the top margin for the worksheet.
|
||||
func (p PageMarginTop) setPageMargins(pm *xlsxPageMargins) {
|
||||
pm.Top = float64(p)
|
||||
}
|
||||
|
||||
// setPageMargins provides a method to get the top margin for the worksheet.
|
||||
func (p *PageMarginTop) getPageMargins(pm *xlsxPageMargins) {
|
||||
// Excel default: 0.75
|
||||
if pm == nil || pm.Top == 0 {
|
||||
*p = 0.75
|
||||
return
|
||||
}
|
||||
*p = PageMarginTop(pm.Top)
|
||||
}
|
||||
|
||||
// PageMarginsOptions is an option of a page margin of a worksheet. See
|
||||
// SetPageMargins().
|
||||
type PageMarginsOptions interface {
|
||||
setPageMargins(layout *xlsxPageMargins)
|
||||
}
|
||||
|
||||
// PageMarginsOptionsPtr is a writable PageMarginsOptions. See
|
||||
// GetPageMargins().
|
||||
type PageMarginsOptionsPtr interface {
|
||||
PageMarginsOptions
|
||||
getPageMargins(layout *xlsxPageMargins)
|
||||
}
|
||||
|
||||
// SetPageMargins provides a function to set worksheet page margins.
|
||||
//
|
||||
// Available options:
|
||||
//
|
||||
// PageMarginBottom(float64)
|
||||
// PageMarginFooter(float64)
|
||||
// PageMarginHeader(float64)
|
||||
// PageMarginLeft(float64)
|
||||
// PageMarginRight(float64)
|
||||
// PageMarginTop(float64)
|
||||
func (f *File) SetPageMargins(sheet string, opts ...PageMarginsOptions) error {
|
||||
s, err := f.workSheetReader(sheet)
|
||||
func (f *File) SetPageMargins(sheet string, opts *PageLayoutMarginsOptions) error {
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pm := s.PageMargins
|
||||
if pm == nil {
|
||||
pm = new(xlsxPageMargins)
|
||||
s.PageMargins = pm
|
||||
if opts == nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt.setPageMargins(pm)
|
||||
preparePageMargins := func(ws *xlsxWorksheet) {
|
||||
if ws.PageMargins == nil {
|
||||
ws.PageMargins = new(xlsxPageMargins)
|
||||
}
|
||||
}
|
||||
preparePrintOptions := func(ws *xlsxWorksheet) {
|
||||
if ws.PrintOptions == nil {
|
||||
ws.PrintOptions = new(xlsxPrintOptions)
|
||||
}
|
||||
}
|
||||
if opts.Bottom != nil {
|
||||
preparePageMargins(ws)
|
||||
ws.PageMargins.Bottom = *opts.Bottom
|
||||
}
|
||||
if opts.Footer != nil {
|
||||
preparePageMargins(ws)
|
||||
ws.PageMargins.Footer = *opts.Footer
|
||||
}
|
||||
if opts.Header != nil {
|
||||
preparePageMargins(ws)
|
||||
ws.PageMargins.Header = *opts.Header
|
||||
}
|
||||
if opts.Left != nil {
|
||||
preparePageMargins(ws)
|
||||
ws.PageMargins.Left = *opts.Left
|
||||
}
|
||||
if opts.Right != nil {
|
||||
preparePageMargins(ws)
|
||||
ws.PageMargins.Right = *opts.Right
|
||||
}
|
||||
if opts.Top != nil {
|
||||
preparePageMargins(ws)
|
||||
ws.PageMargins.Top = *opts.Top
|
||||
}
|
||||
if opts.Horizontally != nil {
|
||||
preparePrintOptions(ws)
|
||||
ws.PrintOptions.HorizontalCentered = *opts.Horizontally
|
||||
}
|
||||
if opts.Vertically != nil {
|
||||
preparePrintOptions(ws)
|
||||
ws.PrintOptions.VerticalCentered = *opts.Vertically
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// GetPageMargins provides a function to get worksheet page margins.
|
||||
//
|
||||
// Available options:
|
||||
//
|
||||
// PageMarginBottom(float64)
|
||||
// PageMarginFooter(float64)
|
||||
// PageMarginHeader(float64)
|
||||
// PageMarginLeft(float64)
|
||||
// PageMarginRight(float64)
|
||||
// PageMarginTop(float64)
|
||||
func (f *File) GetPageMargins(sheet string, opts ...PageMarginsOptionsPtr) error {
|
||||
s, err := f.workSheetReader(sheet)
|
||||
func (f *File) GetPageMargins(sheet string) (PageLayoutMarginsOptions, error) {
|
||||
opts := PageLayoutMarginsOptions{
|
||||
Bottom: float64Ptr(0.75),
|
||||
Footer: float64Ptr(0.3),
|
||||
Header: float64Ptr(0.3),
|
||||
Left: float64Ptr(0.7),
|
||||
Right: float64Ptr(0.7),
|
||||
Top: float64Ptr(0.75),
|
||||
}
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return opts, err
|
||||
}
|
||||
if ws.PageMargins != nil {
|
||||
if ws.PageMargins.Bottom != 0 {
|
||||
opts.Bottom = float64Ptr(ws.PageMargins.Bottom)
|
||||
}
|
||||
if ws.PageMargins.Footer != 0 {
|
||||
opts.Footer = float64Ptr(ws.PageMargins.Footer)
|
||||
}
|
||||
if ws.PageMargins.Header != 0 {
|
||||
opts.Header = float64Ptr(ws.PageMargins.Header)
|
||||
}
|
||||
if ws.PageMargins.Left != 0 {
|
||||
opts.Left = float64Ptr(ws.PageMargins.Left)
|
||||
}
|
||||
if ws.PageMargins.Right != 0 {
|
||||
opts.Right = float64Ptr(ws.PageMargins.Right)
|
||||
}
|
||||
if ws.PageMargins.Top != 0 {
|
||||
opts.Top = float64Ptr(ws.PageMargins.Top)
|
||||
}
|
||||
}
|
||||
if ws.PrintOptions != nil {
|
||||
opts.Horizontally = boolPtr(ws.PrintOptions.HorizontalCentered)
|
||||
opts.Vertically = boolPtr(ws.PrintOptions.VerticalCentered)
|
||||
}
|
||||
return opts, err
|
||||
}
|
||||
|
||||
// setSheetProps set worksheet format properties by given options.
|
||||
func (ws *xlsxWorksheet) setSheetProps(opts *SheetPropsOptions) {
|
||||
prepareSheetPr := func(ws *xlsxWorksheet) {
|
||||
if ws.SheetPr == nil {
|
||||
ws.SheetPr = new(xlsxSheetPr)
|
||||
}
|
||||
}
|
||||
preparePageSetUpPr := func(ws *xlsxWorksheet) {
|
||||
prepareSheetPr(ws)
|
||||
if ws.SheetPr.PageSetUpPr == nil {
|
||||
ws.SheetPr.PageSetUpPr = new(xlsxPageSetUpPr)
|
||||
}
|
||||
}
|
||||
prepareOutlinePr := func(ws *xlsxWorksheet) {
|
||||
prepareSheetPr(ws)
|
||||
if ws.SheetPr.OutlinePr == nil {
|
||||
ws.SheetPr.OutlinePr = new(xlsxOutlinePr)
|
||||
}
|
||||
}
|
||||
prepareTabColor := func(ws *xlsxWorksheet) {
|
||||
prepareSheetPr(ws)
|
||||
if ws.SheetPr.TabColor == nil {
|
||||
ws.SheetPr.TabColor = new(xlsxTabColor)
|
||||
}
|
||||
}
|
||||
if opts.CodeName != nil {
|
||||
prepareSheetPr(ws)
|
||||
ws.SheetPr.CodeName = *opts.CodeName
|
||||
}
|
||||
if opts.EnableFormatConditionsCalculation != nil {
|
||||
prepareSheetPr(ws)
|
||||
ws.SheetPr.EnableFormatConditionsCalculation = opts.EnableFormatConditionsCalculation
|
||||
}
|
||||
if opts.Published != nil {
|
||||
prepareSheetPr(ws)
|
||||
ws.SheetPr.Published = opts.Published
|
||||
}
|
||||
if opts.AutoPageBreaks != nil {
|
||||
preparePageSetUpPr(ws)
|
||||
ws.SheetPr.PageSetUpPr.AutoPageBreaks = *opts.AutoPageBreaks
|
||||
}
|
||||
if opts.FitToPage != nil {
|
||||
preparePageSetUpPr(ws)
|
||||
ws.SheetPr.PageSetUpPr.FitToPage = *opts.FitToPage
|
||||
}
|
||||
if opts.OutlineSummaryBelow != nil {
|
||||
prepareOutlinePr(ws)
|
||||
ws.SheetPr.OutlinePr.SummaryBelow = *opts.OutlineSummaryBelow
|
||||
}
|
||||
if opts.TabColorIndexed != nil {
|
||||
prepareTabColor(ws)
|
||||
ws.SheetPr.TabColor.Indexed = *opts.TabColorIndexed
|
||||
}
|
||||
if opts.TabColorRGB != nil {
|
||||
prepareTabColor(ws)
|
||||
ws.SheetPr.TabColor.RGB = *opts.TabColorRGB
|
||||
}
|
||||
if opts.TabColorTheme != nil {
|
||||
prepareTabColor(ws)
|
||||
ws.SheetPr.TabColor.Theme = *opts.TabColorTheme
|
||||
}
|
||||
if opts.TabColorTint != nil {
|
||||
prepareTabColor(ws)
|
||||
ws.SheetPr.TabColor.Tint = *opts.TabColorTint
|
||||
}
|
||||
}
|
||||
|
||||
// SetSheetProps provides a function to set worksheet properties.
|
||||
func (f *File) SetSheetProps(sheet string, opts *SheetPropsOptions) error {
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pm := s.PageMargins
|
||||
|
||||
for _, opt := range opts {
|
||||
opt.getPageMargins(pm)
|
||||
if opts == nil {
|
||||
return err
|
||||
}
|
||||
ws.setSheetProps(opts)
|
||||
if ws.SheetFormatPr == nil {
|
||||
ws.SheetFormatPr = &xlsxSheetFormatPr{DefaultRowHeight: defaultRowHeight}
|
||||
}
|
||||
if opts.BaseColWidth != nil {
|
||||
ws.SheetFormatPr.BaseColWidth = *opts.BaseColWidth
|
||||
}
|
||||
if opts.DefaultColWidth != nil {
|
||||
ws.SheetFormatPr.DefaultColWidth = *opts.DefaultColWidth
|
||||
}
|
||||
if opts.DefaultRowHeight != nil {
|
||||
ws.SheetFormatPr.DefaultRowHeight = *opts.DefaultRowHeight
|
||||
}
|
||||
if opts.CustomHeight != nil {
|
||||
ws.SheetFormatPr.CustomHeight = *opts.CustomHeight
|
||||
}
|
||||
if opts.ZeroHeight != nil {
|
||||
ws.SheetFormatPr.ZeroHeight = *opts.ZeroHeight
|
||||
}
|
||||
if opts.ThickTop != nil {
|
||||
ws.SheetFormatPr.ThickTop = *opts.ThickTop
|
||||
}
|
||||
if opts.ThickBottom != nil {
|
||||
ws.SheetFormatPr.ThickBottom = *opts.ThickBottom
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SheetFormatPrOptions is an option of the formatting properties of a
|
||||
// worksheet. See SetSheetFormatPr().
|
||||
type SheetFormatPrOptions interface {
|
||||
setSheetFormatPr(formatPr *xlsxSheetFormatPr)
|
||||
}
|
||||
|
||||
// SheetFormatPrOptionsPtr is a writable SheetFormatPrOptions. See
|
||||
// GetSheetFormatPr().
|
||||
type SheetFormatPrOptionsPtr interface {
|
||||
SheetFormatPrOptions
|
||||
getSheetFormatPr(formatPr *xlsxSheetFormatPr)
|
||||
}
|
||||
|
||||
type (
|
||||
// BaseColWidth specifies the number of characters of the maximum digit width
|
||||
// of the normal style's font. This value does not include margin padding or
|
||||
// extra padding for gridlines. It is only the number of characters.
|
||||
BaseColWidth uint8
|
||||
// DefaultColWidth specifies the default column width measured as the number
|
||||
// of characters of the maximum digit width of the normal style's font.
|
||||
DefaultColWidth float64
|
||||
// DefaultRowHeight specifies the default row height measured in point size.
|
||||
// Optimization so we don't have to write the height on all rows. This can be
|
||||
// written out if most rows have custom height, to achieve the optimization.
|
||||
DefaultRowHeight float64
|
||||
// CustomHeight specifies the custom height.
|
||||
CustomHeight bool
|
||||
// ZeroHeight specifies if rows are hidden.
|
||||
ZeroHeight bool
|
||||
// ThickTop specifies if rows have a thick top border by default.
|
||||
ThickTop bool
|
||||
// ThickBottom specifies if rows have a thick bottom border by default.
|
||||
ThickBottom bool
|
||||
)
|
||||
|
||||
// setSheetFormatPr provides a method to set the number of characters of the
|
||||
// maximum digit width of the normal style's font.
|
||||
func (p BaseColWidth) setSheetFormatPr(fp *xlsxSheetFormatPr) {
|
||||
fp.BaseColWidth = uint8(p)
|
||||
}
|
||||
|
||||
// setSheetFormatPr provides a method to set the number of characters of the
|
||||
// maximum digit width of the normal style's font.
|
||||
func (p *BaseColWidth) getSheetFormatPr(fp *xlsxSheetFormatPr) {
|
||||
if fp == nil {
|
||||
*p = 0
|
||||
return
|
||||
// GetSheetProps provides a function to get worksheet properties.
|
||||
func (f *File) GetSheetProps(sheet string) (SheetPropsOptions, error) {
|
||||
baseColWidth := uint8(8)
|
||||
opts := SheetPropsOptions{
|
||||
EnableFormatConditionsCalculation: boolPtr(true),
|
||||
Published: boolPtr(true),
|
||||
AutoPageBreaks: boolPtr(true),
|
||||
OutlineSummaryBelow: boolPtr(true),
|
||||
BaseColWidth: &baseColWidth,
|
||||
}
|
||||
*p = BaseColWidth(fp.BaseColWidth)
|
||||
}
|
||||
|
||||
// setSheetFormatPr provides a method to set the default column width measured
|
||||
// as the number of characters of the maximum digit width of the normal
|
||||
// style's font.
|
||||
func (p DefaultColWidth) setSheetFormatPr(fp *xlsxSheetFormatPr) {
|
||||
fp.DefaultColWidth = float64(p)
|
||||
}
|
||||
|
||||
// getSheetFormatPr provides a method to get the default column width measured
|
||||
// as the number of characters of the maximum digit width of the normal
|
||||
// style's font.
|
||||
func (p *DefaultColWidth) getSheetFormatPr(fp *xlsxSheetFormatPr) {
|
||||
if fp == nil {
|
||||
*p = 0
|
||||
return
|
||||
}
|
||||
*p = DefaultColWidth(fp.DefaultColWidth)
|
||||
}
|
||||
|
||||
// setSheetFormatPr provides a method to set the default row height measured
|
||||
// in point size.
|
||||
func (p DefaultRowHeight) setSheetFormatPr(fp *xlsxSheetFormatPr) {
|
||||
fp.DefaultRowHeight = float64(p)
|
||||
}
|
||||
|
||||
// getSheetFormatPr provides a method to get the default row height measured
|
||||
// in point size.
|
||||
func (p *DefaultRowHeight) getSheetFormatPr(fp *xlsxSheetFormatPr) {
|
||||
if fp == nil {
|
||||
*p = 15
|
||||
return
|
||||
}
|
||||
*p = DefaultRowHeight(fp.DefaultRowHeight)
|
||||
}
|
||||
|
||||
// setSheetFormatPr provides a method to set the custom height.
|
||||
func (p CustomHeight) setSheetFormatPr(fp *xlsxSheetFormatPr) {
|
||||
fp.CustomHeight = bool(p)
|
||||
}
|
||||
|
||||
// getSheetFormatPr provides a method to get the custom height.
|
||||
func (p *CustomHeight) getSheetFormatPr(fp *xlsxSheetFormatPr) {
|
||||
if fp == nil {
|
||||
*p = false
|
||||
return
|
||||
}
|
||||
*p = CustomHeight(fp.CustomHeight)
|
||||
}
|
||||
|
||||
// setSheetFormatPr provides a method to set if rows are hidden.
|
||||
func (p ZeroHeight) setSheetFormatPr(fp *xlsxSheetFormatPr) {
|
||||
fp.ZeroHeight = bool(p)
|
||||
}
|
||||
|
||||
// getSheetFormatPr provides a method to get if rows are hidden.
|
||||
func (p *ZeroHeight) getSheetFormatPr(fp *xlsxSheetFormatPr) {
|
||||
if fp == nil {
|
||||
*p = false
|
||||
return
|
||||
}
|
||||
*p = ZeroHeight(fp.ZeroHeight)
|
||||
}
|
||||
|
||||
// setSheetFormatPr provides a method to set if rows have a thick top border
|
||||
// by default.
|
||||
func (p ThickTop) setSheetFormatPr(fp *xlsxSheetFormatPr) {
|
||||
fp.ThickTop = bool(p)
|
||||
}
|
||||
|
||||
// getSheetFormatPr provides a method to get if rows have a thick top border
|
||||
// by default.
|
||||
func (p *ThickTop) getSheetFormatPr(fp *xlsxSheetFormatPr) {
|
||||
if fp == nil {
|
||||
*p = false
|
||||
return
|
||||
}
|
||||
*p = ThickTop(fp.ThickTop)
|
||||
}
|
||||
|
||||
// setSheetFormatPr provides a method to set if rows have a thick bottom
|
||||
// border by default.
|
||||
func (p ThickBottom) setSheetFormatPr(fp *xlsxSheetFormatPr) {
|
||||
fp.ThickBottom = bool(p)
|
||||
}
|
||||
|
||||
// setSheetFormatPr provides a method to set if rows have a thick bottom
|
||||
// border by default.
|
||||
func (p *ThickBottom) getSheetFormatPr(fp *xlsxSheetFormatPr) {
|
||||
if fp == nil {
|
||||
*p = false
|
||||
return
|
||||
}
|
||||
*p = ThickBottom(fp.ThickBottom)
|
||||
}
|
||||
|
||||
// SetSheetFormatPr provides a function to set worksheet formatting properties.
|
||||
//
|
||||
// Available options:
|
||||
//
|
||||
// BaseColWidth(uint8)
|
||||
// DefaultColWidth(float64)
|
||||
// DefaultRowHeight(float64)
|
||||
// CustomHeight(bool)
|
||||
// ZeroHeight(bool)
|
||||
// ThickTop(bool)
|
||||
// ThickBottom(bool)
|
||||
func (f *File) SetSheetFormatPr(sheet string, opts ...SheetFormatPrOptions) error {
|
||||
s, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
return opts, err
|
||||
}
|
||||
fp := s.SheetFormatPr
|
||||
if fp == nil {
|
||||
fp = new(xlsxSheetFormatPr)
|
||||
s.SheetFormatPr = fp
|
||||
if ws.SheetPr != nil {
|
||||
opts.CodeName = stringPtr(ws.SheetPr.CodeName)
|
||||
if ws.SheetPr.EnableFormatConditionsCalculation != nil {
|
||||
opts.EnableFormatConditionsCalculation = ws.SheetPr.EnableFormatConditionsCalculation
|
||||
}
|
||||
if ws.SheetPr.Published != nil {
|
||||
opts.Published = ws.SheetPr.Published
|
||||
}
|
||||
if ws.SheetPr.PageSetUpPr != nil {
|
||||
opts.AutoPageBreaks = boolPtr(ws.SheetPr.PageSetUpPr.AutoPageBreaks)
|
||||
opts.FitToPage = boolPtr(ws.SheetPr.PageSetUpPr.FitToPage)
|
||||
}
|
||||
if ws.SheetPr.OutlinePr != nil {
|
||||
opts.OutlineSummaryBelow = boolPtr(ws.SheetPr.OutlinePr.SummaryBelow)
|
||||
}
|
||||
if ws.SheetPr.TabColor != nil {
|
||||
opts.TabColorIndexed = intPtr(ws.SheetPr.TabColor.Indexed)
|
||||
opts.TabColorRGB = stringPtr(ws.SheetPr.TabColor.RGB)
|
||||
opts.TabColorTheme = intPtr(ws.SheetPr.TabColor.Theme)
|
||||
opts.TabColorTint = float64Ptr(ws.SheetPr.TabColor.Tint)
|
||||
}
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt.setSheetFormatPr(fp)
|
||||
if ws.SheetFormatPr != nil {
|
||||
opts.BaseColWidth = &ws.SheetFormatPr.BaseColWidth
|
||||
opts.DefaultColWidth = float64Ptr(ws.SheetFormatPr.DefaultColWidth)
|
||||
opts.DefaultRowHeight = float64Ptr(ws.SheetFormatPr.DefaultRowHeight)
|
||||
opts.CustomHeight = boolPtr(ws.SheetFormatPr.CustomHeight)
|
||||
opts.ZeroHeight = boolPtr(ws.SheetFormatPr.ZeroHeight)
|
||||
opts.ThickTop = boolPtr(ws.SheetFormatPr.ThickTop)
|
||||
opts.ThickBottom = boolPtr(ws.SheetFormatPr.ThickBottom)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// GetSheetFormatPr provides a function to get worksheet formatting properties.
|
||||
//
|
||||
// Available options:
|
||||
//
|
||||
// BaseColWidth(uint8)
|
||||
// DefaultColWidth(float64)
|
||||
// DefaultRowHeight(float64)
|
||||
// CustomHeight(bool)
|
||||
// ZeroHeight(bool)
|
||||
// ThickTop(bool)
|
||||
// ThickBottom(bool)
|
||||
func (f *File) GetSheetFormatPr(sheet string, opts ...SheetFormatPrOptionsPtr) error {
|
||||
s, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fp := s.SheetFormatPr
|
||||
for _, opt := range opts {
|
||||
opt.getSheetFormatPr(fp)
|
||||
}
|
||||
return err
|
||||
return opts, err
|
||||
}
|
||||
|
|
550
sheetpr_test.go
550
sheetpr_test.go
|
@ -1,501 +1,107 @@
|
|||
package excelize
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/mohae/deepcopy"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var _ = []SheetPrOption{
|
||||
CodeName("hello"),
|
||||
EnableFormatConditionsCalculation(false),
|
||||
Published(false),
|
||||
FitToPage(true),
|
||||
TabColorIndexed(42),
|
||||
TabColorRGB("#FFFF00"),
|
||||
TabColorTheme(ColorMappingTypeLight2),
|
||||
TabColorTint(0.5),
|
||||
AutoPageBreaks(true),
|
||||
OutlineSummaryBelow(true),
|
||||
}
|
||||
|
||||
var _ = []SheetPrOptionPtr{
|
||||
(*CodeName)(nil),
|
||||
(*EnableFormatConditionsCalculation)(nil),
|
||||
(*Published)(nil),
|
||||
(*FitToPage)(nil),
|
||||
(*TabColorIndexed)(nil),
|
||||
(*TabColorRGB)(nil),
|
||||
(*TabColorTheme)(nil),
|
||||
(*TabColorTint)(nil),
|
||||
(*AutoPageBreaks)(nil),
|
||||
(*OutlineSummaryBelow)(nil),
|
||||
}
|
||||
|
||||
func ExampleFile_SetSheetPrOptions() {
|
||||
f := NewFile()
|
||||
const sheet = "Sheet1"
|
||||
|
||||
if err := f.SetSheetPrOptions(sheet,
|
||||
CodeName("code"),
|
||||
EnableFormatConditionsCalculation(false),
|
||||
Published(false),
|
||||
FitToPage(true),
|
||||
TabColorIndexed(42),
|
||||
TabColorRGB("#FFFF00"),
|
||||
TabColorTheme(ColorMappingTypeLight2),
|
||||
TabColorTint(0.5),
|
||||
AutoPageBreaks(true),
|
||||
OutlineSummaryBelow(false),
|
||||
); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
// Output:
|
||||
}
|
||||
|
||||
func ExampleFile_GetSheetPrOptions() {
|
||||
f := NewFile()
|
||||
const sheet = "Sheet1"
|
||||
|
||||
var (
|
||||
codeName CodeName
|
||||
enableFormatConditionsCalculation EnableFormatConditionsCalculation
|
||||
published Published
|
||||
fitToPage FitToPage
|
||||
tabColorIndexed TabColorIndexed
|
||||
tabColorRGB TabColorRGB
|
||||
tabColorTheme TabColorTheme
|
||||
tabColorTint TabColorTint
|
||||
autoPageBreaks AutoPageBreaks
|
||||
outlineSummaryBelow OutlineSummaryBelow
|
||||
)
|
||||
|
||||
if err := f.GetSheetPrOptions(sheet,
|
||||
&codeName,
|
||||
&enableFormatConditionsCalculation,
|
||||
&published,
|
||||
&fitToPage,
|
||||
&tabColorIndexed,
|
||||
&tabColorRGB,
|
||||
&tabColorTheme,
|
||||
&tabColorTint,
|
||||
&autoPageBreaks,
|
||||
&outlineSummaryBelow,
|
||||
); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println("Defaults:")
|
||||
fmt.Printf("- codeName: %q\n", codeName)
|
||||
fmt.Println("- enableFormatConditionsCalculation:", enableFormatConditionsCalculation)
|
||||
fmt.Println("- published:", published)
|
||||
fmt.Println("- fitToPage:", fitToPage)
|
||||
fmt.Printf("- tabColorIndexed: %d\n", tabColorIndexed)
|
||||
fmt.Printf("- tabColorRGB: %q\n", tabColorRGB)
|
||||
fmt.Printf("- tabColorTheme: %d\n", tabColorTheme)
|
||||
fmt.Printf("- tabColorTint: %f\n", tabColorTint)
|
||||
fmt.Println("- autoPageBreaks:", autoPageBreaks)
|
||||
fmt.Println("- outlineSummaryBelow:", outlineSummaryBelow)
|
||||
// Output:
|
||||
// Defaults:
|
||||
// - codeName: ""
|
||||
// - enableFormatConditionsCalculation: true
|
||||
// - published: true
|
||||
// - fitToPage: false
|
||||
// - tabColorIndexed: -1
|
||||
// - tabColorRGB: ""
|
||||
// - tabColorTheme: -1
|
||||
// - tabColorTint: 0.000000
|
||||
// - autoPageBreaks: false
|
||||
// - outlineSummaryBelow: true
|
||||
}
|
||||
|
||||
func TestSheetPrOptions(t *testing.T) {
|
||||
const sheet = "Sheet1"
|
||||
|
||||
testData := []struct {
|
||||
container SheetPrOptionPtr
|
||||
nonDefault SheetPrOption
|
||||
}{
|
||||
{new(CodeName), CodeName("xx")},
|
||||
{new(EnableFormatConditionsCalculation), EnableFormatConditionsCalculation(false)},
|
||||
{new(Published), Published(false)},
|
||||
{new(FitToPage), FitToPage(true)},
|
||||
{new(TabColorIndexed), TabColorIndexed(42)},
|
||||
{new(TabColorRGB), TabColorRGB("FFFF00")},
|
||||
{new(TabColorTheme), TabColorTheme(ColorMappingTypeLight2)},
|
||||
{new(TabColorTint), TabColorTint(0.5)},
|
||||
{new(AutoPageBreaks), AutoPageBreaks(true)},
|
||||
{new(OutlineSummaryBelow), OutlineSummaryBelow(false)},
|
||||
}
|
||||
|
||||
for i, test := range testData {
|
||||
t.Run(fmt.Sprintf("TestData%d", i), func(t *testing.T) {
|
||||
opts := test.nonDefault
|
||||
t.Logf("option %T", opts)
|
||||
|
||||
def := deepcopy.Copy(test.container).(SheetPrOptionPtr)
|
||||
val1 := deepcopy.Copy(def).(SheetPrOptionPtr)
|
||||
val2 := deepcopy.Copy(def).(SheetPrOptionPtr)
|
||||
|
||||
f := NewFile()
|
||||
// Get the default value
|
||||
assert.NoError(t, f.GetSheetPrOptions(sheet, def), opts)
|
||||
// Get again and check
|
||||
assert.NoError(t, f.GetSheetPrOptions(sheet, val1), opts)
|
||||
if !assert.Equal(t, val1, def, opts) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Set the same value
|
||||
assert.NoError(t, f.SetSheetPrOptions(sheet, val1), opts)
|
||||
// Get again and check
|
||||
assert.NoError(t, f.GetSheetPrOptions(sheet, val1), opts)
|
||||
if !assert.Equal(t, val1, def, "%T: value should not have changed", opts) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Set a different value
|
||||
assert.NoError(t, f.SetSheetPrOptions(sheet, test.nonDefault), opts)
|
||||
assert.NoError(t, f.GetSheetPrOptions(sheet, val1), opts)
|
||||
// Get again and compare
|
||||
assert.NoError(t, f.GetSheetPrOptions(sheet, val2), opts)
|
||||
if !assert.Equal(t, val1, val2, "%T: value should not have changed", opts) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Value should not be the same as the default
|
||||
if !assert.NotEqual(t, def, val1, "%T: value should have changed from default", opts) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Restore the default value
|
||||
assert.NoError(t, f.SetSheetPrOptions(sheet, def), opts)
|
||||
assert.NoError(t, f.GetSheetPrOptions(sheet, val1), opts)
|
||||
if !assert.Equal(t, def, val1) {
|
||||
t.FailNow()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetSheetPrOptions(t *testing.T) {
|
||||
f := NewFile()
|
||||
assert.NoError(t, f.SetSheetPrOptions("Sheet1", TabColorRGB("")))
|
||||
// Test SetSheetPrOptions on not exists worksheet.
|
||||
assert.EqualError(t, f.SetSheetPrOptions("SheetN"), "sheet SheetN does not exist")
|
||||
}
|
||||
|
||||
func TestGetSheetPrOptions(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test GetSheetPrOptions on not exists worksheet.
|
||||
assert.EqualError(t, f.GetSheetPrOptions("SheetN"), "sheet SheetN does not exist")
|
||||
}
|
||||
|
||||
var _ = []PageMarginsOptions{
|
||||
PageMarginBottom(1.0),
|
||||
PageMarginFooter(1.0),
|
||||
PageMarginHeader(1.0),
|
||||
PageMarginLeft(1.0),
|
||||
PageMarginRight(1.0),
|
||||
PageMarginTop(1.0),
|
||||
}
|
||||
|
||||
var _ = []PageMarginsOptionsPtr{
|
||||
(*PageMarginBottom)(nil),
|
||||
(*PageMarginFooter)(nil),
|
||||
(*PageMarginHeader)(nil),
|
||||
(*PageMarginLeft)(nil),
|
||||
(*PageMarginRight)(nil),
|
||||
(*PageMarginTop)(nil),
|
||||
}
|
||||
|
||||
func ExampleFile_SetPageMargins() {
|
||||
f := NewFile()
|
||||
const sheet = "Sheet1"
|
||||
|
||||
if err := f.SetPageMargins(sheet,
|
||||
PageMarginBottom(1.0),
|
||||
PageMarginFooter(1.0),
|
||||
PageMarginHeader(1.0),
|
||||
PageMarginLeft(1.0),
|
||||
PageMarginRight(1.0),
|
||||
PageMarginTop(1.0),
|
||||
); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
// Output:
|
||||
}
|
||||
|
||||
func ExampleFile_GetPageMargins() {
|
||||
f := NewFile()
|
||||
const sheet = "Sheet1"
|
||||
|
||||
var (
|
||||
marginBottom PageMarginBottom
|
||||
marginFooter PageMarginFooter
|
||||
marginHeader PageMarginHeader
|
||||
marginLeft PageMarginLeft
|
||||
marginRight PageMarginRight
|
||||
marginTop PageMarginTop
|
||||
)
|
||||
|
||||
if err := f.GetPageMargins(sheet,
|
||||
&marginBottom,
|
||||
&marginFooter,
|
||||
&marginHeader,
|
||||
&marginLeft,
|
||||
&marginRight,
|
||||
&marginTop,
|
||||
); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println("Defaults:")
|
||||
fmt.Println("- marginBottom:", marginBottom)
|
||||
fmt.Println("- marginFooter:", marginFooter)
|
||||
fmt.Println("- marginHeader:", marginHeader)
|
||||
fmt.Println("- marginLeft:", marginLeft)
|
||||
fmt.Println("- marginRight:", marginRight)
|
||||
fmt.Println("- marginTop:", marginTop)
|
||||
// Output:
|
||||
// Defaults:
|
||||
// - marginBottom: 0.75
|
||||
// - marginFooter: 0.3
|
||||
// - marginHeader: 0.3
|
||||
// - marginLeft: 0.7
|
||||
// - marginRight: 0.7
|
||||
// - marginTop: 0.75
|
||||
}
|
||||
|
||||
func TestPageMarginsOption(t *testing.T) {
|
||||
const sheet = "Sheet1"
|
||||
|
||||
testData := []struct {
|
||||
container PageMarginsOptionsPtr
|
||||
nonDefault PageMarginsOptions
|
||||
}{
|
||||
{new(PageMarginTop), PageMarginTop(1.0)},
|
||||
{new(PageMarginBottom), PageMarginBottom(1.0)},
|
||||
{new(PageMarginLeft), PageMarginLeft(1.0)},
|
||||
{new(PageMarginRight), PageMarginRight(1.0)},
|
||||
{new(PageMarginHeader), PageMarginHeader(1.0)},
|
||||
{new(PageMarginFooter), PageMarginFooter(1.0)},
|
||||
}
|
||||
|
||||
for i, test := range testData {
|
||||
t.Run(fmt.Sprintf("TestData%d", i), func(t *testing.T) {
|
||||
opts := test.nonDefault
|
||||
t.Logf("option %T", opts)
|
||||
|
||||
def := deepcopy.Copy(test.container).(PageMarginsOptionsPtr)
|
||||
val1 := deepcopy.Copy(def).(PageMarginsOptionsPtr)
|
||||
val2 := deepcopy.Copy(def).(PageMarginsOptionsPtr)
|
||||
|
||||
f := NewFile()
|
||||
// Get the default value
|
||||
assert.NoError(t, f.GetPageMargins(sheet, def), opts)
|
||||
// Get again and check
|
||||
assert.NoError(t, f.GetPageMargins(sheet, val1), opts)
|
||||
if !assert.Equal(t, val1, def, opts) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Set the same value
|
||||
assert.NoError(t, f.SetPageMargins(sheet, val1), opts)
|
||||
// Get again and check
|
||||
assert.NoError(t, f.GetPageMargins(sheet, val1), opts)
|
||||
if !assert.Equal(t, val1, def, "%T: value should not have changed", opts) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Set a different value
|
||||
assert.NoError(t, f.SetPageMargins(sheet, test.nonDefault), opts)
|
||||
assert.NoError(t, f.GetPageMargins(sheet, val1), opts)
|
||||
// Get again and compare
|
||||
assert.NoError(t, f.GetPageMargins(sheet, val2), opts)
|
||||
if !assert.Equal(t, val1, val2, "%T: value should not have changed", opts) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Value should not be the same as the default
|
||||
if !assert.NotEqual(t, def, val1, "%T: value should have changed from default", opts) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Restore the default value
|
||||
assert.NoError(t, f.SetPageMargins(sheet, def), opts)
|
||||
assert.NoError(t, f.GetPageMargins(sheet, val1), opts)
|
||||
if !assert.Equal(t, def, val1) {
|
||||
t.FailNow()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetPageMargins(t *testing.T) {
|
||||
f := NewFile()
|
||||
assert.NoError(t, f.SetPageMargins("Sheet1", nil))
|
||||
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
|
||||
assert.True(t, ok)
|
||||
ws.(*xlsxWorksheet).PageMargins = nil
|
||||
ws.(*xlsxWorksheet).PrintOptions = nil
|
||||
expected := PageLayoutMarginsOptions{
|
||||
Bottom: float64Ptr(1.0),
|
||||
Footer: float64Ptr(1.0),
|
||||
Header: float64Ptr(1.0),
|
||||
Left: float64Ptr(1.0),
|
||||
Right: float64Ptr(1.0),
|
||||
Top: float64Ptr(1.0),
|
||||
Horizontally: boolPtr(true),
|
||||
Vertically: boolPtr(true),
|
||||
}
|
||||
assert.NoError(t, f.SetPageMargins("Sheet1", &expected))
|
||||
opts, err := f.GetPageMargins("Sheet1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, opts)
|
||||
// Test set page margins on not exists worksheet.
|
||||
assert.EqualError(t, f.SetPageMargins("SheetN"), "sheet SheetN does not exist")
|
||||
assert.EqualError(t, f.SetPageMargins("SheetN", nil), "sheet SheetN does not exist")
|
||||
}
|
||||
|
||||
func TestGetPageMargins(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test get page margins on not exists worksheet.
|
||||
assert.EqualError(t, f.GetPageMargins("SheetN"), "sheet SheetN does not exist")
|
||||
_, err := f.GetPageMargins("SheetN")
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
}
|
||||
|
||||
func ExampleFile_SetSheetFormatPr() {
|
||||
func TestDebug(t *testing.T) {
|
||||
f := NewFile()
|
||||
const sheet = "Sheet1"
|
||||
|
||||
if err := f.SetSheetFormatPr(sheet,
|
||||
BaseColWidth(1.0),
|
||||
DefaultColWidth(1.0),
|
||||
DefaultRowHeight(1.0),
|
||||
CustomHeight(true),
|
||||
ZeroHeight(true),
|
||||
ThickTop(true),
|
||||
ThickBottom(true),
|
||||
); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
// Output:
|
||||
}
|
||||
|
||||
func ExampleFile_GetSheetFormatPr() {
|
||||
f := NewFile()
|
||||
const sheet = "Sheet1"
|
||||
|
||||
var (
|
||||
baseColWidth BaseColWidth
|
||||
defaultColWidth DefaultColWidth
|
||||
defaultRowHeight DefaultRowHeight
|
||||
customHeight CustomHeight
|
||||
zeroHeight ZeroHeight
|
||||
thickTop ThickTop
|
||||
thickBottom ThickBottom
|
||||
)
|
||||
|
||||
if err := f.GetSheetFormatPr(sheet,
|
||||
&baseColWidth,
|
||||
&defaultColWidth,
|
||||
&defaultRowHeight,
|
||||
&customHeight,
|
||||
&zeroHeight,
|
||||
&thickTop,
|
||||
&thickBottom,
|
||||
); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println("Defaults:")
|
||||
fmt.Println("- baseColWidth:", baseColWidth)
|
||||
fmt.Println("- defaultColWidth:", defaultColWidth)
|
||||
fmt.Println("- defaultRowHeight:", defaultRowHeight)
|
||||
fmt.Println("- customHeight:", customHeight)
|
||||
fmt.Println("- zeroHeight:", zeroHeight)
|
||||
fmt.Println("- thickTop:", thickTop)
|
||||
fmt.Println("- thickBottom:", thickBottom)
|
||||
// Output:
|
||||
// Defaults:
|
||||
// - baseColWidth: 0
|
||||
// - defaultColWidth: 0
|
||||
// - defaultRowHeight: 15
|
||||
// - customHeight: false
|
||||
// - zeroHeight: false
|
||||
// - thickTop: false
|
||||
// - thickBottom: false
|
||||
}
|
||||
|
||||
func TestSheetFormatPrOptions(t *testing.T) {
|
||||
const sheet = "Sheet1"
|
||||
|
||||
testData := []struct {
|
||||
container SheetFormatPrOptionsPtr
|
||||
nonDefault SheetFormatPrOptions
|
||||
}{
|
||||
{new(BaseColWidth), BaseColWidth(1.0)},
|
||||
{new(DefaultColWidth), DefaultColWidth(1.0)},
|
||||
{new(DefaultRowHeight), DefaultRowHeight(1.0)},
|
||||
{new(CustomHeight), CustomHeight(true)},
|
||||
{new(ZeroHeight), ZeroHeight(true)},
|
||||
{new(ThickTop), ThickTop(true)},
|
||||
{new(ThickBottom), ThickBottom(true)},
|
||||
}
|
||||
|
||||
for i, test := range testData {
|
||||
t.Run(fmt.Sprintf("TestData%d", i), func(t *testing.T) {
|
||||
opts := test.nonDefault
|
||||
t.Logf("option %T", opts)
|
||||
|
||||
def := deepcopy.Copy(test.container).(SheetFormatPrOptionsPtr)
|
||||
val1 := deepcopy.Copy(def).(SheetFormatPrOptionsPtr)
|
||||
val2 := deepcopy.Copy(def).(SheetFormatPrOptionsPtr)
|
||||
|
||||
f := NewFile()
|
||||
// Get the default value
|
||||
assert.NoError(t, f.GetSheetFormatPr(sheet, def), opts)
|
||||
// Get again and check
|
||||
assert.NoError(t, f.GetSheetFormatPr(sheet, val1), opts)
|
||||
if !assert.Equal(t, val1, def, opts) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Set the same value
|
||||
assert.NoError(t, f.SetSheetFormatPr(sheet, val1), opts)
|
||||
// Get again and check
|
||||
assert.NoError(t, f.GetSheetFormatPr(sheet, val1), opts)
|
||||
if !assert.Equal(t, val1, def, "%T: value should not have changed", opts) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Set a different value
|
||||
assert.NoError(t, f.SetSheetFormatPr(sheet, test.nonDefault), opts)
|
||||
assert.NoError(t, f.GetSheetFormatPr(sheet, val1), opts)
|
||||
// Get again and compare
|
||||
assert.NoError(t, f.GetSheetFormatPr(sheet, val2), opts)
|
||||
if !assert.Equal(t, val1, val2, "%T: value should not have changed", opts) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Value should not be the same as the default
|
||||
if !assert.NotEqual(t, def, val1, "%T: value should have changed from default", opts) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Restore the default value
|
||||
assert.NoError(t, f.SetSheetFormatPr(sheet, def), opts)
|
||||
assert.NoError(t, f.GetSheetFormatPr(sheet, val1), opts)
|
||||
if !assert.Equal(t, def, val1) {
|
||||
t.FailNow()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetSheetFormatPr(t *testing.T) {
|
||||
f := NewFile()
|
||||
assert.NoError(t, f.GetSheetFormatPr("Sheet1"))
|
||||
assert.NoError(t, f.SetSheetProps("Sheet1", nil))
|
||||
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
|
||||
assert.True(t, ok)
|
||||
ws.(*xlsxWorksheet).PageMargins = nil
|
||||
ws.(*xlsxWorksheet).PrintOptions = nil
|
||||
ws.(*xlsxWorksheet).SheetPr = nil
|
||||
ws.(*xlsxWorksheet).SheetFormatPr = nil
|
||||
assert.NoError(t, f.SetSheetFormatPr("Sheet1", BaseColWidth(1.0)))
|
||||
// Test set formatting properties on not exists worksheet.
|
||||
assert.EqualError(t, f.SetSheetFormatPr("SheetN"), "sheet SheetN does not exist")
|
||||
// w := uint8(10)
|
||||
// f.SetSheetProps("Sheet1", &SheetPropsOptions{BaseColWidth: &w})
|
||||
f.SetPageMargins("Sheet1", &PageLayoutMarginsOptions{Horizontally: boolPtr(true)})
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestDebug.xlsx")))
|
||||
}
|
||||
|
||||
func TestGetSheetFormatPr(t *testing.T) {
|
||||
func TestSetSheetProps(t *testing.T) {
|
||||
f := NewFile()
|
||||
assert.NoError(t, f.GetSheetFormatPr("Sheet1"))
|
||||
assert.NoError(t, f.SetSheetProps("Sheet1", nil))
|
||||
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
|
||||
assert.True(t, ok)
|
||||
ws.(*xlsxWorksheet).SheetPr = nil
|
||||
ws.(*xlsxWorksheet).SheetFormatPr = nil
|
||||
var (
|
||||
baseColWidth BaseColWidth
|
||||
defaultColWidth DefaultColWidth
|
||||
defaultRowHeight DefaultRowHeight
|
||||
customHeight CustomHeight
|
||||
zeroHeight ZeroHeight
|
||||
thickTop ThickTop
|
||||
thickBottom ThickBottom
|
||||
)
|
||||
assert.NoError(t, f.GetSheetFormatPr("Sheet1",
|
||||
&baseColWidth,
|
||||
&defaultColWidth,
|
||||
&defaultRowHeight,
|
||||
&customHeight,
|
||||
&zeroHeight,
|
||||
&thickTop,
|
||||
&thickBottom,
|
||||
))
|
||||
// Test get formatting properties on not exists worksheet.
|
||||
assert.EqualError(t, f.GetSheetFormatPr("SheetN"), "sheet SheetN does not exist")
|
||||
baseColWidth := uint8(8)
|
||||
expected := SheetPropsOptions{
|
||||
CodeName: stringPtr("code"),
|
||||
EnableFormatConditionsCalculation: boolPtr(true),
|
||||
Published: boolPtr(true),
|
||||
AutoPageBreaks: boolPtr(true),
|
||||
FitToPage: boolPtr(true),
|
||||
TabColorIndexed: intPtr(1),
|
||||
TabColorRGB: stringPtr("#FFFF00"),
|
||||
TabColorTheme: intPtr(1),
|
||||
TabColorTint: float64Ptr(1),
|
||||
OutlineSummaryBelow: boolPtr(true),
|
||||
BaseColWidth: &baseColWidth,
|
||||
DefaultColWidth: float64Ptr(10),
|
||||
DefaultRowHeight: float64Ptr(10),
|
||||
CustomHeight: boolPtr(true),
|
||||
ZeroHeight: boolPtr(true),
|
||||
ThickTop: boolPtr(true),
|
||||
ThickBottom: boolPtr(true),
|
||||
}
|
||||
assert.NoError(t, f.SetSheetProps("Sheet1", &expected))
|
||||
opts, err := f.GetSheetProps("Sheet1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, opts)
|
||||
|
||||
ws.(*xlsxWorksheet).SheetPr = nil
|
||||
assert.NoError(t, f.SetSheetProps("Sheet1", &SheetPropsOptions{FitToPage: boolPtr(true)}))
|
||||
ws.(*xlsxWorksheet).SheetPr = nil
|
||||
assert.NoError(t, f.SetSheetProps("Sheet1", &SheetPropsOptions{TabColorRGB: stringPtr("#FFFF00")}))
|
||||
ws.(*xlsxWorksheet).SheetPr = nil
|
||||
assert.NoError(t, f.SetSheetProps("Sheet1", &SheetPropsOptions{TabColorTheme: intPtr(1)}))
|
||||
ws.(*xlsxWorksheet).SheetPr = nil
|
||||
assert.NoError(t, f.SetSheetProps("Sheet1", &SheetPropsOptions{TabColorTint: float64Ptr(1)}))
|
||||
|
||||
// Test SetSheetProps on not exists worksheet.
|
||||
assert.EqualError(t, f.SetSheetProps("SheetN", nil), "sheet SheetN does not exist")
|
||||
}
|
||||
|
||||
func TestGetSheetProps(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test GetSheetProps on not exists worksheet.
|
||||
_, err := f.GetSheetProps("SheetN")
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
}
|
||||
|
|
287
sheetview.go
287
sheetview.go
|
@ -13,150 +13,6 @@ package excelize
|
|||
|
||||
import "fmt"
|
||||
|
||||
// SheetViewOption is an option of a view of a worksheet. See
|
||||
// SetSheetViewOptions().
|
||||
type SheetViewOption interface {
|
||||
setSheetViewOption(view *xlsxSheetView)
|
||||
}
|
||||
|
||||
// SheetViewOptionPtr is a writable SheetViewOption. See
|
||||
// GetSheetViewOptions().
|
||||
type SheetViewOptionPtr interface {
|
||||
SheetViewOption
|
||||
getSheetViewOption(view *xlsxSheetView)
|
||||
}
|
||||
|
||||
type (
|
||||
// DefaultGridColor is a SheetViewOption. It specifies a flag indicating
|
||||
// that the consuming application should use the default grid lines color
|
||||
// (system dependent). Overrides any color specified in colorId.
|
||||
DefaultGridColor bool
|
||||
// ShowFormulas is a SheetViewOption. It specifies a flag indicating
|
||||
// whether this sheet should display formulas.
|
||||
ShowFormulas bool
|
||||
// ShowGridLines is a SheetViewOption. It specifies a flag indicating
|
||||
// whether this sheet should display gridlines.
|
||||
ShowGridLines bool
|
||||
// ShowRowColHeaders is a SheetViewOption. It specifies a flag indicating
|
||||
// whether the sheet should display row and column headings.
|
||||
ShowRowColHeaders bool
|
||||
// ShowZeros is a SheetViewOption. It specifies a flag indicating whether
|
||||
// to "show a zero in cells that have zero value". When using a formula to
|
||||
// reference another cell which is empty, the referenced value becomes 0
|
||||
// when the flag is true. (Default setting is true.)
|
||||
ShowZeros bool
|
||||
// RightToLeft is a SheetViewOption. It specifies a flag indicating whether
|
||||
// the sheet is in 'right to left' display mode. When in this mode, Column
|
||||
// A is on the far right, Column B ;is one column left of Column A, and so
|
||||
// on. Also, information in cells is displayed in the Right to Left format.
|
||||
RightToLeft bool
|
||||
// ShowRuler is a SheetViewOption. It specifies a flag indicating this
|
||||
// sheet should display ruler.
|
||||
ShowRuler bool
|
||||
// View is a SheetViewOption. It specifies a flag indicating how sheet is
|
||||
// displayed, by default it uses empty string available options: normal,
|
||||
// pageLayout, pageBreakPreview
|
||||
View string
|
||||
// TopLeftCell is a SheetViewOption. It specifies a location of the top
|
||||
// left visible cell Location of the top left visible cell in the bottom
|
||||
// right pane (when in Left-to-Right mode).
|
||||
TopLeftCell string
|
||||
// ZoomScale is a SheetViewOption. It specifies a window zoom magnification
|
||||
// for current view representing percent values. This attribute is
|
||||
// restricted to values ranging from 10 to 400. Horizontal & Vertical
|
||||
// scale together.
|
||||
ZoomScale float64
|
||||
)
|
||||
|
||||
// Defaults for each option are described in XML schema for CT_SheetView
|
||||
|
||||
func (o DefaultGridColor) setSheetViewOption(view *xlsxSheetView) {
|
||||
view.DefaultGridColor = boolPtr(bool(o))
|
||||
}
|
||||
|
||||
func (o *DefaultGridColor) getSheetViewOption(view *xlsxSheetView) {
|
||||
*o = DefaultGridColor(defaultTrue(view.DefaultGridColor)) // Excel default: true
|
||||
}
|
||||
|
||||
func (o ShowFormulas) setSheetViewOption(view *xlsxSheetView) {
|
||||
view.ShowFormulas = bool(o) // Excel default: false
|
||||
}
|
||||
|
||||
func (o *ShowFormulas) getSheetViewOption(view *xlsxSheetView) {
|
||||
*o = ShowFormulas(view.ShowFormulas) // Excel default: false
|
||||
}
|
||||
|
||||
func (o ShowGridLines) setSheetViewOption(view *xlsxSheetView) {
|
||||
view.ShowGridLines = boolPtr(bool(o))
|
||||
}
|
||||
|
||||
func (o *ShowGridLines) getSheetViewOption(view *xlsxSheetView) {
|
||||
*o = ShowGridLines(defaultTrue(view.ShowGridLines)) // Excel default: true
|
||||
}
|
||||
|
||||
func (o ShowRowColHeaders) setSheetViewOption(view *xlsxSheetView) {
|
||||
view.ShowRowColHeaders = boolPtr(bool(o))
|
||||
}
|
||||
|
||||
func (o *ShowRowColHeaders) getSheetViewOption(view *xlsxSheetView) {
|
||||
*o = ShowRowColHeaders(defaultTrue(view.ShowRowColHeaders)) // Excel default: true
|
||||
}
|
||||
|
||||
func (o ShowZeros) setSheetViewOption(view *xlsxSheetView) {
|
||||
view.ShowZeros = boolPtr(bool(o))
|
||||
}
|
||||
|
||||
func (o *ShowZeros) getSheetViewOption(view *xlsxSheetView) {
|
||||
*o = ShowZeros(defaultTrue(view.ShowZeros)) // Excel default: true
|
||||
}
|
||||
|
||||
func (o RightToLeft) setSheetViewOption(view *xlsxSheetView) {
|
||||
view.RightToLeft = bool(o) // Excel default: false
|
||||
}
|
||||
|
||||
func (o *RightToLeft) getSheetViewOption(view *xlsxSheetView) {
|
||||
*o = RightToLeft(view.RightToLeft)
|
||||
}
|
||||
|
||||
func (o ShowRuler) setSheetViewOption(view *xlsxSheetView) {
|
||||
view.ShowRuler = boolPtr(bool(o))
|
||||
}
|
||||
|
||||
func (o *ShowRuler) getSheetViewOption(view *xlsxSheetView) {
|
||||
*o = ShowRuler(defaultTrue(view.ShowRuler)) // Excel default: true
|
||||
}
|
||||
|
||||
func (o View) setSheetViewOption(view *xlsxSheetView) {
|
||||
view.View = string(o)
|
||||
}
|
||||
|
||||
func (o *View) getSheetViewOption(view *xlsxSheetView) {
|
||||
if view.View != "" {
|
||||
*o = View(view.View)
|
||||
return
|
||||
}
|
||||
*o = "normal"
|
||||
}
|
||||
|
||||
func (o TopLeftCell) setSheetViewOption(view *xlsxSheetView) {
|
||||
view.TopLeftCell = string(o)
|
||||
}
|
||||
|
||||
func (o *TopLeftCell) getSheetViewOption(view *xlsxSheetView) {
|
||||
*o = TopLeftCell(view.TopLeftCell)
|
||||
}
|
||||
|
||||
func (o ZoomScale) setSheetViewOption(view *xlsxSheetView) {
|
||||
// This attribute is restricted to values ranging from 10 to 400.
|
||||
if float64(o) >= 10 && float64(o) <= 400 {
|
||||
view.ZoomScale = float64(o)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *ZoomScale) getSheetViewOption(view *xlsxSheetView) {
|
||||
*o = ZoomScale(view.ZoomScale)
|
||||
}
|
||||
|
||||
// getSheetView returns the SheetView object
|
||||
func (f *File) getSheetView(sheet string, viewIndex int) (*xlsxSheetView, error) {
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
|
@ -180,65 +36,100 @@ func (f *File) getSheetView(sheet string, viewIndex int) (*xlsxSheetView, error)
|
|||
return &(ws.SheetViews.SheetView[viewIndex]), err
|
||||
}
|
||||
|
||||
// SetSheetViewOptions sets sheet view options. The viewIndex may be negative
|
||||
// and if so is counted backward (-1 is the last view).
|
||||
//
|
||||
// Available options:
|
||||
//
|
||||
// DefaultGridColor(bool)
|
||||
// ShowFormulas(bool)
|
||||
// ShowGridLines(bool)
|
||||
// ShowRowColHeaders(bool)
|
||||
// ShowZeros(bool)
|
||||
// RightToLeft(bool)
|
||||
// ShowRuler(bool)
|
||||
// View(string)
|
||||
// TopLeftCell(string)
|
||||
// ZoomScale(float64)
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// err = f.SetSheetViewOptions("Sheet1", -1, ShowGridLines(false))
|
||||
func (f *File) SetSheetViewOptions(sheet string, viewIndex int, opts ...SheetViewOption) error {
|
||||
// setSheetView set sheet view by given options.
|
||||
func (view *xlsxSheetView) setSheetView(opts *ViewOptions) {
|
||||
if opts.DefaultGridColor != nil {
|
||||
view.DefaultGridColor = opts.DefaultGridColor
|
||||
}
|
||||
if opts.RightToLeft != nil {
|
||||
view.RightToLeft = *opts.RightToLeft
|
||||
}
|
||||
if opts.ShowFormulas != nil {
|
||||
view.ShowFormulas = *opts.ShowFormulas
|
||||
}
|
||||
if opts.ShowGridLines != nil {
|
||||
view.ShowGridLines = opts.ShowGridLines
|
||||
}
|
||||
if opts.ShowRowColHeaders != nil {
|
||||
view.ShowRowColHeaders = opts.ShowRowColHeaders
|
||||
}
|
||||
if opts.ShowRuler != nil {
|
||||
view.ShowRuler = opts.ShowRuler
|
||||
}
|
||||
if opts.ShowZeros != nil {
|
||||
view.ShowZeros = opts.ShowZeros
|
||||
}
|
||||
if opts.TopLeftCell != nil {
|
||||
view.TopLeftCell = *opts.TopLeftCell
|
||||
}
|
||||
if opts.View != nil {
|
||||
if _, ok := map[string]interface{}{
|
||||
"normal": nil,
|
||||
"pageLayout": nil,
|
||||
"pageBreakPreview": nil,
|
||||
}[*opts.View]; ok {
|
||||
view.View = *opts.View
|
||||
}
|
||||
}
|
||||
if opts.ZoomScale != nil && *opts.ZoomScale >= 10 && *opts.ZoomScale <= 400 {
|
||||
view.ZoomScale = *opts.ZoomScale
|
||||
}
|
||||
}
|
||||
|
||||
// SetSheetView sets sheet view options. The viewIndex may be negative and if
|
||||
// so is counted backward (-1 is the last view).
|
||||
func (f *File) SetSheetView(sheet string, viewIndex int, opts *ViewOptions) error {
|
||||
view, err := f.getSheetView(sheet, viewIndex)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt.setSheetViewOption(view)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSheetViewOptions gets the value of sheet view options. The viewIndex may
|
||||
// be negative and if so is counted backward (-1 is the last view).
|
||||
//
|
||||
// Available options:
|
||||
//
|
||||
// DefaultGridColor(bool)
|
||||
// ShowFormulas(bool)
|
||||
// ShowGridLines(bool)
|
||||
// ShowRowColHeaders(bool)
|
||||
// ShowZeros(bool)
|
||||
// RightToLeft(bool)
|
||||
// ShowRuler(bool)
|
||||
// View(string)
|
||||
// TopLeftCell(string)
|
||||
// ZoomScale(float64)
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var showGridLines excelize.ShowGridLines
|
||||
// err = f.GetSheetViewOptions("Sheet1", -1, &showGridLines)
|
||||
func (f *File) GetSheetViewOptions(sheet string, viewIndex int, opts ...SheetViewOptionPtr) error {
|
||||
view, err := f.getSheetView(sheet, viewIndex)
|
||||
if err != nil {
|
||||
if opts == nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt.getSheetViewOption(view)
|
||||
}
|
||||
view.setSheetView(opts)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSheetView gets the value of sheet view options. The viewIndex may be
|
||||
// negative and if so is counted backward (-1 is the last view).
|
||||
func (f *File) GetSheetView(sheet string, viewIndex int) (ViewOptions, error) {
|
||||
opts := ViewOptions{
|
||||
DefaultGridColor: boolPtr(true),
|
||||
ShowFormulas: boolPtr(true),
|
||||
ShowGridLines: boolPtr(true),
|
||||
ShowRowColHeaders: boolPtr(true),
|
||||
ShowRuler: boolPtr(true),
|
||||
ShowZeros: boolPtr(true),
|
||||
View: stringPtr("normal"),
|
||||
ZoomScale: float64Ptr(100),
|
||||
}
|
||||
view, err := f.getSheetView(sheet, viewIndex)
|
||||
if err != nil {
|
||||
return opts, err
|
||||
}
|
||||
if view.DefaultGridColor != nil {
|
||||
opts.DefaultGridColor = view.DefaultGridColor
|
||||
}
|
||||
opts.RightToLeft = boolPtr(view.RightToLeft)
|
||||
opts.ShowFormulas = boolPtr(view.ShowFormulas)
|
||||
if view.ShowGridLines != nil {
|
||||
opts.ShowGridLines = view.ShowGridLines
|
||||
}
|
||||
if view.ShowRowColHeaders != nil {
|
||||
opts.ShowRowColHeaders = view.ShowRowColHeaders
|
||||
}
|
||||
if view.ShowRuler != nil {
|
||||
opts.ShowRuler = view.ShowRuler
|
||||
}
|
||||
if view.ShowZeros != nil {
|
||||
opts.ShowZeros = view.ShowZeros
|
||||
}
|
||||
opts.TopLeftCell = stringPtr(view.TopLeftCell)
|
||||
if view.View != "" {
|
||||
opts.View = stringPtr(view.View)
|
||||
}
|
||||
if view.ZoomScale >= 10 && view.ZoomScale <= 400 {
|
||||
opts.ZoomScale = float64Ptr(view.ZoomScale)
|
||||
}
|
||||
return opts, err
|
||||
}
|
||||
|
|
|
@ -1,218 +1,50 @@
|
|||
package excelize
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var _ = []SheetViewOption{
|
||||
DefaultGridColor(true),
|
||||
ShowFormulas(false),
|
||||
ShowGridLines(true),
|
||||
ShowRowColHeaders(true),
|
||||
ShowZeros(true),
|
||||
RightToLeft(false),
|
||||
ShowRuler(false),
|
||||
View("pageLayout"),
|
||||
TopLeftCell("B2"),
|
||||
ZoomScale(100),
|
||||
// SheetViewOptionPtr are also SheetViewOption
|
||||
new(DefaultGridColor),
|
||||
new(ShowFormulas),
|
||||
new(ShowGridLines),
|
||||
new(ShowRowColHeaders),
|
||||
new(ShowZeros),
|
||||
new(RightToLeft),
|
||||
new(ShowRuler),
|
||||
new(View),
|
||||
new(TopLeftCell),
|
||||
new(ZoomScale),
|
||||
}
|
||||
|
||||
var _ = []SheetViewOptionPtr{
|
||||
(*DefaultGridColor)(nil),
|
||||
(*ShowFormulas)(nil),
|
||||
(*ShowGridLines)(nil),
|
||||
(*ShowRowColHeaders)(nil),
|
||||
(*ShowZeros)(nil),
|
||||
(*RightToLeft)(nil),
|
||||
(*ShowRuler)(nil),
|
||||
(*View)(nil),
|
||||
(*TopLeftCell)(nil),
|
||||
(*ZoomScale)(nil),
|
||||
}
|
||||
|
||||
func ExampleFile_SetSheetViewOptions() {
|
||||
func TestSetView(t *testing.T) {
|
||||
f := NewFile()
|
||||
const sheet = "Sheet1"
|
||||
|
||||
if err := f.SetSheetViewOptions(sheet, 0,
|
||||
DefaultGridColor(false),
|
||||
ShowFormulas(true),
|
||||
ShowGridLines(true),
|
||||
ShowRowColHeaders(true),
|
||||
RightToLeft(false),
|
||||
ShowRuler(false),
|
||||
View("pageLayout"),
|
||||
TopLeftCell("C3"),
|
||||
ZoomScale(80),
|
||||
); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
var zoomScale ZoomScale
|
||||
fmt.Println("Default:")
|
||||
fmt.Println("- zoomScale: 80")
|
||||
|
||||
if err := f.SetSheetViewOptions(sheet, 0, ZoomScale(500)); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if err := f.GetSheetViewOptions(sheet, 0, &zoomScale); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
fmt.Println("Used out of range value:")
|
||||
fmt.Println("- zoomScale:", zoomScale)
|
||||
|
||||
if err := f.SetSheetViewOptions(sheet, 0, ZoomScale(123)); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if err := f.GetSheetViewOptions(sheet, 0, &zoomScale); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
fmt.Println("Used correct value:")
|
||||
fmt.Println("- zoomScale:", zoomScale)
|
||||
|
||||
// Output:
|
||||
// Default:
|
||||
// - zoomScale: 80
|
||||
// Used out of range value:
|
||||
// - zoomScale: 80
|
||||
// Used correct value:
|
||||
// - zoomScale: 123
|
||||
}
|
||||
|
||||
func ExampleFile_GetSheetViewOptions() {
|
||||
f := NewFile()
|
||||
const sheet = "Sheet1"
|
||||
|
||||
var (
|
||||
defaultGridColor DefaultGridColor
|
||||
showFormulas ShowFormulas
|
||||
showGridLines ShowGridLines
|
||||
showRowColHeaders ShowRowColHeaders
|
||||
showZeros ShowZeros
|
||||
rightToLeft RightToLeft
|
||||
showRuler ShowRuler
|
||||
view View
|
||||
topLeftCell TopLeftCell
|
||||
zoomScale ZoomScale
|
||||
)
|
||||
|
||||
if err := f.GetSheetViewOptions(sheet, 0,
|
||||
&defaultGridColor,
|
||||
&showFormulas,
|
||||
&showGridLines,
|
||||
&showRowColHeaders,
|
||||
&showZeros,
|
||||
&rightToLeft,
|
||||
&showRuler,
|
||||
&view,
|
||||
&topLeftCell,
|
||||
&zoomScale,
|
||||
); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
fmt.Println("Default:")
|
||||
fmt.Println("- defaultGridColor:", defaultGridColor)
|
||||
fmt.Println("- showFormulas:", showFormulas)
|
||||
fmt.Println("- showGridLines:", showGridLines)
|
||||
fmt.Println("- showRowColHeaders:", showRowColHeaders)
|
||||
fmt.Println("- showZeros:", showZeros)
|
||||
fmt.Println("- rightToLeft:", rightToLeft)
|
||||
fmt.Println("- showRuler:", showRuler)
|
||||
fmt.Println("- view:", view)
|
||||
fmt.Println("- topLeftCell:", `"`+topLeftCell+`"`)
|
||||
fmt.Println("- zoomScale:", zoomScale)
|
||||
|
||||
if err := f.SetSheetViewOptions(sheet, 0, ShowGridLines(false)); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if err := f.GetSheetViewOptions(sheet, 0, &showGridLines); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if err := f.SetSheetViewOptions(sheet, 0, ShowZeros(false)); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if err := f.GetSheetViewOptions(sheet, 0, &showZeros); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if err := f.SetSheetViewOptions(sheet, 0, View("pageLayout")); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if err := f.GetSheetViewOptions(sheet, 0, &view); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if err := f.SetSheetViewOptions(sheet, 0, TopLeftCell("B2")); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if err := f.GetSheetViewOptions(sheet, 0, &topLeftCell); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
fmt.Println("After change:")
|
||||
fmt.Println("- showGridLines:", showGridLines)
|
||||
fmt.Println("- showZeros:", showZeros)
|
||||
fmt.Println("- view:", view)
|
||||
fmt.Println("- topLeftCell:", topLeftCell)
|
||||
|
||||
// Output:
|
||||
// Default:
|
||||
// - defaultGridColor: true
|
||||
// - showFormulas: false
|
||||
// - showGridLines: true
|
||||
// - showRowColHeaders: true
|
||||
// - showZeros: true
|
||||
// - rightToLeft: false
|
||||
// - showRuler: true
|
||||
// - view: normal
|
||||
// - topLeftCell: ""
|
||||
// - zoomScale: 0
|
||||
// After change:
|
||||
// - showGridLines: false
|
||||
// - showZeros: false
|
||||
// - view: pageLayout
|
||||
// - topLeftCell: B2
|
||||
}
|
||||
|
||||
func TestSheetViewOptionsErrors(t *testing.T) {
|
||||
f := NewFile()
|
||||
const sheet = "Sheet1"
|
||||
|
||||
assert.NoError(t, f.GetSheetViewOptions(sheet, 0))
|
||||
assert.NoError(t, f.GetSheetViewOptions(sheet, -1))
|
||||
assert.Error(t, f.GetSheetViewOptions(sheet, 1))
|
||||
assert.Error(t, f.GetSheetViewOptions(sheet, -2))
|
||||
assert.NoError(t, f.SetSheetViewOptions(sheet, 0))
|
||||
assert.NoError(t, f.SetSheetViewOptions(sheet, -1))
|
||||
assert.Error(t, f.SetSheetViewOptions(sheet, 1))
|
||||
assert.Error(t, f.SetSheetViewOptions(sheet, -2))
|
||||
|
||||
assert.NoError(t, f.SetSheetView("Sheet1", -1, nil))
|
||||
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
|
||||
assert.True(t, ok)
|
||||
ws.(*xlsxWorksheet).SheetViews = nil
|
||||
assert.NoError(t, f.GetSheetViewOptions(sheet, 0))
|
||||
expected := ViewOptions{
|
||||
DefaultGridColor: boolPtr(false),
|
||||
RightToLeft: boolPtr(false),
|
||||
ShowFormulas: boolPtr(false),
|
||||
ShowGridLines: boolPtr(false),
|
||||
ShowRowColHeaders: boolPtr(false),
|
||||
ShowRuler: boolPtr(false),
|
||||
ShowZeros: boolPtr(false),
|
||||
TopLeftCell: stringPtr("A1"),
|
||||
View: stringPtr("normal"),
|
||||
ZoomScale: float64Ptr(120),
|
||||
}
|
||||
assert.NoError(t, f.SetSheetView("Sheet1", 0, &expected))
|
||||
opts, err := f.GetSheetView("Sheet1", 0)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, opts)
|
||||
// Test set sheet view options with invalid view index.
|
||||
assert.EqualError(t, f.SetSheetView("Sheet1", 1, nil), "view index 1 out of range")
|
||||
assert.EqualError(t, f.SetSheetView("Sheet1", -2, nil), "view index -2 out of range")
|
||||
// Test set sheet view options on not exists worksheet.
|
||||
assert.EqualError(t, f.SetSheetView("SheetN", 0, nil), "sheet SheetN does not exist")
|
||||
}
|
||||
|
||||
func TestGetView(t *testing.T) {
|
||||
f := NewFile()
|
||||
_, err := f.getSheetView("SheetN", 0)
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
// Test get sheet view options with invalid view index.
|
||||
_, err = f.GetSheetView("Sheet1", 1)
|
||||
assert.EqualError(t, err, "view index 1 out of range")
|
||||
_, err = f.GetSheetView("Sheet1", -2)
|
||||
assert.EqualError(t, err, "view index -2 out of range")
|
||||
// Test get sheet view options on not exists worksheet.
|
||||
_, err = f.GetSheetView("SheetN", 0)
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
}
|
||||
|
|
34
sparkline.go
34
sparkline.go
|
@ -387,8 +387,9 @@ func (f *File) addSparklineGroupByStyle(ID int) *xlsxX14SparklineGroup {
|
|||
// Markers | Toggle sparkline markers
|
||||
// ColorAxis | An RGB Color is specified as RRGGBB
|
||||
// Axis | Show sparkline axis
|
||||
func (f *File) AddSparkline(sheet string, opts *SparklineOption) (err error) {
|
||||
func (f *File) AddSparkline(sheet string, opts *SparklineOptions) error {
|
||||
var (
|
||||
err error
|
||||
ws *xlsxWorksheet
|
||||
sparkType string
|
||||
sparkTypes map[string]string
|
||||
|
@ -401,7 +402,7 @@ func (f *File) AddSparkline(sheet string, opts *SparklineOption) (err error) {
|
|||
|
||||
// parameter validation
|
||||
if ws, err = f.parseFormatAddSparklineSet(sheet, opts); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
// Handle the sparkline type
|
||||
sparkType = "line"
|
||||
|
@ -409,7 +410,7 @@ func (f *File) AddSparkline(sheet string, opts *SparklineOption) (err error) {
|
|||
if opts.Type != "" {
|
||||
if specifiedSparkTypes, ok = sparkTypes[opts.Type]; !ok {
|
||||
err = ErrSparklineType
|
||||
return
|
||||
return err
|
||||
}
|
||||
sparkType = specifiedSparkTypes
|
||||
}
|
||||
|
@ -435,7 +436,7 @@ func (f *File) AddSparkline(sheet string, opts *SparklineOption) (err error) {
|
|||
f.addSparkline(opts, group)
|
||||
if ws.ExtLst.Ext != "" { // append mode ext
|
||||
if err = f.appendSparkline(ws, group, groups); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
groups = &xlsxX14SparklineGroups{
|
||||
|
@ -443,23 +444,23 @@ func (f *File) AddSparkline(sheet string, opts *SparklineOption) (err error) {
|
|||
SparklineGroups: []*xlsxX14SparklineGroup{group},
|
||||
}
|
||||
if sparklineGroupsBytes, err = xml.Marshal(groups); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if extBytes, err = xml.Marshal(&xlsxWorksheetExt{
|
||||
URI: ExtURISparklineGroups,
|
||||
Content: string(sparklineGroupsBytes),
|
||||
}); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
ws.ExtLst.Ext = string(extBytes)
|
||||
}
|
||||
f.addSheetNameSpace(sheet, NameSpaceSpreadSheetX14)
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
// parseFormatAddSparklineSet provides a function to validate sparkline
|
||||
// properties.
|
||||
func (f *File) parseFormatAddSparklineSet(sheet string, opts *SparklineOption) (*xlsxWorksheet, error) {
|
||||
func (f *File) parseFormatAddSparklineSet(sheet string, opts *SparklineOptions) (*xlsxWorksheet, error) {
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return ws, err
|
||||
|
@ -488,7 +489,7 @@ func (f *File) parseFormatAddSparklineSet(sheet string, opts *SparklineOption) (
|
|||
|
||||
// addSparkline provides a function to create a sparkline in a sparkline group
|
||||
// by given properties.
|
||||
func (f *File) addSparkline(opts *SparklineOption, group *xlsxX14SparklineGroup) {
|
||||
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],
|
||||
|
@ -499,8 +500,9 @@ func (f *File) addSparkline(opts *SparklineOption, group *xlsxX14SparklineGroup)
|
|||
|
||||
// appendSparkline provides a function to append sparkline to sparkline
|
||||
// groups.
|
||||
func (f *File) appendSparkline(ws *xlsxWorksheet, group *xlsxX14SparklineGroup, groups *xlsxX14SparklineGroups) (err error) {
|
||||
func (f *File) appendSparkline(ws *xlsxWorksheet, group *xlsxX14SparklineGroup, groups *xlsxX14SparklineGroups) error {
|
||||
var (
|
||||
err error
|
||||
idx int
|
||||
decodeExtLst *decodeWorksheetExt
|
||||
decodeSparklineGroups *decodeX14SparklineGroups
|
||||
|
@ -510,17 +512,17 @@ func (f *File) appendSparkline(ws *xlsxWorksheet, group *xlsxX14SparklineGroup,
|
|||
decodeExtLst = new(decodeWorksheetExt)
|
||||
if err = f.xmlNewDecoder(strings.NewReader("<extLst>" + ws.ExtLst.Ext + "</extLst>")).
|
||||
Decode(decodeExtLst); err != nil && err != io.EOF {
|
||||
return
|
||||
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
|
||||
return err
|
||||
}
|
||||
if sparklineGroupBytes, err = xml.Marshal(group); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if groups == nil {
|
||||
groups = &xlsxX14SparklineGroups{}
|
||||
|
@ -528,16 +530,16 @@ func (f *File) appendSparkline(ws *xlsxWorksheet, group *xlsxX14SparklineGroup,
|
|||
groups.XMLNSXM = NameSpaceSpreadSheetExcel2006Main.Value
|
||||
groups.Content = decodeSparklineGroups.Content + string(sparklineGroupBytes)
|
||||
if sparklineGroupsBytes, err = xml.Marshal(groups); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
decodeExtLst.Ext[idx].Content = string(sparklineGroupsBytes)
|
||||
}
|
||||
}
|
||||
if extLstBytes, err = xml.Marshal(decodeExtLst); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
ws.ExtLst = &xlsxExtLst{
|
||||
Ext: strings.TrimSuffix(strings.TrimPrefix(string(extLstBytes), "<extLst>"), "</extLst>"),
|
||||
}
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -15,7 +15,10 @@ func TestAddSparkline(t *testing.T) {
|
|||
style, err := f.NewStyle(`{"font":{"bold":true}}`)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "B1", style))
|
||||
assert.NoError(t, f.SetSheetViewOptions("Sheet1", 0, ZoomScale(150)))
|
||||
viewOpts, err := f.GetSheetView("Sheet1", 0)
|
||||
assert.NoError(t, err)
|
||||
viewOpts.ZoomScale = float64Ptr(150)
|
||||
assert.NoError(t, f.SetSheetView("Sheet1", 0, &viewOpts))
|
||||
|
||||
assert.NoError(t, f.SetColWidth("Sheet1", "A", "A", 14))
|
||||
assert.NoError(t, f.SetColWidth("Sheet1", "B", "B", 50))
|
||||
|
@ -24,34 +27,34 @@ func TestAddSparkline(t *testing.T) {
|
|||
assert.NoError(t, f.SetCellValue("Sheet1", "B1", "Description"))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B2", `A default "line" sparkline.`))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A2"},
|
||||
Range: []string{"Sheet3!A1:J1"},
|
||||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B3", `A default "column" sparkline.`))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A3"},
|
||||
Range: []string{"Sheet3!A2:J2"},
|
||||
Type: "column",
|
||||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B4", `A default "win/loss" sparkline.`))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A4"},
|
||||
Range: []string{"Sheet3!A3:J3"},
|
||||
Type: "win_loss",
|
||||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B6", "Line with markers."))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A6"},
|
||||
Range: []string{"Sheet3!A1:J1"},
|
||||
Markers: true,
|
||||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B7", "Line with high and low points."))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A7"},
|
||||
Range: []string{"Sheet3!A1:J1"},
|
||||
High: true,
|
||||
|
@ -59,7 +62,7 @@ func TestAddSparkline(t *testing.T) {
|
|||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B8", "Line with first and last point markers."))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A8"},
|
||||
Range: []string{"Sheet3!A1:J1"},
|
||||
First: true,
|
||||
|
@ -67,28 +70,28 @@ func TestAddSparkline(t *testing.T) {
|
|||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B9", "Line with negative point markers."))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A9"},
|
||||
Range: []string{"Sheet3!A1:J1"},
|
||||
Negative: true,
|
||||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B10", "Line with axis."))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A10"},
|
||||
Range: []string{"Sheet3!A1:J1"},
|
||||
Axis: true,
|
||||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B12", "Column with default style (1)."))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A12"},
|
||||
Range: []string{"Sheet3!A2:J2"},
|
||||
Type: "column",
|
||||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B13", "Column with style 2."))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A13"},
|
||||
Range: []string{"Sheet3!A2:J2"},
|
||||
Type: "column",
|
||||
|
@ -96,7 +99,7 @@ func TestAddSparkline(t *testing.T) {
|
|||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B14", "Column with style 3."))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A14"},
|
||||
Range: []string{"Sheet3!A2:J2"},
|
||||
Type: "column",
|
||||
|
@ -104,7 +107,7 @@ func TestAddSparkline(t *testing.T) {
|
|||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B15", "Column with style 4."))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A15"},
|
||||
Range: []string{"Sheet3!A2:J2"},
|
||||
Type: "column",
|
||||
|
@ -112,7 +115,7 @@ func TestAddSparkline(t *testing.T) {
|
|||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B16", "Column with style 5."))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A16"},
|
||||
Range: []string{"Sheet3!A2:J2"},
|
||||
Type: "column",
|
||||
|
@ -120,7 +123,7 @@ func TestAddSparkline(t *testing.T) {
|
|||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B17", "Column with style 6."))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A17"},
|
||||
Range: []string{"Sheet3!A2:J2"},
|
||||
Type: "column",
|
||||
|
@ -128,7 +131,7 @@ func TestAddSparkline(t *testing.T) {
|
|||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B18", "Column with a user defined color."))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A18"},
|
||||
Range: []string{"Sheet3!A2:J2"},
|
||||
Type: "column",
|
||||
|
@ -136,14 +139,14 @@ func TestAddSparkline(t *testing.T) {
|
|||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B20", "A win/loss sparkline."))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A20"},
|
||||
Range: []string{"Sheet3!A3:J3"},
|
||||
Type: "win_loss",
|
||||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B21", "A win/loss sparkline with negative points highlighted."))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A21"},
|
||||
Range: []string{"Sheet3!A3:J3"},
|
||||
Type: "win_loss",
|
||||
|
@ -151,7 +154,7 @@ func TestAddSparkline(t *testing.T) {
|
|||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B23", "A left to right column (the default)."))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A23"},
|
||||
Range: []string{"Sheet3!A4:J4"},
|
||||
Type: "column",
|
||||
|
@ -159,7 +162,7 @@ func TestAddSparkline(t *testing.T) {
|
|||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B24", "A right to left column."))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A24"},
|
||||
Range: []string{"Sheet3!A4:J4"},
|
||||
Type: "column",
|
||||
|
@ -168,7 +171,7 @@ func TestAddSparkline(t *testing.T) {
|
|||
}))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B25", "Sparkline and text in one cell."))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A25"},
|
||||
Range: []string{"Sheet3!A4:J4"},
|
||||
Type: "column",
|
||||
|
@ -177,34 +180,34 @@ func TestAddSparkline(t *testing.T) {
|
|||
assert.NoError(t, f.SetCellValue("Sheet1", "A25", "Growth"))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B27", "A grouped sparkline. Changes are applied to all three."))
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A27", "A28", "A29"},
|
||||
Range: []string{"Sheet3!A5:J5", "Sheet3!A6:J6", "Sheet3!A7:J7"},
|
||||
Markers: true,
|
||||
}))
|
||||
|
||||
// Sheet2 sections
|
||||
assert.NoError(t, f.AddSparkline("Sheet2", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet2", &SparklineOptions{
|
||||
Location: []string{"F3"},
|
||||
Range: []string{"Sheet2!A3:E3"},
|
||||
Type: "win_loss",
|
||||
Negative: true,
|
||||
}))
|
||||
|
||||
assert.NoError(t, f.AddSparkline("Sheet2", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet2", &SparklineOptions{
|
||||
Location: []string{"F1"},
|
||||
Range: []string{"Sheet2!A1:E1"},
|
||||
Markers: true,
|
||||
}))
|
||||
|
||||
assert.NoError(t, f.AddSparkline("Sheet2", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet2", &SparklineOptions{
|
||||
Location: []string{"F2"},
|
||||
Range: []string{"Sheet2!A2:E2"},
|
||||
Type: "column",
|
||||
Style: 12,
|
||||
}))
|
||||
|
||||
assert.NoError(t, f.AddSparkline("Sheet2", &SparklineOption{
|
||||
assert.NoError(t, f.AddSparkline("Sheet2", &SparklineOptions{
|
||||
Location: []string{"F3"},
|
||||
Range: []string{"Sheet2!A3:E3"},
|
||||
Type: "win_loss",
|
||||
|
@ -215,39 +218,39 @@ func TestAddSparkline(t *testing.T) {
|
|||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddSparkline.xlsx")))
|
||||
|
||||
// Test error exceptions
|
||||
assert.EqualError(t, f.AddSparkline("SheetN", &SparklineOption{
|
||||
assert.EqualError(t, f.AddSparkline("SheetN", &SparklineOptions{
|
||||
Location: []string{"F3"},
|
||||
Range: []string{"Sheet2!A3:E3"},
|
||||
}), "sheet SheetN does not exist")
|
||||
|
||||
assert.EqualError(t, f.AddSparkline("Sheet1", nil), ErrParameterRequired.Error())
|
||||
|
||||
assert.EqualError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.EqualError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Range: []string{"Sheet2!A3:E3"},
|
||||
}), ErrSparklineLocation.Error())
|
||||
|
||||
assert.EqualError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.EqualError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"F3"},
|
||||
}), ErrSparklineRange.Error())
|
||||
|
||||
assert.EqualError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.EqualError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"F2", "F3"},
|
||||
Range: []string{"Sheet2!A3:E3"},
|
||||
}), ErrSparkline.Error())
|
||||
|
||||
assert.EqualError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.EqualError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"F3"},
|
||||
Range: []string{"Sheet2!A3:E3"},
|
||||
Type: "unknown_type",
|
||||
}), ErrSparklineType.Error())
|
||||
|
||||
assert.EqualError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.EqualError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"F3"},
|
||||
Range: []string{"Sheet2!A3:E3"},
|
||||
Style: -1,
|
||||
}), ErrSparklineStyle.Error())
|
||||
|
||||
assert.EqualError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.EqualError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"F3"},
|
||||
Range: []string{"Sheet2!A3:E3"},
|
||||
Style: -1,
|
||||
|
@ -265,7 +268,7 @@ func TestAddSparkline(t *testing.T) {
|
|||
</x14:sparklineGroups>
|
||||
</ext>
|
||||
</extLst>`
|
||||
assert.EqualError(t, f.AddSparkline("Sheet1", &SparklineOption{
|
||||
assert.EqualError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Location: []string{"A2"},
|
||||
Range: []string{"Sheet3!A1:J1"},
|
||||
}), "XML syntax error on line 6: element <sparklineGroup> closed by </sparklines>")
|
||||
|
|
16
stream.go
16
stream.go
|
@ -139,8 +139,8 @@ func (f *File) NewStreamWriter(sheet string) (*StreamWriter, error) {
|
|||
// called after the rows are written but before Flush.
|
||||
//
|
||||
// See File.AddTable for details on the table format.
|
||||
func (sw *StreamWriter) AddTable(hCell, vCell, format string) error {
|
||||
formatSet, err := parseFormatTableSet(format)
|
||||
func (sw *StreamWriter) AddTable(hCell, vCell, opts string) error {
|
||||
options, err := parseTableOptions(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ func (sw *StreamWriter) AddTable(hCell, vCell, format string) error {
|
|||
|
||||
tableID := sw.File.countTables() + 1
|
||||
|
||||
name := formatSet.TableName
|
||||
name := options.TableName
|
||||
if name == "" {
|
||||
name = "Table" + strconv.Itoa(tableID)
|
||||
}
|
||||
|
@ -196,11 +196,11 @@ func (sw *StreamWriter) AddTable(hCell, vCell, format string) error {
|
|||
TableColumn: tableColumn,
|
||||
},
|
||||
TableStyleInfo: &xlsxTableStyleInfo{
|
||||
Name: formatSet.TableStyle,
|
||||
ShowFirstColumn: formatSet.ShowFirstColumn,
|
||||
ShowLastColumn: formatSet.ShowLastColumn,
|
||||
ShowRowStripes: formatSet.ShowRowStripes,
|
||||
ShowColumnStripes: formatSet.ShowColumnStripes,
|
||||
Name: options.TableStyle,
|
||||
ShowFirstColumn: options.ShowFirstColumn,
|
||||
ShowLastColumn: options.ShowLastColumn,
|
||||
ShowRowStripes: options.ShowRowStripes,
|
||||
ShowColumnStripes: options.ShowColumnStripes,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ func TestStreamTable(t *testing.T) {
|
|||
|
||||
assert.NoError(t, streamWriter.AddTable("A1", "C1", ``))
|
||||
|
||||
// Test add table with illegal formatset.
|
||||
// Test add table with illegal options.
|
||||
assert.EqualError(t, streamWriter.AddTable("B26", "A21", `{x}`), "invalid character 'x' looking for beginning of object key string")
|
||||
// Test add table with illegal cell reference.
|
||||
assert.EqualError(t, streamWriter.AddTable("A", "B1", `{}`), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
|
|
60
styles.go
60
styles.go
|
@ -2859,13 +2859,13 @@ func (f *File) SetCellStyle(sheet, hCell, vCell string, styleID int) error {
|
|||
// max_color - Same as min_color, see above.
|
||||
//
|
||||
// bar_color - Used for data_bar. Same as min_color, see above.
|
||||
func (f *File) SetConditionalFormat(sheet, reference, formatSet string) error {
|
||||
var format []*formatConditional
|
||||
err := json.Unmarshal([]byte(formatSet), &format)
|
||||
func (f *File) SetConditionalFormat(sheet, reference, opts string) error {
|
||||
var format []*conditionalOptions
|
||||
err := json.Unmarshal([]byte(opts), &format)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
drawContFmtFunc := map[string]func(p int, ct string, fmtCond *formatConditional) *xlsxCfRule{
|
||||
drawContFmtFunc := map[string]func(p int, ct string, fmtCond *conditionalOptions) *xlsxCfRule{
|
||||
"cellIs": drawCondFmtCellIs,
|
||||
"top10": drawCondFmtTop10,
|
||||
"aboveAverage": drawCondFmtAboveAverage,
|
||||
|
@ -2909,8 +2909,8 @@ func (f *File) SetConditionalFormat(sheet, reference, formatSet string) error {
|
|||
// extractCondFmtCellIs provides a function to extract conditional format
|
||||
// settings for cell value (include between, not between, equal, not equal,
|
||||
// greater than and less than) by given conditional formatting rule.
|
||||
func extractCondFmtCellIs(c *xlsxCfRule) *formatConditional {
|
||||
format := formatConditional{Type: "cell", Criteria: operatorType[c.Operator], Format: *c.DxfID}
|
||||
func extractCondFmtCellIs(c *xlsxCfRule) *conditionalOptions {
|
||||
format := conditionalOptions{Type: "cell", Criteria: operatorType[c.Operator], Format: *c.DxfID}
|
||||
if len(c.Formula) == 2 {
|
||||
format.Minimum, format.Maximum = c.Formula[0], c.Formula[1]
|
||||
return &format
|
||||
|
@ -2922,8 +2922,8 @@ func extractCondFmtCellIs(c *xlsxCfRule) *formatConditional {
|
|||
// extractCondFmtTop10 provides a function to extract conditional format
|
||||
// settings for top N (default is top 10) by given conditional formatting
|
||||
// rule.
|
||||
func extractCondFmtTop10(c *xlsxCfRule) *formatConditional {
|
||||
format := formatConditional{
|
||||
func extractCondFmtTop10(c *xlsxCfRule) *conditionalOptions {
|
||||
format := conditionalOptions{
|
||||
Type: "top",
|
||||
Criteria: "=",
|
||||
Format: *c.DxfID,
|
||||
|
@ -2939,8 +2939,8 @@ func extractCondFmtTop10(c *xlsxCfRule) *formatConditional {
|
|||
// extractCondFmtAboveAverage provides a function to extract conditional format
|
||||
// settings for above average and below average by given conditional formatting
|
||||
// rule.
|
||||
func extractCondFmtAboveAverage(c *xlsxCfRule) *formatConditional {
|
||||
return &formatConditional{
|
||||
func extractCondFmtAboveAverage(c *xlsxCfRule) *conditionalOptions {
|
||||
return &conditionalOptions{
|
||||
Type: "average",
|
||||
Criteria: "=",
|
||||
Format: *c.DxfID,
|
||||
|
@ -2951,8 +2951,8 @@ func extractCondFmtAboveAverage(c *xlsxCfRule) *formatConditional {
|
|||
// extractCondFmtDuplicateUniqueValues provides a function to extract
|
||||
// conditional format settings for duplicate and unique values by given
|
||||
// conditional formatting rule.
|
||||
func extractCondFmtDuplicateUniqueValues(c *xlsxCfRule) *formatConditional {
|
||||
return &formatConditional{
|
||||
func extractCondFmtDuplicateUniqueValues(c *xlsxCfRule) *conditionalOptions {
|
||||
return &conditionalOptions{
|
||||
Type: map[string]string{
|
||||
"duplicateValues": "duplicate",
|
||||
"uniqueValues": "unique",
|
||||
|
@ -2965,8 +2965,8 @@ func extractCondFmtDuplicateUniqueValues(c *xlsxCfRule) *formatConditional {
|
|||
// extractCondFmtColorScale provides a function to extract conditional format
|
||||
// settings for color scale (include 2 color scale and 3 color scale) by given
|
||||
// conditional formatting rule.
|
||||
func extractCondFmtColorScale(c *xlsxCfRule) *formatConditional {
|
||||
var format formatConditional
|
||||
func extractCondFmtColorScale(c *xlsxCfRule) *conditionalOptions {
|
||||
var format conditionalOptions
|
||||
format.Type, format.Criteria = "2_color_scale", "="
|
||||
values := len(c.ColorScale.Cfvo)
|
||||
colors := len(c.ColorScale.Color)
|
||||
|
@ -3000,8 +3000,8 @@ func extractCondFmtColorScale(c *xlsxCfRule) *formatConditional {
|
|||
|
||||
// extractCondFmtDataBar provides a function to extract conditional format
|
||||
// settings for data bar by given conditional formatting rule.
|
||||
func extractCondFmtDataBar(c *xlsxCfRule) *formatConditional {
|
||||
format := formatConditional{Type: "data_bar", Criteria: "="}
|
||||
func extractCondFmtDataBar(c *xlsxCfRule) *conditionalOptions {
|
||||
format := conditionalOptions{Type: "data_bar", Criteria: "="}
|
||||
if c.DataBar != nil {
|
||||
format.MinType = c.DataBar.Cfvo[0].Type
|
||||
format.MaxType = c.DataBar.Cfvo[1].Type
|
||||
|
@ -3012,8 +3012,8 @@ func extractCondFmtDataBar(c *xlsxCfRule) *formatConditional {
|
|||
|
||||
// extractCondFmtExp provides a function to extract conditional format settings
|
||||
// for expression by given conditional formatting rule.
|
||||
func extractCondFmtExp(c *xlsxCfRule) *formatConditional {
|
||||
format := formatConditional{Type: "formula", Format: *c.DxfID}
|
||||
func extractCondFmtExp(c *xlsxCfRule) *conditionalOptions {
|
||||
format := conditionalOptions{Type: "formula", Format: *c.DxfID}
|
||||
if len(c.Formula) > 0 {
|
||||
format.Criteria = c.Formula[0]
|
||||
}
|
||||
|
@ -3023,7 +3023,7 @@ func extractCondFmtExp(c *xlsxCfRule) *formatConditional {
|
|||
// GetConditionalFormats returns conditional format settings by given worksheet
|
||||
// name.
|
||||
func (f *File) GetConditionalFormats(sheet string) (map[string]string, error) {
|
||||
extractContFmtFunc := map[string]func(c *xlsxCfRule) *formatConditional{
|
||||
extractContFmtFunc := map[string]func(c *xlsxCfRule) *conditionalOptions{
|
||||
"cellIs": extractCondFmtCellIs,
|
||||
"top10": extractCondFmtTop10,
|
||||
"aboveAverage": extractCondFmtAboveAverage,
|
||||
|
@ -3040,14 +3040,14 @@ func (f *File) GetConditionalFormats(sheet string) (map[string]string, error) {
|
|||
return conditionalFormats, err
|
||||
}
|
||||
for _, cf := range ws.ConditionalFormatting {
|
||||
var format []*formatConditional
|
||||
var opts []*conditionalOptions
|
||||
for _, cr := range cf.CfRule {
|
||||
if extractFunc, ok := extractContFmtFunc[cr.Type]; ok {
|
||||
format = append(format, extractFunc(cr))
|
||||
opts = append(opts, extractFunc(cr))
|
||||
}
|
||||
}
|
||||
formatSet, _ := json.Marshal(format)
|
||||
conditionalFormats[cf.SQRef] = string(formatSet)
|
||||
options, _ := json.Marshal(opts)
|
||||
conditionalFormats[cf.SQRef] = string(options)
|
||||
}
|
||||
return conditionalFormats, err
|
||||
}
|
||||
|
@ -3071,7 +3071,7 @@ func (f *File) UnsetConditionalFormat(sheet, reference string) error {
|
|||
// drawCondFmtCellIs provides a function to create conditional formatting rule
|
||||
// for cell value (include between, not between, equal, not equal, greater
|
||||
// than and less than) by given priority, criteria type and format settings.
|
||||
func drawCondFmtCellIs(p int, ct string, format *formatConditional) *xlsxCfRule {
|
||||
func drawCondFmtCellIs(p int, ct string, format *conditionalOptions) *xlsxCfRule {
|
||||
c := &xlsxCfRule{
|
||||
Priority: p + 1,
|
||||
Type: validType[format.Type],
|
||||
|
@ -3094,7 +3094,7 @@ func drawCondFmtCellIs(p int, ct string, format *formatConditional) *xlsxCfRule
|
|||
// drawCondFmtTop10 provides a function to create conditional formatting rule
|
||||
// for top N (default is top 10) by given priority, criteria type and format
|
||||
// settings.
|
||||
func drawCondFmtTop10(p int, ct string, format *formatConditional) *xlsxCfRule {
|
||||
func drawCondFmtTop10(p int, ct string, format *conditionalOptions) *xlsxCfRule {
|
||||
c := &xlsxCfRule{
|
||||
Priority: p + 1,
|
||||
Bottom: format.Type == "bottom",
|
||||
|
@ -3113,7 +3113,7 @@ func drawCondFmtTop10(p int, ct string, format *formatConditional) *xlsxCfRule {
|
|||
// drawCondFmtAboveAverage provides a function to create conditional
|
||||
// formatting rule for above average and below average by given priority,
|
||||
// criteria type and format settings.
|
||||
func drawCondFmtAboveAverage(p int, ct string, format *formatConditional) *xlsxCfRule {
|
||||
func drawCondFmtAboveAverage(p int, ct string, format *conditionalOptions) *xlsxCfRule {
|
||||
return &xlsxCfRule{
|
||||
Priority: p + 1,
|
||||
Type: validType[format.Type],
|
||||
|
@ -3125,7 +3125,7 @@ func drawCondFmtAboveAverage(p int, ct string, format *formatConditional) *xlsxC
|
|||
// drawCondFmtDuplicateUniqueValues provides a function to create conditional
|
||||
// formatting rule for duplicate and unique values by given priority, criteria
|
||||
// type and format settings.
|
||||
func drawCondFmtDuplicateUniqueValues(p int, ct string, format *formatConditional) *xlsxCfRule {
|
||||
func drawCondFmtDuplicateUniqueValues(p int, ct string, format *conditionalOptions) *xlsxCfRule {
|
||||
return &xlsxCfRule{
|
||||
Priority: p + 1,
|
||||
Type: validType[format.Type],
|
||||
|
@ -3136,7 +3136,7 @@ func drawCondFmtDuplicateUniqueValues(p int, ct string, format *formatConditiona
|
|||
// drawCondFmtColorScale provides a function to create conditional formatting
|
||||
// rule for color scale (include 2 color scale and 3 color scale) by given
|
||||
// priority, criteria type and format settings.
|
||||
func drawCondFmtColorScale(p int, ct string, format *formatConditional) *xlsxCfRule {
|
||||
func drawCondFmtColorScale(p int, ct string, format *conditionalOptions) *xlsxCfRule {
|
||||
minValue := format.MinValue
|
||||
if minValue == "" {
|
||||
minValue = "0"
|
||||
|
@ -3173,7 +3173,7 @@ func drawCondFmtColorScale(p int, ct string, format *formatConditional) *xlsxCfR
|
|||
|
||||
// drawCondFmtDataBar provides a function to create conditional formatting
|
||||
// rule for data bar by given priority, criteria type and format settings.
|
||||
func drawCondFmtDataBar(p int, ct string, format *formatConditional) *xlsxCfRule {
|
||||
func drawCondFmtDataBar(p int, ct string, format *conditionalOptions) *xlsxCfRule {
|
||||
return &xlsxCfRule{
|
||||
Priority: p + 1,
|
||||
Type: validType[format.Type],
|
||||
|
@ -3186,7 +3186,7 @@ func drawCondFmtDataBar(p int, ct string, format *formatConditional) *xlsxCfRule
|
|||
|
||||
// drawCondFmtExp provides a function to create conditional formatting rule
|
||||
// for expression by given priority, criteria type and format settings.
|
||||
func drawCondFmtExp(p int, ct string, format *formatConditional) *xlsxCfRule {
|
||||
func drawCondFmtExp(p int, ct string, format *conditionalOptions) *xlsxCfRule {
|
||||
return &xlsxCfRule{
|
||||
Priority: p + 1,
|
||||
Type: validType[format.Type],
|
||||
|
|
|
@ -192,9 +192,9 @@ func TestGetConditionalFormats(t *testing.T) {
|
|||
f := NewFile()
|
||||
err := f.SetConditionalFormat("Sheet1", "A1:A2", format)
|
||||
assert.NoError(t, err)
|
||||
formatSet, err := f.GetConditionalFormats("Sheet1")
|
||||
opts, err := f.GetConditionalFormats("Sheet1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, format, formatSet["A1:A2"])
|
||||
assert.Equal(t, format, opts["A1:A2"])
|
||||
}
|
||||
// Test get conditional formats on no exists worksheet
|
||||
f := NewFile()
|
||||
|
|
60
table.go
60
table.go
|
@ -20,12 +20,12 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// parseFormatTableSet provides a function to parse the format settings of the
|
||||
// parseTableOptions provides a function to parse the format settings of the
|
||||
// table with default value.
|
||||
func parseFormatTableSet(formatSet string) (*formatTable, error) {
|
||||
format := formatTable{ShowRowStripes: true}
|
||||
err := json.Unmarshal(parseFormatSet(formatSet), &format)
|
||||
return &format, err
|
||||
func parseTableOptions(opts string) (*tableOptions, error) {
|
||||
options := tableOptions{ShowRowStripes: true}
|
||||
err := json.Unmarshal(fallbackOptions(opts), &options)
|
||||
return &options, err
|
||||
}
|
||||
|
||||
// AddTable provides the method to add table in a worksheet by given worksheet
|
||||
|
@ -57,8 +57,8 @@ func parseFormatTableSet(formatSet string) (*formatTable, error) {
|
|||
// TableStyleLight1 - TableStyleLight21
|
||||
// TableStyleMedium1 - TableStyleMedium28
|
||||
// TableStyleDark1 - TableStyleDark11
|
||||
func (f *File) AddTable(sheet, hCell, vCell, format string) error {
|
||||
formatSet, err := parseFormatTableSet(format)
|
||||
func (f *File) AddTable(sheet, hCell, vCell, opts string) error {
|
||||
options, err := parseTableOptions(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ func (f *File) AddTable(sheet, hCell, vCell, format string) error {
|
|||
return err
|
||||
}
|
||||
f.addSheetNameSpace(sheet, SourceRelationship)
|
||||
if err = f.addTable(sheet, tableXML, hCol, hRow, vCol, vRow, tableID, formatSet); err != nil {
|
||||
if err = f.addTable(sheet, tableXML, hCol, hRow, vCol, vRow, tableID, options); err != nil {
|
||||
return err
|
||||
}
|
||||
f.addContentTypePart(tableID, "table")
|
||||
|
@ -160,7 +160,7 @@ func (f *File) setTableHeader(sheet string, x1, y1, x2 int) ([]*xlsxTableColumn,
|
|||
|
||||
// addTable provides a function to add table by given worksheet name,
|
||||
// range reference and format set.
|
||||
func (f *File) addTable(sheet, tableXML string, x1, y1, x2, y2, i int, formatSet *formatTable) error {
|
||||
func (f *File) addTable(sheet, tableXML string, x1, y1, x2, y2, i int, opts *tableOptions) error {
|
||||
// Correct the minimum number of rows, the table at least two lines.
|
||||
if y1 == y2 {
|
||||
y2++
|
||||
|
@ -172,7 +172,7 @@ func (f *File) addTable(sheet, tableXML string, x1, y1, x2, y2, i int, formatSet
|
|||
return err
|
||||
}
|
||||
tableColumns, _ := f.setTableHeader(sheet, x1, y1, x2)
|
||||
name := formatSet.TableName
|
||||
name := opts.TableName
|
||||
if name == "" {
|
||||
name = "Table" + strconv.Itoa(i)
|
||||
}
|
||||
|
@ -190,11 +190,11 @@ func (f *File) addTable(sheet, tableXML string, x1, y1, x2, y2, i int, formatSet
|
|||
TableColumn: tableColumns,
|
||||
},
|
||||
TableStyleInfo: &xlsxTableStyleInfo{
|
||||
Name: formatSet.TableStyle,
|
||||
ShowFirstColumn: formatSet.ShowFirstColumn,
|
||||
ShowLastColumn: formatSet.ShowLastColumn,
|
||||
ShowRowStripes: formatSet.ShowRowStripes,
|
||||
ShowColumnStripes: formatSet.ShowColumnStripes,
|
||||
Name: opts.TableStyle,
|
||||
ShowFirstColumn: opts.ShowFirstColumn,
|
||||
ShowLastColumn: opts.ShowLastColumn,
|
||||
ShowRowStripes: opts.ShowRowStripes,
|
||||
ShowColumnStripes: opts.ShowColumnStripes,
|
||||
},
|
||||
}
|
||||
table, _ := xml.Marshal(t)
|
||||
|
@ -202,12 +202,12 @@ func (f *File) addTable(sheet, tableXML string, x1, y1, x2, y2, i int, formatSet
|
|||
return nil
|
||||
}
|
||||
|
||||
// parseAutoFilterSet provides a function to parse the settings of the auto
|
||||
// parseAutoFilterOptions provides a function to parse the settings of the auto
|
||||
// filter.
|
||||
func parseAutoFilterSet(formatSet string) (*formatAutoFilter, error) {
|
||||
format := formatAutoFilter{}
|
||||
err := json.Unmarshal([]byte(formatSet), &format)
|
||||
return &format, err
|
||||
func parseAutoFilterOptions(opts string) (*autoFilterOptions, error) {
|
||||
options := autoFilterOptions{}
|
||||
err := json.Unmarshal([]byte(opts), &options)
|
||||
return &options, err
|
||||
}
|
||||
|
||||
// AutoFilter provides the method to add auto filter in a worksheet by given
|
||||
|
@ -279,7 +279,7 @@ func parseAutoFilterSet(formatSet string) (*formatAutoFilter, error) {
|
|||
// x < 2000
|
||||
// col < 2000
|
||||
// Price < 2000
|
||||
func (f *File) AutoFilter(sheet, hCell, vCell, format string) error {
|
||||
func (f *File) AutoFilter(sheet, hCell, vCell, opts string) error {
|
||||
hCol, hRow, err := CellNameToCoordinates(hCell)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -297,7 +297,7 @@ func (f *File) AutoFilter(sheet, hCell, vCell, format string) error {
|
|||
vRow, hRow = hRow, vRow
|
||||
}
|
||||
|
||||
formatSet, _ := parseAutoFilterSet(format)
|
||||
options, _ := parseAutoFilterOptions(opts)
|
||||
cellStart, _ := CoordinatesToCellName(hCol, hRow, true)
|
||||
cellEnd, _ := CoordinatesToCellName(vCol, vRow, true)
|
||||
ref, filterDB := cellStart+":"+cellEnd, "_xlnm._FilterDatabase"
|
||||
|
@ -328,12 +328,12 @@ func (f *File) AutoFilter(sheet, hCell, vCell, format string) error {
|
|||
}
|
||||
}
|
||||
refRange := vCol - hCol
|
||||
return f.autoFilter(sheet, ref, refRange, hCol, formatSet)
|
||||
return f.autoFilter(sheet, ref, refRange, hCol, options)
|
||||
}
|
||||
|
||||
// autoFilter provides a function to extract the tokens from the filter
|
||||
// expression. The tokens are mainly non-whitespace groups.
|
||||
func (f *File) autoFilter(sheet, ref string, refRange, col int, formatSet *formatAutoFilter) error {
|
||||
func (f *File) autoFilter(sheet, ref string, refRange, col int, opts *autoFilterOptions) error {
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -346,28 +346,28 @@ func (f *File) autoFilter(sheet, ref string, refRange, col int, formatSet *forma
|
|||
Ref: ref,
|
||||
}
|
||||
ws.AutoFilter = filter
|
||||
if formatSet.Column == "" || formatSet.Expression == "" {
|
||||
if opts.Column == "" || opts.Expression == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
fsCol, err := ColumnNameToNumber(formatSet.Column)
|
||||
fsCol, err := ColumnNameToNumber(opts.Column)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
offset := fsCol - col
|
||||
if offset < 0 || offset > refRange {
|
||||
return fmt.Errorf("incorrect index of column '%s'", formatSet.Column)
|
||||
return fmt.Errorf("incorrect index of column '%s'", opts.Column)
|
||||
}
|
||||
|
||||
filter.FilterColumn = append(filter.FilterColumn, &xlsxFilterColumn{
|
||||
ColID: offset,
|
||||
})
|
||||
re := regexp.MustCompile(`"(?:[^"]|"")*"|\S+`)
|
||||
token := re.FindAllString(formatSet.Expression, -1)
|
||||
token := re.FindAllString(opts.Expression, -1)
|
||||
if len(token) != 3 && len(token) != 7 {
|
||||
return fmt.Errorf("incorrect number of tokens in criteria '%s'", formatSet.Expression)
|
||||
return fmt.Errorf("incorrect number of tokens in criteria '%s'", opts.Expression)
|
||||
}
|
||||
expressions, tokens, err := f.parseFilterExpression(formatSet.Expression, token)
|
||||
expressions, tokens, err := f.parseFilterExpression(opts.Expression, token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ func TestAddTable(t *testing.T) {
|
|||
|
||||
// Test add table in not exist worksheet.
|
||||
assert.EqualError(t, f.AddTable("SheetN", "B26", "A21", `{}`), "sheet SheetN does not exist")
|
||||
// Test add table with illegal formatset.
|
||||
// Test add table with illegal options.
|
||||
assert.EqualError(t, f.AddTable("Sheet1", "B26", "A21", `{x}`), "invalid character 'x' looking for beginning of object key string")
|
||||
// Test add table with illegal cell reference.
|
||||
assert.EqualError(t, f.AddTable("Sheet1", "A", "B1", `{}`), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
|
@ -108,19 +108,19 @@ func TestAutoFilterError(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
assert.EqualError(t, f.autoFilter("SheetN", "A1", 1, 1, &formatAutoFilter{
|
||||
assert.EqualError(t, f.autoFilter("SheetN", "A1", 1, 1, &autoFilterOptions{
|
||||
Column: "A",
|
||||
Expression: "",
|
||||
}), "sheet SheetN does not exist")
|
||||
assert.EqualError(t, f.autoFilter("Sheet1", "A1", 1, 1, &formatAutoFilter{
|
||||
assert.EqualError(t, f.autoFilter("Sheet1", "A1", 1, 1, &autoFilterOptions{
|
||||
Column: "-",
|
||||
Expression: "-",
|
||||
}), newInvalidColumnNameError("-").Error())
|
||||
assert.EqualError(t, f.autoFilter("Sheet1", "A1", 1, 100, &formatAutoFilter{
|
||||
assert.EqualError(t, f.autoFilter("Sheet1", "A1", 1, 100, &autoFilterOptions{
|
||||
Column: "A",
|
||||
Expression: "-",
|
||||
}), `incorrect index of column 'A'`)
|
||||
assert.EqualError(t, f.autoFilter("Sheet1", "A1", 1, 1, &formatAutoFilter{
|
||||
assert.EqualError(t, f.autoFilter("Sheet1", "A1", 1, 1, &autoFilterOptions{
|
||||
Column: "A",
|
||||
Expression: "-",
|
||||
}), `incorrect number of tokens in criteria '-'`)
|
||||
|
|
125
workbook.go
125
workbook.go
|
@ -21,26 +21,38 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// WorkbookPrOption is an option of a view of a workbook. See SetWorkbookPrOptions().
|
||||
type WorkbookPrOption interface {
|
||||
setWorkbookPrOption(pr *xlsxWorkbookPr)
|
||||
// SetWorkbookProps provides a function to sets workbook properties.
|
||||
func (f *File) SetWorkbookProps(opts *WorkbookPropsOptions) error {
|
||||
wb := f.workbookReader()
|
||||
if wb.WorkbookPr == nil {
|
||||
wb.WorkbookPr = new(xlsxWorkbookPr)
|
||||
}
|
||||
if opts == nil {
|
||||
return nil
|
||||
}
|
||||
if opts.Date1904 != nil {
|
||||
wb.WorkbookPr.Date1904 = *opts.Date1904
|
||||
}
|
||||
if opts.FilterPrivacy != nil {
|
||||
wb.WorkbookPr.FilterPrivacy = *opts.FilterPrivacy
|
||||
}
|
||||
if opts.CodeName != nil {
|
||||
wb.WorkbookPr.CodeName = *opts.CodeName
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WorkbookPrOptionPtr is a writable WorkbookPrOption. See GetWorkbookPrOptions().
|
||||
type WorkbookPrOptionPtr interface {
|
||||
WorkbookPrOption
|
||||
getWorkbookPrOption(pr *xlsxWorkbookPr)
|
||||
// GetWorkbookProps provides a function to gets workbook properties.
|
||||
func (f *File) GetWorkbookProps() (WorkbookPropsOptions, error) {
|
||||
wb, opts := f.workbookReader(), WorkbookPropsOptions{}
|
||||
if wb.WorkbookPr != nil {
|
||||
opts.Date1904 = boolPtr(wb.WorkbookPr.Date1904)
|
||||
opts.FilterPrivacy = boolPtr(wb.WorkbookPr.FilterPrivacy)
|
||||
opts.CodeName = stringPtr(wb.WorkbookPr.CodeName)
|
||||
}
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
type (
|
||||
// Date1904 is an option used for WorkbookPrOption, that indicates whether
|
||||
// to use a 1900 or 1904 date system when converting serial date-times in
|
||||
// the workbook to dates
|
||||
Date1904 bool
|
||||
// FilterPrivacy is an option used for WorkbookPrOption
|
||||
FilterPrivacy bool
|
||||
)
|
||||
|
||||
// setWorkbook update workbook property of the spreadsheet. Maximum 31
|
||||
// characters are allowed in sheet title.
|
||||
func (f *File) setWorkbook(name string, sheetID, rid int) {
|
||||
|
@ -116,84 +128,3 @@ func (f *File) workBookWriter() {
|
|||
f.saveFileList(f.getWorkbookPath(), replaceRelationshipsBytes(f.replaceNameSpaceBytes(f.getWorkbookPath(), output)))
|
||||
}
|
||||
}
|
||||
|
||||
// SetWorkbookPrOptions provides a function to sets workbook properties.
|
||||
//
|
||||
// Available options:
|
||||
//
|
||||
// Date1904(bool)
|
||||
// FilterPrivacy(bool)
|
||||
// CodeName(string)
|
||||
func (f *File) SetWorkbookPrOptions(opts ...WorkbookPrOption) error {
|
||||
wb := f.workbookReader()
|
||||
pr := wb.WorkbookPr
|
||||
if pr == nil {
|
||||
pr = new(xlsxWorkbookPr)
|
||||
wb.WorkbookPr = pr
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt.setWorkbookPrOption(pr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// setWorkbookPrOption implements the WorkbookPrOption interface.
|
||||
func (o Date1904) setWorkbookPrOption(pr *xlsxWorkbookPr) {
|
||||
pr.Date1904 = bool(o)
|
||||
}
|
||||
|
||||
// setWorkbookPrOption implements the WorkbookPrOption interface.
|
||||
func (o FilterPrivacy) setWorkbookPrOption(pr *xlsxWorkbookPr) {
|
||||
pr.FilterPrivacy = bool(o)
|
||||
}
|
||||
|
||||
// setWorkbookPrOption implements the WorkbookPrOption interface.
|
||||
func (o CodeName) setWorkbookPrOption(pr *xlsxWorkbookPr) {
|
||||
pr.CodeName = string(o)
|
||||
}
|
||||
|
||||
// GetWorkbookPrOptions provides a function to gets workbook properties.
|
||||
//
|
||||
// Available options:
|
||||
//
|
||||
// Date1904(bool)
|
||||
// FilterPrivacy(bool)
|
||||
// CodeName(string)
|
||||
func (f *File) GetWorkbookPrOptions(opts ...WorkbookPrOptionPtr) error {
|
||||
wb := f.workbookReader()
|
||||
pr := wb.WorkbookPr
|
||||
for _, opt := range opts {
|
||||
opt.getWorkbookPrOption(pr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getWorkbookPrOption implements the WorkbookPrOption interface and get the
|
||||
// date1904 of the workbook.
|
||||
func (o *Date1904) getWorkbookPrOption(pr *xlsxWorkbookPr) {
|
||||
if pr == nil {
|
||||
*o = false
|
||||
return
|
||||
}
|
||||
*o = Date1904(pr.Date1904)
|
||||
}
|
||||
|
||||
// getWorkbookPrOption implements the WorkbookPrOption interface and get the
|
||||
// filter privacy of the workbook.
|
||||
func (o *FilterPrivacy) getWorkbookPrOption(pr *xlsxWorkbookPr) {
|
||||
if pr == nil {
|
||||
*o = false
|
||||
return
|
||||
}
|
||||
*o = FilterPrivacy(pr.FilterPrivacy)
|
||||
}
|
||||
|
||||
// getWorkbookPrOption implements the WorkbookPrOption interface and get the
|
||||
// code name of the workbook.
|
||||
func (o *CodeName) getWorkbookPrOption(pr *xlsxWorkbookPr) {
|
||||
if pr == nil {
|
||||
*o = ""
|
||||
return
|
||||
}
|
||||
*o = CodeName(pr.CodeName)
|
||||
}
|
||||
|
|
|
@ -1,69 +1,23 @@
|
|||
package excelize
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func ExampleFile_SetWorkbookPrOptions() {
|
||||
f := NewFile()
|
||||
if err := f.SetWorkbookPrOptions(
|
||||
Date1904(false),
|
||||
FilterPrivacy(false),
|
||||
CodeName("code"),
|
||||
); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
// Output:
|
||||
}
|
||||
|
||||
func ExampleFile_GetWorkbookPrOptions() {
|
||||
f := NewFile()
|
||||
var (
|
||||
date1904 Date1904
|
||||
filterPrivacy FilterPrivacy
|
||||
codeName CodeName
|
||||
)
|
||||
if err := f.GetWorkbookPrOptions(&date1904); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err := f.GetWorkbookPrOptions(&filterPrivacy); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err := f.GetWorkbookPrOptions(&codeName); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println("Defaults:")
|
||||
fmt.Printf("- date1904: %t\n", date1904)
|
||||
fmt.Printf("- filterPrivacy: %t\n", filterPrivacy)
|
||||
fmt.Printf("- codeName: %q\n", codeName)
|
||||
// Output:
|
||||
// Defaults:
|
||||
// - date1904: false
|
||||
// - filterPrivacy: true
|
||||
// - codeName: ""
|
||||
}
|
||||
|
||||
func TestWorkbookPr(t *testing.T) {
|
||||
func TestWorkbookProps(t *testing.T) {
|
||||
f := NewFile()
|
||||
assert.NoError(t, f.SetWorkbookProps(nil))
|
||||
wb := f.workbookReader()
|
||||
wb.WorkbookPr = nil
|
||||
var date1904 Date1904
|
||||
assert.NoError(t, f.GetWorkbookPrOptions(&date1904))
|
||||
assert.Equal(t, false, bool(date1904))
|
||||
|
||||
wb.WorkbookPr = nil
|
||||
var codeName CodeName
|
||||
assert.NoError(t, f.GetWorkbookPrOptions(&codeName))
|
||||
assert.Equal(t, "", string(codeName))
|
||||
assert.NoError(t, f.SetWorkbookPrOptions(CodeName("code")))
|
||||
assert.NoError(t, f.GetWorkbookPrOptions(&codeName))
|
||||
assert.Equal(t, "code", string(codeName))
|
||||
|
||||
wb.WorkbookPr = nil
|
||||
var filterPrivacy FilterPrivacy
|
||||
assert.NoError(t, f.GetWorkbookPrOptions(&filterPrivacy))
|
||||
assert.Equal(t, false, bool(filterPrivacy))
|
||||
expected := WorkbookPropsOptions{
|
||||
Date1904: boolPtr(true),
|
||||
FilterPrivacy: boolPtr(true),
|
||||
CodeName: stringPtr("code"),
|
||||
}
|
||||
assert.NoError(t, f.SetWorkbookProps(&expected))
|
||||
opts, err := f.GetWorkbookProps()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, opts)
|
||||
}
|
||||
|
|
73
xmlChart.go
73
xmlChart.go
|
@ -518,8 +518,8 @@ type cPageMargins struct {
|
|||
T float64 `xml:"t,attr"`
|
||||
}
|
||||
|
||||
// formatChartAxis directly maps the format settings of the chart axis.
|
||||
type formatChartAxis struct {
|
||||
// chartAxisOptions directly maps the format settings of the chart axis.
|
||||
type chartAxisOptions struct {
|
||||
None bool `json:"none"`
|
||||
Crossing string `json:"crossing"`
|
||||
MajorGridlines bool `json:"major_grid_lines"`
|
||||
|
@ -543,26 +543,27 @@ type formatChartAxis struct {
|
|||
Italic bool `json:"italic"`
|
||||
Underline bool `json:"underline"`
|
||||
} `json:"num_font"`
|
||||
LogBase float64 `json:"logbase"`
|
||||
NameLayout formatLayout `json:"name_layout"`
|
||||
LogBase float64 `json:"logbase"`
|
||||
NameLayout layoutOptions `json:"name_layout"`
|
||||
}
|
||||
|
||||
type formatChartDimension struct {
|
||||
// chartDimensionOptions directly maps the dimension of the chart.
|
||||
type chartDimensionOptions struct {
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
}
|
||||
|
||||
// formatChart directly maps the format settings of the chart.
|
||||
type formatChart struct {
|
||||
Type string `json:"type"`
|
||||
Series []formatChartSeries `json:"series"`
|
||||
Format formatPicture `json:"format"`
|
||||
Dimension formatChartDimension `json:"dimension"`
|
||||
Legend formatChartLegend `json:"legend"`
|
||||
Title formatChartTitle `json:"title"`
|
||||
VaryColors bool `json:"vary_colors"`
|
||||
XAxis formatChartAxis `json:"x_axis"`
|
||||
YAxis formatChartAxis `json:"y_axis"`
|
||||
// chartOptions directly maps the format settings of the chart.
|
||||
type chartOptions struct {
|
||||
Type string `json:"type"`
|
||||
Series []chartSeriesOptions `json:"series"`
|
||||
Format pictureOptions `json:"format"`
|
||||
Dimension chartDimensionOptions `json:"dimension"`
|
||||
Legend chartLegendOptions `json:"legend"`
|
||||
Title chartTitleOptions `json:"title"`
|
||||
VaryColors bool `json:"vary_colors"`
|
||||
XAxis chartAxisOptions `json:"x_axis"`
|
||||
YAxis chartAxisOptions `json:"y_axis"`
|
||||
Chartarea struct {
|
||||
Border struct {
|
||||
None bool `json:"none"`
|
||||
|
@ -594,7 +595,7 @@ type formatChart struct {
|
|||
Fill struct {
|
||||
Color string `json:"color"`
|
||||
} `json:"fill"`
|
||||
Layout formatLayout `json:"layout"`
|
||||
Layout layoutOptions `json:"layout"`
|
||||
} `json:"plotarea"`
|
||||
ShowBlanksAs string `json:"show_blanks_as"`
|
||||
ShowHiddenData bool `json:"show_hidden_data"`
|
||||
|
@ -603,19 +604,19 @@ type formatChart struct {
|
|||
order int
|
||||
}
|
||||
|
||||
// formatChartLegend directly maps the format settings of the chart legend.
|
||||
type formatChartLegend struct {
|
||||
None bool `json:"none"`
|
||||
DeleteSeries []int `json:"delete_series"`
|
||||
Font Font `json:"font"`
|
||||
Layout formatLayout `json:"layout"`
|
||||
Position string `json:"position"`
|
||||
ShowLegendEntry bool `json:"show_legend_entry"`
|
||||
ShowLegendKey bool `json:"show_legend_key"`
|
||||
// chartLegendOptions directly maps the format settings of the chart legend.
|
||||
type chartLegendOptions struct {
|
||||
None bool `json:"none"`
|
||||
DeleteSeries []int `json:"delete_series"`
|
||||
Font Font `json:"font"`
|
||||
Layout layoutOptions `json:"layout"`
|
||||
Position string `json:"position"`
|
||||
ShowLegendEntry bool `json:"show_legend_entry"`
|
||||
ShowLegendKey bool `json:"show_legend_key"`
|
||||
}
|
||||
|
||||
// formatChartSeries directly maps the format settings of the chart series.
|
||||
type formatChartSeries struct {
|
||||
// chartSeriesOptions directly maps the format settings of the chart series.
|
||||
type chartSeriesOptions struct {
|
||||
Name string `json:"name"`
|
||||
Categories string `json:"categories"`
|
||||
Values string `json:"values"`
|
||||
|
@ -640,16 +641,16 @@ type formatChartSeries struct {
|
|||
} `json:"marker"`
|
||||
}
|
||||
|
||||
// formatChartTitle directly maps the format settings of the chart title.
|
||||
type formatChartTitle struct {
|
||||
None bool `json:"none"`
|
||||
Name string `json:"name"`
|
||||
Overlay bool `json:"overlay"`
|
||||
Layout formatLayout `json:"layout"`
|
||||
// chartTitleOptions directly maps the format settings of the chart title.
|
||||
type chartTitleOptions struct {
|
||||
None bool `json:"none"`
|
||||
Name string `json:"name"`
|
||||
Overlay bool `json:"overlay"`
|
||||
Layout layoutOptions `json:"layout"`
|
||||
}
|
||||
|
||||
// formatLayout directly maps the format settings of the element layout.
|
||||
type formatLayout struct {
|
||||
// layoutOptions directly maps the format settings of the element layout.
|
||||
type layoutOptions struct {
|
||||
X float64 `json:"x"`
|
||||
Y float64 `json:"y"`
|
||||
Width float64 `json:"width"`
|
||||
|
|
|
@ -72,8 +72,8 @@ type xlsxPhoneticRun struct {
|
|||
T string `xml:"t"`
|
||||
}
|
||||
|
||||
// formatComment directly maps the format settings of the comment.
|
||||
type formatComment struct {
|
||||
// commentOptions directly maps the format settings of the comment.
|
||||
type commentOptions struct {
|
||||
Author string `json:"author"`
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
|
|
@ -493,8 +493,8 @@ type xdrTxBody struct {
|
|||
P []*aP `xml:"a:p"`
|
||||
}
|
||||
|
||||
// formatPicture directly maps the format settings of the picture.
|
||||
type formatPicture struct {
|
||||
// pictureOptions directly maps the format settings of the picture.
|
||||
type pictureOptions struct {
|
||||
FPrintsWithSheet bool `json:"print_obj"`
|
||||
FLocksWithSheet bool `json:"locked"`
|
||||
NoChangeAspect bool `json:"lock_aspect_ratio"`
|
||||
|
@ -508,33 +508,33 @@ type formatPicture struct {
|
|||
Positioning string `json:"positioning"`
|
||||
}
|
||||
|
||||
// formatShape directly maps the format settings of the shape.
|
||||
type formatShape struct {
|
||||
Macro string `json:"macro"`
|
||||
Type string `json:"type"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
Format formatPicture `json:"format"`
|
||||
Color formatShapeColor `json:"color"`
|
||||
Line formatLine `json:"line"`
|
||||
Paragraph []formatShapeParagraph `json:"paragraph"`
|
||||
// shapeOptions directly maps the format settings of the shape.
|
||||
type shapeOptions struct {
|
||||
Macro string `json:"macro"`
|
||||
Type string `json:"type"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
Format pictureOptions `json:"format"`
|
||||
Color shapeColorOptions `json:"color"`
|
||||
Line lineOptions `json:"line"`
|
||||
Paragraph []shapeParagraphOptions `json:"paragraph"`
|
||||
}
|
||||
|
||||
// formatShapeParagraph directly maps the format settings of the paragraph in
|
||||
// shapeParagraphOptions directly maps the format settings of the paragraph in
|
||||
// the shape.
|
||||
type formatShapeParagraph struct {
|
||||
type shapeParagraphOptions struct {
|
||||
Font Font `json:"font"`
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
// formatShapeColor directly maps the color settings of the shape.
|
||||
type formatShapeColor struct {
|
||||
// shapeColorOptions directly maps the color settings of the shape.
|
||||
type shapeColorOptions struct {
|
||||
Line string `json:"line"`
|
||||
Fill string `json:"fill"`
|
||||
Effect string `json:"effect"`
|
||||
}
|
||||
|
||||
// formatLine directly maps the line settings of the shape.
|
||||
type formatLine struct {
|
||||
// lineOptions directly maps the line settings of the shape.
|
||||
type lineOptions struct {
|
||||
Width float64 `json:"width"`
|
||||
}
|
||||
|
|
|
@ -196,8 +196,8 @@ type xlsxTableStyleInfo struct {
|
|||
ShowColumnStripes bool `xml:"showColumnStripes,attr"`
|
||||
}
|
||||
|
||||
// formatTable directly maps the format settings of the table.
|
||||
type formatTable struct {
|
||||
// tableOptions directly maps the format settings of the table.
|
||||
type tableOptions struct {
|
||||
TableName string `json:"table_name"`
|
||||
TableStyle string `json:"table_style"`
|
||||
ShowFirstColumn bool `json:"show_first_column"`
|
||||
|
@ -206,8 +206,8 @@ type formatTable struct {
|
|||
ShowColumnStripes bool `json:"show_column_stripes"`
|
||||
}
|
||||
|
||||
// formatAutoFilter directly maps the auto filter settings.
|
||||
type formatAutoFilter struct {
|
||||
// autoFilterOptions directly maps the auto filter settings.
|
||||
type autoFilterOptions struct {
|
||||
Column string `json:"column"`
|
||||
Expression string `json:"expression"`
|
||||
FilterList []struct {
|
||||
|
|
|
@ -308,8 +308,15 @@ type xlsxCustomWorkbookView struct {
|
|||
// DefinedName directly maps the name for a cell or cell range on a
|
||||
// worksheet.
|
||||
type DefinedName struct {
|
||||
Name string
|
||||
Comment string
|
||||
RefersTo string
|
||||
Scope string
|
||||
Name string `json:"name,omitempty"`
|
||||
Comment string `json:"comment,omitempty"`
|
||||
RefersTo string `json:"refers_to,omitempty"`
|
||||
Scope string `json:"scope,omitempty"`
|
||||
}
|
||||
|
||||
// WorkbookPropsOptions directly maps the settings of workbook proprieties.
|
||||
type WorkbookPropsOptions struct {
|
||||
Date1904 *bool `json:"date_1994,omitempty"`
|
||||
FilterPrivacy *bool `json:"filter_privacy,omitempty"`
|
||||
CodeName *string `json:"code_name,omitempty"`
|
||||
}
|
||||
|
|
266
xmlWorksheet.go
266
xmlWorksheet.go
|
@ -454,7 +454,11 @@ type DataValidation struct {
|
|||
// b (Boolean) | Cell containing a boolean.
|
||||
// d (Date) | Cell contains a date in the ISO 8601 format.
|
||||
// e (Error) | Cell containing an error.
|
||||
// inlineStr (Inline String) | Cell containing an (inline) rich string, i.e., one not in the shared string table. If this cell type is used, then the cell value is in the is element rather than the v element in the cell (c element).
|
||||
// inlineStr (Inline String) | Cell containing an (inline) rich string, i.e.,
|
||||
// | one not in the shared string table. If this
|
||||
// | cell type is used, then the cell value is in
|
||||
// | the is element rather than the v element in
|
||||
// | the cell (c element).
|
||||
// n (Number) | Cell containing a number.
|
||||
// s (Shared String) | Cell containing a shared string.
|
||||
// str (String) | Cell containing a formula string.
|
||||
|
@ -777,39 +781,39 @@ type xlsxX14Sparkline struct {
|
|||
Sqref string `xml:"xm:sqref"`
|
||||
}
|
||||
|
||||
// SparklineOption directly maps the settings of the sparkline.
|
||||
type SparklineOption struct {
|
||||
Location []string
|
||||
Range []string
|
||||
Max int
|
||||
CustMax int
|
||||
Min int
|
||||
CustMin int
|
||||
Type string
|
||||
Weight float64
|
||||
DateAxis bool
|
||||
Markers bool
|
||||
High bool
|
||||
Low bool
|
||||
First bool
|
||||
Last bool
|
||||
Negative bool
|
||||
Axis bool
|
||||
Hidden bool
|
||||
Reverse bool
|
||||
Style int
|
||||
SeriesColor string
|
||||
NegativeColor string
|
||||
MarkersColor string
|
||||
FirstColor string
|
||||
LastColor string
|
||||
HightColor string
|
||||
LowColor string
|
||||
EmptyCells string
|
||||
// SparklineOptions directly maps the settings of the sparkline.
|
||||
type SparklineOptions struct {
|
||||
Location []string `json:"location"`
|
||||
Range []string `json:"range"`
|
||||
Max int `json:"max"`
|
||||
CustMax int `json:"cust_max"`
|
||||
Min int `json:"min"`
|
||||
CustMin int `json:"cust_min"`
|
||||
Type string `json:"hype"`
|
||||
Weight float64 `json:"weight"`
|
||||
DateAxis bool `json:"date_axis"`
|
||||
Markers bool `json:"markers"`
|
||||
High bool `json:"high"`
|
||||
Low bool `json:"low"`
|
||||
First bool `json:"first"`
|
||||
Last bool `json:"last"`
|
||||
Negative bool `json:"negative"`
|
||||
Axis bool `json:"axis"`
|
||||
Hidden bool `json:"hidden"`
|
||||
Reverse bool `json:"reverse"`
|
||||
Style int `json:"style"`
|
||||
SeriesColor string `json:"series_color"`
|
||||
NegativeColor string `json:"negative_color"`
|
||||
MarkersColor string `json:"markers_color"`
|
||||
FirstColor string `json:"first_color"`
|
||||
LastColor string `json:"last_color"`
|
||||
HightColor string `json:"hight_color"`
|
||||
LowColor string `json:"low_color"`
|
||||
EmptyCells string `json:"empty_cells"`
|
||||
}
|
||||
|
||||
// formatPanes directly maps the settings of the panes.
|
||||
type formatPanes struct {
|
||||
// panesOptions directly maps the settings of the panes.
|
||||
type panesOptions struct {
|
||||
Freeze bool `json:"freeze"`
|
||||
Split bool `json:"split"`
|
||||
XSplit int `json:"x_split"`
|
||||
|
@ -823,8 +827,8 @@ type formatPanes struct {
|
|||
} `json:"panes"`
|
||||
}
|
||||
|
||||
// formatConditional directly maps the conditional format settings of the cells.
|
||||
type formatConditional struct {
|
||||
// conditionalOptions directly maps the conditional format settings of the cells.
|
||||
type conditionalOptions struct {
|
||||
Type string `json:"type"`
|
||||
AboveAverage bool `json:"above_average,omitempty"`
|
||||
Percent bool `json:"percent,omitempty"`
|
||||
|
@ -848,47 +852,163 @@ type formatConditional struct {
|
|||
BarColor string `json:"bar_color,omitempty"`
|
||||
}
|
||||
|
||||
// FormatSheetProtection directly maps the settings of worksheet protection.
|
||||
type FormatSheetProtection struct {
|
||||
AlgorithmName string
|
||||
AutoFilter bool
|
||||
DeleteColumns bool
|
||||
DeleteRows bool
|
||||
EditObjects bool
|
||||
EditScenarios bool
|
||||
FormatCells bool
|
||||
FormatColumns bool
|
||||
FormatRows bool
|
||||
InsertColumns bool
|
||||
InsertHyperlinks bool
|
||||
InsertRows bool
|
||||
Password string
|
||||
PivotTables bool
|
||||
SelectLockedCells bool
|
||||
SelectUnlockedCells bool
|
||||
Sort bool
|
||||
// SheetProtectionOptions directly maps the settings of worksheet protection.
|
||||
type SheetProtectionOptions struct {
|
||||
AlgorithmName string `json:"algorithm_name,omitempty"`
|
||||
AutoFilter bool `json:"auto_filter,omitempty"`
|
||||
DeleteColumns bool `json:"delete_columns,omitempty"`
|
||||
DeleteRows bool `json:"delete_rows,omitempty"`
|
||||
EditObjects bool `json:"edit_objects,omitempty"`
|
||||
EditScenarios bool `json:"edit_scenarios,omitempty"`
|
||||
FormatCells bool `json:"format_cells,omitempty"`
|
||||
FormatColumns bool `json:"format_columns,omitempty"`
|
||||
FormatRows bool `json:"format_rows,omitempty"`
|
||||
InsertColumns bool `json:"insert_columns,omitempty"`
|
||||
InsertHyperlinks bool `json:"insert_hyperlinks,omitempty"`
|
||||
InsertRows bool `json:"insert_rows,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
PivotTables bool `json:"pivot_tables,omitempty"`
|
||||
SelectLockedCells bool `json:"select_locked_cells,omitempty"`
|
||||
SelectUnlockedCells bool `json:"select_unlocked_cells,omitempty"`
|
||||
Sort bool `json:"sort,omitempty"`
|
||||
}
|
||||
|
||||
// FormatHeaderFooter directly maps the settings of header and footer.
|
||||
type FormatHeaderFooter struct {
|
||||
AlignWithMargins bool
|
||||
DifferentFirst bool
|
||||
DifferentOddEven bool
|
||||
ScaleWithDoc bool
|
||||
OddHeader string
|
||||
OddFooter string
|
||||
EvenHeader string
|
||||
EvenFooter string
|
||||
FirstHeader string
|
||||
FirstFooter string
|
||||
// HeaderFooterOptions directly maps the settings of header and footer.
|
||||
type HeaderFooterOptions struct {
|
||||
AlignWithMargins bool `json:"align_with_margins,omitempty"`
|
||||
DifferentFirst bool `json:"different_first,omitempty"`
|
||||
DifferentOddEven bool `json:"different_odd_even,omitempty"`
|
||||
ScaleWithDoc bool `json:"scale_with_doc,omitempty"`
|
||||
OddHeader string `json:"odd_header,omitempty"`
|
||||
OddFooter string `json:"odd_footer,omitempty"`
|
||||
EvenHeader string `json:"even_header,omitempty"`
|
||||
EvenFooter string `json:"even_footer,omitempty"`
|
||||
FirstHeader string `json:"first_header,omitempty"`
|
||||
FirstFooter string `json:"first_footer,omitempty"`
|
||||
}
|
||||
|
||||
// FormatPageMargins directly maps the settings of page margins
|
||||
type FormatPageMargins struct {
|
||||
Bottom string
|
||||
Footer string
|
||||
Header string
|
||||
Left string
|
||||
Right string
|
||||
Top string
|
||||
// PageLayoutMarginsOptions directly maps the settings of page layout margins.
|
||||
type PageLayoutMarginsOptions struct {
|
||||
Bottom *float64 `json:"bottom,omitempty"`
|
||||
Footer *float64 `json:"footer,omitempty"`
|
||||
Header *float64 `json:"header,omitempty"`
|
||||
Left *float64 `json:"left,omitempty"`
|
||||
Right *float64 `json:"right,omitempty"`
|
||||
Top *float64 `json:"top,omitempty"`
|
||||
Horizontally *bool `json:"horizontally,omitempty"`
|
||||
Vertically *bool `json:"vertically,omitempty"`
|
||||
}
|
||||
|
||||
// PageLayoutOptions directly maps the settings of page layout.
|
||||
type PageLayoutOptions struct {
|
||||
// Size defines the paper size of the worksheet.
|
||||
Size *int `json:"size,omitempty"`
|
||||
// Orientation defines the orientation of page layout for a worksheet.
|
||||
Orientation *string `json:"orientation,omitempty"`
|
||||
// FirstPageNumber specified the first printed page number. If no value is
|
||||
// specified, then 'automatic' is assumed.
|
||||
FirstPageNumber *uint `json:"first_page_number,omitempty"`
|
||||
// AdjustTo defines the print scaling. This attribute is restricted to
|
||||
// value ranging from 10 (10%) to 400 (400%). This setting is overridden
|
||||
// when fitToWidth and/or fitToHeight are in use.
|
||||
AdjustTo *uint `json:"adjust_to,omitempty"`
|
||||
// FitToHeight specified the number of vertical pages to fit on.
|
||||
FitToHeight *int `json:"fit_to_height,omitempty"`
|
||||
// FitToWidth specified the number of horizontal pages to fit on.
|
||||
FitToWidth *int `json:"fit_to_width,omitempty"`
|
||||
// BlackAndWhite specified print black and white.
|
||||
BlackAndWhite *bool `json:"black_and_white,omitempty"`
|
||||
}
|
||||
|
||||
// ViewOptions directly maps the settings of sheet view.
|
||||
type ViewOptions struct {
|
||||
// DefaultGridColor indicating that the consuming application should use
|
||||
// the default grid lines color(system dependent). Overrides any color
|
||||
// specified in colorId.
|
||||
DefaultGridColor *bool `json:"default_grid_color,omitempty"`
|
||||
// RightToLeft indicating whether the sheet is in 'right to left' display
|
||||
// mode. When in this mode, Column A is on the far right, Column B; is one
|
||||
// column left of Column A, and so on. Also, information in cells is
|
||||
// displayed in the Right to Left format.
|
||||
RightToLeft *bool `json:"right_to_left,omitempty"`
|
||||
// ShowFormulas indicating whether this sheet should display formulas.
|
||||
ShowFormulas *bool `json:"show_formulas,omitempty"`
|
||||
// ShowGridLines indicating whether this sheet should display grid lines.
|
||||
ShowGridLines *bool `json:"show_grid_lines,omitempty"`
|
||||
// ShowRowColHeaders indicating whether the sheet should display row and
|
||||
// column headings.
|
||||
ShowRowColHeaders *bool `json:"show_row_col_headers,omitempty"`
|
||||
// ShowRuler indicating this sheet should display ruler.
|
||||
ShowRuler *bool `json:"show_ruler,omitempty"`
|
||||
// ShowZeros indicating whether to "show a zero in cells that have zero
|
||||
// value". When using a formula to reference another cell which is empty,
|
||||
// the referenced value becomes 0 when the flag is true. (Default setting
|
||||
// is true.)
|
||||
ShowZeros *bool `json:"show_zeros,omitempty"`
|
||||
// TopLeftCell specifies a location of the top left visible cell Location
|
||||
// of the top left visible cell in the bottom right pane (when in
|
||||
// Left-to-Right mode).
|
||||
TopLeftCell *string `json:"top_left_cell,omitempty"`
|
||||
// View indicating how sheet is displayed, by default it uses empty string
|
||||
// available options: normal, pageLayout, pageBreakPreview
|
||||
View *string `json:"low_color,omitempty"`
|
||||
// ZoomScale specifies a window zoom magnification for current view
|
||||
// representing percent values. This attribute is restricted to values
|
||||
// ranging from 10 to 400. Horizontal & Vertical scale together.
|
||||
ZoomScale *float64 `json:"zoom_scale,omitempty"`
|
||||
}
|
||||
|
||||
// SheetPropsOptions directly maps the settings of sheet view.
|
||||
type SheetPropsOptions struct {
|
||||
// Specifies a stable name of the sheet, which should not change over time,
|
||||
// and does not change from user input. This name should be used by code
|
||||
// to reference a particular sheet.
|
||||
CodeName *string `json:"code_name,omitempty"`
|
||||
// EnableFormatConditionsCalculation indicating whether the conditional
|
||||
// formatting calculations shall be evaluated. If set to false, then the
|
||||
// min/max values of color scales or data bars or threshold values in Top N
|
||||
// rules shall not be updated. Essentially the conditional
|
||||
// formatting "calc" is off.
|
||||
EnableFormatConditionsCalculation *bool `json:"enable_format_conditions_calculation,omitempty"`
|
||||
// Published indicating whether the worksheet is published.
|
||||
Published *bool `json:"published,omitempty"`
|
||||
// AutoPageBreaks indicating whether the sheet displays Automatic Page
|
||||
// Breaks.
|
||||
AutoPageBreaks *bool `json:"auto_page_breaks,omitempty"`
|
||||
// FitToPage indicating whether the Fit to Page print option is enabled.
|
||||
FitToPage *bool `json:"fit_to_page,omitempty"`
|
||||
// TabColorIndexed represents the indexed color value.
|
||||
TabColorIndexed *int `json:"tab_color_indexed,omitempty"`
|
||||
// TabColorRGB represents the standard Alpha Red Green Blue color value.
|
||||
TabColorRGB *string `json:"tab_color_rgb,omitempty"`
|
||||
// TabColorTheme represents the zero-based index into the collection,
|
||||
// referencing a particular value expressed in the Theme part.
|
||||
TabColorTheme *int `json:"tab_color_theme,omitempty"`
|
||||
// TabColorTint specifies the tint value applied to the color.
|
||||
TabColorTint *float64 `json:"tab_color_tint,omitempty"`
|
||||
// OutlineSummaryBelow indicating whether summary rows appear below detail
|
||||
// in an outline, when applying an outline.
|
||||
OutlineSummaryBelow *bool `json:"outline_summary_below,omitempty"`
|
||||
// BaseColWidth specifies the number of characters of the maximum digit
|
||||
// width of the normal style's font. This value does not include margin
|
||||
// padding or extra padding for grid lines. It is only the number of
|
||||
// characters.
|
||||
BaseColWidth *uint8 `json:"base_col_width,omitempty"`
|
||||
// DefaultColWidth specifies the default column width measured as the
|
||||
// number of characters of the maximum digit width of the normal style's
|
||||
// font.
|
||||
DefaultColWidth *float64 `json:"default_col_width,omitempty"`
|
||||
// DefaultRowHeight specifies the default row height measured in point
|
||||
// size. Optimization so we don't have to write the height on all rows.
|
||||
// This can be written out if most rows have custom height, to achieve the
|
||||
// optimization.
|
||||
DefaultRowHeight *float64 `json:"default_row_height,omitempty"`
|
||||
// CustomHeight specifies the custom height.
|
||||
CustomHeight *bool `json:"custom_height,omitempty"`
|
||||
// ZeroHeight specifies if rows are hidden.
|
||||
ZeroHeight *bool `json:"zero_height,omitempty"`
|
||||
// ThickTop specifies if rows have a thick top border by default.
|
||||
ThickTop *bool `json:"thick_top,omitempty"`
|
||||
// ThickBottom specifies if rows have a thick bottom border by default.
|
||||
ThickBottom *bool `json:"thick_bottom,omitempty"`
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue