summaryrefslogtreecommitdiff
path: root/shape.go
diff options
context:
space:
mode:
authorRi Xu <xuri.me@gmail.com>2017-04-30 20:03:43 +0800
committerRi Xu <xuri.me@gmail.com>2017-04-30 20:03:43 +0800
commit7f30a6c9430476bcd5fc1662523ada0e95f60947 (patch)
tree80d4341e95a80aedae3076c87b90447a881b32c8 /shape.go
parent46b8c46d91be522c3dff1044a23810ecb1a81c96 (diff)
- Initialize shape support: new function `AddShape()` added. Relate issue #38;
- Drawing `nvPicPr` element ID property calculation changed; - go test updated
Diffstat (limited to 'shape.go')
-rw-r--r--shape.go375
1 files changed, 375 insertions, 0 deletions
diff --git a/shape.go b/shape.go
new file mode 100644
index 0000000..5994c31
--- /dev/null
+++ b/shape.go
@@ -0,0 +1,375 @@
+package excelize
+
+import (
+ "encoding/json"
+ "encoding/xml"
+ "strconv"
+ "strings"
+)
+
+// parseFormatShapeSet provides function to parse the format settings of the
+// shape with default value.
+func parseFormatShapeSet(formatSet string) *formatShape {
+ format := formatShape{
+ Width: 160,
+ Height: 160,
+ Format: formatPicture{
+ FPrintsWithSheet: true,
+ FLocksWithSheet: false,
+ NoChangeAspect: false,
+ OffsetX: 0,
+ OffsetY: 0,
+ XScale: 1.0,
+ YScale: 1.0,
+ },
+ Text: " ",
+ }
+ json.Unmarshal([]byte(formatSet), &format)
+ return &format
+}
+
+// AddShape provides the method to add shape in a sheet by given worksheet
+// index, shape format set (such as offset, scale, aspect ratio setting and
+// 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}`)
+//
+// The following shows the type of chart supported by excelize:
+//
+// accentBorderCallout1 (Callout 1 with Border and Accent Shape)
+// accentBorderCallout2 (Callout 2 with Border and Accent Shape)
+// accentBorderCallout3 (Callout 3 with Border and Accent Shape)
+// accentCallout1 (Callout 1 Shape)
+// accentCallout2 (Callout 2 Shape)
+// accentCallout3 (Callout 3 Shape)
+// actionButtonBackPrevious (Back or Previous Button Shape)
+// actionButtonBeginning (Beginning Button Shape)
+// actionButtonBlank (Blank Button Shape)
+// actionButtonDocument (Document Button Shape)
+// actionButtonEnd (End Button Shape)
+// actionButtonForwardNext (Forward or Next Button Shape)
+// actionButtonHelp (Help Button Shape)
+// actionButtonHome (Home Button Shape)
+// actionButtonInformation (Information Button Shape)
+// actionButtonMovie (Movie Button Shape)
+// actionButtonReturn (Return Button Shape)
+// actionButtonSound (Sound Button Shape)
+// arc (Curved Arc Shape)
+// bentArrow (Bent Arrow Shape)
+// bentConnector2 (Bent Connector 2 Shape)
+// bentConnector3 (Bent Connector 3 Shape)
+// bentConnector4 (Bent Connector 4 Shape)
+// bentConnector5 (Bent Connector 5 Shape)
+// bentUpArrow (Bent Up Arrow Shape)
+// bevel (Bevel Shape)
+// blockArc (Block Arc Shape)
+// borderCallout1 (Callout 1 with Border Shape)
+// borderCallout2 (Callout 2 with Border Shape)
+// borderCallout3 (Callout 3 with Border Shape)
+// bracePair (Brace Pair Shape)
+// bracketPair (Bracket Pair Shape)
+// callout1 (Callout 1 Shape)
+// callout2 (Callout 2 Shape)
+// callout3 (Callout 3 Shape)
+// can (Can Shape)
+// chartPlus (Chart Plus Shape)
+// chartStar (Chart Star Shape)
+// chartX (Chart X Shape)
+// chevron (Chevron Shape)
+// chord (Chord Shape)
+// circularArrow (Circular Arrow Shape)
+// cloud (Cloud Shape)
+// cloudCallout (Callout Cloud Shape)
+// corner (Corner Shape)
+// cornerTabs (Corner Tabs Shape)
+// cube (Cube Shape)
+// curvedConnector2 (Curved Connector 2 Shape)
+// curvedConnector3 (Curved Connector 3 Shape)
+// curvedConnector4 (Curved Connector 4 Shape)
+// curvedConnector5 (Curved Connector 5 Shape)
+// curvedDownArrow (Curved Down Arrow Shape)
+// curvedLeftArrow (Curved Left Arrow Shape)
+// curvedRightArrow (Curved Right Arrow Shape)
+// curvedUpArrow (Curved Up Arrow Shape)
+// decagon (Decagon Shape)
+// diagStripe (Diagonal Stripe Shape)
+// diamond (Diamond Shape)
+// dodecagon (Dodecagon Shape)
+// donut (Donut Shape)
+// doubleWave (Double Wave Shape)
+// downArrow (Down Arrow Shape)
+// downArrowCallout (Callout Down Arrow Shape)
+// ellipse (Ellipse Shape)
+// ellipseRibbon (Ellipse Ribbon Shape)
+// ellipseRibbon2 (Ellipse Ribbon 2 Shape)
+// flowChartAlternateProcess (Alternate Process Flow Shape)
+// flowChartCollate (Collate Flow Shape)
+// flowChartConnector (Connector Flow Shape)
+// flowChartDecision (Decision Flow Shape)
+// flowChartDelay (Delay Flow Shape)
+// flowChartDisplay (Display Flow Shape)
+// flowChartDocument (Document Flow Shape)
+// flowChartExtract (Extract Flow Shape)
+// flowChartInputOutput (Input Output Flow Shape)
+// flowChartInternalStorage (Internal Storage Flow Shape)
+// flowChartMagneticDisk (Magnetic Disk Flow Shape)
+// flowChartMagneticDrum (Magnetic Drum Flow Shape)
+// flowChartMagneticTape (Magnetic Tape Flow Shape)
+// flowChartManualInput (Manual Input Flow Shape)
+// flowChartManualOperation (Manual Operation Flow Shape)
+// flowChartMerge (Merge Flow Shape)
+// flowChartMultidocument (Multi-Document Flow Shape)
+// flowChartOfflineStorage (Offline Storage Flow Shape)
+// flowChartOffpageConnector (Off-Page Connector Flow Shape)
+// flowChartOnlineStorage (Online Storage Flow Shape)
+// flowChartOr (Or Flow Shape)
+// flowChartPredefinedProcess (Predefined Process Flow Shape)
+// flowChartPreparation (Preparation Flow Shape)
+// flowChartProcess (Process Flow Shape)
+// flowChartPunchedCard (Punched Card Flow Shape)
+// flowChartPunchedTape (Punched Tape Flow Shape)
+// flowChartSort (Sort Flow Shape)
+// flowChartSummingJunction (Summing Junction Flow Shape)
+// flowChartTerminator (Terminator Flow Shape)
+// foldedCorner (Folded Corner Shape)
+// frame (Frame Shape)
+// funnel (Funnel Shape)
+// gear6 (Gear 6 Shape)
+// gear9 (Gear 9 Shape)
+// halfFrame (Half Frame Shape)
+// heart (Heart Shape)
+// heptagon (Heptagon Shape)
+// hexagon (Hexagon Shape)
+// homePlate (Home Plate Shape)
+// horizontalScroll (Horizontal Scroll Shape)
+// irregularSeal1 (Irregular Seal 1 Shape)
+// irregularSeal2 (Irregular Seal 2 Shape)
+// leftArrow (Left Arrow Shape)
+// leftArrowCallout (Callout Left Arrow Shape)
+// leftBrace (Left Brace Shape)
+// leftBracket (Left Bracket Shape)
+// leftCircularArrow (Left Circular Arrow Shape)
+// leftRightArrow (Left Right Arrow Shape)
+// leftRightArrowCallout (Callout Left Right Arrow Shape)
+// leftRightCircularArrow (Left Right Circular Arrow Shape)
+// leftRightRibbon (Left Right Ribbon Shape)
+// leftRightUpArrow (Left Right Up Arrow Shape)
+// leftUpArrow (Left Up Arrow Shape)
+// lightningBolt (Lightning Bolt Shape)
+// line (Line Shape)
+// lineInv (Line Inverse Shape)
+// mathDivide (Divide Math Shape)
+// mathEqual (Equal Math Shape)
+// mathMinus (Minus Math Shape)
+// mathMultiply (Multiply Math Shape)
+// mathNotEqual (Not Equal Math Shape)
+// mathPlus (Plus Math Shape)
+// moon (Moon Shape)
+// nonIsoscelesTrapezoid (Non-Isosceles Trapezoid Shape)
+// noSmoking (No Smoking Shape)
+// notchedRightArrow (Notched Right Arrow Shape)
+// octagon (Octagon Shape)
+// parallelogram (Parallelogram Shape)
+// pentagon (Pentagon Shape)
+// pie (Pie Shape)
+// pieWedge (Pie Wedge Shape)
+// plaque (Plaque Shape)
+// plaqueTabs (Plaque Tabs Shape)
+// plus (Plus Shape)
+// quadArrow (Quad-Arrow Shape)
+// quadArrowCallout (Callout Quad-Arrow Shape)
+// rect (Rectangle Shape)
+// ribbon (Ribbon Shape)
+// ribbon2 (Ribbon 2 Shape)
+// rightArrow (Right Arrow Shape)
+// rightArrowCallout (Callout Right Arrow Shape)
+// rightBrace (Right Brace Shape)
+// rightBracket (Right Bracket Shape)
+// round1Rect (One Round Corner Rectangle Shape)
+// round2DiagRect (Two Diagonal Round Corner Rectangle Shape)
+// round2SameRect (Two Same-side Round Corner Rectangle Shape)
+// roundRect (Round Corner Rectangle Shape)
+// rtTriangle (Right Triangle Shape)
+// smileyFace (Smiley Face Shape)
+// snip1Rect (One Snip Corner Rectangle Shape)
+// snip2DiagRect (Two Diagonal Snip Corner Rectangle Shape)
+// snip2SameRect (Two Same-side Snip Corner Rectangle Shape)
+// snipRoundRect (One Snip One Round Corner Rectangle Shape)
+// squareTabs (Square Tabs Shape)
+// star10 (Ten Pointed Star Shape)
+// star12 (Twelve Pointed Star Shape)
+// star16 (Sixteen Pointed Star Shape)
+// star24 (Twenty Four Pointed Star Shape)
+// star32 (Thirty Two Pointed Star Shape)
+// star4 (Four Pointed Star Shape)
+// star5 (Five Pointed Star Shape)
+// star6 (Six Pointed Star Shape)
+// star7 (Seven Pointed Star Shape)
+// star8 (Eight Pointed Star Shape)
+// straightConnector1 (Straight Connector 1 Shape)
+// stripedRightArrow (Striped Right Arrow Shape)
+// sun (Sun Shape)
+// swooshArrow (Swoosh Arrow Shape)
+// teardrop (Teardrop Shape)
+// trapezoid (Trapezoid Shape)
+// triangle (Triangle Shape)
+// upArrow (Up Arrow Shape)
+// upArrowCallout (Callout Up Arrow Shape)
+// upDownArrow (Up Down Arrow Shape)
+// upDownArrowCallout (Callout Up Down Arrow Shape)
+// uturnArrow (U-Turn Arrow Shape)
+// verticalScroll (Vertical Scroll Shape)
+// wave (Wave Shape)
+// wedgeEllipseCallout (Callout Wedge Ellipse Shape)
+// wedgeRectCallout (Callout Wedge Rectangle Shape)
+// wedgeRoundRectCallout (Callout Wedge Round Rectangle Shape)
+//
+func (f *File) AddShape(sheet, cell, format string) {
+ formatSet := parseFormatShapeSet(format)
+ // Read sheet data.
+ xlsx := f.workSheetReader(sheet)
+ // Add first shape for given sheet, create xl/drawings/ and xl/drawings/_rels/ folder.
+ drawingID := f.countDrawings() + 1
+ drawingXML := "xl/drawings/drawing" + strconv.Itoa(drawingID) + ".xml"
+ sheetRelationshipsDrawingXML := "../drawings/drawing" + strconv.Itoa(drawingID) + ".xml"
+
+ if xlsx.Drawing != nil {
+ // The worksheet already has a shape or chart relationships, use the relationships drawing ../drawings/drawing%d.xml.
+ sheetRelationshipsDrawingXML = f.getSheetRelationshipsTargetByID(sheet, xlsx.Drawing.RID)
+ drawingID, _ = strconv.Atoi(strings.TrimSuffix(strings.TrimPrefix(sheetRelationshipsDrawingXML, "../drawings/drawing"), ".xml"))
+ drawingXML = strings.Replace(sheetRelationshipsDrawingXML, "..", "xl", -1)
+ } else {
+ // Add first shape for given sheet.
+ rID := f.addSheetRelationships(sheet, SourceRelationshipDrawingML, sheetRelationshipsDrawingXML, "")
+ f.addSheetDrawing(sheet, rID)
+ }
+ f.addDrawingShape(sheet, drawingXML, cell, formatSet)
+ f.addDrawingContentTypePart(drawingID)
+}
+
+// addDrawingShape
+func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *formatShape) {
+ cell = strings.ToUpper(cell)
+ fromCol := string(strings.Map(letterOnlyMapF, cell))
+ fromRow, _ := strconv.Atoi(strings.Map(intOnlyMapF, cell))
+ row := fromRow - 1
+ col := titleToNumber(fromCol)
+ width := int(float64(formatSet.Width) * formatSet.Format.XScale)
+ height := int(float64(formatSet.Height) * formatSet.Format.YScale)
+ colStart, rowStart, _, _, colEnd, rowEnd, x2, y2 := f.positionObjectPixels(sheet, col, row, formatSet.Format.OffsetX, formatSet.Format.OffsetY, width, height)
+ content := xlsxWsDr{}
+ content.A = NameSpaceDrawingML
+ content.Xdr = NameSpaceDrawingMLSpreadSheet
+ cNvPrID := 1
+ _, ok := f.XLSX[drawingXML]
+ if ok { // Append Model
+ decodeWsDr := decodeWsDr{}
+ xml.Unmarshal([]byte(f.readXML(drawingXML)), &decodeWsDr)
+ cNvPrID = len(decodeWsDr.OneCellAnchor) + len(decodeWsDr.TwoCellAnchor) + 1
+ for _, v := range decodeWsDr.OneCellAnchor {
+ content.OneCellAnchor = append(content.OneCellAnchor, &xdrCellAnchor{
+ EditAs: v.EditAs,
+ GraphicFrame: v.Content,
+ })
+ }
+ for _, v := range decodeWsDr.TwoCellAnchor {
+ content.TwoCellAnchor = append(content.TwoCellAnchor, &xdrCellAnchor{
+ EditAs: v.EditAs,
+ GraphicFrame: v.Content,
+ })
+ }
+ }
+ twoCellAnchor := xdrCellAnchor{}
+ twoCellAnchor.EditAs = "oneCell"
+ from := xlsxFrom{}
+ from.Col = colStart
+ from.ColOff = formatSet.Format.OffsetX * EMU
+ from.Row = rowStart
+ from.RowOff = formatSet.Format.OffsetY * EMU
+ to := xlsxTo{}
+ to.Col = colEnd
+ to.ColOff = x2 * EMU
+ to.Row = rowEnd
+ to.RowOff = y2 * EMU
+ twoCellAnchor.From = &from
+ twoCellAnchor.To = &to
+ shape := xdrSp{
+ NvSpPr: &xdrNvSpPr{
+ CNvPr: &xlsxCNvPr{
+ ID: cNvPrID,
+ Name: "Shape " + strconv.Itoa(cNvPrID),
+ },
+ CNvSpPr: &xdrCNvSpPr{
+ TxBox: true,
+ },
+ },
+ SpPr: &xlsxSpPr{
+ PrstGeom: xlsxPrstGeom{
+ Prst: formatSet.Type,
+ },
+ },
+ Style: &xdrStyle{
+ LnRef: setShapeRef(formatSet.Color.Line, 2),
+ FillRef: setShapeRef(formatSet.Color.Fill, 1),
+ EffectRef: setShapeRef(formatSet.Color.Effect, 0),
+ FontRef: &aFontRef{
+ Idx: "minor",
+ SchemeClr: &attrValString{
+ Val: "tx1",
+ },
+ },
+ },
+ TxBody: &xdrTxBody{
+ BodyPr: &aBodyPr{
+ VertOverflow: "clip",
+ HorzOverflow: "clip",
+ Wrap: "none",
+ RtlCol: false,
+ Anchor: "t",
+ },
+ P: &aP{
+ R: &aR{
+ RPr: aRPr{
+ Lang: "en-US",
+ AltLang: "en-US",
+ Sz: 1100,
+ },
+ T: formatSet.Text,
+ },
+ EndParaRPr: &aEndParaRPr{
+ Lang: "en-US",
+ },
+ },
+ },
+ }
+ twoCellAnchor.Sp = &shape
+ twoCellAnchor.ClientData = &xdrClientData{
+ FLocksWithSheet: formatSet.Format.FLocksWithSheet,
+ FPrintsWithSheet: formatSet.Format.FPrintsWithSheet,
+ }
+ content.TwoCellAnchor = append(content.TwoCellAnchor, &twoCellAnchor)
+ output, _ := xml.Marshal(content)
+ f.saveFileList(drawingXML, string(output))
+}
+
+// setShapeRef provides function to set color with hex model by given actual
+// color value.
+func setShapeRef(color string, i int) *aRef {
+ if color == "" {
+ return &aRef{
+ Idx: 0,
+ ScrgbClr: &aScrgbClr{
+ R: 0,
+ G: 0,
+ B: 0,
+ },
+ }
+ }
+ return &aRef{
+ Idx: i,
+ SrgbClr: &attrValString{
+ Val: strings.Replace(strings.ToUpper(color), "#", "", -1),
+ },
+ }
+}