From 70f6328150aa954cd9721e90883f001ea005c1ee Mon Sep 17 00:00:00 2001 From: Ri Xu Date: Tue, 16 May 2017 20:42:01 +0800 Subject: [PATCH] Support set font style of shape text. Relate issue #38. --- chart.go | 6 ++-- comment.go | 6 ++-- excelize_test.go | 2 +- shape.go | 50 +++++++++++++++++++++++++++++++-- xmlChart.go | 73 ++++++++++++++++++++---------------------------- xmlDrawing.go | 1 + xmlStyles.go | 19 +++++++------ 7 files changed, 96 insertions(+), 61 deletions(-) diff --git a/chart.go b/chart.go index ba428d5..3f21ea6 100644 --- a/chart.go +++ b/chart.go @@ -252,7 +252,7 @@ func (f *File) addChart(formatSet *formatChart) { Rich: &cRich{ P: aP{ PPr: &aPPr{ - DefRPr: aDefRPr{ + DefRPr: aRPr{ Kern: 1200, Strike: "noStrike", U: "none", @@ -292,7 +292,7 @@ func (f *File) addChart(formatSet *formatChart) { TxPr: cTxPr{ P: aP{ PPr: &aPPr{ - DefRPr: aDefRPr{ + DefRPr: aRPr{ Kern: 1200, U: "none", Sz: 14000, @@ -812,7 +812,7 @@ func (f *File) drawPlotAreaTxPr() *cTxPr { }, P: aP{ PPr: &aPPr{ - DefRPr: aDefRPr{ + DefRPr: aRPr{ Sz: 900, B: false, I: false, diff --git a/comment.go b/comment.go index 48a1654..3dae11a 100644 --- a/comment.go +++ b/comment.go @@ -158,7 +158,7 @@ func (f *File) addComment(commentsXML, cell string, formatSet *formatComment) { } comments := xlsxComments{ Authors: []xlsxAuthor{ - xlsxAuthor{ + { Author: formatSet.Author, }, }, @@ -168,7 +168,7 @@ func (f *File) addComment(commentsXML, cell string, formatSet *formatComment) { AuthorID: 0, Text: xlsxText{ R: []xlsxR{ - xlsxR{ + { RPr: &xlsxRPr{ B: " ", Sz: &attrValInt{Val: 9}, @@ -180,7 +180,7 @@ func (f *File) addComment(commentsXML, cell string, formatSet *formatComment) { }, T: a, }, - xlsxR{ + { RPr: &xlsxRPr{ Sz: &attrValInt{Val: 9}, Color: &xlsxColor{ diff --git a/excelize_test.go b/excelize_test.go index a5cc657..99c2dd4 100644 --- a/excelize_test.go +++ b/excelize_test.go @@ -517,7 +517,7 @@ func TestAddShape(t *testing.T) { t.Log(err) } xlsx.AddShape("Sheet1", "A30", `{"type":"rect","text":"Rectangle Shape"}`) - xlsx.AddShape("Sheet3", "H1", `{"type":"ellipseRibbon", "color":{"line":"#4286f4","fill":"#8eb9ff"}, "height": 90}`) + xlsx.AddShape("Sheet3", "H1", `{"type":"ellipseRibbon", "color":{"line":"#4286f4","fill":"#8eb9ff"}, "font":{"bold":true,"italic":true,"family":"Berlin Sans FB Demi","size":36,"color":"#777777","underline":"single"}, "height": 90}`) err = xlsx.Save() if err != nil { t.Log(err) diff --git a/shape.go b/shape.go index 5994c31..1805b66 100644 --- a/shape.go +++ b/shape.go @@ -22,6 +22,14 @@ func parseFormatShapeSet(formatSet string) *formatShape { XScale: 1.0, YScale: 1.0, }, + Font: formatFont{ + Bold: false, + Italic: false, + Underline: "none", + Family: "Calibri", + Size: 11, + Color: "#000000", + }, Text: " ", } json.Unmarshal([]byte(formatSet), &format) @@ -33,7 +41,7 @@ func parseFormatShapeSet(formatSet string) *formatShape { // print settings) and properties set. For example, add text box (rect shape) in // Sheet1: // -// xlsx.AddShape("Sheet1", "G6", `{"type":"rect", "text":"Rectangle Shape", "color":{"line":"#4286F4","fill":"#8eb9ff"}, "width": 180, "height": 90}`) +// xlsx.AddShape("Sheet1", "G6", `{"type":"rect", "text":"Rectangle Shape", "color":{"line":"#4286F4","fill":"#8eb9ff"}, "font":{"bold":true,"italic":true,"family":"Berlin Sans FB Demi","size":36,"color":"#777777","underline":"sng"}, "width": 180, "height": 90}`) // // The following shows the type of chart supported by excelize: // @@ -225,6 +233,27 @@ func parseFormatShapeSet(formatSet string) *formatShape { // wedgeRectCallout (Callout Wedge Rectangle Shape) // wedgeRoundRectCallout (Callout Wedge Round Rectangle Shape) // +// The following shows the type of text underline supported by excelize: +// +// none +// words +// sng +// dbl +// heavy +// dotted +// dottedHeavy +// dash +// dashHeavy +// dashLong +// dashLongHeavy +// dotDash +// dotDashHeavy +// dotDotDash +// dotDotDashHeavy +// wavy +// wavyHeavy +// wavyDbl +// func (f *File) AddShape(sheet, cell, format string) { formatSet := parseFormatShapeSet(format) // Read sheet data. @@ -250,6 +279,12 @@ func (f *File) AddShape(sheet, cell, format string) { // addDrawingShape func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *formatShape) { + textUnderlineType := map[string]bool{"none": true, "words": true, "sng": true, "dbl": true, "heavy": true, "dotted": true, "dottedHeavy": true, "dash": true, "dashHeavy": true, "dashLong": true, "dashLongHeavy": true, "dotDash": true, "dotDashHeavy": true, "dotDotDash": true, "dotDotDashHeavy": true, "wavy": true, "wavyHeavy": true, "wavyDbl": true} + u := formatSet.Font.Underline + _, ok := textUnderlineType[u] + if !ok { + u = "none" + } cell = strings.ToUpper(cell) fromCol := string(strings.Map(letterOnlyMapF, cell)) fromRow, _ := strconv.Atoi(strings.Map(intOnlyMapF, cell)) @@ -262,7 +297,7 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *format content.A = NameSpaceDrawingML content.Xdr = NameSpaceDrawingMLSpreadSheet cNvPrID := 1 - _, ok := f.XLSX[drawingXML] + _, ok = f.XLSX[drawingXML] if ok { // Append Model decodeWsDr := decodeWsDr{} xml.Unmarshal([]byte(f.readXML(drawingXML)), &decodeWsDr) @@ -331,9 +366,18 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *format P: &aP{ R: &aR{ RPr: aRPr{ + I: formatSet.Font.Italic, + B: formatSet.Font.Bold, Lang: "en-US", AltLang: "en-US", - Sz: 1100, + U: u, + Sz: formatSet.Font.Size * 100, + Latin: &aLatin{Typeface: formatSet.Font.Family}, + SolidFill: &aSolidFill{ + SrgbClr: &attrValString{ + Val: strings.Replace(strings.ToUpper(formatSet.Font.Color), "#", "", -1), + }, + }, }, T: formatSet.Text, }, diff --git a/xmlChart.go b/xmlChart.go index 816cb2b..4d5b382 100644 --- a/xmlChart.go +++ b/xmlChart.go @@ -108,44 +108,15 @@ type aP struct { // formatting, since they are directly applied to the paragraph and supersede // any formatting from styles. type aPPr struct { - DefRPr aDefRPr `xml:"a:defRPr"` -} - -// aDefRPr directly maps the a:defRPr element. This element contains all -// default run level text properties for the text runs within a containing -// paragraph. These properties are to be used when overriding properties have -// not been defined within the rPr element. -type aDefRPr struct { - AltLang string `xml:"altLang,attr,omitempty"` - B bool `xml:"b,attr"` - Baseline int `xml:"baseline,attr"` - Bmk string `xml:"bmk,attr,omitempty"` - Cap string `xml:"cap,attr,omitempty"` - Dirty bool `xml:"dirty,attr,omitempty"` - Err bool `xml:"err,attr,omitempty"` - I bool `xml:"i,attr"` - Kern int `xml:"kern,attr"` - Kumimoji bool `xml:"kumimoji,attr,omitempty"` - Lang string `xml:"lang,attr,omitempty"` - NoProof bool `xml:"noProof,attr,omitempty"` - NormalizeH bool `xml:"normalizeH,attr,omitempty"` - SmtClean bool `xml:"smtClean,attr,omitempty"` - SmtID uint64 `xml:"smtId,attr,omitempty"` - Spc int `xml:"spc,attr"` - Strike string `xml:"strike,attr,omitempty"` - Sz int `xml:"sz,attr"` - U string `xml:"u,attr,omitempty"` - SolidFill *aSolidFill `xml:"a:solidFill"` - Latin *aLatin `xml:"a:latin"` - Ea *aEa `xml:"a:ea"` - Cs *aCs `xml:"a:cs"` + DefRPr aRPr `xml:"a:defRPr"` } // aSolidFill (Solid Fill) directly maps the solidFill element. This element // specifies a solid color fill. The shape is filled entirely with the specified // color. type aSolidFill struct { - SchemeClr *aSchemeClr `xml:"a:schemeClr,omitempty"` + SchemeClr *aSchemeClr `xml:"a:schemeClr"` + SrgbClr *attrValString `xml:"a:srgbClr"` } // aSchemeClr (Scheme Color) directly maps the a:schemeClr element. This @@ -206,9 +177,29 @@ type aR struct { // properties are defined as direct formatting, since they are directly applied // to the run and supersede any formatting from styles. type aRPr struct { - Lang string `xml:"lang,attr,omitempty"` - AltLang string `xml:"altLang,attr,omitempty"` - Sz int `xml:"sz,attr,omitempty"` + AltLang string `xml:"altLang,attr,omitempty"` + B bool `xml:"b,attr"` + Baseline int `xml:"baseline,attr"` + Bmk string `xml:"bmk,attr,omitempty"` + Cap string `xml:"cap,attr,omitempty"` + Dirty bool `xml:"dirty,attr,omitempty"` + Err bool `xml:"err,attr,omitempty"` + I bool `xml:"i,attr"` + Kern int `xml:"kern,attr"` + Kumimoji bool `xml:"kumimoji,attr,omitempty"` + Lang string `xml:"lang,attr,omitempty"` + NoProof bool `xml:"noProof,attr,omitempty"` + NormalizeH bool `xml:"normalizeH,attr,omitempty"` + SmtClean bool `xml:"smtClean,attr,omitempty"` + SmtID uint64 `xml:"smtId,attr,omitempty"` + Spc int `xml:"spc,attr"` + Strike string `xml:"strike,attr,omitempty"` + Sz int `xml:"sz,attr,omitempty"` + U string `xml:"u,attr,omitempty"` + SolidFill *aSolidFill `xml:"a:solidFill"` + Latin *aLatin `xml:"a:latin"` + Ea *aEa `xml:"a:ea"` + Cs *aCs `xml:"a:cs"` } // cSpPr (Shape Properties) directly maps the c:spPr element. This element @@ -579,14 +570,10 @@ type formatChart struct { // formatChartLegend directly maps the format settings of the chart legend. type formatChartLegend struct { - None bool `json:"none"` - DeleteSeries []int `json:"delete_series"` - Font struct { - Size int `json:"size"` - Blod bool `json:"blod"` - Italic bool `json:"italic"` - } `json:"font"` - Layout struct { + None bool `json:"none"` + DeleteSeries []int `json:"delete_series"` + Font formatFont `json:"font"` + Layout struct { X float64 `json:"x"` Y float64 `json:"y"` Width float64 `json:"width"` diff --git a/xmlDrawing.go b/xmlDrawing.go index 71b9cf9..966ca7b 100644 --- a/xmlDrawing.go +++ b/xmlDrawing.go @@ -349,6 +349,7 @@ type formatShape struct { Width int `json:"width"` Height int `json:"height"` Format formatPicture `json:"format"` + Font formatFont `json:"font"` Text string `json:"text"` Color formatShapeColor `json:"color"` } diff --git a/xmlStyles.go b/xmlStyles.go index aa0c9c8..4e7a7d1 100644 --- a/xmlStyles.go +++ b/xmlStyles.go @@ -282,6 +282,16 @@ type xlsxStyleColors struct { Color string `xml:",innerxml"` } +// formatFont directly maps the styles settings of the fonts. +type formatFont struct { + Bold bool `json:"bold"` + Italic bool `json:"italic"` + Underline string `json:"underline"` + Family string `json:"family"` + Size int `json:"size"` + Color string `json:"color"` +} + // formatCellStyle directly maps the styles settings of the borders. type formatCellStyle struct { Border []struct { @@ -295,14 +305,7 @@ type formatCellStyle struct { Color []string `json:"color"` Shading int `json:"shading"` } `json:"fill"` - Font *struct { - Bold bool `json:"bold"` - Italic bool `json:"italic"` - Underline string `json:"underline"` - Family string `json:"family"` - Size int `json:"size"` - Color string `json:"color"` - } `json:"font"` + Font *formatFont `json:"font"` Alignment *struct { Horizontal string `json:"horizontal"` Indent int `json:"indent"`