TypeScript 导出 Excel 表格(带斑马纹样式)

TypeScript 导出 Excel 表格(带斑马纹样式)

开发需求

  1. 表头单元格自动合并(类似 EasyExcel)
  2. 单元格样式自动设置(带斑马纹样式)
  3. 根据单元格数据自动设置表格列宽
  4. 读取表格数据自动转换为 Map 列表
  5. 表数据异步处理(多个 Sheet 同时执行)
  6. 表头数据(行)及行标题(列)单元格冻结

最终效果

  1. 导出 Excel 数据(指定列宽)

在这里插入图片描述

  1. 导出 Excel 数据(自动列宽)

在这里插入图片描述

  1. 导出 Excel 数据(单元格冻结)

在这里插入图片描述
在这里插入图片描述

  1. Excel 数据读取
    在这里插入图片描述
    在这里插入图片描述

依赖模块

xlsx-js-style, xlsx-style

xlsx-js-style 最新版: https://www.npmjs.com/package/xlsx-js-style
xlsx-style 最新版:https://pan.baidu.com/s/1y6vaPHVMy8U_pT2_5xzLsw 提取码: uny2

测试类

import {LogUtil} from "./LogUtil";
import {Log} from "./Log";
import {ExcelUtil} from "./ExcelUtil";
import {AsyncUtil} from "./AsyncUtil";

export class ApplicationTest {

	//导出Excel数据测试四:单元格数据冻结二
	public test7(): void {
        let lstHeader = [
            ["序号"],
            ["书名"],
            ["作者"],
            ["年代"],
            ["字数"],
        ];
        let lstData = [
            ["《水浒传》", "施耐庵", "宋朝", "96 万字"],
            ["《三国演义》", "罗贯中", "元朝", "73.4 万字"],
            ["《西游记》", "吴承恩", "明代", "82 万字"],
            ["《红楼梦》", "曹雪芹", "清代", "107.5 万字"],
            ["《聊斋志异》", "蒲松龄", "清代", "70.8 万字"],
        ];

        let lstSheet = [];
        for (let num = 1; num <= 5; num++) {
            ExcelUtil.writeHeader(lstHeader, undefined, 1);
            for (let i = 0, rowIndex = 1; i < lstData.length; i++, rowIndex++) {
                let colIndex = 0;
                ExcelUtil.writeCellData(rowIndex, colIndex++, (i + 1) + "");
                for (let j = 0; j < lstData[i].length; j++) {
                    ExcelUtil.writeCellData(rowIndex, colIndex++, lstData[i][j]);
                }
            }
            let sheet = ExcelUtil.getDataSheet();
            lstSheet.push({sheet: sheet, name: "Sheet" + num});
        }

        ExcelUtil.write(lstSheet, "C:\\Users\\admin\\Desktop\\demo-width-auto-" + Date.now() + ".xlsx");
    }

	//导出Excel数据测试四:单元格数据冻结一
	public async test6(): Promise<void> {
        let lstHeader = [
            ["a", "a", "e"],
            ["b", "b", "e"],
            ["b", "b", "f"],
            ["c", "a", "a"],
            ["c", "a", "a"]
        ];

        let lstNum = [1, 2, 3, 4, 5];
        let lstData = new Array<Record<string, any>>();
        await AsyncUtil.execWithListDataByAsync(lstNum, num => {
            ExcelUtil.writeHeader(lstHeader, 22, 1);
            for (let i = 0, rowIndex = 3; i < num * 50 + num; i++, rowIndex += 2) {
                for (let j = 0; j < 5; j++) {
                    ExcelUtil.writeCellData(rowIndex, j, "test");
                    ExcelUtil.writeCellData(rowIndex + 1, j, "demo");
                }
            }
            let sheet = ExcelUtil.getDataSheet();
            lstData.push({sheet: sheet, name: "Sheet" + num});
        });
        ExcelUtil.write(lstData, "C:\\Users\\admin\\Desktop\\demo-" + Date.now() + ".xlsx");
    }

	//导出Excel数据测试三:多个 Sheet 异步处理
	public async test5(): Promise<void> {
        let lstHeader = [
            ["a", "a", "e"],
            ["b", "b", "e"],
            ["b", "b", "f"],
            ["c", "a", "a"],
            ["c", "a", "a"]
        ];

        let lstNum = [1, 2, 3, 4, 5];
        let lstData = new Array<Record<string, any>>();
        await AsyncUtil.execWithListDataByAsync(lstNum, num => {
            ExcelUtil.writeHeader(lstHeader, 22);
            for (let i = 0, rowIndex = 3; i < num * 50 + num; i++, rowIndex += 2) {
                for (let j = 0; j < 5; j++) {
                    ExcelUtil.writeCellData(rowIndex, j, "test");
                    ExcelUtil.writeCellData(rowIndex + 1, j, "demo");
                }
            }
            let sheet = ExcelUtil.getDataSheet();
            lstData.push({sheet: sheet, name: "Sheet" + num});
        });
        ExcelUtil.write(lstData, "C:\\Users\\admin\\Desktop\\demo-" + Date.now() + ".xlsx");
    }

	//Excel数据读取测试二
    public test4(): void {
        let lstData = ExcelUtil.toMap(
            "C:\\Users\\admin\\Desktop\\demo-width-auto-1659158251861.xlsx",
            0
        );
        LogUtil.loggerLine(Log.of("ApplicationTest", "test4", "lstData", lstData));

        for (let data of lstData) {
            let num = data.get("序号");
            let name = data.get("书名");
            let author = data.get("作者");
            let age = data.get("年代");
            let words = data.get("字数");
            LogUtil.loggerLine(Log.of("ApplicationTest", "test4", "num", num));
            LogUtil.loggerLine(Log.of("ApplicationTest", "test4", "name", name));
            LogUtil.loggerLine(Log.of("ApplicationTest", "test4", "author", author));
            LogUtil.loggerLine(Log.of("ApplicationTest", "test4", "age", age));
            LogUtil.loggerLine(Log.of("ApplicationTest", "test4", "words", words));
            console.log("---------------------------------------------------------------------------");
        }
    }

	//导出Excel数据测试二:单元格列宽自动设置
    public test3(): void {
        let lstHeader = [
            ["序号"],
            ["书名"],
            ["作者"],
            ["年代"],
            ["字数"],
        ];
        let lstData = [
            ["《水浒传》", "施耐庵", "宋朝", "96 万字"],
            ["《三国演义》", "罗贯中", "元朝", "73.4 万字"],
            ["《西游记》", "吴承恩", "明代", "82 万字"],
            ["《红楼梦》", "曹雪芹", "清代", "107.5 万字"],
            ["《聊斋志异》", "蒲松龄", "清代", "70.8 万字"],
        ];

        let lstSheet = [];
        for (let num = 1; num <= 5; num++) {
            ExcelUtil.writeHeader(lstHeader);
            for (let i = 0, rowIndex = 1; i < lstData.length; i++, rowIndex++) {
                let colIndex = 0;
                ExcelUtil.writeCellData(rowIndex, colIndex++, (i + 1) + "");
                for (let j = 0; j < lstData[i].length; j++) {
                    ExcelUtil.writeCellData(rowIndex, colIndex++, lstData[i][j]);
                }
            }
            let sheet = ExcelUtil.getDataSheet();
            lstSheet.push({sheet: sheet, name: "Sheet" + num});
        }

        ExcelUtil.write(lstSheet, "C:\\Users\\admin\\Desktop\\demo-width-auto-" + Date.now() + ".xlsx");
    }

	//Excel读取测试一
    public test2(): void {
        let lstData = ExcelUtil.toMap(
            "C:\\Users\\admin\\Desktop\\新建 XLSX 工作表.xlsx",
            0
        );
        LogUtil.loggerLine(Log.of("ApplicationTest", "test2", "lstData", lstData));

        for (let data of lstData) {
            let num = data.get("序号");
            let animal = data.get("动物");
            let food = data.get("食物");
            LogUtil.loggerLine(Log.of("ApplicationTest", "test2", "num", num));
            LogUtil.loggerLine(Log.of("ApplicationTest", "test2", "animal", animal));
            LogUtil.loggerLine(Log.of("ApplicationTest", "test2", "food", food));
            console.log("---------------------------------------------------------------------------");
        }
    }

	//导出Excel数据测试一:表头单元格自动合并
    public test1(): void {
        let lstHeader = [
            ["a", "a", "e"],
            ["b", "b", "e"],
            ["b", "b", "f"],
            ["c", "a", "a"],
            ["c", "a", "a"]
        ];

        let lstData = [];
        for (let num = 1; num <= 5; num++) {
            ExcelUtil.writeHeader(lstHeader, 22);
            for (let i = 0, rowIndex = 3; i < num * 50 + num; i++, rowIndex += 2) {
                for (let j = 0; j < 5; j++) {
                    ExcelUtil.writeCellData(rowIndex, j, "test");
                    ExcelUtil.writeCellData(rowIndex + 1, j, "demo");
                }
            }
            let sheet = ExcelUtil.getDataSheet();
            lstData.push({sheet: sheet, name: "Sheet" + num});
        }

        ExcelUtil.write(lstData, "C:\\Users\\admin\\Desktop\\demo-" + Date.now() + ".xlsx");
    }

}

实体类

  1. 单元格坐标实体
export class Coords {

    private _x: number;
    private _y: number;
    private _value: string;

    private constructor(lstHeader: Array<Array<string>>, row: number, col: number) {
        this._x = row;
        this._y = col;
        this._value = lstHeader[col][row];
    }

    public static of(lstHeader: Array<Array<string>>, row: number, col: number): Coords {
        return new Coords(lstHeader, row, col);
    }

    get x(): number {
        return this._x;
    }

    set x(value: number) {
        this._x = value;
    }

    get y(): number {
        return this._y;
    }

    set y(value: number) {
        this._y = value;
    }

    get value(): string {
        return this._value;
    }

    set value(value: string) {
        this._value = value;
    }
}
  1. 日志记录实体
export class Log {

    private _className: string;
    private _methodName: string;
    private _paramName: string;
    private _value: any;

    private constructor(className: string, methodName: string, paramName: string, value: any) {
        this._className = className;
        this._methodName = methodName;
        this._paramName = paramName;
        this._value = value;
    }

    public static of(className: string, methodName: string, paramName: string, value: any): Log {
        return new Log(className, methodName, paramName, value);
    }

    get className(): string {
        return this._className;
    }

    set className(value: string) {
        this._className = value;
    }

    get methodName(): string {
        return this._methodName;
    }

    set methodName(value: string) {
        this._methodName = value;
    }

    get paramName(): string {
        return this._paramName;
    }

    set paramName(value: string) {
        this._paramName = value;
    }

    get value(): any {
        return this._value;
    }

    set value(value: any) {
        this._value = value;
    }

}

工具类

  1. Excel 文件读取、导出
import * as path from "path";
import {Coords} from "./Coords";
import * as XLSX from "xlsx-js-style";
import {CellObject, CellStyle, ColInfo, Range, RowInfo, WorkBook, WorkSheet} from "xlsx-js-style";

export class ExcelUtil {

    //行高
    private static height: number = 36;
    //数据行
    private static dataRow: number = -1;
    //自动设置列宽
    private static widthAuto: boolean = false;
    //单元格合并列表
    private static lstRange: Array<Range> = [];
    //列宽列表
    private static lstColInfo: Array<ColInfo> = [];
    //行高列表
    private static lstRowInfo: Array<RowInfo> = [];
    //列表冻结
    private static freezeInfo: Record<string, any> = {};
    //单元格数据列表
    private static lstValue: Array<Array<CellObject>> = [];
    //样式列表
    private static lstCellStyle: Array<CellStyle> = [];
    //移动方向:上、右、下、左
    private static readonly MOVE: Array<Array<number>> = [[0, 1], [1, 0], [0, -1], [-1, 0]];

    //获取excel表数据
    public static toMap(excelName: string, sheetName: string | number, headerRow?: number, headerCol?: number, headerLastCol?: number, dataRow?: number, dataLastRow?: number, extraData?: Map<string, string>): Array<Map<string, string>> {
        let workbook = XLSX.readFile(excelName);
        if (typeof sheetName === "number") {
            sheetName = workbook.SheetNames[sheetName];
        }
        let sheet = workbook.Sheets[sheetName];
        //表数据转数组数据
        let sheetJson = <Array<Array<any>>>XLSX.utils.sheet_to_json(sheet, {header: 1});

        //数据初始化
        headerRow = headerRow || 0;
        headerCol = headerCol || 0;
        dataRow = dataRow || headerRow + 1;
        this.lstRange = sheet["!merges"] || [];
        dataLastRow = dataLastRow || sheetJson.length;
        extraData = extraData || new Map<string, string>();
        headerLastCol = headerLastCol || sheetJson[headerRow].length;

        //列号列表
        let lstHeaderCol: Array<number> = [];
        for (let i = headerCol; i < headerLastCol; i++) {
            lstHeaderCol.push(i);
        }
        //行号列表
        let lstDataRow: Array<number> = [];
        for (let i = dataRow; i < dataLastRow; i++) {
            lstDataRow.push(i);
        }
        return this.getSheetData(sheetJson, headerRow, lstHeaderCol, lstDataRow, extraData);
    }

    //excel表数据解析
    private static getSheetData(sheet: Array<Array<any>>, headerRow: number, headerCol: Array<number>, dataRow: Array<number>, extraData: Map<string, string>): Array<Map<string, string>> {
        //获取列头与列号的对应关系
        let mapHeader = new Map<string, number>();
        for (let col of headerCol) {
            this.getSheetHeader(sheet, mapHeader, headerRow, col);
        }
        //根据列头与列号关系解析表格数据
        let lstData = new Array<Map<string, string>>;
        for (let row of dataRow) {
            let map = this.getSheetBody(sheet, mapHeader, row);
            if (map.size == 0) continue;
            //添加外部数据
            extraData.forEach((v, k) => map.set(k, v));
            lstData.push(map);
        }
        return lstData;
    }

    //列头与列号对应关系
    private static getSheetHeader(sheet: Array<Array<any>>, mapHeader: Map<string, number>, row: number, col: number) {
        //格式化字符串数据
        let value: string = (sheet[row][col] + "").trim();
        mapHeader.set(value, col);
    }

    //获取与列头对应的列数据
    private static getSheetBody(sheet: Array<Array<any>>, mapHeader: Map<string, number>, row: number): Map<string, string> {
        let map = new Map<string, string>;
        if (row > sheet.length) {
            return map;
        }
        for (let [header, col] of mapHeader) {
            //格式化字符串数据
            let value = (sheet[row][col] + "").trim();
            if (value.length == 0) {
                //尝试获取单元格数据
                value = this.getMergedCellValue(sheet, row, col);
            }
            if (value.length == 0) continue;
            map.set(header, value);
        }
        return map;
    }

    //获取合并单元格数据
    private static getMergedCellValue(sheet: Array<Array<any>>, row: number, col: number): string {
        for (let range of this.lstRange) {
            let minCell = range.s;
            let maxCell = range.e;
            if (minCell.r <= row && row <= maxCell.r &&
                minCell.c <= col && col <= maxCell.c) {
                //格式化字符串数据
                return (sheet[minCell.r][minCell.c] + "").trim();
            }
        }
        return "";
    }

    //行高、列宽初始化
    private static init(rowSize: number, colSize: number): void {
        this.dataRow = -1;
        this.lstRange = [];
        this.lstValue = [];
        this.lstColInfo = [];
        this.lstRowInfo = [];
        this.lstCellStyle = [];
        for (let i = 0; i < rowSize; i++) {
            this.lstValue.push([]);
            this.lstRowInfo.push({});
            for (let j = 0; j < colSize; j++) {
                if (i == 0) {
                    this.lstColInfo.push({});
                }
                this.lstValue[i].push({v: "", t: "s"});
            }
        }
        this.initCellStyle();
    }

    //样式列表初始化
    private static initCellStyle(): void {
        let lstColor = ["F2F2F2", "FAFAFA", "D4D4D4"];
        this.lstCellStyle.push(this.chooseCellStyle(lstColor, 0));
        this.lstCellStyle.push(this.chooseCellStyle(lstColor, 1));
        this.lstCellStyle.push(this.chooseCellStyle(lstColor, 2));
    }

    //单元格样式选择
    private static chooseCellStyle(lstColor: Array<string>, choose: number): CellStyle {
        let cellStyle: CellStyle = {};
        cellStyle.alignment = {};
        cellStyle.border = {};
        cellStyle.font = {};
        if (choose == 0) {
            //设置表头字体样式:粗体、大小
            cellStyle.font = {bold: true, sz: 11};
            //设置背景色
            cellStyle.fill = {fgColor: {rgb: lstColor[0]}, patternType: "solid"};
        } else if (choose == 1) {
            //设置数据显示字体样式:大小
            cellStyle.font = {sz: 10};
            //设置背景色
            cellStyle.fill = {fgColor: {rgb: lstColor[1]}, patternType: "solid"};
        } else if (choose == 2) {
            //设置数据显示字体样式:大小
            cellStyle.font = {sz: 10};
        }
        //设置字体: 微软雅黑
        cellStyle.font.name = "Microsoft YaHei";
        //设置居中:垂直居中、水平居中
        cellStyle.alignment.vertical = "center";
        cellStyle.alignment.horizontal = "center";
        //设置边框宽度、颜色
        cellStyle.border.top = {style: "thin", color: {rgb: lstColor[2]}};
        cellStyle.border.bottom = {style: "thin", color: {rgb: lstColor[2]}};
        cellStyle.border.left = {style: "thin", color: {rgb: lstColor[2]}};
        cellStyle.border.right = {style: "thin", color: {rgb: lstColor[2]}};
        return cellStyle;
    }

    //表格数据写入
    public static writeCellData(rowIndex: number, colIndex: number, cellData: string): void {
        //写入单元格数据并设置单元格样式
        let cellStyle = this.getCellStyle(this.dataRow, rowIndex);
        if (this.widthAuto) {
            //自动设置列宽
            this.lstColInfo[colIndex] = {wch: this.getWidthColByAuto(colIndex, cellData)};
        }
        this.saveCellValue(rowIndex, cellStyle, cellData);
        if (colIndex == 0) {
            //设置行高
            this.lstRowInfo[rowIndex] = {hpt: this.height};
        }
    }

    //表头数据写入
    public static writeHeader(lstHeader: Array<Array<string>>, widthCol?: number, dataCol?: number, lstExcludeRow?: Array<number>): void {
        let colSize = lstHeader.length;
        let rowSize = lstHeader[0].length;
        this.init(rowSize, colSize);
        this.dataRow = rowSize;
        this.widthAuto = widthCol == null;
        let lstFlag = this.getFlagArray(rowSize, colSize);
        for (let row = 0; row < rowSize; row++) {
            for (let col = 0; col < colSize; col++) {
                if (!lstFlag[row][col]) {
                    lstFlag[row][col] = true;

                    let lstCoords = new Array<Coords>();
                    lstCoords.push(Coords.of(lstHeader, row, col));
                    if (lstExcludeRow == null || lstExcludeRow.length == 0 || !lstExcludeRow.includes(row)) {
                        this.checkMergeRange(lstHeader, lstFlag, lstCoords, row, col, lstHeader[col][row]);
                    }

                    this.merge(lstCoords, widthCol);
                }
            }
        }
        //单元格冻结:从上往下,冻结 dataRow 行;从左往右,冻结 dataCol 列
        this.freezeInfo = {xSplit: dataCol || 0 + "", ySplit: this.dataRow + "", activePane: "bottomRight", state: "frozen"};
    }

    //单元格合并范围递归检查
    private static checkMergeRange(lstHeader: Array<Array<string>>, lstFlag: Array<Array<boolean>>, lstCoords: Array<Coords>, x: number, y: number, value: string): void {
        let colSize = lstHeader.length;
        let rowSize = lstHeader[0].length;
        for (let move of this.MOVE) {
            let moveX = x + move[0];
            let moveY = y + move[1];
            if (0 <= moveX && moveX < rowSize && 0 <= moveY && moveY < colSize && !lstFlag[moveX][moveY]) {
                if (lstHeader[moveY][moveX] === value) {
                    lstFlag[moveX][moveY] = true;
                    lstCoords.push(Coords.of(lstHeader, moveX, moveY));
                    this.checkMergeRange(lstHeader, lstFlag, lstCoords, moveX, moveY, value);
                }
            }
        }
    }

    //单元格合并
    private static merge(lstCoords: Array<Coords>, widthCol?: number): void {
        //单元格坐标排序
        lstCoords.sort((c1, c2) => {
            if (c1.x > c2.x || c1.y > c2.y) {
                return 1;
            } else if (c1.x < c2.x || c1.y < c2.y) {
                return -1;
            } else {
                return 0;
            }
        });
        for (let coords of lstCoords) {
            //设置列宽
            this.lstColInfo[coords.y] = {wch: widthCol || this.getWidthColByAuto(coords.y, coords.value)};
            //设置行高
            this.lstRowInfo[coords.x] = {hpt: this.height};
            //写入单元格数据并设置单元格样式
            let cellStyle = this.getCellStyle(this.dataRow, coords.x);
            this.saveHeaderCellValue(coords.x, coords.y, cellStyle, coords.value);
        }
        //合并单元格
        if (lstCoords.length > 1) {
            let minCoords = lstCoords[0];
            let maxCoords = lstCoords[lstCoords.length - 1];
            this.lstRange.push({s: {r: minCoords.x, c: minCoords.y}, e: {r: maxCoords.x, c: maxCoords.y}})
        }
    }

    //自动设置列宽
    private static getWidthColByAuto(col: number, value: string): number {
        let widthCol = this.lstColInfo[col].wch || 0;
        let tempWidthCol = this.getWidthCol(value);
        if (widthCol < tempWidthCol) {
            widthCol = tempWidthCol;
        }
        return widthCol;
    }

    //根据字符串获取列宽
    private static getWidthCol(value: string): number {
        let chineseSum = 0;
        let englishSum = 0;
        let charSum = 0;
        for (let i = 0; i < value.length; i++) {
            if (this.isChineseChar(value.charCodeAt(i))) {
                chineseSum += 2;
                charSum += 2;
            } else {
                englishSum += 1;
                charSum += 1;
            }
        }
        charSum = charSum > 1 ? 13 + charSum - 1 : 13;
        if (chineseSum == 0 && englishSum > 0) {
            charSum += 4;
        } else if (chineseSum > 0 && englishSum > 0) {
            let percent = englishSum / chineseSum;
            if (percent < 0.2) {
                charSum -= 2;
            } else if (percent > 0.8) {
                charSum += 2;
            }
        }
        return charSum;
    }

    //判断是否为中文字符
    private static isChineseChar(charCode: number): boolean {
        return !(0 <= charCode && charCode <= 128);
    }

    //表头单元格数据写入
    private static saveHeaderCellValue(rowIndex: number, colIndex: number, cellStyle: CellStyle, value: string): void {
        this.lstValue[rowIndex][colIndex] = {v: value, t: "s", s: cellStyle};
    }

    //表格单元格数据写入
    private static saveCellValue(rowIndex: number, cellStyle: CellStyle, value: string): void {
        if (this.lstValue.length === rowIndex) {
            this.lstValue.push([]);
        }
        this.lstValue[rowIndex].push({v: value, t: "s", s: cellStyle});
    }

    //表头标记矩阵初始化
    private static getFlagArray(rowSize: number, colSize: number): Array<Array<boolean>> {
        let lstFlag = new Array<Array<boolean>>();
        for (let i = 0; i < rowSize; i++) {
            let flags = new Array<boolean>();
            for (let j = 0; j < colSize; j++) {
                flags.push(false);
            }
            lstFlag.push(flags);
        }
        return lstFlag;
    }

    //获取单元格样式
    private static getCellStyle(dataRow: number, rowIndex: number): CellStyle {
        //单元格样式:带斑马纹表格
        let cellStyle;
        if (dataRow === -1 || rowIndex < dataRow) {
            //表头样式
            cellStyle = this.lstCellStyle[0];
        } else {
            //数据样式
            if (dataRow % 2 == 0) {
                if (rowIndex % 2 == 0) {
                    cellStyle = this.lstCellStyle[2];
                } else {
                    cellStyle = this.lstCellStyle[1];
                }
            } else {
                if (rowIndex % 2 != 0) {
                    cellStyle = this.lstCellStyle[2];
                } else {
                    cellStyle = this.lstCellStyle[1];
                }
            }
        }
        return cellStyle;
    }

    //数据写入到表中
    public static getDataSheet(): WorkSheet {
        let sheet = XLSX.utils.aoa_to_sheet(this.lstValue);
        sheet["!rows"] = this.lstRowInfo;
        sheet["!cols"] = this.lstColInfo;
        sheet["!merges"] = this.lstRange;
        sheet["!freeze"] = this.freezeInfo;
        return sheet;
    }

    //导出excel文件
    public static write(lstData: Array<Record<string, any>>, fileName: string): void {
        let workbook: WorkBook = XLSX.utils.book_new();
        for (let data of lstData) {
            let name = <string>data.name;
            let sheet = <WorkSheet>data.sheet;
            XLSX.utils.book_append_sheet(workbook, sheet, name);
        }
        // XLSX.writeFile(workbook, fileName);
        let XLSX_STYLE = require(path.join(
            __dirname,
            "./xlsx-style/xlsx.js"
        ));
        XLSX_STYLE.writeFile(workbook, fileName);
    }

}

  1. 日志打印
import {Log} from "./Log";

export class LogUtil {

    private static readonly enable = true;

    private constructor() {
    }

    public static loggerLine(log: Log): void {
        if (this.enable) {
            console.log("[" + log.className + "] " + log.methodName + " -> " + log.paramName + ": ", log.value);
        }
    }

    public static logger(log: Log): void {
        if (this.enable) {
            process.stdout.write("[" + log.className + "] " + log.methodName + " -> " + log.paramName + ": " + log.value);
        }
    }

}
  1. 异步执行
export class AsyncUtil {

    private constructor() {
    }

    public static execWithListDataByAsync<T>(lstData: Array<T>, consumer: (data: T) => void): Promise<void> {
        return new Promise(resolve => {
            let lstPromise: Array<Promise<void>> = [];
            for (let data of lstData) {
                lstPromise.push(new Promise(resolve => {
                    consumer(data);
                    resolve();
                }));
            }
            Promise.all(lstPromise).then(() => {
                resolve();
            });
        });
    }

}

编码感想

  1. 要贪玩
  2. 要开心
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值