Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import { Component, OnDestroy, Input, EventEmitter, forwardRef } from '@angular/core';
- import { NG_VALUE_ACCESSOR, NG_VALIDATORS, ControlValueAccessor, Validator, AbstractControl } from '@angular/forms';
- declare var $: any;
- import '../../../../node_modules/jexcel/dist/js/jexcel';
- import '../../../../node_modules/jexcel/dist/js/jquery.jexcel';
- import '../../../../node_modules/jexcel/dist/js/jquery.jcalendar';
- import '../../../../node_modules/jexcel/dist/js/jquery.jdropdown';
- import '../../../../node_modules/jexcel/dist/js/jexcel-formulas';
- import '../../../../node_modules/jexcel/dist/js/jquery.csv.min';
- import { DateFormatPipe } from '../pipe/date-format.pipe';
- import { JExcelColumn, JExcelError, JExcel, JExcelOptions, JExcelColumnRule } from './jexcel';
- import { ObjectHelper } from '../helper/object-helper';
- import { TranslateService } from '@ngx-translate/core';
- import * as lodash from 'lodash';
- import * as excelColumnName from 'excel-column-name';
- export const JEXCEL_CONTROL_VALUE_ACCESSOR: any = {
- provide: NG_VALUE_ACCESSOR,
- useExisting: forwardRef(() => JExcelComponent),
- multi: true
- };
- export const JEXCEL_INPUT_VALIDATORS_ACCESSOR: any = {
- provide: NG_VALIDATORS,
- useExisting: forwardRef(() => JExcelComponent),
- multi: true,
- };
- @Component({
- selector: 'app-jexcel',
- templateUrl: './jexcel.component.html',
- providers: [
- JEXCEL_CONTROL_VALUE_ACCESSOR,
- JEXCEL_INPUT_VALIDATORS_ACCESSOR
- ]
- })
- export class JExcelComponent implements ControlValueAccessor, Validator, OnDestroy {
- @Input()
- public get id(): string { return this._id; }
- public set id(id: string) { this.setID(id); }
- private _id: string;
- @Input()
- public get name(): string { return this._name; }
- public set name(name: string) { this._name = name; }
- private _name: string;
- @Input()
- public get options(): JExcelOptions { return this._options; }
- public set options(options: JExcelOptions) {
- this._options = options;
- this.setSpreadsheet();
- }
- public _options: JExcelOptions;
- public value: any[] = [];
- public onchange: EventEmitter<any[]>;
- public translate: boolean = true;
- protected valid: boolean;
- protected errors: any[];
- protected globalErrors: JExcelError[] = [];
- private configuration: JExcel;
- private dateFormatPipe: DateFormatPipe;
- private defaultColumnWidth: number = 100;
- private defaultCellBackground: string = 'background-color:white';
- private defaultCellBackgroundError: string = 'background-color:lightcoral';
- private defaultColumnType: any = { type: 'text' };
- private onchangeEvent: Function;
- private yearMonthPattern: string = '(0[1-9]|10|11|12)/20[0-9]{2}$';
- constructor(
- private translateService: TranslateService
- ) {
- this.dateFormatPipe = new DateFormatPipe();
- this.globalErrors = [];
- this.errors = [];
- this.onchange = new EventEmitter();
- this.onchangeEvent = (obj, cell, val) => {
- const value = this.getValues();
- this.propagateChange(value);
- this.onchange.emit(value);
- };
- this.setID('app-jexcel');
- }
- ngOnDestroy() {
- this.getInstance().jexcel('destroy');
- }
- private setID(id: string) {
- this._id = id;
- this.getInstance().jexcel();
- }
- public propagateChange = (_: any) => { /* do nothing */ };
- public propagateTouch = (_: any) => { /* do nothing */ };
- public writeValue(value: any): void {
- this.getInstance().jexcel('destroy');
- this.value = value;
- if (this.configuration && this.value) {
- this.initData();
- this.getInstance().jexcel('setData', this.configuration.data, false);
- }
- }
- public registerOnChange(fn: (_: any) => {}): void {
- this.propagateChange = fn;
- }
- public registerOnTouched(fn: (_: any) => {}): void {
- this.propagateTouch = fn;
- }
- public setDisabledState(isDisabled: boolean): void { }
- public setSpreadsheet() {
- this.globalErrors = [];
- if (this.options) {
- this.initConfiguration();
- this.getInstance().jexcel(this.configuration);
- }
- }
- private getInstance() {
- return $('#' + this.id);
- }
- private initConfiguration() {
- if (!this.configuration) {
- this.configuration = {};
- }
- this.configuration.colAlignments = [];
- this.configuration.colHeaders = [];
- this.configuration.colWidths = [];
- this.configuration.columns = [];
- let index = 0;
- for (const column of this.options.columns) {
- if (ObjectHelper.isEmpty(column)) {
- this.globalErrors.push({ code: 'jexcel.column.required', args: [(index + 1)] });
- console.error('JExcel errors : ', this.globalErrors);
- break;
- }
- // Header text
- if (ObjectHelper.isEmpty(column.headerText)) {
- // TODO : set content alert LOL!
- this.globalErrors.push({ code: 'jexcel.header.required', args: [(index + 1)] });
- console.error('JExcel errors : ', this.globalErrors);
- break;
- } else {
- if (this.translate) {
- this.translateService.get(column.headerText).subscribe(
- (translated) => {
- this.configuration.colHeaders.push(translated);
- }
- );
- } else {
- this.configuration.colHeaders.push(column.headerText);
- }
- }
- // Width
- if (ObjectHelper.isEmpty(column.width)) {
- this.configuration.colWidths.push(this.defaultColumnWidth);
- } else {
- this.configuration.colWidths.push(column.width);
- }
- // Alignment
- if (ObjectHelper.isEmpty(column.alignment)) {
- this.configuration.colAlignments.push('left');
- } else {
- this.configuration.colAlignments.push(column.alignment);
- }
- // Column
- const validColumn = lodash.cloneDeep(column);
- if (ObjectHelper.isEmpty(validColumn.type)) {
- validColumn.type = this.defaultColumnType;
- }
- if (ObjectHelper.isEmpty(validColumn.readOnly)) {
- validColumn.readOnly = false;
- }
- if (validColumn.type === 'dropdown' || validColumn.type === 'autocomplete') {
- validColumn.source.map(item => {
- if (typeof item === 'object') {
- const name = validColumn.sourceKey ? validColumn.sourceKey : (Object.keys(item).find(key => key.indexOf('name') > -1 || key.indexOf('nama') > -1));
- item.oid = item.id;
- item.id = item[name];
- }
- });
- }
- if (validColumn.type === 'yearmonth') {
- validColumn.type = 'text';
- validColumn.isYearMonth = true;
- }
- this.configuration.columns.push(validColumn);
- // Data
- this.initData();
- index++;
- }
- // Options
- this.initOptions();
- }
- private initOptions() {
- this.configuration.editable = this.options.editable;
- this.configuration.columnResize = this.options.columnResize;
- this.configuration.allowInsertRow = this.options.allowInsertRow;
- this.configuration.allowManualInsertRow = this.options.allowManualInsertRow;
- this.configuration.allowInsertColumn = this.options.allowInsertColumn;
- this.configuration.allowManualInsertColumn = this.options.allowManualInsertColumn;
- this.configuration.allowDeleteRow = this.options.allowDeleteRow;
- this.configuration.allowDeleteColumn = this.options.allowDeleteColumn;
- this.configuration.allowComments = this.options.allowComments;
- this.configuration.toolbar = this.options.toolbar;
- this.configuration.onchange = (this.options.onchange === undefined || this.options.onchange === null) ? this.onchangeEvent : this.options.onchange;
- }
- private setConfig() {
- Object.keys(this.configuration).forEach(config => {
- this.getInstance().jexcel('setConfig', config, this.configuration[config]);
- });
- }
- public getValues() {
- const value = lodash.cloneDeep(this.value);
- const spreadsheetValues = this.getInstance().jexcel('getData', false) as any[];
- spreadsheetValues.forEach((row: any[], rowIndex: number) => {
- row.forEach((col: any, colIndex: number) => {
- // TODO: blm ada handler untuk add row baru
- value[rowIndex][this.configuration.columns[colIndex].columnName] = this.getColValue(this.configuration.columns[colIndex], col);
- });
- });
- return value;
- }
- private initData() {
- if (this.configuration && this.value) {
- const values: any = [];
- let rowIndex = 0;
- let colIndex = 0;
- for (const obj of this.value) {
- colIndex = 0;
- values[rowIndex] = [];
- for (const column of this.configuration.columns) {
- if (ObjectHelper.isEmpty(obj[column.columnName])) {
- values[rowIndex][colIndex] = '';
- } else {
- if (column.type === 'calendar') {
- const dateVal = new Date(obj[column.columnName]);
- values[rowIndex][colIndex] = this.dateFormatPipe.transform(dateVal, 'jexcelFullDate');
- } else if (column.type === 'dropdown' || column.type === 'autocomplete') {
- if (typeof obj[column.columnName] === 'object') {
- const name = column.sourceKey ? column.sourceKey : (Object.keys(obj[column.columnName]).find(key => key.indexOf('name') > -1 || key.indexOf('nama') > -1));
- values[rowIndex][colIndex] = obj[column.columnName][name];
- } else {
- values[rowIndex][colIndex] = obj[column.columnName];
- }
- } else {
- values[rowIndex][colIndex] = obj[column.columnName];
- }
- }
- colIndex++;
- }
- rowIndex++;
- }
- this.configuration.data = values;
- }
- }
- private getColValue(column: JExcelColumn, value: any): any {
- if (column) {
- if (ObjectHelper.isEmpty(value)) {
- return null;
- } else {
- if (column.type === 'text') {
- if (!column.isYearMonth) {
- return String(value);
- } else {
- const regExp = new RegExp(this.yearMonthPattern);
- if (!regExp.test(value)) {
- return value;
- } else {
- return String(value).substr(3, 4) + String(value).substr(0, 2);
- }
- }
- } else if (column.type === 'numeric') {
- return Number(value);
- } else if (column.type === 'calendar') {
- return new Date(value);
- } else if (column.type === 'checkbox') {
- return value === '1' ? true : false;
- } else if (column.type === 'dropdown' || column.type === 'autocomplete') {
- let objValue = lodash.cloneDeep(column.source.find(item => {
- if (typeof item === 'object') {
- const name = column.sourceKey ? column.sourceKey : (Object.keys(item).find(key => key.indexOf('name') > -1 || key.indexOf('nama') > -1));
- return item[name] === value;
- } else {
- return item === value;
- }
- }));
- // Delete oid helper
- if (typeof objValue === 'object') {
- if (objValue.oid) {
- objValue.id = objValue.oid;
- delete (objValue.oid);
- } else {
- objValue = objValue.id;
- }
- }
- return objValue ? objValue : null;
- } else {
- return value;
- }
- }
- }
- return null;
- }
- validate(c: AbstractControl): { [key: string]: any } {
- if (this.configuration && this.value) {
- const spreadsheetValues = this.getInstance().jexcel('getData', false) as any[];
- spreadsheetValues.forEach((rowValue, rowIndex) => {
- if (!this.errors[rowIndex]) {
- this.errors[rowIndex] = { row: rowIndex, cells: [] };
- }
- this.configuration.columns.forEach((column, colIndex) => {
- const cell = { cell: colIndex, validation: null, code: null, args: [] };
- if (column.validations) {
- for (const validation of column.validations) {
- if (validation.rule === JExcelColumnRule.required) {
- if (ObjectHelper.isEmpty(rowValue[colIndex])) {
- cell.validation = { required: true };
- this.setStyle(rowIndex, colIndex, this.defaultCellBackgroundError);
- cell.code = 'excel.cell.required';
- this.translateService.get(cell.code).subscribe(
- (translateMessage) => {
- this.setComment(rowIndex, colIndex, translateMessage);
- }
- );
- } else {
- this.setStyle(rowIndex, colIndex, this.defaultCellBackground);
- this.setComment(rowIndex, colIndex, '');
- }
- }
- if (validation.rule === JExcelColumnRule.min) {
- if (column.type === 'text') {
- if (String(rowValue[colIndex]).length < validation.value) {
- cell.validation = { min: validation.value, actualValue: rowValue[colIndex] };
- this.setStyle(rowIndex, colIndex, this.defaultCellBackgroundError);
- const colName = excelColumnName.intToExcelCol(colIndex + 1);
- cell.code = 'excel.cell.min.length';
- cell.args = [validation.value];
- this.translateService.get(cell.code, cell.args).subscribe(
- (translateMessage) => {
- this.setComment(rowIndex, colIndex, translateMessage);
- }
- );
- } else {
- this.setStyle(rowIndex, colIndex, this.defaultCellBackground);
- this.setComment(rowIndex, colIndex, '');
- }
- } else if (column.type === 'numeric') {
- if (Number(rowValue[colIndex]) < validation.value) {
- cell.validation = { min: validation.value, actualValue: Number(rowValue[colIndex]) };
- this.setStyle(rowIndex, colIndex, this.defaultCellBackgroundError);
- const colName = excelColumnName.intToExcelCol(colIndex + 1);
- cell.code = 'excel.cell.min.length';
- cell.args = [validation.value];
- this.translateService.get(cell.code, cell.args).subscribe(
- (translateMessage) => {
- this.setComment(rowIndex, colIndex, translateMessage);
- }
- );
- } else {
- this.setStyle(rowIndex, colIndex, this.defaultCellBackground);
- this.setComment(rowIndex, colIndex, '');
- }
- } else if (column.type === 'calendar') {
- const dateValue = new Date(rowValue[colIndex]);
- if (dateValue.getTime() < (validation.value as Date).getTime()) {
- cell.validation = { min: validation.value, actualValue: dateValue };
- this.setStyle(rowIndex, colIndex, this.defaultCellBackgroundError);
- cell.code = 'excel.cell.min.length';
- cell.args = [validation.value];
- this.translateService.get(cell.code, cell.args).subscribe(
- (translateMessage) => {
- this.setComment(rowIndex, colIndex, translateMessage);
- }
- );
- } else {
- this.setStyle(rowIndex, colIndex, this.defaultCellBackground);
- this.setComment(rowIndex, colIndex, '');
- }
- } else {
- cell.validation = null;
- this.setStyle(rowIndex, colIndex, this.defaultCellBackground);
- this.setComment(rowIndex, colIndex, '');
- }
- }
- if (validation.rule === JExcelColumnRule.max) {
- if (column.type === 'text') {
- if (String(rowValue[colIndex]).length > validation.value) {
- cell.validation = { max: validation.value, actualValue: rowValue[colIndex] };
- this.setStyle(rowIndex, colIndex, this.defaultCellBackgroundError);
- cell.code = 'excel.cell.max.length';
- cell.args = [validation.value];
- this.translateService.get(cell.code, cell.args).subscribe(
- (translateMessage) => {
- this.setComment(rowIndex, colIndex, translateMessage);
- }
- );
- } else {
- this.setStyle(rowIndex, colIndex, this.defaultCellBackground);
- this.setComment(rowIndex, colIndex, '');
- }
- } else if (column.type === 'numeric') {
- if (Number(rowValue[colIndex]) > validation.value) {
- cell.validation = { max: validation.value, actualValue: Number(rowValue[colIndex]) };
- this.setStyle(rowIndex, colIndex, this.defaultCellBackgroundError);
- cell.code = 'excel.cell.max.length';
- cell.args = [validation.value];
- this.translateService.get(cell.code, cell.args).subscribe(
- (translateMessage) => {
- this.setComment(rowIndex, colIndex, translateMessage);
- }
- );
- } else {
- this.setStyle(rowIndex, colIndex, this.defaultCellBackground);
- this.setComment(rowIndex, colIndex, '');
- }
- } else if (column.type === 'calendar') {
- const dateValue = new Date(rowValue[colIndex]);
- if (dateValue.getTime() > (validation.value as Date).getTime()) {
- cell.validation = { max: validation.value, actualValue: dateValue };
- this.setStyle(rowIndex, colIndex, this.defaultCellBackgroundError);
- cell.code = 'excel.cell.max.length';
- cell.args = [validation.value];
- this.translateService.get(cell.code, cell.args).subscribe(
- (translateMessage) => {
- this.setComment(rowIndex, colIndex, translateMessage);
- }
- );
- } else {
- this.setStyle(rowIndex, colIndex, this.defaultCellBackground);
- this.setComment(rowIndex, colIndex, '');
- }
- } else {
- cell.validation = null;
- this.setStyle(rowIndex, colIndex, this.defaultCellBackground);
- this.setComment(rowIndex, colIndex, '');
- }
- }
- if (validation.rule === JExcelColumnRule.yearmonth) {
- const regExp = new RegExp(this.yearMonthPattern);
- if (!regExp.test(rowValue[colIndex])) {
- cell.validation = { pattern: validation.value };
- this.setStyle(rowIndex, colIndex, this.defaultCellBackgroundError);
- cell.code = 'excel.cell.invalid';
- cell.args = [validation.value];
- this.translateService.get(cell.code).subscribe(
- (translateMessage) => {
- this.setComment(rowIndex, colIndex, translateMessage);
- }
- );
- } else {
- cell.validation = null;
- this.setStyle(rowIndex, colIndex, this.defaultCellBackground);
- this.setComment(rowIndex, colIndex, '');
- }
- }
- if (validation.rule === JExcelColumnRule.pattern) {
- const regExp = new RegExp(String(validation.value));
- if (!regExp.test(rowValue[colIndex])) {
- cell.validation = { pattern: validation.value };
- this.setStyle(rowIndex, colIndex, this.defaultCellBackgroundError);
- cell.code = 'excel.cell.invalid';
- cell.args = [validation.value];
- this.translateService.get(cell.code).subscribe(
- (translateMessage) => {
- this.setComment(rowIndex, colIndex, translateMessage);
- }
- );
- } else {
- cell.validation = null;
- this.setStyle(rowIndex, colIndex, this.defaultCellBackground);
- this.setComment(rowIndex, colIndex, '');
- }
- }
- if (this.errors[rowIndex].cells[colIndex]) {
- this.errors[rowIndex].cells[colIndex] = cell;
- } else {
- this.errors[rowIndex].cells.push(cell);
- }
- }
- } else {
- if (!this.errors[rowIndex].cells[colIndex]) {
- this.errors[rowIndex].cells.push(cell);
- }
- }
- });
- });
- this.valid = true;
- for (const error of this.errors) {
- if (error.cells.find(item => item.validation !== null) !== undefined) {
- this.valid = false;
- break;
- }
- }
- if (this.valid) {
- return null;
- } else {
- return this.errors;
- }
- }
- return null;
- }
- public setStyle(rowIndex: number, colIndex: number, style: string) {
- const colName = excelColumnName.intToExcelCol(colIndex + 1);
- const cell = {};
- cell[colName + '' + (rowIndex + 1)] = style;
- this.getInstance().jexcel('setStyle', [cell]);
- }
- public setComment(rowIndex: number, colIndex: number, comment: string = '') {
- const colName = excelColumnName.intToExcelCol(colIndex + 1);
- this.getInstance().jexcel('setComments', colName + '' + (rowIndex + 1), comment);
- }
- public updateSettings(options: JExcelOptions) {
- this.getInstance().jexcel('destroy');
- this.options = Object.assign({}, options);
- this.globalErrors = [];
- if (this.options) {
- this.initConfiguration();
- this.setConfig();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment