diff --git a/calc.go b/calc.go index ef8d0b0..d650eca 100644 --- a/calc.go +++ b/calc.go @@ -948,7 +948,7 @@ func (f *File) parseOperatorPrefixToken(optStack, opdStack *Stack, token efp.Tok return } -// isFunctionStartToken determine if the token is function stop. +// isFunctionStartToken determine if the token is function start. func isFunctionStartToken(token efp.Token) bool { return token.TType == efp.TokenTypeFunction && token.TSubType == efp.TokenSubTypeStart } diff --git a/shape.go b/shape.go index e58d5cf..61322dd 100644 --- a/shape.go +++ b/shape.go @@ -32,6 +32,7 @@ func parseFormatShapeSet(formatSet string) (*formatShape, error) { XScale: 1.0, YScale: 1.0, }, + Line: formatLine{Width: 1}, } err := json.Unmarshal([]byte(formatSet), &format) return &format, err @@ -42,7 +43,33 @@ func parseFormatShapeSet(formatSet string) (*formatShape, error) { // print settings) and properties set. For example, add text box (rect shape) // in Sheet1: // -// err := f.AddShape("Sheet1", "G6", `{"type":"rect","color":{"line":"#4286F4","fill":"#8eb9ff"},"paragraph":[{"text":"Rectangle Shape","font":{"bold":true,"italic":true,"family":"Times New Roman","size":36,"color":"#777777","underline":"sng"}}],"width":180,"height": 90}`) +// err := f.AddShape("Sheet1", "G6", `{ +// "type": "rect", +// "color": +// { +// "line": "#4286F4", +// "fill": "#8eb9ff" +// }, +// "paragraph": [ +// { +// "text": "Rectangle Shape", +// "font": +// { +// "bold": true, +// "italic": true, +// "family": "Times New Roman", +// "size": 36, +// "color": "#777777", +// "underline": "sng" +// } +// }], +// "width": 180, +// "height": 90, +// "line": +// { +// "width": 1.2 +// } +// }`) // // The following shows the type of shape supported by excelize: // @@ -378,6 +405,11 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *format }, }, } + if formatSet.Line.Width != 1 { + shape.SpPr.Ln = xlsxLineProperties{ + W: f.ptToEMUs(formatSet.Line.Width), + } + } if len(formatSet.Paragraph) < 1 { formatSet.Paragraph = []formatShapeParagraph{ { diff --git a/shape_test.go b/shape_test.go index 61fb443..a02e53d 100644 --- a/shape_test.go +++ b/shape_test.go @@ -16,13 +16,75 @@ func TestAddShape(t *testing.T) { assert.NoError(t, f.AddShape("Sheet1", "A30", `{"type":"rect","paragraph":[{"text":"Rectangle","font":{"color":"CD5C5C"}},{"text":"Shape","font":{"bold":true,"color":"2980B9"}}]}`)) assert.NoError(t, f.AddShape("Sheet1", "B30", `{"type":"rect","paragraph":[{"text":"Rectangle"},{}]}`)) assert.NoError(t, f.AddShape("Sheet1", "C30", `{"type":"rect","paragraph":[]}`)) - assert.EqualError(t, f.AddShape("Sheet3", "H1", `{"type":"ellipseRibbon", "color":{"line":"#4286f4","fill":"#8eb9ff"}, "paragraph":[{"font":{"bold":true,"italic":true,"family":"Times New Roman","size":36,"color":"#777777","underline":"single"}}], "height": 90}`), "sheet Sheet3 is not exist") + assert.EqualError(t, f.AddShape("Sheet3", "H1", `{ + "type": "ellipseRibbon", + "color": + { + "line": "#4286f4", + "fill": "#8eb9ff" + }, + "paragraph": [ + { + "font": + { + "bold": true, + "italic": true, + "family": "Times New Roman", + "size": 36, + "color": "#777777", + "underline": "single" + } + }], + "height": 90 + }`), "sheet Sheet3 is not exist") assert.EqualError(t, f.AddShape("Sheet3", "H1", ""), "unexpected end of JSON input") - assert.EqualError(t, f.AddShape("Sheet1", "A", `{"type":"rect","paragraph":[{"text":"Rectangle","font":{"color":"CD5C5C"}},{"text":"Shape","font":{"bold":true,"color":"2980B9"}}]}`), `cannot convert cell "A" to coordinates: invalid cell name "A"`) + assert.EqualError(t, f.AddShape("Sheet1", "A", `{ + "type": "rect", + "paragraph": [ + { + "text": "Rectangle", + "font": + { + "color": "CD5C5C" + } + }, + { + "text": "Shape", + "font": + { + "bold": true, + "color": "2980B9" + } + }] + }`), `cannot convert cell "A" to coordinates: invalid cell name "A"`) assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddShape1.xlsx"))) // Test add first shape for given sheet. f = NewFile() - assert.NoError(t, f.AddShape("Sheet1", "A1", `{"type":"ellipseRibbon", "color":{"line":"#4286f4","fill":"#8eb9ff"}, "paragraph":[{"font":{"bold":true,"italic":true,"family":"Times New Roman","size":36,"color":"#777777","underline":"single"}}], "height": 90}`)) + assert.NoError(t, f.AddShape("Sheet1", "A1", `{ + "type": "ellipseRibbon", + "color": + { + "line": "#4286f4", + "fill": "#8eb9ff" + }, + "paragraph": [ + { + "font": + { + "bold": true, + "italic": true, + "family": "Times New Roman", + "size": 36, + "color": "#777777", + "underline": "single" + } + }], + "height": 90, + "line": + { + "width": 1.2 + } + }`)) assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddShape2.xlsx"))) } diff --git a/xmlDrawing.go b/xmlDrawing.go index b49ae9d..0bb11ac 100644 --- a/xmlDrawing.go +++ b/xmlDrawing.go @@ -234,14 +234,22 @@ type xlsxBlipFill struct { Stretch xlsxStretch `xml:"a:stretch"` } +// xlsxLineProperties specifies the width of a line in EMUs. This simple type +// has a minimum value of greater than or equal to 0. This simple type has a +// maximum value of less than or equal to 20116800. +type xlsxLineProperties struct { + W int `xml:"w,attr,omitempty"` +} + // xlsxSpPr directly maps the spPr (Shape Properties). This element specifies // the visual shape properties that can be applied to a picture. These are the // same properties that are allowed to describe the visual properties of a shape // but are used here to describe the visual appearance of a picture within a // document. type xlsxSpPr struct { - Xfrm xlsxXfrm `xml:"a:xfrm"` - PrstGeom xlsxPrstGeom `xml:"a:prstGeom"` + Xfrm xlsxXfrm `xml:"a:xfrm"` + PrstGeom xlsxPrstGeom `xml:"a:prstGeom"` + Ln xlsxLineProperties `xml:"a:ln"` } // xlsxPic elements encompass the definition of pictures within the DrawingML @@ -469,6 +477,7 @@ type formatShape struct { Height int `json:"height"` Format formatPicture `json:"format"` Color formatShapeColor `json:"color"` + Line formatLine `json:"line"` Paragraph []formatShapeParagraph `json:"paragraph"` } @@ -485,3 +494,8 @@ type formatShapeColor struct { Fill string `json:"fill"` Effect string `json:"effect"` } + +// formatLine directly maps the line settings of the shape. +type formatLine struct { + Width float64 `json:"width"` +}