Shape Text

SpreadJS allows you to add text in shapes. By using textEffect, and textFrame you will have the possibility to format the added text to your liking.

You can customize the properties of autoShapes using the Shape API: text: Gets or sets the text of the shape. You can use the textDirection property of the textFrame in the Style: this property is used to get or set the text direction of the shape. The TextDirection enum defines the direction of the text in the shape.
import { Component, NgModule, enableProdMode } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { BrowserModule } from '@angular/platform-browser'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { SpreadSheetsModule } from '@mescius/spread-sheets-angular'; import GC from '@mescius/spread-sheets'; import "@mescius/spread-sheets-shapes" import './styles.css'; function getEnumList(enumObject: object) { let names = []; for (var name in enumObject) { if (name === "none" || (parseInt(<any>name, 10)) == <any>name) { continue; } names.push({ name: name, value: enumObject[name] }); } names.sort(function(a, b) { return a.name > b.name ? 1 : -1 }); return names; } const horizontalAlign = { left: 0, center: 1, right: 2 }; const verticalAlign = { top: 0, center: 1, bottom: 2 }; const resizeToFitTextOptions = { false: 0, true: 1 } @Component({ selector: 'app-component', templateUrl: 'src/app.component.html' }) export class AppComponent { spread: GC.Spread.Sheets.Workbook; hostStyle = { width: 'calc(100% - 280px)', height: '100%', overflow: 'hidden', float: 'left' }; showShapeTxtPanel = false; text = `abcdefgHIJKLMN 12356789 SpreadJSSpreadJS`; textColor = "#FFFF00"; transparencyTxt = 0.5; font = "bold 15px Georgia"; hAlign = 1; vAlign = 1; resizeToFitText = 0; textDirection = GC.Spread.Sheets.Shapes.TextDirection.horz; textDirectionList = [ {text: 'Horizontal', value: GC.Spread.Sheets.Shapes.TextDirection.horz }, {text: 'Vertical(Ltr)', value: GC.Spread.Sheets.Shapes.TextDirection.eaVertLtr}, {text: 'Vertical', value: GC.Spread.Sheets.Shapes.TextDirection.eaVert}, {text: 'Rotate all text 90°', value: GC.Spread.Sheets.Shapes.TextDirection.vert}, {text: 'Rotate all text 270°', value: GC.Spread.Sheets.Shapes.TextDirection.vert270}, {text: 'Stacked', value: GC.Spread.Sheets.Shapes.TextDirection.wordArtVert}, {text: 'Stacked(Rtl)', value: GC.Spread.Sheets.Shapes.TextDirection.wordArtVertRtl} ]; horizontalAlignList = getEnumList(horizontalAlign); verticalAlignList = getEnumList(verticalAlign); resizeToFitTextList = getEnumList(resizeToFitTextOptions); initSpread($event: any) { let spread = this.spread = $event.spread; spread.getActiveSheet().shapes.add("rectangle", GC.Spread.Sheets.Shapes.AutoShapeType.rectangle, 40, 20, 150, 150); spread.getActiveSheet().shapes.add("rightTriangle", GC.Spread.Sheets.Shapes.AutoShapeType.rightTriangle, 40, 230, 150, 150); spread.getActiveSheet().shapes.add("hexagon", GC.Spread.Sheets.Shapes.AutoShapeType.hexagon, 250, 20, 150, 150); spread.getActiveSheet().shapes.add("oval", GC.Spread.Sheets.Shapes.AutoShapeType.oval, 250, 230, 150, 150); this.bindSpreadEvent(); } bindSpreadEvent() { let spread = this.spread, self = this; spread.bind(GC.Spread.Sheets.Events.ShapeSelectionChanged, function() { let sheet = spread.getActiveSheet(); var selectedShape = sheet.shapes.all().filter(function(sp: GC.Spread.Sheets.Shapes.ShapeBase) { return sp.isSelected(); }); var isShapeSelected = false, isConnectorSelected = false; if (selectedShape.length > 0) { selectedShape.forEach((shape: GC.Spread.Sheets.Shapes.ShapeBase) => { if (!isShapeSelected && shape instanceof GC.Spread.Sheets.Shapes.Shape) { isShapeSelected = true; } else if (!isConnectorSelected && shape instanceof GC.Spread.Sheets.Shapes.ConnectorShape) { isConnectorSelected = true; } }); self.setShapePropVisibility(isShapeSelected); } else { self.setShapePropVisibility(false); } }) } setShapePropVisibility(isShow: boolean) { this.showShapeTxtPanel = isShow; } updateShapeStyle(action: string, value: any) { let sheet = this.spread.getActiveSheet(); let activeShape = sheet.shapes.all().filter(function(sp: GC.Spread.Sheets.Shapes.ShapeBase) { return sp.isSelected(); }); if (activeShape.length > 0) { activeShape.forEach((shape: GC.Spread.Sheets.Shapes.ShapeBase) => { if (shape instanceof GC.Spread.Sheets.Shapes.Shape) { this._setShapeStyle(shape, action, value); } }); sheet.repaint(); } } _setShapeStyle(shape: GC.Spread.Sheets.Shapes.ShapeBase, action: string, value: any) { if (action === 'text') { shape.text(value); } else { var shapeStyle = shape.style(); if (action === 'color') { shapeStyle.textEffect.color = value; } else if (action === 'transparencyTxt') { shapeStyle.textEffect.transparency = value; } else if (action === 'font') { shapeStyle.textEffect.font = value; } else if(action === 'textDirection') { const textDirection = parseInt(value); shapeStyle.textFrame.textDirection = textDirection; switch (textDirection) { case GC.Spread.Sheets.Shapes.TextDirection.vert: case GC.Spread.Sheets.Shapes.TextDirection.wordArtVertRtl: case GC.Spread.Sheets.Shapes.TextDirection.eaVert: shapeStyle.textFrame.hAlign = GC.Spread.Sheets.HorizontalAlign.right; break; case GC.Spread.Sheets.Shapes.TextDirection.vert270: case GC.Spread.Sheets.Shapes.TextDirection.wordArtVert: case GC.Spread.Sheets.Shapes.TextDirection.eaVertLtr: shapeStyle.textFrame.hAlign = GC.Spread.Sheets.HorizontalAlign.left; break; } } else if (action === 'hAlign') { shapeStyle.textFrame.hAlign = parseInt(value); } else if (action === 'vAlign') { shapeStyle.textFrame.vAlign = parseInt(value); } else if (action === 'resizeToFitText') { shapeStyle.textFrame.resizeToFitText = value === '1'; } shape.style(shapeStyle); } } } @NgModule({ imports: [BrowserModule, SpreadSheetsModule, FormsModule], declarations: [AppComponent], exports: [AppComponent], bootstrap: [AppComponent] }) export class AppModule { } enableProdMode(); platformBrowserDynamic().bootstrapModule(AppModule);
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/angular/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <!-- Polyfills --> <script src="$DEMOROOT$/en/angular/node_modules/core-js/client/shim.min.js"></script> <script src="$DEMOROOT$/en/angular/node_modules/zone.js/fesm2015/zone.min.js"></script> <!-- SystemJS --> <script src="$DEMOROOT$/en/angular/node_modules/systemjs/dist/system.js"></script> <script src="systemjs.config.js"></script> <script> // workaround to load 'rxjs/operators' from the rxjs bundle System.import('rxjs').then(function (m) { System.import('@angular/compiler'); System.set(SystemJS.resolveSync('rxjs/operators'), System.newModule(m.operators)); System.import('$DEMOROOT$/en/lib/angular/license.ts'); System.import('./src/app.component'); }); </script> </head> <body> <app-component></app-component> </body> </html>
<div class="sample-tutorial"> <gc-spread-sheets [hostStyle]="hostStyle" (workbookInitialized)="initSpread($event)"> </gc-spread-sheets> <div class="options-container"> <div class="option-row"> Try selecting a shape and change the text properties to see the outcome: </div> <div id="divideLine" class="divide-line"></div> <div *ngIf="showShapeTxtPanel" class="option-row"> <label>Text: </label> <textarea [(ngModel)]="text" type="text" placeholder="Shape text" rows="3"></textarea> <input type="button" (click)="updateShapeStyle('text', text)" value="Set" /> <label>Text Direction:</label> <select [(ngModel)]="textDirection"> <option *ngFor="let item of textDirectionList" [value]="item.value|number"> {{item.text}} </option> </select> <input type="button" (click)="updateShapeStyle('textDirection', textDirection)" value="Set" /> <label>Text Color: </label> <input [(ngModel)]="textColor" type="color" value="#FFFF00" /> <input type="button" (click)="updateShapeStyle('color', textColor)" value="Set" /> <label>Text Transparency: </label> <input [(ngModel)]="transparencyTxt" [value]="transparencyTxt|number" type="text" value="0.5" /> <input type="button" (click)="updateShapeStyle('transparencyTxt', transparencyTxt)" value="Set" /> <label>Text Font: </label> <input [(ngModel)]="font" type="text" /> <input type="button" (click)="updateShapeStyle('font', font)" value="Set" /> <label> Horizontal Align:</label> <select [(ngModel)]="hAlign"> <option *ngFor="let item of horizontalAlignList" [value]="item.value|number"> {{item.name}} </option> </select> <input type="button" (click)="updateShapeStyle('hAlign', hAlign)" value="Set" /> <label>Vertical Align:</label> <select [(ngModel)]="vAlign"> <option *ngFor="let item of verticalAlignList" [value]="item.value|number"> {{item.name}} </option> </select> <input type="button" (click)="updateShapeStyle('vAlign', vAlign)" value="Set" /> <label>Resize To Fit Text:</label> <select [(ngModel)]="resizeToFitText"> <option *ngFor="let item of resizeToFitTextList" [value]="item.value|number"> {{item.name}} </option> </select> <input type="button" (click)="updateShapeStyle('resizeToFitText', resizeToFitText)" value="Set" /> </div> </div> </div>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } .sample-spreadsheets { width: calc(100% - 280px); height: 100%; overflow: hidden; float: left; } .options-container { float: right; width: 280px; padding: 12px; height: 100%; box-sizing: border-box; background: #fbfbfb; overflow: auto; } .option-row { font-size: 14px; padding-left: 5px; } .divide-line { width: 100%; height: 1px; background: #cbcbcb; margin-top: 10px; margin-bottom: 3px; } .title { text-align: center; font-weight: bold; } label { display: block; margin-top: 15px; margin-bottom: 5px; } p { padding: 2px 10px; background-color: #F4F8EB; } input { width: 160px; margin-left: 10px; display: inline; } input[type=button] { width: 50px; margin-left: 1px; } select { width: 160px; margin-left: 10px; display: inline; } textarea { width: 160px; margin-left: 10px; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }
(function (global) { System.config({ transpiler: 'ts', typescriptOptions: { tsconfig: true }, meta: { 'typescript': { "exports": "ts" }, '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { 'core-js': 'npm:core-js/client/shim.min.js', 'zone': 'npm:zone.js/fesm2015/zone.min.js', 'rxjs': 'npm:rxjs/dist/bundles/rxjs.umd.min.js', '@angular/core': 'npm:@angular/core/fesm2022', '@angular/common': 'npm:@angular/common/fesm2022/common.mjs', '@angular/compiler': 'npm:@angular/compiler/fesm2022/compiler.mjs', '@angular/platform-browser': 'npm:@angular/platform-browser/fesm2022/platform-browser.mjs', '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/fesm2022/platform-browser-dynamic.mjs', '@angular/common/http': 'npm:@angular/common/fesm2022/http.mjs', '@angular/router': 'npm:@angular/router/fesm2022/router.mjs', '@angular/forms': 'npm:@angular/forms/fesm2022/forms.mjs', 'jszip': 'npm:jszip/dist/jszip.min.js', 'typescript': 'npm:typescript/lib/typescript.js', 'ts': './plugin.js', 'tslib':'npm:tslib/tslib.js', 'css': 'npm:systemjs-plugin-css/css.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', 'systemjs-babel-build':'npm:systemjs-plugin-babel/systemjs-babel-browser.js', '@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js', '@mescius/spread-sheets-shapes': 'npm:@mescius/spread-sheets-shapes/index.js', '@mescius/spread-sheets-angular': 'npm:@mescius/spread-sheets-angular/fesm2020/mescius-spread-sheets-angular.mjs', '@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js' }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'ts' }, rxjs: { defaultExtension: 'js' }, "node_modules": { defaultExtension: 'js' }, "node_modules/@angular": { defaultExtension: 'mjs' }, "@mescius/spread-sheets-angular": { defaultExtension: 'mjs' }, '@angular/core': { defaultExtension: 'mjs', main: 'core.mjs' } } }); })(this);