Support to create of 17 kinds of fill variants styles

- Update the unit tests
- Update the `SetHeaderFooter` function parameters name
- Update document for the `SetDocProps` and `SetCellHyperLink` functions
This commit is contained in:
xuri 2023-02-01 00:11:08 +08:00
parent be36b09c8a
commit 85e0b6c56e
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
5 changed files with 67 additions and 57 deletions

View File

@ -835,7 +835,7 @@ type HyperlinkOpts struct {
// //
// display, tooltip := "https://github.com/xuri/excelize", "Excelize on GitHub" // display, tooltip := "https://github.com/xuri/excelize", "Excelize on GitHub"
// if err := f.SetCellHyperLink("Sheet1", "A3", // if err := f.SetCellHyperLink("Sheet1", "A3",
// "https://github.com/xuri/excelize", "External", excelize.HyperlinkOpts{ // display, "External", excelize.HyperlinkOpts{
// Display: &display, // Display: &display,
// Tooltip: &tooltip, // Tooltip: &tooltip,
// }); err != nil { // }); err != nil {

View File

@ -120,39 +120,45 @@ func (f *File) GetAppProps() (ret *AppProperties, err error) {
// properties that can be set are: // properties that can be set are:
// //
// Property | Description // Property | Description
// ----------------+----------------------------------------------------------------------------- // ----------------+-----------------------------------------------------------
// Title | The name given to the resource. // Title | The name given to the resource.
// | // |
// Subject | The topic of the content of the resource. // Subject | The topic of the content of the resource.
// | // |
// Creator | An entity primarily responsible for making the content of the resource. // Creator | An entity primarily responsible for making the content of
// | the resource.
// | // |
// Keywords | A delimited set of keywords to support searching and indexing. This is // Keywords | A delimited set of keywords to support searching and
// | typically a list of terms that are not available elsewhere in the properties. // | indexing. This is typically a list of terms that are not
// | available elsewhere in the properties.
// | // |
// Description | An explanation of the content of the resource. // Description | An explanation of the content of the resource.
// | // |
// LastModifiedBy | The user who performed the last modification. The identification is // LastModifiedBy | The user who performed the last modification. The
// | environment-specific. // | identification is environment-specific.
// | // |
// Language | The language of the intellectual content of the resource. // Language | The language of the intellectual content of the resource.
// | // |
// Identifier | An unambiguous reference to the resource within a given context. // Identifier | An unambiguous reference to the resource within a given
// | context.
// | // |
// Revision | The topic of the content of the resource. // Revision | The topic of the content of the resource.
// | // |
// ContentStatus | The status of the content. For example: Values might include "Draft", // ContentStatus | The status of the content. For example: Values might
// | "Reviewed" and "Final" // | include "Draft", "Reviewed" and "Final"
// | // |
// Category | A categorization of the content of this package. // Category | A categorization of the content of this package.
// | // |
// Version | The version number. This value is set by the user or by the application. // Version | The version number. This value is set by the user or by
// | the application.
// | // |
// Modified | The created time of the content of the resource which // Created | The created time of the content of the resource which
// | represent in ISO 8601 UTC format, for example "2019-06-04T22:00:10Z". // | represent in ISO 8601 UTC format, for example
// | "2019-06-04T22:00:10Z".
// | // |
// Modified | The modified time of the content of the resource which // Modified | The modified time of the content of the resource which
// | represent in ISO 8601 UTC format, for example "2019-06-04T22:00:10Z". // | represent in ISO 8601 UTC format, for example
// | "2019-06-04T22:00:10Z".
// | // |
// //
// For example: // For example:

View File

@ -1183,17 +1183,17 @@ func attrValToBool(name string, attrs []xml.Attr) (val bool, err error) {
// that same page // that same page
// //
// - No footer on the first page // - No footer on the first page
func (f *File) SetHeaderFooter(sheet string, settings *HeaderFooterOptions) error { func (f *File) SetHeaderFooter(sheet string, opts *HeaderFooterOptions) error {
ws, err := f.workSheetReader(sheet) ws, err := f.workSheetReader(sheet)
if err != nil { if err != nil {
return err return err
} }
if settings == nil { if opts == nil {
ws.HeaderFooter = nil ws.HeaderFooter = nil
return err return err
} }
v := reflect.ValueOf(*settings) v := reflect.ValueOf(*opts)
// Check 6 string type fields: OddHeader, OddFooter, EvenHeader, EvenFooter, // Check 6 string type fields: OddHeader, OddFooter, EvenHeader, EvenFooter,
// FirstFooter, FirstHeader // FirstFooter, FirstHeader
for i := 4; i < v.NumField()-1; i++ { for i := 4; i < v.NumField()-1; i++ {
@ -1202,16 +1202,16 @@ func (f *File) SetHeaderFooter(sheet string, settings *HeaderFooterOptions) erro
} }
} }
ws.HeaderFooter = &xlsxHeaderFooter{ ws.HeaderFooter = &xlsxHeaderFooter{
AlignWithMargins: settings.AlignWithMargins, AlignWithMargins: opts.AlignWithMargins,
DifferentFirst: settings.DifferentFirst, DifferentFirst: opts.DifferentFirst,
DifferentOddEven: settings.DifferentOddEven, DifferentOddEven: opts.DifferentOddEven,
ScaleWithDoc: settings.ScaleWithDoc, ScaleWithDoc: opts.ScaleWithDoc,
OddHeader: settings.OddHeader, OddHeader: opts.OddHeader,
OddFooter: settings.OddFooter, OddFooter: opts.OddFooter,
EvenHeader: settings.EvenHeader, EvenHeader: opts.EvenHeader,
EvenFooter: settings.EvenFooter, EvenFooter: opts.EvenFooter,
FirstFooter: settings.FirstFooter, FirstFooter: opts.FirstFooter,
FirstHeader: settings.FirstHeader, FirstHeader: opts.FirstHeader,
} }
return err return err
} }

View File

@ -1145,9 +1145,9 @@ func parseFormatStyleSet(style *Style) (*Style, error) {
// //
// Index | Style | Index | Style // Index | Style | Index | Style
// -------+-----------------+-------+----------------- // -------+-----------------+-------+-----------------
// 0 | Horizontal | 3 | Diagonal down // 0-2 | Horizontal | 9-11 | Diagonal down
// 1 | Vertical | 4 | From corner // 3-5 | Vertical | 12-15 | From corner
// 2 | Diagonal Up | 5 | From center // 6-8 | Diagonal Up | 16 | From center
// //
// The following table shows the pattern styles used in 'Fill.Pattern' supported // The following table shows the pattern styles used in 'Fill.Pattern' supported
// by excelize index number: // by excelize index number:
@ -2459,41 +2459,38 @@ func newFills(style *Style, fg bool) *xlsxFill {
"gray125", "gray125",
"gray0625", "gray0625",
} }
variants := []xlsxGradientFill{
variants := []float64{ {Degree: 90, Stop: []*xlsxGradientFillStop{{}, {Position: 1}}},
90, {Degree: 270, Stop: []*xlsxGradientFillStop{{}, {Position: 1}}},
0, {Degree: 90, Stop: []*xlsxGradientFillStop{{}, {Position: 0.5}, {Position: 1}}},
45, {Stop: []*xlsxGradientFillStop{{}, {Position: 1}}},
135, {Degree: 180, Stop: []*xlsxGradientFillStop{{}, {Position: 1}}},
{Stop: []*xlsxGradientFillStop{{}, {Position: 0.5}, {Position: 1}}},
{Degree: 45, Stop: []*xlsxGradientFillStop{{}, {Position: 1}}},
{Degree: 255, Stop: []*xlsxGradientFillStop{{}, {Position: 1}}},
{Degree: 45, Stop: []*xlsxGradientFillStop{{}, {Position: 0.5}, {Position: 1}}},
{Degree: 135, Stop: []*xlsxGradientFillStop{{}, {Position: 1}}},
{Degree: 315, Stop: []*xlsxGradientFillStop{{}, {Position: 1}}},
{Degree: 135, Stop: []*xlsxGradientFillStop{{}, {Position: 0.5}, {Position: 1}}},
{Stop: []*xlsxGradientFillStop{{}, {Position: 1}}, Type: "path"},
{Stop: []*xlsxGradientFillStop{{}, {Position: 1}}, Type: "path", Left: 1, Right: 1},
{Stop: []*xlsxGradientFillStop{{}, {Position: 1}}, Type: "path", Bottom: 1, Top: 1},
{Stop: []*xlsxGradientFillStop{{}, {Position: 1}}, Type: "path", Bottom: 1, Left: 1, Right: 1, Top: 1},
{Stop: []*xlsxGradientFillStop{{}, {Position: 1}}, Type: "path", Bottom: 0.5, Left: 0.5, Right: 0.5, Top: 0.5},
} }
var fill xlsxFill var fill xlsxFill
switch style.Fill.Type { switch style.Fill.Type {
case "gradient": case "gradient":
if len(style.Fill.Color) != 2 { if len(style.Fill.Color) != 2 || style.Fill.Shading < 0 || style.Fill.Shading > 16 {
break break
} }
var gradient xlsxGradientFill gradient := variants[style.Fill.Shading]
switch style.Fill.Shading { gradient.Stop[0].Color.RGB = getPaletteColor(style.Fill.Color[0])
case 0, 1, 2, 3: gradient.Stop[1].Color.RGB = getPaletteColor(style.Fill.Color[1])
gradient.Degree = variants[style.Fill.Shading] if len(gradient.Stop) == 3 {
case 4: gradient.Stop[2].Color.RGB = getPaletteColor(style.Fill.Color[0])
gradient.Type = "path"
case 5:
gradient.Type = "path"
gradient.Bottom = 0.5
gradient.Left = 0.5
gradient.Right = 0.5
gradient.Top = 0.5
} }
var stops []*xlsxGradientFillStop
for index, color := range style.Fill.Color {
var stop xlsxGradientFillStop
stop.Position = float64(index)
stop.Color.RGB = getPaletteColor(color)
stops = append(stops, &stop)
}
gradient.Stop = stops
fill.GradientFill = &gradient fill.GradientFill = &gradient
case "pattern": case "pattern":
if style.Fill.Pattern > 18 || style.Fill.Pattern < 0 { if style.Fill.Pattern > 18 || style.Fill.Pattern < 0 {

View File

@ -223,6 +223,13 @@ func TestUnsetConditionalFormat(t *testing.T) {
func TestNewStyle(t *testing.T) { func TestNewStyle(t *testing.T) {
f := NewFile() f := NewFile()
for i := 0; i < 18; i++ {
_, err := f.NewStyle(&Style{
Fill: Fill{Type: "gradient", Color: []string{"#FFFFFF", "#4E71BE"}, Shading: i},
})
assert.NoError(t, err)
}
f = NewFile()
styleID, err := f.NewStyle(&Style{Font: &Font{Bold: true, Italic: true, Family: "Times New Roman", Size: 36, Color: "#777777"}}) styleID, err := f.NewStyle(&Style{Font: &Font{Bold: true, Italic: true, Family: "Times New Roman", Size: 36, Color: "#777777"}})
assert.NoError(t, err) assert.NoError(t, err)
styles, err := f.stylesReader() styles, err := f.stylesReader()