From dfea8f96edc326717822ec9c4b92f462d0fe1255 Mon Sep 17 00:00:00 2001 From: xuri Date: Tue, 12 May 2020 23:26:26 +0800 Subject: [PATCH] - New API: SetSheetFormatPr and GetSheetFormatPr - typo fix, resolve #635 --- sheet.go | 2 +- sheetpr.go | 197 ++++++++++++++++++++++++++++++++++++++++++++++- sheetpr_test.go | 160 ++++++++++++++++++++++++++++++++++++++ xmlPivotCache.go | 11 +++ 4 files changed, 367 insertions(+), 3 deletions(-) diff --git a/sheet.go b/sheet.go index fa858af22f..6a935b1fdc 100644 --- a/sheet.go +++ b/sheet.go @@ -354,7 +354,7 @@ func (f *File) getSheetID(name string) int { // GetSheetIndex provides a function to get a sheet index of the workbook by // the given sheet name. If the given sheet name is invalid, it will return an -// integer type value -1. +// integer type value 0. func (f *File) GetSheetIndex(name string) int { var idx = -1 for index, sheet := range f.GetSheetList() { diff --git a/sheetpr.go b/sheetpr.go index 350e189a34..dbfb7341b3 100644 --- a/sheetpr.go +++ b/sheetpr.go @@ -313,7 +313,7 @@ type PageMarginsOptionsPtr interface { // SetPageMargins provides a function to set worksheet page margins. // // Available options: -// PageMarginBotom(float64) +// PageMarginBottom(float64) // PageMarginFooter(float64) // PageMarginHeader(float64) // PageMarginLeft(float64) @@ -339,7 +339,7 @@ func (f *File) SetPageMargins(sheet string, opts ...PageMarginsOptions) error { // GetPageMargins provides a function to get worksheet page margins. // // Available options: -// PageMarginBotom(float64) +// PageMarginBottom(float64) // PageMarginFooter(float64) // PageMarginHeader(float64) // PageMarginLeft(float64) @@ -357,3 +357,196 @@ func (f *File) GetPageMargins(sheet string, opts ...PageMarginsOptionsPtr) error } 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 + } + *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) + if err != nil { + return err + } + fp := s.SheetFormatPr + if fp == nil { + fp = new(xlsxSheetFormatPr) + s.SheetFormatPr = fp + } + for _, opt := range opts { + opt.setSheetFormatPr(fp) + } + 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 +} diff --git a/sheetpr_test.go b/sheetpr_test.go index 25b67d753e..6e031518e1 100644 --- a/sheetpr_test.go +++ b/sheetpr_test.go @@ -307,3 +307,163 @@ func TestGetPageMargins(t *testing.T) { // Test get page margins on not exists worksheet. assert.EqualError(t, f.GetPageMargins("SheetN"), "sheet SheetN is not exist") } + +func ExampleFile_SetSheetFormatPr() { + f := excelize.NewFile() + const sheet = "Sheet1" + + if err := f.SetSheetFormatPr(sheet, + excelize.BaseColWidth(1.0), + excelize.DefaultColWidth(1.0), + excelize.DefaultRowHeight(1.0), + excelize.CustomHeight(true), + excelize.ZeroHeight(true), + excelize.ThickTop(true), + excelize.ThickBottom(true), + ); err != nil { + fmt.Println(err) + } + // Output: +} + +func ExampleFile_GetSheetFormatPr() { + f := excelize.NewFile() + const sheet = "Sheet1" + + var ( + baseColWidth excelize.BaseColWidth + defaultColWidth excelize.DefaultColWidth + defaultRowHeight excelize.DefaultRowHeight + customHeight excelize.CustomHeight + zeroHeight excelize.ZeroHeight + thickTop excelize.ThickTop + thickBottom excelize.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 excelize.SheetFormatPrOptionsPtr + nonDefault excelize.SheetFormatPrOptions + }{ + {new(excelize.BaseColWidth), excelize.BaseColWidth(1.0)}, + {new(excelize.DefaultColWidth), excelize.DefaultColWidth(1.0)}, + {new(excelize.DefaultRowHeight), excelize.DefaultRowHeight(1.0)}, + {new(excelize.CustomHeight), excelize.CustomHeight(true)}, + {new(excelize.ZeroHeight), excelize.ZeroHeight(true)}, + {new(excelize.ThickTop), excelize.ThickTop(true)}, + {new(excelize.ThickBottom), excelize.ThickBottom(true)}, + } + + for i, test := range testData { + t.Run(fmt.Sprintf("TestData%d", i), func(t *testing.T) { + + opt := test.nonDefault + t.Logf("option %T", opt) + + def := deepcopy.Copy(test.container).(excelize.SheetFormatPrOptionsPtr) + val1 := deepcopy.Copy(def).(excelize.SheetFormatPrOptionsPtr) + val2 := deepcopy.Copy(def).(excelize.SheetFormatPrOptionsPtr) + + f := excelize.NewFile() + // Get the default value + assert.NoError(t, f.GetSheetFormatPr(sheet, def), opt) + // Get again and check + assert.NoError(t, f.GetSheetFormatPr(sheet, val1), opt) + if !assert.Equal(t, val1, def, opt) { + t.FailNow() + } + // Set the same value + assert.NoError(t, f.SetSheetFormatPr(sheet, val1), opt) + // Get again and check + assert.NoError(t, f.GetSheetFormatPr(sheet, val1), opt) + if !assert.Equal(t, val1, def, "%T: value should not have changed", opt) { + t.FailNow() + } + // Set a different value + assert.NoError(t, f.SetSheetFormatPr(sheet, test.nonDefault), opt) + assert.NoError(t, f.GetSheetFormatPr(sheet, val1), opt) + // Get again and compare + assert.NoError(t, f.GetSheetFormatPr(sheet, val2), opt) + if !assert.Equal(t, val1, val2, "%T: value should not have changed", opt) { + t.FailNow() + } + // Value should not be the same as the default + if !assert.NotEqual(t, def, val1, "%T: value should have changed from default", opt) { + t.FailNow() + } + // Restore the default value + assert.NoError(t, f.SetSheetFormatPr(sheet, def), opt) + assert.NoError(t, f.GetSheetFormatPr(sheet, val1), opt) + if !assert.Equal(t, def, val1) { + t.FailNow() + } + }) + } +} + +func TestSetSheetFormatPr(t *testing.T) { + f := excelize.NewFile() + assert.NoError(t, f.GetSheetFormatPr("Sheet1")) + f.Sheet["xl/worksheets/sheet1.xml"].SheetFormatPr = nil + assert.NoError(t, f.SetSheetFormatPr("Sheet1", excelize.BaseColWidth(1.0))) + // Test set formatting properties on not exists worksheet. + assert.EqualError(t, f.SetSheetFormatPr("SheetN"), "sheet SheetN is not exist") +} + +func TestGetSheetFormatPr(t *testing.T) { + f := excelize.NewFile() + assert.NoError(t, f.GetSheetFormatPr("Sheet1")) + f.Sheet["xl/worksheets/sheet1.xml"].SheetFormatPr = nil + var ( + baseColWidth excelize.BaseColWidth + defaultColWidth excelize.DefaultColWidth + defaultRowHeight excelize.DefaultRowHeight + customHeight excelize.CustomHeight + zeroHeight excelize.ZeroHeight + thickTop excelize.ThickTop + thickBottom excelize.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 is not exist") +} diff --git a/xmlPivotCache.go b/xmlPivotCache.go index 45b48de99c..feaec54f03 100644 --- a/xmlPivotCache.go +++ b/xmlPivotCache.go @@ -1,3 +1,14 @@ +// Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of +// this source code is governed by a BSD-style license that can be found in +// the LICENSE file. +// +// Package excelize providing a set of functions that allow you to write to +// and read from XLSX / XLSM / XLTM files. Supports reading and writing +// spreadsheet documents generated by Microsoft Exce™ 2007 and later. Supports +// complex components by high compatibility, and provided streaming API for +// generating or reading data from a worksheet with huge amounts of data. This +// library needs Go version 1.10 or later. + package excelize import "encoding/xml"