前言
PE版本有CSV/XLS数据导出功能,具体视频演示查看官方文档地址。
对此功能的描述如下:
ThingsBoard允许您将数据从小部件导出到CSV或XLS。几乎任何小部件都支持此功能。
导出数据集中的列列表与您在数据集配置中配置的参数列表相对应。
CE版本实现演示
注意:
调试前端代码 在ui-ngx目录下 打开命令行 执行yarn start 进行调试,更改后自动重新编译前端,不需要重复启动项目。
thingsboard版本 3.2.0
组件设置页面修改
添加「启用数据导出选项」
源码实现
主要修改下列文件(添加注释部分代码。官方源码部分有省略,减少篇幅)ui-ngx/src/app/modules/home/components/widget/widget-config.component.html
377行
<div fxLayout="column" fxLayoutAlign="center" fxLayoutGap="8px" fxFlex.sm="40%" fxFlex.gt-sm="30%"><mat-checkbox formControlName="enableFullscreen">{{ 'widget-config.enable-fullscreen' | translate }}</mat-checkbox><!--添加数据导出按钮↓↓↓--><mat-checkbox formControlName="enableDataExport">{{ 'widget-config.enable-data-export' | translate }}</mat-checkbox></div>
widget-config.component.ts
208行
this.widgetSettings = this.fb.group({dropShadow: [null, []],enableFullscreen: [null, []],//添加是否允许数据导出变量enableDataExport: [null, []],backgroundColor: [null, []],...});
379行
this.widgetSettings.patchValue({dropShadow: isDefined(config.dropShadow) ? config.dropShadow : true,enableFullscreen: isDefined(config.enableFullscreen) ? config.enableFullscreen : true,//是否允许数据导出 设置默认值enableDataExport: isDefined(config.enableDataExport) ? config.enableDataExport : true,backgroundColor: config.backgroundColor,...},
ui-ngx/src/app/shared/models/widget.models.ts
369行
export interface WidgetConfig {dropShadow?: boolean;enableFullscreen?: boolean;//添加是否允许数据导出变量enableDataExport?: boolean;useDashboardTimewindow?: boolean;...}
组件右上角导出数据按钮实现
源码实现
ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.html
123行 添加俩个注释中间部分
注意:
<mat-icon>{{'archive'}}</mat-icon>中的archive代表图标样式,其他mat-icon标签同理可替换图标 可以在https://www.materialpalette.com/icons中找到喜欢的进行替换。
<button mat-button mat-icon-button *ngFor="let action of widget.widgetActions"[fxShow]="!isEdit && action.show"(click)="action.onAction($event)"matTooltip="{{ action.name | translate }}"matTooltipPosition="above"><mat-icon>{{ action.icon }}</mat-icon></button><!--数据导出按钮实现 开始↓--><button mat-button mat-icon-button[matMenuTriggerFor]="menu"#menuTrigger="matMenuTrigger"[fxShow]="!isEdit && widget.enableDataExport"matTooltip="{{ 'widget.data-export' | translate }}"matTooltipPosition="above"><mat-icon>{{'archive'}}</mat-icon></button><mat-menu #menu="matMenu"><button mat-menu-item (click)="exportData($event, widgetComponent.widgetContext,'csv');menuTrigger.toggleMenu();"><mat-icon>insert_drive_file</mat-icon><span>{{ 'widget.data-export-csv' | translate }}</span></button><button mat-menu-item (click)="exportData($event, widgetComponent.widgetContext,'xls');menuTrigger.toggleMenu();"><mat-icon>insert_drive_file</mat-icon><span>{{ 'widget.data-export-xls' | translate }}</span></button><button mat-menu-item (click)="exportData($event, widgetComponent.widgetContext,'xlsx');menuTrigger.toggleMenu();"><mat-icon>insert_drive_file</mat-icon><span>{{ 'widget.data-export-xlsx' | translate }}</span></button></mat-menu><!--数据导出按钮实现 结束↑--><button mat-button mat-icon-button[fxShow]="!isEdit && widget.enableFullscreen"(click)="$event.stopPropagation(); widget.isFullscreen = !widget.isFullscreen"matTooltip="{{(widget.isFullscreen ? 'fullscreen.exit' : 'fullscreen.expand') | translate}}"matTooltipPosition="above"><mat-icon>{{ widget.isFullscreen ? 'fullscreen_exit' : 'fullscreen' }}</mat-icon></button>
ui-ngx/src/app/modules/home/models/dashboard-component.models.ts
添加注释部分代码
export class DashboardWidget implements GridsterItem, IDashboardWidget {dropShadow: boolean;enableFullscreen: boolean;//308行后 添加变量enableDataExport: boolean;hasTimewindow: boolean;}//379行后 添加默认值this.enableDataExport = isDefined(this.widget.config.enableDataExport) ? this.widget.config.enableDataExport : true;
ui-ngx/src/app/shared/models/ace/widget-completion.models.ts
217行
enableDataExport: {description: 'Whether to enable data export button on widget.',meta: 'property',type: 'boolean'},
ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.ts
添加方法
//文件开头导入依赖import { WidgetContext } from '@home/models/widget-component.models';exportData($event: Event, ctx: WidgetContext, fileType) {if ($event) {$event.stopPropagation();}const export_data = this.data_format(ctx.datasources, ctx.data);this.export(export_data, fileType, ctx.widgetConfig.title);}
console.log(fileType);可以看出点击的哪个文件类型的导出按钮console.log(ctx.datasources);可以看出实体enityName,实体类型enityType及数据点dataKeys
console.log(ctx.data);可以看到具体数据,格式是二维数据[[时间戳,值],[时间戳,值],[时间戳,值]],还有每条数据对应的数据键
this.data_format(datasource, data);是对数据做格式转换
转化后执行console.log(export_data);结果如下
最后执行this.export(export_data, fileType, ctx.widgetConfig.title);导出数据到浏览器下载。
文件名格式小部件标题-时间戳.文件后缀
translate相关
ui-ngx/src/assets/locale/locale.constant-zh_CN.json
添加widget中的内容
"widget": {"data-export": "导出数据","data-export-csv": "数据导出为CSV格式","data-export-xls": "数据导出为XLS格式","data-export-xlsx": "数据导出为XLSX格式",}
添加widget-config中的内容
"widget-config": {"enable-data-export": "启用数据导出",}
时间段选择
如果勾选了「使用仪表板的时间窗口」
则导出数据的时间段就是仪表板上的时间段内的数据
可以根据自己需求得时间段进行修改
如果没有勾选「使用仪表板的时间窗口」
那么组件上会有时间选择器
可以根据自己需求得时间段进行修改
优化
按照前面步骤做完,所有部件类型都加上了数据导出功能。实际上rpc,alarm,static是不需要的。

小部件有五种类型:timeseries,latest-values,rpc,alarm,static
但并不是每一种部件类型都需要数据导出功能。下面演示如何让rpc,static,alarm三类部件去掉数据导出功能。
rpc,static,alarm去掉图例中的启用数据导出选项
ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts
- 添加变量控制是否渲染启用数据导出选项
- writeValue方法给isEnableDataExport赋值 ```typescript //添加变量控制是否渲染启用数据导出选项 isEnableDataExport: boolean;
writeValue(value: WidgetConfigComponentData): void { this.modelValue = value; this.removeChangeSubscriptions(); if (this.modelValue) { if (this.widgetType !== this.modelValue.widgetType) { this.widgetType = this.modelValue.widgetType; this.buildForms(); //给isEnableDataExport赋值 this.isEnableDataExport = (!(this.widgetType === widgetType.static || this.widgetType === widgetType.rpc || this.widgetType === widgetType.alarm)); } …. } }
//384行 this.widgetSettings.patchValue中之前定义的默认值改为false //是否允许数据导出 设置默认值 enableDataExport: isDefined(config.enableDataExport) ? config.enableDataExport : false,
ui-ngx/src/app/modules/home/components/widget/widget-config.component.html1. 前面图例页面中添加的`启用数据导出`按钮上添加`*ngIf='isEnableDataExport'````html<!--添加数据导出按钮↓↓↓--><mat-checkbox *ngIf='isEnableDataExport' formControlName="enableDataExport">{{ 'widget-config.enable-data-export' | translate }}</mat-checkbox>
效果
导出功能手动打开,添加后默认 启用数据导出 选项是不勾选状态。rpc,alram,static类型部件不显示启用数据导出选项
alarm类型部件左上角没有了
rpc类型部件左上角没有了吧
而且部件设置中也没有了选项启用数据导出
测试
新建俩种实体
实体Timer A Timer B 有数据点 bili ali
实体Bus A Bus B 有数据点 long lat
规则链生成测试数据,红框内的节点复制后共8份。
每一个节点:1条数据/s,四个节点8份 = 32条数据/s。
测试导出10分钟数据:10分钟60秒32条 = 1.92w条


注意:测试节点生成数据无数量限制message-count = 0,但是根规则链的保存时序节点TTL设置600s(10分钟)有效期,防止测试数据无限多。
1.92w条近10分钟的数据瞬间导出,数据结构视频演示,包含不同实体的不同字段。
[](https://www.yuque.com/thingsboard/book/yoe8ys?_lake_card=%7B%22status%22%3A%22done%22%2C%22name%22%3A%22%E6%95%B0%E6%8D%AE%E6%BC%94%E7%A4%BA.mp4%22%2C%22size%22%3A1881041%2C%22taskId%22%3A%22Bzrdghg9ZnWb%22%2C%22taskType%22%3A%22%22%2C%22url%22%3Anull%2C%22cover%22%3Anull%2C%22videoId%22%3A%22inputs%2Fprod%2Fyuque%2F2021%2F1453676%2Fmp4%2F1619587751391-ff983a97-57b9-45a1-9c98-5ffc5c9a43e5.mp4%22%2C%22download%22%3Afalse%2C%22percent%22%3A100%2C%22__spacing%22%3A%22both%22%2C%22id%22%3A%228BmAu%22%2C%22margin%22%3A%7B%22top%22%3Atrue%2C%22bottom%22%3Atrue%7D%2C%22card%22%3A%22video%22%7D#8BmAu)到这里,毫无保留的数据及功能已经全部拿到,基本可以自己实现了,就差数据格式转换和导出浏览器下载,有动手能力的自己实现一下也是不错的。
不想掉头发的可以继续看下面的内容:
- 下面俩个方法的具体实现
const export_data = this.data_format(ctx.datasources, ctx.data);this.export(export_data, fileType, ctx.widgetConfig.title);
