Skip to content

Commit dd07139

Browse files
committed
This closes qax-os#2176, support set transparency for chart and shape
- Add Transparency field in the Fill data type - Add a new exported error variable ErrTransparency - Update error message for more clear - Update unit tests
1 parent 249b593 commit dd07139

File tree

12 files changed

+83
-23
lines changed

12 files changed

+83
-23
lines changed

chart_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ func TestAddChart(t *testing.T) {
177177
series2 := []ChartSeries{
178178
{
179179
Name: "Sheet1!$A$30", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$30:$D$30",
180-
Fill: Fill{Type: "pattern", Color: []string{"000000"}, Pattern: 1},
180+
Fill: Fill{Type: "pattern", Color: []string{"000000"}, Pattern: 1, Transparency: 60},
181181
Marker: ChartMarker{Symbol: "none", Size: 10},
182182
},
183183
{Name: "Sheet1!$A$31", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$31:$D$31"},

drawing.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -788,7 +788,11 @@ func (f *File) drawShapeFill(fill Fill, spPr *cSpPr) *cSpPr {
788788
spPr = &cSpPr{}
789789
}
790790
if len(fill.Color) == 1 {
791-
spPr.SolidFill = &aSolidFill{SrgbClr: &attrValString{Val: stringPtr(strings.TrimPrefix(fill.Color[0], "#"))}}
791+
spPr.SolidFill = &aSolidFill{SrgbClr: &aSrgbClr{Val: stringPtr(strings.TrimPrefix(fill.Color[0], "#"))}}
792+
if fill.Transparency > 0 {
793+
val := (100 - fill.Transparency) * 1000
794+
spPr.SolidFill.SrgbClr.Alpha = &attrValInt{Val: &val}
795+
}
792796
return spPr
793797
}
794798
spPr.SolidFill = nil
@@ -1186,7 +1190,7 @@ func drawChartFont(fnt *Font, r *aRPr) {
11861190
r.SolidFill = &aSolidFill{}
11871191
}
11881192
r.SolidFill.SchemeClr = nil
1189-
r.SolidFill.SrgbClr = &attrValString{Val: stringPtr(strings.ReplaceAll(strings.ToUpper(fnt.Color), "#", ""))}
1193+
r.SolidFill.SrgbClr = &aSrgbClr{Val: stringPtr(strings.ReplaceAll(strings.ToUpper(fnt.Color), "#", ""))}
11901194
}
11911195
if fnt.Family != "" {
11921196
if r.Latin == nil {

errors.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ var (
6060
// family name overflow.
6161
ErrFontLength = fmt.Errorf("the length of the font family name must be less than or equal to %d", MaxFontFamilyLength)
6262
// ErrFontSize defined the error message on the size of the font is invalid.
63-
ErrFontSize = fmt.Errorf("font size must be between %d and %d points", MinFontSize, MaxFontSize)
63+
ErrFontSize = fmt.Errorf("font size must be an integer from %d to %d points", MinFontSize, MaxFontSize)
6464
// ErrFormControlValue defined the error message for receiving a scroll
6565
// value exceeds limit.
66-
ErrFormControlValue = fmt.Errorf("scroll value must be between 0 and %d", MaxFormControlValue)
66+
ErrFormControlValue = fmt.Errorf("scroll value must be an integer from 0 to %d", MaxFormControlValue)
6767
// ErrGroupSheets defined the error message on group sheets.
6868
ErrGroupSheets = errors.New("group worksheet must contain an active worksheet")
6969
// ErrImgExt defined the error message on receive an unsupported image
@@ -91,7 +91,7 @@ var (
9191
ErrOutlineLevel = errors.New("invalid outline level")
9292
// ErrPageSetupAdjustTo defined the error message for receiving a page setup
9393
// adjust to value exceeds limit.
94-
ErrPageSetupAdjustTo = errors.New("adjust to value must be between 10 and 400")
94+
ErrPageSetupAdjustTo = errors.New("adjust to value must be an integer from 0 to 400")
9595
// ErrParameterInvalid defined the error message on receive the invalid
9696
// parameter.
9797
ErrParameterInvalid = errors.New("parameter is invalid")
@@ -132,10 +132,10 @@ var (
132132
ErrSparklineRange = errors.New("parameter 'Range' is required")
133133
// ErrSparklineStyle defined the error message on receive the invalid
134134
// sparkline Style parameters.
135-
ErrSparklineStyle = errors.New("parameter 'Style' must between 0-35")
135+
ErrSparklineStyle = errors.New("parameter 'Style' value must be an integer from 0 to 35")
136136
// ErrSparklineType defined the error message on receive the invalid
137137
// sparkline Type parameters.
138-
ErrSparklineType = errors.New("parameter 'Type' must be 'line', 'column' or 'win_loss'")
138+
ErrSparklineType = errors.New("parameter 'Type' value must be one of 'line', 'column' or 'win_loss'")
139139
// ErrStreamSetColStyle defined the error message on set column style in
140140
// stream writing mode.
141141
ErrStreamSetColStyle = errors.New("must call the SetColStyle function before the SetRow function")
@@ -148,6 +148,9 @@ var (
148148
// ErrTotalSheetHyperlinks defined the error message on hyperlinks count
149149
// overflow.
150150
ErrTotalSheetHyperlinks = errors.New("over maximum limit hyperlinks in a worksheet")
151+
// ErrTransparency defined the error message for receiving a transparency
152+
// value exceeds limit.
153+
ErrTransparency = errors.New("transparency value must be an integer from 0 to 100")
151154
// ErrUnknownEncryptMechanism defined the error message on unsupported
152155
// encryption mechanism.
153156
ErrUnknownEncryptMechanism = errors.New("unknown encryption mechanism")

shape.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ func parseShapeOptions(opts *Shape) (*Shape, error) {
4646
if opts.Line.Width == nil {
4747
opts.Line.Width = float64Ptr(defaultShapeLineWidth)
4848
}
49+
if opts.Fill.Transparency < 0 || 100 < opts.Fill.Transparency {
50+
return opts, ErrTransparency
51+
}
4952
return opts, nil
5053
}
5154

@@ -363,7 +366,7 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, opts *Shape) erro
363366
}
364367
var solidColor string
365368
if len(opts.Fill.Color) == 1 {
366-
solidColor = opts.Fill.Color[0]
369+
solidColor = strings.ReplaceAll(strings.ToUpper(opts.Fill.Color[0]), "#", "")
367370
}
368371
shape := xdrSp{
369372
Macro: opts.Macro,
@@ -407,6 +410,13 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, opts *Shape) erro
407410
W: f.ptToEMUs(*opts.Line.Width),
408411
}
409412
}
413+
if opts.Fill.Transparency > 0 {
414+
val := (100 - opts.Fill.Transparency) * 1000
415+
shape.SpPr.SolidFill = &aSolidFill{SrgbClr: &aSrgbClr{
416+
Val: stringPtr(solidColor),
417+
Alpha: &attrValInt{Val: &val},
418+
}}
419+
}
410420
defaultFont, err := f.GetDefaultFont()
411421
if err != nil {
412422
return err
@@ -459,7 +469,7 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, opts *Shape) erro
459469
srgbClr := strings.ReplaceAll(strings.ToUpper(font.Color), "#", "")
460470
if len(srgbClr) == 6 {
461471
paragraph.R.RPr.SolidFill = &aSolidFill{
462-
SrgbClr: &attrValString{
472+
SrgbClr: &aSrgbClr{
463473
Val: stringPtr(srgbClr),
464474
},
465475
}

shape_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func TestAddShape(t *testing.T) {
6262
Cell: "A1",
6363
Type: "ellipseRibbon",
6464
Line: ShapeLine{Color: "4286F4", Width: &lineWidth},
65-
Fill: Fill{Color: []string{"8EB9FF"}},
65+
Fill: Fill{Color: []string{"8EB9FF"}, Transparency: 60},
6666
Paragraph: []RichTextRun{
6767
{
6868
Font: &Font{
@@ -87,6 +87,8 @@ func TestAddShape(t *testing.T) {
8787
{Text: "Shape", Font: &Font{Bold: true, Color: "2980B9"}},
8888
},
8989
}))
90+
// Test add shape with transparency value exceeds limit
91+
assert.Equal(t, ErrTransparency, f.AddShape("Sheet1", &Shape{Cell: "B30", Type: "rect", Fill: Fill{Color: []string{"8EB9FF"}, Transparency: 110}}))
9092
// Test add shape with unsupported charset style sheet
9193
f.Styles = nil
9294
f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)

sheet_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,11 +219,11 @@ func TestSetPageLayout(t *testing.T) {
219219
// Test set page layout on not exists worksheet
220220
assert.EqualError(t, f.SetPageLayout("SheetN", nil), "sheet SheetN does not exist")
221221
// Test set page layout with invalid sheet name
222-
assert.EqualError(t, f.SetPageLayout("Sheet:1", nil), ErrSheetNameInvalid.Error())
222+
assert.Equal(t, ErrSheetNameInvalid, f.SetPageLayout("Sheet:1", nil))
223223
// Test set page layout with invalid parameters
224-
assert.EqualError(t, f.SetPageLayout("Sheet1", &PageLayoutOptions{
224+
assert.Equal(t, ErrPageSetupAdjustTo, f.SetPageLayout("Sheet1", &PageLayoutOptions{
225225
AdjustTo: uintPtr(5),
226-
}), "adjust to value must be between 10 and 400")
226+
}))
227227
assert.EqualError(t, f.SetPageLayout("Sheet1", &PageLayoutOptions{
228228
Orientation: stringPtr("x"),
229229
}), "invalid Orientation value \"x\", acceptable value should be one of portrait, landscape")

slicer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ func (f *File) addDrawingSlicer(sheet, slicerName string, ns xml.Attr, opts *Sli
633633
},
634634
SpPr: &xlsxSpPr{
635635
Xfrm: xlsxXfrm{Off: xlsxOff{X: 2914650, Y: 152400}, Ext: xlsxPositiveSize2D{Cx: 1828800, Cy: 2238375}},
636-
SolidFill: &xlsxInnerXML{Content: "<a:prstClr val=\"white\"/>"},
636+
SolidFill: &aSolidFill{SrgbClr: &aSrgbClr{Val: stringPtr("FFFFFF")}},
637637
PrstGeom: xlsxPrstGeom{
638638
Prst: "rect",
639639
},

sparkline.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ func (f *File) parseFormatAddSparklineSet(sheet string, opts *SparklineOptions)
461461
if len(opts.Location) != len(opts.Range) {
462462
return ws, ErrSparkline
463463
}
464-
if opts.Style < 0 || opts.Style > 35 {
464+
if opts.Style < 0 || 35 < opts.Style {
465465
return ws, ErrSparklineStyle
466466
}
467467
if ws.ExtLst == nil {

styles.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,11 @@ func parseFormatStyleSet(style *Style) (*Style, error) {
216216
// 8 | darkUp | 18 | gray0625
217217
// 9 | darkGrid | |
218218
//
219+
// The 'Fill.Transparency' only use to set transparency for chart and shape, not
220+
// used for cell. The value of 'Fill.Transparency' should be a number from 0 to
221+
// 100, which represents 0% to 100%, The default value is 0, representing full
222+
// opaque (not transparent).
223+
//
219224
// The 'Alignment.Indent' is an integer value, where an increment of 1
220225
// represents 3 spaces. Indicates the number of spaces (of the normal style
221226
// font) of indentation for text in a cell. The number of spaces to indent is

xmlChart.go

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,47 @@ type aPPr struct {
119119
DefRPr aRPr `xml:"a:defRPr"`
120120
}
121121

122+
// aSrgbClr (RGB Color Model - Hex Variant) specifies a color using the red,
123+
// green, blue RGB color model. Red, green, and blue is expressed as sequence of
124+
// hex digits, RRGGBB. A perceptual gamma of 2.2 is used.
125+
type aSrgbClr struct {
126+
Val *string `xml:"val,attr"`
127+
Tint *attrValInt `xml:"a:tint"`
128+
Shade *attrValInt `xml:"a:shade"`
129+
Comp *attrValInt `xml:"a:comp"`
130+
Inv *attrValInt `xml:"a:inv"`
131+
Gray *attrValInt `xml:"a:gray"`
132+
Alpha *attrValInt `xml:"a:alpha"`
133+
AlphaOff *attrValInt `xml:"a:alphaOff"`
134+
AlphaMod *attrValInt `xml:"a:alphaMod"`
135+
Hue *attrValInt `xml:"a:hue"`
136+
HueOff *attrValInt `xml:"a:hueOff"`
137+
HueMod *attrValInt `xml:"a:hueMod"`
138+
Sat *attrValInt `xml:"a:sat"`
139+
SatOff *attrValInt `xml:"a:satOff"`
140+
SatMod *attrValInt `xml:"a:satMod"`
141+
Lum *attrValInt `xml:"a:lum"`
142+
LumOff *attrValInt `xml:"a:lumOff"`
143+
LumMod *attrValInt `xml:"a:lumMod"`
144+
Red *attrValInt `xml:"a:red"`
145+
RedOff *attrValInt `xml:"a:redOff"`
146+
RedMod *attrValInt `xml:"a:redMod"`
147+
Green *attrValInt `xml:"a:green"`
148+
GreenOff *attrValInt `xml:"a:greenOff"`
149+
GreenMod *attrValInt `xml:"a:greenMod"`
150+
Blue *attrValInt `xml:"a:blue"`
151+
BlueOff *attrValInt `xml:"a:blueOff"`
152+
BlueMod *attrValInt `xml:"a:blueMod"`
153+
Gamma *attrValInt `xml:"a:gamma"`
154+
InvGamma *attrValInt `xml:"a:invGamma"`
155+
}
156+
122157
// aSolidFill (Solid Fill) directly maps the solidFill element. This element
123158
// specifies a solid color fill. The shape is filled entirely with the specified
124159
// color.
125160
type aSolidFill struct {
126-
SchemeClr *aSchemeClr `xml:"a:schemeClr"`
127-
SrgbClr *attrValString `xml:"a:srgbClr"`
161+
SchemeClr *aSchemeClr `xml:"a:schemeClr"`
162+
SrgbClr *aSrgbClr `xml:"a:srgbClr"`
128163
}
129164

130165
// aSchemeClr (Scheme Color) directly maps the a:schemeClr element. This

0 commit comments

Comments
 (0)